Skip to content

Commit b80fa76

Browse files
committed
Implement ToOwned::clone_into for CStr
It can try to keep its allocation by converting the inner `Box` to `Vec`, using `clone_into` on the bytes, then convert back to `Box`.
1 parent e8339e8 commit b80fa76

File tree

1 file changed

+17
-0
lines changed

1 file changed

+17
-0
lines changed

src/libstd/ffi/c_str.rs

Lines changed: 17 additions & 0 deletions
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";

0 commit comments

Comments
 (0)