#![no_std]
#![deny(missing_docs)]
pub trait ArrayIterator<const N: usize>: Sized {
type Item;
fn map_array<U, F: Fn(Self::Item) -> U>(self, f: F) -> Map<Self, F> {
Map{a: self, f}
}
fn zip_array<B: ArrayIterator<N>>(self, b: B) -> Zip<Self, B> {
Zip{a: self, b}
}
fn collect_array(self) -> [Self::Item; N] where Self::Item: Copy {
let mut array: [Self::Item; N] = unsafe { core::mem::MaybeUninit::uninit().assume_init() };
for i in 0..N {
array[i] = self.get(i);
}
array
}
#[cfg(feature = "drop")]
fn build_array(self) -> [Self::Item; N] where Self::Item: Drop {
let mut builder = array_builder::ArrayBuilder::new();
for i in 0..N {
builder.push(self.get(i));
}
unsafe { builder.build_unchecked() }
}
fn get(&self, n: usize) -> Self::Item;
}
pub struct Map<A, F> {
a: A,
f: F,
}
pub struct Zip<A, B> {
a: A,
b: B,
}
impl<T: Copy, const N: usize> ArrayIterator<N> for [T; N] {
type Item = T;
fn collect_array(self) -> [T; N] {
self
}
fn get(&self, n: usize) -> T {
self[n]
}
}
impl<U, A, F, const N: usize> ArrayIterator<N> for Map<A, F>
where
U: Copy,
A: ArrayIterator<N>,
F: Fn(A::Item) -> U,
{
type Item = U;
fn get(&self, n: usize) -> U {
(self.f)(self.a.get(n))
}
}
impl<A, B, const N: usize> ArrayIterator<N> for Zip<A, B>
where
A: ArrayIterator<N>,
B: ArrayIterator<N>,
{
type Item = (A::Item, B::Item);
fn get(&self, n: usize) -> Self::Item {
(self.a.get(n), self.b.get(n))
}
}
#[cfg(test)]
mod tests {
use crate::ArrayIterator;
#[test]
fn zip() {
let a = [1, 2, 3, 4];
let b = [5, 6, 7, 8];
let c = a.zip_array(b).map_array(|(a, b)| a + b).collect_array();
assert_eq!(c, [6, 8, 10, 12]);
}
}