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> {
14 Node(RedNode<'a, L>),
16 Leaf(RedLeaf<L>),
18}
19
20impl<'a, L: Language> Clone for RedTree<'a, L> {
22 fn clone(&self) -> Self {
23 *self
24 }
25}
26
27impl<'a, L: Language> Copy for RedTree<'a, L> {}
28
29impl<'a, L: Language> fmt::Debug for RedTree<'a, L> {
30 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31 match self {
32 Self::Node(node) => fmt::Debug::fmt(node, f),
33 Self::Leaf(leaf) => fmt::Debug::fmt(leaf, f),
34 }
35 }
36}
37
38impl<'a, L: Language> PartialEq for RedTree<'a, L> {
39 fn eq(&self, other: &Self) -> bool {
40 match (self, other) {
41 (Self::Node(l0), Self::Node(r0)) => l0 == r0,
42 (Self::Leaf(l0), Self::Leaf(r0)) => l0 == r0,
43 _ => false,
44 }
45 }
46}
47
48impl<'a, L: Language> Eq for RedTree<'a, L> {}
49
50impl<'a, L: Language> RedTree<'a, L> {
51 #[inline]
53 pub fn span(&self) -> Range<usize> {
54 match self {
55 RedTree::Node(n) => n.span(),
56 RedTree::Leaf(t) => t.span,
57 }
58 }
59}
60
61pub struct RedNode<'a, L: Language> {
63 pub green: &'a GreenNode<'a, L>,
65 pub offset: usize,
67}
68
69impl<'a, L: Language> Clone for RedNode<'a, L> {
71 fn clone(&self) -> Self {
72 *self
73 }
74}
75
76impl<'a, L: Language> Copy for RedNode<'a, L> {}
77
78impl<'a, L: Language> PartialEq for RedNode<'a, L> {
79 fn eq(&self, other: &Self) -> bool {
80 self.green == other.green && self.offset == other.offset
81 }
82}
83
84impl<'a, L: Language> Eq for RedNode<'a, L> {}
85
86impl<'a, L: Language> fmt::Debug for RedNode<'a, L> {
87 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
88 f.debug_struct("RedNode").field("green", &self.green).field("offset", &self.offset).finish()
89 }
90}
91
92pub struct RedLeaf<L: Language> {
94 pub kind: L::TokenType,
96 pub span: Range<usize>,
98}
99
100impl<L: Language> Clone for RedLeaf<L> {
102 fn clone(&self) -> Self {
103 *self
104 }
105}
106
107impl<L: Language> Copy for RedLeaf<L> {}
108
109impl<L: Language> PartialEq for RedLeaf<L> {
110 fn eq(&self, other: &Self) -> bool {
111 self.kind == other.kind && self.span == other.span
112 }
113}
114
115impl<L: Language> Eq for RedLeaf<L> {}
116
117impl<L: Language> fmt::Debug for RedLeaf<L> {
118 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
119 f.debug_struct("RedLeaf").field("kind", &self.kind).field("span", &self.span).finish()
120 }
121}
122
123impl<'a, L: Language> RedNode<'a, L> {
124 #[inline]
126 pub fn new(green: &'a GreenNode<'a, L>, offset: usize) -> Self {
127 Self { green, offset }
128 }
129
130 #[inline]
132 pub fn span(&self) -> Range<usize> {
133 Range { start: self.offset, end: self.offset + self.green.text_len() as usize }
134 }
135
136 pub fn child_at(&self, idx: usize) -> RedTree<'a, L> {
138 let children = self.green.children();
139 let green_child = &children[idx];
140
141 let mut offset = self.offset;
143 for i in 0..idx {
144 offset += children[i].len() as usize;
145 }
146
147 match green_child {
148 GreenTree::Node(n) => RedTree::Node(RedNode::new(n, offset)),
149 GreenTree::Leaf(t) => RedTree::Leaf(RedLeaf { kind: t.kind, span: Range { start: offset, end: offset + t.length as usize } }),
150 }
151 }
152
153 pub fn children(&self) -> RedChildren<'a, L> {
155 RedChildren { node: *self, index: 0, offset: self.offset }
156 }
157
158 pub fn child_index_at_offset(&self, offset: usize) -> Option<usize> {
160 if offset < self.offset || offset >= self.offset + self.green.text_len() as usize {
161 return None;
162 }
163
164 let relative_offset = (offset - self.offset) as u32;
165 let mut current_pos = 0;
166
167 for (idx, child) in self.green.children().iter().enumerate() {
168 let len = child.len();
169 if relative_offset < current_pos + len {
170 return Some(idx);
171 }
172 current_pos += len;
173 }
174
175 None
176 }
177
178 pub fn child_at_offset(&self, offset: usize) -> Option<RedTree<'a, L>> {
180 self.child_index_at_offset(offset).map(|idx| self.child_at(idx))
181 }
182}
183
184pub struct RedChildren<'a, L: Language> {
186 node: RedNode<'a, L>,
187 index: usize,
188 offset: usize,
189}
190
191impl<'a, L: Language> Iterator for RedChildren<'a, L> {
192 type Item = RedTree<'a, L>;
193
194 fn next(&mut self) -> Option<Self::Item> {
195 let children = self.node.green.children();
196 if self.index >= children.len() {
197 return None;
198 }
199
200 let ch = &children[self.index];
201 let offset = self.offset;
202 let elem = match ch {
203 GreenTree::Node(n) => RedTree::Node(RedNode::new(n, offset)),
204 GreenTree::Leaf(t) => RedTree::Leaf(RedLeaf { kind: t.kind, span: Range { start: offset, end: offset + t.length as usize } }),
205 };
206
207 self.offset += ch.len() as usize;
208 self.index += 1;
209 Some(elem)
210 }
211}