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 #[inline]
103 pub fn is_missing(&self) -> bool {
104 unsafe { ts_node_is_missing(self.as_raw()) }
105 }
106
107 #[inline(always)]
109 pub fn start_byte(&self) -> u32 {
110 self.context[0]
123 }
124
125 #[inline]
127 pub fn end_byte(&self) -> u32 {
128 unsafe { ts_node_end_byte(self.as_raw()) }
129 }
130
131 #[inline]
133 pub fn byte_range(&self) -> Range<u32> {
134 self.start_byte()..self.end_byte()
135 }
136
137 #[inline]
144 pub fn child(&self, i: u32) -> Option<Node<'tree>> {
145 unsafe { Node::from_raw(ts_node_child(self.as_raw(), i)) }
146 }
147
148 #[inline]
150 pub fn child_count(&self) -> u32 {
151 unsafe { ts_node_child_count(self.as_raw()) }
152 }
153
154 #[inline]
161 pub fn named_child(&self, i: u32) -> Option<Node<'tree>> {
162 unsafe { Node::from_raw(ts_node_named_child(self.as_raw(), i)) }
163 }
164
165 #[inline]
169 pub fn named_child_count(&self) -> u32 {
170 unsafe { ts_node_named_child_count(self.as_raw()) }
171 }
172
173 #[inline]
174 unsafe fn map(&self, f: unsafe extern "C" fn(NodeRaw) -> NodeRaw) -> Option<Node<'tree>> {
175 Node::from_raw(f(self.as_raw()))
176 }
177
178 #[inline]
180 pub fn parent(&self) -> Option<Self> {
181 unsafe { self.map(ts_node_parent) }
182 }
183
184 #[inline]
186 pub fn next_sibling(&self) -> Option<Self> {
187 unsafe { self.map(ts_node_next_sibling) }
188 }
189
190 #[inline]
192 pub fn prev_sibling(&self) -> Option<Self> {
193 unsafe { self.map(ts_node_prev_sibling) }
194 }
195
196 #[inline]
198 pub fn next_named_sibling(&self) -> Option<Self> {
199 unsafe { self.map(ts_node_next_named_sibling) }
200 }
201
202 #[inline]
204 pub fn prev_named_sibling(&self) -> Option<Self> {
205 unsafe { self.map(ts_node_prev_named_sibling) }
206 }
207
208 #[inline]
210 pub fn descendant_for_byte_range(&self, start: u32, end: u32) -> Option<Self> {
211 unsafe { Self::from_raw(ts_node_descendant_for_byte_range(self.as_raw(), start, end)) }
212 }
213
214 #[inline]
216 pub fn named_descendant_for_byte_range(&self, start: u32, end: u32) -> Option<Self> {
217 unsafe {
218 Self::from_raw(ts_node_named_descendant_for_byte_range(
219 self.as_raw(),
220 start,
221 end,
222 ))
223 }
224 }
225
226 pub fn children(&self) -> impl ExactSizeIterator<Item = Node<'tree>> {
236 let mut cursor = TreeCursor::new(self);
237 cursor.goto_first_child();
238 (0..self.child_count()).map(move |_| {
239 let result = cursor.node();
240 cursor.goto_next_sibling();
241 result
242 })
243 }
244
245 pub fn walk(&self) -> TreeCursor<'tree> {
246 TreeCursor::new(self)
247 }
248}
249
250impl PartialEq for Node<'_> {
251 fn eq(&self, other: &Self) -> bool {
252 self.id == other.id
253 }
254}
255
256impl Eq for Node<'_> {}
257
258unsafe impl Send for Node<'_> {}
259unsafe impl Sync for Node<'_> {}
260
261extern "C" {
262 fn ts_node_type(node: NodeRaw) -> *const c_char;
264
265 fn ts_node_symbol(node: NodeRaw) -> u16;
267
268 fn ts_node_language(node: NodeRaw) -> Grammar;
270
271 fn ts_node_is_named(node: NodeRaw) -> bool;
275
276 fn ts_node_is_missing(node: NodeRaw) -> bool;
279
280 fn ts_node_parent(node: NodeRaw) -> NodeRaw;
282
283 fn ts_node_child(node: NodeRaw, child_index: u32) -> NodeRaw;
286
287 fn ts_node_child_count(node: NodeRaw) -> u32;
289
290 fn ts_node_named_child(node: NodeRaw, child_index: u32) -> NodeRaw;
293
294 fn ts_node_named_child_count(node: NodeRaw) -> u32;
296
297 fn ts_node_next_sibling(node: NodeRaw) -> NodeRaw;
299
300 fn ts_node_prev_sibling(node: NodeRaw) -> NodeRaw;
301
302 fn ts_node_next_named_sibling(node: NodeRaw) -> NodeRaw;
304
305 fn ts_node_prev_named_sibling(node: NodeRaw) -> NodeRaw;
306
307 fn ts_node_descendant_for_byte_range(node: NodeRaw, start: u32, end: u32) -> NodeRaw;
310
311 fn ts_node_named_descendant_for_byte_range(node: NodeRaw, start: u32, end: u32) -> NodeRaw;
314
315 fn ts_node_end_byte(node: NodeRaw) -> u32;
317}