use std::{
collections::hash_map,
ops::{Index, IndexMut},
};
use fxhash::FxHashMap;
use index_vec::{Idx, IndexVec};
use crate::{
pointer::{ArcFamily, PointerFamily, RcFamily, RefFamily},
IndexedDomain, IndexedValue, ToIndex,
};
pub struct SparseIndexMap<'a, K: IndexedValue + 'a, V, P: PointerFamily<'a>> {
map: FxHashMap<K::Index, V>,
domain: P::Pointer<IndexedDomain<K>>,
}
pub type SparseRcIndexMap<'a, K, V> = SparseIndexMap<'a, K, V, RcFamily>;
pub type SparseArcIndexMap<'a, K, V> = SparseIndexMap<'a, K, V, ArcFamily>;
pub type SparseRefIndexMap<'a, K, V> = SparseIndexMap<'a, K, V, RefFamily<'a>>;
impl<'a, K, V, P> SparseIndexMap<'a, K, V, P>
where
K: IndexedValue + 'a,
P: PointerFamily<'a>,
{
pub fn new(domain: &P::Pointer<IndexedDomain<K>>) -> Self {
SparseIndexMap {
map: FxHashMap::default(),
domain: domain.clone(),
}
}
#[inline]
pub fn get<M>(&self, key: impl ToIndex<K, M>) -> Option<&V> {
let idx = key.to_index(&self.domain);
self.map.get(&idx)
}
#[inline]
pub fn get_mut<M>(&mut self, key: impl ToIndex<K, M>) -> Option<&mut V> {
let idx = key.to_index(&self.domain);
self.map.get_mut(&idx)
}
#[inline]
pub unsafe fn get_unchecked<M>(&self, key: impl ToIndex<K, M>) -> &V {
let idx = key.to_index(&self.domain);
self.map.get(&idx).unwrap_unchecked()
}
#[inline]
pub unsafe fn get_unchecked_mut<M>(&mut self, key: impl ToIndex<K, M>) -> &mut V {
let idx = key.to_index(&self.domain);
self.map.get_mut(&idx).unwrap_unchecked()
}
#[inline]
pub fn insert<M>(&mut self, key: impl ToIndex<K, M>, value: V) {
let idx = key.to_index(&self.domain);
self.map.insert(idx, value);
}
#[inline]
pub fn values(&self) -> impl Iterator<Item = &V> + '_ {
self.map.values()
}
#[inline]
pub fn entry<M>(&mut self, key: impl ToIndex<K, M>) -> hash_map::Entry<'_, K::Index, V> {
let idx = key.to_index(&self.domain);
self.map.entry(idx)
}
}
impl<'a, K, V, P> Index<K::Index> for SparseIndexMap<'a, K, V, P>
where
K: IndexedValue + 'a,
P: PointerFamily<'a>,
{
type Output = V;
fn index(&self, index: K::Index) -> &Self::Output {
self.get(index).unwrap()
}
}
impl<'a, K, V, P> IndexMut<K::Index> for SparseIndexMap<'a, K, V, P>
where
K: IndexedValue + 'a,
P: PointerFamily<'a>,
{
fn index_mut(&mut self, index: K::Index) -> &mut Self::Output {
self.get_mut(index).unwrap()
}
}
pub struct DenseIndexMap<'a, K: IndexedValue + 'a, V, P: PointerFamily<'a>> {
map: IndexVec<K::Index, V>,
domain: P::Pointer<IndexedDomain<K>>,
}
pub type DenseRcIndexMap<'a, K, V> = DenseIndexMap<'a, K, V, RcFamily>;
pub type DenseArcIndexMap<'a, K, V> = DenseIndexMap<'a, K, V, ArcFamily>;
pub type DenseRefIndexMap<'a, K, V> = DenseIndexMap<'a, K, V, RefFamily<'a>>;
impl<'a, K, V, P> DenseIndexMap<'a, K, V, P>
where
K: IndexedValue + 'a,
P: PointerFamily<'a>,
{
#[inline]
pub fn new(domain: &P::Pointer<IndexedDomain<K>>, mk_elem: impl FnMut(K::Index) -> V) -> Self {
DenseIndexMap {
map: IndexVec::from_iter(domain.indices().map(mk_elem)),
domain: domain.clone(),
}
}
#[inline]
pub fn get<M>(&self, idx: impl ToIndex<K, M>) -> Option<&V> {
let idx = idx.to_index(&self.domain);
self.map.get(idx)
}
#[inline]
pub fn get_mut<M>(&mut self, idx: impl ToIndex<K, M>) -> Option<&mut V> {
let idx = idx.to_index(&self.domain);
self.map.get_mut(idx)
}
#[inline]
pub unsafe fn get_unchecked<M>(&self, idx: impl ToIndex<K, M>) -> &V {
let idx = idx.to_index(&self.domain);
self.map.raw.get_unchecked(idx.index())
}
#[inline]
pub unsafe fn get_unchecked_mut<M>(&mut self, idx: impl ToIndex<K, M>) -> &mut V {
let idx = idx.to_index(&self.domain);
self.map.raw.get_unchecked_mut(idx.index())
}
#[inline]
pub fn insert<M>(&mut self, idx: impl ToIndex<K, M>, value: V) {
let idx = idx.to_index(&self.domain);
self.map[idx] = value;
}
#[inline]
pub fn values(&self) -> impl Iterator<Item = &V> + '_ {
self.map.iter()
}
}
impl<'a, K, V, P> Index<K::Index> for DenseIndexMap<'a, K, V, P>
where
K: IndexedValue + 'a,
P: PointerFamily<'a>,
{
type Output = V;
#[inline]
fn index(&self, index: K::Index) -> &Self::Output {
self.get(index).unwrap()
}
}
impl<'a, K, V, P> IndexMut<K::Index> for DenseIndexMap<'a, K, V, P>
where
K: IndexedValue + 'a,
P: PointerFamily<'a>,
{
#[inline]
fn index_mut(&mut self, index: K::Index) -> &mut Self::Output {
self.get_mut(index).unwrap()
}
}