use crate::map_tree::error::MoveError;
use crate::map_tree::location::Location;
use crate::map_tree::Entry;
use crate::tree;
use crate::tree::{CannotRemoveRoot, Children, NodeId};
use imbl::HashMap;
use std::hash::Hash;
#[derive(Debug)]
pub struct NodeMut<'a, Key: Hash + Eq + Clone, T: Clone> {
inner: tree::NodeMut<'a, Entry<Key, T>>,
map: &'a mut HashMap<Key, NodeId>,
}
impl<'a, Key: Hash + Eq + Clone, T: Clone> NodeMut<'a, Key, T> {
pub(crate) fn new(
inner: tree::NodeMut<'a, Entry<Key, T>>,
map: &'a mut HashMap<Key, NodeId>,
) -> Self {
Self { inner, map }
}
}
impl<'a, Key: Hash + Eq + Clone, T: Clone> NodeMut<'a, Key, T> {
#[must_use]
pub fn data(&self) -> &T {
self.inner.data().value()
}
#[must_use]
pub fn key(&self) -> &Key {
self.inner.data().key()
}
pub fn children(&self) -> Children<Entry<Key, T>> {
self.inner.children()
}
}
#[derive(Copy, Clone, Debug)]
pub struct KeyAlreadyExists<Key>(pub Key);
#[derive(Copy, Clone, Debug)]
pub enum AddSiblingError<Key> {
KeyAlreadyExists(Key),
RootCannotHaveSiblings,
}
impl<'a, Key: Hash + Eq + Clone, T: Clone> NodeMut<'a, Key, T> {
#[must_use]
pub fn data_mut(&mut self) -> &mut T {
&mut self.inner.data_mut().value
}
#[must_use]
pub fn into_data_mut(self) -> &'a mut T {
&mut self.inner.into_data_mut().value
}
pub fn push_front_child(
&mut self,
key: Key,
value: T,
) -> Result<NodeMut<Key, T>, KeyAlreadyExists<Key>> {
if self.map.contains_key(&key) {
return Err(KeyAlreadyExists(key));
}
let child = self.inner.push_front_child(Entry::new(key.clone(), value));
self.map.insert(key, child.id());
Ok(NodeMut::new(child, self.map))
}
pub fn push_next_sibling(
&mut self,
key: Key,
value: T,
) -> Result<NodeMut<Key, T>, AddSiblingError<Key>> {
if self.map.contains_key(&key) {
return Err(AddSiblingError::KeyAlreadyExists(key));
}
if let Ok(child) = self.inner.push_next_sibling(Entry::new(key.clone(), value)) {
self.map.insert(key, child.id());
Ok(NodeMut::new(child, self.map))
} else {
Err(AddSiblingError::RootCannotHaveSiblings)
}
}
pub fn remove(self) -> Result<(), CannotRemoveRoot> {
self.remove_with_consumer(|_| {})
}
pub fn remove_with_consumer(
self,
mut consumer: impl FnMut(Entry<Key, T>),
) -> Result<(), CannotRemoveRoot> {
self.inner.remove_with_consumer(|entry| {
self.map.remove(entry.key());
(consumer)(entry);
})
}
pub fn move_to(&mut self, location: Location<Key>) -> Result<(), MoveError<Key>> {
let mapped_location = location.into_tree_location(|key| {
self.map
.get(&key)
.copied()
.ok_or(MoveError::NoSuchNode(key))
})?;
self.inner
.move_to(mapped_location)
.map_err(|err| match err {
tree::MoveError::NoSuchNode(_) => {
unreachable!("node found in map and must exist")
}
tree::MoveError::RootCannotHaveSiblings => MoveError::RootCannotHaveSiblings,
tree::MoveError::CannotMoveUnderSelf => MoveError::CannotMoveUnderSelf,
})
}
}