Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 07bbc8b

Browse files
committedJun 25, 2024
impl CloneToUninit for Path and OsStr
1 parent 3ed73fe commit 07bbc8b

File tree

8 files changed

+95
-0
lines changed

8 files changed

+95
-0
lines changed
 

‎library/std/src/ffi/os_str.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,15 @@
33
#[cfg(test)]
44
mod tests;
55

6+
use core::clone::CloneToUninit;
7+
68
use crate::borrow::{Borrow, Cow};
79
use crate::cmp;
810
use crate::collections::TryReserveError;
911
use crate::fmt;
1012
use crate::hash::{Hash, Hasher};
1113
use crate::ops::{self, Range};
14+
use crate::ptr::addr_of_mut;
1215
use crate::rc::Rc;
1316
use crate::slice;
1417
use crate::str::FromStr;
@@ -1266,6 +1269,15 @@ impl Clone for Box<OsStr> {
12661269
}
12671270
}
12681271

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

‎library/std/src/ffi/os_str/tests.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
use super::*;
22

3+
use crate::mem::MaybeUninit;
4+
use crate::ptr;
5+
36
#[test]
47
fn test_os_string_with_capacity() {
58
let os_string = OsString::with_capacity(0);
@@ -286,3 +289,18 @@ fn slice_surrogate_edge() {
286289
assert_eq!(post_crab.slice_encoded_bytes(..4), "🦀");
287290
assert_eq!(post_crab.slice_encoded_bytes(4..), surrogate);
288291
}
292+
293+
#[test]
294+
fn clone_to_uninit() {
295+
let a = OsStr::new("hello.txt");
296+
297+
let mut storage = vec![MaybeUninit::<u8>::uninit(); size_of_val::<OsStr>(a)];
298+
unsafe { a.clone_to_uninit(ptr::from_mut::<[_]>(storage.as_mut_slice()) as *mut OsStr) };
299+
assert_eq!(a.as_encoded_bytes(), unsafe { MaybeUninit::slice_assume_init_ref(&storage) });
300+
301+
let mut b: Box<OsStr> = OsStr::new("world.exe").into();
302+
assert_eq!(size_of_val::<OsStr>(a), size_of_val::<OsStr>(&b));
303+
assert_ne!(a, &*b);
304+
unsafe { a.clone_to_uninit(ptr::from_mut::<OsStr>(&mut b)) };
305+
assert_eq!(a, &*b);
306+
}

‎library/std/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,7 @@
319319
// tidy-alphabetical-start
320320
#![feature(c_str_module)]
321321
#![feature(char_internals)]
322+
#![feature(clone_to_uninit)]
322323
#![feature(core_intrinsics)]
323324
#![feature(core_io_borrowed_buf)]
324325
#![feature(duration_constants)]

‎library/std/src/path.rs

Lines changed: 11 additions & 0 deletions
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::cmp;
7577
use crate::collections::TryReserveError;
@@ -3022,6 +3024,15 @@ impl Path {
30223024
}
30233025
}
30243026

3027+
#[unstable(feature = "clone_to_uninit", issue = "126799")]
3028+
unsafe impl CloneToUninit for Path {
3029+
#[cfg_attr(debug_assertions, track_caller)]
3030+
unsafe fn clone_to_uninit(&self, dst: *mut Self) {
3031+
// SAFETY: Path is just a wrapper around OsStr
3032+
unsafe { self.inner.clone_to_uninit(core::ptr::addr_of_mut!((*dst).inner)) }
3033+
}
3034+
}
3035+
30253036
#[stable(feature = "rust1", since = "1.0.0")]
30263037
impl AsRef<OsStr> for Path {
30273038
#[inline]

‎library/std/src/path/tests.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ use super::*;
22

33
use crate::collections::{BTreeSet, HashSet};
44
use crate::hash::DefaultHasher;
5+
use crate::mem::MaybeUninit;
6+
use crate::ptr;
57
use core::hint::black_box;
68

79
#[allow(unknown_lints, unused_macro_rules)]
@@ -1945,3 +1947,20 @@ fn bench_hash_path_long(b: &mut test::Bencher) {
19451947

19461948
black_box(hasher.finish());
19471949
}
1950+
1951+
#[test]
1952+
fn clone_to_uninit() {
1953+
let a = Path::new("hello.txt");
1954+
1955+
let mut storage = vec![MaybeUninit::<u8>::uninit(); size_of_val::<Path>(a)];
1956+
unsafe { a.clone_to_uninit(ptr::from_mut::<[_]>(storage.as_mut_slice()) as *mut Path) };
1957+
assert_eq!(a.as_os_str().as_encoded_bytes(), unsafe {
1958+
MaybeUninit::slice_assume_init_ref(&storage)
1959+
});
1960+
1961+
let mut b: Box<Path> = Path::new("world.exe").into();
1962+
assert_eq!(size_of_val::<Path>(a), size_of_val::<Path>(&b));
1963+
assert_ne!(a, &*b);
1964+
unsafe { a.clone_to_uninit(ptr::from_mut::<Path>(&mut b)) };
1965+
assert_eq!(a, &*b);
1966+
}

‎library/std/src/sys/os_str/bytes.rs

Lines changed: 12 additions & 0 deletions
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;
@@ -347,3 +350,12 @@ impl Slice {
347350
self.inner.eq_ignore_ascii_case(&other.inner)
348351
}
349352
}
353+
354+
#[unstable(feature = "clone_to_uninit", issue = "126799")]
355+
unsafe impl CloneToUninit for Slice {
356+
#[cfg_attr(debug_assertions, track_caller)]
357+
unsafe fn clone_to_uninit(&self, dst: *mut Self) {
358+
// SAFETY: we're just a wrapper around [u8]
359+
unsafe { self.inner.clone_to_uninit(addr_of_mut!((*dst).inner)) }
360+
}
361+
}

‎library/std/src/sys/os_str/wtf8.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
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;
35

46
use crate::borrow::Cow;
57
use crate::collections::TryReserveError;
@@ -270,3 +272,12 @@ impl Slice {
270272
self.inner.eq_ignore_ascii_case(&other.inner)
271273
}
272274
}
275+
276+
#[unstable(feature = "clone_to_uninit", issue = "126799")]
277+
unsafe impl CloneToUninit for Slice {
278+
#[cfg_attr(debug_assertions, track_caller)]
279+
unsafe fn clone_to_uninit(&self, dst: *mut Self) {
280+
// SAFETY: we're just a wrapper around Wtf8
281+
unsafe { self.inner.clone_to_uninit(addr_of_mut!((*dst).inner)) }
282+
}
283+
}

‎library/std/src/sys_common/wtf8.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
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;
@@ -28,6 +29,7 @@ use crate::hash::{Hash, Hasher};
2829
use crate::iter::FusedIterator;
2930
use crate::mem;
3031
use crate::ops;
32+
use crate::ptr::addr_of_mut;
3133
use crate::rc::Rc;
3234
use crate::slice;
3335
use crate::str;
@@ -1044,3 +1046,12 @@ impl Hash for Wtf8 {
10441046
0xfeu8.hash(state)
10451047
}
10461048
}
1049+
1050+
#[unstable(feature = "clone_to_uninit", issue = "126799")]
1051+
unsafe impl CloneToUninit for Wtf8 {
1052+
#[cfg_attr(debug_assertions, track_caller)]
1053+
unsafe fn clone_to_uninit(&self, dst: *mut Self) {
1054+
// SAFETY: we're just a wrapper around [u8]
1055+
unsafe { self.bytes.clone_to_uninit(addr_of_mut!((*dst).bytes)) }
1056+
}
1057+
}

0 commit comments

Comments
 (0)
Please sign in to comment.