Skip to main content

rslint_rowan/green/
node.rs

1use std::{iter::FusedIterator, slice, sync::Arc};
2
3use erasable::Thin;
4use slice_dst::SliceWithHeader;
5
6use crate::{
7    green::{GreenElement, GreenElementRef, PackedGreenElement, SyntaxKind},
8    TextSize,
9};
10
11#[repr(align(2))] // NB: this is an at-least annotation
12#[derive(Debug, Clone, PartialEq, Eq, Hash)]
13pub(super) struct GreenNodeHead {
14    kind: SyntaxKind,
15    text_len: TextSize,
16}
17
18/// Internal node in the immutable tree.
19/// It has other nodes and tokens as children.
20#[derive(Debug, Clone, PartialEq, Eq, Hash)]
21#[repr(transparent)]
22pub struct GreenNode {
23    pub(super) data: Thin<Arc<SliceWithHeader<GreenNodeHead, PackedGreenElement>>>,
24}
25
26impl GreenNode {
27    /// Creates new Node.
28    #[inline]
29    pub fn new<I>(kind: SyntaxKind, children: I) -> GreenNode
30    where
31        I: IntoIterator<Item = GreenElement>,
32        I::IntoIter: ExactSizeIterator,
33    {
34        let mut text_len: TextSize = 0.into();
35        let children = children
36            .into_iter()
37            .inspect(|it| text_len += it.text_len())
38            .map(PackedGreenElement::from);
39        let mut data: Arc<_> =
40            SliceWithHeader::new(GreenNodeHead { kind, text_len: 0.into() }, children);
41
42        // XXX: fixup `text_len` after construction, because we can't iterate
43        // `children` twice.
44        Arc::get_mut(&mut data).unwrap().header.text_len = text_len;
45
46        GreenNode { data: data.into() }
47    }
48
49    /// Kind of this node.
50    #[inline]
51    pub fn kind(&self) -> SyntaxKind {
52        self.data.header.kind
53    }
54
55    /// Returns the length of the text covered by this node.
56    #[inline]
57    pub fn text_len(&self) -> TextSize {
58        self.data.header.text_len
59    }
60
61    /// Children of this node.
62    #[inline]
63    pub fn children(&self) -> Children<'_> {
64        Children { inner: self.data.slice.iter() }
65    }
66
67    pub(crate) fn ptr(&self) -> *const u8 {
68        let r: &SliceWithHeader<_, _> = &*self.data;
69        r as *const _ as _
70    }
71}
72
73#[derive(Debug, Clone)]
74pub struct Children<'a> {
75    inner: slice::Iter<'a, PackedGreenElement>,
76}
77
78// NB: forward everything stable that iter::Slice specializes as of Rust 1.39.0
79impl ExactSizeIterator for Children<'_> {
80    #[inline(always)]
81    fn len(&self) -> usize {
82        self.inner.len()
83    }
84}
85
86impl<'a> Iterator for Children<'a> {
87    type Item = GreenElementRef<'a>;
88
89    #[inline]
90    fn next(&mut self) -> Option<GreenElementRef<'a>> {
91        self.inner.next().map(PackedGreenElement::as_ref)
92    }
93
94    #[inline]
95    fn size_hint(&self) -> (usize, Option<usize>) {
96        self.inner.size_hint()
97    }
98
99    #[inline]
100    fn count(self) -> usize
101    where
102        Self: Sized,
103    {
104        self.inner.count()
105    }
106
107    #[inline]
108    fn nth(&mut self, n: usize) -> Option<Self::Item> {
109        self.inner.nth(n).map(PackedGreenElement::as_ref)
110    }
111
112    #[inline]
113    fn last(mut self) -> Option<Self::Item>
114    where
115        Self: Sized,
116    {
117        self.next_back()
118    }
119
120    #[inline]
121    fn fold<Acc, Fold>(mut self, init: Acc, mut f: Fold) -> Acc
122    where
123        Fold: FnMut(Acc, Self::Item) -> Acc,
124    {
125        let mut accum = init;
126        while let Some(x) = self.next() {
127            accum = f(accum, x);
128        }
129        accum
130    }
131}
132
133impl<'a> DoubleEndedIterator for Children<'a> {
134    #[inline]
135    fn next_back(&mut self) -> Option<Self::Item> {
136        self.inner.next_back().map(PackedGreenElement::as_ref)
137    }
138
139    #[inline]
140    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
141        self.inner.nth_back(n).map(PackedGreenElement::as_ref)
142    }
143
144    #[inline]
145    fn rfold<Acc, Fold>(mut self, init: Acc, mut f: Fold) -> Acc
146    where
147        Fold: FnMut(Acc, Self::Item) -> Acc,
148    {
149        let mut accum = init;
150        while let Some(x) = self.next_back() {
151            accum = f(accum, x);
152        }
153        accum
154    }
155}
156
157impl FusedIterator for Children<'_> {}