impl CloneToUninit for str and CStr
This commit is contained in:
parent
4db3d12e6f
commit
ec921db289
2 changed files with 61 additions and 0 deletions
|
@ -346,6 +346,27 @@ unsafe impl<T: Copy> CloneToUninit for [T] {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "clone_to_uninit", issue = "126799")]
|
||||||
|
unsafe impl CloneToUninit for str {
|
||||||
|
#[cfg_attr(debug_assertions, track_caller)]
|
||||||
|
unsafe fn clone_to_uninit(&self, dst: *mut Self) {
|
||||||
|
// SAFETY: str is just a [u8] with UTF-8 invariant
|
||||||
|
unsafe { self.as_bytes().clone_to_uninit(dst as *mut [u8]) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "clone_to_uninit", issue = "126799")]
|
||||||
|
unsafe impl CloneToUninit for crate::ffi::CStr {
|
||||||
|
#[cfg_attr(debug_assertions, track_caller)]
|
||||||
|
unsafe fn clone_to_uninit(&self, dst: *mut Self) {
|
||||||
|
// SAFETY: For now, CStr is just a #[repr(trasnsparent)] [c_char] with some invariants.
|
||||||
|
// And we can cast [c_char] to [u8] on all supported platforms (see: to_bytes_with_nul).
|
||||||
|
// The pointer metadata properly preserves the length (NUL included).
|
||||||
|
// See: `cstr_metadata_is_length_with_nul` in tests.
|
||||||
|
unsafe { self.to_bytes_with_nul().clone_to_uninit(dst as *mut [u8]) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Ownership of a collection of values stored in a non-owned `[MaybeUninit<T>]`, some of which
|
/// Ownership of a collection of values stored in a non-owned `[MaybeUninit<T>]`, some of which
|
||||||
/// are not yet initialized. This is sort of like a `Vec` that doesn't own its allocation.
|
/// are not yet initialized. This is sort of like a `Vec` that doesn't own its allocation.
|
||||||
/// Its responsibility is to provide cleanup on unwind by dropping the values that *are*
|
/// Its responsibility is to provide cleanup on unwind by dropping the values that *are*
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
use core::clone::CloneToUninit;
|
use core::clone::CloneToUninit;
|
||||||
|
use core::ffi::CStr;
|
||||||
use core::mem::MaybeUninit;
|
use core::mem::MaybeUninit;
|
||||||
|
use core::ptr;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[allow(suspicious_double_ref_op)]
|
#[allow(suspicious_double_ref_op)]
|
||||||
|
@ -81,3 +83,41 @@ fn test_clone_to_uninit_slice_drops_on_panic() {
|
||||||
drop(a);
|
drop(a);
|
||||||
assert_eq!(COUNTER.load(Relaxed), 0);
|
assert_eq!(COUNTER.load(Relaxed), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_clone_to_uninit_str() {
|
||||||
|
let a = "hello";
|
||||||
|
|
||||||
|
let mut storage: MaybeUninit<[u8; 5]> = MaybeUninit::uninit();
|
||||||
|
unsafe { a.clone_to_uninit(storage.as_mut_ptr() as *mut [u8] as *mut str) };
|
||||||
|
assert_eq!(a.as_bytes(), unsafe { storage.assume_init() }.as_slice());
|
||||||
|
|
||||||
|
let mut b: Box<str> = "world".into();
|
||||||
|
assert_eq!(a.len(), b.len());
|
||||||
|
assert_ne!(a, &*b);
|
||||||
|
unsafe { a.clone_to_uninit(ptr::from_mut::<str>(&mut b)) };
|
||||||
|
assert_eq!(a, &*b);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_clone_to_uninit_cstr() {
|
||||||
|
let a = c"hello";
|
||||||
|
|
||||||
|
let mut storage: MaybeUninit<[u8; 6]> = MaybeUninit::uninit();
|
||||||
|
unsafe { a.clone_to_uninit(storage.as_mut_ptr() as *mut [u8] as *mut CStr) };
|
||||||
|
assert_eq!(a.to_bytes_with_nul(), unsafe { storage.assume_init() }.as_slice());
|
||||||
|
|
||||||
|
let mut b: Box<CStr> = c"world".into();
|
||||||
|
assert_eq!(a.count_bytes(), b.count_bytes());
|
||||||
|
assert_ne!(a, &*b);
|
||||||
|
unsafe { a.clone_to_uninit(ptr::from_mut::<CStr>(&mut b)) };
|
||||||
|
assert_eq!(a, &*b);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn cstr_metadata_is_length_with_nul() {
|
||||||
|
let s: &CStr = c"abcdef";
|
||||||
|
let p: *const CStr = ptr::from_ref(s);
|
||||||
|
let bytes: *const [u8] = p as *const [u8];
|
||||||
|
assert_eq!(s.to_bytes_with_nul().len(), bytes.len());
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue