use crate::prelude::*;
use alloc::slice::Iter;
use core::hash::Hash;
use core::ops::{Bound, RangeBounds};
#[derive(Clone, Debug, Eq)]
pub struct IndexedMap<K: Hash + Ord, V> {
map: HashMap<K, V>,
keys: Vec<K>,
}
impl<K: Clone + Hash + Ord, V> IndexedMap<K, V> {
pub fn new() -> Self {
Self { map: new_hash_map(), keys: Vec::new() }
}
pub fn with_capacity(capacity: usize) -> Self {
Self { map: hash_map_with_capacity(capacity), keys: Vec::with_capacity(capacity) }
}
#[inline(always)]
pub fn get(&self, key: &K) -> Option<&V> {
self.map.get(key)
}
pub fn get_mut(&mut self, key: &K) -> Option<&mut V> {
self.map.get_mut(key)
}
pub fn get_key_value(&self, key: &K) -> Option<(&K, &V)> {
self.map.get_key_value(key)
}
#[inline]
pub fn contains_key(&self, key: &K) -> bool {
self.map.contains_key(key)
}
pub fn remove(&mut self, key: &K) -> Option<V> {
let ret = self.map.remove(key);
if let Some(_) = ret {
let idx =
self.keys.iter().position(|k| k == key).expect("map and keys must be consistent");
self.keys.remove(idx);
}
ret
}
pub fn remove_fetch_bulk(&mut self, keys: &HashSet<K>) -> Vec<(K, V)> {
let mut res = Vec::with_capacity(keys.len());
for key in keys.iter() {
if let Some((k, v)) = self.map.remove_entry(key) {
res.push((k, v));
}
}
self.keys.retain(|k| !keys.contains(k));
res
}
pub fn remove_bulk(&mut self, keys: &HashSet<K>) {
for key in keys.iter() {
self.map.remove(key);
}
self.keys.retain(|k| !keys.contains(k));
}
pub fn insert(&mut self, key: K, value: V) -> Option<V> {
let ret = self.map.insert(key.clone(), value);
if ret.is_none() {
self.keys.push(key);
}
ret
}
pub fn entry(&mut self, key: K) -> Entry<'_, K, V> {
match self.map.entry(key.clone()) {
hash_map::Entry::Vacant(entry) => {
Entry::Vacant(VacantEntry { underlying_entry: entry, key, keys: &mut self.keys })
},
hash_map::Entry::Occupied(entry) => {
Entry::Occupied(OccupiedEntry { underlying_entry: entry, keys: &mut self.keys })
},
}
}
pub fn unordered_keys(&self) -> impl Iterator<Item = &K> {
self.map.keys()
}
pub fn unordered_iter(&self) -> impl Iterator<Item = (&K, &V)> {
self.map.iter()
}
pub fn unordered_iter_mut(&mut self) -> impl Iterator<Item = (&K, &mut V)> {
self.map.iter_mut()
}
pub fn range<R: RangeBounds<K>>(&mut self, range: R) -> Range<'_, K, V> {
self.keys.sort_unstable();
let start = match range.start_bound() {
Bound::Unbounded => 0,
Bound::Included(key) => self.keys.binary_search(key).unwrap_or_else(|index| index),
Bound::Excluded(key) => {
self.keys.binary_search(key).map(|index| index + 1).unwrap_or_else(|index| index)
},
};
let end = match range.end_bound() {
Bound::Unbounded => self.keys.len(),
Bound::Included(key) => {
self.keys.binary_search(key).map(|index| index + 1).unwrap_or_else(|index| index)
},
Bound::Excluded(key) => self.keys.binary_search(key).unwrap_or_else(|index| index),
};
Range { inner_range: self.keys[start..end].iter(), map: &self.map }
}
pub fn len(&self) -> usize {
self.map.len()
}
pub fn is_empty(&self) -> bool {
self.map.is_empty()
}
}
impl<K: Hash + Ord + PartialEq, V: PartialEq> PartialEq for IndexedMap<K, V> {
fn eq(&self, other: &Self) -> bool {
self.map == other.map
}
}
pub struct Range<'a, K: Hash + Ord, V> {
inner_range: Iter<'a, K>,
map: &'a HashMap<K, V>,
}
impl<'a, K: Hash + Ord, V: 'a> Iterator for Range<'a, K, V> {
type Item = (&'a K, &'a V);
fn next(&mut self) -> Option<(&'a K, &'a V)> {
self.inner_range
.next()
.map(|k| (k, self.map.get(k).expect("map and keys must be consistent")))
}
}
pub struct VacantEntry<'a, K: Hash + Ord, V> {
underlying_entry: VacantHashMapEntry<'a, K, V>,
key: K,
keys: &'a mut Vec<K>,
}
pub struct OccupiedEntry<'a, K: Hash + Ord, V> {
underlying_entry: OccupiedHashMapEntry<'a, K, V>,
keys: &'a mut Vec<K>,
}
pub enum Entry<'a, K: Hash + Ord, V> {
Vacant(VacantEntry<'a, K, V>),
Occupied(OccupiedEntry<'a, K, V>),
}
impl<'a, K: Hash + Ord, V> VacantEntry<'a, K, V> {
pub fn insert(self, value: V) -> &'a mut V {
self.keys.push(self.key);
self.underlying_entry.insert(value)
}
}
impl<'a, K: Hash + Ord, V> OccupiedEntry<'a, K, V> {
pub fn remove_entry(self) -> (K, V) {
let res = self.underlying_entry.remove_entry();
let idx =
self.keys.iter().position(|k| k == &res.0).expect("map and keys must be consistent");
self.keys.remove(idx);
res
}
pub fn key(&self) -> &K {
self.underlying_entry.key()
}
pub fn get(&self) -> &V {
self.underlying_entry.get()
}
pub fn get_mut(&mut self) -> &mut V {
self.underlying_entry.get_mut()
}
pub fn into_mut(self) -> &'a mut V {
self.underlying_entry.into_mut()
}
}