use super::Vector;
use core::{
array::IntoIter,
convert::{TryFrom, TryInto},
iter::IntoIterator,
mem::{self, MaybeUninit},
slice,
};
impl<T, const N: usize> Vector<T, N> {
pub fn iter(&self) -> slice::Iter<'_, T> {
self.as_ref().iter()
}
pub fn iter_mut(&mut self) -> slice::IterMut<'_, T> {
self.as_mut().iter_mut()
}
}
impl<T, const N: usize> IntoIterator for Vector<T, N> {
type Item = T;
type IntoIter = IntoIter<T, N>;
fn into_iter(self) -> Self::IntoIter {
self.into_array().into_iter()
}
}
impl<'a, T, const N: usize> IntoIterator for &'a Vector<T, N> {
type Item = &'a T;
type IntoIter = slice::Iter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.as_ref().iter()
}
}
impl<'a, T, const N: usize> IntoIterator for &'a mut Vector<T, N> {
type Item = &'a mut T;
type IntoIter = slice::IterMut<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.as_mut().iter_mut()
}
}
impl<'a, T, const N: usize> TryFrom<&'a [T]> for Vector<T, N>
where
T: Copy,
{
type Error = ();
fn try_from(s: &'a [T]) -> Result<Self, Self::Error> {
s.try_into().map(Self::from_array).map_err(|_| ())
}
}
impl<T, const N: usize> Vector<T, N> {
pub fn try_from_iter<I>(iter: I) -> Option<Self>
where
I: Iterator<Item = T>,
{
let mut a = Vector::uninit();
let mut pos: usize = 0;
for (x, y) in a.iter_mut().zip(iter) {
let _ = mem::replace(x, MaybeUninit::new(y));
pos += 1;
}
#[allow(clippy::comparison_chain)]
if pos > N {
unreachable!();
} else if pos == N {
Some(unsafe { a.assume_init() })
} else {
unsafe {
for x in a.as_mut().get_unchecked_mut(0..pos) {
mem::replace(x, MaybeUninit::uninit()).assume_init();
}
}
None
}
}
}
impl<const N: usize> Vector<usize, N> {
pub fn indices() -> Self {
Self::try_from_iter(0..N).unwrap()
}
}
impl<T, const N: usize> Vector<T, N> {
pub fn for_each<F: FnMut(T)>(self, f: F) {
self.into_iter().for_each(f)
}
pub fn map<U, F: FnMut(T) -> U>(self, f: F) -> Vector<U, N> {
self.into_array().map(f).into()
}
pub fn zip<U>(self, other: Vector<U, N>) -> Vector<(T, U), N> {
Vector::try_from_iter(&mut self.into_iter().zip(other.into_iter())).unwrap()
}
pub fn enumerate(self) -> Vector<(usize, T), N> {
Vector::indices().zip(self)
}
}
impl<T, U, const N: usize> Vector<(T, U), N> {
pub fn unzip(self) -> (Vector<T, N>, Vector<U, N>) {
let mut a = Vector::<T, N>::uninit();
let mut b = Vector::<U, N>::uninit();
for ((x, y), (u, v)) in self.into_iter().zip(a.iter_mut().zip(b.iter_mut())) {
let _ = mem::replace(u, MaybeUninit::new(x));
let _ = mem::replace(v, MaybeUninit::new(y));
}
unsafe { (a.assume_init(), b.assume_init()) }
}
}
impl<T, const N: usize> Vector<T, N> {
pub fn fold<S, F: FnMut(S, T) -> S>(self, s: S, f: F) -> S {
self.into_iter().fold(s, f)
}
pub fn fold_first<F: FnMut(T, T) -> T>(self, f: F) -> T {
let mut t = self.into_iter();
let x = t.next().unwrap();
t.fold(x, f)
}
pub fn scan<S, U, F: FnMut(&mut S, T) -> U>(self, s: S, mut f: F) -> Vector<U, N> {
Vector::try_from_iter(&mut self.into_iter().scan(s, |s, x| Some(f(s, x)))).unwrap()
}
}
pub struct GroupIter<I: Iterator, const N: usize> {
iter: I,
}
impl<I, const N: usize> GroupIter<I, N>
where
I: Iterator,
{
pub fn new(iter: I) -> Self {
Self { iter }
}
}
impl<I, const N: usize> Iterator for GroupIter<I, N>
where
I: Iterator,
{
type Item = Vector<I::Item, N>;
fn next(&mut self) -> Option<Self::Item> {
<Self::Item>::try_from_iter(&mut self.iter)
}
}