use super::hash::{Hash, HashedKey, Hasher};
use super::mutable::HamtMut;
pub use super::mutable::{InsertError, RemoveError, ReplaceError, UpdateError};
use super::node::{lookup_one, size_rec, Entry, LookupRet, Node, NodeIter};
use std::iter::FromIterator;
use std::marker::PhantomData;
use std::mem::swap;
use std::slice;
pub struct Hamt<K, V, H> {
pub(crate) root: Node<K, V>,
pub(crate) hasher: PhantomData<H>,
}
impl<H, K, V> Clone for Hamt<K, V, H> {
fn clone(&self) -> Self {
Hamt {
root: self.root.clone(),
hasher: self.hasher.clone(),
}
}
}
pub struct HamtIter<'a, K, V> {
stack: Vec<NodeIter<'a, K, V>>,
content: Option<slice::Iter<'a, (K, V)>>,
}
impl<H: Hasher + Default, K: Eq + Hash, V> Default for Hamt<K, V, H> {
fn default() -> Self {
Self::new()
}
}
impl<H: Hasher + Default, K: PartialEq + Eq + Hash, V> Hamt<K, V, H> {
pub fn new() -> Self {
Hamt {
root: Node::new(),
hasher: PhantomData,
}
}
pub fn is_empty(&self) -> bool {
self.root.is_empty()
}
pub fn size(&self) -> usize {
size_rec(&self.root)
}
pub fn thaw(&self) -> HamtMut<K, V, H> {
self.into()
}
pub fn mutate_freeze<E, F>(&self, f: F) -> Result<Self, E>
where
F: FnOnce(&mut HamtMut<K, V, H>) -> Result<(), E>,
{
let mut x = self.thaw();
f(&mut x)?;
Ok(x.freeze())
}
pub fn mutate_freeze_ret<E, F, R>(&self, f: F) -> Result<(Self, R), E>
where
F: FnOnce(&mut HamtMut<K, V, H>) -> Result<R, E>,
{
let mut x = self.thaw();
let r = f(&mut x)?;
Ok((x.freeze(), r))
}
}
impl<H: Hasher + Default, K: Hash + Eq, V> Hamt<K, V, H> {
pub fn lookup(&self, k: &K) -> Option<&V> {
let h = HashedKey::compute(self.hasher, &k);
let mut n = &self.root;
let mut lvl = 0;
loop {
match lookup_one(n, &h, lvl, k) {
LookupRet::NotFound => return None,
LookupRet::Found(v) => return Some(v),
LookupRet::ContinueIn(subnode) => {
lvl += 1;
n = &subnode;
}
}
}
}
pub fn contains_key(&self, k: &K) -> bool {
self.lookup(k).map_or_else(|| false, |_| true)
}
pub fn iter(&self) -> HamtIter<K, V> {
HamtIter {
stack: vec![self.root.iter()],
content: None,
}
}
}
impl<'a, K, V> Iterator for HamtIter<'a, K, V> {
type Item = (&'a K, &'a V);
fn next(&mut self) -> Option<Self::Item> {
loop {
let mut x = None;
swap(&mut self.content, &mut x);
match x {
Some(mut iter) => match iter.next() {
None => self.content = None,
Some(ref o) => {
self.content = Some(iter);
return Some((&o.0, &o.1));
}
},
None => match self.stack.last_mut() {
None => return None,
Some(last) => match last.next() {
None => {
self.stack.pop();
}
Some(next) => match next.as_ref() {
Entry::SubNode(ref sub) => self.stack.push(sub.iter()),
Entry::Leaf(_, ref k, ref v) => return Some((&k, &v)),
Entry::LeafMany(_, ref col) => self.content = Some(col.iter()),
},
},
},
}
}
}
}
impl<H: Default + Hasher, K: Eq + Hash + Clone, V: Clone> FromIterator<(K, V)> for Hamt<K, V, H> {
fn from_iter<I: IntoIterator<Item = (K, V)>>(iter: I) -> Self {
HamtMut::from_iter(iter).freeze()
}
}
impl<H: Default + Hasher, K: Eq + Hash, V: PartialEq> PartialEq for Hamt<K, V, H> {
fn eq(&self, other: &Self) -> bool {
if self.is_empty() && other.is_empty() {
return true;
}
if self.is_empty() != other.is_empty() {
return false;
}
if self.root.bitmap != other.root.bitmap {
return false;
}
for (k, v) in self.iter() {
if let Some(v2) = other.lookup(k) {
if v != v2 {
return false;
}
} else {
return false;
}
}
true
}
}
impl<H: Default + Hasher, K: Eq + Hash, V: Eq> Eq for Hamt<K, V, H> {}