atelier/bake/lib/wald/mod.rs
2025-01-16 20:05:09 -05:00

165 lines
3.4 KiB
Rust

use std::{fmt::Display, ops::Range};
pub enum Text {
Span(Range<usize>),
Static(&'static str),
String(String),
}
impl Default for Text {
fn default() -> Self {
Self::Static("")
}
}
impl Text {
pub fn empty() -> Self {
Self::default()
}
pub fn is_empty(&self) -> bool {
match self {
Self::Span(s) => s.is_empty(),
Self::Static(s) => s.is_empty(),
Self::String(s) => s.is_empty(),
}
}
pub fn as_str<'a>(&'a self, text: &'a str) -> &'a str {
match self {
Self::Span(s) => &text[s.clone()],
Self::Static(s) => s,
Self::String(s) => s.as_str(),
}
}
}
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
pub struct NodeRef(usize);
#[derive(Default)]
pub struct NodeStorage {
tags: Vec<u16>,
parents: Vec<Option<NodeRef>>,
children: Vec<Vec<NodeRef>>,
siblings_prev: Vec<Option<NodeRef>>,
siblings_next: Vec<Option<NodeRef>>,
texts: Vec<Text>,
}
impl NodeStorage {
pub fn nodes(&self) -> impl Iterator<Item = NodeRef> {
(0..self.tags.len()).map(NodeRef)
}
pub fn new_node(&mut self, tag: u16) -> NodeRef {
let node = NodeRef(self.tags.len());
self.tags.push(tag);
self.parents.push(None);
self.children.push(vec![]);
self.siblings_prev.push(None);
self.siblings_next.push(None);
self.texts.push(Text::default());
node
}
pub fn tag(&self, node: NodeRef) -> u16 {
self.tags[node.0]
}
pub fn parent(&self, node: NodeRef) -> Option<NodeRef> {
self.parents[node.0]
}
pub fn set_parent(&mut self, child: NodeRef, parent: NodeRef) {
self.parents[child.0] = Some(parent);
}
pub fn children(&self, node: NodeRef) -> impl Iterator<Item = NodeRef> {
self.children[node.0].iter().copied()
}
pub fn append_child(&mut self, parent: NodeRef, child: NodeRef) {
self.set_parent(child, parent);
let children = &mut self.children[parent.0];
let child_index = children.len();
children.push(child);
if child_index > 0 {
let prev_index = child_index - 1;
let prev_sibling = children[prev_index];
self.set_sibling_next(prev_sibling, child);
self.set_sibling_prev(child, prev_sibling);
}
}
pub fn sibling_next(&mut self, node: NodeRef) -> Option<NodeRef> {
self.siblings_next[node.0]
}
pub fn set_sibling_next(&mut self, this: NodeRef, next: NodeRef) {
self.siblings_next[this.0] = Some(next);
}
pub fn sibling_prev(&mut self, node: NodeRef) -> Option<NodeRef> {
self.siblings_prev[node.0]
}
pub fn set_sibling_prev(&mut self, this: NodeRef, prev: NodeRef) {
self.siblings_prev[this.0] = Some(prev);
}
pub fn text(&self, node: NodeRef) -> &Text {
&self.texts[node.0]
}
pub fn set_text(&mut self, node: NodeRef, text: Text) {
self.texts[node.0] = text;
}
pub fn display_syntax<'a>(
&'a self,
text: &'a str,
node: NodeRef,
) -> impl Display + 'a {
struct DisplaySyntax<'a> {
nodes: &'a NodeStorage,
node: NodeRef,
text: &'a str,
}
impl Display for DisplaySyntax<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let s = match self.nodes.text(self.node) {
Text::Span(s) => &self.text[s.clone()],
Text::Static(s) => s,
Text::String(s) => s.as_str(),
};
write!(f, "{s}")?;
for child in self.nodes.children(self.node) {
write!(
f,
"{}",
self.nodes.display_syntax(self.text, child)
)?;
}
Ok(())
}
}
DisplaySyntax {
nodes: self,
node,
text,
}
}
}
impl NodeStorage {
pub fn new() -> Self {
Self::default()
}
}