#![doc = include_str!("../README.md")]
pub type Childs<'a, T> = Box<dyn AsRef<[T]> + 'a>;
pub trait LogTree: Sized {
fn add_node(&self, lvl: u8) -> Option<(String, Childs<Self>)>;
fn decorators(&self, lvl: u8) -> [&str; 4] {
match lvl {
0 => ["├─╼ ", "│ ", "└─╼ ", " "],
_ => ["├─> ", "│ ", "╰─> ", " "],
}
}
fn fmt_tree(&self) -> String {
let mut out = String::new();
if let Some((key, childs)) = self.add_node(0) {
out.push_str(&key);
let childs = childs.as_ref().as_ref();
let len = childs.len();
for (i, child) in childs.iter().enumerate() {
fmt_tree(String::new(), i == len - 1, child, &mut out, 0);
}
}
out
}
fn fmt_tree_node(&self, is_last: bool) -> String {
let mut out = String::new();
fmt_tree(String::new(), is_last, self, &mut out, 0);
out
}
}
fn fmt_tree(
mut prefix: String,
is_last: bool,
tree: &impl LogTree,
out: &mut String,
lvl: u8,
) {
let decorators = tree.decorators(lvl);
out.push('\n');
out.push_str(&prefix);
prefix.push_str(match is_last {
false => {
out.push_str(decorators[0]);
decorators[1]
}
true => {
out.push_str(decorators[2]);
decorators[3]
}
});
if let Some((key, childs)) = tree.add_node(lvl) {
out.push_str(&key);
let childs = childs.as_ref().as_ref();
let len = childs.len();
for (i, child) in childs.iter().enumerate() {
fmt_tree(prefix.clone(), i == len - 1, child, out, lvl + 1);
}
}
}