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(always)]
117 pub fn start_byte(&self) -> u32 {
118 self.context[0]
131 }
132
133 #[inline]
135 pub fn end_byte(&self) -> u32 {
136 unsafe { ts_node_end_byte(self.as_raw()) }
137 }
138
139 #[inline]
141 pub fn byte_range(&self) -> Range<u32> {
142 self.start_byte()..self.end_byte()
143 }
144
145 #[inline]
152 pub fn child(&self, i: u32) -> Option<Node<'tree>> {
153 unsafe { Node::from_raw(ts_node_child(self.as_raw(), i)) }
154 }
155
156 #[inline]
158 pub fn child_count(&self) -> u32 {
159 unsafe { ts_node_child_count(self.as_raw()) }
160 }
161
162 #[inline]
169 pub fn named_child(&self, i: u32) -> Option<Node<'tree>> {
170 unsafe { Node::from_raw(ts_node_named_child(self.as_raw(), i)) }
171 }
172
173 #[inline]
177 pub fn named_child_count(&self) -> u32 {
178 unsafe { ts_node_named_child_count(self.as_raw()) }
179 }
180
181 #[inline]
182 unsafe fn map(&self, f: unsafe extern "C" fn(NodeRaw) -> NodeRaw) -> Option<Node<'tree>> {
183 Node::from_raw(f(self.as_raw()))
184 }
185
186 #[inline]
188 pub fn parent(&self) -> Option<Self> {
189 unsafe { self.map(ts_node_parent) }
190 }
191
192 #[inline]
194 pub fn next_sibling(&self) -> Option<Self> {
195 unsafe { self.map(ts_node_next_sibling) }
196 }
197
198 #[inline]
200 pub fn prev_sibling(&self) -> Option<Self> {
201 unsafe { self.map(ts_node_prev_sibling) }
202 }
203
204 #[inline]
206 pub fn next_named_sibling(&self) -> Option<Self> {
207 unsafe { self.map(ts_node_next_named_sibling) }
208 }
209
210 #[inline]
212 pub fn prev_named_sibling(&self) -> Option<Self> {
213 unsafe { self.map(ts_node_prev_named_sibling) }
214 }
215
216 #[inline]
218 pub fn descendant_for_byte_range(&self, start: u32, end: u32) -> Option<Self> {
219 unsafe { Self::from_raw(ts_node_descendant_for_byte_range(self.as_raw(), start, end)) }
220 }
221
222 #[inline]
224 pub fn named_descendant_for_byte_range(&self, start: u32, end: u32) -> Option<Self> {
225 unsafe {
226 Self::from_raw(ts_node_named_descendant_for_byte_range(
227 self.as_raw(),
228 start,
229 end,
230 ))
231 }
232 }
233
234 pub fn children(&self) -> impl ExactSizeIterator<Item = Node<'tree>> {
244 let mut cursor = TreeCursor::new(self);
245 cursor.goto_first_child();
246 (0..self.child_count()).map(move |_| {
247 let result = cursor.node();
248 cursor.goto_next_sibling();
249 result
250 })
251 }
252
253 pub fn walk(&self) -> TreeCursor<'tree> {
254 TreeCursor::new(self)
255 }
256}
257
258impl PartialEq for Node<'_> {
259 fn eq(&self, other: &Self) -> bool {
260 self.id == other.id
261 }
262}
263
264impl Eq for Node<'_> {}
265
266unsafe impl Send for Node<'_> {}
267unsafe impl Sync for Node<'_> {}
268
269extern "C" {
270 fn ts_node_type(node: NodeRaw) -> *const c_char;
272
273 fn ts_node_symbol(node: NodeRaw) -> u16;
275
276 fn ts_node_language(node: NodeRaw) -> Grammar;
278
279 fn ts_node_is_named(node: NodeRaw) -> bool;
283
284 fn ts_node_is_missing(node: NodeRaw) -> bool;
287
288 fn ts_node_parent(node: NodeRaw) -> NodeRaw;
290
291 fn ts_node_child(node: NodeRaw, child_index: u32) -> NodeRaw;
294
295 fn ts_node_child_count(node: NodeRaw) -> u32;
297
298 fn ts_node_named_child(node: NodeRaw, child_index: u32) -> NodeRaw;
301
302 fn ts_node_named_child_count(node: NodeRaw) -> u32;
304
305 fn ts_node_next_sibling(node: NodeRaw) -> NodeRaw;
307
308 fn ts_node_prev_sibling(node: NodeRaw) -> NodeRaw;
309
310 fn ts_node_next_named_sibling(node: NodeRaw) -> NodeRaw;
312
313 fn ts_node_prev_named_sibling(node: NodeRaw) -> NodeRaw;
314
315 fn ts_node_descendant_for_byte_range(node: NodeRaw, start: u32, end: u32) -> NodeRaw;
318
319 fn ts_node_named_descendant_for_byte_range(node: NodeRaw, start: u32, end: u32) -> NodeRaw;
322
323 fn ts_node_end_byte(node: NodeRaw) -> u32;
325}