310 lines
9.6 KiB
Rust
310 lines
9.6 KiB
Rust
#[derive(Default, Debug, Clone)]
|
|
pub enum StringTreeElement {
|
|
#[default]
|
|
None,
|
|
Element(String, Box<Vec<StringTreeElement>>),
|
|
}
|
|
impl StringTreeElement {
|
|
pub fn is_none(&self) -> bool {
|
|
match self {
|
|
StringTreeElement::None => true,
|
|
_ => false,
|
|
}
|
|
}
|
|
pub fn name_of(&self) -> Option<&String> {
|
|
match self {
|
|
StringTreeElement::Element(name, _) => Some(name),
|
|
_ => None,
|
|
}
|
|
}
|
|
pub fn new(key: &String) -> StringTreeElement {
|
|
StringTreeElement::Element(key.clone(), Box::new(Vec::new()))
|
|
}
|
|
}
|
|
#[derive(Default, Debug, Clone)]
|
|
pub struct StringTree {
|
|
pub root: Vec<StringTreeElement>,
|
|
}
|
|
impl StringTree {
|
|
pub fn new() -> Self {
|
|
StringTree { root: Vec::new() }
|
|
}
|
|
pub fn add_root_level(&mut self, element: &String) -> bool {
|
|
for each in &self.root {
|
|
if Self::check_present(each, element) {
|
|
return false;
|
|
}
|
|
}
|
|
self.root.push(StringTreeElement::new(element));
|
|
true
|
|
}
|
|
pub fn add_child(&mut self, child: &String, parent: &String) -> bool {
|
|
if !self.is_present(child) {
|
|
for each in &mut self.root {
|
|
let res = Self::add_child_to_parent(each, child, parent);
|
|
if res {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
// returns false if parent not found or string already present
|
|
false
|
|
}
|
|
fn add_child_to_parent(
|
|
element: &mut StringTreeElement,
|
|
child: &String,
|
|
parent: &String,
|
|
) -> bool {
|
|
if let StringTreeElement::Element(name, children) = element {
|
|
if name == parent {
|
|
children.as_mut().push(StringTreeElement::new(child));
|
|
return true;
|
|
}
|
|
for each in children.as_mut() {
|
|
if Self::add_child_to_parent(each, child, parent) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
false
|
|
}
|
|
pub fn is_present(&self, key: &String) -> bool {
|
|
for each in &self.root {
|
|
let res = Self::check_present(each, key);
|
|
if res {
|
|
return true;
|
|
}
|
|
}
|
|
false
|
|
}
|
|
fn check_present(element: &StringTreeElement, key: &String) -> bool {
|
|
if let StringTreeElement::Element(name, children) = element {
|
|
if name.eq(key) {
|
|
return true;
|
|
}
|
|
for each in children.as_ref() {
|
|
if Self::check_present(each, key) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
false
|
|
}
|
|
pub fn add(&mut self, element: &String, parent: Option<&String>) -> bool {
|
|
if let Some(parent) = parent {
|
|
return self.add_child(element, parent);
|
|
} else {
|
|
return self.add_root_level(element);
|
|
}
|
|
}
|
|
|
|
pub fn move_branch(&mut self, element: &String, parent: &String) -> bool {
|
|
if self.is_present(parent) {
|
|
if let Some(popped) = self.pop_branch(element) {
|
|
for each in &mut self.root {
|
|
if Self::place_branch(each, parent, &popped) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
false
|
|
}
|
|
fn place_branch(
|
|
subject: &mut StringTreeElement,
|
|
target_parent: &String,
|
|
element: &StringTreeElement,
|
|
) -> bool {
|
|
match subject {
|
|
StringTreeElement::Element(name, branch) => {
|
|
//
|
|
if name == target_parent {
|
|
branch.push(element.clone());
|
|
return true;
|
|
}
|
|
for each in branch.as_mut() {
|
|
if Self::place_branch(each, target_parent, element) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
_ => {}
|
|
}
|
|
false
|
|
}
|
|
|
|
fn pop_branch(&mut self, element: &String) -> Option<StringTreeElement> {
|
|
let mut index = usize::MAX;
|
|
for (ind, each) in (&self.root).iter().enumerate() {
|
|
if let Some(el) = each.name_of() {
|
|
if el == element {
|
|
index = ind;
|
|
}
|
|
}
|
|
}
|
|
if index != usize::MAX {
|
|
let popped = self.root.remove(index);
|
|
return Some(popped);
|
|
} else {
|
|
for each in &mut self.root {
|
|
let x = Self::recursive_branch_find_pop(each, element);
|
|
if x.is_some() {
|
|
return x;
|
|
}
|
|
}
|
|
}
|
|
None
|
|
}
|
|
fn recursive_branch_find_pop(
|
|
iterator: &mut StringTreeElement,
|
|
name: &String,
|
|
) -> Option<StringTreeElement> {
|
|
// name checked in previous iteration
|
|
if let StringTreeElement::Element(_, branch) = iterator {
|
|
let mut index = usize::MAX;
|
|
for each in branch.as_ref().iter().enumerate() {
|
|
if let Some(el_name) = each.1.name_of() {
|
|
if el_name == name {
|
|
index = each.0;
|
|
}
|
|
}
|
|
}
|
|
if index != usize::MAX {
|
|
let popped = branch.remove(index);
|
|
return Some(popped);
|
|
} else {
|
|
for each in branch.as_mut() {
|
|
let x = Self::recursive_branch_find_pop(each, name);
|
|
if x.is_some() {
|
|
return x;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
None
|
|
}
|
|
|
|
pub fn remove_branch(&mut self, element: &String) -> bool {
|
|
return self.pop_branch(element).is_some();
|
|
}
|
|
|
|
pub fn remove_element_preserve_branch(&mut self, search: &String) -> bool {
|
|
let mut failed_yet = false;
|
|
let clone = self.clone();
|
|
let parent = clone.parent_of(search);
|
|
if let Some(popped) = self.pop_branch(search) {
|
|
let mut popped = popped;
|
|
if parent.is_some() {
|
|
let parent = parent.unwrap();
|
|
match &mut popped {
|
|
StringTreeElement::None => {}
|
|
StringTreeElement::Element(_, branch) => {
|
|
for each in branch.as_mut() {
|
|
for branches in &mut self.root {
|
|
let x = Self::place_branch(branches, parent, &each);
|
|
if !x {
|
|
failed_yet = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
match &mut popped {
|
|
StringTreeElement::None => {}
|
|
StringTreeElement::Element(_, branch) => {
|
|
for each in branch.as_ref() {
|
|
self.root.push(each.clone());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
!failed_yet
|
|
}
|
|
pub fn parent_of(&self, search: &String) -> Option<&String> {
|
|
let mut queue = Vec::new();
|
|
|
|
for each in &self.root {
|
|
queue.push(each);
|
|
}
|
|
while !queue.is_empty() {
|
|
let element = queue.pop().unwrap();
|
|
if let StringTreeElement::Element(name, branch) = element {
|
|
for each in branch.as_ref() {
|
|
if let Some(c_name) = each.name_of() {
|
|
if c_name == search {
|
|
return Some(name);
|
|
}
|
|
}
|
|
queue.push(each);
|
|
}
|
|
}
|
|
}
|
|
None
|
|
}
|
|
/* iterative variation of is_present
|
|
pub fn contains(&self, search: &String) -> bool {
|
|
let mut queue = Vec::new();
|
|
|
|
for each in &self.root {
|
|
queue.push(each);
|
|
}
|
|
while !queue.is_empty() {
|
|
let element = queue.pop().unwrap();
|
|
if let StringTreeElement::Element(name, branch) = element {
|
|
if name == search {
|
|
return true;
|
|
}
|
|
for each in branch.as_ref() {
|
|
queue.push(each);
|
|
}
|
|
}
|
|
}
|
|
false
|
|
} */
|
|
|
|
pub fn list_of_elements(&self) -> Vec<String> {
|
|
let mut list: Vec<String> = Vec::new();
|
|
let mut to_search = Vec::new();
|
|
for each in &self.root {
|
|
to_search.push(each);
|
|
}
|
|
while !to_search.is_empty() {
|
|
let next = to_search.pop();
|
|
if let Some(next) = next {
|
|
if let Some(name) = next.name_of() {
|
|
list.push(name.clone());
|
|
}
|
|
if let StringTreeElement::Element(_, children) = next {
|
|
for each in children.as_ref() {
|
|
to_search.push(each);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return list;
|
|
}
|
|
}
|
|
#[test]
|
|
pub fn test_string_tree() {
|
|
let parent = &String::from("parent1");
|
|
let parent2 = &String::from("parent2");
|
|
let child = &String::from("child1");
|
|
let child2 = &String::from("child2");
|
|
let mut tester = StringTree::new();
|
|
tester = dbg!(tester);
|
|
assert!(dbg!(tester.add(parent, None)));
|
|
tester = dbg!(tester);
|
|
assert!(dbg!(tester.add_child(child, parent)));
|
|
tester = dbg!(tester);
|
|
assert!(dbg!(tester.add_root_level(parent2)));
|
|
tester = dbg!(tester);
|
|
assert!(!dbg!(tester.add_child(child, parent2)));
|
|
tester = dbg!(tester);
|
|
assert!(dbg!(tester.add(child2, Some(parent2))));
|
|
tester = dbg!(tester);
|
|
assert!(dbg!(tester.move_branch(parent2, parent)));
|
|
dbg!(tester);
|
|
}
|