#[derive(Clone, Debug, Default, PartialEq)]
pub(crate) struct IshikawaNode {
pub(crate) text: String,
pub(crate) children: Vec<usize>,
}
#[derive(Clone, Debug, Default)]
pub(crate) struct IshikawaDb {
pub(crate) title: Option<String>,
pub(crate) nodes: Vec<IshikawaNode>,
stack: Vec<(usize, usize)>,
base_level: Option<usize>,
}
impl IshikawaDb {
pub(crate) fn new(title: Option<&str>) -> IshikawaDb {
IshikawaDb {
title: title.map(str::to_string),
..IshikawaDb::default()
}
}
pub(crate) fn root(&self) -> Option<&IshikawaNode> {
self.nodes.first()
}
pub(crate) fn add_node(&mut self, raw_level: usize, text: &str) {
let index = self.nodes.len();
self.nodes.push(IshikawaNode {
text: text.to_string(),
children: Vec::new(),
});
if index == 0 {
self.stack = vec![(0, 0)];
return;
}
let base = *self.base_level.get_or_insert(raw_level);
let level = (raw_level + 1).saturating_sub(base).max(1);
while self.stack.len() > 1 && self.stack[self.stack.len() - 1].0 >= level {
self.stack.pop();
}
let parent = self.stack[self.stack.len() - 1].1;
self.nodes[parent].children.push(index);
self.stack.push((level, index));
}
}