use core::{
borrow::{Borrow, BorrowMut},
ops::{Deref, DerefMut},
slice::{Iter, IterMut},
};
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
#[repr(transparent)]
pub struct ArrayWrapper<T, const N: usize>(
pub [T; N],
);
impl<T, const N: usize> ArrayWrapper<T, N> {
#[inline]
pub fn from_fn<F>(mut cb: F) -> Self
where
F: FnMut(usize) -> T,
{
let mut idx = 0;
Self([(); N].map(|_| {
let res = cb(idx);
idx = idx.wrapping_add(1);
res
}))
}
#[inline]
pub fn try_from_fn<E, F>(cb: F) -> Result<Self, E>
where
F: FnMut(usize) -> Result<T, E>,
{
Ok(Self(here_be_dragons::try_from_fn(cb)?))
}
}
impl<T, const N: usize> AsRef<[T; N]> for ArrayWrapper<T, N> {
#[inline]
fn as_ref(&self) -> &[T; N] {
self
}
}
impl<T, const N: usize> AsMut<[T; N]> for ArrayWrapper<T, N> {
#[inline]
fn as_mut(&mut self) -> &mut [T; N] {
self
}
}
impl<T, const N: usize> Borrow<[T; N]> for ArrayWrapper<T, N> {
#[inline]
fn borrow(&self) -> &[T; N] {
self
}
}
impl<T, const N: usize> BorrowMut<[T; N]> for ArrayWrapper<T, N> {
#[inline]
fn borrow_mut(&mut self) -> &mut [T; N] {
self
}
}
impl<T, const N: usize> Default for ArrayWrapper<T, N>
where
T: Default,
{
#[inline]
fn default() -> Self {
Self::from_fn(|_| T::default())
}
}
impl<T, const N: usize> Deref for ArrayWrapper<T, N> {
type Target = [T; N];
#[inline]
fn deref(&self) -> &[T; N] {
&self.0
}
}
impl<T, const N: usize> DerefMut for ArrayWrapper<T, N> {
#[inline]
fn deref_mut(&mut self) -> &mut [T; N] {
&mut self.0
}
}
impl<T, const N: usize> From<[T; N]> for ArrayWrapper<T, N> {
#[inline]
fn from(from: [T; N]) -> Self {
Self(from)
}
}
impl<'array, T, const N: usize> IntoIterator for &'array ArrayWrapper<T, N> {
type IntoIter = Iter<'array, T>;
type Item = &'array T;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.0.iter()
}
}
impl<'array, T, const N: usize> IntoIterator for &'array mut ArrayWrapper<T, N> {
type IntoIter = IterMut<'array, T>;
type Item = &'array mut T;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.0.iter_mut()
}
}
mod here_be_dragons {
#![allow(clippy::as_conversions, clippy::mem_forget, trivial_casts, unsafe_code)]
use core::{
mem::{self, MaybeUninit},
ptr,
};
#[inline]
pub(super) fn try_from_fn<E, F, T, const N: usize>(cb: F) -> Result<[T; N], E>
where
F: FnMut(usize) -> Result<T, E>,
{
let mut iter = (0..N).map(cb);
debug_assert!(N <= iter.size_hint().1.unwrap_or(usize::MAX));
debug_assert!(N <= iter.size_hint().0);
unsafe { try_collect_into_array(&mut iter).unwrap_unchecked() }
}
unsafe fn array_assume_init<T, const N: usize>(array: [MaybeUninit<T>; N]) -> [T; N] {
(&array as *const _ as *const [T; N]).read()
}
fn try_collect_into_array<E, I, T, const N: usize>(iter: &mut I) -> Option<Result<[T; N], E>>
where
I: Iterator<Item = Result<T, E>>,
{
if N == 0 {
return unsafe { Some(mem::zeroed()) };
}
struct Guard<'array, T, const N: usize> {
array_mut: &'array mut [MaybeUninit<T>; N],
initialized: usize,
}
impl<T, const N: usize> Drop for Guard<'_, T, N> {
fn drop(&mut self) {
debug_assert!(self.initialized <= N);
unsafe {
ptr::drop_in_place(slice_assume_init_mut(
self.array_mut.get_unchecked_mut(..self.initialized),
));
}
}
}
let mut array = uninit_array::<T, N>();
let mut guard = Guard { array_mut: &mut array, initialized: 0 };
for item_rslt in iter {
let item = match item_rslt {
Err(err) => {
return Some(Err(err));
}
Ok(elem) => elem,
};
unsafe {
let _ = guard.array_mut.get_unchecked_mut(guard.initialized).write(item);
}
guard.initialized = guard.initialized.wrapping_add(1);
if guard.initialized == N {
mem::forget(guard);
let out = unsafe { array_assume_init(array) };
return Some(Ok(out));
}
}
None
}
unsafe fn slice_assume_init_mut<T>(slice: &mut [MaybeUninit<T>]) -> &mut [T] {
&mut *(slice as *mut [MaybeUninit<T>] as *mut [T])
}
const fn uninit_array<T, const LEN: usize>() -> [MaybeUninit<T>; LEN] {
unsafe { MaybeUninit::<[MaybeUninit<T>; LEN]>::uninit().assume_init() }
}
}
#[cfg(feature = "serde")]
mod serde {
use crate::ArrayWrapper;
use core::{fmt, marker::PhantomData};
use serde::{
de::{self, SeqAccess, Visitor},
ser::SerializeTuple,
Deserialize, Deserializer, Serialize, Serializer,
};
impl<'de, T, const N: usize> Deserialize<'de> for ArrayWrapper<T, N>
where
T: Deserialize<'de>,
{
#[inline]
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct ArrayVisitor<T, const N: usize>(PhantomData<T>);
impl<'de, T, const N: usize> Visitor<'de> for ArrayVisitor<T, N>
where
T: Deserialize<'de>,
{
type Value = ArrayWrapper<T, N>;
#[inline]
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_fmt(format_args!("an array with {} elements", N))
}
#[inline]
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
ArrayWrapper::try_from_fn(|_| {
seq.next_element::<T>()?.ok_or_else(|| {
de::Error::invalid_length(N, &"Array need more data to be constructed")
})
})
}
}
deserializer.deserialize_seq(ArrayVisitor::<T, N>(PhantomData))
}
}
impl<T, const N: usize> Serialize for ArrayWrapper<T, N>
where
T: Serialize,
{
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut seq = serializer.serialize_tuple(self.0.len())?;
for elem in &self.0 {
seq.serialize_element(elem)?;
}
seq.end()
}
}
}