use std::{
collections::hash_map,
ops::{Index, IndexMut},
};
use rustc_hash::FxHashMap;
use crate::{
FromIndexicalIterator, IndexedDomain, IndexedValue, ToIndex,
pointer::{ArcFamily, PointerFamily, RcFamily, RefFamily},
vec::IndexVec,
};
pub struct SparseIndexMap<'a, K: IndexedValue + 'a, V, P: PointerFamily<'a>> {
map: FxHashMap<K::Index, V>,
domain: P::Pointer<IndexedDomain<K>>,
}
pub type SparseRcIndexMap<K, V> = SparseIndexMap<'static, K, V, RcFamily>;
pub type SparseArcIndexMap<K, V> = SparseIndexMap<'static, 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(),
}
}
pub fn get<M>(&self, key: impl ToIndex<K, M>) -> Option<&V> {
let idx = key.to_index(&self.domain);
self.map.get(&idx)
}
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)
}
pub unsafe fn get_unchecked<M>(&self, key: impl ToIndex<K, M>) -> &V {
let idx = key.to_index(&self.domain);
unsafe { self.map.get(&idx).unwrap_unchecked() }
}
pub unsafe fn get_unchecked_mut<M>(&mut self, key: impl ToIndex<K, M>) -> &mut V {
let idx = key.to_index(&self.domain);
unsafe { self.map.get_mut(&idx).unwrap_unchecked() }
}
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);
}
pub fn values(&self) -> impl ExactSizeIterator<Item = &V> {
self.map.values()
}
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)
}
pub fn len(&self) -> usize {
self.map.len()
}
pub fn is_empty(&self) -> bool {
self.map.is_empty()
}
pub fn iter(&self) -> hash_map::Iter<'_, K::Index, V> {
self.map.iter()
}
}
impl<'a, K, V, P> PartialEq for SparseIndexMap<'a, K, V, P>
where
K: IndexedValue + 'a,
P: PointerFamily<'a>,
V: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
self.map == other.map
}
}
impl<'a, K, V, P> Eq for SparseIndexMap<'a, K, V, P>
where
K: IndexedValue + 'a,
P: PointerFamily<'a>,
V: Eq,
{
}
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()
}
}
impl<'a, K, V, P, M, U> FromIndexicalIterator<'a, K, P, M, (U, V)> for SparseIndexMap<'a, K, V, P>
where
K: IndexedValue + 'a,
P: PointerFamily<'a>,
U: ToIndex<K, M>,
{
fn from_indexical_iter(
iter: impl Iterator<Item = (U, V)>,
domain: &P::Pointer<IndexedDomain<K>>,
) -> Self {
let map = iter
.map(|(u, v)| (u.to_index(domain), v))
.collect::<FxHashMap<_, _>>();
SparseIndexMap {
map,
domain: domain.clone(),
}
}
}
impl<'a, 'b, K, V, P> IntoIterator for &'b SparseIndexMap<'a, K, V, P>
where
K: IndexedValue + 'a + 'b,
V: 'b,
P: PointerFamily<'a>,
{
type Item = (&'b K::Index, &'b V);
type IntoIter = hash_map::Iter<'b, K::Index, V>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
pub struct DenseIndexMap<'a, K: IndexedValue + 'a, V, P: PointerFamily<'a>>(
IndexVec<'a, K, Option<V>, P>,
);
pub type DenseRcIndexMap<K, V> = DenseIndexMap<'static, K, V, RcFamily>;
pub type DenseArcIndexMap<K, V> = DenseIndexMap<'static, 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>,
{
pub fn new(domain: &P::Pointer<IndexedDomain<K>>) -> Self {
Self(IndexVec::from_fn(|_| None, domain))
}
pub fn get<M>(&self, idx: impl ToIndex<K, M>) -> Option<&V> {
self.0.get(idx).as_ref()
}
pub fn get_mut<M>(&mut self, idx: impl ToIndex<K, M>) -> Option<&mut V> {
self.0.get_mut(idx).as_mut()
}
pub unsafe fn get_unchecked<M>(&self, idx: impl ToIndex<K, M>) -> &V {
unsafe { self.get(idx).unwrap_unchecked() }
}
pub unsafe fn get_unchecked_mut<M>(&mut self, idx: impl ToIndex<K, M>) -> &mut V {
unsafe { self.get_mut(idx).unwrap_unchecked() }
}
pub fn insert<M>(&mut self, idx: impl ToIndex<K, M>, value: V) {
let idx = idx.to_index(&self.0.domain);
self.0[idx] = Some(value);
}
pub fn values(&self) -> impl Iterator<Item = &V> {
self.0.iter().filter_map(Option::as_ref)
}
}
impl<'a, K, V, P> Index<K::Index> for DenseIndexMap<'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 DenseIndexMap<'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()
}
}
impl<'a, K, V, P, M, U> FromIndexicalIterator<'a, K, P, M, (U, V)> for DenseIndexMap<'a, K, V, P>
where
K: IndexedValue + 'a,
P: PointerFamily<'a>,
U: ToIndex<K, M>,
{
fn from_indexical_iter(
iter: impl Iterator<Item = (U, V)>,
domain: &P::Pointer<IndexedDomain<K>>,
) -> Self {
let mut map = DenseIndexMap::new(domain);
for (u, v) in iter {
map.insert(u, v);
}
map
}
}