grapes 0.3.0

Persistent graph data structures: Tree, Graph, Arena & more
Documentation
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;

/// A mutable reference to a node in a [MapTree](super::MapTree)
///
/// The library guarantees that this references a valid node in the associated tree
#[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> {
    /// Get the entry associated with the node
    #[must_use]
    pub fn data(&self) -> &T {
        self.inner.data().value()
    }

    /// Get the key associated with the node.
    #[must_use]
    pub fn key(&self) -> &Key {
        self.inner.data().key()
    }

    /// Iterate over the node's children entries
    pub fn children(&self) -> Children<Entry<Key, T>> {
        self.inner.children()
    }
}

/// Error: the specified key is already present in the tree
#[derive(Copy, Clone, Debug)]
pub struct KeyAlreadyExists<Key>(pub Key);

/// Error when adding a sibling node to a [MapTree](super::MapTree)
#[derive(Copy, Clone, Debug)]
pub enum AddSiblingError<Key> {
    /// The specified key is already present in the tree
    KeyAlreadyExists(Key),
    /// The root node cannot have siblings
    RootCannotHaveSiblings,
}

impl<'a, Key: Hash + Eq + Clone, T: Clone> NodeMut<'a, Key, T> {
    /// Get a mutable reference to the node's data
    #[must_use]
    pub fn data_mut(&mut self) -> &mut T {
        &mut self.inner.data_mut().value
    }

    /// Convert into a mutable reference to the node's data with the same lifetime as the tree
    #[must_use]
    pub fn into_data_mut(self) -> &'a mut T {
        &mut self.inner.into_data_mut().value
    }

    /// Push a new child node to the front of the children list
    ///
    /// This operation should always succeed
    ///
    /// (The specified value will become the first child, and any subsequent children will be pushed down)
    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))
    }

    /// Push a new child as the next sibling of this node
    ///
    /// This is allowed for all nodes except for the root node. When attempting to add a sibling to the root node, this will return [None], and nothing will be added to the tree
    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)
        }
    }

    /// Remove this node and all of its descendants from the tree
    ///
    /// Note: if you'd like to do something with the removed values, use `remove_with_consumer` instead.
    ///
    /// Removing the root node is not allowed and will return an error with [CannotRemoveRoot]. All other removals are allowed.
    pub fn remove(self) -> Result<(), CannotRemoveRoot> {
        self.remove_with_consumer(|_| {})
    }

    /// Remove this node and all of its descendants from the tree
    ///
    /// All removed values will be passed to the specified `consumer` function
    ///
    /// Removing the root node is not allowed and will return an error with [CannotRemoveRoot]. All other removals are allowed.
    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);
        })
    }

    /// Move this node, along with all descendants, to a new location
    ///
    /// If this is not allowed, a [MoveError] will be returned, and no changes will be made. See the [MoveError] documentation for details on possible errors.
    ///
    /// Moving a node to `AfterSibling(self ID)` is allowed and has no effect.
    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,
            })
    }
}