1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
use std::mem::MaybeUninit;
/// This trait is used to write code that may work on matrices that may or may not
/// be initialized.
///
/// This trait is used to describe how a value must be accessed to initialize it or
/// to retrieve a reference or mutable reference. Typically, a function accepting
/// both initialized and uninitialized inputs should have a `Status: InitStatus<T>`
/// type parameter. Then the methods of the `Status` can be used to access the element.
///
/// # Safety
/// This trait must not be implemented outside of this crate.
pub unsafe trait InitStatus<T>: Copy {
    /// The type of the values with the initialization status described by `Self`.
    type Value;
    /// Initialize the given element.
    fn init(out: &mut Self::Value, t: T);
    /// Retrieve a reference to the element, assuming that it is initialized.
    ///
    /// # Safety
    /// This is unsound if the referenced value isn’t initialized.
    unsafe fn assume_init_ref(t: &Self::Value) -> &T;
    /// Retrieve a mutable reference to the element, assuming that it is initialized.
    ///
    /// # Safety
    /// This is unsound if the referenced value isn’t initialized.
    unsafe fn assume_init_mut(t: &mut Self::Value) -> &mut T;
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
/// A type implementing `InitStatus` indicating that the value is completely initialized.
pub struct Init;
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
/// A type implementing `InitStatus` indicating that the value is completely uninitialized.
pub struct Uninit;
unsafe impl<T> InitStatus<T> for Init {
    type Value = T;
    #[inline(always)]
    fn init(out: &mut T, t: T) {
        *out = t;
    }
    #[inline(always)]
    unsafe fn assume_init_ref(t: &T) -> &T {
        t
    }
    #[inline(always)]
    unsafe fn assume_init_mut(t: &mut T) -> &mut T {
        t
    }
}
unsafe impl<T> InitStatus<T> for Uninit {
    type Value = MaybeUninit<T>;
    #[inline(always)]
    fn init(out: &mut MaybeUninit<T>, t: T) {
        *out = MaybeUninit::new(t);
    }
    #[inline(always)]
    unsafe fn assume_init_ref(t: &MaybeUninit<T>) -> &T {
        &*t.as_ptr() // TODO: use t.assume_init_ref()
    }
    #[inline(always)]
    unsafe fn assume_init_mut(t: &mut MaybeUninit<T>) -> &mut T {
        &mut *t.as_mut_ptr() // TODO: use t.assume_init_mut()
    }
}