1use crate::{
6 Language,
7 tree::green_tree::{GreenNode, GreenTree},
8};
9use core::range::Range;
10use std::fmt;
11
12pub enum RedTree<'a, L: Language> {
18 Node(RedNode<'a, L>),
20 Leaf(RedLeaf<L>),
22}
23
24impl<'a, L: Language> Clone for RedTree<'a, L> {
26 fn clone(&self) -> Self {
27 *self
28 }
29}
30
31impl<'a, L: Language> Copy for RedTree<'a, L> {}
32
33impl<'a, L: Language> fmt::Debug for RedTree<'a, L> {
34 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
35 match self {
36 Self::Node(node) => fmt::Debug::fmt(node, f),
37 Self::Leaf(leaf) => fmt::Debug::fmt(leaf, f),
38 }
39 }
40}
41
42impl<'a, L: Language> PartialEq for RedTree<'a, L> {
43 fn eq(&self, other: &Self) -> bool {
44 match (self, other) {
45 (Self::Node(l0), Self::Node(r0)) => l0 == r0,
46 (Self::Leaf(l0), Self::Leaf(r0)) => l0 == r0,
47 _ => false,
48 }
49 }
50}
51
52impl<'a, L: Language> Eq for RedTree<'a, L> {}
53
54impl<'a, L: Language> RedTree<'a, L> {
55 #[inline]
59 pub fn span(&self) -> Range<usize> {
60 match self {
61 RedTree::Node(n) => n.span(),
62 RedTree::Leaf(t) => t.span,
63 }
64 }
65
66 pub fn kind<T>(&self) -> T
72 where
73 T: From<L::ElementType> + From<L::TokenType>,
74 {
75 match self {
76 RedTree::Node(n) => T::from(n.green.kind),
77 RedTree::Leaf(l) => T::from(l.kind),
78 }
79 }
80
81 pub fn text<'s, S: crate::source::Source + ?Sized>(&self, source: &'s S) -> std::borrow::Cow<'s, str> {
87 source.get_text_in(self.span())
88 }
89
90 pub fn children(&self) -> RedChildren<'a, L> {
94 match self {
95 RedTree::Node(n) => n.children(),
96 RedTree::Leaf(_) => RedChildren::empty(),
97 }
98 }
99
100 pub fn as_node(&self) -> Option<RedNode<'a, L>> {
102 match self {
103 RedTree::Node(n) => Some(*n),
104 RedTree::Leaf(_) => None,
105 }
106 }
107
108 pub fn as_leaf(&self) -> Option<RedLeaf<L>> {
110 match self {
111 RedTree::Node(_) => None,
112 RedTree::Leaf(l) => Some(*l),
113 }
114 }
115}
116
117pub struct RedNode<'a, L: Language> {
123 pub green: &'a GreenNode<'a, L>,
125 pub offset: usize,
127}
128
129impl<'a, L: Language> Clone for RedNode<'a, L> {
131 fn clone(&self) -> Self {
132 *self
133 }
134}
135
136impl<'a, L: Language> Copy for RedNode<'a, L> {}
137
138impl<'a, L: Language> PartialEq for RedNode<'a, L> {
139 fn eq(&self, other: &Self) -> bool {
140 self.green == other.green && self.offset == other.offset
141 }
142}
143
144impl<'a, L: Language> Eq for RedNode<'a, L> {}
145
146impl<'a, L: Language> fmt::Debug for RedNode<'a, L> {
147 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
148 f.debug_struct("RedNode").field("green", &self.green).field("offset", &self.offset).finish()
149 }
150}
151
152pub struct RedLeaf<L: Language> {
156 pub kind: L::TokenType,
158 pub span: Range<usize>,
160}
161
162impl<L: Language> Clone for RedLeaf<L> {
164 fn clone(&self) -> Self {
165 *self
166 }
167}
168
169impl<L: Language> Copy for RedLeaf<L> {}
170
171impl<L: Language> PartialEq for RedLeaf<L> {
172 fn eq(&self, other: &Self) -> bool {
173 self.kind == other.kind && self.span == other.span
174 }
175}
176
177impl<L: Language> Eq for RedLeaf<L> {}
178
179impl<L: Language> fmt::Debug for RedLeaf<L> {
180 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
181 f.debug_struct("RedLeaf").field("kind", &self.kind).field("span", &self.span).finish()
182 }
183}
184
185pub struct RedChildren<'a, L: Language> {
190 node: Option<RedNode<'a, L>>,
192 index: usize,
194 offset: usize,
196}
197
198impl<'a, L: Language> RedChildren<'a, L> {
199 pub fn empty() -> Self {
201 Self { node: None, index: 0, offset: 0 }
202 }
203}
204
205impl<'a, L: Language> RedNode<'a, L> {
206 #[inline]
208 pub fn new(green: &'a GreenNode<'a, L>, offset: usize) -> Self {
209 Self { green, offset }
210 }
211
212 #[inline]
214 pub fn span(&self) -> Range<usize> {
215 Range { start: self.offset, end: self.offset + self.green.text_len() as usize }
216 }
217
218 #[inline]
220 pub fn element_type(&self) -> L::ElementType {
221 self.green.kind
222 }
223
224 #[inline]
226 pub fn green(&self) -> &'a GreenNode<'a, L> {
227 self.green
228 }
229
230 pub fn kind<T>(&self) -> T
232 where
233 T: From<L::ElementType>,
234 {
235 T::from(self.green.kind)
236 }
237
238 pub fn child_at(&self, idx: usize) -> RedTree<'a, L> {
248 let children = self.green.children();
249 let green_child = &children[idx];
250
251 let mut offset = self.offset;
253 for i in 0..idx {
254 offset += children[i].len() as usize
255 }
256
257 match green_child {
258 GreenTree::Node(n) => RedTree::Node(RedNode::new(n, offset)),
259 GreenTree::Leaf(t) => RedTree::Leaf(RedLeaf { kind: t.kind, span: Range { start: offset, end: offset + t.length as usize } }),
260 }
261 }
262
263 pub fn children(&self) -> RedChildren<'a, L> {
265 RedChildren { node: Some(*self), index: 0, offset: self.offset }
266 }
267
268 pub fn child_index_at_offset(&self, offset: usize) -> Option<usize> {
274 if offset < self.offset || offset >= self.offset + self.green.text_len() as usize {
275 return None;
276 }
277
278 let relative_offset = (offset - self.offset) as u32;
279 let mut current_pos = 0;
280
281 for (idx, child) in self.green.children().iter().enumerate() {
282 let len = child.len();
283 if relative_offset < current_pos + len {
284 return Some(idx);
285 }
286 current_pos += len
287 }
288
289 None
290 }
291
292 pub fn child_at_offset(&self, offset: usize) -> Option<RedTree<'a, L>> {
298 self.child_index_at_offset(offset).map(|idx| self.child_at(idx))
299 }
300
301 pub fn leaf_at_offset(&self, offset: usize) -> Option<RedLeaf<L>> {
309 let mut current = *self;
310 loop {
311 match current.child_at_offset(offset)? {
312 RedTree::Node(n) => current = n,
313 RedTree::Leaf(l) => return Some(l),
314 }
315 }
316 }
317}
318
319impl<'a, L: Language> Iterator for RedChildren<'a, L> {
320 type Item = RedTree<'a, L>;
321
322 fn next(&mut self) -> Option<Self::Item> {
323 let node = self.node.as_ref()?;
324 let children = node.green.children();
325 if self.index >= children.len() {
326 return None;
327 }
328
329 let ch = &children[self.index];
330 let offset = self.offset;
331 let elem = match ch {
332 GreenTree::Node(n) => RedTree::Node(RedNode::new(n, offset)),
333 GreenTree::Leaf(t) => RedTree::Leaf(RedLeaf { kind: t.kind, span: Range { start: offset, end: offset + t.length as usize } }),
334 };
335
336 self.offset += ch.len() as usize;
337 self.index += 1;
338 Some(elem)
339 }
340}