From 1906c6f714502b1a0de46b9c217dc02570c3fd3e Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Sat, 19 Oct 2019 00:48:21 +0200 Subject: [PATCH 1/3] Add `MaybeUninit` methods `uninit_array`, `slice_get_ref`, `slice_get_mut` --- src/libcore/mem/maybe_uninit.rs | 57 +++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/src/libcore/mem/maybe_uninit.rs b/src/libcore/mem/maybe_uninit.rs index 03093139bc2f9..46b0fd3c3cbaa 100644 --- a/src/libcore/mem/maybe_uninit.rs +++ b/src/libcore/mem/maybe_uninit.rs @@ -258,6 +258,37 @@ impl MaybeUninit { MaybeUninit { uninit: () } } + /// Create a new array of `MaybeUninit` items, in an uninitialized state. + /// + /// # Examples + /// + /// ``` + /// #![feature(maybe_uninit_uninit_array, maybe_uninit_extra, maybe_uninit_slice_assume_init)] + /// use std::mem::MaybeUninit; + /// + /// let input = b"Foo"; + /// let f = u8::to_ascii_uppercase; + /// + /// let mut buffer: [MaybeUninit; 32] = MaybeUninit::uninit_array(); + /// let vec; + /// let output = if let Some(buffer) = buffer.get_mut(..input.len()) { + /// buffer.iter_mut().zip(input).for_each(|(a, b)| { a.write(f(b)); }); + /// unsafe { MaybeUninit::slice_get_ref(buffer) } + /// } else { + /// vec = input.iter().map(f).collect::>(); + /// &vec + /// }; + /// + /// assert_eq!(output, b"FOO"); + /// ``` + #[unstable(feature = "maybe_uninit_uninit_array", issue = "0")] + #[inline(always)] + pub fn uninit_array() -> [Self; LEN] { + unsafe { + MaybeUninit::<[MaybeUninit; LEN]>::uninit().assume_init() + } + } + /// A promotable constant, equivalent to `uninit()`. #[unstable(feature = "internal_uninit_const", issue = "0", reason = "hack to work around promotability")] @@ -690,6 +721,32 @@ impl MaybeUninit { &mut *self.value } + /// Get a slice of assume-initialized items. + /// + /// # Safety + /// + /// It is up to the caller to guarantee that the `MaybeUninit` items + /// really are in an initialized state. + /// Calling this when the content is not yet fully initialized causes undefined behavior. + #[unstable(feature = "maybe_uninit_slice_assume_init", issue = "0")] + #[inline(always)] + pub unsafe fn slice_get_ref(slice: &[Self]) -> &[T] { + &*(slice as *const [Self] as *const [T]) + } + + /// Get a mutable slice of assume-initialized items. + /// + /// # Safety + /// + /// It is up to the caller to guarantee that the `MaybeUninit` items + /// really are in an initialized state. + /// Calling this when the content is not yet fully initialized causes undefined behavior. + #[unstable(feature = "maybe_uninit_slice_assume_init", issue = "0")] + #[inline(always)] + pub unsafe fn slice_get_mut(slice: &mut [Self]) -> &mut [T] { + &mut *(slice as *mut [Self] as *mut [T]) + } + /// Gets a pointer to the first element of the array. #[unstable(feature = "maybe_uninit_slice", issue = "63569")] #[inline(always)] From 05c14bcc3180092ec4c03d59977abf96db7b4b7a Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Sat, 26 Oct 2019 08:51:49 +0200 Subject: [PATCH 2/3] Apply docs suggestions from review Co-Authored-By: Mazdak Farrokhzad --- src/libcore/mem/maybe_uninit.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libcore/mem/maybe_uninit.rs b/src/libcore/mem/maybe_uninit.rs index 46b0fd3c3cbaa..31f908e91f55e 100644 --- a/src/libcore/mem/maybe_uninit.rs +++ b/src/libcore/mem/maybe_uninit.rs @@ -721,11 +721,11 @@ impl MaybeUninit { &mut *self.value } - /// Get a slice of assume-initialized items. + /// Assuming all the elements are initialized, get a slice to them. /// /// # Safety /// - /// It is up to the caller to guarantee that the `MaybeUninit` items + /// It is up to the caller to guarantee that the `MaybeUninit` elements /// really are in an initialized state. /// Calling this when the content is not yet fully initialized causes undefined behavior. #[unstable(feature = "maybe_uninit_slice_assume_init", issue = "0")] @@ -734,11 +734,11 @@ impl MaybeUninit { &*(slice as *const [Self] as *const [T]) } - /// Get a mutable slice of assume-initialized items. + /// Assuming all the elements are initialized, get a mutable slice to them. /// /// # Safety /// - /// It is up to the caller to guarantee that the `MaybeUninit` items + /// It is up to the caller to guarantee that the `MaybeUninit` elements /// really are in an initialized state. /// Calling this when the content is not yet fully initialized causes undefined behavior. #[unstable(feature = "maybe_uninit_slice_assume_init", issue = "0")] From 639c4f779c60119383dd8a49b44522f6a6958a53 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Sat, 26 Oct 2019 09:19:48 +0200 Subject: [PATCH 3/3] MaybeUninit::uninit_array docs: better example --- src/libcore/mem/maybe_uninit.rs | 34 +++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/src/libcore/mem/maybe_uninit.rs b/src/libcore/mem/maybe_uninit.rs index 31f908e91f55e..0c0a6d8a121b8 100644 --- a/src/libcore/mem/maybe_uninit.rs +++ b/src/libcore/mem/maybe_uninit.rs @@ -260,26 +260,32 @@ impl MaybeUninit { /// Create a new array of `MaybeUninit` items, in an uninitialized state. /// + /// Note: in a future Rust version this method may become unnecessary + /// when array literal syntax allows + /// [repeating const expressions](https://github.com/rust-lang/rust/issues/49147). + /// The example below could then use `let mut buf = [MaybeUninit::::uninit(); 32];`. + /// /// # Examples /// - /// ``` + /// ```no_run /// #![feature(maybe_uninit_uninit_array, maybe_uninit_extra, maybe_uninit_slice_assume_init)] + /// /// use std::mem::MaybeUninit; /// - /// let input = b"Foo"; - /// let f = u8::to_ascii_uppercase; - /// - /// let mut buffer: [MaybeUninit; 32] = MaybeUninit::uninit_array(); - /// let vec; - /// let output = if let Some(buffer) = buffer.get_mut(..input.len()) { - /// buffer.iter_mut().zip(input).for_each(|(a, b)| { a.write(f(b)); }); - /// unsafe { MaybeUninit::slice_get_ref(buffer) } - /// } else { - /// vec = input.iter().map(f).collect::>(); - /// &vec - /// }; + /// extern "C" { + /// fn read_into_buffer(ptr: *mut u8, max_len: usize) -> usize; + /// } + /// + /// /// Returns a (possibly smaller) slice of data that was actually read + /// fn read(buf: &mut [MaybeUninit]) -> &[u8] { + /// unsafe { + /// let len = read_into_buffer(buf.as_mut_ptr() as *mut u8, buf.len()); + /// MaybeUninit::slice_get_ref(&buf[..len]) + /// } + /// } /// - /// assert_eq!(output, b"FOO"); + /// let mut buf: [MaybeUninit; 32] = MaybeUninit::uninit_array(); + /// let data = read(&mut buf); /// ``` #[unstable(feature = "maybe_uninit_uninit_array", issue = "0")] #[inline(always)]