#[derive(PartialEq, Eq, Debug, Copy, Clone)]
pub enum TreePart {
Edge,
Line,
Corner,
Blank,
}
impl TreePart {
pub fn ascii_art(self) -> &'static str {
#[rustfmt::skip]
return match self {
Self::Edge => "├── ",
Self::Line => "│ ",
Self::Corner => "└── ",
Self::Blank => " ",
};
}
}
#[derive(Debug, Default)]
pub struct TreeTrunk {
stack: Vec<TreePart>,
last_params: Option<TreeParams>,
}
#[derive(Debug, Copy, Clone)]
pub struct TreeParams {
depth: TreeDepth,
last: bool,
}
#[derive(Debug, Copy, Clone)]
pub struct TreeDepth(pub usize);
impl TreeTrunk {
pub fn new_row(&mut self, params: TreeParams) -> &[TreePart] {
if let Some(last) = self.last_params {
self.stack[last.depth.0] = if last.last {
TreePart::Blank
} else {
TreePart::Line
};
}
self.stack.resize(params.depth.0 + 1, TreePart::Edge);
self.stack[params.depth.0] = if params.last {
TreePart::Corner
} else {
TreePart::Edge
};
self.last_params = Some(params);
&self.stack[1..]
}
}
impl TreeParams {
pub fn new(depth: TreeDepth, last: bool) -> Self {
Self { depth, last }
}
}
impl TreeDepth {
pub fn root() -> Self {
Self(0)
}
pub fn deeper(self) -> Self {
Self(self.0 + 1)
}
pub fn iterate_over<I, T>(self, inner: I) -> Iter<I>
where
I: ExactSizeIterator + Iterator<Item = T>,
{
Iter {
current_depth: self,
inner,
}
}
}
pub struct Iter<I> {
current_depth: TreeDepth,
inner: I,
}
impl<I, T> Iterator for Iter<I>
where
I: ExactSizeIterator + Iterator<Item = T>,
{
type Item = (TreeParams, T);
fn next(&mut self) -> Option<Self::Item> {
let t = self.inner.next()?;
let params = TreeParams::new(self.current_depth, self.inner.len() == 0);
Some((params, t))
}
}
#[cfg(test)]
mod trunk_test {
use super::*;
fn params(depth: usize, last: bool) -> TreeParams {
TreeParams::new(TreeDepth(depth), last)
}
#[rustfmt::skip]
#[test]
fn empty_at_first() {
let mut tt = TreeTrunk::default();
assert_eq!(tt.new_row(params(0, true)), &[ ]);
}
#[rustfmt::skip]
#[test]
fn one_child() {
let mut tt = TreeTrunk::default();
assert_eq!(tt.new_row(params(0, true)), &[ ]);
assert_eq!(tt.new_row(params(1, true)), &[ TreePart::Corner ]);
}
#[rustfmt::skip]
#[test]
fn two_children() {
let mut tt = TreeTrunk::default();
assert_eq!(tt.new_row(params(0, true)), &[ ]);
assert_eq!(tt.new_row(params(1, false)), &[ TreePart::Edge ]);
assert_eq!(tt.new_row(params(1, true)), &[ TreePart::Corner ]);
}
#[rustfmt::skip]
#[test]
fn two_times_two_children() {
let mut tt = TreeTrunk::default();
assert_eq!(tt.new_row(params(0, false)), &[ ]);
assert_eq!(tt.new_row(params(1, false)), &[ TreePart::Edge ]);
assert_eq!(tt.new_row(params(1, true)), &[ TreePart::Corner ]);
assert_eq!(tt.new_row(params(0, true)), &[ ]);
assert_eq!(tt.new_row(params(1, false)), &[ TreePart::Edge ]);
assert_eq!(tt.new_row(params(1, true)), &[ TreePart::Corner ]);
}
#[rustfmt::skip]
#[test]
fn two_times_two_nested_children() {
let mut tt = TreeTrunk::default();
assert_eq!(tt.new_row(params(0, true)), &[ ]);
assert_eq!(tt.new_row(params(1, false)), &[ TreePart::Edge ]);
assert_eq!(tt.new_row(params(2, false)), &[ TreePart::Line, TreePart::Edge ]);
assert_eq!(tt.new_row(params(2, true)), &[ TreePart::Line, TreePart::Corner ]);
assert_eq!(tt.new_row(params(1, true)), &[ TreePart::Corner ]);
assert_eq!(tt.new_row(params(2, false)), &[ TreePart::Blank, TreePart::Edge ]);
assert_eq!(tt.new_row(params(2, true)), &[ TreePart::Blank, TreePart::Corner ]);
}
}
#[cfg(test)]
mod iter_test {
use super::*;
#[test]
fn test_iteration() {
let foos = &["first", "middle", "last"];
let mut iter = TreeDepth::root().iterate_over(foos.iter());
let next = iter.next().unwrap();
assert_eq!(&"first", next.1);
assert!(!next.0.last);
let next = iter.next().unwrap();
assert_eq!(&"middle", next.1);
assert!(!next.0.last);
let next = iter.next().unwrap();
assert_eq!(&"last", next.1);
assert!(next.0.last);
assert!(iter.next().is_none());
}
#[test]
fn test_empty() {
let nothing: &[usize] = &[];
let mut iter = TreeDepth::root().iterate_over(nothing.iter());
assert!(iter.next().is_none());
}
}