use core::mem::MaybeUninit;
use crate::util::transmute::extremely_unsafe_transmute;
pub unsafe trait Array: Sized {
type Item;
type Maybe: Array<Item = MaybeUninit<Self::Item>>;
const SIZE: usize;
fn as_slice(&self) -> &[Self::Item];
fn as_mut_slice(&mut self) -> &mut [Self::Item];
fn try_unfold<St, F, E>(init: St, f: F) -> Result<Self, E>
where
F: FnMut(&mut St) -> Result<Self::Item, E>;
fn unfold<St, F>(init: St, f: F) -> Self
where
F: FnMut(&mut St) -> Self::Item;
fn try_from_fn<F, E>(f: F) -> Result<Self, E>
where
F: FnMut(usize) -> Result<Self::Item, E>;
fn from_fn<F>(f: F) -> Self
where
F: FnMut(usize) -> Self::Item;
fn try_from_iter<I>(iter: I) -> Option<Self>
where
I: IntoIterator<Item = Self::Item>;
#[inline]
fn from_iter<I>(iter: I) -> Self
where
I: IntoIterator<Item = Self::Item>,
{
Self::try_from_iter(iter)
.expect("there weren't enough elements to fill an array of that size")
}
#[inline]
fn into_uninit(self) -> Self::Maybe {
unsafe { extremely_unsafe_transmute::<Self, Self::Maybe>(self) }
}
#[inline]
#[allow(clippy::uninit_assumed_init)]
fn uninit() -> Self::Maybe {
unsafe {
MaybeUninit::uninit().assume_init()
}
}
#[inline]
unsafe fn assume_init(uninit: Self::Maybe) -> Self {
extremely_unsafe_transmute::<Self::Maybe, Self>(uninit)
}
#[cfg(feature = "alloc")]
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
fn into_boxed_slice(self) -> alloc::boxed::Box<[Self::Item]>;
}
unsafe impl<T> Array for [T; 0] {
type Item = T;
type Maybe = [MaybeUninit<T>; 0];
const SIZE: usize = 0;
crate::if_alloc! {
#[inline]
fn into_boxed_slice(self) -> alloc::boxed::Box<[Self::Item]> {
alloc::boxed::Box::new(self) as _
}
}
#[inline]
fn as_slice(&self) -> &[T] {
&[]
}
#[inline]
fn as_mut_slice(&mut self) -> &mut [T] {
&mut []
}
#[inline]
fn try_unfold<St, F, E>(_init: St, _f: F) -> Result<Self, E>
where
F: FnMut(&mut St) -> Result<Self::Item, E>,
{
Ok([])
}
#[inline]
fn unfold<St, F>(_init: St, _f: F) -> Self
where
F: FnMut(&mut St) -> Self::Item,
{
[]
}
#[inline]
fn try_from_fn<F, E>(_f: F) -> Result<Self, E>
where
F: FnMut(usize) -> Result<Self::Item, E>,
{
Ok([])
}
#[inline]
fn from_fn<F>(_f: F) -> Self
where
F: FnMut(usize) -> Self::Item,
{
[]
}
#[inline]
fn try_from_iter<I>(_iter: I) -> Option<Self>
where
I: IntoIterator<Item = Self::Item>,
{
Some([])
}
#[inline]
fn into_uninit(self) -> Self::Maybe {
[]
}
}
macro_rules! array_impl {
($e:tt) => {
unsafe impl<T> Array for [T; $e] {
type Item = T;
type Maybe = [MaybeUninit<T>; $e];
const SIZE: usize = $e;
#[inline]
fn as_slice(&self) -> &[T] { &self[..] }
#[inline]
fn as_mut_slice(&mut self) -> &mut [T] { &mut self[..] }
#[inline]
#[allow(unused_mut)]
fn try_unfold<St, F, E>(mut init: St, mut f: F) -> Result<Self, E>
where
F: FnMut(&mut St) -> Result<Self::Item, E>
{
Ok(
block_specialisation!(
$e,
{ $crate::util::init::try_unfold_array(init, f)? },
{ f(&mut init)? }
)
)
}
#[inline]
#[allow(unused_mut)]
fn unfold<St, F>(mut init: St, mut f: F) -> Self
where
F: FnMut(&mut St) -> Self::Item
{
block_specialisation!(
$e,
{ $crate::util::init::unfold_array(init, f) },
{ f(&mut init) }
)
}
#[inline]
#[allow(unused_mut)]
fn try_from_fn<F, E>(mut f: F) -> Result<Self, E>
where
F: FnMut(usize) -> Result<Self::Item, E>
{
Ok(try_from_fn_specialisation!($e, f))
}
#[inline]
#[allow(unused_mut)]
fn from_fn<F>(mut f: F) -> Self
where
F: FnMut(usize) -> Self::Item
{
from_fn_specialisation!($e, f)
}
#[inline]
fn try_from_iter<I>(iter: I) -> Option<Self>
where
I: IntoIterator<Item = Self::Item>
{
#[allow(unused_mut)]
let mut iter = iter.into_iter();
Some(
block_specialisation!(
$e,
{ $crate::util::init::array_init_iter(iter)? },
{ iter.next()? }
)
)
}
$crate::if_alloc! {
#[inline]
fn into_boxed_slice(self) -> alloc::boxed::Box<[Self::Item]> {
alloc::boxed::Box::new(self) as _
}
}
}
};
}
array_impls!(array_impl);