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
77
78
79
80
81
82
83
84
85
use core::{
    convert::{AsMut, AsRef},
    mem::MaybeUninit,
};
use num_traits::{Bounded, FromPrimitive, NumAssign, ToPrimitive, Unsigned};

/// Slot for `T` that may be empty or occupied.
///
/// Must have the same layout as `T`.
pub unsafe trait Slot: Sized {
    type Item: Sized;

    fn new(item: Self::Item) -> Self;
    unsafe fn assume_init(self) -> Self::Item;
    unsafe fn assume_init_read(&self) -> Self::Item;
}
pub trait UninitSlot: Slot {
    fn uninit() -> Self;
}
unsafe impl<T> Slot for MaybeUninit<T> {
    type Item = T;

    fn new(item: T) -> Self {
        Self::new(item)
    }
    unsafe fn assume_init(self) -> Self::Item {
        self.assume_init()
    }
    unsafe fn assume_init_read(&self) -> Self::Item {
        self.assume_init_read()
    }
}
impl<T> UninitSlot for MaybeUninit<T> {
    fn uninit() -> Self {
        Self::uninit()
    }
}

/// Abstract container. May be unsized.
///
/// # Safety
///
/// [`as_ref()`](`AsRef::as_ref`) and [`as_mut()`](`AsMut::as_mut`) must provide the same slices with the always the same content and unchanged length.
pub unsafe trait Container: AsRef<[Self::Slot]> + AsMut<[Self::Slot]> {
    type Item: Sized;
    type Slot: Slot<Item = Self::Item>;
}

/// Default container.
///
/// Exists because [`Default`] is not implemented for generic-length array (`[T; N]`).
pub trait DefaultContainer: Container + Sized {
    fn default() -> Self;
}

unsafe impl<S: Slot, const N: usize> Container for [S; N] {
    type Item = S::Item;
    type Slot = S;
}
impl<S: UninitSlot, const N: usize> DefaultContainer for [S; N] {
    fn default() -> Self {
        [(); N].map(|()| S::uninit())
    }
}

unsafe impl<S: Slot> Container for [S] {
    type Item = S::Item;
    type Slot = S;
}

unsafe impl<'a, S: Slot> Container for &'a mut [S] {
    type Item = S::Item;
    type Slot = S;
}

/// Abstract type that could be used as vector length.
pub trait Length:
    Unsigned + NumAssign + Copy + Sized + Ord + Bounded + ToPrimitive + FromPrimitive
{
}

impl<T> Length for T where
    T: Unsigned + NumAssign + Copy + Sized + Ord + Bounded + ToPrimitive + FromPrimitive
{
}