use super::{
Array,
errors::{
UnmatchedCapacity,
CapacityExceeded
}
};
use alloc::vec::Vec;
use constrangeiter::ConstIntoIterator;
use core::{
mem::{
MaybeUninit,
transmute_neo as transmute,
forget
},
array::from_fn as arrayfn,
marker::Destruct
};
const impl<
Type: [const] Destruct,
const M: usize,
const N: usize
> From<[Type; N]> for Array<Type, M> where [(); M - N]: {
fn from(value: [Type; N]) -> Self {
let mut data = MaybeUninit::<[Type; M]>::uninit().transpose();
let mut index = 0;
let _ = value.map(const |element| {
data[index].write(element);
index += 1;
});
return Array {
length: N,
data: data
};
}
}
const impl<
Type: [const] Destruct,
Generator: [const] FnMut(usize) -> Type + [const] Destruct,
const N: usize,
> From<Generator> for Array<Type, N> {
fn from(mut value: Generator) -> Self {return Array {
length: N,
data: arrayfn(const |index| MaybeUninit::new(value(index)))
}}
}
const impl<Type, const N: usize> TryFrom<Vec<Type>> for Array<Type, N> {
type Error = CapacityExceeded<N>;
fn try_from(value: Vec<Type>) -> Result<Self, Self::Error> {
let (pointer, length, _) = value.into_parts();
if length > N {return Err(CapacityExceeded {
expected: length
})}
let mut array = Array {
length: length,
data: MaybeUninit::uninit().transpose()
};
for index in (0..length).const_into_iter() {
array.data[index].write(unsafe {pointer.add(index).read()});
}
return Ok(array);
}
}
const impl<Type, const N: usize> From<(usize, [MaybeUninit<Type>; N])> for Array<Type, N> {
fn from((length, data): (usize, [MaybeUninit<Type>; N])) -> Self {return Array {
length: length,
data: data
}}
}
impl<Type, const N: usize> Into<Vec<Type>> for Array<Type, N> {
fn into(self) -> Vec<Type> {return Vec::from_iter(self.into_iter())}
}
const impl<
Type,
const N: usize,
const LENGTH: usize
> TryInto<[Type; LENGTH]> for Array<Type, N> where [(); N - LENGTH]: {
type Error = UnmatchedCapacity<LENGTH>;
fn try_into(self) -> Result<[Type; LENGTH], Self::Error> {
let (length, data) = self.into();
if length != LENGTH {return Err(UnmatchedCapacity {
present: length
})}
let (initialized, _): (
[MaybeUninit<Type>; LENGTH],
[MaybeUninit<Type>; N - LENGTH]
) = unsafe {transmute(data)};
return Ok(unsafe {transmute(initialized)});
}
}
const impl<Type, const N: usize> Into<(usize, [MaybeUninit<Type>; N])> for Array<Type, N> {
fn into(self) -> (usize, [MaybeUninit<Type>; N]) {
let length = self.length;
let data = unsafe {self.data.as_ptr().cast::<[MaybeUninit<Type>; N]>().read()};
forget(self);
return (length, data);
}
}