use std::{
marker::PhantomData,
ops::{Index, IndexMut},
};
pub struct IndexMap<I: Into<usize> + From<usize>, V> {
pub(crate) entries: Vec<V>,
index: PhantomData<I>,
}
impl<I: Into<usize> + From<usize>, V> Default for IndexMap<I, V> {
fn default() -> Self {
Self {
entries: Vec::new(),
index: PhantomData,
}
}
}
impl<I: Into<usize> + From<usize>, V> IndexMap<I, V> {
pub fn is_empty(&self) -> bool {
self.entries.is_empty()
}
pub fn len(&self) -> usize {
self.entries.len()
}
pub fn get(&self, index: I) -> Option<&V> {
self.entries.get(index.into())
}
pub fn get_mut(&self, index: I) -> Option<&V> {
self.entries.get(index.into())
}
pub fn iter(&self) -> Iter<'_, I, V> {
self.into_iter()
}
pub(crate) fn insert(&mut self, index: I, value: V) {
let i = index.into();
assert_eq!(i, self.entries.len(), "Wrong insertion order");
self.entries.push(value);
}
}
impl<I: Into<usize> + From<usize>, V> Index<I> for IndexMap<I, V> {
type Output = V;
fn index(&self, index: I) -> &V {
&self.entries[index.into()]
}
}
impl<I: Into<usize> + From<usize>, V> IndexMut<I> for IndexMap<I, V> {
fn index_mut(&mut self, index: I) -> &mut V {
&mut self.entries[index.into()]
}
}
pub struct IntoIter<I: Into<usize> + From<usize>, V> {
data: std::iter::Enumerate<std::vec::IntoIter<V>>,
index: PhantomData<I>,
}
impl<I: Into<usize> + From<usize>, V> Iterator for IntoIter<I, V> {
type Item = (I, V);
fn next(&mut self) -> Option<(I, V)> {
let (i, value) = self.data.next()?;
Some((i.into(), value))
}
}
impl<I: Into<usize> + From<usize>, V> IntoIterator for IndexMap<I, V> {
type Item = (I, V);
type IntoIter = IntoIter<I, V>;
fn into_iter(self) -> IntoIter<I, V> {
IntoIter {
data: self.entries.into_iter().enumerate(),
index: PhantomData,
}
}
}
pub struct Iter<'a, I: Into<usize> + From<usize>, V> {
data: std::iter::Enumerate<std::slice::Iter<'a, V>>,
index: PhantomData<I>,
}
impl<'a, I: Into<usize> + From<usize>, V> Iterator for Iter<'a, I, V> {
type Item = (I, &'a V);
fn next(&mut self) -> Option<(I, &'a V)> {
let (i, value) = self.data.next()?;
Some((i.into(), value))
}
}
impl<'a, I: Into<usize> + From<usize>, V> IntoIterator for &'a IndexMap<I, V> {
type Item = (I, &'a V);
type IntoIter = Iter<'a, I, V>;
fn into_iter(self) -> Iter<'a, I, V> {
Iter {
data: self.entries.iter().enumerate(),
index: PhantomData,
}
}
}