use crate::Error;
use std::collections::HashMap;
#[derive(Clone, Debug)]
pub(crate) struct IndexMap<V, Index> {
data: Vec<V>,
map: HashMap<V, Index>,
}
impl<V, Index> Default for IndexMap<V, Index> {
fn default() -> Self {
Self {
data: vec![],
map: HashMap::new(),
}
}
}
pub(crate) trait Index {
fn new(i: usize) -> Self;
fn get(&self) -> usize;
}
impl<V, I> IndexMap<V, I>
where
V: Eq + std::hash::Hash + Clone,
I: Eq + std::hash::Hash + Copy + Index,
{
pub fn clear(&mut self) {
self.data.clear();
self.map.clear();
}
pub fn len(&self) -> usize {
self.data.len()
}
pub fn is_empty(&self) -> bool {
self.data.is_empty()
}
pub fn get_by_index(&self, i: I) -> Option<&V> {
self.data.get(i.get())
}
pub fn insert(&mut self, v: V) -> I {
*self.map.entry(v.clone()).or_insert_with(|| {
let out = I::new(self.data.len());
self.data.push(v);
out
})
}
pub fn pop(&mut self) -> Result<V, Error> {
match self.data.pop() {
Some(v) => {
self.map.remove(&v);
Ok(v)
}
None => Err(Error::EmptyMap),
}
}
pub fn keys(&self) -> impl Iterator<Item = I> {
(0..self.data.len()).map(I::new)
}
}
#[derive(Clone, Debug)]
pub struct IndexVec<V, I> {
data: Vec<V>,
_phantom: std::marker::PhantomData<*const I>,
}
impl<V, I> Default for IndexVec<V, I> {
fn default() -> Self {
Self {
data: vec![],
_phantom: std::marker::PhantomData,
}
}
}
impl<V, I> std::iter::IntoIterator for IndexVec<V, I> {
type Item = V;
type IntoIter = std::vec::IntoIter<V>;
fn into_iter(self) -> Self::IntoIter {
self.data.into_iter()
}
}
impl<V, I> FromIterator<V> for IndexVec<V, I> {
fn from_iter<T: IntoIterator<Item = V>>(iter: T) -> Self {
Vec::from_iter(iter).into()
}
}
impl<V, I> std::ops::Index<I> for IndexVec<V, I>
where
I: Index,
{
type Output = V;
fn index(&self, i: I) -> &V {
&self.data[i.get()]
}
}
impl<V, I> std::ops::IndexMut<I> for IndexVec<V, I>
where
I: Index,
{
fn index_mut(&mut self, i: I) -> &mut V {
&mut self.data[i.get()]
}
}
impl<V, I> From<Vec<V>> for IndexVec<V, I> {
fn from(data: Vec<V>) -> Self {
Self {
data,
_phantom: std::marker::PhantomData,
}
}
}
impl<V, I> IndexVec<V, I> {
pub fn len(&self) -> usize {
self.data.len()
}
}
macro_rules! define_index {
($name:ident, $doc:literal) => {
#[doc = $doc]
#[derive(
Copy, Clone, Default, Debug, Eq, PartialEq, Hash, Ord, PartialOrd,
)]
pub struct $name(usize);
impl crate::context::indexed::Index for $name {
fn new(i: usize) -> Self {
Self(i)
}
fn get(&self) -> usize {
self.0
}
}
};
}
pub(crate) use define_index;