1use alloc::{
2 borrow::{Cow, ToOwned},
3 vec::Vec,
4};
5use core::{
6 borrow::Borrow,
7 fmt,
8 iter::{self, FusedIterator},
9 mem::{self, ManuallyDrop},
10 ops, ptr, slice,
11};
12
13use crate::{
14 GreenToken, NodeOrToken, TextRange, TextSize,
15 arc::{Arc, HeaderSlice, ThinArc},
16 countme::Count,
17 green::{GreenElement, GreenElementRef, SyntaxKind},
18};
19
20#[derive(Debug, Clone, PartialEq, Eq, Hash)]
21pub(super) struct GreenNodeHead {
22 kind: SyntaxKind,
23 text_len: TextSize,
24 _c: Count<GreenNode>,
25}
26
27#[derive(Debug, Clone, PartialEq, Eq, Hash)]
28#[repr(u8)]
29pub(crate) enum GreenChild {
30 Node { rel_offset: TextSize, node: GreenNode },
31 Token { rel_offset: TextSize, token: GreenToken },
32}
33
34type Repr = HeaderSlice<GreenNodeHead, [GreenChild]>;
35type ReprThin = HeaderSlice<GreenNodeHead, [GreenChild; 0]>;
36#[repr(transparent)]
37pub struct GreenNodeData {
38 data: ReprThin,
39}
40
41impl PartialEq for GreenNodeData {
42 fn eq(&self, other: &Self) -> bool {
43 self.header() == other.header() && self.slice() == other.slice()
44 }
45}
46
47#[derive(Clone, PartialEq, Eq, Hash)]
50#[repr(transparent)]
51pub struct GreenNode {
52 ptr: ThinArc<GreenNodeHead, GreenChild>,
53}
54
55impl ToOwned for GreenNodeData {
56 type Owned = GreenNode;
57
58 #[inline]
59 fn to_owned(&self) -> GreenNode {
60 let green = unsafe { GreenNode::from_raw(ptr::NonNull::from(self)) };
61 let green = ManuallyDrop::new(green);
62 GreenNode::clone(&green)
63 }
64}
65
66impl Borrow<GreenNodeData> for GreenNode {
67 #[inline]
68 fn borrow(&self) -> &GreenNodeData {
69 self
70 }
71}
72
73impl From<Cow<'_, GreenNodeData>> for GreenNode {
74 #[inline]
75 fn from(cow: Cow<'_, GreenNodeData>) -> Self {
76 cow.into_owned()
77 }
78}
79
80impl fmt::Debug for GreenNodeData {
81 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82 f.debug_struct("GreenNode")
83 .field("kind", &self.kind())
84 .field("text_len", &self.text_len())
85 .field("n_children", &self.children().len())
86 .finish()
87 }
88}
89
90impl fmt::Debug for GreenNode {
91 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
92 let data: &GreenNodeData = self;
93 fmt::Debug::fmt(data, f)
94 }
95}
96
97impl fmt::Display for GreenNode {
98 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
99 let data: &GreenNodeData = self;
100 fmt::Display::fmt(data, f)
101 }
102}
103
104impl fmt::Display for GreenNodeData {
105 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
106 for child in self.children() {
107 write!(f, "{}", child)?;
108 }
109 Ok(())
110 }
111}
112
113impl GreenNodeData {
114 #[inline]
115 fn header(&self) -> &GreenNodeHead {
116 &self.data.header
117 }
118
119 #[inline]
120 fn slice(&self) -> &[GreenChild] {
121 self.data.slice()
122 }
123
124 #[inline]
126 pub fn kind(&self) -> SyntaxKind {
127 self.header().kind
128 }
129
130 #[inline]
132 pub fn text_len(&self) -> TextSize {
133 self.header().text_len
134 }
135
136 #[inline]
138 pub fn children(&self) -> Children<'_> {
139 Children { raw: self.slice().iter() }
140 }
141
142 pub(crate) fn child_at_range(
143 &self,
144 rel_range: TextRange,
145 ) -> Option<(usize, TextSize, GreenElementRef<'_>)> {
146 let idx = self
147 .slice()
148 .binary_search_by(|it| {
149 let child_range = it.rel_range();
150 TextRange::ordering(child_range, rel_range)
151 })
152 .unwrap_or_else(|it| it.saturating_sub(1));
154 let child = &self.slice().get(idx).filter(|it| it.rel_range().contains_range(rel_range))?;
155 Some((idx, child.rel_offset(), child.as_ref()))
156 }
157
158 #[must_use]
159 pub fn replace_child(&self, index: usize, new_child: GreenElement) -> GreenNode {
160 let mut replacement = Some(new_child);
161 let children = self.children().enumerate().map(|(i, child)| {
162 if i == index { replacement.take().unwrap() } else { child.to_owned() }
163 });
164 GreenNode::new(self.kind(), children)
165 }
166 #[must_use]
167 pub fn insert_child(&self, index: usize, new_child: GreenElement) -> GreenNode {
168 self.splice_children(index..index, iter::once(new_child))
170 }
171 #[must_use]
172 pub fn remove_child(&self, index: usize) -> GreenNode {
173 self.splice_children(index..=index, iter::empty())
174 }
175 #[must_use]
176 pub fn splice_children<R, I>(&self, range: R, replace_with: I) -> GreenNode
177 where
178 R: ops::RangeBounds<usize>,
179 I: IntoIterator<Item = GreenElement>,
180 {
181 let mut children: Vec<_> = self.children().map(|it| it.to_owned()).collect();
182 children.splice(range, replace_with);
183 GreenNode::new(self.kind(), children)
184 }
185}
186
187impl ops::Deref for GreenNode {
188 type Target = GreenNodeData;
189
190 #[inline]
191 fn deref(&self) -> &GreenNodeData {
192 let repr: &Repr = &self.ptr;
193 unsafe {
194 let repr: &ReprThin = &*(repr as *const Repr as *const ReprThin);
195 mem::transmute::<&ReprThin, &GreenNodeData>(repr)
196 }
197 }
198}
199
200impl GreenNode {
201 #[inline]
203 pub fn new<I>(kind: SyntaxKind, children: I) -> GreenNode
204 where
205 I: IntoIterator<Item = GreenElement>,
206 I::IntoIter: ExactSizeIterator,
207 {
208 let mut text_len: TextSize = 0.into();
209 let children = children.into_iter().map(|el| {
210 let rel_offset = text_len;
211 text_len += el.text_len();
212 match el {
213 NodeOrToken::Node(node) => GreenChild::Node { rel_offset, node },
214 NodeOrToken::Token(token) => GreenChild::Token { rel_offset, token },
215 }
216 });
217
218 let data = ThinArc::from_header_and_iter(
219 GreenNodeHead { kind, text_len: 0.into(), _c: Count::new() },
220 children,
221 );
222
223 let data = {
226 let mut data = Arc::from_thin(data);
227 Arc::get_mut(&mut data).unwrap().header.text_len = text_len;
228 Arc::into_thin(data)
229 };
230
231 GreenNode { ptr: data }
232 }
233
234 #[inline]
235 pub(crate) fn into_raw(this: GreenNode) -> ptr::NonNull<GreenNodeData> {
236 let green = ManuallyDrop::new(this);
237 let green: &GreenNodeData = &green;
238 ptr::NonNull::from(green)
239 }
240
241 #[inline]
242 pub(crate) unsafe fn from_raw(ptr: ptr::NonNull<GreenNodeData>) -> GreenNode {
243 unsafe {
244 let arc = Arc::from_raw(&ptr.as_ref().data as *const ReprThin);
245 let arc = mem::transmute::<Arc<ReprThin>, ThinArc<GreenNodeHead, GreenChild>>(arc);
246 GreenNode { ptr: arc }
247 }
248 }
249}
250
251impl GreenChild {
252 #[inline]
253 pub(crate) fn as_ref(&self) -> GreenElementRef<'_> {
254 match self {
255 GreenChild::Node { node, .. } => NodeOrToken::Node(node),
256 GreenChild::Token { token, .. } => NodeOrToken::Token(token),
257 }
258 }
259 #[inline]
260 pub(crate) fn rel_offset(&self) -> TextSize {
261 match self {
262 GreenChild::Node { rel_offset, .. } | GreenChild::Token { rel_offset, .. } => {
263 *rel_offset
264 }
265 }
266 }
267 #[inline]
268 fn rel_range(&self) -> TextRange {
269 let len = self.as_ref().text_len();
270 TextRange::at(self.rel_offset(), len)
271 }
272}
273
274#[derive(Debug, Clone)]
275pub struct Children<'a> {
276 pub(crate) raw: slice::Iter<'a, GreenChild>,
277}
278
279impl ExactSizeIterator for Children<'_> {
281 #[inline(always)]
282 fn len(&self) -> usize {
283 self.raw.len()
284 }
285}
286
287impl<'a> Iterator for Children<'a> {
288 type Item = GreenElementRef<'a>;
289
290 #[inline]
291 fn next(&mut self) -> Option<GreenElementRef<'a>> {
292 self.raw.next().map(GreenChild::as_ref)
293 }
294
295 #[inline]
296 fn size_hint(&self) -> (usize, Option<usize>) {
297 self.raw.size_hint()
298 }
299
300 #[inline]
301 fn count(self) -> usize
302 where
303 Self: Sized,
304 {
305 self.raw.count()
306 }
307
308 #[inline]
309 fn nth(&mut self, n: usize) -> Option<Self::Item> {
310 self.raw.nth(n).map(GreenChild::as_ref)
311 }
312
313 #[inline]
314 fn last(mut self) -> Option<Self::Item>
315 where
316 Self: Sized,
317 {
318 self.next_back()
319 }
320
321 #[inline]
322 fn fold<Acc, Fold>(self, init: Acc, mut f: Fold) -> Acc
323 where
324 Fold: FnMut(Acc, Self::Item) -> Acc,
325 {
326 let mut accum = init;
327 for x in self {
328 accum = f(accum, x);
329 }
330 accum
331 }
332}
333
334impl DoubleEndedIterator for Children<'_> {
335 #[inline]
336 fn next_back(&mut self) -> Option<Self::Item> {
337 self.raw.next_back().map(GreenChild::as_ref)
338 }
339
340 #[inline]
341 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
342 self.raw.nth_back(n).map(GreenChild::as_ref)
343 }
344
345 #[inline]
346 fn rfold<Acc, Fold>(mut self, init: Acc, mut f: Fold) -> Acc
347 where
348 Fold: FnMut(Acc, Self::Item) -> Acc,
349 {
350 let mut accum = init;
351 while let Some(x) = self.next_back() {
352 accum = f(accum, x);
353 }
354 accum
355 }
356}
357
358impl FusedIterator for Children<'_> {}
359
360#[cfg(test)]
361mod test {
362
363 #[test]
364 #[cfg(target_pointer_width = "64")]
365 fn check_green_child_size() {
366 use super::GreenChild;
367 use core::mem;
368
369 assert_eq!(mem::size_of::<GreenChild>(), mem::size_of::<usize>() * 2);
370 }
371}