use std::fmt;
use indextree::Arena;
use string_interner::{DefaultBackend, StringInterner};
use crate::low::v7400::AttributeValue;
use self::node::{NodeData, NodeNameSym};
pub use self::{
error::LoadError,
loader::Loader,
node::{
handle::{Children, ChildrenByName, NodeHandle},
NodeId,
},
};
mod macros;
mod error;
mod loader;
mod node;
#[derive(Debug, Clone, PartialEq)]
pub struct Tree {
arena: Arena<NodeData>,
node_names: StringInterner<DefaultBackend<NodeNameSym>>,
root_id: NodeId,
}
impl Tree {
#[inline]
#[must_use]
pub fn root(&self) -> NodeHandle<'_> {
NodeHandle::new(self, self.root_id)
}
#[inline]
#[must_use]
fn new(
arena: Arena<NodeData>,
node_names: StringInterner<DefaultBackend<NodeNameSym>>,
root_id: NodeId,
) -> Self {
Self {
arena,
node_names,
root_id,
}
}
#[must_use]
pub(crate) fn node(&self, node_id: NodeId) -> &indextree::Node<NodeData> {
self.arena.get(node_id.raw()).unwrap_or_else(|| {
panic!(
"The given node ID is not used in the tree: node_id={:?}",
node_id
)
})
}
#[must_use]
pub(crate) fn resolve_node_name(&self, sym: NodeNameSym) -> &str {
self.node_names
.resolve(sym)
.unwrap_or_else(|| panic!("Unresolvable node name symbol: {:?}", sym))
}
#[must_use]
pub(crate) fn node_name_sym(&self, name: &str) -> Option<NodeNameSym> {
self.node_names.get(name)
}
#[must_use]
pub(crate) fn contains_node(&self, node_id: NodeId) -> bool {
self.arena.get(node_id.raw()).is_some()
}
pub fn create_node(&mut self, name: &str) -> NodeId {
let name_sym = self.node_names.get_or_intern(name);
let new_node = self.arena.new_node(NodeData::new(name_sym, Vec::new()));
NodeId::new(new_node)
}
pub fn append(&mut self, new_last_child: NodeId, parent: NodeId) {
parent.raw().append(new_last_child.raw(), &mut self.arena);
}
pub fn prepend(&mut self, new_first_child: NodeId, parent: NodeId) {
parent.raw().prepend(new_first_child.raw(), &mut self.arena);
}
pub fn insert_after(&mut self, new_next_sibling: NodeId, prev_sibling: NodeId) {
prev_sibling
.raw()
.insert_after(new_next_sibling.raw(), &mut self.arena);
}
pub fn insert_before(&mut self, new_prev_sibling: NodeId, next_sibling: NodeId) {
next_sibling
.raw()
.insert_after(new_prev_sibling.raw(), &mut self.arena);
}
pub fn append_new(&mut self, parent: NodeId, name: &str) -> NodeId {
let name_sym = self.node_names.get_or_intern(name);
let new_child = self.arena.new_node(NodeData::new(name_sym, Vec::new()));
parent.raw().append(new_child, &mut self.arena);
NodeId::new(new_child)
}
pub fn prepend_new(&mut self, parent: NodeId, name: &str) -> NodeId {
let name_sym = self.node_names.get_or_intern(name);
let new_child = self.arena.new_node(NodeData::new(name_sym, Vec::new()));
parent.raw().prepend(new_child, &mut self.arena);
NodeId::new(new_child)
}
pub fn insert_new_after(&mut self, sibling: NodeId, name: &str) -> NodeId {
assert_ne!(sibling, self.root_id, "Root node should have no siblings");
let name_sym = self.node_names.get_or_intern(name);
let new_child = self.arena.new_node(NodeData::new(name_sym, Vec::new()));
sibling.raw().insert_after(new_child, &mut self.arena);
NodeId::new(new_child)
}
pub fn insert_new_before(&mut self, sibling: NodeId, name: &str) -> NodeId {
assert_ne!(sibling, self.root_id, "Root node should have no siblings");
let name_sym = self.node_names.get_or_intern(name);
let new_child = self.arena.new_node(NodeData::new(name_sym, Vec::new()));
sibling.raw().insert_before(new_child, &mut self.arena);
NodeId::new(new_child)
}
pub fn detach(&mut self, subtree_root: NodeId) {
subtree_root.raw().detach(&mut self.arena);
}
pub fn append_attribute(&mut self, node_id: NodeId, v: impl Into<AttributeValue>) {
self.append_attribute_impl(node_id, v.into())
}
fn append_attribute_impl(&mut self, node_id: NodeId, v: AttributeValue) {
assert_ne!(node_id, self.root_id, "Root node should have no attributes");
let node = self.arena.get_mut(node_id.raw()).expect("Invalid node ID");
node.get_mut().append_attribute(v)
}
#[must_use]
pub fn get_attribute_mut(&mut self, node_id: NodeId, i: usize) -> Option<&mut AttributeValue> {
let node = self.arena.get_mut(node_id.raw()).expect("Invalid node ID");
node.get_mut().get_attribute_mut(i)
}
pub fn take_attributes_vec(&mut self, node_id: NodeId) -> Vec<AttributeValue> {
let node = self.arena.get_mut(node_id.raw()).expect("Invalid node ID");
node.get_mut().replace_attributes(Default::default())
}
pub fn set_attributes_vec(&mut self, node_id: NodeId, new: Vec<AttributeValue>) {
let node = self.arena.get_mut(node_id.raw()).expect("Invalid node ID");
node.get_mut().replace_attributes(new);
}
#[inline]
#[must_use]
pub fn strict_eq(&self, other: &Self) -> bool {
self.root().strict_eq(&other.root())
}
#[inline]
#[must_use]
pub fn debug_tree(&self) -> impl fmt::Debug + '_ {
DebugTree { tree: self }
}
}
impl Default for Tree {
fn default() -> Self {
let mut arena = Arena::new();
let mut node_names = StringInterner::new();
let root_id =
NodeId::new(arena.new_node(NodeData::new(node_names.get_or_intern(""), Vec::new())));
Self {
arena,
node_names,
root_id,
}
}
}
struct DebugTree<'a> {
tree: &'a Tree,
}
impl fmt::Debug for DebugTree<'_> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let v = DebugNodeHandle {
node: self.tree.root(),
};
v.fmt(f)
}
}
struct DebugNodeHandle<'a> {
node: NodeHandle<'a>,
}
impl fmt::Debug for DebugNodeHandle<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Node")
.field("name", &self.node.name())
.field("attributes", &self.node.attributes())
.field("children", &DebugNodeHandleChildren { node: self.node })
.finish()
}
}
struct DebugNodeHandleChildren<'a> {
node: NodeHandle<'a>,
}
impl fmt::Debug for DebugNodeHandleChildren<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list()
.entries(
self.node
.children()
.map(|child| DebugNodeHandle { node: child }),
)
.finish()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum DepthFirstTraversed {
Open(NodeId),
Close(NodeId),
}
impl DepthFirstTraversed {
#[inline]
#[must_use]
pub fn node_id(self) -> NodeId {
match self {
Self::Open(id) => id,
Self::Close(id) => id,
}
}
#[inline]
#[must_use]
pub fn is_open(self) -> bool {
matches!(self, Self::Open(_))
}
#[inline]
#[must_use]
pub fn is_close(self) -> bool {
matches!(self, Self::Close(_))
}
#[inline]
#[must_use]
pub fn node_id_open(self) -> Option<NodeId> {
match self {
Self::Open(id) => Some(id),
Self::Close(_) => None,
}
}
#[inline]
#[must_use]
pub fn node_id_close(self) -> Option<NodeId> {
match self {
Self::Open(_) => None,
Self::Close(id) => Some(id),
}
}
#[must_use]
pub fn next(self, tree: &Tree) -> Option<Self> {
let next = match self {
Self::Open(current) => {
match current.to_handle(tree).first_child() {
Some(child) => Self::Open(child.node_id()),
None => Self::Close(current),
}
}
Self::Close(current) => {
let node = current.to_handle(tree);
match node.next_sibling() {
Some(next_sib) => Self::Open(next_sib.node_id()),
None => Self::Close(node.parent()?.node_id()),
}
}
};
Some(next)
}
#[must_use]
pub fn prev(self, tree: &Tree) -> Option<Self> {
let prev = match self {
Self::Close(current) => {
match current.to_handle(tree).last_child() {
Some(child) => Self::Close(child.node_id()),
None => Self::Open(current),
}
}
Self::Open(current) => {
let node = current.to_handle(tree);
match node.previous_sibling() {
Some(prev_sib) => Self::Close(prev_sib.node_id()),
None => Self::Open(node.parent()?.node_id()),
}
}
};
Some(prev)
}
}
#[derive(Debug, Clone, Copy)]
pub struct DepthFirstTraverseSubtree {
cursors: Option<(DepthFirstTraversed, DepthFirstTraversed)>,
}
impl DepthFirstTraverseSubtree {
#[inline]
#[must_use]
fn with_root_id(root: NodeId) -> Self {
Self {
cursors: Some((
DepthFirstTraversed::Open(root),
DepthFirstTraversed::Close(root),
)),
}
}
#[inline]
pub fn next_forward(&mut self, tree: &Tree) -> Option<DepthFirstTraversed> {
let (forward, backward) = self.cursors?;
if forward == backward {
self.cursors = None;
} else {
let next_of_next = forward
.next(tree)
.expect("`forward` should point before `backward`");
self.cursors = Some((next_of_next, backward));
}
Some(forward)
}
#[inline]
pub fn next_backward(&mut self, tree: &Tree) -> Option<DepthFirstTraversed> {
let (forward, backward) = self.cursors?;
if forward == backward {
self.cursors = None;
} else {
let next_of_next = backward
.prev(tree)
.expect("`forward` should point before `backward`");
self.cursors = Some((forward, next_of_next));
}
Some(backward)
}
#[inline]
#[must_use]
pub fn peek_forward(&self) -> Option<DepthFirstTraversed> {
self.cursors.map(|(forward, _backward)| forward)
}
#[inline]
#[must_use]
pub fn peek_backward(&self) -> Option<DepthFirstTraversed> {
self.cursors.map(|(_forward, backward)| backward)
}
pub fn next_open_forward(&mut self, tree: &Tree) -> Option<NodeId> {
loop {
let next = self.next_forward(tree)?;
if let DepthFirstTraversed::Open(id) = next {
return Some(id);
}
}
}
pub fn next_close_forward(&mut self, tree: &Tree) -> Option<NodeId> {
loop {
let next = self.next_forward(tree)?;
if let DepthFirstTraversed::Close(id) = next {
return Some(id);
}
}
}
#[must_use]
pub fn next_open_backward(&mut self, tree: &Tree) -> Option<NodeId> {
loop {
let next = self.next_backward(tree)?;
if let DepthFirstTraversed::Open(id) = next {
return Some(id);
}
}
}
#[must_use]
pub fn next_close_backward(&mut self, tree: &Tree) -> Option<NodeId> {
loop {
let next = self.next_backward(tree)?;
if let DepthFirstTraversed::Close(id) = next {
return Some(id);
}
}
}
}