libpitust 0.1.2

libpitust implements random utility functions I tend to use a lot
Documentation
use std::{
    marker::PhantomData,
    ops::{Index, IndexMut},
};

use crate::index::Idx;

impl<I: Idx, T> Default for IndexVec<I, T> {
    fn default() -> Self {
        IndexVec::new()
    }
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct IndexVec<I: Idx, T> {
    vec: Vec<T>,
    _marker: PhantomData<fn(&I)>,
}
impl<I: Idx, T> IndexVec<I, T> {
    pub fn index_iter(&self) -> impl DoubleEndedIterator<Item = I> + use<I, T> {
        (0..self.vec.len()).map(|i| I::new(i as u64))
    }
    pub fn iter(&self) -> impl DoubleEndedIterator<Item = (I, &T)> {
        self.vec
            .iter()
            .enumerate()
            .map(|(i, elem)| (Idx::new(i as u64), elem))
    }
    pub fn iter_mut(&mut self) -> impl DoubleEndedIterator<Item = (I, &mut T)> {
        self.vec
            .iter_mut()
            .enumerate()
            .map(|(i, elem)| (Idx::new(i as u64), elem))
    }
    pub fn key_cast<I2: Idx>(self) -> IndexVec<I2, T> {
        IndexVec {
            vec: self.vec,
            _marker: PhantomData,
        }
    }
    pub fn resize(&mut self, len: usize, fill: impl Fn(I) -> T) {
        if self.len() < len {
            while self.len() < len {
                let item = fill(Idx::new(self.len() as u64));
                self.push(item);
            }
        } else {
            self.vec.truncate(len);
        }
    }
    pub fn clear(&mut self) {
        self.vec.clear();
    }
    pub fn clear_to_len(&mut self, len: usize)
    where
        T: Default,
    {
        self.vec.truncate(0);
        while self.len() < len {
            self.push(T::default());
        }
    }
    pub fn with_map<V>(&self, mut f: impl FnMut(I, &T) -> V) -> IndexVec<I, V> {
        let mut dst = IndexVec::new();
        dst.vec.reserve(self.len());
        for (i, val) in self.iter() {
            let res = dst.vec.push_within_capacity(f(i, val));

            // SAFETY: we reserve enough capacity to make this work
            unsafe { res.unwrap_unchecked() };
        }

        dst
    }
    pub fn with_map_mut<V>(&mut self, mut f: impl FnMut(I, &mut T) -> V) -> IndexVec<I, V> {
        let mut dst = IndexVec::new();
        dst.vec.reserve(self.len());
        for (i, val) in self.iter_mut() {
            let res = dst.vec.push_within_capacity(f(i, val));

            // SAFETY: we reserve enough capacity to make this work
            unsafe { res.unwrap_unchecked() };
        }

        dst
    }
    pub fn idx_cast<DstIdx: Idx>(self) -> IndexVec<DstIdx, T> {
        IndexVec {
            vec: self.vec,
            _marker: PhantomData,
        }
    }
}
impl<'a, I: Idx, T> IntoIterator for &'a IndexVec<I, T> {
    type Item = (I, &'a T);
    type IntoIter = impl DoubleEndedIterator<Item = Self::Item>;

    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}
impl<'a, I: Idx, T> IntoIterator for &'a mut IndexVec<I, T> {
    type Item = (I, &'a mut T);
    type IntoIter = impl DoubleEndedIterator<Item = Self::Item>;

    fn into_iter(self) -> Self::IntoIter {
        self.vec
            .iter_mut()
            .enumerate()
            .map(|(i, elem)| (Idx::new(i as u64), elem))
    }
}
impl<I: Idx, T> IntoIterator for IndexVec<I, T> {
    type Item = (I, T);
    type IntoIter = impl DoubleEndedIterator<Item = Self::Item>;

    fn into_iter(self) -> Self::IntoIter {
        self.vec
            .into_iter()
            .enumerate()
            .map(|(i, elem)| (Idx::new(i as u64), elem))
    }
}
impl<I: Idx, T> Index<I> for IndexVec<I, T> {
    type Output = T;

    fn index(&self, index: I) -> &T {
        &self.vec[index.index() as usize]
    }
}
impl<I: Idx, T> IndexMut<I> for IndexVec<I, T> {
    fn index_mut(&mut self, index: I) -> &mut T {
        &mut self.vec[index.index() as usize]
    }
}
impl<I: Idx, T> IndexVec<I, T> {
    pub fn new() -> IndexVec<I, T> {
        IndexVec {
            vec: Vec::new(),
            _marker: PhantomData,
        }
    }
    pub fn new_with<const N: usize>(elems: [T; N]) -> IndexVec<I, T> {
        IndexVec {
            vec: elems.into(),
            _marker: PhantomData,
        }
    }
    pub fn len(&self) -> usize {
        self.vec.len()
    }
    pub fn push(&mut self, it: T) -> I {
        let l = self.vec.len();
        self.vec.push(it);
        I::new(l as u64)
    }
    pub fn insert_into(&mut self, idx: I, it: T) {
        self.vec.insert(idx.index() as usize, it);
    }
    pub fn from_vec(vec: Vec<T>) -> IndexVec<I, T> {
        IndexVec {
            vec,
            _marker: PhantomData,
        }
    }
}