Skip to content

Commit 795bc2c

Browse files
authored
Rollup merge of #70201 - cuviper:clone_into, r=dtolnay
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`.
2 parents 39b6253 + f854070 commit 795bc2c

File tree

6 files changed

+36
-8
lines changed

6 files changed

+36
-8
lines changed

src/liballoc/slice.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -733,14 +733,14 @@ impl<T: Clone> ToOwned for [T] {
733733
fn clone_into(&self, target: &mut Vec<T>) {
734734
// drop anything in target that will not be overwritten
735735
target.truncate(self.len());
736-
let len = target.len();
737-
738-
// reuse the contained values' allocations/resources.
739-
target.clone_from_slice(&self[..len]);
740736

741737
// target.len <= self.len due to the truncate above, so the
742-
// slice here is always in-bounds.
743-
target.extend_from_slice(&self[len..]);
738+
// slices here are always in-bounds.
739+
let (init, tail) = self.split_at(target.len());
740+
741+
// reuse the contained values' allocations/resources.
742+
target.clone_from_slice(init);
743+
target.extend_from_slice(tail);
744744
}
745745
}
746746

src/libstd/ffi/c_str.rs

+17
Original file line numberDiff line numberDiff line change
@@ -1329,6 +1329,12 @@ impl ToOwned for CStr {
13291329
fn to_owned(&self) -> CString {
13301330
CString { inner: self.to_bytes_with_nul().into() }
13311331
}
1332+
1333+
fn clone_into(&self, target: &mut CString) {
1334+
let mut b = Vec::from(mem::take(&mut target.inner));
1335+
self.to_bytes_with_nul().clone_into(&mut b);
1336+
target.inner = b.into_boxed_slice();
1337+
}
13321338
}
13331339

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

1519+
#[test]
1520+
fn test_c_str_clone_into() {
1521+
let mut c_string = CString::new("lorem").unwrap();
1522+
let c_ptr = c_string.as_ptr();
1523+
let c_str = CStr::from_bytes_with_nul(b"ipsum\0").unwrap();
1524+
c_str.clone_into(&mut c_string);
1525+
assert_eq!(c_str, c_string.as_c_str());
1526+
// The exact same size shouldn't have needed to move its allocation
1527+
assert_eq!(c_ptr, c_string.as_ptr());
1528+
}
1529+
15131530
#[test]
15141531
fn into_rc() {
15151532
let orig: &[u8] = b"Hello, world!\0";

src/libstd/ffi/os_str.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1120,8 +1120,7 @@ impl ToOwned for OsStr {
11201120
self.to_os_string()
11211121
}
11221122
fn clone_into(&self, target: &mut OsString) {
1123-
target.clear();
1124-
target.push(self);
1123+
self.inner.clone_into(&mut target.inner)
11251124
}
11261125
}
11271126

src/libstd/sys/windows/os_str.rs

+4
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,10 @@ impl Slice {
159159
Buf { inner: buf }
160160
}
161161

162+
pub fn clone_into(&self, buf: &mut Buf) {
163+
self.inner.clone_into(&mut buf.inner)
164+
}
165+
162166
#[inline]
163167
pub fn into_box(&self) -> Box<Slice> {
164168
unsafe { mem::transmute(self.inner.into_box()) }

src/libstd/sys_common/os_str_bytes.rs

+4
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,10 @@ impl Slice {
173173
Buf { inner: self.inner.to_vec() }
174174
}
175175

176+
pub fn clone_into(&self, buf: &mut Buf) {
177+
self.inner.clone_into(&mut buf.inner)
178+
}
179+
176180
#[inline]
177181
pub fn into_box(&self) -> Box<Slice> {
178182
let boxed: Box<[u8]> = self.inner.into();

src/libstd/sys_common/wtf8.rs

+4
Original file line numberDiff line numberDiff line change
@@ -613,6 +613,10 @@ impl Wtf8 {
613613
}
614614
}
615615

616+
pub fn clone_into(&self, buf: &mut Wtf8Buf) {
617+
self.bytes.clone_into(&mut buf.bytes)
618+
}
619+
616620
/// Boxes this `Wtf8`.
617621
#[inline]
618622
pub fn into_box(&self) -> Box<Wtf8> {

0 commit comments

Comments
 (0)