use std::sync::Arc;
use crate::{SmolStr, TextUnit, Types};
#[derive(Debug)]
pub struct GreenNode<T: Types>(GreenNodeImpl<T>);
impl<T: Types> Clone for GreenNode<T> {
fn clone(&self) -> GreenNode<T> {
GreenNode(match &self.0 {
GreenNodeImpl::Leaf { kind, text } => GreenNodeImpl::Leaf {
kind: *kind,
text: text.clone(),
},
GreenNodeImpl::Branch(branch) => GreenNodeImpl::Branch(Arc::clone(branch)),
})
}
}
#[derive(Clone, Copy, Debug)]
pub struct Checkpoint(usize);
#[derive(Debug)]
enum GreenNodeImpl<T: Types> {
Leaf { kind: T::Kind, text: SmolStr },
Branch(Arc<GreenBranch<T>>),
}
#[derive(Debug)]
pub struct GreenNodeBuilder<T: Types> {
parents: Vec<(T::Kind, usize)>,
children: Vec<GreenNode<T>>,
}
impl<T: Types> GreenNodeBuilder<T> {
pub fn new() -> Self {
GreenNodeBuilder {
parents: Vec::new(),
children: Vec::new(),
}
}
pub fn leaf(&mut self, kind: T::Kind, text: SmolStr) {
self.children.push(GreenNode::new_leaf(kind, text));
}
pub fn start_internal(&mut self, kind: T::Kind) {
let len = self.children.len();
self.parents.push((kind, len));
}
pub fn finish_internal(&mut self) {
let (kind, first_child) = self.parents.pop().unwrap();
let children: Vec<_> = self.children.drain(first_child..).collect();
self.children
.push(GreenNode::new_branch(kind, children.into_boxed_slice()));
}
pub fn checkpoint(&self) -> Checkpoint {
Checkpoint(self.children.len())
}
pub fn start_internal_at(&mut self, checkpoint: Checkpoint, kind: T::Kind) {
let Checkpoint(checkpoint) = checkpoint;
assert!(checkpoint <= self.children.len(), "checkpoint no longer valid, was finish_internal called early?");
if let Some(&(_, first_child)) = self.parents.last() {
assert!(checkpoint >= first_child, "checkpoint no longer valid, was an unmatched start_internal called?");
}
self.parents.push((kind, checkpoint));
}
pub fn finish(mut self) -> GreenNode<T> {
assert_eq!(self.children.len(), 1);
self.children.pop().unwrap()
}
}
impl<T: Types> GreenNode<T> {
pub fn new_leaf(kind: T::Kind, text: SmolStr) -> GreenNode<T> {
GreenNode(GreenNodeImpl::Leaf { kind, text })
}
pub fn new_branch(kind: T::Kind, children: Box<[GreenNode<T>]>) -> GreenNode<T> {
GreenNode(GreenNodeImpl::Branch(Arc::new(GreenBranch::new(
kind, children,
))))
}
pub fn kind(&self) -> T::Kind {
match &self.0 {
GreenNodeImpl::Leaf { kind, .. } => *kind,
GreenNodeImpl::Branch(b) => b.kind(),
}
}
pub fn text_len(&self) -> TextUnit {
match &self.0 {
GreenNodeImpl::Leaf { text, .. } => TextUnit::from(text.len() as u32),
GreenNodeImpl::Branch(b) => b.text_len(),
}
}
pub fn children(&self) -> &[GreenNode<T>] {
match &self.0 {
GreenNodeImpl::Leaf { .. } => &[],
GreenNodeImpl::Branch(b) => b.children(),
}
}
pub fn leaf_text(&self) -> Option<&SmolStr> {
match &self.0 {
GreenNodeImpl::Leaf { text, .. } => Some(text),
GreenNodeImpl::Branch(_) => None,
}
}
}
#[derive(Debug)]
struct GreenBranch<T: Types> {
text_len: TextUnit,
kind: T::Kind,
children: Box<[GreenNode<T>]>,
}
impl<T: Types> GreenBranch<T> {
fn new(kind: T::Kind, children: Box<[GreenNode<T>]>) -> GreenBranch<T> {
let text_len = children.iter().map(|x| x.text_len()).sum::<TextUnit>();
GreenBranch {
text_len,
kind,
children,
}
}
fn kind(&self) -> T::Kind {
self.kind
}
fn text_len(&self) -> TextUnit {
self.text_len
}
fn children(&self) -> &[GreenNode<T>] {
&*self.children
}
}