use std::fmt::{self, Display};
#[derive(Debug)]
pub struct Tree<D: Display>(D, Vec<Tree<D>>);
impl<D: Display> Tree<D> {
pub fn new(root: D, leaves: Vec<Tree<D>>) -> Tree<D> {
Tree(root, leaves)
}
pub fn root(root: D) -> Tree<D> {
Tree(root, Vec::new())
}
pub fn push(&mut self, leaf: Tree<D>) -> &mut Self {
self.1.push(leaf);
self
}
fn display_leaves(f: &mut fmt::Formatter,
leaves: &Vec<Tree<D>>,
spaces: Vec<bool>)
-> fmt::Result {
for (i, leaf) in leaves.iter().enumerate() {
let last = i >= leaves.len() - 1;
let mut clone = spaces.clone();
for s in &spaces {
if *s {
let _ = write!(f, " ");
} else {
let _ = write!(f, "| ");
}
}
if last {
let _ = writeln!(f, "└── {}", leaf.0);
} else {
let _ = writeln!(f, "├── {}", leaf.0);
}
if !leaf.1.is_empty() {
clone.push(last);
let _ = Self::display_leaves(f, &leaf.1, clone);
}
}
write!(f, "")
}
}
impl<D: Display> Display for Tree<D> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let _ = writeln!(f, "{}", self.0);
Self::display_leaves(f, &self.1, Vec::new())
}
}
#[cfg(test)]
mod tests {
use super::Tree;
#[test]
fn render_tree_root() {
let tree = Tree::root("foo");
assert_eq!(format!("{}", tree), "foo\n")
}
#[test]
fn render_tree_with_leaves() {
let tree = Tree::new(
"foo", vec![
Tree::new(
"bar", vec![
Tree::root("baz")
]
)
]
);
assert_eq!(format!("{}", tree), r#"foo
└── bar
└── baz
"#)
}
}