use crate::cst::syntax::SyntaxKind;
use crate::prelude::*;
#[derive(Debug, Clone)]
pub enum GreenChild {
Node(GreenNode),
Token {
kind: SyntaxKind,
len: u32,
},
}
impl GreenChild {
#[must_use]
pub fn text_len(&self) -> usize {
match self {
Self::Node(n) => n.text_len(),
Self::Token { len, .. } => *len as usize,
}
}
#[must_use]
pub fn token_text<'s>(&self, source: &'s str, offset: usize) -> Option<&'s str> {
match self {
Self::Token { len, .. } => Some(&source[offset..offset + *len as usize]),
Self::Node(_) => None,
}
}
pub(crate) fn write_text(&self, out: &mut String, source: &str, offset: usize) -> usize {
match self {
Self::Node(n) => n.write_text(out, source, offset),
Self::Token { len, .. } => {
let l = *len as usize;
out.push_str(&source[offset..offset + l]);
offset + l
}
}
}
}
#[derive(Debug, Clone)]
pub struct GreenNode {
kind: SyntaxKind,
text_len: u32,
children: Arc<[GreenChild]>,
}
impl GreenNode {
#[must_use]
pub fn new(kind: SyntaxKind, children: Vec<GreenChild>) -> Self {
let text_len: usize = children.iter().map(GreenChild::text_len).sum();
let text_len = u32::try_from(text_len)
.expect("YAML document exceeds 4 GiB — parser cap should have rejected this earlier");
Self {
kind,
text_len,
children: Arc::from(children),
}
}
#[must_use]
pub fn kind(&self) -> SyntaxKind {
self.kind
}
#[must_use]
pub fn text_len(&self) -> usize {
self.text_len as usize
}
pub fn children(&self) -> impl Iterator<Item = &GreenChild> {
self.children.iter()
}
#[must_use]
pub fn text(&self, source: &str) -> String {
let mut out = String::with_capacity(self.text_len as usize);
let _ = self.write_text(&mut out, source, 0);
out
}
pub(crate) fn write_text(&self, out: &mut String, source: &str, offset: usize) -> usize {
let mut pos = offset;
for child in self.children.iter() {
pos = child.write_text(out, source, pos);
}
pos
}
}