Skip to content

Commit

Permalink
Rollup merge of rust-lang#70201 - cuviper:clone_into, r=dtolnay
Browse files Browse the repository at this point in the history
Small tweaks in ToOwned::clone_into

- `<[T]>::clone_into` is slightly more optimized.
- `CStr::clone_into` is new, letting it reuse its allocation.
- `OsStr::clone_into` now forwards to the underlying slice/`Vec`.
  • Loading branch information
Dylan-DPC committed Mar 21, 2020
2 parents 83d64cf + 28791f6 commit 4d38ac1
Show file tree
Hide file tree
Showing 6 changed files with 36 additions and 8 deletions.
12 changes: 6 additions & 6 deletions src/liballoc/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -735,14 +735,14 @@ impl<T: Clone> ToOwned for [T] {
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..]);
// slices here are always in-bounds.
let (init, tail) = self.split_at(target.len());

// reuse the contained values' allocations/resources.
target.clone_from_slice(init);
target.extend_from_slice(tail);
}
}

Expand Down
17 changes: 17 additions & 0 deletions src/libstd/ffi/c_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1329,6 +1329,12 @@ impl ToOwned for CStr {
fn to_owned(&self) -> CString {
CString { inner: self.to_bytes_with_nul().into() }
}

fn clone_into(&self, target: &mut CString) {
let mut b = Vec::from(mem::take(&mut target.inner));
self.to_bytes_with_nul().clone_into(&mut b);
target.inner = b.into_boxed_slice();
}
}

#[stable(feature = "cstring_asref", since = "1.7.0")]
Expand Down Expand Up @@ -1510,6 +1516,17 @@ mod tests {
assert_eq!(boxed.to_bytes_with_nul(), &[0]);
}

#[test]
fn test_c_str_clone_into() {
let mut c_string = CString::new("bonjour").unwrap();
let c_ptr = c_string.as_ptr();
let c_str = CStr::from_bytes_with_nul(b"hello\0").unwrap();
c_str.clone_into(&mut c_string);
assert_eq!(c_str, c_string.as_c_str());
// It shouldn't have needed to move its allocation
assert_eq!(c_ptr, c_string.as_ptr());
}

#[test]
fn into_rc() {
let orig: &[u8] = b"Hello, world!\0";
Expand Down
3 changes: 1 addition & 2 deletions src/libstd/ffi/os_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -952,8 +952,7 @@ impl ToOwned for OsStr {
self.to_os_string()
}
fn clone_into(&self, target: &mut OsString) {
target.clear();
target.push(self);
self.inner.clone_into(&mut target.inner)
}
}

Expand Down
4 changes: 4 additions & 0 deletions src/libstd/sys/windows/os_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,10 @@ impl Slice {
Buf { inner: buf }
}

pub fn clone_into(&self, buf: &mut Buf) {
self.inner.clone_into(&mut buf.inner)
}

#[inline]
pub fn into_box(&self) -> Box<Slice> {
unsafe { mem::transmute(self.inner.into_box()) }
Expand Down
4 changes: 4 additions & 0 deletions src/libstd/sys_common/os_str_bytes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,10 @@ impl Slice {
Buf { inner: self.inner.to_vec() }
}

pub fn clone_into(&self, buf: &mut Buf) {
self.inner.clone_into(&mut buf.inner)
}

#[inline]
pub fn into_box(&self) -> Box<Slice> {
let boxed: Box<[u8]> = self.inner.into();
Expand Down
4 changes: 4 additions & 0 deletions src/libstd/sys_common/wtf8.rs
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,10 @@ impl Wtf8 {
}
}

pub fn clone_into(&self, buf: &mut Wtf8Buf) {
self.bytes.clone_into(&mut buf.bytes)
}

/// Boxes this `Wtf8`.
#[inline]
pub fn into_box(&self) -> Box<Wtf8> {
Expand Down

0 comments on commit 4d38ac1

Please sign in to comment.