tree_house_bindings/
node.rs1use std::ffi::{c_char, c_void, CStr};
2use std::fmt;
3use std::marker::PhantomData;
4use std::ops::Range;
5use std::ptr::NonNull;
6
7use crate::tree::Tree;
8use crate::tree_cursor::TreeCursor;
9use crate::Grammar;
10
11#[repr(C)]
12#[derive(Debug, Clone, Copy)]
13pub(super) struct NodeRaw {
14 context: [u32; 4],
15 id: *const c_void,
16 tree: *const c_void,
17}
18
19impl From<Node<'_>> for NodeRaw {
20 fn from(node: Node) -> NodeRaw {
21 NodeRaw {
22 context: node.context,
23 id: node.id.as_ptr(),
24 tree: node.tree.as_ptr(),
25 }
26 }
27}
28
29#[derive(Clone)]
30#[repr(C)]
31pub struct Node<'tree> {
32 context: [u32; 4],
33 id: NonNull<c_void>,
34 tree: NonNull<c_void>,
35 _phantom: PhantomData<&'tree Tree>,
36}
37
38impl fmt::Debug for Node<'_> {
39 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
40 let range = self.byte_range();
41 write!(f, "{{Node {} {range:?}}}", self.kind())
42 }
43}
44
45impl<'tree> Node<'tree> {
46 #[inline]
47 pub(super) unsafe fn from_raw(raw: NodeRaw) -> Option<Self> {
48 Some(Node {
49 context: raw.context,
50 id: NonNull::new(raw.id as *mut _)?,
51 tree: unsafe { NonNull::new_unchecked(raw.tree as *mut _) },
52 _phantom: PhantomData,
53 })
54 }
55
56 #[inline]
57 pub(crate) fn as_raw(&self) -> NodeRaw {
58 NodeRaw {
59 context: self.context,
60 id: self.id.as_ptr(),
61 tree: self.tree.as_ptr(),
62 }
63 }
64
65 pub fn id(&self) -> usize {
66 self.id.as_ptr() as usize
67 }
68
69 #[inline]
71 pub fn kind(&self) -> &'tree str {
72 unsafe { CStr::from_ptr(ts_node_type(self.as_raw())) }
73 .to_str()
74 .unwrap()
75 }
76
77 #[inline]
79 pub fn kind_id(&self) -> u16 {
80 unsafe { ts_node_symbol(self.as_raw()) }
81 }
82
83 #[inline]
85 pub fn grammar(&self) -> Grammar {
86 unsafe { ts_node_language(self.as_raw()) }
87 }
88
89 #[inline]
94 pub fn is_named(&self) -> bool {
95 unsafe { ts_node_is_named(self.as_raw()) }
96 }
97
98 pub fn is_contained_within(&self, range: Range<u32>) -> bool {
102 (self.start_byte() > range.start && self.end_byte() <= range.end)
103 || (self.start_byte() >= range.start && self.end_byte() < range.end)
104 }
105
106 #[inline]
111 pub fn is_missing(&self) -> bool {
112 unsafe { ts_node_is_missing(self.as_raw()) }
113 }
114
115 #[inline]
120 pub fn is_extra(&self) -> bool {
121 unsafe { ts_node_is_extra(self.as_raw()) }
122 }
123
124 #[inline(always)]
126 pub fn start_byte(&self) -> u32 {
127 self.context[0]
140 }
141
142 #[inline]
144 pub fn end_byte(&self) -> u32 {
145 unsafe { ts_node_end_byte(self.as_raw()) }
146 }
147
148 #[inline]
150 pub fn byte_range(&self) -> Range<u32> {
151 self.start_byte()..self.end_byte()
152 }
153
154 #[inline]
161 pub fn child(&self, i: u32) -> Option<Node<'tree>> {
162 unsafe { Node::from_raw(ts_node_child(self.as_raw(), i)) }
163 }
164
165 #[inline]
167 pub fn child_count(&self) -> u32 {
168 unsafe { ts_node_child_count(self.as_raw()) }
169 }
170
171 #[inline]
178 pub fn named_child(&self, i: u32) -> Option<Node<'tree>> {
179 unsafe { Node::from_raw(ts_node_named_child(self.as_raw(), i)) }
180 }
181
182 #[inline]
186 pub fn named_child_count(&self) -> u32 {
187 unsafe { ts_node_named_child_count(self.as_raw()) }
188 }
189
190 #[inline]
191 unsafe fn map(&self, f: unsafe extern "C" fn(NodeRaw) -> NodeRaw) -> Option<Node<'tree>> {
192 Node::from_raw(f(self.as_raw()))
193 }
194
195 #[inline]
197 pub fn parent(&self) -> Option<Self> {
198 unsafe { self.map(ts_node_parent) }
199 }
200
201 #[inline]
203 pub fn next_sibling(&self) -> Option<Self> {
204 unsafe { self.map(ts_node_next_sibling) }
205 }
206
207 #[inline]
209 pub fn prev_sibling(&self) -> Option<Self> {
210 unsafe { self.map(ts_node_prev_sibling) }
211 }
212
213 #[inline]
215 pub fn next_named_sibling(&self) -> Option<Self> {
216 unsafe { self.map(ts_node_next_named_sibling) }
217 }
218
219 #[inline]
221 pub fn prev_named_sibling(&self) -> Option<Self> {
222 unsafe { self.map(ts_node_prev_named_sibling) }
223 }
224
225 #[inline]
227 pub fn descendant_for_byte_range(&self, start: u32, end: u32) -> Option<Self> {
228 unsafe { Self::from_raw(ts_node_descendant_for_byte_range(self.as_raw(), start, end)) }
229 }
230
231 #[inline]
233 pub fn named_descendant_for_byte_range(&self, start: u32, end: u32) -> Option<Self> {
234 unsafe {
235 Self::from_raw(ts_node_named_descendant_for_byte_range(
236 self.as_raw(),
237 start,
238 end,
239 ))
240 }
241 }
242
243 pub fn children(&self) -> impl ExactSizeIterator<Item = Node<'tree>> {
253 let mut cursor = TreeCursor::new(self);
254 cursor.goto_first_child();
255 (0..self.child_count()).map(move |_| {
256 let result = cursor.node();
257 cursor.goto_next_sibling();
258 result
259 })
260 }
261
262 pub fn walk(&self) -> TreeCursor<'tree> {
263 TreeCursor::new(self)
264 }
265}
266
267impl PartialEq for Node<'_> {
268 fn eq(&self, other: &Self) -> bool {
269 self.id == other.id
270 }
271}
272
273impl Eq for Node<'_> {}
274
275unsafe impl Send for Node<'_> {}
276unsafe impl Sync for Node<'_> {}
277
278extern "C" {
279 fn ts_node_type(node: NodeRaw) -> *const c_char;
281
282 fn ts_node_symbol(node: NodeRaw) -> u16;
284
285 fn ts_node_language(node: NodeRaw) -> Grammar;
287
288 fn ts_node_is_named(node: NodeRaw) -> bool;
292
293 fn ts_node_is_missing(node: NodeRaw) -> bool;
296
297 fn ts_node_is_extra(node: NodeRaw) -> bool;
302
303 fn ts_node_parent(node: NodeRaw) -> NodeRaw;
305
306 fn ts_node_child(node: NodeRaw, child_index: u32) -> NodeRaw;
309
310 fn ts_node_child_count(node: NodeRaw) -> u32;
312
313 fn ts_node_named_child(node: NodeRaw, child_index: u32) -> NodeRaw;
316
317 fn ts_node_named_child_count(node: NodeRaw) -> u32;
319
320 fn ts_node_next_sibling(node: NodeRaw) -> NodeRaw;
322
323 fn ts_node_prev_sibling(node: NodeRaw) -> NodeRaw;
324
325 fn ts_node_next_named_sibling(node: NodeRaw) -> NodeRaw;
327
328 fn ts_node_prev_named_sibling(node: NodeRaw) -> NodeRaw;
329
330 fn ts_node_descendant_for_byte_range(node: NodeRaw, start: u32, end: u32) -> NodeRaw;
333
334 fn ts_node_named_descendant_for_byte_range(node: NodeRaw, start: u32, end: u32) -> NodeRaw;
337
338 fn ts_node_end_byte(node: NodeRaw) -> u32;
340}