use std::borrow::Borrow;
use std::collections::{BTreeMap, HashMap, VecDeque};
use std::hash::{BuildHasher, Hash, RandomState};
use std::ops::Index;
#[derive(Debug)]
pub struct ContextManager<K, V, S = RandomState> {
inner: VecDeque<HashMap<K, V, S>>
}
impl<K, V> ContextManager<K, V, RandomState>
where K: Hash + Eq {
pub fn with_empty() -> Self { Self { inner: VecDeque::from([HashMap::new()]) } }
pub fn new() -> Self { Self::default() }
pub fn with_capacity(capacity: usize) -> Self {
Self { inner: VecDeque::with_capacity(capacity) }
}
pub fn collapse(mut self) -> HashMap<K, V> {
if self.inner.len() == 1 {
self.inner.pop_front().unwrap()
} else {
let mut map = HashMap::new();
loop {
if self.inner.is_empty() { break; }
let next = self.inner.pop_back().unwrap();
map.extend(next);
}
map
}
}
pub fn push_empty(&mut self) { self.inner.push_front(HashMap::new()) }
}
impl<K, V, S> ContextManager<K, V, S> {
pub fn is_empty(&self) -> bool { self.inner.is_empty() }
pub fn len(&self) -> usize { self.inner.len() }
pub fn pop(&mut self) -> Option<HashMap<K, V, S>> { self.inner.pop_front() }
pub fn push(&mut self, context: HashMap<K, V, S>) { self.inner.push_front(context) ; }
}
impl<K, V, S> ContextManager<K, V, S>
where K: Hash + Eq, S: BuildHasher {
pub fn collapse_into(mut self, src: &mut HashMap<K, V, S>) {
loop {
if self.inner.is_empty() { break; }
let next = self.inner.pop_back().unwrap();
src.extend(next);
}
}
pub fn contains_key<Q>(&self, key: &Q) -> bool
where K: Borrow<Q>, Q: ?Sized + Hash + Eq {
for map in &self.inner {
if map.contains_key(key) {
return true;
}
}
false
}
pub fn contains_local_key<Q>(&self, key: &Q) -> bool
where K: Borrow<Q>, Q: ?Sized + Hash + Eq {
self.inner.len() > 0 && self.inner[0].contains_key(key)
}
pub fn get<Q>(&self, key: &Q) -> Option<&V>
where K: Borrow<Q>, Q: ?Sized + Hash + Eq {
self.inner.iter().find_map(|ctx| ctx.get(key))
}
pub fn get_all<Q>(&self, key: &Q) -> Vec<&V>
where K: Borrow<Q>, Q: ?Sized + Hash + Eq {
self.inner.iter().filter_map(|map| map.get(key)).collect()
}
pub fn get_from<Q>(&self, index: usize, key: &Q) -> Option<&V>
where K: Borrow<Q>, Q: ?Sized + Hash + Eq {
self.inner.range(index..).find_map(|ctx| ctx.get(key))
}
pub fn get_local<Q>(&self, key: &Q) -> Option<&V>
where K: Borrow<Q>, Q: ?Sized + Hash + Eq {
if self.inner.is_empty() { None } else { self.inner[0].get(key) }
}
pub fn get_local_mut<Q>(&mut self, key: &Q) -> Option<&mut V>
where K: Borrow<Q>, Q: ?Sized + Hash + Eq {
if self.inner.is_empty() { None } else { self.inner[0].get_mut(key) }
}
pub fn get_mut<Q>(&mut self, key: &Q) -> Option<&mut V>
where K: Borrow<Q>, Q: ?Sized + Hash + Eq {
self.inner.iter_mut().find_map(|ctx| ctx.get_mut(key))
}
pub fn get_mut_from<Q>(&mut self, index: usize, key: &Q) -> Option<&mut V>
where K: Borrow<Q>, Q: ?Sized + Hash + Eq {
self.inner.range_mut(index..).find_map(|ctx| ctx.get_mut(key))
}
pub fn insert(&mut self, key: K, value: V) -> Option<V> {
if self.inner.is_empty() { None } else { self.inner[0].insert(key, value) }
}
pub fn remove<Q>(&mut self, key: &Q) -> Option<V>
where K: Borrow<Q>, Q: ?Sized + Hash + Eq {
if self.inner.is_empty() { None } else { self.inner[0].remove(key) }
}
pub fn remove_all<Q>(&mut self, key: &Q) -> Vec<V>
where K: Borrow<Q>, Q: ?Sized + Hash + Eq {
self.inner.iter_mut().filter_map(|ctx| ctx.remove(key)).collect()
}
}
impl<K, V, S> ContextManager<K, V, S>
where K: Hash + Eq + Clone, V: Clone, S: BuildHasher + Clone {
pub fn fork(&self) -> Option<ContextManager<K, V, S>> {
if self.inner.is_empty() { None } else { Some(ContextManager::from(self.inner[0].clone())) }
}
pub fn fork_from(&self, index: usize) -> Option<ContextManager<K, V, S>> {
if index >= self.inner.len() {
None
} else {
Some(ContextManager {
inner: self.inner
.range(0..(index + 1)).map(|ctx| ctx.clone())
.collect()
})
}
}
pub fn push_local(&mut self) {
if self.inner.len() > 0 {
let context = self.inner[0].clone();
self.inner.push_front(context);
}
}
pub fn push_with_local(&mut self, context: HashMap<K, V, S>) {
if self.inner.is_empty() {
self.inner.push_back(context)
} else {
let mut plocal = self.inner[0].clone();
plocal.extend(context);
self.inner.push_front(plocal);
}
}
}
impl<K, V, S> ContextManager<K, V, S>
where K: Ord {
pub fn collapse_ordered(mut self) -> BTreeMap<K, V> {
let mut map = BTreeMap::new();
loop {
if self.inner.is_empty() { break; }
let next = self.inner.pop_back().unwrap();
map.extend(next);
}
map
}
pub fn collapse_into_ordered(mut self, src: &mut BTreeMap<K, V>) {
loop {
if self.inner.is_empty() { break; }
let next = self.inner.pop_back().unwrap();
src.extend(next);
}
}
}
impl<K, V, S> Clone for ContextManager<K, V, S>
where K: Clone, V: Clone, S: Clone{
fn clone(&self) -> Self { Self { inner: self.inner.clone() } }
}
impl<K, V, S> Default for ContextManager<K, V, S> {
fn default() -> Self { Self { inner: VecDeque::new() } }
}
impl <K, V, S> Extend<(K, V)> for ContextManager<K, V, S>
where K: Hash + Eq, S: BuildHasher + Default {
fn extend<I: IntoIterator<Item=(K, V)>>(&mut self, iter: I) {
if self.inner.is_empty() {
self.inner.push_front(HashMap::from_iter(iter));
} else {
self.inner[0].extend(iter);
}
}
}
impl<K, V, S> From<HashMap<K, V, S>> for ContextManager<K, V, S>
where K: Hash + Eq, S: BuildHasher {
fn from(initial: HashMap<K, V, S>) -> Self {
Self { inner: VecDeque::from([initial]) }
}
}
impl<K, V, const N: usize> From<[(K, V); N]> for ContextManager<K, V, RandomState>
where K: Hash + Eq {
fn from(initial: [(K, V); N]) -> Self {
Self { inner: VecDeque::from([HashMap::from(initial)]) }
}
}
impl<K, V, S, const N: usize> From<[HashMap<K, V, S>; N]> for ContextManager<K, V, S>
where K: Hash + Eq, S: BuildHasher {
fn from(initial: [HashMap<K, V, S>; N]) -> Self {
Self { inner: VecDeque::from(initial) }
}
}
impl<K, V, S> FromIterator<(K, V)> for ContextManager<K, V, S>
where K: Hash + Eq, S: BuildHasher + Default {
fn from_iter<I: IntoIterator<Item=(K, V)>>(initial: I) -> Self {
Self { inner: VecDeque::from([HashMap::from_iter(initial)]) }
}
}
impl<K, V, S> FromIterator<HashMap<K, V, S>> for ContextManager<K, V, S>
where K: Hash + Eq, S: BuildHasher {
fn from_iter<I: IntoIterator<Item=HashMap<K, V, S>>>(iter: I) -> Self {
Self { inner: VecDeque::from_iter(iter) }
}
}
impl<K, Q, V, S> Index<&Q> for ContextManager<K, V, S>
where K: Hash + Eq + Borrow<Q>, Q: ?Sized + Hash + Eq, S: BuildHasher {
type Output = V;
fn index(&self, key: &Q) -> &V {
self.inner.iter().find_map(|ctx| ctx.get(key)).expect("key not found")
}
}
impl<K, V, S> PartialEq for ContextManager<K, V, S>
where K: Hash + Eq, V: PartialEq, S: BuildHasher {
fn eq(&self, other: &ContextManager<K, V, S>) -> bool {
self.inner.eq(&other.inner)
}
}
impl<K, V, S> Eq for ContextManager<K, V, S>
where K: Hash + Eq, V: Eq, S: BuildHasher {}