use std::{
collections::BTreeMap,
fmt::{Debug, Display, Formatter},
hash::Hash,
};
use rapidhash::RapidHashMap as HashMap;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Tree<Q, T>
where
Q: PartialEq + Eq + Clone + Display + Debug + Hash + Ord,
T: PartialEq + Eq + Clone,
{
nodes: HashMap<Q, Node<T, Q>>,
}
impl<Q, T> Default for Tree<Q, T>
where
Q: PartialEq + Eq + Clone + Display + Debug + Hash + Ord,
T: PartialEq + Eq + Clone,
{
fn default() -> Self {
Self {
nodes: Default::default(),
}
}
}
impl<Q, T> Tree<Q, T>
where
Q: PartialEq + Eq + Clone + Display + Debug + Hash + Ord,
T: PartialEq + Eq + Clone,
{
pub fn new() -> Self {
Self::default()
}
pub fn get_parent(&self, key: &Q) -> Result<&Q, Error<Q>> {
self.nodes
.get(key)
.map(|node| &node.parent)
.ok_or_else(|| Error::NonexistentNode(key.clone()))
}
pub fn set_parent(&mut self, child: &Q, parent: Q) -> Result<(), Error<Q>> {
self.get(&parent)?;
self.nodes
.get_mut(child)
.ok_or_else(|| Error::NonexistentNode(child.clone()))?
.parent = parent;
Ok(())
}
pub fn rename(&mut self, from: &Q, to: Q) -> Result<(), Error<Q>> {
if self.get(&to).is_ok() {
Err(Error::NonUniqueKey(to))
} else {
let node = self.nodes.remove(from);
match node {
Some(node) => {
self.add(to.clone(), node)?;
for child in self.children(from) {
self.set_parent(&child, to.clone())?;
}
Ok(())
}
None => Err(Error::NonexistentNode(from.clone())),
}
}
}
pub fn add(&mut self, key: Q, node: Node<T, Q>) -> Result<(), Error<Q>> {
if self.nodes.contains_key(&key) {
Err(Error::NonUniqueKey(key))
} else {
self.nodes.insert(key.clone(), node);
Ok(())
}
}
pub fn remove(&mut self, key: &Q, remove_children: bool) -> Result<T, Error<Q>> {
let node = self.nodes.remove(key);
match node {
Some(node) => {
if remove_children {
for child in self.children(key) {
self.remove(&child, remove_children)?;
}
} else {
for child in self.children(key) {
self.set_parent(&child, node.parent.clone())?;
}
}
Ok(node.value)
}
None => Err(Error::NonexistentNode(key.clone())),
}
}
pub fn get(&self, key: &Q) -> Result<&Node<T, Q>, Error<Q>> {
self.nodes
.get(key)
.ok_or_else(|| Error::NonexistentNode(key.clone()))
}
pub fn get_mut(&mut self, key: &Q) -> Result<&mut Node<T, Q>, Error<Q>> {
self.nodes
.get_mut(key)
.ok_or_else(|| Error::NonexistentNode(key.clone()))
}
pub fn get_from_parent(&self, key: &Q, parent: &Q) -> Result<Option<&Node<T, Q>>, Error<Q>> {
let node = self.get(key)?;
if self.get_parent(key)? == parent {
Ok(Some(node))
} else {
Ok(None)
}
}
pub fn get_all(&self, keys: Vec<Q>) -> Result<BTreeMap<Q, Node<T, Q>>, Error<Q>> {
Ok(keys
.iter()
.map(|key| self.get(key))
.collect::<Result<Vec<&Node<T, Q>>, Error<Q>>>()?
.into_iter()
.cloned()
.enumerate()
.map_while(|(index, value)| keys.get(index).map(|key| (key.clone(), value)))
.collect())
}
pub fn get_all_values(&self, keys: Vec<Q>) -> Result<BTreeMap<Q, T>, Error<Q>> {
Ok(self
.get_all(keys)?
.into_iter()
.map(|(key, node)| (key, node.value))
.collect())
}
pub fn children(&self, key: &Q) -> Vec<Q> {
self.nodes
.iter()
.filter_map(|(child, node)| {
if node.parent == *key {
Some(child.clone())
} else {
None
}
})
.collect()
}
pub fn siblings(&self, key: &Q, inclusive: bool) -> Result<Vec<Q>, Error<Q>> {
let nodes = self.children(self.get_parent(key)?);
if inclusive {
Ok(nodes)
} else {
Ok(nodes.into_iter().filter(|k| k != key).collect())
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct Node<T, Q>
where
Q: PartialEq + Eq + Clone + Display + Debug + Hash + Ord,
T: PartialEq + Eq + Clone,
{
pub value: T,
pub parent: Q,
}
impl<T, Q> Node<T, Q>
where
Q: PartialEq + Eq + Clone + Display + Debug + Hash + Ord,
T: PartialEq + Eq + Clone,
{
pub fn new(value: T, parent: Q) -> Self {
Self { value, parent }
}
}
#[derive(Debug)]
pub enum Error<Q>
where
Q: PartialEq + Eq + Clone + Display + Debug + Hash + Ord,
{
NonUniqueKey(Q),
NonexistentNode(Q),
}
impl<Q> Display for Error<Q>
where
Q: PartialEq + Eq + Clone + Display + Debug + Hash + Ord,
{
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Self::NonUniqueKey(key) => write!(f, "The key is already in use: {:?}", key),
Self::NonexistentNode(key) => {
write!(f, "Specified node or nodes do not exist: {:?}", key)
}
}
}
}
impl<Q> std::error::Error for Error<Q> where Q: PartialEq + Eq + Clone + Display + Debug + Hash + Ord
{}