#![cfg_attr(feature = "nightly", feature(generic_const_exprs))]
pub trait Array<T> {
fn len(&self) -> usize;
fn is_empty(&self) -> bool;
fn first(&self) -> Option<&T>;
fn first_mut(&mut self) -> Option<&mut T>;
fn last(&self) -> Option<&T>;
fn last_mut(&mut self) -> Option<&mut T>;
fn get(&self, index: usize) -> Option<&T>;
fn get_mut(&mut self, index: usize) -> Option<&mut T>;
fn as_slice(&self) -> &[T];
fn as_mut_slice(&mut self) -> &mut [T];
fn map_<F>(self, f: F) -> Self
where
F: FnMut(T) -> T,
Self: Sized;
fn foldl<A, F>(self, acc: A, f: F) -> A
where
F: FnMut(A, T) -> A,
Self: Sized;
fn foldr<A, F>(self, acc: A, f: F) -> A
where
F: FnMut(A, T) -> A,
Self: Sized;
fn resize<const S: usize>(self, elem: T) -> [T; S]
where
T: Clone,
Self: Sized;
fn resize_with<F, const S: usize>(self, f: F) -> [T; S]
where
F: FnMut(usize) -> T,
Self: Sized;
#[deprecated(since = "0.4.0", note = "use std::array::from_fn instead")]
fn from_fn<F>(f: F) -> Self
where
F: FnMut(usize) -> T,
Self: Sized;
fn from_iter(iter: impl Iterator<Item = T>) -> Option<Self>
where
Self: Sized;
}
impl<T, const N: usize> Array<T> for [T; N] {
#[inline]
fn len(&self) -> usize {
N
}
#[inline]
fn is_empty(&self) -> bool {
N == 0
}
#[inline]
fn first(&self) -> Option<&T> {
if N > 0 {
Some(&self[0])
} else {
None
}
}
#[inline]
fn first_mut(&mut self) -> Option<&mut T> {
if N > 0 {
Some(&mut self[0])
} else {
None
}
}
#[inline]
fn last(&self) -> Option<&T> {
if N > 0 {
Some(&self[N - 1])
} else {
None
}
}
#[inline]
fn last_mut(&mut self) -> Option<&mut T> {
if N > 0 {
Some(&mut self[N - 1])
} else {
None
}
}
#[inline]
fn get(&self, index: usize) -> Option<&T> {
if index < N {
Some(&self[index])
} else {
None
}
}
#[inline]
fn get_mut(&mut self, index: usize) -> Option<&mut T> {
if index < N {
Some(&mut self[index])
} else {
None
}
}
#[inline]
fn as_slice(&self) -> &[T] {
self
}
#[inline]
fn as_mut_slice(&mut self) -> &mut [T] {
self
}
#[inline]
fn map_<F>(self, f: F) -> Self
where
F: FnMut(T) -> T,
{
self.map(f)
}
#[inline]
fn foldl<A, F>(self, mut acc: A, mut f: F) -> A
where
F: FnMut(A, T) -> A,
{
for val in self {
acc = f(acc, val);
}
acc
}
#[inline]
fn foldr<A, F>(self, mut acc: A, mut f: F) -> A
where
F: FnMut(A, T) -> A,
{
for val in self.into_iter().rev() {
acc = f(acc, val);
}
acc
}
#[inline]
fn resize<const S: usize>(self, elem: T) -> [T; S]
where
T: Clone,
{
self.resize_with(|_| elem.clone())
}
#[inline]
fn resize_with<F, const S: usize>(self, mut f: F) -> [T; S]
where
F: FnMut(usize) -> T,
{
let mut a = self.into_iter();
std::array::from_fn(|i| if i < N { a.next().unwrap() } else { f(i) })
}
#[inline]
fn from_fn<F>(f: F) -> Self
where
F: FnMut(usize) -> T,
{
std::array::from_fn(f)
}
#[inline]
fn from_iter(mut iter: impl Iterator<Item = T>) -> Option<Self> {
let mut v = Vec::with_capacity(N); for _ in 0..N {
v.push(iter.next()?);
}
v.try_into().ok()
}
}
pub trait ArrayN<T, const N: usize>: Array<T> {
fn zip_with<U, V, F>(self, other: [U; N], f: F) -> [V; N]
where
F: FnMut(T, U) -> V,
Self: Sized;
fn downcast(self) -> [T; N];
fn downcast_ref(&self) -> &[T; N];
fn downcast_mut(&mut self) -> &mut [T; N];
#[cfg(feature = "nightly")]
fn concat<const M: usize>(self, other: [T; M]) -> [T; N + M]
where
Self: Sized;
#[cfg(feature = "nightly")]
fn split<const P: usize>(self) -> ([T; P], [T; N - P])
where
Self: Sized;
}
impl<T, const N: usize> ArrayN<T, N> for [T; N] {
#[inline]
fn zip_with<U, V, F>(self, other: [U; N], mut f: F) -> [V; N]
where
F: FnMut(T, U) -> V,
{
let mut b = other.into_iter();
self.map(|a| f(a, b.next().unwrap()))
}
#[inline]
fn downcast(self) -> [T; N] {
self
}
#[inline]
fn downcast_ref(&self) -> &[T; N] {
self
}
#[inline]
fn downcast_mut(&mut self) -> &mut [T; N] {
self
}
#[cfg(feature = "nightly")]
fn concat<const M: usize>(self, other: [T; M]) -> [T; N + M] {
let mut a = self.into_iter();
let mut b = other.into_iter();
std::array::from_fn(|i| if i < N { a.next() } else { b.next() }.unwrap())
}
#[cfg(feature = "nightly")]
fn split<const P: usize>(self) -> ([T; P], [T; N - P]) {
let mut a = self.into_iter();
let l = [(); P].map(|_| a.next().unwrap());
let r = [(); N - P].map(|_| a.next().unwrap());
(l, r)
}
}
#[cfg(test)]
mod tests;