about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPavel Grigorenko <GrigorenkoPV@ya.ru>2024-06-23 23:05:10 +0300
committerPavel Grigorenko <GrigorenkoPV@ya.ru>2024-07-29 20:44:39 +0300
commitafabc583f7f646d45f506263a1c331383ebdc252 (patch)
treedf95c9b8b394722c04dd8c6e865c8275e946f0ad
parentec921db289ea87fd4030cb7f8a70f6ba3a31c2c7 (diff)
downloadrust-afabc583f7f646d45f506263a1c331383ebdc252.tar.gz
rust-afabc583f7f646d45f506263a1c331383ebdc252.zip
impl CloneToUninit for Path and OsStr
-rw-r--r--library/std/src/ffi/os_str.rs12
-rw-r--r--library/std/src/ffi/os_str/tests.rs17
-rw-r--r--library/std/src/lib.rs1
-rw-r--r--library/std/src/path.rs11
-rw-r--r--library/std/src/path/tests.rs19
-rw-r--r--library/std/src/sys/os_str/bytes.rs12
-rw-r--r--library/std/src/sys/os_str/wtf8.rs12
-rw-r--r--library/std/src/sys_common/wtf8.rs11
8 files changed, 95 insertions, 0 deletions
diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs
index a501bcc98cf..f68ea3c562a 100644
--- a/library/std/src/ffi/os_str.rs
+++ b/library/std/src/ffi/os_str.rs
@@ -3,10 +3,13 @@
 #[cfg(test)]
 mod tests;
 
+use core::clone::CloneToUninit;
+
 use crate::borrow::{Borrow, Cow};
 use crate::collections::TryReserveError;
 use crate::hash::{Hash, Hasher};
 use crate::ops::{self, Range};
+use crate::ptr::addr_of_mut;
 use crate::rc::Rc;
 use crate::str::FromStr;
 use crate::sync::Arc;
@@ -1261,6 +1264,15 @@ impl Clone for Box<OsStr> {
     }
 }
 
+#[unstable(feature = "clone_to_uninit", issue = "126799")]
+unsafe impl CloneToUninit for OsStr {
+    #[cfg_attr(debug_assertions, track_caller)]
+    unsafe fn clone_to_uninit(&self, dst: *mut Self) {
+        // SAFETY: we're just a wrapper around a platform-specific Slice
+        unsafe { self.inner.clone_to_uninit(addr_of_mut!((*dst).inner)) }
+    }
+}
+
 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl From<OsString> for Arc<OsStr> {
     /// Converts an [`OsString`] into an <code>[Arc]<[OsStr]></code> by moving the [`OsString`]
diff --git a/library/std/src/ffi/os_str/tests.rs b/library/std/src/ffi/os_str/tests.rs
index 5b39b9e34d8..67147934b4d 100644
--- a/library/std/src/ffi/os_str/tests.rs
+++ b/library/std/src/ffi/os_str/tests.rs
@@ -1,4 +1,6 @@
 use super::*;
+use crate::mem::MaybeUninit;
+use crate::ptr;
 
 #[test]
 fn test_os_string_with_capacity() {
@@ -286,3 +288,18 @@ fn slice_surrogate_edge() {
     assert_eq!(post_crab.slice_encoded_bytes(..4), "🦀");
     assert_eq!(post_crab.slice_encoded_bytes(4..), surrogate);
 }
+
+#[test]
+fn clone_to_uninit() {
+    let a = OsStr::new("hello.txt");
+
+    let mut storage = vec![MaybeUninit::<u8>::uninit(); size_of_val::<OsStr>(a)];
+    unsafe { a.clone_to_uninit(ptr::from_mut::<[_]>(storage.as_mut_slice()) as *mut OsStr) };
+    assert_eq!(a.as_encoded_bytes(), unsafe { MaybeUninit::slice_assume_init_ref(&storage) });
+
+    let mut b: Box<OsStr> = OsStr::new("world.exe").into();
+    assert_eq!(size_of_val::<OsStr>(a), size_of_val::<OsStr>(&b));
+    assert_ne!(a, &*b);
+    unsafe { a.clone_to_uninit(ptr::from_mut::<OsStr>(&mut b)) };
+    assert_eq!(a, &*b);
+}
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index ee6f5a6f3c0..5cc6376a32d 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -323,6 +323,7 @@
 // tidy-alphabetical-start
 #![feature(c_str_module)]
 #![feature(char_internals)]
+#![feature(clone_to_uninit)]
 #![feature(core_intrinsics)]
 #![feature(core_io_borrowed_buf)]
 #![feature(duration_constants)]
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index 80163667636..d6c78883f28 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -70,6 +70,8 @@
 #[cfg(test)]
 mod tests;
 
+use core::clone::CloneToUninit;
+
 use crate::borrow::{Borrow, Cow};
 use crate::collections::TryReserveError;
 use crate::error::Error;
@@ -3109,6 +3111,15 @@ impl Path {
     }
 }
 
+#[unstable(feature = "clone_to_uninit", issue = "126799")]
+unsafe impl CloneToUninit for Path {
+    #[cfg_attr(debug_assertions, track_caller)]
+    unsafe fn clone_to_uninit(&self, dst: *mut Self) {
+        // SAFETY: Path is just a wrapper around OsStr
+        unsafe { self.inner.clone_to_uninit(core::ptr::addr_of_mut!((*dst).inner)) }
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl AsRef<OsStr> for Path {
     #[inline]
diff --git a/library/std/src/path/tests.rs b/library/std/src/path/tests.rs
index a12e42cba0c..6436872087d 100644
--- a/library/std/src/path/tests.rs
+++ b/library/std/src/path/tests.rs
@@ -3,6 +3,8 @@ use core::hint::black_box;
 use super::*;
 use crate::collections::{BTreeSet, HashSet};
 use crate::hash::DefaultHasher;
+use crate::mem::MaybeUninit;
+use crate::ptr;
 
 #[allow(unknown_lints, unused_macro_rules)]
 macro_rules! t (
@@ -2054,3 +2056,20 @@ fn bench_hash_path_long(b: &mut test::Bencher) {
 
     black_box(hasher.finish());
 }
+
+#[test]
+fn clone_to_uninit() {
+    let a = Path::new("hello.txt");
+
+    let mut storage = vec![MaybeUninit::<u8>::uninit(); size_of_val::<Path>(a)];
+    unsafe { a.clone_to_uninit(ptr::from_mut::<[_]>(storage.as_mut_slice()) as *mut Path) };
+    assert_eq!(a.as_os_str().as_encoded_bytes(), unsafe {
+        MaybeUninit::slice_assume_init_ref(&storage)
+    });
+
+    let mut b: Box<Path> = Path::new("world.exe").into();
+    assert_eq!(size_of_val::<Path>(a), size_of_val::<Path>(&b));
+    assert_ne!(a, &*b);
+    unsafe { a.clone_to_uninit(ptr::from_mut::<Path>(&mut b)) };
+    assert_eq!(a, &*b);
+}
diff --git a/library/std/src/sys/os_str/bytes.rs b/library/std/src/sys/os_str/bytes.rs
index 0f8bd645352..8529207366e 100644
--- a/library/std/src/sys/os_str/bytes.rs
+++ b/library/std/src/sys/os_str/bytes.rs
@@ -1,6 +1,9 @@
 //! The underlying OsString/OsStr implementation on Unix and many other
 //! systems: just a `Vec<u8>`/`[u8]`.
 
+use core::clone::CloneToUninit;
+use core::ptr::addr_of_mut;
+
 use crate::borrow::Cow;
 use crate::collections::TryReserveError;
 use crate::fmt::Write;
@@ -345,3 +348,12 @@ impl Slice {
         self.inner.eq_ignore_ascii_case(&other.inner)
     }
 }
+
+#[unstable(feature = "clone_to_uninit", issue = "126799")]
+unsafe impl CloneToUninit for Slice {
+    #[cfg_attr(debug_assertions, track_caller)]
+    unsafe fn clone_to_uninit(&self, dst: *mut Self) {
+        // SAFETY: we're just a wrapper around [u8]
+        unsafe { self.inner.clone_to_uninit(addr_of_mut!((*dst).inner)) }
+    }
+}
diff --git a/library/std/src/sys/os_str/wtf8.rs b/library/std/src/sys/os_str/wtf8.rs
index ed975ba58b5..e5755a4b874 100644
--- a/library/std/src/sys/os_str/wtf8.rs
+++ b/library/std/src/sys/os_str/wtf8.rs
@@ -1,5 +1,8 @@
 //! The underlying OsString/OsStr implementation on Windows is a
 //! wrapper around the "WTF-8" encoding; see the `wtf8` module for more.
+use core::clone::CloneToUninit;
+use core::ptr::addr_of_mut;
+
 use crate::borrow::Cow;
 use crate::collections::TryReserveError;
 use crate::rc::Rc;
@@ -268,3 +271,12 @@ impl Slice {
         self.inner.eq_ignore_ascii_case(&other.inner)
     }
 }
+
+#[unstable(feature = "clone_to_uninit", issue = "126799")]
+unsafe impl CloneToUninit for Slice {
+    #[cfg_attr(debug_assertions, track_caller)]
+    unsafe fn clone_to_uninit(&self, dst: *mut Self) {
+        // SAFETY: we're just a wrapper around Wtf8
+        unsafe { self.inner.clone_to_uninit(addr_of_mut!((*dst).inner)) }
+    }
+}
diff --git a/library/std/src/sys_common/wtf8.rs b/library/std/src/sys_common/wtf8.rs
index 277c9506feb..2bdeff78ddf 100644
--- a/library/std/src/sys_common/wtf8.rs
+++ b/library/std/src/sys_common/wtf8.rs
@@ -19,12 +19,14 @@
 mod tests;
 
 use core::char::{encode_utf16_raw, encode_utf8_raw};
+use core::clone::CloneToUninit;
 use core::str::next_code_point;
 
 use crate::borrow::Cow;
 use crate::collections::TryReserveError;
 use crate::hash::{Hash, Hasher};
 use crate::iter::FusedIterator;
+use crate::ptr::addr_of_mut;
 use crate::rc::Rc;
 use crate::sync::Arc;
 use crate::sys_common::AsInner;
@@ -1046,3 +1048,12 @@ impl Hash for Wtf8 {
         0xfeu8.hash(state)
     }
 }
+
+#[unstable(feature = "clone_to_uninit", issue = "126799")]
+unsafe impl CloneToUninit for Wtf8 {
+    #[cfg_attr(debug_assertions, track_caller)]
+    unsafe fn clone_to_uninit(&self, dst: *mut Self) {
+        // SAFETY: we're just a wrapper around [u8]
+        unsafe { self.bytes.clone_to_uninit(addr_of_mut!((*dst).bytes)) }
+    }
+}