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;
9mod util;
10
11pub use lookahead::LookaheadIterator;
12#[doc(hidden)]
13pub use sexp::format_sexp;
14
15#[cfg(any(
16 not(feature = "std"),
17 all(target_arch = "wasm32", target_os = "unknown")
18))]
19extern crate alloc;
20#[cfg(not(feature = "std"))]
21use alloc::{
22 boxed::Box,
23 string::{String, ToString},
24 vec::Vec,
25};
26use core::{
27 ffi::{CStr, c_char, c_void},
28 fmt, hash, iter,
29 marker::PhantomData,
30 num::NonZeroU16,
31 ops::{ControlFlow, Deref},
32 ptr::{self, NonNull},
33 slice, str,
34};
35#[cfg(feature = "std")]
36use std::error;
37#[cfg(all(unix, feature = "std"))]
38use std::os::fd::AsRawFd;
39#[cfg(all(windows, feature = "std"))]
40use std::os::windows::io::AsRawHandle;
41
42use tree_sitter_language::LanguageFn;
43
44#[cfg(feature = "wasm")]
45mod wasm_language;
46#[cfg(feature = "wasm")]
47#[cfg_attr(docsrs, doc(cfg(feature = "wasm")))]
48pub use wasm_language::*;
49
50#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
51mod wasm_allocator;
52
53#[doc(alias = "TREE_SITTER_LANGUAGE_VERSION")]
61pub const LANGUAGE_VERSION: usize = ffi::TREE_SITTER_LANGUAGE_VERSION as usize;
62
63#[doc(alias = "TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION")]
67pub const MIN_COMPATIBLE_LANGUAGE_VERSION: usize =
68 ffi::TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION as usize;
69
70pub const PARSER_HEADER: &str = include_str!("../src/parser.h");
71
72#[doc(alias = "TSLanguage")]
75#[derive(Debug, PartialEq, Eq, Hash)]
76#[repr(transparent)]
77pub struct Language(pub(crate) *const ffi::TSLanguage);
78
79pub struct LanguageRef<'a>(
80 pub(crate) *const ffi::TSLanguage,
81 pub(crate) PhantomData<&'a ()>,
82);
83
84#[doc(alias = "TSLanguageMetadata")]
89pub struct LanguageMetadata {
90 pub major_version: u8,
91 pub minor_version: u8,
92 pub patch_version: u8,
93}
94
95impl From<ffi::TSLanguageMetadata> for LanguageMetadata {
96 fn from(val: ffi::TSLanguageMetadata) -> Self {
97 Self {
98 major_version: val.major_version,
99 minor_version: val.minor_version,
100 patch_version: val.patch_version,
101 }
102 }
103}
104
105#[doc(alias = "TSTree")]
107pub struct Tree(NonNull<ffi::TSTree>);
108
109#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord)]
113pub struct Point {
114 pub row: usize,
115 pub column: usize,
116}
117
118#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
121pub struct Range {
122 pub start_byte: usize,
123 pub end_byte: usize,
124 pub start_point: Point,
125 pub end_point: Point,
126}
127
128#[derive(Clone, Copy, Debug, PartialEq, Eq)]
130pub struct InputEdit {
131 pub start_byte: usize,
132 pub old_end_byte: usize,
133 pub new_end_byte: usize,
134 pub start_position: Point,
135 pub old_end_position: Point,
136 pub new_end_position: Point,
137}
138
139impl InputEdit {
140 #[doc(alias = "ts_point_edit")]
146 pub fn edit_point(&self, point: &mut Point, byte: &mut usize) {
147 let edit = self.into();
148 let mut ts_point = (*point).into();
149 let mut ts_byte = *byte as u32;
150
151 unsafe {
152 ffi::ts_point_edit(
153 core::ptr::addr_of_mut!(ts_point),
154 core::ptr::addr_of_mut!(ts_byte),
155 &raw const edit,
156 );
157 }
158
159 *point = ts_point.into();
160 *byte = ts_byte as usize;
161 }
162
163 #[doc(alias = "ts_range_edit")]
169 pub fn edit_range(&self, range: &mut Range) {
170 let edit = self.into();
171 let mut ts_range = (*range).into();
172
173 unsafe {
174 ffi::ts_range_edit(core::ptr::addr_of_mut!(ts_range), &raw const edit);
175 }
176
177 *range = ts_range.into();
178 }
179}
180
181#[doc(alias = "TSNode")]
183#[derive(Clone, Copy)]
184#[repr(transparent)]
185pub struct Node<'tree>(ffi::TSNode, PhantomData<&'tree ()>);
186
187#[doc(alias = "TSParser")]
190pub struct Parser(NonNull<ffi::TSParser>);
191
192pub struct ParseState(NonNull<ffi::TSParseState>);
195
196impl ParseState {
197 #[must_use]
198 pub const fn current_byte_offset(&self) -> usize {
199 unsafe { self.0.as_ref() }.current_byte_offset as usize
200 }
201
202 #[must_use]
203 pub const fn has_error(&self) -> bool {
204 unsafe { self.0.as_ref() }.has_error
205 }
206}
207
208#[derive(Default)]
209pub struct ParseOptions<'a> {
210 pub progress_callback: Option<ParseProgressCallback<'a>>,
211}
212
213impl<'a> ParseOptions<'a> {
214 #[must_use]
215 pub fn new() -> Self {
216 Self::default()
217 }
218
219 #[must_use]
220 pub fn progress_callback<F: FnMut(&ParseState) -> ControlFlow<()>>(
221 mut self,
222 callback: &'a mut F,
223 ) -> Self {
224 self.progress_callback = Some(callback);
225 self
226 }
227
228 #[must_use]
233 pub fn reborrow(&mut self) -> ParseOptions {
234 ParseOptions {
235 progress_callback: match &mut self.progress_callback {
236 Some(cb) => Some(*cb),
237 None => None,
238 },
239 }
240 }
241}
242
243#[derive(Debug, PartialEq, Eq)]
245pub enum LogType {
246 Parse,
247 Lex,
248}
249
250type FieldId = NonZeroU16;
251
252type Logger = Box<dyn FnMut(LogType, &str) + Send + 'static>;
254
255type UnsafeLogger<'a> = Box<dyn FnMut(LogType, &str) + Send + 'a>;
257
258type ParseProgressCallback<'a> = &'a mut dyn FnMut(&ParseState) -> ControlFlow<()>;
260
261pub trait Decode {
262 fn decode(bytes: &[u8]) -> (i32, u32);
265}
266
267#[doc(alias = "TSTreeCursor")]
269pub struct TreeCursor<'tree>(ffi::TSTreeCursor, PhantomData<&'tree ()>);
270
271#[derive(Debug, PartialEq, Eq)]
275pub enum LanguageError {
276 Version(usize),
277 NotParseable,
278 #[cfg(feature = "wasm")]
279 Wasm,
280}
281
282#[derive(Debug, PartialEq, Eq)]
284pub struct IncludedRangesError(pub usize);
285
286impl Language {
287 #[must_use]
288 pub fn new(builder: LanguageFn) -> Self {
289 Self(unsafe { builder.into_raw()().cast() })
290 }
291
292 #[doc(alias = "ts_language_is_parseable")]
299 #[must_use]
300 pub fn is_parseable(&self) -> bool {
301 unsafe { ffi::ts_language_is_parseable(self.0) }
302 }
303
304 #[doc(alias = "ts_language_name")]
307 #[must_use]
308 pub fn name(&self) -> Option<&str> {
309 let ptr = unsafe { ffi::ts_language_name(self.0) };
310 (!ptr.is_null()).then(|| unsafe { CStr::from_ptr(ptr) }.to_str().unwrap())
311 }
312
313 #[doc(alias = "ts_language_abi_version")]
320 #[must_use]
321 pub fn abi_version(&self) -> usize {
322 unsafe { ffi::ts_language_abi_version(self.0) as usize }
323 }
324
325 #[doc(alias = "ts_language_metadata")]
332 #[must_use]
333 pub fn metadata(&self) -> Option<LanguageMetadata> {
334 unsafe {
335 let ptr = ffi::ts_language_metadata(self.0);
336 (!ptr.is_null()).then(|| (*ptr).into())
337 }
338 }
339
340 #[doc(alias = "ts_language_symbol_count")]
342 #[must_use]
343 pub fn node_kind_count(&self) -> usize {
344 unsafe { ffi::ts_language_symbol_count(self.0) as usize }
345 }
346
347 #[doc(alias = "ts_language_state_count")]
349 #[must_use]
350 pub fn parse_state_count(&self) -> usize {
351 unsafe { ffi::ts_language_state_count(self.0) as usize }
352 }
353
354 #[doc(alias = "ts_language_supertypes")]
357 #[must_use]
358 pub fn supertypes(&self) -> &[u16] {
359 let mut length = 0u32;
360 unsafe {
361 let ptr = ffi::ts_language_supertypes(self.0, core::ptr::addr_of_mut!(length));
362 if length == 0 {
363 &[]
364 } else {
365 slice::from_raw_parts(ptr.cast_mut(), length as usize)
366 }
367 }
368 }
369
370 #[doc(alias = "ts_language_supertype_map")]
373 #[must_use]
374 pub fn subtypes_for_supertype(&self, supertype: u16) -> &[u16] {
375 unsafe {
376 let mut length = 0u32;
377 let ptr = ffi::ts_language_subtypes(self.0, supertype, core::ptr::addr_of_mut!(length));
378 if length == 0 {
379 &[]
380 } else {
381 slice::from_raw_parts(ptr.cast_mut(), length as usize)
382 }
383 }
384 }
385
386 #[doc(alias = "ts_language_symbol_name")]
388 #[must_use]
389 pub fn node_kind_for_id(&self, id: u16) -> Option<&str> {
390 let ptr = unsafe { ffi::ts_language_symbol_name(self.0, id) };
391 (!ptr.is_null()).then(|| unsafe { CStr::from_ptr(ptr) }.to_str().unwrap())
392 }
393
394 #[doc(alias = "ts_language_symbol_for_name")]
396 #[must_use]
397 pub fn id_for_node_kind(&self, kind: &str, named: bool) -> u16 {
398 unsafe {
399 ffi::ts_language_symbol_for_name(
400 self.0,
401 kind.as_bytes().as_ptr().cast::<c_char>(),
402 kind.len() as u32,
403 named,
404 )
405 }
406 }
407
408 fn node_kind_id_is_valid(&self, id: u16) -> bool {
415 (id as usize) < self.node_kind_count() || id >= u16::MAX - 1
416 }
417
418 #[must_use]
421 pub fn node_kind_is_named(&self, id: u16) -> bool {
422 self.node_kind_id_is_valid(id)
423 && unsafe { ffi::ts_language_symbol_type(self.0, id) == ffi::TSSymbolTypeRegular }
424 }
425
426 #[must_use]
429 pub fn node_kind_is_visible(&self, id: u16) -> bool {
430 self.node_kind_id_is_valid(id)
431 && unsafe { ffi::ts_language_symbol_type(self.0, id) <= ffi::TSSymbolTypeAnonymous }
432 }
433
434 #[must_use]
436 pub fn node_kind_is_supertype(&self, id: u16) -> bool {
437 self.node_kind_id_is_valid(id)
438 && unsafe { ffi::ts_language_symbol_type(self.0, id) == ffi::TSSymbolTypeSupertype }
439 }
440
441 #[doc(alias = "ts_language_field_count")]
443 #[must_use]
444 pub fn field_count(&self) -> usize {
445 unsafe { ffi::ts_language_field_count(self.0) as usize }
446 }
447
448 #[doc(alias = "ts_language_field_name_for_id")]
450 #[must_use]
451 pub fn field_name_for_id(&self, field_id: u16) -> Option<&str> {
452 let ptr = unsafe { ffi::ts_language_field_name_for_id(self.0, field_id) };
453 (!ptr.is_null()).then(|| unsafe { CStr::from_ptr(ptr) }.to_str().unwrap())
454 }
455
456 #[doc(alias = "ts_language_field_id_for_name")]
458 #[must_use]
459 pub fn field_id_for_name(&self, field_name: impl AsRef<[u8]>) -> Option<FieldId> {
460 let field_name = field_name.as_ref();
461 let id = unsafe {
462 ffi::ts_language_field_id_for_name(
463 self.0,
464 field_name.as_ptr().cast::<c_char>(),
465 field_name.len() as u32,
466 )
467 };
468 FieldId::new(id)
469 }
470
471 #[doc(alias = "ts_language_next_state")]
480 #[must_use]
481 pub fn next_state(&self, state: u16, id: u16) -> u16 {
482 unsafe { ffi::ts_language_next_state(self.0, state, id) }
483 }
484
485 #[doc(alias = "ts_lookahead_iterator_new")]
505 #[must_use]
506 pub fn lookahead_iterator(&self, state: u16) -> Option<LookaheadIterator> {
507 let ptr = unsafe { ffi::ts_lookahead_iterator_new(self.0, state) };
508 (!ptr.is_null()).then(|| unsafe { LookaheadIterator::from_raw(ptr) })
509 }
510}
511
512impl From<LanguageFn> for Language {
513 fn from(value: LanguageFn) -> Self {
514 Self::new(value)
515 }
516}
517
518impl Clone for Language {
519 fn clone(&self) -> Self {
520 unsafe { Self(ffi::ts_language_copy(self.0)) }
521 }
522}
523
524impl Drop for Language {
525 fn drop(&mut self) {
526 unsafe { ffi::ts_language_delete(self.0) }
527 }
528}
529
530impl Deref for LanguageRef<'_> {
531 type Target = Language;
532
533 fn deref(&self) -> &Self::Target {
534 unsafe { &*(core::ptr::addr_of!(self.0).cast::<Language>()) }
535 }
536}
537
538impl Default for Parser {
539 fn default() -> Self {
540 Self::new()
541 }
542}
543
544impl Parser {
545 #[doc(alias = "ts_parser_new")]
547 #[must_use]
548 pub fn new() -> Self {
549 unsafe {
550 let parser = ffi::ts_parser_new();
551 Self(NonNull::new_unchecked(parser))
552 }
553 }
554
555 #[doc(alias = "ts_parser_set_language")]
563 pub fn set_language(&mut self, language: &Language) -> Result<(), LanguageError> {
564 let version = language.abi_version();
565 if (MIN_COMPATIBLE_LANGUAGE_VERSION..=LANGUAGE_VERSION).contains(&version) {
566 if !language.is_parseable() {
567 return Err(LanguageError::NotParseable);
568 }
569 #[cfg_attr(
570 not(feature = "wasm"),
571 expect(unused_variables, reason = "only used when wasm feature is enabled")
572 )]
573 let success = unsafe { ffi::ts_parser_set_language(self.0.as_ptr(), language.0) };
574 #[cfg(feature = "wasm")]
575 if !success {
576 return Err(LanguageError::Wasm);
577 }
578 Ok(())
579 } else {
580 Err(LanguageError::Version(version))
581 }
582 }
583
584 #[doc(alias = "ts_parser_language")]
586 #[must_use]
587 pub fn language(&self) -> Option<LanguageRef<'_>> {
588 let ptr = unsafe { ffi::ts_parser_language(self.0.as_ptr()) };
589 (!ptr.is_null()).then_some(LanguageRef(ptr, PhantomData))
590 }
591
592 #[doc(alias = "ts_parser_logger")]
594 #[must_use]
595 pub fn logger(&self) -> Option<&Logger> {
596 let logger = unsafe { ffi::ts_parser_logger(self.0.as_ptr()) };
597 unsafe { logger.payload.cast::<Logger>().as_ref() }
598 }
599
600 #[doc(alias = "ts_parser_set_logger")]
605 pub fn set_logger(&mut self, logger: Option<Logger>) {
606 unsafe { self.set_logger_unchecked(logger) };
608 }
609
610 pub unsafe fn set_logger_unchecked(&mut self, logger: Option<UnsafeLogger<'_>>) {
619 let prev_logger = unsafe { ffi::ts_parser_logger(self.0.as_ptr()) };
620 if !prev_logger.payload.is_null() {
621 drop(unsafe { Box::from_raw(prev_logger.payload.cast::<Logger>()) });
622 }
623
624 let c_logger = if let Some(logger) = logger {
625 let container = Box::new(logger);
626
627 unsafe extern "C" fn log(
628 payload: *mut c_void,
629 c_log_type: ffi::TSLogType,
630 c_message: *const c_char,
631 ) {
632 unsafe {
633 let callback = payload.cast::<Logger>().as_mut().unwrap();
634 if let Ok(message) = CStr::from_ptr(c_message).to_str() {
635 let log_type = if c_log_type == ffi::TSLogTypeParse {
636 LogType::Parse
637 } else {
638 LogType::Lex
639 };
640 callback(log_type, message);
641 }
642 }
643 }
644
645 let raw_container = Box::into_raw(container);
646
647 ffi::TSLogger {
648 payload: raw_container.cast::<c_void>(),
649 log: Some(log),
650 }
651 } else {
652 ffi::TSLogger {
653 payload: ptr::null_mut(),
654 log: None,
655 }
656 };
657
658 unsafe { ffi::ts_parser_set_logger(self.0.as_ptr(), c_logger) };
659 }
660
661 #[doc(alias = "ts_parser_print_dot_graphs")]
666 #[cfg(not(target_os = "wasi"))]
667 #[cfg(feature = "std")]
668 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
669 pub fn print_dot_graphs(
670 &mut self,
671 #[cfg(unix)] file: &impl AsRawFd,
672 #[cfg(windows)] file: &impl AsRawHandle,
673 ) {
674 #[cfg(unix)]
675 {
676 let fd = file.as_raw_fd();
677 unsafe {
678 ffi::ts_parser_print_dot_graphs(self.0.as_ptr(), ffi::_ts_dup(fd));
679 }
680 }
681
682 #[cfg(windows)]
683 {
684 let handle = file.as_raw_handle();
685 unsafe {
686 ffi::ts_parser_print_dot_graphs(self.0.as_ptr(), ffi::_ts_dup(handle));
687 }
688 }
689 }
690
691 #[doc(alias = "ts_parser_print_dot_graphs")]
693 #[cfg(not(target_os = "wasi"))]
694 #[cfg(feature = "std")]
695 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
696 pub fn stop_printing_dot_graphs(&mut self) {
697 unsafe { ffi::ts_parser_print_dot_graphs(self.0.as_ptr(), -1) }
698 }
699
700 #[doc(alias = "ts_parser_parse")]
711 pub fn parse(&mut self, text: impl AsRef<[u8]>, old_tree: Option<&Tree>) -> Option<Tree> {
712 let bytes = text.as_ref();
713 if let Ok(len) = u32::try_from(bytes.len()) {
714 return unsafe {
715 self.parse_raw_bytes(
716 (bytes.as_ptr().cast::<c_char>(), len),
717 old_tree,
718 ffi::TSInputEncodingUTF8,
719 )
720 };
721 }
722 let len = bytes.len();
723 self.parse_with_options(
724 &mut |i, _| {
725 if i < len {
726 &bytes[i..]
727 } else {
728 Default::default()
729 }
730 },
731 old_tree,
732 None,
733 )
734 }
735
736 pub fn parse_with_options<T: AsRef<[u8]>, F: FnMut(usize, Point) -> T>(
748 &mut self,
749 callback: &mut F,
750 old_tree: Option<&Tree>,
751 options: Option<ParseOptions>,
752 ) -> Option<Tree> {
753 self.parse_chunks::<0, u8, T, F>(
754 callback,
755 old_tree,
756 (options, ffi::TSInputEncodingUTF8, None),
757 )
758 }
759
760 pub fn parse_utf16_le(
768 &mut self,
769 input: impl AsRef<[u16]>,
770 old_tree: Option<&Tree>,
771 ) -> Option<Tree> {
772 self.parse_utf16_slice::<true>(input.as_ref(), old_tree)
773 }
774
775 pub fn parse_utf16_le_with_options<T: AsRef<[u16]>, F: FnMut(usize, Point) -> T>(
787 &mut self,
788 callback: &mut F,
789 old_tree: Option<&Tree>,
790 options: Option<ParseOptions>,
791 ) -> Option<Tree> {
792 self.parse_utf16_with_options::<true, T, F>(callback, old_tree, options)
793 }
794
795 pub fn parse_utf16_be(
803 &mut self,
804 input: impl AsRef<[u16]>,
805 old_tree: Option<&Tree>,
806 ) -> Option<Tree> {
807 self.parse_utf16_slice::<false>(input.as_ref(), old_tree)
808 }
809
810 pub fn parse_utf16_be_with_options<T: AsRef<[u16]>, F: FnMut(usize, Point) -> T>(
822 &mut self,
823 callback: &mut F,
824 old_tree: Option<&Tree>,
825 options: Option<ParseOptions>,
826 ) -> Option<Tree> {
827 self.parse_utf16_with_options::<false, T, F>(callback, old_tree, options)
828 }
829
830 pub fn parse_custom_encoding<D: Decode, T: AsRef<[u8]>, F: FnMut(usize, Point) -> T>(
847 &mut self,
848 callback: &mut F,
849 old_tree: Option<&Tree>,
850 options: Option<ParseOptions>,
851 ) -> Option<Tree> {
852 unsafe extern "C" fn decode_fn<D: Decode>(
853 data: *const u8,
854 len: u32,
855 code_point: *mut i32,
856 ) -> u32 {
857 unsafe {
858 let (c, len) = D::decode(core::slice::from_raw_parts(data, len as usize));
859 if let Some(code_point) = code_point.as_mut() {
860 *code_point = c;
861 }
862 len
863 }
864 }
865
866 self.parse_chunks::<0, u8, T, F>(
867 callback,
868 old_tree,
869 (options, ffi::TSInputEncodingCustom, Some(decode_fn::<D>)),
870 )
871 }
872
873 fn parse_utf16_slice<const LE: bool>(
874 &mut self,
875 code_points: &[u16],
876 old_tree: Option<&Tree>,
877 ) -> Option<Tree> {
878 let encoding = if LE {
879 ffi::TSInputEncodingUTF16LE
880 } else {
881 ffi::TSInputEncodingUTF16BE
882 };
883 if let Some(byte_len) = code_points
884 .len()
885 .checked_mul(2)
886 .and_then(|n| u32::try_from(n).ok())
887 {
888 return unsafe {
889 self.parse_raw_bytes(
890 (code_points.as_ptr().cast::<c_char>(), byte_len),
891 old_tree,
892 encoding,
893 )
894 };
895 }
896 let len = code_points.len();
897 self.parse_utf16_with_options::<LE, _, _>(
898 &mut |i, _| if i < len { &code_points[i..] } else { &[] },
899 old_tree,
900 None,
901 )
902 }
903
904 fn parse_utf16_with_options<const LE: bool, T: AsRef<[u16]>, F: FnMut(usize, Point) -> T>(
905 &mut self,
906 callback: &mut F,
907 old_tree: Option<&Tree>,
908 options: Option<ParseOptions>,
909 ) -> Option<Tree> {
910 let encoding = if LE {
911 ffi::TSInputEncodingUTF16LE
912 } else {
913 ffi::TSInputEncodingUTF16BE
914 };
915 self.parse_chunks::<1, u16, T, F>(callback, old_tree, (options, encoding, None))
916 }
917
918 fn parse_chunks<const UNIT_SHIFT: u32, U, T: AsRef<[U]>, F: FnMut(usize, Point) -> T>(
919 &mut self,
920 callback: &mut F,
921 old_tree: Option<&Tree>,
922 (options, encoding, decode): (
923 Option<ParseOptions>,
924 ffi::TSInputEncoding,
925 ffi::TSDecodeFunction,
926 ),
927 ) -> Option<Tree> {
928 type Payload<'a, F, T> = (&'a mut F, Option<T>);
929
930 unsafe extern "C" fn read<
931 const UNIT_SHIFT: u32,
932 U,
933 T: AsRef<[U]>,
934 F: FnMut(usize, Point) -> T,
935 >(
936 payload: *mut c_void,
937 byte_offset: u32,
938 position: ffi::TSPoint,
939 bytes_read: *mut u32,
940 ) -> *const c_char {
941 unsafe {
942 let (callback, text) = payload.cast::<Payload<F, T>>().as_mut().unwrap();
943 *text = Some(callback(
944 (byte_offset as usize) >> UNIT_SHIFT,
945 Point {
946 row: position.row as usize,
947 column: (position.column as usize) >> UNIT_SHIFT,
948 },
949 ));
950 let slice = text.as_ref().unwrap().as_ref();
951 *bytes_read =
952 (slice.len().min((u32::MAX as usize) >> UNIT_SHIFT) << UNIT_SHIFT) as u32;
953 slice.as_ptr().cast::<c_char>()
954 }
955 }
956
957 let mut payload: Payload<F, T> = (callback, None);
959 let c_input = ffi::TSInput {
960 payload: ptr::addr_of_mut!(payload).cast::<c_void>(),
961 read: Some(read::<UNIT_SHIFT, U, T, F>),
962 encoding,
963 decode,
964 };
965 unsafe { self.parse_c_input(c_input, old_tree, options) }
966 }
967
968 unsafe fn parse_raw_bytes(
969 &mut self,
970 (bytes, byte_len): (*const c_char, u32),
971 old_tree: Option<&Tree>,
972 encoding: ffi::TSInputEncoding,
973 ) -> Option<Tree> {
974 let c_old_tree = old_tree.map_or(ptr::null(), |t| t.0.as_ptr().cast_const());
975 let c_new_tree = unsafe {
976 ffi::ts_parser_parse_string_encoding(
977 self.0.as_ptr(),
978 c_old_tree,
979 bytes,
980 byte_len,
981 encoding,
982 )
983 };
984 NonNull::new(c_new_tree).map(Tree)
985 }
986
987 unsafe fn parse_c_input(
988 &mut self,
989 c_input: ffi::TSInput,
990 old_tree: Option<&Tree>,
991 options: Option<ParseOptions>,
992 ) -> Option<Tree> {
993 unsafe extern "C" fn progress(state: *mut ffi::TSParseState) -> bool {
994 unsafe {
995 let callback = (*state)
996 .payload
997 .cast::<ParseProgressCallback>()
998 .as_mut()
999 .unwrap();
1000 match callback(&ParseState::from_raw(state)) {
1001 ControlFlow::Continue(()) => false,
1002 ControlFlow::Break(()) => true,
1003 }
1004 }
1005 }
1006
1007 let mut callback_ptr;
1008 let parse_options = if let Some(cb) = options.and_then(|o| o.progress_callback) {
1009 callback_ptr = cb;
1010 ffi::TSParseOptions {
1011 payload: core::ptr::addr_of_mut!(callback_ptr).cast::<c_void>(),
1012 progress_callback: Some(progress),
1013 }
1014 } else {
1015 ffi::TSParseOptions {
1016 payload: ptr::null_mut(),
1017 progress_callback: None,
1018 }
1019 };
1020
1021 let c_old_tree = old_tree.map_or(ptr::null_mut(), |t| t.0.as_ptr());
1022 let c_new_tree = unsafe {
1023 ffi::ts_parser_parse_with_options(self.0.as_ptr(), c_old_tree, c_input, parse_options)
1024 };
1025 NonNull::new(c_new_tree).map(Tree)
1026 }
1027
1028 #[doc(alias = "ts_parser_reset")]
1035 pub fn reset(&mut self) {
1036 unsafe { ffi::ts_parser_reset(self.0.as_ptr()) }
1037 }
1038
1039 #[doc(alias = "ts_parser_set_included_ranges")]
1057 pub fn set_included_ranges(&mut self, ranges: &[Range]) -> Result<(), IncludedRangesError> {
1058 let ts_ranges = ranges.iter().copied().map(Into::into).collect::<Vec<_>>();
1059 let result = unsafe {
1060 ffi::ts_parser_set_included_ranges(
1061 self.0.as_ptr(),
1062 ts_ranges.as_ptr(),
1063 ts_ranges.len() as u32,
1064 )
1065 };
1066
1067 if result {
1068 Ok(())
1069 } else {
1070 let mut prev_end_byte = 0;
1071 for (i, range) in ranges.iter().enumerate() {
1072 if range.start_byte < prev_end_byte || range.end_byte < range.start_byte {
1073 return Err(IncludedRangesError(i));
1074 }
1075 prev_end_byte = range.end_byte;
1076 }
1077 Err(IncludedRangesError(0))
1078 }
1079 }
1080
1081 #[doc(alias = "ts_parser_included_ranges")]
1083 #[must_use]
1084 pub fn included_ranges(&self) -> Vec<Range> {
1085 let mut count = 0u32;
1086 unsafe {
1087 let ptr =
1088 ffi::ts_parser_included_ranges(self.0.as_ptr(), core::ptr::addr_of_mut!(count));
1089 let ranges = slice::from_raw_parts(ptr, count as usize);
1090 ranges.iter().copied().map(Into::into).collect()
1091 }
1092 }
1093}
1094
1095impl Drop for Parser {
1096 fn drop(&mut self) {
1097 #[cfg(feature = "std")]
1098 #[cfg(not(target_os = "wasi"))]
1099 {
1100 self.stop_printing_dot_graphs();
1101 }
1102 self.set_logger(None);
1103 unsafe { ffi::ts_parser_delete(self.0.as_ptr()) }
1104 }
1105}
1106
1107#[cfg(windows)]
1108unsafe extern "C" {
1109 fn _open_osfhandle(osfhandle: isize, flags: core::ffi::c_int) -> core::ffi::c_int;
1110}
1111
1112impl Tree {
1113 #[doc(alias = "ts_tree_root_node")]
1115 #[must_use]
1116 pub fn root_node(&self) -> Node {
1117 Node::new(unsafe { ffi::ts_tree_root_node(self.0.as_ptr()) }).unwrap()
1118 }
1119
1120 #[doc(alias = "ts_tree_root_node_with_offset")]
1123 #[must_use]
1124 pub fn root_node_with_offset(&self, offset_bytes: usize, offset_extent: Point) -> Node {
1125 Node::new(unsafe {
1126 ffi::ts_tree_root_node_with_offset(
1127 self.0.as_ptr(),
1128 offset_bytes as u32,
1129 offset_extent.into(),
1130 )
1131 })
1132 .unwrap()
1133 }
1134
1135 #[doc(alias = "ts_tree_language")]
1142 #[must_use]
1143 pub fn language(&self) -> LanguageRef {
1144 LanguageRef(
1145 unsafe { ffi::ts_tree_language(self.0.as_ptr()) },
1146 PhantomData,
1147 )
1148 }
1149
1150 #[doc(alias = "ts_tree_edit")]
1156 pub fn edit(&mut self, edit: &InputEdit) {
1157 let edit = edit.into();
1158 unsafe { ffi::ts_tree_edit(self.0.as_ptr(), &raw const edit) };
1159 }
1160
1161 #[must_use]
1163 pub fn walk(&self) -> TreeCursor {
1164 self.root_node().walk()
1165 }
1166
1167 #[doc(alias = "ts_tree_get_changed_ranges")]
1177 pub fn changed_ranges(&self, other: &Self) -> impl ExactSizeIterator<Item = Range> {
1178 let mut count = 0u32;
1179 unsafe {
1180 let ptr = ffi::ts_tree_get_changed_ranges(
1181 self.0.as_ptr(),
1182 other.0.as_ptr(),
1183 core::ptr::addr_of_mut!(count),
1184 );
1185 util::CBufferIter::new(ptr, count as usize).map(Into::into)
1186 }
1187 }
1188
1189 #[doc(alias = "ts_tree_included_ranges")]
1191 #[must_use]
1192 pub fn included_ranges(&self) -> Vec<Range> {
1193 let mut count = 0u32;
1194 unsafe {
1195 let ptr = ffi::ts_tree_included_ranges(self.0.as_ptr(), core::ptr::addr_of_mut!(count));
1196 let ranges = slice::from_raw_parts(ptr, count as usize);
1197 let result = ranges.iter().copied().map(Into::into).collect();
1198 ts_free(ptr.cast::<c_void>());
1199 result
1200 }
1201 }
1202
1203 #[doc(alias = "ts_tree_print_dot_graph")]
1208 #[cfg(not(target_os = "wasi"))]
1209 #[cfg(feature = "std")]
1210 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
1211 pub fn print_dot_graph(
1212 &self,
1213 #[cfg(unix)] file: &impl AsRawFd,
1214 #[cfg(windows)] file: &impl AsRawHandle,
1215 ) {
1216 #[cfg(unix)]
1217 {
1218 let fd = file.as_raw_fd();
1219 unsafe { ffi::ts_tree_print_dot_graph(self.0.as_ptr(), fd) }
1220 }
1221
1222 #[cfg(windows)]
1223 {
1224 let handle = file.as_raw_handle();
1225 let fd = unsafe { _open_osfhandle(handle as isize, 0) };
1226 unsafe { ffi::ts_tree_print_dot_graph(self.0.as_ptr(), fd) }
1227 }
1228 }
1229}
1230
1231impl fmt::Debug for Tree {
1232 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1233 write!(f, "{{Tree {:?}}}", self.root_node())
1234 }
1235}
1236
1237impl Drop for Tree {
1238 fn drop(&mut self) {
1239 unsafe { ffi::ts_tree_delete(self.0.as_ptr()) }
1240 }
1241}
1242
1243impl Clone for Tree {
1244 fn clone(&self) -> Self {
1245 unsafe { Self(NonNull::new_unchecked(ffi::ts_tree_copy(self.0.as_ptr()))) }
1246 }
1247}
1248
1249impl<'tree> Node<'tree> {
1250 fn new(node: ffi::TSNode) -> Option<Self> {
1251 (!node.id.is_null()).then_some(Node(node, PhantomData))
1252 }
1253
1254 #[must_use]
1265 pub fn id(&self) -> usize {
1266 self.0.id as usize
1267 }
1268
1269 #[doc(alias = "ts_node_symbol")]
1271 #[must_use]
1272 pub fn kind_id(&self) -> u16 {
1273 unsafe { ffi::ts_node_symbol(self.0) }
1274 }
1275
1276 #[doc(alias = "ts_node_grammar_symbol")]
1279 #[must_use]
1280 pub fn grammar_id(&self) -> u16 {
1281 unsafe { ffi::ts_node_grammar_symbol(self.0) }
1282 }
1283
1284 #[doc(alias = "ts_node_type")]
1286 #[must_use]
1287 pub fn kind(&self) -> &'tree str {
1288 let ptr = unsafe { ffi::ts_node_type(self.0) };
1289 assert!(!ptr.is_null());
1290 unsafe { CStr::from_ptr(ptr) }.to_str().unwrap()
1291 }
1292
1293 #[doc(alias = "ts_node_grammar_type")]
1296 #[must_use]
1297 pub fn grammar_name(&self) -> &'tree str {
1298 let ptr = unsafe { ffi::ts_node_grammar_type(self.0) };
1299 assert!(!ptr.is_null());
1300 unsafe { CStr::from_ptr(ptr) }.to_str().unwrap()
1301 }
1302
1303 #[doc(alias = "ts_node_language")]
1311 #[must_use]
1312 pub fn language(&self) -> LanguageRef<'tree> {
1313 LanguageRef(unsafe { ffi::ts_node_language(self.0) }, PhantomData)
1314 }
1315
1316 #[doc(alias = "ts_node_is_named")]
1321 #[must_use]
1322 pub fn is_named(&self) -> bool {
1323 unsafe { ffi::ts_node_is_named(self.0) }
1324 }
1325
1326 #[doc(alias = "ts_node_is_extra")]
1331 #[must_use]
1332 pub fn is_extra(&self) -> bool {
1333 unsafe { ffi::ts_node_is_extra(self.0) }
1334 }
1335
1336 #[doc(alias = "ts_node_has_changes")]
1338 #[must_use]
1339 pub fn has_changes(&self) -> bool {
1340 unsafe { ffi::ts_node_has_changes(self.0) }
1341 }
1342
1343 #[doc(alias = "ts_node_has_error")]
1346 #[must_use]
1347 pub fn has_error(&self) -> bool {
1348 unsafe { ffi::ts_node_has_error(self.0) }
1349 }
1350
1351 #[doc(alias = "ts_node_is_error")]
1356 #[must_use]
1357 pub fn is_error(&self) -> bool {
1358 unsafe { ffi::ts_node_is_error(self.0) }
1359 }
1360
1361 #[doc(alias = "ts_node_parse_state")]
1370 #[must_use]
1371 pub fn parse_state(&self) -> u16 {
1372 unsafe { ffi::ts_node_parse_state(self.0) }
1373 }
1374
1375 #[doc(alias = "ts_node_next_parse_state")]
1377 #[must_use]
1378 pub fn next_parse_state(&self) -> u16 {
1379 unsafe { ffi::ts_node_next_parse_state(self.0) }
1380 }
1381
1382 #[doc(alias = "ts_node_is_missing")]
1387 #[must_use]
1388 pub fn is_missing(&self) -> bool {
1389 unsafe { ffi::ts_node_is_missing(self.0) }
1390 }
1391
1392 #[doc(alias = "ts_node_start_byte")]
1394 #[must_use]
1395 pub fn start_byte(&self) -> usize {
1396 unsafe { ffi::ts_node_start_byte(self.0) as usize }
1397 }
1398
1399 #[doc(alias = "ts_node_end_byte")]
1401 #[must_use]
1402 pub fn end_byte(&self) -> usize {
1403 unsafe { ffi::ts_node_end_byte(self.0) as usize }
1404 }
1405
1406 #[must_use]
1408 pub fn byte_range(&self) -> core::ops::Range<usize> {
1409 self.start_byte()..self.end_byte()
1410 }
1411
1412 #[must_use]
1415 pub fn range(&self) -> Range {
1416 Range {
1417 start_byte: self.start_byte(),
1418 end_byte: self.end_byte(),
1419 start_point: self.start_position(),
1420 end_point: self.end_position(),
1421 }
1422 }
1423
1424 #[doc(alias = "ts_node_start_point")]
1426 #[must_use]
1427 pub fn start_position(&self) -> Point {
1428 let result = unsafe { ffi::ts_node_start_point(self.0) };
1429 result.into()
1430 }
1431
1432 #[doc(alias = "ts_node_end_point")]
1434 #[must_use]
1435 pub fn end_position(&self) -> Point {
1436 let result = unsafe { ffi::ts_node_end_point(self.0) };
1437 result.into()
1438 }
1439
1440 #[doc(alias = "ts_node_child")]
1447 #[must_use]
1448 pub fn child(&self, i: u32) -> Option<Self> {
1449 Self::new(unsafe { ffi::ts_node_child(self.0, i) })
1450 }
1451
1452 #[doc(alias = "ts_node_child_count")]
1454 #[must_use]
1455 pub fn child_count(&self) -> u32 {
1456 unsafe { ffi::ts_node_child_count(self.0) }
1457 }
1458
1459 #[doc(alias = "ts_node_named_child")]
1466 #[must_use]
1467 pub fn named_child(&self, i: u32) -> Option<Self> {
1468 Self::new(unsafe { ffi::ts_node_named_child(self.0, i) })
1469 }
1470
1471 #[doc(alias = "ts_node_named_child_count")]
1475 #[must_use]
1476 pub fn named_child_count(&self) -> usize {
1477 unsafe { ffi::ts_node_named_child_count(self.0) as usize }
1478 }
1479
1480 #[doc(alias = "ts_node_child_by_field_name")]
1485 #[must_use]
1486 pub fn child_by_field_name(&self, field_name: impl AsRef<[u8]>) -> Option<Self> {
1487 let field_name = field_name.as_ref();
1488 Self::new(unsafe {
1489 ffi::ts_node_child_by_field_name(
1490 self.0,
1491 field_name.as_ptr().cast::<c_char>(),
1492 field_name.len() as u32,
1493 )
1494 })
1495 }
1496
1497 #[doc(alias = "ts_node_child_by_field_id")]
1502 #[must_use]
1503 pub fn child_by_field_id(&self, field_id: u16) -> Option<Self> {
1504 Self::new(unsafe { ffi::ts_node_child_by_field_id(self.0, field_id) })
1505 }
1506
1507 #[doc(alias = "ts_node_field_name_for_child")]
1509 #[must_use]
1510 pub fn field_name_for_child(&self, child_index: u32) -> Option<&'tree str> {
1511 unsafe {
1512 let ptr = ffi::ts_node_field_name_for_child(self.0, child_index);
1513 (!ptr.is_null()).then(|| CStr::from_ptr(ptr).to_str().unwrap())
1514 }
1515 }
1516
1517 #[must_use]
1519 pub fn field_name_for_named_child(&self, named_child_index: u32) -> Option<&'tree str> {
1520 unsafe {
1521 let ptr = ffi::ts_node_field_name_for_named_child(self.0, named_child_index);
1522 (!ptr.is_null()).then(|| CStr::from_ptr(ptr).to_str().unwrap())
1523 }
1524 }
1525
1526 pub fn children<'cursor>(
1536 &self,
1537 cursor: &'cursor mut TreeCursor<'tree>,
1538 ) -> impl ExactSizeIterator<Item = Node<'tree>> + 'cursor {
1539 cursor.reset(*self);
1540 cursor.goto_first_child();
1541 (0..self.child_count()).map(move |_| {
1542 let result = cursor.node();
1543 cursor.goto_next_sibling();
1544 result
1545 })
1546 }
1547
1548 pub fn named_children<'cursor>(
1552 &self,
1553 cursor: &'cursor mut TreeCursor<'tree>,
1554 ) -> impl ExactSizeIterator<Item = Node<'tree>> + 'cursor {
1555 cursor.reset(*self);
1556 cursor.goto_first_child();
1557 (0..self.named_child_count()).map(move |_| {
1558 while !cursor.node().is_named() {
1559 if !cursor.goto_next_sibling() {
1560 break;
1561 }
1562 }
1563 let result = cursor.node();
1564 cursor.goto_next_sibling();
1565 result
1566 })
1567 }
1568
1569 pub fn children_by_field_name<'cursor>(
1573 &self,
1574 field_name: &str,
1575 cursor: &'cursor mut TreeCursor<'tree>,
1576 ) -> impl Iterator<Item = Node<'tree>> + 'cursor {
1577 let field_id = self.language().field_id_for_name(field_name);
1578 let mut done = field_id.is_none();
1579 if !done {
1580 cursor.reset(*self);
1581 cursor.goto_first_child();
1582 }
1583 iter::from_fn(move || {
1584 if !done {
1585 while cursor.field_id() != field_id {
1586 if !cursor.goto_next_sibling() {
1587 return None;
1588 }
1589 }
1590 let result = cursor.node();
1591 if !cursor.goto_next_sibling() {
1592 done = true;
1593 }
1594 return Some(result);
1595 }
1596 None
1597 })
1598 }
1599
1600 pub fn children_by_field_id<'cursor>(
1604 &self,
1605 field_id: FieldId,
1606 cursor: &'cursor mut TreeCursor<'tree>,
1607 ) -> impl Iterator<Item = Node<'tree>> + 'cursor {
1608 cursor.reset(*self);
1609 cursor.goto_first_child();
1610 let mut done = false;
1611 iter::from_fn(move || {
1612 if !done {
1613 while cursor.field_id() != Some(field_id) {
1614 if !cursor.goto_next_sibling() {
1615 return None;
1616 }
1617 }
1618 let result = cursor.node();
1619 if !cursor.goto_next_sibling() {
1620 done = true;
1621 }
1622 return Some(result);
1623 }
1624 None
1625 })
1626 }
1627
1628 #[doc(alias = "ts_node_parent")]
1632 #[must_use]
1633 pub fn parent(&self) -> Option<Self> {
1634 Self::new(unsafe { ffi::ts_node_parent(self.0) })
1635 }
1636
1637 #[doc(alias = "ts_node_child_with_descendant")]
1641 #[must_use]
1642 pub fn child_with_descendant(&self, descendant: Self) -> Option<Self> {
1643 Self::new(unsafe { ffi::ts_node_child_with_descendant(self.0, descendant.0) })
1644 }
1645
1646 #[doc(alias = "ts_node_next_sibling")]
1648 #[must_use]
1649 pub fn next_sibling(&self) -> Option<Self> {
1650 Self::new(unsafe { ffi::ts_node_next_sibling(self.0) })
1651 }
1652
1653 #[doc(alias = "ts_node_prev_sibling")]
1655 #[must_use]
1656 pub fn prev_sibling(&self) -> Option<Self> {
1657 Self::new(unsafe { ffi::ts_node_prev_sibling(self.0) })
1658 }
1659
1660 #[doc(alias = "ts_node_next_named_sibling")]
1662 #[must_use]
1663 pub fn next_named_sibling(&self) -> Option<Self> {
1664 Self::new(unsafe { ffi::ts_node_next_named_sibling(self.0) })
1665 }
1666
1667 #[doc(alias = "ts_node_prev_named_sibling")]
1669 #[must_use]
1670 pub fn prev_named_sibling(&self) -> Option<Self> {
1671 Self::new(unsafe { ffi::ts_node_prev_named_sibling(self.0) })
1672 }
1673
1674 #[doc(alias = "ts_node_first_child_for_byte")]
1676 #[must_use]
1677 pub fn first_child_for_byte(&self, byte: usize) -> Option<Self> {
1678 Self::new(unsafe { ffi::ts_node_first_child_for_byte(self.0, byte as u32) })
1679 }
1680
1681 #[doc(alias = "ts_node_first_named_child_for_point")]
1683 #[must_use]
1684 pub fn first_named_child_for_byte(&self, byte: usize) -> Option<Self> {
1685 Self::new(unsafe { ffi::ts_node_first_named_child_for_byte(self.0, byte as u32) })
1686 }
1687
1688 #[doc(alias = "ts_node_descendant_count")]
1690 #[must_use]
1691 pub fn descendant_count(&self) -> usize {
1692 unsafe { ffi::ts_node_descendant_count(self.0) as usize }
1693 }
1694
1695 #[doc(alias = "ts_node_descendant_for_byte_range")]
1697 #[must_use]
1698 pub fn descendant_for_byte_range(&self, start: usize, end: usize) -> Option<Self> {
1699 Self::new(unsafe {
1700 ffi::ts_node_descendant_for_byte_range(self.0, start as u32, end as u32)
1701 })
1702 }
1703
1704 #[doc(alias = "ts_node_named_descendant_for_byte_range")]
1706 #[must_use]
1707 pub fn named_descendant_for_byte_range(&self, start: usize, end: usize) -> Option<Self> {
1708 Self::new(unsafe {
1709 ffi::ts_node_named_descendant_for_byte_range(self.0, start as u32, end as u32)
1710 })
1711 }
1712
1713 #[doc(alias = "ts_node_descendant_for_point_range")]
1715 #[must_use]
1716 pub fn descendant_for_point_range(&self, start: Point, end: Point) -> Option<Self> {
1717 Self::new(unsafe {
1718 ffi::ts_node_descendant_for_point_range(self.0, start.into(), end.into())
1719 })
1720 }
1721
1722 #[doc(alias = "ts_node_named_descendant_for_point_range")]
1724 #[must_use]
1725 pub fn named_descendant_for_point_range(&self, start: Point, end: Point) -> Option<Self> {
1726 Self::new(unsafe {
1727 ffi::ts_node_named_descendant_for_point_range(self.0, start.into(), end.into())
1728 })
1729 }
1730
1731 #[doc(alias = "ts_node_string")]
1733 #[must_use]
1734 pub fn to_sexp(&self) -> String {
1735 let c_string = unsafe { ffi::ts_node_string(self.0) };
1736 let result = unsafe { CStr::from_ptr(c_string) }
1737 .to_str()
1738 .unwrap()
1739 .to_string();
1740 unsafe { ts_free(c_string.cast::<c_void>()) };
1741 result
1742 }
1743
1744 pub fn utf8_text<'a>(&self, source: &'a [u8]) -> Result<&'a str, str::Utf8Error> {
1745 str::from_utf8(&source[self.start_byte()..self.end_byte()])
1746 }
1747
1748 #[must_use]
1749 pub fn utf16_text<'a>(&self, source: &'a [u16]) -> &'a [u16] {
1750 &source[self.start_byte() / 2..self.end_byte() / 2]
1751 }
1752
1753 #[doc(alias = "ts_tree_cursor_new")]
1758 #[must_use]
1759 pub fn walk(&self) -> TreeCursor<'tree> {
1760 TreeCursor(unsafe { ffi::ts_tree_cursor_new(self.0) }, PhantomData)
1761 }
1762
1763 #[doc(alias = "ts_node_edit")]
1771 pub fn edit(&mut self, edit: &InputEdit) {
1772 let edit = edit.into();
1773 unsafe { ffi::ts_node_edit(core::ptr::addr_of_mut!(self.0), &raw const edit) }
1774 }
1775}
1776
1777impl PartialEq for Node<'_> {
1778 fn eq(&self, other: &Self) -> bool {
1779 core::ptr::eq(self.0.id, other.0.id)
1780 }
1781}
1782
1783impl Eq for Node<'_> {}
1784
1785impl hash::Hash for Node<'_> {
1786 fn hash<H: hash::Hasher>(&self, state: &mut H) {
1787 self.0.id.hash(state);
1788 self.0.context[0].hash(state);
1789 self.0.context[1].hash(state);
1790 self.0.context[2].hash(state);
1791 self.0.context[3].hash(state);
1792 }
1793}
1794
1795impl fmt::Debug for Node<'_> {
1796 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1797 write!(
1798 f,
1799 "{{Node {} {} - {}}}",
1800 self.kind(),
1801 self.start_position(),
1802 self.end_position()
1803 )
1804 }
1805}
1806
1807impl fmt::Display for Node<'_> {
1808 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1809 if !f.alternate() {
1810 return f.write_str(&self.to_sexp());
1811 }
1812 let c_string = unsafe { ts_node_string_pretty(self.0, f.width().unwrap_or(0)) };
1813 let result = unsafe { CStr::from_ptr(c_string) }
1814 .to_str()
1815 .unwrap()
1816 .to_string();
1817 unsafe { ts_free(c_string.cast::<c_void>()) };
1818 f.write_str(&result)
1819 }
1820}
1821
1822impl<'tree> TreeCursor<'tree> {
1823 #[doc(alias = "ts_tree_cursor_current_node")]
1825 #[must_use]
1826 pub fn node(&self) -> Node<'tree> {
1827 Node(
1828 unsafe { ffi::ts_tree_cursor_current_node(&raw const self.0) },
1829 PhantomData,
1830 )
1831 }
1832
1833 #[doc(alias = "ts_tree_cursor_current_field_id")]
1837 #[must_use]
1838 pub fn field_id(&self) -> Option<FieldId> {
1839 let id = unsafe { ffi::ts_tree_cursor_current_field_id(&raw const self.0) };
1840 FieldId::new(id)
1841 }
1842
1843 #[doc(alias = "ts_tree_cursor_current_field_name")]
1845 #[must_use]
1846 pub fn field_name(&self) -> Option<&'tree str> {
1847 unsafe {
1848 let ptr = ffi::ts_tree_cursor_current_field_name(&raw const self.0);
1849 (!ptr.is_null()).then(|| CStr::from_ptr(ptr).to_str().unwrap())
1850 }
1851 }
1852
1853 #[doc(alias = "ts_tree_cursor_current_depth")]
1856 #[must_use]
1857 pub fn depth(&self) -> u32 {
1858 unsafe { ffi::ts_tree_cursor_current_depth(&raw const self.0) }
1859 }
1860
1861 #[doc(alias = "ts_tree_cursor_current_descendant_index")]
1864 #[must_use]
1865 pub fn descendant_index(&self) -> usize {
1866 unsafe { ffi::ts_tree_cursor_current_descendant_index(&raw const self.0) as usize }
1867 }
1868
1869 #[doc(alias = "ts_tree_cursor_goto_first_child")]
1874 pub fn goto_first_child(&mut self) -> bool {
1875 unsafe { ffi::ts_tree_cursor_goto_first_child(&raw mut self.0) }
1876 }
1877
1878 #[doc(alias = "ts_tree_cursor_goto_last_child")]
1887 pub fn goto_last_child(&mut self) -> bool {
1888 unsafe { ffi::ts_tree_cursor_goto_last_child(&raw mut self.0) }
1889 }
1890
1891 #[doc(alias = "ts_tree_cursor_goto_parent")]
1900 pub fn goto_parent(&mut self) -> bool {
1901 unsafe { ffi::ts_tree_cursor_goto_parent(&raw mut self.0) }
1902 }
1903
1904 #[doc(alias = "ts_tree_cursor_goto_next_sibling")]
1912 pub fn goto_next_sibling(&mut self) -> bool {
1913 unsafe { ffi::ts_tree_cursor_goto_next_sibling(&raw mut self.0) }
1914 }
1915
1916 #[doc(alias = "ts_tree_cursor_goto_descendant")]
1920 pub fn goto_descendant(&mut self, descendant_index: usize) {
1921 unsafe { ffi::ts_tree_cursor_goto_descendant(&raw mut self.0, descendant_index as u32) }
1922 }
1923
1924 #[doc(alias = "ts_tree_cursor_goto_previous_sibling")]
1936 pub fn goto_previous_sibling(&mut self) -> bool {
1937 unsafe { ffi::ts_tree_cursor_goto_previous_sibling(&raw mut self.0) }
1938 }
1939
1940 #[doc(alias = "ts_tree_cursor_goto_first_child_for_byte")]
1946 pub fn goto_first_child_for_byte(&mut self, index: usize) -> Option<usize> {
1947 let result =
1948 unsafe { ffi::ts_tree_cursor_goto_first_child_for_byte(&raw mut self.0, index as u32) };
1949 result.try_into().ok()
1950 }
1951
1952 #[doc(alias = "ts_tree_cursor_goto_first_child_for_point")]
1958 pub fn goto_first_child_for_point(&mut self, point: Point) -> Option<usize> {
1959 let result = unsafe {
1960 ffi::ts_tree_cursor_goto_first_child_for_point(&raw mut self.0, point.into())
1961 };
1962 result.try_into().ok()
1963 }
1964
1965 #[doc(alias = "ts_tree_cursor_reset")]
1968 pub fn reset(&mut self, node: Node<'tree>) {
1969 unsafe { ffi::ts_tree_cursor_reset(&raw mut self.0, node.0) };
1970 }
1971
1972 #[doc(alias = "ts_tree_cursor_reset_to")]
1977 pub fn reset_to(&mut self, cursor: &Self) {
1978 unsafe { ffi::ts_tree_cursor_reset_to(&raw mut self.0, &raw const cursor.0) };
1979 }
1980}
1981
1982impl Clone for TreeCursor<'_> {
1983 fn clone(&self) -> Self {
1984 TreeCursor(
1985 unsafe { ffi::ts_tree_cursor_copy(&raw const self.0) },
1986 PhantomData,
1987 )
1988 }
1989}
1990
1991impl Drop for TreeCursor<'_> {
1992 fn drop(&mut self) {
1993 unsafe { ffi::ts_tree_cursor_delete(&raw mut self.0) }
1994 }
1995}
1996
1997impl Point {
1998 #[must_use]
1999 pub const fn new(row: usize, column: usize) -> Self {
2000 Self { row, column }
2001 }
2002}
2003
2004impl fmt::Display for Point {
2005 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2006 write!(f, "({}, {})", self.row, self.column)
2007 }
2008}
2009
2010impl From<Point> for ffi::TSPoint {
2011 fn from(val: Point) -> Self {
2012 Self {
2013 row: val.row as u32,
2014 column: val.column as u32,
2015 }
2016 }
2017}
2018
2019impl From<ffi::TSPoint> for Point {
2020 fn from(point: ffi::TSPoint) -> Self {
2021 Self {
2022 row: point.row as usize,
2023 column: point.column as usize,
2024 }
2025 }
2026}
2027
2028impl From<Range> for ffi::TSRange {
2029 fn from(val: Range) -> Self {
2030 Self {
2031 start_byte: val.start_byte as u32,
2032 end_byte: val.end_byte as u32,
2033 start_point: val.start_point.into(),
2034 end_point: val.end_point.into(),
2035 }
2036 }
2037}
2038
2039impl From<ffi::TSRange> for Range {
2040 fn from(range: ffi::TSRange) -> Self {
2041 Self {
2042 start_byte: range.start_byte as usize,
2043 end_byte: range.end_byte as usize,
2044 start_point: range.start_point.into(),
2045 end_point: range.end_point.into(),
2046 }
2047 }
2048}
2049
2050impl From<&InputEdit> for ffi::TSInputEdit {
2051 fn from(val: &InputEdit) -> Self {
2052 Self {
2053 start_byte: val.start_byte as u32,
2054 old_end_byte: val.old_end_byte as u32,
2055 new_end_byte: val.new_end_byte as u32,
2056 start_point: val.start_position.into(),
2057 old_end_point: val.old_end_position.into(),
2058 new_end_point: val.new_end_position.into(),
2059 }
2060 }
2061}
2062
2063impl fmt::Display for IncludedRangesError {
2064 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2065 write!(f, "Incorrect range by index: {}", self.0)
2066 }
2067}
2068
2069impl fmt::Display for LanguageError {
2070 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2071 match self {
2072 Self::Version(version) => {
2073 write!(
2074 f,
2075 "Incompatible language version {version:#x}. Expected {LANGUAGE_VERSION:#x}",
2076 )
2077 }
2078 Self::NotParseable => {
2079 write!(f, "Language cannot be used for parsing.")
2080 }
2081 #[cfg(feature = "wasm")]
2082 Self::Wasm => {
2083 write!(f, "Failed to load the Wasm store.")
2084 }
2085 }
2086 }
2087}
2088
2089pub fn wasm_stdlib_symbols() -> impl Iterator<Item = &'static str> {
2090 const WASM_STDLIB_SYMBOLS: &str = include_str!(concat!(env!("OUT_DIR"), "/stdlib-symbols.txt"));
2091
2092 WASM_STDLIB_SYMBOLS
2093 .lines()
2094 .map(|s| s.trim_matches(|c| c == '"' || c == ','))
2095}
2096
2097unsafe extern "C" {
2098 fn ts_node_string_pretty(node: ffi::TSNode, initial_indent_level: usize) -> *mut c_char;
2099 static mut ts_current_free: unsafe extern "C" fn(ptr: *mut c_void);
2100}
2101
2102#[inline]
2105unsafe fn ts_free(ptr: *mut c_void) {
2106 let f = unsafe { core::ptr::addr_of!(ts_current_free).read() };
2107 unsafe { f(ptr) };
2108}
2109
2110#[derive(Copy, Clone)]
2112pub struct Allocator {
2113 pub malloc: unsafe extern "C" fn(size: usize) -> *mut c_void,
2114 pub calloc: unsafe extern "C" fn(nmemb: usize, size: usize) -> *mut c_void,
2115 pub realloc: unsafe extern "C" fn(ptr: *mut c_void, size: usize) -> *mut c_void,
2116 pub free: unsafe extern "C" fn(ptr: *mut c_void),
2117}
2118
2119#[doc(alias = "ts_set_allocator")]
2138pub unsafe fn set_allocator(allocator: Option<Allocator>) {
2139 let (m, c, r, f) = match allocator {
2140 Some(a) => (
2141 Some(a.malloc),
2142 Some(a.calloc),
2143 Some(a.realloc),
2144 Some(a.free),
2145 ),
2146 None => (None, None, None, None),
2147 };
2148 unsafe { ffi::ts_set_allocator(m, c, r, f) };
2149}
2150
2151#[cfg(feature = "std")]
2152#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
2153impl error::Error for IncludedRangesError {}
2154#[cfg(feature = "std")]
2155#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
2156impl error::Error for LanguageError {}
2157
2158#[cfg(not(target_family = "wasm"))]
2159unsafe impl Send for Language {}
2160#[cfg(not(target_family = "wasm"))]
2161unsafe impl Sync for Language {}
2162
2163unsafe impl Send for Node<'_> {}
2164unsafe impl Sync for Node<'_> {}
2165
2166#[cfg(not(target_family = "wasm"))]
2167unsafe impl Send for Parser {}
2168#[cfg(not(target_family = "wasm"))]
2169unsafe impl Sync for Parser {}
2170
2171unsafe impl Send for Tree {}
2172unsafe impl Sync for Tree {}
2173
2174unsafe impl Send for TreeCursor<'_> {}
2175unsafe impl Sync for TreeCursor<'_> {}