use std::collections::HashMap;
use std::ops::Deref;
use crate::value::Value;
#[derive(Debug, Clone)]
pub enum Node {
Group {
path: Vec<String>,
location: GroupLocation,
information: Information,
children: Vec<Node>,
},
Leaf(Leaf),
}
impl Node {
pub fn index_range(&self) -> (usize, usize) {
match self {
Node::Group { children, .. } => children
.iter()
.fold((usize::MAX, usize::MIN), |(min_from, max_to), ch| {
let (from, to) = ch.index_range();
(min_from.min(from), max_to.max(to))
}),
Node::Leaf(Leaf::Real(RealLeaf { location, .. })) => (location.index, location.index),
_ => (usize::MAX, usize::MIN),
}
}
pub fn information(&self) -> &Information {
match self {
Node::Group { information, .. } => information,
Node::Leaf(Leaf::Real(l)) => &l.information,
Node::Leaf(Leaf::Virtual(l)) => &l.information,
}
}
}
#[derive(Debug, Clone)]
pub struct LeafLocation {
pub from: usize,
pub to: usize,
pub index: usize,
}
#[derive(Debug, Clone)]
pub struct GroupLocation {
pub byte_from: usize,
pub byte_to: usize,
pub index_from: usize,
pub index_to: usize,
}
#[derive(Debug, Clone)]
pub struct Information {
pub label: String,
pub data: HashMap<&'static str, String>,
pub tags: Vec<Tag>,
pub value: Value,
pub doc: Option<String>,
pub splain: Option<String>,
}
impl Information {
pub fn has_data(&self, key: &'static str, value: &str) -> bool {
match self.data.get(key) {
Some(v) => v == value,
_ => false,
}
}
}
#[derive(Debug, Clone)]
pub struct Tag {
pub label: String,
pub color: Option<String>,
pub doc: Option<String>,
}
#[derive(Debug, Clone)]
pub struct VirtualLeaf {
pub path: Vec<String>,
pub information: Information,
}
#[derive(Debug, Clone)]
pub struct RealLeaf {
pub path: Vec<String>,
pub location: LeafLocation,
pub information: Information,
}
#[derive(Debug, Clone)]
pub enum Leaf {
Real(RealLeaf),
Virtual(VirtualLeaf),
}
#[derive(Debug)]
pub struct Tree(Vec<Node>);
impl Tree {
#[inline]
pub fn from_nodes(trees: Vec<Node>) -> Tree {
Tree(trees)
}
pub fn leaves(&self) -> Vec<&RealLeaf> {
Self::tree_leaves(&self.0)
}
fn tree_leaves(trees: &[Node]) -> Vec<&RealLeaf> {
trees
.iter()
.flat_map(|tree| match tree {
Node::Group { children, .. } => Self::tree_leaves(children),
Node::Leaf(Leaf::Real(leaf)) => vec![leaf],
_ => vec![], })
.collect()
}
pub fn select<'a>(&'a self, path: &'a [String]) -> Option<&'a Node> {
Self::select_path(&self.0, path)
}
fn select_path<'a>(tree: &'a [Node], path: &'a [String]) -> Option<&'a Node> {
let (head, tail) = path.split_first()?;
let i = head.parse::<usize>().ok()?;
let subtree = tree
.iter()
.collect::<Vec<_>>();
let subtree = subtree.get(i)?;
if tail.is_empty() {
Some(subtree)
} else {
match subtree {
Node::Group { children, .. } => Self::select_path(children, tail),
_ => None,
}
}
}
}
impl Deref for Tree {
type Target = [Node];
fn deref(&self) -> &Self::Target {
&self.0
}
}