Created
July 27, 2019 16:28
-
-
Save DutchGhost/04cd56b6f37c0cb4b1e5cd2d0de83f90 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| use core::{ | |
| mem::{self, MaybeUninit}, | |
| ptr, | |
| }; | |
| /// This struct is a simple wrapper around `[MaybeUninit<T>; N]`. | |
| /// It provides some convenience methods for working with arrays that may have uninitialized items. | |
| pub(crate) struct MaybeArray<T, const N: usize> { | |
| array: [MaybeUninit<T>; N] | |
| } | |
| impl <T, const N: usize> Default for MaybeArray<T, { N }> { | |
| #[inline(always)] | |
| fn default() -> Self { | |
| Self { | |
| array: unsafe { MaybeUninit::<_>::uninit().assume_init() } | |
| } | |
| } | |
| } | |
| impl <T, const N: usize> MaybeArray<T, { N }> { | |
| /// Returns a pointer to the element at `index`. | |
| /// This element *may* be uninitialized. | |
| #[inline(always)] | |
| fn nth_ptr(&self, index: usize) -> *const T { | |
| debug_assert!(index < N); | |
| unsafe { | |
| let nth_element = &*(self.array.get_unchecked(index)); | |
| nth_element.as_ptr() | |
| } | |
| } | |
| /// Returns a mutable pointer to the element at `index`. | |
| /// This element *may* be uninitialized. | |
| #[inline(always)] | |
| fn nth_ptr_mut(&mut self, index: usize) -> *mut T { | |
| debug_assert!(index < N); | |
| unsafe { | |
| let nth_element = &mut *(self.array.get_unchecked_mut(index)); | |
| nth_element.as_mut_ptr() | |
| } | |
| } | |
| /// Returns a pointer to the first element of the array. | |
| /// This element *may* be uninitialized. | |
| #[inline(always)] | |
| fn first_ptr(&mut self) -> *const T { | |
| self.nth_ptr(0) | |
| } | |
| /// Returns a mutable pointer to the first element of the array. | |
| /// This element *may* be uninitialized. | |
| #[inline(always)] | |
| fn first_ptr_mut(&mut self) -> *mut T { | |
| self.nth_ptr_mut(0) | |
| } | |
| /// Returns a pointer to the whole array. | |
| /// There *may* be elements in the array that are uninitialized. | |
| #[inline(always)] | |
| const fn array_ptr(&self) -> *const [T; N] { | |
| &self.array as *const [MaybeUninit<T>; N] as *const [T; N] | |
| } | |
| /// Returns a mutable pointer to the whole array. | |
| /// There *may* be elements in the array that are uninitialized. | |
| #[inline(always)] | |
| fn array_ptr_mut(&mut self) -> *mut [T; N] { | |
| &mut self.array as *mut [MaybeUninit<T>; N] as *mut [T; N] | |
| } | |
| /// Reads the element at `index`. | |
| /// | |
| /// # Unsafe | |
| /// Marked unsafe because | |
| /// 1) `index` is *NOT* boundschecked. | |
| /// 2) The element at `index` may be uninitialized, thus reading it is invalid. | |
| #[inline(always)] | |
| pub unsafe fn take(&mut self, index: usize) -> T { | |
| ptr::read(self.nth_ptr_mut(index)) | |
| } | |
| /// Sets the element at `index` to `value`. | |
| /// | |
| /// # Unsafe | |
| /// Marked unsafe because `index` is not boundchecked. | |
| #[inline(always)] | |
| pub unsafe fn set(&mut self, index: usize, value: T) { | |
| ptr::write(self.nth_ptr_mut(index), value) | |
| } | |
| /// Transforms `this` into an array. | |
| /// # Unsafe | |
| /// Marked unsafe because all elements within the `MaybeArray` *MUST* | |
| /// be initialized. If they are not, invoking this function is UB. | |
| pub unsafe fn into_array(mut this: MaybeArray<T, N>) -> [T; N] { | |
| // We dont have to `mem::forget(this)`, | |
| // since the inner array contains `MaybeUninit<T>`'s, | |
| // which will never invoke the destructor. | |
| let array_ptr = this.array_ptr_mut(); | |
| ptr::read(array_ptr) | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment