1#![cfg_attr(not(any(test, doctest)), doc = include_str!("./README.md"))]
3#![cfg_attr(not(feature = "std"), no_std)]
4#![cfg_attr(docsrs, feature(doc_cfg))]
5
6pub mod ffi;
7mod lookahead;
8mod sexp;
9
10pub use lookahead::LookaheadIterator;
11#[doc(hidden)]
12pub use sexp::format_sexp;
13
14#[cfg(any(
15 not(feature = "std"),
16 all(target_arch = "wasm32", target_os = "unknown")
17))]
18extern crate alloc;
19#[cfg(not(feature = "std"))]
20use alloc::{
21 boxed::Box,
22 string::{String, ToString},
23 vec::Vec,
24};
25use core::{
26 ffi::{CStr, c_char, c_void},
27 fmt, hash, iter,
28 marker::PhantomData,
29 num::NonZeroU16,
30 ops::{ControlFlow, Deref},
31 ptr::{self, NonNull},
32 slice, str,
33};
34#[cfg(feature = "std")]
35use std::error;
36#[cfg(all(unix, feature = "std"))]
37use std::os::fd::AsRawFd;
38#[cfg(all(windows, feature = "std"))]
39use std::os::windows::io::AsRawHandle;
40
41use tree_sitter_language::LanguageFn;
42
43#[cfg(feature = "wasm")]
44mod wasm_language;
45#[cfg(feature = "wasm")]
46#[cfg_attr(docsrs, doc(cfg(feature = "wasm")))]
47pub use wasm_language::*;
48
49#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
50mod wasm_allocator;
51
52#[doc(alias = "TREE_SITTER_LANGUAGE_VERSION")]
60pub const LANGUAGE_VERSION: usize = ffi::TREE_SITTER_LANGUAGE_VERSION as usize;
61
62#[doc(alias = "TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION")]
66pub const MIN_COMPATIBLE_LANGUAGE_VERSION: usize =
67 ffi::TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION as usize;
68
69pub const PARSER_HEADER: &str = include_str!("../src/parser.h");
70
71#[doc(alias = "TSLanguage")]
74#[derive(Debug, PartialEq, Eq, Hash)]
75#[repr(transparent)]
76pub struct Language(pub(crate) *const ffi::TSLanguage);
77
78pub struct LanguageRef<'a>(
79 pub(crate) *const ffi::TSLanguage,
80 pub(crate) PhantomData<&'a ()>,
81);
82
83#[doc(alias = "TSLanguageMetadata")]
88pub struct LanguageMetadata {
89 pub major_version: u8,
90 pub minor_version: u8,
91 pub patch_version: u8,
92}
93
94impl From<ffi::TSLanguageMetadata> for LanguageMetadata {
95 fn from(val: ffi::TSLanguageMetadata) -> Self {
96 Self {
97 major_version: val.major_version,
98 minor_version: val.minor_version,
99 patch_version: val.patch_version,
100 }
101 }
102}
103
104#[doc(alias = "TSTree")]
106pub struct Tree(NonNull<ffi::TSTree>);
107
108#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord)]
112pub struct Point {
113 pub row: usize,
114 pub column: usize,
115}
116
117#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
120pub struct Range {
121 pub start_byte: usize,
122 pub end_byte: usize,
123 pub start_point: Point,
124 pub end_point: Point,
125}
126
127#[doc(alias = "TSNode")]
129#[derive(Clone, Copy)]
130#[repr(transparent)]
131pub struct Node<'tree>(ffi::TSNode, PhantomData<&'tree ()>);
132
133#[doc(alias = "TSParser")]
136pub struct Parser(NonNull<ffi::TSParser>);
137
138pub struct ParseState(NonNull<ffi::TSParseState>);
141
142impl ParseState {
143 #[must_use]
144 pub const fn current_byte_offset(&self) -> usize {
145 unsafe { self.0.as_ref() }.current_byte_offset as usize
146 }
147
148 #[must_use]
149 pub const fn has_error(&self) -> bool {
150 unsafe { self.0.as_ref() }.has_error
151 }
152}
153
154#[derive(Default)]
155pub struct ParseOptions<'a> {
156 pub progress_callback: Option<ParseProgressCallback<'a>>,
157}
158
159impl<'a> ParseOptions<'a> {
160 #[must_use]
161 pub fn new() -> Self {
162 Self::default()
163 }
164
165 #[must_use]
166 pub fn progress_callback<F: FnMut(&ParseState) -> ControlFlow<()>>(
167 mut self,
168 callback: &'a mut F,
169 ) -> Self {
170 self.progress_callback = Some(callback);
171 self
172 }
173
174 #[must_use]
179 pub fn reborrow(&mut self) -> ParseOptions {
180 ParseOptions {
181 progress_callback: match &mut self.progress_callback {
182 Some(cb) => Some(*cb),
183 None => None,
184 },
185 }
186 }
187}
188
189#[derive(Debug, PartialEq, Eq)]
191pub enum LogType {
192 Parse,
193 Lex,
194}
195
196type FieldId = NonZeroU16;
197
198type Logger = Box<dyn FnMut(LogType, &str) + Send + 'static>;
200
201type UnsafeLogger<'a> = Box<dyn FnMut(LogType, &str) + Send + 'a>;
203
204type ParseProgressCallback<'a> = &'a mut dyn FnMut(&ParseState) -> ControlFlow<()>;
206
207pub trait Decode {
208 fn decode(bytes: &[u8]) -> (i32, u32);
211}
212
213#[doc(alias = "TSTreeCursor")]
215pub struct TreeCursor<'tree>(ffi::TSTreeCursor, PhantomData<&'tree ()>);
216
217#[derive(Debug, PartialEq, Eq)]
221pub enum LanguageError {
222 Version(usize),
223 NotParseable,
224 #[cfg(feature = "wasm")]
225 Wasm,
226}
227
228#[derive(Debug, PartialEq, Eq)]
230pub struct IncludedRangesError(pub usize);
231
232impl Language {
233 #[must_use]
234 pub fn new(builder: LanguageFn) -> Self {
235 Self(unsafe { builder.into_raw()().cast() })
236 }
237
238 #[doc(alias = "ts_language_is_parseable")]
245 #[must_use]
246 pub fn is_parseable(&self) -> bool {
247 unsafe { ffi::ts_language_is_parseable(self.0) }
248 }
249
250 #[doc(alias = "ts_language_name")]
253 #[must_use]
254 pub fn name(&self) -> Option<&str> {
255 let ptr = unsafe { ffi::ts_language_name(self.0) };
256 (!ptr.is_null()).then(|| unsafe { CStr::from_ptr(ptr) }.to_str().unwrap())
257 }
258
259 #[doc(alias = "ts_language_abi_version")]
266 #[must_use]
267 pub fn abi_version(&self) -> usize {
268 unsafe { ffi::ts_language_abi_version(self.0) as usize }
269 }
270
271 #[doc(alias = "ts_language_metadata")]
278 #[must_use]
279 pub fn metadata(&self) -> Option<LanguageMetadata> {
280 unsafe {
281 let ptr = ffi::ts_language_metadata(self.0);
282 (!ptr.is_null()).then(|| (*ptr).into())
283 }
284 }
285
286 #[doc(alias = "ts_language_symbol_count")]
288 #[must_use]
289 pub fn node_kind_count(&self) -> usize {
290 unsafe { ffi::ts_language_symbol_count(self.0) as usize }
291 }
292
293 #[doc(alias = "ts_language_state_count")]
295 #[must_use]
296 pub fn parse_state_count(&self) -> usize {
297 unsafe { ffi::ts_language_state_count(self.0) as usize }
298 }
299
300 #[doc(alias = "ts_language_supertypes")]
303 #[must_use]
304 pub fn supertypes(&self) -> &[u16] {
305 let mut length = 0u32;
306 unsafe {
307 let ptr = ffi::ts_language_supertypes(self.0, core::ptr::addr_of_mut!(length));
308 if length == 0 {
309 &[]
310 } else {
311 slice::from_raw_parts(ptr.cast_mut(), length as usize)
312 }
313 }
314 }
315
316 #[doc(alias = "ts_language_supertype_map")]
319 #[must_use]
320 pub fn subtypes_for_supertype(&self, supertype: u16) -> &[u16] {
321 unsafe {
322 let mut length = 0u32;
323 let ptr = ffi::ts_language_subtypes(self.0, supertype, core::ptr::addr_of_mut!(length));
324 if length == 0 {
325 &[]
326 } else {
327 slice::from_raw_parts(ptr.cast_mut(), length as usize)
328 }
329 }
330 }
331
332 #[doc(alias = "ts_language_symbol_name")]
334 #[must_use]
335 pub fn node_kind_for_id(&self, id: u16) -> Option<&str> {
336 let ptr = unsafe { ffi::ts_language_symbol_name(self.0, id) };
337 (!ptr.is_null()).then(|| unsafe { CStr::from_ptr(ptr) }.to_str().unwrap())
338 }
339
340 #[doc(alias = "ts_language_symbol_for_name")]
342 #[must_use]
343 pub fn id_for_node_kind(&self, kind: &str, named: bool) -> u16 {
344 unsafe {
345 ffi::ts_language_symbol_for_name(
346 self.0,
347 kind.as_bytes().as_ptr().cast::<c_char>(),
348 kind.len() as u32,
349 named,
350 )
351 }
352 }
353
354 fn node_kind_id_is_valid(&self, id: u16) -> bool {
361 (id as usize) < self.node_kind_count() || id >= u16::MAX - 1
362 }
363
364 #[must_use]
367 pub fn node_kind_is_named(&self, id: u16) -> bool {
368 self.node_kind_id_is_valid(id)
369 && unsafe { ffi::ts_language_symbol_type(self.0, id) == ffi::TSSymbolTypeRegular }
370 }
371
372 #[must_use]
375 pub fn node_kind_is_visible(&self, id: u16) -> bool {
376 self.node_kind_id_is_valid(id)
377 && unsafe { ffi::ts_language_symbol_type(self.0, id) <= ffi::TSSymbolTypeAnonymous }
378 }
379
380 #[must_use]
382 pub fn node_kind_is_supertype(&self, id: u16) -> bool {
383 self.node_kind_id_is_valid(id)
384 && unsafe { ffi::ts_language_symbol_type(self.0, id) == ffi::TSSymbolTypeSupertype }
385 }
386
387 #[doc(alias = "ts_language_field_count")]
389 #[must_use]
390 pub fn field_count(&self) -> usize {
391 unsafe { ffi::ts_language_field_count(self.0) as usize }
392 }
393
394 #[doc(alias = "ts_language_field_name_for_id")]
396 #[must_use]
397 pub fn field_name_for_id(&self, field_id: u16) -> Option<&str> {
398 let ptr = unsafe { ffi::ts_language_field_name_for_id(self.0, field_id) };
399 (!ptr.is_null()).then(|| unsafe { CStr::from_ptr(ptr) }.to_str().unwrap())
400 }
401
402 #[doc(alias = "ts_language_field_id_for_name")]
404 #[must_use]
405 pub fn field_id_for_name(&self, field_name: impl AsRef<[u8]>) -> Option<FieldId> {
406 let field_name = field_name.as_ref();
407 let id = unsafe {
408 ffi::ts_language_field_id_for_name(
409 self.0,
410 field_name.as_ptr().cast::<c_char>(),
411 field_name.len() as u32,
412 )
413 };
414 FieldId::new(id)
415 }
416
417 #[doc(alias = "ts_language_next_state")]
426 #[must_use]
427 pub fn next_state(&self, state: u16, id: u16) -> u16 {
428 unsafe { ffi::ts_language_next_state(self.0, state, id) }
429 }
430
431 #[doc(alias = "ts_lookahead_iterator_new")]
451 #[must_use]
452 pub fn lookahead_iterator(&self, state: u16) -> Option<LookaheadIterator> {
453 let ptr = unsafe { ffi::ts_lookahead_iterator_new(self.0, state) };
454 (!ptr.is_null()).then(|| unsafe { LookaheadIterator::from_raw(ptr) })
455 }
456}
457
458impl From<LanguageFn> for Language {
459 fn from(value: LanguageFn) -> Self {
460 Self::new(value)
461 }
462}
463
464impl Clone for Language {
465 fn clone(&self) -> Self {
466 unsafe { Self(ffi::ts_language_copy(self.0)) }
467 }
468}
469
470impl Drop for Language {
471 fn drop(&mut self) {
472 unsafe { ffi::ts_language_delete(self.0) }
473 }
474}
475
476impl Deref for LanguageRef<'_> {
477 type Target = Language;
478
479 fn deref(&self) -> &Self::Target {
480 unsafe { &*(core::ptr::addr_of!(self.0).cast::<Language>()) }
481 }
482}
483
484impl Default for Parser {
485 fn default() -> Self {
486 Self::new()
487 }
488}
489
490impl Parser {
491 #[doc(alias = "ts_parser_new")]
493 #[must_use]
494 pub fn new() -> Self {
495 unsafe {
496 let parser = ffi::ts_parser_new();
497 Self(NonNull::new_unchecked(parser))
498 }
499 }
500
501 #[doc(alias = "ts_parser_set_language")]
509 pub fn set_language(&mut self, language: &Language) -> Result<(), LanguageError> {
510 let version = language.abi_version();
511 if (MIN_COMPATIBLE_LANGUAGE_VERSION..=LANGUAGE_VERSION).contains(&version) {
512 if !language.is_parseable() {
513 return Err(LanguageError::NotParseable);
514 }
515 #[cfg_attr(
516 not(feature = "wasm"),
517 expect(unused_variables, reason = "only used when wasm feature is enabled")
518 )]
519 let success = unsafe { ffi::ts_parser_set_language(self.0.as_ptr(), language.0) };
520 #[cfg(feature = "wasm")]
521 if !success {
522 return Err(LanguageError::Wasm);
523 }
524 Ok(())
525 } else {
526 Err(LanguageError::Version(version))
527 }
528 }
529
530 #[doc(alias = "ts_parser_language")]
532 #[must_use]
533 pub fn language(&self) -> Option<LanguageRef<'_>> {
534 let ptr = unsafe { ffi::ts_parser_language(self.0.as_ptr()) };
535 (!ptr.is_null()).then_some(LanguageRef(ptr, PhantomData))
536 }
537
538 #[doc(alias = "ts_parser_logger")]
540 #[must_use]
541 pub fn logger(&self) -> Option<&Logger> {
542 let logger = unsafe { ffi::ts_parser_logger(self.0.as_ptr()) };
543 unsafe { logger.payload.cast::<Logger>().as_ref() }
544 }
545
546 #[doc(alias = "ts_parser_set_logger")]
551 pub fn set_logger(&mut self, logger: Option<Logger>) {
552 unsafe { self.set_logger_unchecked(logger) };
554 }
555
556 pub unsafe fn set_logger_unchecked(&mut self, logger: Option<UnsafeLogger<'_>>) {
565 let prev_logger = unsafe { ffi::ts_parser_logger(self.0.as_ptr()) };
566 if !prev_logger.payload.is_null() {
567 drop(unsafe { Box::from_raw(prev_logger.payload.cast::<Logger>()) });
568 }
569
570 let c_logger = if let Some(logger) = logger {
571 let container = Box::new(logger);
572
573 unsafe extern "C" fn log(
574 payload: *mut c_void,
575 c_log_type: ffi::TSLogType,
576 c_message: *const c_char,
577 ) {
578 unsafe {
579 let callback = payload.cast::<Logger>().as_mut().unwrap();
580 if let Ok(message) = CStr::from_ptr(c_message).to_str() {
581 let log_type = if c_log_type == ffi::TSLogTypeParse {
582 LogType::Parse
583 } else {
584 LogType::Lex
585 };
586 callback(log_type, message);
587 }
588 }
589 }
590
591 let raw_container = Box::into_raw(container);
592
593 ffi::TSLogger {
594 payload: raw_container.cast::<c_void>(),
595 log: Some(log),
596 }
597 } else {
598 ffi::TSLogger {
599 payload: ptr::null_mut(),
600 log: None,
601 }
602 };
603
604 unsafe { ffi::ts_parser_set_logger(self.0.as_ptr(), c_logger) };
605 }
606
607 #[doc(alias = "ts_parser_print_dot_graphs")]
612 #[cfg(not(target_os = "wasi"))]
613 #[cfg(feature = "std")]
614 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
615 pub fn print_dot_graphs(
616 &mut self,
617 #[cfg(unix)] file: &impl AsRawFd,
618 #[cfg(windows)] file: &impl AsRawHandle,
619 ) {
620 #[cfg(unix)]
621 {
622 let fd = file.as_raw_fd();
623 unsafe {
624 ffi::ts_parser_print_dot_graphs(self.0.as_ptr(), ffi::_ts_dup(fd));
625 }
626 }
627
628 #[cfg(windows)]
629 {
630 let handle = file.as_raw_handle();
631 unsafe {
632 ffi::ts_parser_print_dot_graphs(self.0.as_ptr(), ffi::_ts_dup(handle));
633 }
634 }
635 }
636
637 #[doc(alias = "ts_parser_print_dot_graphs")]
639 #[cfg(not(target_os = "wasi"))]
640 #[cfg(feature = "std")]
641 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
642 pub fn stop_printing_dot_graphs(&mut self) {
643 unsafe { ffi::ts_parser_print_dot_graphs(self.0.as_ptr(), -1) }
644 }
645
646 #[doc(alias = "ts_parser_parse")]
654 pub fn parse(&mut self, text: impl AsRef<[u8]>) -> Option<Tree> {
655 let bytes = text.as_ref();
656 if let Ok(len) = u32::try_from(bytes.len()) {
657 return unsafe {
658 self.parse_raw_bytes(
659 (bytes.as_ptr().cast::<c_char>(), len),
660 ffi::TSInputEncodingUTF8,
661 )
662 };
663 }
664 let len = bytes.len();
665 self.parse_with_options(
666 &mut |i, _| {
667 if i < len {
668 &bytes[i..]
669 } else {
670 Default::default()
671 }
672 },
673 None,
674 )
675 }
676
677 pub fn parse_with_options<T: AsRef<[u8]>, F: FnMut(usize, Point) -> T>(
686 &mut self,
687 callback: &mut F,
688 options: Option<ParseOptions>,
689 ) -> Option<Tree> {
690 self.parse_chunks::<0, u8, T, F>(callback, (options, ffi::TSInputEncodingUTF8, None))
691 }
692
693 pub fn parse_utf16_le(&mut self, input: impl AsRef<[u16]>) -> Option<Tree> {
698 self.parse_utf16_slice::<true>(input.as_ref())
699 }
700
701 pub fn parse_utf16_le_with_options<T: AsRef<[u16]>, F: FnMut(usize, Point) -> T>(
710 &mut self,
711 callback: &mut F,
712 options: Option<ParseOptions>,
713 ) -> Option<Tree> {
714 self.parse_utf16_with_options::<true, T, F>(callback, options)
715 }
716
717 pub fn parse_utf16_be(&mut self, input: impl AsRef<[u16]>) -> Option<Tree> {
722 self.parse_utf16_slice::<false>(input.as_ref())
723 }
724
725 pub fn parse_utf16_be_with_options<T: AsRef<[u16]>, F: FnMut(usize, Point) -> T>(
734 &mut self,
735 callback: &mut F,
736 options: Option<ParseOptions>,
737 ) -> Option<Tree> {
738 self.parse_utf16_with_options::<false, T, F>(callback, options)
739 }
740
741 pub fn parse_custom_encoding<D: Decode, T: AsRef<[u8]>, F: FnMut(usize, Point) -> T>(
755 &mut self,
756 callback: &mut F,
757 options: Option<ParseOptions>,
758 ) -> Option<Tree> {
759 unsafe extern "C" fn decode_fn<D: Decode>(
760 data: *const u8,
761 len: u32,
762 code_point: *mut i32,
763 ) -> u32 {
764 unsafe {
765 let (c, len) = D::decode(core::slice::from_raw_parts(data, len as usize));
766 if let Some(code_point) = code_point.as_mut() {
767 *code_point = c;
768 }
769 len
770 }
771 }
772
773 self.parse_chunks::<0, u8, T, F>(
774 callback,
775 (options, ffi::TSInputEncodingCustom, Some(decode_fn::<D>)),
776 )
777 }
778
779 fn parse_utf16_slice<const LE: bool>(&mut self, code_points: &[u16]) -> Option<Tree> {
780 let encoding = if LE {
781 ffi::TSInputEncodingUTF16LE
782 } else {
783 ffi::TSInputEncodingUTF16BE
784 };
785 if let Some(byte_len) = code_points
786 .len()
787 .checked_mul(2)
788 .and_then(|n| u32::try_from(n).ok())
789 {
790 return unsafe {
791 self.parse_raw_bytes((code_points.as_ptr().cast::<c_char>(), byte_len), encoding)
792 };
793 }
794 let len = code_points.len();
795 self.parse_utf16_with_options::<LE, _, _>(
796 &mut |i, _| if i < len { &code_points[i..] } else { &[] },
797 None,
798 )
799 }
800
801 fn parse_utf16_with_options<const LE: bool, T: AsRef<[u16]>, F: FnMut(usize, Point) -> T>(
802 &mut self,
803 callback: &mut F,
804 options: Option<ParseOptions>,
805 ) -> Option<Tree> {
806 let encoding = if LE {
807 ffi::TSInputEncodingUTF16LE
808 } else {
809 ffi::TSInputEncodingUTF16BE
810 };
811 self.parse_chunks::<1, u16, T, F>(callback, (options, encoding, None))
812 }
813
814 fn parse_chunks<const UNIT_SHIFT: u32, U, T: AsRef<[U]>, F: FnMut(usize, Point) -> T>(
815 &mut self,
816 callback: &mut F,
817 (options, encoding, decode): (
818 Option<ParseOptions>,
819 ffi::TSInputEncoding,
820 ffi::TSDecodeFunction,
821 ),
822 ) -> Option<Tree> {
823 type Payload<'a, F, T> = (&'a mut F, Option<T>);
824
825 unsafe extern "C" fn read<
826 const UNIT_SHIFT: u32,
827 U,
828 T: AsRef<[U]>,
829 F: FnMut(usize, Point) -> T,
830 >(
831 payload: *mut c_void,
832 byte_offset: u32,
833 position: ffi::TSPoint,
834 bytes_read: *mut u32,
835 ) -> *const c_char {
836 unsafe {
837 let (callback, text) = payload.cast::<Payload<F, T>>().as_mut().unwrap();
838 *text = Some(callback(
839 (byte_offset as usize) >> UNIT_SHIFT,
840 Point {
841 row: position.row as usize,
842 column: (position.column as usize) >> UNIT_SHIFT,
843 },
844 ));
845 let slice = text.as_ref().unwrap().as_ref();
846 *bytes_read =
847 (slice.len().min((u32::MAX as usize) >> UNIT_SHIFT) << UNIT_SHIFT) as u32;
848 slice.as_ptr().cast::<c_char>()
849 }
850 }
851
852 let mut payload: Payload<F, T> = (callback, None);
854 let c_input = ffi::TSInput {
855 payload: ptr::addr_of_mut!(payload).cast::<c_void>(),
856 read: Some(read::<UNIT_SHIFT, U, T, F>),
857 encoding,
858 decode,
859 };
860 unsafe { self.parse_c_input(c_input, options) }
861 }
862
863 unsafe fn parse_raw_bytes(
864 &mut self,
865 (bytes, byte_len): (*const c_char, u32),
866 encoding: ffi::TSInputEncoding,
867 ) -> Option<Tree> {
868 let c_new_tree = unsafe {
869 ffi::ts_parser_parse_string_encoding(self.0.as_ptr(), bytes, byte_len, encoding)
870 };
871 NonNull::new(c_new_tree).map(Tree)
872 }
873
874 unsafe fn parse_c_input(
875 &mut self,
876 c_input: ffi::TSInput,
877 options: Option<ParseOptions>,
878 ) -> Option<Tree> {
879 unsafe extern "C" fn progress(state: *mut ffi::TSParseState) -> bool {
880 unsafe {
881 let callback = (*state)
882 .payload
883 .cast::<ParseProgressCallback>()
884 .as_mut()
885 .unwrap();
886 match callback(&ParseState::from_raw(state)) {
887 ControlFlow::Continue(()) => false,
888 ControlFlow::Break(()) => true,
889 }
890 }
891 }
892
893 let mut callback_ptr;
894 let parse_options = if let Some(cb) = options.and_then(|o| o.progress_callback) {
895 callback_ptr = cb;
896 ffi::TSParseOptions {
897 payload: core::ptr::addr_of_mut!(callback_ptr).cast::<c_void>(),
898 progress_callback: Some(progress),
899 }
900 } else {
901 ffi::TSParseOptions {
902 payload: ptr::null_mut(),
903 progress_callback: None,
904 }
905 };
906
907 let c_new_tree =
908 unsafe { ffi::ts_parser_parse_with_options(self.0.as_ptr(), c_input, parse_options) };
909 NonNull::new(c_new_tree).map(Tree)
910 }
911
912 #[doc(alias = "ts_parser_reset")]
919 pub fn reset(&mut self) {
920 unsafe { ffi::ts_parser_reset(self.0.as_ptr()) }
921 }
922
923 #[doc(alias = "ts_parser_set_included_ranges")]
941 pub fn set_included_ranges(&mut self, ranges: &[Range]) -> Result<(), IncludedRangesError> {
942 let ts_ranges = ranges.iter().copied().map(Into::into).collect::<Vec<_>>();
943 let result = unsafe {
944 ffi::ts_parser_set_included_ranges(
945 self.0.as_ptr(),
946 ts_ranges.as_ptr(),
947 ts_ranges.len() as u32,
948 )
949 };
950
951 if result {
952 Ok(())
953 } else {
954 let mut prev_end_byte = 0;
955 for (i, range) in ranges.iter().enumerate() {
956 if range.start_byte < prev_end_byte || range.end_byte < range.start_byte {
957 return Err(IncludedRangesError(i));
958 }
959 prev_end_byte = range.end_byte;
960 }
961 Err(IncludedRangesError(0))
962 }
963 }
964
965 #[doc(alias = "ts_parser_included_ranges")]
967 #[must_use]
968 pub fn included_ranges(&self) -> Vec<Range> {
969 let mut count = 0u32;
970 unsafe {
971 let ptr =
972 ffi::ts_parser_included_ranges(self.0.as_ptr(), core::ptr::addr_of_mut!(count));
973 let ranges = slice::from_raw_parts(ptr, count as usize);
974 ranges.iter().copied().map(Into::into).collect()
975 }
976 }
977}
978
979impl Drop for Parser {
980 fn drop(&mut self) {
981 #[cfg(feature = "std")]
982 #[cfg(not(target_os = "wasi"))]
983 {
984 self.stop_printing_dot_graphs();
985 }
986 self.set_logger(None);
987 unsafe { ffi::ts_parser_delete(self.0.as_ptr()) }
988 }
989}
990
991#[cfg(windows)]
992unsafe extern "C" {
993 fn _open_osfhandle(osfhandle: isize, flags: core::ffi::c_int) -> core::ffi::c_int;
994}
995
996impl Tree {
997 #[doc(alias = "ts_tree_root_node")]
999 #[must_use]
1000 pub fn root_node(&self) -> Node {
1001 Node::new(unsafe { ffi::ts_tree_root_node(self.0.as_ptr()) }).unwrap()
1002 }
1003
1004 #[doc(alias = "ts_tree_root_node_with_offset")]
1007 #[must_use]
1008 pub fn root_node_with_offset(&self, offset_bytes: usize, offset_extent: Point) -> Node {
1009 Node::new(unsafe {
1010 ffi::ts_tree_root_node_with_offset(
1011 self.0.as_ptr(),
1012 offset_bytes as u32,
1013 offset_extent.into(),
1014 )
1015 })
1016 .unwrap()
1017 }
1018
1019 #[doc(alias = "ts_tree_language")]
1026 #[must_use]
1027 pub fn language(&self) -> LanguageRef {
1028 LanguageRef(
1029 unsafe { ffi::ts_tree_language(self.0.as_ptr()) },
1030 PhantomData,
1031 )
1032 }
1033
1034 #[must_use]
1036 pub fn walk(&self) -> TreeCursor {
1037 self.root_node().walk()
1038 }
1039
1040 #[doc(alias = "ts_tree_included_ranges")]
1042 #[must_use]
1043 pub fn included_ranges(&self) -> Vec<Range> {
1044 let mut count = 0u32;
1045 unsafe {
1046 let ptr = ffi::ts_tree_included_ranges(self.0.as_ptr(), core::ptr::addr_of_mut!(count));
1047 let ranges = slice::from_raw_parts(ptr, count as usize);
1048 let result = ranges.iter().copied().map(Into::into).collect();
1049 ts_free(ptr.cast::<c_void>());
1050 result
1051 }
1052 }
1053
1054 #[doc(alias = "ts_tree_print_dot_graph")]
1059 #[cfg(not(target_os = "wasi"))]
1060 #[cfg(feature = "std")]
1061 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
1062 pub fn print_dot_graph(
1063 &self,
1064 #[cfg(unix)] file: &impl AsRawFd,
1065 #[cfg(windows)] file: &impl AsRawHandle,
1066 ) {
1067 #[cfg(unix)]
1068 {
1069 let fd = file.as_raw_fd();
1070 unsafe { ffi::ts_tree_print_dot_graph(self.0.as_ptr(), fd) }
1071 }
1072
1073 #[cfg(windows)]
1074 {
1075 let handle = file.as_raw_handle();
1076 let fd = unsafe { _open_osfhandle(handle as isize, 0) };
1077 unsafe { ffi::ts_tree_print_dot_graph(self.0.as_ptr(), fd) }
1078 }
1079 }
1080}
1081
1082impl fmt::Debug for Tree {
1083 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1084 write!(f, "{{Tree {:?}}}", self.root_node())
1085 }
1086}
1087
1088impl Drop for Tree {
1089 fn drop(&mut self) {
1090 unsafe { ffi::ts_tree_delete(self.0.as_ptr()) }
1091 }
1092}
1093
1094impl Clone for Tree {
1095 fn clone(&self) -> Self {
1096 unsafe { Self(NonNull::new_unchecked(ffi::ts_tree_copy(self.0.as_ptr()))) }
1097 }
1098}
1099
1100impl<'tree> Node<'tree> {
1101 fn new(node: ffi::TSNode) -> Option<Self> {
1102 (!node.id.is_null()).then_some(Node(node, PhantomData))
1103 }
1104
1105 #[must_use]
1107 pub fn id(&self) -> usize {
1108 self.0.id as usize
1109 }
1110
1111 #[doc(alias = "ts_node_symbol")]
1113 #[must_use]
1114 pub fn kind_id(&self) -> u16 {
1115 unsafe { ffi::ts_node_symbol(self.0) }
1116 }
1117
1118 #[doc(alias = "ts_node_grammar_symbol")]
1121 #[must_use]
1122 pub fn grammar_id(&self) -> u16 {
1123 unsafe { ffi::ts_node_grammar_symbol(self.0) }
1124 }
1125
1126 #[doc(alias = "ts_node_type")]
1128 #[must_use]
1129 pub fn kind(&self) -> &'tree str {
1130 let ptr = unsafe { ffi::ts_node_type(self.0) };
1131 assert!(!ptr.is_null());
1132 unsafe { CStr::from_ptr(ptr) }.to_str().unwrap()
1133 }
1134
1135 #[doc(alias = "ts_node_grammar_type")]
1138 #[must_use]
1139 pub fn grammar_name(&self) -> &'tree str {
1140 let ptr = unsafe { ffi::ts_node_grammar_type(self.0) };
1141 assert!(!ptr.is_null());
1142 unsafe { CStr::from_ptr(ptr) }.to_str().unwrap()
1143 }
1144
1145 #[doc(alias = "ts_node_language")]
1153 #[must_use]
1154 pub fn language(&self) -> LanguageRef<'tree> {
1155 LanguageRef(unsafe { ffi::ts_node_language(self.0) }, PhantomData)
1156 }
1157
1158 #[doc(alias = "ts_node_is_named")]
1163 #[must_use]
1164 pub fn is_named(&self) -> bool {
1165 unsafe { ffi::ts_node_is_named(self.0) }
1166 }
1167
1168 #[doc(alias = "ts_node_is_extra")]
1173 #[must_use]
1174 pub fn is_extra(&self) -> bool {
1175 unsafe { ffi::ts_node_is_extra(self.0) }
1176 }
1177
1178 #[doc(alias = "ts_node_has_error")]
1181 #[must_use]
1182 pub fn has_error(&self) -> bool {
1183 unsafe { ffi::ts_node_has_error(self.0) }
1184 }
1185
1186 #[doc(alias = "ts_node_is_error")]
1191 #[must_use]
1192 pub fn is_error(&self) -> bool {
1193 unsafe { ffi::ts_node_is_error(self.0) }
1194 }
1195
1196 #[doc(alias = "ts_node_parse_state")]
1205 #[must_use]
1206 pub fn parse_state(&self) -> u16 {
1207 unsafe { ffi::ts_node_parse_state(self.0) }
1208 }
1209
1210 #[doc(alias = "ts_node_next_parse_state")]
1212 #[must_use]
1213 pub fn next_parse_state(&self) -> u16 {
1214 unsafe { ffi::ts_node_next_parse_state(self.0) }
1215 }
1216
1217 #[doc(alias = "ts_node_is_missing")]
1222 #[must_use]
1223 pub fn is_missing(&self) -> bool {
1224 unsafe { ffi::ts_node_is_missing(self.0) }
1225 }
1226
1227 #[doc(alias = "ts_node_start_byte")]
1229 #[must_use]
1230 pub fn start_byte(&self) -> usize {
1231 unsafe { ffi::ts_node_start_byte(self.0) as usize }
1232 }
1233
1234 #[doc(alias = "ts_node_end_byte")]
1236 #[must_use]
1237 pub fn end_byte(&self) -> usize {
1238 unsafe { ffi::ts_node_end_byte(self.0) as usize }
1239 }
1240
1241 #[must_use]
1243 pub fn byte_range(&self) -> core::ops::Range<usize> {
1244 self.start_byte()..self.end_byte()
1245 }
1246
1247 #[must_use]
1250 pub fn range(&self) -> Range {
1251 Range {
1252 start_byte: self.start_byte(),
1253 end_byte: self.end_byte(),
1254 start_point: self.start_position(),
1255 end_point: self.end_position(),
1256 }
1257 }
1258
1259 #[doc(alias = "ts_node_start_point")]
1261 #[must_use]
1262 pub fn start_position(&self) -> Point {
1263 let result = unsafe { ffi::ts_node_start_point(self.0) };
1264 result.into()
1265 }
1266
1267 #[doc(alias = "ts_node_end_point")]
1269 #[must_use]
1270 pub fn end_position(&self) -> Point {
1271 let result = unsafe { ffi::ts_node_end_point(self.0) };
1272 result.into()
1273 }
1274
1275 #[doc(alias = "ts_node_child")]
1282 #[must_use]
1283 pub fn child(&self, i: u32) -> Option<Self> {
1284 Self::new(unsafe { ffi::ts_node_child(self.0, i) })
1285 }
1286
1287 #[doc(alias = "ts_node_child_count")]
1289 #[must_use]
1290 pub fn child_count(&self) -> u32 {
1291 unsafe { ffi::ts_node_child_count(self.0) }
1292 }
1293
1294 #[doc(alias = "ts_node_named_child")]
1301 #[must_use]
1302 pub fn named_child(&self, i: u32) -> Option<Self> {
1303 Self::new(unsafe { ffi::ts_node_named_child(self.0, i) })
1304 }
1305
1306 #[doc(alias = "ts_node_named_child_count")]
1310 #[must_use]
1311 pub fn named_child_count(&self) -> usize {
1312 unsafe { ffi::ts_node_named_child_count(self.0) as usize }
1313 }
1314
1315 #[doc(alias = "ts_node_child_by_field_name")]
1320 #[must_use]
1321 pub fn child_by_field_name(&self, field_name: impl AsRef<[u8]>) -> Option<Self> {
1322 let field_name = field_name.as_ref();
1323 Self::new(unsafe {
1324 ffi::ts_node_child_by_field_name(
1325 self.0,
1326 field_name.as_ptr().cast::<c_char>(),
1327 field_name.len() as u32,
1328 )
1329 })
1330 }
1331
1332 #[doc(alias = "ts_node_child_by_field_id")]
1337 #[must_use]
1338 pub fn child_by_field_id(&self, field_id: u16) -> Option<Self> {
1339 Self::new(unsafe { ffi::ts_node_child_by_field_id(self.0, field_id) })
1340 }
1341
1342 #[doc(alias = "ts_node_field_name_for_child")]
1344 #[must_use]
1345 pub fn field_name_for_child(&self, child_index: u32) -> Option<&'tree str> {
1346 unsafe {
1347 let ptr = ffi::ts_node_field_name_for_child(self.0, child_index);
1348 (!ptr.is_null()).then(|| CStr::from_ptr(ptr).to_str().unwrap())
1349 }
1350 }
1351
1352 #[must_use]
1354 pub fn field_name_for_named_child(&self, named_child_index: u32) -> Option<&'tree str> {
1355 unsafe {
1356 let ptr = ffi::ts_node_field_name_for_named_child(self.0, named_child_index);
1357 (!ptr.is_null()).then(|| CStr::from_ptr(ptr).to_str().unwrap())
1358 }
1359 }
1360
1361 pub fn children<'cursor>(
1371 &self,
1372 cursor: &'cursor mut TreeCursor<'tree>,
1373 ) -> impl ExactSizeIterator<Item = Node<'tree>> + 'cursor {
1374 cursor.reset(*self);
1375 cursor.goto_first_child();
1376 (0..self.child_count()).map(move |_| {
1377 let result = cursor.node();
1378 cursor.goto_next_sibling();
1379 result
1380 })
1381 }
1382
1383 pub fn named_children<'cursor>(
1387 &self,
1388 cursor: &'cursor mut TreeCursor<'tree>,
1389 ) -> impl ExactSizeIterator<Item = Node<'tree>> + 'cursor {
1390 cursor.reset(*self);
1391 cursor.goto_first_child();
1392 (0..self.named_child_count()).map(move |_| {
1393 while !cursor.node().is_named() {
1394 if !cursor.goto_next_sibling() {
1395 break;
1396 }
1397 }
1398 let result = cursor.node();
1399 cursor.goto_next_sibling();
1400 result
1401 })
1402 }
1403
1404 pub fn children_by_field_name<'cursor>(
1408 &self,
1409 field_name: &str,
1410 cursor: &'cursor mut TreeCursor<'tree>,
1411 ) -> impl Iterator<Item = Node<'tree>> + 'cursor {
1412 let field_id = self.language().field_id_for_name(field_name);
1413 let mut done = field_id.is_none();
1414 if !done {
1415 cursor.reset(*self);
1416 cursor.goto_first_child();
1417 }
1418 iter::from_fn(move || {
1419 if !done {
1420 while cursor.field_id() != field_id {
1421 if !cursor.goto_next_sibling() {
1422 return None;
1423 }
1424 }
1425 let result = cursor.node();
1426 if !cursor.goto_next_sibling() {
1427 done = true;
1428 }
1429 return Some(result);
1430 }
1431 None
1432 })
1433 }
1434
1435 pub fn children_by_field_id<'cursor>(
1439 &self,
1440 field_id: FieldId,
1441 cursor: &'cursor mut TreeCursor<'tree>,
1442 ) -> impl Iterator<Item = Node<'tree>> + 'cursor {
1443 cursor.reset(*self);
1444 cursor.goto_first_child();
1445 let mut done = false;
1446 iter::from_fn(move || {
1447 if !done {
1448 while cursor.field_id() != Some(field_id) {
1449 if !cursor.goto_next_sibling() {
1450 return None;
1451 }
1452 }
1453 let result = cursor.node();
1454 if !cursor.goto_next_sibling() {
1455 done = true;
1456 }
1457 return Some(result);
1458 }
1459 None
1460 })
1461 }
1462
1463 #[doc(alias = "ts_node_parent")]
1467 #[must_use]
1468 pub fn parent(&self) -> Option<Self> {
1469 Self::new(unsafe { ffi::ts_node_parent(self.0) })
1470 }
1471
1472 #[doc(alias = "ts_node_child_with_descendant")]
1476 #[must_use]
1477 pub fn child_with_descendant(&self, descendant: Self) -> Option<Self> {
1478 Self::new(unsafe { ffi::ts_node_child_with_descendant(self.0, descendant.0) })
1479 }
1480
1481 #[doc(alias = "ts_node_next_sibling")]
1483 #[must_use]
1484 pub fn next_sibling(&self) -> Option<Self> {
1485 Self::new(unsafe { ffi::ts_node_next_sibling(self.0) })
1486 }
1487
1488 #[doc(alias = "ts_node_prev_sibling")]
1490 #[must_use]
1491 pub fn prev_sibling(&self) -> Option<Self> {
1492 Self::new(unsafe { ffi::ts_node_prev_sibling(self.0) })
1493 }
1494
1495 #[doc(alias = "ts_node_next_named_sibling")]
1497 #[must_use]
1498 pub fn next_named_sibling(&self) -> Option<Self> {
1499 Self::new(unsafe { ffi::ts_node_next_named_sibling(self.0) })
1500 }
1501
1502 #[doc(alias = "ts_node_prev_named_sibling")]
1504 #[must_use]
1505 pub fn prev_named_sibling(&self) -> Option<Self> {
1506 Self::new(unsafe { ffi::ts_node_prev_named_sibling(self.0) })
1507 }
1508
1509 #[doc(alias = "ts_node_first_child_for_byte")]
1511 #[must_use]
1512 pub fn first_child_for_byte(&self, byte: usize) -> Option<Self> {
1513 Self::new(unsafe { ffi::ts_node_first_child_for_byte(self.0, byte as u32) })
1514 }
1515
1516 #[doc(alias = "ts_node_first_named_child_for_point")]
1518 #[must_use]
1519 pub fn first_named_child_for_byte(&self, byte: usize) -> Option<Self> {
1520 Self::new(unsafe { ffi::ts_node_first_named_child_for_byte(self.0, byte as u32) })
1521 }
1522
1523 #[doc(alias = "ts_node_descendant_count")]
1525 #[must_use]
1526 pub fn descendant_count(&self) -> usize {
1527 unsafe { ffi::ts_node_descendant_count(self.0) as usize }
1528 }
1529
1530 #[doc(alias = "ts_node_descendant_for_byte_range")]
1532 #[must_use]
1533 pub fn descendant_for_byte_range(&self, start: usize, end: usize) -> Option<Self> {
1534 Self::new(unsafe {
1535 ffi::ts_node_descendant_for_byte_range(self.0, start as u32, end as u32)
1536 })
1537 }
1538
1539 #[doc(alias = "ts_node_named_descendant_for_byte_range")]
1541 #[must_use]
1542 pub fn named_descendant_for_byte_range(&self, start: usize, end: usize) -> Option<Self> {
1543 Self::new(unsafe {
1544 ffi::ts_node_named_descendant_for_byte_range(self.0, start as u32, end as u32)
1545 })
1546 }
1547
1548 #[doc(alias = "ts_node_descendant_for_point_range")]
1550 #[must_use]
1551 pub fn descendant_for_point_range(&self, start: Point, end: Point) -> Option<Self> {
1552 Self::new(unsafe {
1553 ffi::ts_node_descendant_for_point_range(self.0, start.into(), end.into())
1554 })
1555 }
1556
1557 #[doc(alias = "ts_node_named_descendant_for_point_range")]
1559 #[must_use]
1560 pub fn named_descendant_for_point_range(&self, start: Point, end: Point) -> Option<Self> {
1561 Self::new(unsafe {
1562 ffi::ts_node_named_descendant_for_point_range(self.0, start.into(), end.into())
1563 })
1564 }
1565
1566 #[doc(alias = "ts_node_string")]
1568 #[must_use]
1569 pub fn to_sexp(&self) -> String {
1570 let c_string = unsafe { ffi::ts_node_string(self.0) };
1571 let result = unsafe { CStr::from_ptr(c_string) }
1572 .to_str()
1573 .unwrap()
1574 .to_string();
1575 unsafe { ts_free(c_string.cast::<c_void>()) };
1576 result
1577 }
1578
1579 pub fn utf8_text<'a>(&self, source: &'a [u8]) -> Result<&'a str, str::Utf8Error> {
1580 str::from_utf8(&source[self.start_byte()..self.end_byte()])
1581 }
1582
1583 #[must_use]
1584 pub fn utf16_text<'a>(&self, source: &'a [u16]) -> &'a [u16] {
1585 &source[self.start_byte() / 2..self.end_byte() / 2]
1586 }
1587
1588 #[doc(alias = "ts_tree_cursor_new")]
1593 #[must_use]
1594 pub fn walk(&self) -> TreeCursor<'tree> {
1595 TreeCursor(unsafe { ffi::ts_tree_cursor_new(self.0) }, PhantomData)
1596 }
1597}
1598
1599impl PartialEq for Node<'_> {
1600 fn eq(&self, other: &Self) -> bool {
1601 core::ptr::eq(self.0.id, other.0.id)
1602 }
1603}
1604
1605impl Eq for Node<'_> {}
1606
1607impl hash::Hash for Node<'_> {
1608 fn hash<H: hash::Hasher>(&self, state: &mut H) {
1609 self.0.id.hash(state);
1610 self.0.context[0].hash(state);
1611 self.0.context[1].hash(state);
1612 self.0.context[2].hash(state);
1613 self.0.context[3].hash(state);
1614 }
1615}
1616
1617impl fmt::Debug for Node<'_> {
1618 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1619 write!(
1620 f,
1621 "{{Node {} {} - {}}}",
1622 self.kind(),
1623 self.start_position(),
1624 self.end_position()
1625 )
1626 }
1627}
1628
1629impl fmt::Display for Node<'_> {
1630 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1631 if !f.alternate() {
1632 return f.write_str(&self.to_sexp());
1633 }
1634 let c_string = unsafe { ts_node_string_pretty(self.0, f.width().unwrap_or(0)) };
1635 let result = unsafe { CStr::from_ptr(c_string) }
1636 .to_str()
1637 .unwrap()
1638 .to_string();
1639 unsafe { ts_free(c_string.cast::<c_void>()) };
1640 f.write_str(&result)
1641 }
1642}
1643
1644impl<'tree> TreeCursor<'tree> {
1645 #[doc(alias = "ts_tree_cursor_current_node")]
1647 #[must_use]
1648 pub fn node(&self) -> Node<'tree> {
1649 Node(
1650 unsafe { ffi::ts_tree_cursor_current_node(&raw const self.0) },
1651 PhantomData,
1652 )
1653 }
1654
1655 #[doc(alias = "ts_tree_cursor_current_field_id")]
1659 #[must_use]
1660 pub fn field_id(&self) -> Option<FieldId> {
1661 let id = unsafe { ffi::ts_tree_cursor_current_field_id(&raw const self.0) };
1662 FieldId::new(id)
1663 }
1664
1665 #[doc(alias = "ts_tree_cursor_current_field_name")]
1667 #[must_use]
1668 pub fn field_name(&self) -> Option<&'tree str> {
1669 unsafe {
1670 let ptr = ffi::ts_tree_cursor_current_field_name(&raw const self.0);
1671 (!ptr.is_null()).then(|| CStr::from_ptr(ptr).to_str().unwrap())
1672 }
1673 }
1674
1675 #[doc(alias = "ts_tree_cursor_current_depth")]
1678 #[must_use]
1679 pub fn depth(&self) -> u32 {
1680 unsafe { ffi::ts_tree_cursor_current_depth(&raw const self.0) }
1681 }
1682
1683 #[doc(alias = "ts_tree_cursor_current_descendant_index")]
1686 #[must_use]
1687 pub fn descendant_index(&self) -> usize {
1688 unsafe { ffi::ts_tree_cursor_current_descendant_index(&raw const self.0) as usize }
1689 }
1690
1691 #[doc(alias = "ts_tree_cursor_goto_first_child")]
1696 pub fn goto_first_child(&mut self) -> bool {
1697 unsafe { ffi::ts_tree_cursor_goto_first_child(&raw mut self.0) }
1698 }
1699
1700 #[doc(alias = "ts_tree_cursor_goto_last_child")]
1709 pub fn goto_last_child(&mut self) -> bool {
1710 unsafe { ffi::ts_tree_cursor_goto_last_child(&raw mut self.0) }
1711 }
1712
1713 #[doc(alias = "ts_tree_cursor_goto_parent")]
1722 pub fn goto_parent(&mut self) -> bool {
1723 unsafe { ffi::ts_tree_cursor_goto_parent(&raw mut self.0) }
1724 }
1725
1726 #[doc(alias = "ts_tree_cursor_goto_next_sibling")]
1734 pub fn goto_next_sibling(&mut self) -> bool {
1735 unsafe { ffi::ts_tree_cursor_goto_next_sibling(&raw mut self.0) }
1736 }
1737
1738 #[doc(alias = "ts_tree_cursor_goto_descendant")]
1742 pub fn goto_descendant(&mut self, descendant_index: usize) {
1743 unsafe { ffi::ts_tree_cursor_goto_descendant(&raw mut self.0, descendant_index as u32) }
1744 }
1745
1746 #[doc(alias = "ts_tree_cursor_goto_previous_sibling")]
1758 pub fn goto_previous_sibling(&mut self) -> bool {
1759 unsafe { ffi::ts_tree_cursor_goto_previous_sibling(&raw mut self.0) }
1760 }
1761
1762 #[doc(alias = "ts_tree_cursor_goto_first_child_for_byte")]
1768 pub fn goto_first_child_for_byte(&mut self, index: usize) -> Option<usize> {
1769 let result =
1770 unsafe { ffi::ts_tree_cursor_goto_first_child_for_byte(&raw mut self.0, index as u32) };
1771 result.try_into().ok()
1772 }
1773
1774 #[doc(alias = "ts_tree_cursor_goto_first_child_for_point")]
1780 pub fn goto_first_child_for_point(&mut self, point: Point) -> Option<usize> {
1781 let result = unsafe {
1782 ffi::ts_tree_cursor_goto_first_child_for_point(&raw mut self.0, point.into())
1783 };
1784 result.try_into().ok()
1785 }
1786
1787 #[doc(alias = "ts_tree_cursor_reset")]
1790 pub fn reset(&mut self, node: Node<'tree>) {
1791 unsafe { ffi::ts_tree_cursor_reset(&raw mut self.0, node.0) };
1792 }
1793
1794 #[doc(alias = "ts_tree_cursor_reset_to")]
1799 pub fn reset_to(&mut self, cursor: &Self) {
1800 unsafe { ffi::ts_tree_cursor_reset_to(&raw mut self.0, &raw const cursor.0) };
1801 }
1802}
1803
1804impl Clone for TreeCursor<'_> {
1805 fn clone(&self) -> Self {
1806 TreeCursor(
1807 unsafe { ffi::ts_tree_cursor_copy(&raw const self.0) },
1808 PhantomData,
1809 )
1810 }
1811}
1812
1813impl Drop for TreeCursor<'_> {
1814 fn drop(&mut self) {
1815 unsafe { ffi::ts_tree_cursor_delete(&raw mut self.0) }
1816 }
1817}
1818
1819impl Point {
1820 #[must_use]
1821 pub const fn new(row: usize, column: usize) -> Self {
1822 Self { row, column }
1823 }
1824}
1825
1826impl fmt::Display for Point {
1827 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1828 write!(f, "({}, {})", self.row, self.column)
1829 }
1830}
1831
1832impl From<Point> for ffi::TSPoint {
1833 fn from(val: Point) -> Self {
1834 Self {
1835 row: val.row as u32,
1836 column: val.column as u32,
1837 }
1838 }
1839}
1840
1841impl From<ffi::TSPoint> for Point {
1842 fn from(point: ffi::TSPoint) -> Self {
1843 Self {
1844 row: point.row as usize,
1845 column: point.column as usize,
1846 }
1847 }
1848}
1849
1850impl From<Range> for ffi::TSRange {
1851 fn from(val: Range) -> Self {
1852 Self {
1853 start_byte: val.start_byte as u32,
1854 end_byte: val.end_byte as u32,
1855 start_point: val.start_point.into(),
1856 end_point: val.end_point.into(),
1857 }
1858 }
1859}
1860
1861impl From<ffi::TSRange> for Range {
1862 fn from(range: ffi::TSRange) -> Self {
1863 Self {
1864 start_byte: range.start_byte as usize,
1865 end_byte: range.end_byte as usize,
1866 start_point: range.start_point.into(),
1867 end_point: range.end_point.into(),
1868 }
1869 }
1870}
1871
1872impl fmt::Display for IncludedRangesError {
1873 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1874 write!(f, "Incorrect range by index: {}", self.0)
1875 }
1876}
1877
1878impl fmt::Display for LanguageError {
1879 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1880 match self {
1881 Self::Version(version) => {
1882 write!(
1883 f,
1884 "Incompatible language version {version:#x}. Expected {LANGUAGE_VERSION:#x}",
1885 )
1886 }
1887 Self::NotParseable => {
1888 write!(f, "Language cannot be used for parsing.")
1889 }
1890 #[cfg(feature = "wasm")]
1891 Self::Wasm => {
1892 write!(f, "Failed to load the Wasm store.")
1893 }
1894 }
1895 }
1896}
1897
1898pub fn wasm_stdlib_symbols() -> impl Iterator<Item = &'static str> {
1899 const WASM_STDLIB_SYMBOLS: &str = include_str!(concat!(env!("OUT_DIR"), "/stdlib-symbols.txt"));
1900
1901 WASM_STDLIB_SYMBOLS
1902 .lines()
1903 .map(|s| s.trim_matches(|c| c == '"' || c == ','))
1904}
1905
1906unsafe extern "C" {
1907 fn ts_node_string_pretty(node: ffi::TSNode, initial_indent_level: usize) -> *mut c_char;
1908 static mut ts_current_free: unsafe extern "C" fn(ptr: *mut c_void);
1909}
1910
1911#[inline]
1914unsafe fn ts_free(ptr: *mut c_void) {
1915 let f = unsafe { core::ptr::addr_of!(ts_current_free).read() };
1916 unsafe { f(ptr) };
1917}
1918
1919#[derive(Copy, Clone)]
1921pub struct Allocator {
1922 pub malloc: unsafe extern "C" fn(size: usize) -> *mut c_void,
1923 pub calloc: unsafe extern "C" fn(nmemb: usize, size: usize) -> *mut c_void,
1924 pub realloc: unsafe extern "C" fn(ptr: *mut c_void, size: usize) -> *mut c_void,
1925 pub free: unsafe extern "C" fn(ptr: *mut c_void),
1926}
1927
1928#[doc(alias = "ts_set_allocator")]
1947pub unsafe fn set_allocator(allocator: Option<Allocator>) {
1948 let (m, c, r, f) = match allocator {
1949 Some(a) => (
1950 Some(a.malloc),
1951 Some(a.calloc),
1952 Some(a.realloc),
1953 Some(a.free),
1954 ),
1955 None => (None, None, None, None),
1956 };
1957 unsafe { ffi::ts_set_allocator(m, c, r, f) };
1958}
1959
1960#[cfg(feature = "std")]
1961#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
1962impl error::Error for IncludedRangesError {}
1963#[cfg(feature = "std")]
1964#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
1965impl error::Error for LanguageError {}
1966
1967#[cfg(not(target_family = "wasm"))]
1968unsafe impl Send for Language {}
1969#[cfg(not(target_family = "wasm"))]
1970unsafe impl Sync for Language {}
1971
1972unsafe impl Send for Node<'_> {}
1973unsafe impl Sync for Node<'_> {}
1974
1975#[cfg(not(target_family = "wasm"))]
1976unsafe impl Send for Parser {}
1977#[cfg(not(target_family = "wasm"))]
1978unsafe impl Sync for Parser {}
1979
1980unsafe impl Send for Tree {}
1981unsafe impl Sync for Tree {}
1982
1983unsafe impl Send for TreeCursor<'_> {}
1984unsafe impl Sync for TreeCursor<'_> {}