Skip to content

Commit e11fc75

Browse files
authored
Rollup merge of rust-lang#65580 - SimonSapin:maybeuninit-array, r=Amanieu
Add `MaybeUninit` methods `uninit_array`, `slice_get_ref`, `slice_get_mut` Eventually these will hopefully become the idiomatic way to work with partially-initialized stack buffers. All methods are unstable. Note that `uninit_array` takes a type-level `const usize` parameter, so it is blocked (at least in its current form) on const generics. Example: ```rust use std::mem::MaybeUninit; let input = b"Foo"; let f = u8::to_ascii_uppercase; let mut buffer: [MaybeUninit<u8>; 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<u8>>(); &vec }; assert_eq!(output, b"FOO"); ```
2 parents 3bb06d6 + 639c4f7 commit e11fc75

File tree

1 file changed

+63
-0
lines changed

1 file changed

+63
-0
lines changed

src/libcore/mem/maybe_uninit.rs

+63
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,43 @@ impl<T> MaybeUninit<T> {
258258
MaybeUninit { uninit: () }
259259
}
260260

261+
/// Create a new array of `MaybeUninit<T>` items, in an uninitialized state.
262+
///
263+
/// Note: in a future Rust version this method may become unnecessary
264+
/// when array literal syntax allows
265+
/// [repeating const expressions](https://github.com/rust-lang/rust/issues/49147).
266+
/// The example below could then use `let mut buf = [MaybeUninit::<u8>::uninit(); 32];`.
267+
///
268+
/// # Examples
269+
///
270+
/// ```no_run
271+
/// #![feature(maybe_uninit_uninit_array, maybe_uninit_extra, maybe_uninit_slice_assume_init)]
272+
///
273+
/// use std::mem::MaybeUninit;
274+
///
275+
/// extern "C" {
276+
/// fn read_into_buffer(ptr: *mut u8, max_len: usize) -> usize;
277+
/// }
278+
///
279+
/// /// Returns a (possibly smaller) slice of data that was actually read
280+
/// fn read(buf: &mut [MaybeUninit<u8>]) -> &[u8] {
281+
/// unsafe {
282+
/// let len = read_into_buffer(buf.as_mut_ptr() as *mut u8, buf.len());
283+
/// MaybeUninit::slice_get_ref(&buf[..len])
284+
/// }
285+
/// }
286+
///
287+
/// let mut buf: [MaybeUninit<u8>; 32] = MaybeUninit::uninit_array();
288+
/// let data = read(&mut buf);
289+
/// ```
290+
#[unstable(feature = "maybe_uninit_uninit_array", issue = "0")]
291+
#[inline(always)]
292+
pub fn uninit_array<const LEN: usize>() -> [Self; LEN] {
293+
unsafe {
294+
MaybeUninit::<[MaybeUninit<T>; LEN]>::uninit().assume_init()
295+
}
296+
}
297+
261298
/// A promotable constant, equivalent to `uninit()`.
262299
#[unstable(feature = "internal_uninit_const", issue = "0",
263300
reason = "hack to work around promotability")]
@@ -690,6 +727,32 @@ impl<T> MaybeUninit<T> {
690727
&mut *self.value
691728
}
692729

730+
/// Assuming all the elements are initialized, get a slice to them.
731+
///
732+
/// # Safety
733+
///
734+
/// It is up to the caller to guarantee that the `MaybeUninit<T>` elements
735+
/// really are in an initialized state.
736+
/// Calling this when the content is not yet fully initialized causes undefined behavior.
737+
#[unstable(feature = "maybe_uninit_slice_assume_init", issue = "0")]
738+
#[inline(always)]
739+
pub unsafe fn slice_get_ref(slice: &[Self]) -> &[T] {
740+
&*(slice as *const [Self] as *const [T])
741+
}
742+
743+
/// Assuming all the elements are initialized, get a mutable slice to them.
744+
///
745+
/// # Safety
746+
///
747+
/// It is up to the caller to guarantee that the `MaybeUninit<T>` elements
748+
/// really are in an initialized state.
749+
/// Calling this when the content is not yet fully initialized causes undefined behavior.
750+
#[unstable(feature = "maybe_uninit_slice_assume_init", issue = "0")]
751+
#[inline(always)]
752+
pub unsafe fn slice_get_mut(slice: &mut [Self]) -> &mut [T] {
753+
&mut *(slice as *mut [Self] as *mut [T])
754+
}
755+
693756
/// Gets a pointer to the first element of the array.
694757
#[unstable(feature = "maybe_uninit_slice", issue = "63569")]
695758
#[inline(always)]

0 commit comments

Comments
 (0)