use std::{borrow::Borrow, collections::HashMap, fmt::Debug, hash::Hash, ops::Index};
use crate::index::{Idx, vec::IndexVec};
pub struct InternMap<Key: Idx, Value: Eq + Hash + Clone> {
idx_map: IndexVec<Key, Value>,
lut_map: HashMap<Value, Key>,
}
impl<Key: Idx, Value: Eq + Hash + Clone> InternMap<Key, Value> {
pub fn new() -> InternMap<Key, Value> {
InternMap {
idx_map: IndexVec::new(),
lut_map: HashMap::new(),
}
}
pub fn push_unindexed(&mut self, val: Value) -> Key {
self.idx_map.push(val)
}
pub fn push<'a, V: ?Sized>(&mut self, val: &'a V) -> Key
where
V: Eq + Hash + ToOwned<Owned = Value>,
Value: Borrow<V>,
{
if let Some(k) = self.lut_map.get(&val).copied() {
k
} else {
let k = self.idx_map.push(val.to_owned());
self.lut_map.insert(val.to_owned(), k);
k
}
}
pub fn try_push<'a, V: ?Sized>(&self, val: &'a V) -> Option<Key>
where
V: Eq + Hash,
Value: Borrow<V>,
{
if let Some(k) = self.lut_map.get(&val).copied() {
Some(k)
} else {
None
}
}
pub fn watermark(&self) -> usize {
self.idx_map.len()
}
}
impl<Key: Idx, Value: Eq + Hash + Clone> Index<Key> for InternMap<Key, Value> {
type Output = Value;
fn index(&self, index: Key) -> &Value {
&self.idx_map[index]
}
}
impl<Key: Idx, Value: Eq + Hash + Clone> Default for InternMap<Key, Value> {
fn default() -> Self {
InternMap::new()
}
}
impl<Key: Idx, Value: Eq + Hash + Clone + Debug> Debug for InternMap<Key, Value> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_map().entries(self.idx_map.iter()).finish()
}
}