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));
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));
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,
}
}
}