Add ToOwned::clone_into (unstable as toowned_clone_into)
to_owned generalizes clone; this generalizes clone_from. Use to_owned to give it a default impl. Customize the impl for [T], str, and T:Clone. Use it in Cow::clone_from to reuse resources when cloning Owned into Owned.
This commit is contained in:
@@ -193,6 +193,7 @@
|
|||||||
- [thread_local](thread-local.md)
|
- [thread_local](thread-local.md)
|
||||||
- [thread_local_internals](thread-local-internals.md)
|
- [thread_local_internals](thread-local-internals.md)
|
||||||
- [thread_local_state](thread-local-state.md)
|
- [thread_local_state](thread-local-state.md)
|
||||||
|
- [toowned_clone_into](toowned-clone-into.md)
|
||||||
- [trace_macros](trace-macros.md)
|
- [trace_macros](trace-macros.md)
|
||||||
- [trusted_len](trusted-len.md)
|
- [trusted_len](trusted-len.md)
|
||||||
- [try_from](try-from.md)
|
- [try_from](try-from.md)
|
||||||
|
|||||||
7
src/doc/unstable-book/src/toowned-clone-into.md
Normal file
7
src/doc/unstable-book/src/toowned-clone-into.md
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# `toowned_clone_into`
|
||||||
|
|
||||||
|
The tracking issue for this feature is: [#41263]
|
||||||
|
|
||||||
|
[#41263]: https://github.com/rust-lang/rust/issues/41263
|
||||||
|
|
||||||
|
------------------------
|
||||||
@@ -60,6 +60,29 @@ pub trait ToOwned {
|
|||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn to_owned(&self) -> Self::Owned;
|
fn to_owned(&self) -> Self::Owned;
|
||||||
|
|
||||||
|
/// Uses borrowed data to replace owned data, usually by cloning.
|
||||||
|
///
|
||||||
|
/// This is borrow-generalized version of `Clone::clone_from`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// Basic usage:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # #![feature(toowned_clone_into)]
|
||||||
|
/// let mut s: String = String::new();
|
||||||
|
/// "hello".clone_into(&mut s);
|
||||||
|
///
|
||||||
|
/// let mut v: Vec<i32> = Vec::new();
|
||||||
|
/// [1, 2][..].clone_into(&mut v);
|
||||||
|
/// ```
|
||||||
|
#[unstable(feature = "toowned_clone_into",
|
||||||
|
reason = "recently added",
|
||||||
|
issue = "41263")]
|
||||||
|
fn clone_into(&self, target: &mut Self::Owned) {
|
||||||
|
*target = self.to_owned();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
@@ -70,6 +93,10 @@ impl<T> ToOwned for T
|
|||||||
fn to_owned(&self) -> T {
|
fn to_owned(&self) -> T {
|
||||||
self.clone()
|
self.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn clone_into(&self, target: &mut T) {
|
||||||
|
target.clone_from(self);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A clone-on-write smart pointer.
|
/// A clone-on-write smart pointer.
|
||||||
@@ -141,6 +168,17 @@ impl<'a, B: ?Sized> Clone for Cow<'a, B>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn clone_from(&mut self, source: &Cow<'a, B>) {
|
||||||
|
if let Owned(ref mut dest) = *self {
|
||||||
|
if let Owned(ref o) = *source {
|
||||||
|
o.borrow().clone_into(dest);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*self = source.clone();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, B: ?Sized> Cow<'a, B>
|
impl<'a, B: ?Sized> Cow<'a, B>
|
||||||
|
|||||||
@@ -1527,6 +1527,19 @@ impl<T: Clone> ToOwned for [T] {
|
|||||||
fn to_owned(&self) -> Vec<T> {
|
fn to_owned(&self) -> Vec<T> {
|
||||||
panic!("not available with cfg(test)")
|
panic!("not available with cfg(test)")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn clone_into(&self, target: &mut Vec<T>) {
|
||||||
|
// drop anything in target that will not be overwritten
|
||||||
|
target.truncate(self.len());
|
||||||
|
let len = target.len();
|
||||||
|
|
||||||
|
// reuse the contained values' allocations/resources.
|
||||||
|
target.clone_from_slice(&self[..len]);
|
||||||
|
|
||||||
|
// target.len <= self.len due to the truncate above, so the
|
||||||
|
// slice here is always in-bounds.
|
||||||
|
target.extend_from_slice(&self[len..]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|||||||
@@ -199,6 +199,12 @@ impl ToOwned for str {
|
|||||||
fn to_owned(&self) -> String {
|
fn to_owned(&self) -> String {
|
||||||
unsafe { String::from_utf8_unchecked(self.as_bytes().to_owned()) }
|
unsafe { String::from_utf8_unchecked(self.as_bytes().to_owned()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn clone_into(&self, target: &mut String) {
|
||||||
|
let mut b = mem::replace(target, String::new()).into_bytes();
|
||||||
|
self.as_bytes().clone_into(&mut b);
|
||||||
|
*target = unsafe { String::from_utf8_unchecked(b) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Methods for string slices.
|
/// Methods for string slices.
|
||||||
|
|||||||
@@ -139,3 +139,13 @@ fn check_cow_add_assign_str() {
|
|||||||
assert_eq!("Hi, World!", owned);
|
assert_eq!("Hi, World!", owned);
|
||||||
assert_eq!("Hello, World!", borrowed);
|
assert_eq!("Hello, World!", borrowed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn check_cow_clone_from() {
|
||||||
|
let mut c1: Cow<str> = Cow::Owned(String::with_capacity(25));
|
||||||
|
let s: String = "hi".to_string();
|
||||||
|
assert!(s.capacity() < 25);
|
||||||
|
let c2: Cow<str> = Cow::Owned(s);
|
||||||
|
c1.clone_from(&c2);
|
||||||
|
assert!(c1.into_owned().capacity() >= 25);
|
||||||
|
}
|
||||||
@@ -1396,16 +1396,7 @@ impl<T: Clone> Clone for Vec<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn clone_from(&mut self, other: &Vec<T>) {
|
fn clone_from(&mut self, other: &Vec<T>) {
|
||||||
// drop anything in self that will not be overwritten
|
other.as_slice().clone_into(self);
|
||||||
self.truncate(other.len());
|
|
||||||
let len = self.len();
|
|
||||||
|
|
||||||
// reuse the contained values' allocations/resources.
|
|
||||||
self.clone_from_slice(&other[..len]);
|
|
||||||
|
|
||||||
// self.len <= other.len due to the truncate above, so the
|
|
||||||
// slice here is always in-bounds.
|
|
||||||
self.extend_from_slice(&other[len..]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user