use crate::raw::{AllocError, Init, Storage, StorageWithCapacity, Uninit};
use core::mem::{size_of, MaybeUninit};
pub type UninitArray<T, const N: usize> = Uninit<MaybeUninit<[T; N]>>;
pub type Array<T, const N: usize> = Init<[T; N]>;
unsafe impl<T, const N: usize> Send for UninitArray<T, N> {}
unsafe impl<T, const N: usize> Sync for UninitArray<T, N> {}
impl<T, const N: usize> UninitArray<T, N> {
pub const fn uninit() -> Self { Self(MaybeUninit::uninit()) }
pub const fn with_array(array: [T; N]) -> Self { Self(MaybeUninit::new(array)) }
}
impl<T, const N: usize> Array<T, N> {
pub const fn new(array: [T; N]) -> Self { Self(array) }
}
impl<T, const N: usize> Default for UninitArray<T, N> {
fn default() -> Self { Self::uninit() }
}
impl<T: Default + Copy, const N: usize> Default for Array<T, N> {
fn default() -> Self { Self([T::default(); N]) }
}
impl<T, const N: usize> Clone for UninitArray<T, N> {
fn clone(&self) -> Self { Self::default() }
}
impl<T: Copy, const N: usize> Copy for Array<T, N> {}
impl<T: Copy, const N: usize> Clone for Array<T, N> {
fn clone(&self) -> Self { *self }
}
impl<U, T, const N: usize> StorageWithCapacity<U> for UninitArray<T, N> {
fn with_capacity(capacity: usize) -> Self {
if capacity > N {
crate::raw::fixed_capacity_reserve_error(N, capacity)
}
Self::default()
}
#[inline]
#[doc(hidden)]
#[allow(non_snake_case)]
fn __with_capacity__const_capacity_checked(capacity: usize, old_capacity: Option<usize>) -> Self {
match old_capacity {
Some(old_capacity) if old_capacity <= N => Self::default(),
_ => StorageWithCapacity::<U>::with_capacity(capacity),
}
}
}
unsafe impl<U, T, const N: usize> Storage<U> for UninitArray<T, N> {
#[doc(hidden)]
const CONST_CAPACITY: Option<usize> = Some(crate::raw::capacity(N, size_of::<T>(), size_of::<U>()));
fn is_valid_storage() -> bool { true }
fn capacity(&self) -> usize { <Self as Storage<U>>::CONST_CAPACITY.unwrap() }
fn as_ptr(&self) -> *const U { self.0.as_ptr().cast() }
fn as_mut_ptr(&mut self) -> *mut U { self.0.as_mut_ptr().cast() }
fn reserve(&mut self, new_capacity: usize) {
let new_capacity = crate::raw::capacity(new_capacity, size_of::<U>(), size_of::<T>());
if new_capacity > N {
crate::raw::fixed_capacity_reserve_error(N, new_capacity)
}
}
fn try_reserve(&mut self, capacity: usize) -> Result<(), AllocError> {
if capacity <= N {
Ok(())
} else {
Err(AllocError)
}
}
}
unsafe impl<T: Copy, const N: usize> crate::raw::StorageInit<T> for Array<T, N> {}
impl<T: Default + Copy, const N: usize> StorageWithCapacity<T> for Array<T, N> {
fn with_capacity(capacity: usize) -> Self {
if capacity > N {
crate::raw::fixed_capacity_reserve_error(N, capacity)
}
Self::default()
}
#[inline]
#[doc(hidden)]
#[allow(non_snake_case)]
fn __with_capacity__const_capacity_checked(capacity: usize, old_capacity: Option<usize>) -> Self {
match old_capacity {
Some(old_capacity) if old_capacity <= N => Self::default(),
_ => Self::with_capacity(capacity),
}
}
}
unsafe impl<T: Copy, const N: usize> Storage<T> for Array<T, N> {
#[doc(hidden)]
const CONST_CAPACITY: Option<usize> = Some(N);
fn is_valid_storage() -> bool { true }
fn capacity(&self) -> usize { N }
fn as_ptr(&self) -> *const T { self.0.as_ptr().cast() }
fn as_mut_ptr(&mut self) -> *mut T { self.0.as_mut_ptr().cast() }
fn reserve(&mut self, capacity: usize) {
if capacity > N {
crate::raw::fixed_capacity_reserve_error(N, capacity)
}
}
fn try_reserve(&mut self, capacity: usize) -> Result<(), AllocError> {
if capacity <= N {
Ok(())
} else {
Err(AllocError)
}
}
}