use std::{
borrow::Borrow,
collections::{HashMap, HashSet},
fmt::{self, Debug},
hash::Hash,
iter::{ExactSizeIterator, FusedIterator},
ops::Index,
};
#[allow(rustdoc::private_intra_doc_links)]
#[derive(Clone)]
pub struct DeltaHashMap<K, V> {
pub(crate) base: HashMap<K, V>,
pub(crate) delta: HashMap<K, Option<V>>,
}
impl<K, V> DeltaHashMap<K, V> {
#[must_use]
#[inline]
pub fn new() -> Self {
DeltaHashMap {
base: HashMap::new(),
delta: HashMap::new(),
}
}
#[inline]
pub fn keys(&self) -> Keys<'_, K, V> {
Keys { inner: self.iter() }
}
#[inline]
pub fn values(&self) -> Values<'_, K, V> {
Values { inner: self.iter() }
}
#[inline]
pub fn iter(&self) -> Iter<'_, K, V> {
Iter {
discard: HashSet::new(),
base: self.base.iter(),
cache: self.delta.iter(),
}
}
pub fn revert(&mut self) {
self.delta.clear()
}
#[cfg_attr(feature = "inline-more", inline)]
pub fn clear(&mut self) {
self.base.clear();
self.delta.clear();
}
#[inline]
pub unsafe fn base_ref(&self) -> &HashMap<K, V> {
&self.base
}
#[inline]
pub unsafe fn delta_ref(&self) -> &HashMap<K, Option<V>> {
&self.delta
}
#[inline]
pub unsafe fn base_ref_mut(&mut self) -> &mut HashMap<K, V> {
&mut self.base
}
#[inline]
pub unsafe fn delta_ref_mut(&mut self) -> &mut HashMap<K, Option<V>> {
&mut self.delta
}
}
impl<K, V> DeltaHashMap<K, V>
where
K: Hash + Eq,
{
pub fn len(&self) -> usize {
let mut cnt = HashSet::new();
for key in self.base.keys() {
cnt.insert(key);
}
for (key, val) in self.delta.iter() {
match val {
Some(_) => cnt.insert(key),
None => cnt.remove(key),
};
}
cnt.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
#[inline]
pub fn insert_delta(&mut self, k: K, v: V) {
self.delta.insert(k, Some(v));
}
#[inline]
pub fn get_delta<Q: ?Sized>(&self, k: &Q) -> Option<&V>
where
K: Borrow<Q>,
Q: Hash + Eq,
{
self.delta.get(k).map(Option::as_ref).flatten()
}
#[inline]
pub fn get_mut_delta<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut V>
where
K: Borrow<Q>,
Q: Hash + Eq,
{
self.delta.get_mut(k).map(Option::as_mut).flatten()
}
#[inline]
pub fn remove_delta(&mut self, k: K) {
self.delta.insert(k, None);
}
}
impl<K, V> DeltaHashMap<K, V>
where
K: Clone + Hash + Eq,
{
pub fn retain<F>(&mut self, mut f: F)
where
F: FnMut(&K, &V) -> bool,
{
let mut discard = HashSet::new();
for (key, value) in self.base.iter() {
if !f(key, value) {
discard.insert(key.clone());
}
}
for (key, state) in self.delta.iter_mut() {
match state {
Some(value) => {
if !f(key, value) {
discard.remove(key);
*state = None
}
}
None => {}
}
}
for key in discard {
self.delta.insert(key, None);
}
}
}
impl<K, V> DeltaHashMap<K, V>
where
K: Hash + Eq,
{
#[cfg_attr(feature = "inline-more", inline)]
pub fn get<Q: ?Sized>(&self, key: &Q) -> Option<&V>
where
K: Borrow<Q>,
Q: Hash + Eq,
{
match self.delta.get(key) {
Some(state) => {
state.as_ref()
}
None => {
self.base.get(key)
}
}
}
#[cfg_attr(feature = "inline-more", inline)]
pub fn get_key_value<Q: ?Sized>(&self, key: &Q) -> Option<(&K, &V)>
where
K: Borrow<Q>,
Q: Hash + Eq,
{
match self.delta.get_key_value(key) {
Some((key, state)) => {
state.as_ref().map(|state| (key, state))
}
None => {
self.base.get_key_value(key)
}
}
}
#[cfg_attr(feature = "inline-more", inline)]
pub fn contains_key<Q: ?Sized>(&self, key: &Q) -> bool
where
K: Borrow<Q>,
Q: Hash + Eq,
{
match self.delta.get(key) {
Some(state) => state.is_some(),
None => self.base.contains_key(key),
}
}
}
impl<K, V> DeltaHashMap<K, V>
where
K: Hash + Eq,
V: Clone,
{
#[cfg_attr(feature = "inline-more", inline)]
pub fn get_mut(&mut self, key: K) -> Option<&mut V> {
let state = self.base.get(&key);
self.delta
.entry(key)
.or_insert_with(|| state.cloned())
.as_mut()
}
#[cfg_attr(feature = "inline-more", inline)]
pub fn insert(&mut self, key: K, value: V) -> Option<V> {
let base_old_value = self.base.get(&key);
match self.delta.insert(key, Some(value)) {
Some(old) => {
old
}
None => {
base_old_value.cloned()
}
}
}
#[cfg_attr(feature = "inline-more", inline)]
pub fn remove(&mut self, key: K) -> Option<V> {
match self.delta.get_mut(&key) {
Some(state) => std::mem::replace(state, None),
None => {
let state = self.base.get(&key);
self.delta.insert(key, None);
state.cloned()
}
}
}
#[inline]
pub fn into_keys(self) -> IntoKeys<K, V> {
IntoKeys {
inner: self.into_iter(),
}
}
#[inline]
pub fn into_values(self) -> IntoValues<K, V> {
IntoValues {
inner: self.into_iter(),
}
}
}
impl<K, V> DeltaHashMap<K, V>
where
K: Hash + Eq,
V: Clone,
{
#[allow(rustdoc::private_intra_doc_links)]
#[cfg_attr(feature = "inline-more", inline)]
pub fn commit(&mut self) {
let cache = std::mem::replace(&mut self.delta, HashMap::new());
for (key, state) in cache.into_iter() {
match state {
Some(value) => {
self.base.insert(key, value);
}
None => {
self.base.remove(&key);
}
}
}
}
}
impl<K, V> From<HashMap<K, V>> for DeltaHashMap<K, V> {
fn from(base: HashMap<K, V>) -> Self {
Self {
base,
delta: HashMap::new(),
}
}
}
impl<K, V> Into<HashMap<K, V>> for DeltaHashMap<K, V>
where
K: Hash + Eq,
V: Clone,
{
fn into(mut self) -> HashMap<K, V> {
self.commit();
self.base
}
}
impl<K, V> DeltaHashMap<K, V>
where
K: Clone + Hash + Eq,
V: Clone,
{
#[cfg_attr(feature = "inline-more", inline)]
pub fn cocommit_key(&mut self, key: K) -> &mut Option<V> {
let base_value = self.base.get(&key);
self.delta.entry(key).or_insert_with(|| base_value.cloned())
}
#[cfg_attr(feature = "inline-more", inline)]
pub fn cocommit(&mut self) {
for (key, value) in self.base.iter() {
self.delta
.entry(key.clone())
.or_insert_with(|| Some(value.clone()));
}
}
#[inline]
pub fn values_mut(&mut self) -> ValuesMut<'_, K, V> {
ValuesMut {
inner: self.iter_mut(),
}
}
#[inline]
pub fn iter_mut(&mut self) -> IterMut<'_, K, V> {
self.cocommit();
IterMut {
base: self.delta.iter_mut(),
}
}
}
impl<K, V> PartialEq for DeltaHashMap<K, V>
where
K: Eq + Hash,
V: PartialEq,
{
#[inline]
fn eq(&self, other: &DeltaHashMap<K, V>) -> bool {
if self.len() != other.len() {
return false;
}
self.iter()
.all(|(key, value)| other.get(key).map_or(false, |v| *value == *v))
}
}
impl<K, V> Eq for DeltaHashMap<K, V>
where
K: Eq + Hash,
V: Eq,
{
}
impl<K, V> Debug for DeltaHashMap<K, V>
where
K: Debug + Hash + Eq,
V: Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_map().entries(self.iter()).finish()
}
}
impl<K, V> Default for DeltaHashMap<K, V> {
#[inline]
fn default() -> DeltaHashMap<K, V> {
DeltaHashMap::new()
}
}
impl<K, Q: ?Sized, V> Index<&Q> for DeltaHashMap<K, V>
where
K: Eq + Hash + Borrow<Q>,
Q: Eq + Hash,
{
type Output = V;
#[inline]
fn index(&self, key: &Q) -> &Self::Output {
self.get(key).expect("no entry found for key")
}
}
impl<K, V, const N: usize> From<[(K, V); N]> for DeltaHashMap<K, V>
where
K: Eq + Hash,
{
#[inline]
fn from(arr: [(K, V); N]) -> Self {
Self::from_iter(arr)
}
}
#[derive(Clone, Debug)]
pub struct Iter<'a, K: 'a, V: 'a> {
discard: HashSet<&'a K>,
base: std::collections::hash_map::Iter<'a, K, V>,
cache: std::collections::hash_map::Iter<'a, K, Option<V>>,
}
#[derive(Debug)]
pub struct IterMut<'a, K: 'a, V: 'a> {
base: std::collections::hash_map::IterMut<'a, K, Option<V>>,
}
#[derive(Debug)]
pub struct IntoIter<K, V> {
base: std::collections::hash_map::IntoIter<K, V>,
}
#[derive(Clone, Debug)]
pub struct Keys<'a, K: 'a, V: 'a> {
inner: Iter<'a, K, V>,
}
#[derive(Clone, Debug)]
pub struct Values<'a, K: 'a, V: 'a> {
inner: Iter<'a, K, V>,
}
pub struct ValuesMut<'a, K: 'a, V: 'a> {
inner: IterMut<'a, K, V>,
}
#[derive(Debug)]
pub struct IntoKeys<K, V> {
inner: IntoIter<K, V>,
}
#[derive(Debug)]
pub struct IntoValues<K, V> {
inner: IntoIter<K, V>,
}
impl<'a, K, V> IntoIterator for &'a DeltaHashMap<K, V>
where
K: Hash + Eq,
{
type Item = (&'a K, &'a V);
type IntoIter = Iter<'a, K, V>;
#[inline]
fn into_iter(self) -> Iter<'a, K, V> {
self.iter()
}
}
impl<'a, K, V> IntoIterator for &'a mut DeltaHashMap<K, V>
where
K: Clone + Hash + Eq,
V: Clone,
{
type Item = (&'a K, &'a mut V);
type IntoIter = IterMut<'a, K, V>;
#[inline]
fn into_iter(self) -> IterMut<'a, K, V> {
self.iter_mut()
}
}
impl<K, V> IntoIterator for DeltaHashMap<K, V>
where
K: Hash + Eq,
V: Clone,
{
type Item = (K, V);
type IntoIter = IntoIter<K, V>;
#[inline]
fn into_iter(mut self) -> IntoIter<K, V> {
self.commit();
IntoIter {
base: self.base.into_iter(),
}
}
}
impl<'a, K, V> Iterator for Iter<'a, K, V>
where
K: Hash + Eq,
{
type Item = (&'a K, &'a V);
fn next(&mut self) -> Option<(&'a K, &'a V)> {
while let Some((key, state)) = self.cache.next() {
self.discard.insert(key);
match state {
Some(value) => return Some((key, value)),
None => continue,
}
}
while let Some((key, value)) = self.base.next() {
if self.discard.contains(key) {
continue;
}
return Some((key, value));
}
None
}
}
impl<K, V> FusedIterator for Iter<'_, K, V> where K: Hash + Eq {}
impl<'a, K, V> Iterator for IterMut<'a, K, V> {
type Item = (&'a K, &'a mut V);
fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
loop {
match self.base.next() {
Some((key, Some(value))) => break Some((key, value)),
Some((_key, None)) => continue,
None => break None,
}
}
}
}
impl<K, V> FusedIterator for IterMut<'_, K, V> {}
impl<K, V> Iterator for IntoIter<K, V> {
type Item = (K, V);
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.base.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.base.size_hint()
}
#[inline]
fn count(self) -> usize {
self.base.len()
}
#[inline]
fn fold<B, F>(self, init: B, f: F) -> B
where
Self: Sized,
F: FnMut(B, Self::Item) -> B,
{
self.base.fold(init, f)
}
}
impl<K, V> ExactSizeIterator for IntoIter<K, V> {
#[inline]
fn len(&self) -> usize {
self.base.len()
}
}
impl<K, V> FusedIterator for IntoIter<K, V> {}
impl<'a, K, V> Iterator for Keys<'a, K, V>
where
K: Hash + Eq,
{
type Item = &'a K;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.inner.next().map(|(k, _)| k)
}
}
impl<K, V> FusedIterator for Keys<'_, K, V> where K: Hash + Eq {}
impl<'a, K, V> Iterator for Values<'a, K, V>
where
K: Hash + Eq,
{
type Item = &'a V;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.inner.next().map(|(_, v)| v)
}
}
impl<K, V> FusedIterator for Values<'_, K, V> where K: Hash + Eq {}
impl<'a, K, V> Iterator for ValuesMut<'a, K, V>
where
K: Hash + Eq,
{
type Item = &'a mut V;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.inner.next().map(|(_, v)| v)
}
}
impl<K, V> FusedIterator for ValuesMut<'_, K, V> where K: Hash + Eq {}
impl<K, V> Iterator for IntoKeys<K, V> {
type Item = K;
#[inline]
fn next(&mut self) -> Option<K> {
self.inner.next().map(|(k, _)| k)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
#[inline]
fn count(self) -> usize {
self.inner.len()
}
#[inline]
fn fold<B, F>(self, init: B, mut f: F) -> B
where
Self: Sized,
F: FnMut(B, Self::Item) -> B,
{
self.inner.fold(init, |acc, (k, _)| f(acc, k))
}
}
impl<K, V> ExactSizeIterator for IntoKeys<K, V> {
#[inline]
fn len(&self) -> usize {
self.inner.len()
}
}
impl<K, V> FusedIterator for IntoKeys<K, V> {}
impl<K, V> Iterator for IntoValues<K, V> {
type Item = V;
#[inline]
fn next(&mut self) -> Option<V> {
self.inner.next().map(|(_, v)| v)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
#[inline]
fn count(self) -> usize {
self.inner.len()
}
#[inline]
fn fold<B, F>(self, init: B, mut f: F) -> B
where
Self: Sized,
F: FnMut(B, Self::Item) -> B,
{
self.inner.fold(init, |acc, (_, v)| f(acc, v))
}
}
impl<K, V> ExactSizeIterator for IntoValues<K, V> {
#[inline]
fn len(&self) -> usize {
self.inner.len()
}
}
impl<K, V> FusedIterator for IntoValues<K, V> {}
impl<K, V> FromIterator<(K, V)> for DeltaHashMap<K, V>
where
K: Hash + Eq,
{
fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> DeltaHashMap<K, V> {
let mut base = HashMap::new();
let cache = HashMap::new();
base.extend(iter);
DeltaHashMap { base, delta: cache }
}
}
impl<K, V> Extend<(K, V)> for DeltaHashMap<K, V>
where
K: Eq + Hash,
{
#[inline]
fn extend<T: IntoIterator<Item = (K, V)>>(&mut self, iter: T) {
self.delta
.extend(iter.into_iter().map(|(k, v)| (k, Some(v))))
}
}