use crate::Language;
use std::{
fmt,
hash::{Hash, Hasher},
};
pub enum GreenTree<'a, L: Language> {
Node(&'a GreenNode<'a, L>),
Leaf(GreenLeaf<L>),
}
impl<'a, L: Language> Clone for GreenTree<'a, L> {
fn clone(&self) -> Self {
*self
}
}
impl<'a, L: Language> Copy for GreenTree<'a, L> {}
impl<'a, L: Language> fmt::Debug for GreenTree<'a, L> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Node(node) => fmt::Debug::fmt(node, f),
Self::Leaf(leaf) => fmt::Debug::fmt(leaf, f),
}
}
}
impl<'a, L: Language> PartialEq for GreenTree<'a, L> {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Self::Node(l0), Self::Node(r0)) => l0 == r0,
(Self::Leaf(l0), Self::Leaf(r0)) => l0 == r0,
_ => false,
}
}
}
impl<'a, L: Language> Eq for GreenTree<'a, L> {}
impl<'a, L: Language> Hash for GreenTree<'a, L> {
fn hash<H: Hasher>(&self, state: &mut H) {
match self {
Self::Node(node) => node.hash(state),
Self::Leaf(leaf) => leaf.hash(state),
}
}
}
impl<'a, L: Language> GreenTree<'a, L> {
#[inline]
pub fn len(&self) -> u32 {
match self {
GreenTree::Node(n) => n.byte_length,
GreenTree::Leaf(t) => t.length,
}
}
#[inline]
pub fn is_node(&self) -> bool {
matches!(self, Self::Node(_))
}
#[inline]
pub fn is_leaf(&self) -> bool {
matches!(self, Self::Leaf(_))
}
#[inline]
pub fn as_node(&self) -> Option<&'a GreenNode<'a, L>> {
match self {
Self::Node(n) => Some(n),
_ => None,
}
}
#[inline]
pub fn as_leaf(&self) -> Option<GreenLeaf<L>> {
match self {
Self::Leaf(l) => Some(*l),
_ => None,
}
}
}
pub struct GreenLeaf<L: Language> {
pub kind: L::TokenType,
pub length: u32,
pub metadata: Option<std::num::NonZeroU32>,
}
impl<L: Language> fmt::Debug for GreenLeaf<L> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("GreenLeaf").field("kind", &self.kind).field("length", &self.length).field("metadata", &self.metadata).finish()
}
}
impl<L: Language> Hash for GreenLeaf<L> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.kind.hash(state);
self.length.hash(state);
self.metadata.hash(state)
}
}
impl<L: Language> Clone for GreenLeaf<L> {
fn clone(&self) -> Self {
*self
}
}
impl<L: Language> Copy for GreenLeaf<L> {}
impl<L: Language> PartialEq for GreenLeaf<L> {
fn eq(&self, other: &Self) -> bool {
self.kind == other.kind && self.length == other.length && self.metadata == other.metadata
}
}
impl<L: Language> Eq for GreenLeaf<L> {}
impl<L: Language> GreenLeaf<L> {
#[inline]
pub fn new(kind: L::TokenType, len: u32) -> Self {
Self { kind, length: len, metadata: None }
}
#[inline]
pub fn with_metadata(kind: L::TokenType, len: u32, metadata: Option<std::num::NonZeroU32>) -> Self {
Self { kind, length: len, metadata }
}
#[inline]
pub fn kind(&self) -> L::TokenType {
self.kind
}
#[inline]
pub fn length(&self) -> u32 {
self.length
}
}
pub struct GreenNode<'a, L: Language> {
pub kind: L::ElementType,
pub children: &'a [GreenTree<'a, L>],
pub byte_length: u32,
}
impl<'a, L: Language> Clone for GreenNode<'a, L> {
fn clone(&self) -> Self {
Self { kind: self.kind, byte_length: self.byte_length, children: self.children }
}
}
impl<'a, L: Language> PartialEq for GreenNode<'a, L> {
fn eq(&self, other: &Self) -> bool {
self.kind == other.kind && self.byte_length == other.byte_length && self.children == other.children
}
}
impl<'a, L: Language> Eq for GreenNode<'a, L> {}
impl<'a, L: Language> fmt::Debug for GreenNode<'a, L> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("GreenNode").field("kind", &self.kind).field("children", &self.children).field("length", &self.byte_length).finish()
}
}
impl<'a, L: Language> Hash for GreenNode<'a, L> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.kind.hash(state);
self.children.hash(state)
}
}
impl<'a, L: Language> GreenNode<'a, L> {
pub fn new(kind: L::ElementType, children: &'a [GreenTree<'a, L>]) -> Self {
let len: u32 = children.iter().map(|c| c.len()).sum();
Self { kind, byte_length: len, children }
}
#[inline]
pub fn kind(&self) -> L::ElementType {
self.kind
}
#[inline]
pub fn text_len(&self) -> u32 {
self.byte_length
}
#[inline]
pub fn children(&self) -> &'a [GreenTree<'a, L>] {
self.children
}
#[inline]
pub fn child_at(&self, index: usize) -> Option<&'a GreenTree<'a, L>> {
self.children.get(index)
}
#[inline]
pub fn has_children(&self) -> bool {
!self.children.is_empty()
}
#[inline]
pub fn children_count(&self) -> usize {
self.children.len()
}
}