use std::hash::Hash;
use crate::tree;
use crate::tree::{NodeId, Tree};
use imbl::HashMap;
pub use children::*;
pub use error::*;
pub use location::*;
pub use node_mut::*;
pub use node_ref::*;
mod children;
mod error;
mod location;
mod node_mut;
mod node_ref;
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Entry<Key: Hash + Eq + Clone, T: Clone> {
value: T,
key: Key,
}
impl<Key: Hash + Eq + Clone, T: Clone> Entry<Key, T> {
pub(crate) fn new(key: Key, value: T) -> Self {
Self { value, key }
}
#[must_use]
pub fn value(&self) -> &T {
&self.value
}
#[must_use]
pub fn value_mut(&mut self) -> &mut T {
&mut self.value
}
#[must_use]
pub fn key(&self) -> &Key {
&self.key
}
}
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct MapTree<Key: Hash + Eq + Clone, T: Clone> {
tree: Tree<Entry<Key, T>>,
map: HashMap<Key, NodeId>,
}
#[derive(Debug, Clone, Copy)]
pub enum InsertError<Key> {
KeyAlreadyExists(Key),
NoSuchNode(Key),
RootCannotHaveSiblings,
}
impl<Key: Hash + Eq + Clone, T: Clone> MapTree<Key, T> {
#[must_use]
pub fn new_with_root(key: Key, value: T) -> Self {
let tree = Tree::new_with_root(Entry::new(key.clone(), value));
Self {
map: HashMap::unit(key, tree.root().id()),
tree,
}
}
pub fn insert(
&mut self,
key: Key,
value: T,
location: Location<Key>,
) -> Result<(), InsertError<Key>> {
if self.map.contains_key(&key) {
return Err(InsertError::KeyAlreadyExists(key));
}
let mapped_location = location.into_tree_location(|key| {
self.map
.get(&key)
.copied()
.ok_or(InsertError::NoSuchNode(key))
})?;
let new_id = self
.tree
.insert(Entry::new(key.clone(), value), mapped_location)
.map_err(|error| match error {
tree::InvalidLocation::NoSuchNode(_) => {
unreachable!()
}
tree::InvalidLocation::RootCannotHaveSiblings => {
InsertError::RootCannotHaveSiblings
}
})?;
self.map.insert(key, new_id);
Ok(())
}
#[must_use]
pub fn root(&self) -> NodeRef<Key, T> {
NodeRef::new(self.tree.root())
}
#[must_use]
pub fn root_mut(&mut self) -> NodeMut<Key, T> {
NodeMut::new(self.tree.root_mut(), &mut self.map)
}
#[must_use]
pub fn get(&self, key: &Key) -> Option<NodeRef<Key, T>> {
let id = self.map.get(key)?;
let inner = self.tree.get(*id)?;
Some(NodeRef::new(inner))
}
#[must_use]
pub fn get_mut(&mut self, key: &Key) -> Option<NodeMut<Key, T>> {
let id = self.map.get(key)?;
let inner = self.tree.get_mut(*id)?;
Some(NodeMut::new(inner, &mut self.map))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn new_with_root() {
let tree = MapTree::new_with_root("hello", 42);
assert_eq!(tree.root().key(), &"hello");
assert_eq!(tree.root().data(), &42);
}
}