use std::{collections::HashMap, fmt::Display, path::PathBuf}; use super::{error, MapKey, Mapping}; /// A prefix tree pub struct MappingTree { root: Node, } #[derive(Clone)] pub struct Node { children: HashMap, value: Option, /// The key needed to get to this node location: Vec, } impl MappingTree { pub fn new() -> Self { Self { root: Node::new(vec![], None), } } /// Returns the node at the key, otherwise None pub fn get(&self, key: &[MapKey]) -> Option<&Node> { let mut current_node = &self.root; for ch in key.iter() { current_node = current_node.children.get(&ch)? } Some(current_node) } /// Returns the node at the key, otherwise None. The node can be changed pub fn get_mut(&mut self, key: &[MapKey]) -> Option<&mut Node> { let mut current_node = &mut self.root; for ch in key.iter() { current_node = current_node.children.get_mut(&ch)? } Some(current_node) } /// Returns the node at the key, otherwise the last node that matched. pub fn try_get(&self, key: &[MapKey]) -> &Node { let mut current_node = &self.root; for ch in key.iter() { if let Some(node) = current_node.children.get(&ch) { current_node = node; } else { return current_node; } } current_node } pub fn insert(&mut self, key: &[MapKey], mapping: Mapping) -> Result<(), error::Error> { let node = self.try_get(key).clone(); if node.location.as_slice() != key { let needed_nodes_key = key .strip_prefix(node.location.as_slice()) .expect("The node's location is a prefix"); let needed_nodes_length = needed_nodes_key.iter().count(); let mut current_node = self .get_mut(&node.location) .expect("This should always exists"); let mut current_location = node.location.clone(); let mut counter = 1; for ch in needed_nodes_key.iter() { current_location.push(ch.to_owned()); let next_node = if counter == needed_nodes_length { Node::new(current_location.clone(), Some(mapping.clone())) } else { Node::new(current_location.clone(), None) }; current_node.children.insert(ch.to_owned(), next_node); current_node = current_node .children .get_mut(&ch) .expect("Was just inserted"); counter += 1; } } else { return Err(error::Error::NodeExits(MapKey::display(key))); } Ok(()) } } impl Node { pub fn new(location: Vec, mapping: Option) -> Self { Self { children: HashMap::new(), location, value: mapping, } } } impl Display for MappingTree { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn write_node( node: &Node, indention: String, has_parent: bool, is_last: bool, f: &mut std::fmt::Formatter<'_>, ) -> std::fmt::Result { let bullet = if has_parent { if is_last { String::from("└── ") } else { String::from("├── ") } } else { String::new() }; let node_value = if let Some(value) = &node.value { value.to_string() } else { "[No Value]".to_owned() }; let new_idention = if !has_parent { String::new() } else if is_last { indention.replace('│', " ") + " " } else { indention.clone() + "│ " }; write!( f, "{}{}\x1b[1;33m{}\x1b[0m: {}\n", indention, bullet, MapKey::display(&node.location), node_value, )?; let value_length = node.children.len(); let mut counter = 1; for child in node.children.values() { if counter == value_length { write_node(child, new_idention.clone(), true, true, f)?; } else { write_node(child, new_idention.clone(), true, false, f)?; }; counter += 1; } Ok(()) } write_node(&self.root, String::new(), false, false, f)?; Ok(()) } }