use core::{
convert::{AsMut, AsRef},
mem::MaybeUninit,
};
use num_traits::{Bounded, FromPrimitive, NumAssign, ToPrimitive, Unsigned};
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()
}
}
pub unsafe trait Container: AsRef<[Self::Slot]> + AsMut<[Self::Slot]> {
type Item: Sized;
type Slot: Slot<Item = Self::Item>;
}
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;
}
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
{
}