Skip to content

Commit e8c3718

Browse files
committed
impl CloneToUninit for Path and OsStr
1 parent ef8c591 commit e8c3718

File tree

8 files changed

+95
-0
lines changed

8 files changed

+95
-0
lines changed

Diff for: std/src/ffi/os_str.rs

+12
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@
33
#[cfg(test)]
44
mod tests;
55

6+
use core::clone::CloneToUninit;
7+
68
use crate::borrow::{Borrow, Cow};
79
use crate::collections::TryReserveError;
810
use crate::hash::{Hash, Hasher};
911
use crate::ops::{self, Range};
12+
use crate::ptr::addr_of_mut;
1013
use crate::rc::Rc;
1114
use crate::str::FromStr;
1215
use crate::sync::Arc;
@@ -1261,6 +1264,15 @@ impl Clone for Box<OsStr> {
12611264
}
12621265
}
12631266

1267+
#[unstable(feature = "clone_to_uninit", issue = "126799")]
1268+
unsafe impl CloneToUninit for OsStr {
1269+
#[cfg_attr(debug_assertions, track_caller)]
1270+
unsafe fn clone_to_uninit(&self, dst: *mut Self) {
1271+
// SAFETY: we're just a wrapper around a platform-specific Slice
1272+
unsafe { self.inner.clone_to_uninit(addr_of_mut!((*dst).inner)) }
1273+
}
1274+
}
1275+
12641276
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
12651277
impl From<OsString> for Arc<OsStr> {
12661278
/// Converts an [`OsString`] into an <code>[Arc]<[OsStr]></code> by moving the [`OsString`]

Diff for: std/src/ffi/os_str/tests.rs

+17
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
use super::*;
2+
use crate::mem::MaybeUninit;
3+
use crate::ptr;
24

35
#[test]
46
fn test_os_string_with_capacity() {
@@ -286,3 +288,18 @@ fn slice_surrogate_edge() {
286288
assert_eq!(post_crab.slice_encoded_bytes(..4), "🦀");
287289
assert_eq!(post_crab.slice_encoded_bytes(4..), surrogate);
288290
}
291+
292+
#[test]
293+
fn clone_to_uninit() {
294+
let a = OsStr::new("hello.txt");
295+
296+
let mut storage = vec![MaybeUninit::<u8>::uninit(); size_of_val::<OsStr>(a)];
297+
unsafe { a.clone_to_uninit(ptr::from_mut::<[_]>(storage.as_mut_slice()) as *mut OsStr) };
298+
assert_eq!(a.as_encoded_bytes(), unsafe { MaybeUninit::slice_assume_init_ref(&storage) });
299+
300+
let mut b: Box<OsStr> = OsStr::new("world.exe").into();
301+
assert_eq!(size_of_val::<OsStr>(a), size_of_val::<OsStr>(&b));
302+
assert_ne!(a, &*b);
303+
unsafe { a.clone_to_uninit(ptr::from_mut::<OsStr>(&mut b)) };
304+
assert_eq!(a, &*b);
305+
}

Diff for: std/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@
323323
// tidy-alphabetical-start
324324
#![feature(c_str_module)]
325325
#![feature(char_internals)]
326+
#![feature(clone_to_uninit)]
326327
#![feature(core_intrinsics)]
327328
#![feature(core_io_borrowed_buf)]
328329
#![feature(duration_constants)]

Diff for: std/src/path.rs

+11
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@
7070
#[cfg(test)]
7171
mod tests;
7272

73+
use core::clone::CloneToUninit;
74+
7375
use crate::borrow::{Borrow, Cow};
7476
use crate::collections::TryReserveError;
7577
use crate::error::Error;
@@ -3109,6 +3111,15 @@ impl Path {
31093111
}
31103112
}
31113113

3114+
#[unstable(feature = "clone_to_uninit", issue = "126799")]
3115+
unsafe impl CloneToUninit for Path {
3116+
#[cfg_attr(debug_assertions, track_caller)]
3117+
unsafe fn clone_to_uninit(&self, dst: *mut Self) {
3118+
// SAFETY: Path is just a wrapper around OsStr
3119+
unsafe { self.inner.clone_to_uninit(core::ptr::addr_of_mut!((*dst).inner)) }
3120+
}
3121+
}
3122+
31123123
#[stable(feature = "rust1", since = "1.0.0")]
31133124
impl AsRef<OsStr> for Path {
31143125
#[inline]

Diff for: std/src/path/tests.rs

+19
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ use core::hint::black_box;
33
use super::*;
44
use crate::collections::{BTreeSet, HashSet};
55
use crate::hash::DefaultHasher;
6+
use crate::mem::MaybeUninit;
7+
use crate::ptr;
68

79
#[allow(unknown_lints, unused_macro_rules)]
810
macro_rules! t (
@@ -2054,3 +2056,20 @@ fn bench_hash_path_long(b: &mut test::Bencher) {
20542056

20552057
black_box(hasher.finish());
20562058
}
2059+
2060+
#[test]
2061+
fn clone_to_uninit() {
2062+
let a = Path::new("hello.txt");
2063+
2064+
let mut storage = vec![MaybeUninit::<u8>::uninit(); size_of_val::<Path>(a)];
2065+
unsafe { a.clone_to_uninit(ptr::from_mut::<[_]>(storage.as_mut_slice()) as *mut Path) };
2066+
assert_eq!(a.as_os_str().as_encoded_bytes(), unsafe {
2067+
MaybeUninit::slice_assume_init_ref(&storage)
2068+
});
2069+
2070+
let mut b: Box<Path> = Path::new("world.exe").into();
2071+
assert_eq!(size_of_val::<Path>(a), size_of_val::<Path>(&b));
2072+
assert_ne!(a, &*b);
2073+
unsafe { a.clone_to_uninit(ptr::from_mut::<Path>(&mut b)) };
2074+
assert_eq!(a, &*b);
2075+
}

Diff for: std/src/sys/os_str/bytes.rs

+12
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
//! The underlying OsString/OsStr implementation on Unix and many other
22
//! systems: just a `Vec<u8>`/`[u8]`.
33
4+
use core::clone::CloneToUninit;
5+
use core::ptr::addr_of_mut;
6+
47
use crate::borrow::Cow;
58
use crate::collections::TryReserveError;
69
use crate::fmt::Write;
@@ -345,3 +348,12 @@ impl Slice {
345348
self.inner.eq_ignore_ascii_case(&other.inner)
346349
}
347350
}
351+
352+
#[unstable(feature = "clone_to_uninit", issue = "126799")]
353+
unsafe impl CloneToUninit for Slice {
354+
#[cfg_attr(debug_assertions, track_caller)]
355+
unsafe fn clone_to_uninit(&self, dst: *mut Self) {
356+
// SAFETY: we're just a wrapper around [u8]
357+
unsafe { self.inner.clone_to_uninit(addr_of_mut!((*dst).inner)) }
358+
}
359+
}

Diff for: std/src/sys/os_str/wtf8.rs

+12
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
//! The underlying OsString/OsStr implementation on Windows is a
22
//! wrapper around the "WTF-8" encoding; see the `wtf8` module for more.
3+
use core::clone::CloneToUninit;
4+
use core::ptr::addr_of_mut;
5+
36
use crate::borrow::Cow;
47
use crate::collections::TryReserveError;
58
use crate::rc::Rc;
@@ -268,3 +271,12 @@ impl Slice {
268271
self.inner.eq_ignore_ascii_case(&other.inner)
269272
}
270273
}
274+
275+
#[unstable(feature = "clone_to_uninit", issue = "126799")]
276+
unsafe impl CloneToUninit for Slice {
277+
#[cfg_attr(debug_assertions, track_caller)]
278+
unsafe fn clone_to_uninit(&self, dst: *mut Self) {
279+
// SAFETY: we're just a wrapper around Wtf8
280+
unsafe { self.inner.clone_to_uninit(addr_of_mut!((*dst).inner)) }
281+
}
282+
}

Diff for: std/src/sys_common/wtf8.rs

+11
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,14 @@
1919
mod tests;
2020

2121
use core::char::{encode_utf16_raw, encode_utf8_raw};
22+
use core::clone::CloneToUninit;
2223
use core::str::next_code_point;
2324

2425
use crate::borrow::Cow;
2526
use crate::collections::TryReserveError;
2627
use crate::hash::{Hash, Hasher};
2728
use crate::iter::FusedIterator;
29+
use crate::ptr::addr_of_mut;
2830
use crate::rc::Rc;
2931
use crate::sync::Arc;
3032
use crate::sys_common::AsInner;
@@ -1046,3 +1048,12 @@ impl Hash for Wtf8 {
10461048
0xfeu8.hash(state)
10471049
}
10481050
}
1051+
1052+
#[unstable(feature = "clone_to_uninit", issue = "126799")]
1053+
unsafe impl CloneToUninit for Wtf8 {
1054+
#[cfg_attr(debug_assertions, track_caller)]
1055+
unsafe fn clone_to_uninit(&self, dst: *mut Self) {
1056+
// SAFETY: we're just a wrapper around [u8]
1057+
unsafe { self.bytes.clone_to_uninit(addr_of_mut!((*dst).bytes)) }
1058+
}
1059+
}

0 commit comments

Comments
 (0)