1#![cfg_attr(not(any(test, doctest)), doc = include_str!("./README.md"))]
2#![cfg_attr(not(feature = "std"), no_std)]
3#![cfg_attr(docsrs, feature(doc_cfg))]
4
5pub mod ffi;
6mod util;
7
8#[cfg(any(
9 not(feature = "std"),
10 all(target_arch = "wasm32", target_os = "unknown")
11))]
12extern crate alloc;
13#[cfg(not(feature = "std"))]
14use alloc::{boxed::Box, format, string::String, string::ToString, vec::Vec};
15use core::{
16 ffi::{CStr, c_char, c_void},
17 fmt::{self, Write},
18 hash, iter,
19 marker::PhantomData,
20 mem::MaybeUninit,
21 num::NonZeroU16,
22 ops::{self, ControlFlow, Deref},
23 ptr::{self, NonNull},
24 slice, str,
25};
26#[cfg(feature = "std")]
27use std::error;
28#[cfg(all(unix, feature = "std"))]
29use std::os::fd::AsRawFd;
30#[cfg(all(windows, feature = "std"))]
31use std::os::windows::io::AsRawHandle;
32
33pub use streaming_iterator::{StreamingIterator, StreamingIteratorMut};
34use tree_sitter_language::LanguageFn;
35
36#[cfg(feature = "wasm")]
37mod wasm_language;
38#[cfg(feature = "wasm")]
39#[cfg_attr(docsrs, doc(cfg(feature = "wasm")))]
40pub use wasm_language::*;
41
42#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
43mod wasm_allocator;
44
45#[doc(alias = "TREE_SITTER_LANGUAGE_VERSION")]
53pub const LANGUAGE_VERSION: usize = ffi::TREE_SITTER_LANGUAGE_VERSION as usize;
54
55#[doc(alias = "TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION")]
58pub const MIN_COMPATIBLE_LANGUAGE_VERSION: usize =
59 ffi::TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION as usize;
60
61pub const PARSER_HEADER: &str = include_str!("../src/parser.h");
62
63#[doc(alias = "TSLanguage")]
66#[derive(Debug, PartialEq, Eq, Hash)]
67#[repr(transparent)]
68pub struct Language(*const ffi::TSLanguage);
69
70pub struct LanguageRef<'a>(*const ffi::TSLanguage, PhantomData<&'a ()>);
71
72#[doc(alias = "TSLanguageMetadata")]
79pub struct LanguageMetadata {
80 pub major_version: u8,
81 pub minor_version: u8,
82 pub patch_version: u8,
83}
84
85impl From<ffi::TSLanguageMetadata> for LanguageMetadata {
86 fn from(val: ffi::TSLanguageMetadata) -> Self {
87 Self {
88 major_version: val.major_version,
89 minor_version: val.minor_version,
90 patch_version: val.patch_version,
91 }
92 }
93}
94
95#[doc(alias = "TSTree")]
97pub struct Tree(NonNull<ffi::TSTree>);
98
99#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord)]
103pub struct Point {
104 pub row: usize,
105 pub column: usize,
106}
107
108#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
111pub struct Range {
112 pub start_byte: usize,
113 pub end_byte: usize,
114 pub start_point: Point,
115 pub end_point: Point,
116}
117
118#[derive(Clone, Copy, Debug, PartialEq, Eq)]
120pub struct InputEdit {
121 pub start_byte: usize,
122 pub old_end_byte: usize,
123 pub new_end_byte: usize,
124 pub start_position: Point,
125 pub old_end_position: Point,
126 pub new_end_position: Point,
127}
128
129impl InputEdit {
130 #[doc(alias = "ts_point_edit")]
136 pub fn edit_point(&self, point: &mut Point, byte: &mut usize) {
137 let edit = self.into();
138 let mut ts_point = (*point).into();
139 let mut ts_byte = *byte as u32;
140
141 unsafe {
142 ffi::ts_point_edit(
143 core::ptr::addr_of_mut!(ts_point),
144 core::ptr::addr_of_mut!(ts_byte),
145 &raw const edit,
146 );
147 }
148
149 *point = ts_point.into();
150 *byte = ts_byte as usize;
151 }
152
153 #[doc(alias = "ts_range_edit")]
159 pub fn edit_range(&self, range: &mut Range) {
160 let edit = self.into();
161 let mut ts_range = (*range).into();
162
163 unsafe {
164 ffi::ts_range_edit(core::ptr::addr_of_mut!(ts_range), &raw const edit);
165 }
166
167 *range = ts_range.into();
168 }
169}
170
171#[doc(alias = "TSNode")]
173#[derive(Clone, Copy)]
174#[repr(transparent)]
175pub struct Node<'tree>(ffi::TSNode, PhantomData<&'tree ()>);
176
177#[doc(alias = "TSParser")]
180pub struct Parser(NonNull<ffi::TSParser>);
181
182#[doc(alias = "TSLookaheadIterator")]
185pub struct LookaheadIterator(NonNull<ffi::TSLookaheadIterator>);
186struct LookaheadNamesIterator<'a>(&'a mut LookaheadIterator);
187
188pub struct ParseState(NonNull<ffi::TSParseState>);
191
192impl ParseState {
193 #[must_use]
194 pub const fn current_byte_offset(&self) -> usize {
195 unsafe { self.0.as_ref() }.current_byte_offset as usize
196 }
197
198 #[must_use]
199 pub const fn has_error(&self) -> bool {
200 unsafe { self.0.as_ref() }.has_error
201 }
202}
203
204pub struct QueryCursorState(NonNull<ffi::TSQueryCursorState>);
207
208impl QueryCursorState {
209 #[must_use]
210 pub const fn current_byte_offset(&self) -> usize {
211 unsafe { self.0.as_ref() }.current_byte_offset as usize
212 }
213}
214
215#[derive(Default)]
216pub struct ParseOptions<'a> {
217 pub progress_callback: Option<ParseProgressCallback<'a>>,
218}
219
220impl<'a> ParseOptions<'a> {
221 #[must_use]
222 pub fn new() -> Self {
223 Self::default()
224 }
225
226 #[must_use]
227 pub fn progress_callback<F: FnMut(&ParseState) -> ControlFlow<()>>(
228 mut self,
229 callback: &'a mut F,
230 ) -> Self {
231 self.progress_callback = Some(callback);
232 self
233 }
234
235 #[must_use]
240 pub fn reborrow(&mut self) -> ParseOptions {
241 ParseOptions {
242 progress_callback: match &mut self.progress_callback {
243 Some(cb) => Some(*cb),
244 None => None,
245 },
246 }
247 }
248}
249
250#[derive(Default)]
251pub struct QueryCursorOptions<'a> {
252 pub progress_callback: Option<QueryProgressCallback<'a>>,
253}
254
255impl<'a> QueryCursorOptions<'a> {
256 #[must_use]
257 pub fn new() -> Self {
258 Self::default()
259 }
260
261 #[must_use]
262 pub fn progress_callback<F: FnMut(&QueryCursorState) -> ControlFlow<()>>(
263 mut self,
264 callback: &'a mut F,
265 ) -> Self {
266 self.progress_callback = Some(callback);
267 self
268 }
269
270 #[must_use]
275 pub fn reborrow(&mut self) -> QueryCursorOptions {
276 QueryCursorOptions {
277 progress_callback: match &mut self.progress_callback {
278 Some(cb) => Some(*cb),
279 None => None,
280 },
281 }
282 }
283}
284
285struct QueryCursorOptionsDrop<'options>(
286 *mut ffi::TSQueryCursorOptions,
287 PhantomData<QueryProgressCallback<'options>>,
288);
289
290impl Drop for QueryCursorOptionsDrop<'_> {
291 fn drop(&mut self) {
292 unsafe {
293 if !(*self.0).payload.is_null() {
294 drop(Box::from_raw(
295 (*self.0).payload.cast::<QueryProgressCallback>(),
296 ));
297 }
298 drop(Box::from_raw(self.0));
299 }
300 }
301}
302
303#[derive(Debug, PartialEq, Eq)]
305pub enum LogType {
306 Parse,
307 Lex,
308}
309
310type FieldId = NonZeroU16;
311
312type Logger = Box<dyn FnMut(LogType, &str) + Send + 'static>;
314
315type UnsafeLogger<'a> = Box<dyn FnMut(LogType, &str) + Send + 'a>;
317
318type ParseProgressCallback<'a> = &'a mut dyn FnMut(&ParseState) -> ControlFlow<()>;
320
321type QueryProgressCallback<'a> = &'a mut dyn FnMut(&QueryCursorState) -> ControlFlow<()>;
323
324pub trait Decode {
325 fn decode(bytes: &[u8]) -> (i32, u32);
328}
329
330#[doc(alias = "TSTreeCursor")]
332pub struct TreeCursor<'tree>(ffi::TSTreeCursor, PhantomData<&'tree ()>);
333
334#[doc(alias = "TSQuery")]
336#[derive(Debug)]
337#[expect(
338 clippy::type_complexity,
339 reason = "complex nested types are inherent to the query data model"
340)]
341pub struct Query {
342 ptr: NonNull<ffi::TSQuery>,
343 capture_names: Box<[&'static str]>,
344 capture_quantifiers: Box<[Box<[CaptureQuantifier]>]>,
345 text_predicates: Box<[Box<[TextPredicateCapture]>]>,
346 property_settings: Box<[Box<[QueryProperty]>]>,
347 property_predicates: Box<[Box<[(QueryProperty, bool)]>]>,
348 general_predicates: Box<[Box<[QueryPredicate]>]>,
349}
350
351#[derive(Debug, PartialEq, Eq, Clone, Copy)]
353pub enum CaptureQuantifier {
354 Zero,
355 ZeroOrOne,
356 ZeroOrMore,
357 One,
358 OneOrMore,
359}
360
361impl From<ffi::TSQuantifier> for CaptureQuantifier {
362 fn from(value: ffi::TSQuantifier) -> Self {
363 match value {
364 ffi::TSQuantifierZero => Self::Zero,
365 ffi::TSQuantifierZeroOrOne => Self::ZeroOrOne,
366 ffi::TSQuantifierZeroOrMore => Self::ZeroOrMore,
367 ffi::TSQuantifierOne => Self::One,
368 ffi::TSQuantifierOneOrMore => Self::OneOrMore,
369 _ => unreachable!(),
370 }
371 }
372}
373
374#[doc(alias = "TSQueryCursor")]
376pub struct QueryCursor {
377 ptr: NonNull<ffi::TSQueryCursor>,
378}
379
380#[derive(Debug, PartialEq, Eq)]
382pub struct QueryProperty {
383 pub key: Box<str>,
384 pub value: Option<Box<str>>,
385 pub capture_id: Option<usize>,
386}
387
388#[derive(Debug, PartialEq, Eq)]
389pub enum QueryPredicateArg {
390 Capture(u32),
391 String(Box<str>),
392}
393
394#[derive(Debug, PartialEq, Eq)]
396pub struct QueryPredicate {
397 pub operator: Box<str>,
398 pub args: Box<[QueryPredicateArg]>,
399}
400
401pub struct QueryMatch<'cursor, 'tree> {
403 pub pattern_index: usize,
404 captures: &'cursor [QueryCapture<'tree>],
405 id: u32,
406 cursor: *mut ffi::TSQueryCursor,
407}
408
409pub struct QueryMatches<'query, 'tree, 'options, T: TextProvider<I>, I: AsRef<[u8]>> {
411 ptr: *mut ffi::TSQueryCursor,
412 query: &'query Query,
413 text_provider: T,
414 buffer1: Vec<u8>,
415 buffer2: Vec<u8>,
416 current_match: Option<QueryMatch<'query, 'tree>>,
417 _options: Option<QueryCursorOptionsDrop<'options>>,
418 _phantom: PhantomData<(&'tree (), I)>,
419}
420
421pub struct QueryCaptures<'query, 'tree, 'options, T: TextProvider<I>, I: AsRef<[u8]>> {
426 ptr: *mut ffi::TSQueryCursor,
427 query: &'query Query,
428 text_provider: T,
429 buffer1: Vec<u8>,
430 buffer2: Vec<u8>,
431 current_match: Option<(QueryMatch<'query, 'tree>, usize)>,
432 _options: Option<QueryCursorOptionsDrop<'options>>,
433 _phantom: PhantomData<(&'tree (), I)>,
434}
435
436pub trait TextProvider<I>
437where
438 I: AsRef<[u8]>,
439{
440 type I: Iterator<Item = I>;
441 fn text(&mut self, node: Node) -> Self::I;
442}
443
444#[derive(Clone, Copy, Debug)]
447#[repr(C)]
448pub struct QueryCapture<'tree> {
449 pub node: Node<'tree>,
450 pub index: u32,
451}
452
453#[derive(Debug, PartialEq, Eq)]
457pub enum LanguageError {
458 Version(usize),
459 NotParseable,
460 #[cfg(feature = "wasm")]
461 Wasm,
462}
463
464#[derive(Debug, PartialEq, Eq)]
466pub struct IncludedRangesError(pub usize);
467
468#[derive(Debug, PartialEq, Eq)]
470pub struct QueryError {
471 pub row: usize,
472 pub column: usize,
473 pub offset: usize,
474 pub message: String,
475 pub kind: QueryErrorKind,
476}
477
478#[derive(Debug, PartialEq, Eq)]
479pub enum QueryErrorKind {
480 Syntax,
481 NodeType,
482 Field,
483 Capture,
484 Predicate,
485 Structure,
486 Language,
487}
488
489#[derive(Debug)]
490enum TextPredicateCapture {
496 EqString(u32, Box<str>, bool, bool),
497 EqCapture(u32, u32, bool, bool),
498 MatchString(u32, regex::bytes::Regex, bool, bool),
499 AnyString(u32, Box<[Box<str>]>, bool),
500}
501
502pub struct LossyUtf8<'a> {
505 bytes: &'a [u8],
506 in_replacement: bool,
507}
508
509impl Language {
510 #[must_use]
511 pub fn new(builder: LanguageFn) -> Self {
512 Self(unsafe { builder.into_raw()().cast() })
513 }
514
515 #[doc(alias = "ts_language_is_parseable")]
522 #[must_use]
523 pub fn is_parseable(&self) -> bool {
524 unsafe { ffi::ts_language_is_parseable(self.0) }
525 }
526
527 #[doc(alias = "ts_language_name")]
530 #[must_use]
531 pub fn name(&self) -> Option<&str> {
532 let ptr = unsafe { ffi::ts_language_name(self.0) };
533 (!ptr.is_null()).then(|| unsafe { CStr::from_ptr(ptr) }.to_str().unwrap())
534 }
535
536 #[doc(alias = "ts_language_abi_version")]
542 #[must_use]
543 pub fn abi_version(&self) -> usize {
544 unsafe { ffi::ts_language_abi_version(self.0) as usize }
545 }
546
547 #[doc(alias = "ts_language_metadata")]
554 #[must_use]
555 pub fn metadata(&self) -> Option<LanguageMetadata> {
556 unsafe {
557 let ptr = ffi::ts_language_metadata(self.0);
558 (!ptr.is_null()).then(|| (*ptr).into())
559 }
560 }
561
562 #[doc(alias = "ts_language_symbol_count")]
564 #[must_use]
565 pub fn node_kind_count(&self) -> usize {
566 unsafe { ffi::ts_language_symbol_count(self.0) as usize }
567 }
568
569 #[doc(alias = "ts_language_state_count")]
571 #[must_use]
572 pub fn parse_state_count(&self) -> usize {
573 unsafe { ffi::ts_language_state_count(self.0) as usize }
574 }
575
576 #[doc(alias = "ts_language_supertypes")]
579 #[must_use]
580 pub fn supertypes(&self) -> &[u16] {
581 let mut length = 0u32;
582 unsafe {
583 let ptr = ffi::ts_language_supertypes(self.0, core::ptr::addr_of_mut!(length));
584 if length == 0 {
585 &[]
586 } else {
587 slice::from_raw_parts(ptr.cast_mut(), length as usize)
588 }
589 }
590 }
591
592 #[doc(alias = "ts_language_supertype_map")]
595 #[must_use]
596 pub fn subtypes_for_supertype(&self, supertype: u16) -> &[u16] {
597 unsafe {
598 let mut length = 0u32;
599 let ptr = ffi::ts_language_subtypes(self.0, supertype, core::ptr::addr_of_mut!(length));
600 if length == 0 {
601 &[]
602 } else {
603 slice::from_raw_parts(ptr.cast_mut(), length as usize)
604 }
605 }
606 }
607
608 #[doc(alias = "ts_language_symbol_name")]
610 #[must_use]
611 pub fn node_kind_for_id(&self, id: u16) -> Option<&str> {
612 let ptr = unsafe { ffi::ts_language_symbol_name(self.0, id) };
613 (!ptr.is_null()).then(|| unsafe { CStr::from_ptr(ptr) }.to_str().unwrap())
614 }
615
616 #[doc(alias = "ts_language_symbol_for_name")]
618 #[must_use]
619 pub fn id_for_node_kind(&self, kind: &str, named: bool) -> u16 {
620 unsafe {
621 ffi::ts_language_symbol_for_name(
622 self.0,
623 kind.as_bytes().as_ptr().cast::<c_char>(),
624 kind.len() as u32,
625 named,
626 )
627 }
628 }
629
630 fn node_kind_id_is_valid(&self, id: u16) -> bool {
637 (id as usize) < self.node_kind_count() || id >= u16::MAX - 1
638 }
639
640 #[must_use]
643 pub fn node_kind_is_named(&self, id: u16) -> bool {
644 self.node_kind_id_is_valid(id)
645 && unsafe { ffi::ts_language_symbol_type(self.0, id) == ffi::TSSymbolTypeRegular }
646 }
647
648 #[must_use]
651 pub fn node_kind_is_visible(&self, id: u16) -> bool {
652 self.node_kind_id_is_valid(id)
653 && unsafe { ffi::ts_language_symbol_type(self.0, id) <= ffi::TSSymbolTypeAnonymous }
654 }
655
656 #[must_use]
658 pub fn node_kind_is_supertype(&self, id: u16) -> bool {
659 self.node_kind_id_is_valid(id)
660 && unsafe { ffi::ts_language_symbol_type(self.0, id) == ffi::TSSymbolTypeSupertype }
661 }
662
663 #[doc(alias = "ts_language_field_count")]
665 #[must_use]
666 pub fn field_count(&self) -> usize {
667 unsafe { ffi::ts_language_field_count(self.0) as usize }
668 }
669
670 #[doc(alias = "ts_language_field_name_for_id")]
672 #[must_use]
673 pub fn field_name_for_id(&self, field_id: u16) -> Option<&str> {
674 let ptr = unsafe { ffi::ts_language_field_name_for_id(self.0, field_id) };
675 (!ptr.is_null()).then(|| unsafe { CStr::from_ptr(ptr) }.to_str().unwrap())
676 }
677
678 #[doc(alias = "ts_language_field_id_for_name")]
680 #[must_use]
681 pub fn field_id_for_name(&self, field_name: impl AsRef<[u8]>) -> Option<FieldId> {
682 let field_name = field_name.as_ref();
683 let id = unsafe {
684 ffi::ts_language_field_id_for_name(
685 self.0,
686 field_name.as_ptr().cast::<c_char>(),
687 field_name.len() as u32,
688 )
689 };
690 FieldId::new(id)
691 }
692
693 #[doc(alias = "ts_language_next_state")]
702 #[must_use]
703 pub fn next_state(&self, state: u16, id: u16) -> u16 {
704 unsafe { ffi::ts_language_next_state(self.0, state, id) }
705 }
706
707 #[doc(alias = "ts_lookahead_iterator_new")]
727 #[must_use]
728 pub fn lookahead_iterator(&self, state: u16) -> Option<LookaheadIterator> {
729 let ptr = unsafe { ffi::ts_lookahead_iterator_new(self.0, state) };
730 (!ptr.is_null()).then(|| unsafe { LookaheadIterator::from_raw(ptr) })
731 }
732}
733
734impl From<LanguageFn> for Language {
735 fn from(value: LanguageFn) -> Self {
736 Self::new(value)
737 }
738}
739
740impl Clone for Language {
741 fn clone(&self) -> Self {
742 unsafe { Self(ffi::ts_language_copy(self.0)) }
743 }
744}
745
746impl Drop for Language {
747 fn drop(&mut self) {
748 unsafe { ffi::ts_language_delete(self.0) }
749 }
750}
751
752impl Deref for LanguageRef<'_> {
753 type Target = Language;
754
755 fn deref(&self) -> &Self::Target {
756 unsafe { &*(core::ptr::addr_of!(self.0).cast::<Language>()) }
757 }
758}
759
760impl Default for Parser {
761 fn default() -> Self {
762 Self::new()
763 }
764}
765
766impl Parser {
767 #[doc(alias = "ts_parser_new")]
769 #[must_use]
770 pub fn new() -> Self {
771 unsafe {
772 let parser = ffi::ts_parser_new();
773 Self(NonNull::new_unchecked(parser))
774 }
775 }
776
777 #[doc(alias = "ts_parser_set_language")]
785 pub fn set_language(&mut self, language: &Language) -> Result<(), LanguageError> {
786 let version = language.abi_version();
787 if version == LANGUAGE_VERSION {
788 if !language.is_parseable() {
789 return Err(LanguageError::NotParseable);
790 }
791 #[cfg_attr(
792 not(feature = "wasm"),
793 expect(unused_variables, reason = "only used when wasm feature is enabled")
794 )]
795 let success = unsafe { ffi::ts_parser_set_language(self.0.as_ptr(), language.0) };
796 #[cfg(feature = "wasm")]
797 if !success {
798 return Err(LanguageError::Wasm);
799 }
800 Ok(())
801 } else {
802 Err(LanguageError::Version(version))
803 }
804 }
805
806 #[doc(alias = "ts_parser_language")]
808 #[must_use]
809 pub fn language(&self) -> Option<LanguageRef<'_>> {
810 let ptr = unsafe { ffi::ts_parser_language(self.0.as_ptr()) };
811 (!ptr.is_null()).then_some(LanguageRef(ptr, PhantomData))
812 }
813
814 #[doc(alias = "ts_parser_logger")]
816 #[must_use]
817 pub fn logger(&self) -> Option<&Logger> {
818 let logger = unsafe { ffi::ts_parser_logger(self.0.as_ptr()) };
819 unsafe { logger.payload.cast::<Logger>().as_ref() }
820 }
821
822 #[doc(alias = "ts_parser_set_logger")]
827 pub fn set_logger(&mut self, logger: Option<Logger>) {
828 unsafe { self.set_logger_unchecked(logger) };
830 }
831
832 pub unsafe fn set_logger_unchecked(&mut self, logger: Option<UnsafeLogger<'_>>) {
841 let prev_logger = unsafe { ffi::ts_parser_logger(self.0.as_ptr()) };
842 if !prev_logger.payload.is_null() {
843 drop(unsafe { Box::from_raw(prev_logger.payload.cast::<Logger>()) });
844 }
845
846 let c_logger = if let Some(logger) = logger {
847 let container = Box::new(logger);
848
849 unsafe extern "C" fn log(
850 payload: *mut c_void,
851 c_log_type: ffi::TSLogType,
852 c_message: *const c_char,
853 ) {
854 unsafe {
855 let callback = payload.cast::<Logger>().as_mut().unwrap();
856 if let Ok(message) = CStr::from_ptr(c_message).to_str() {
857 let log_type = if c_log_type == ffi::TSLogTypeParse {
858 LogType::Parse
859 } else {
860 LogType::Lex
861 };
862 callback(log_type, message);
863 }
864 }
865 }
866
867 let raw_container = Box::into_raw(container);
868
869 ffi::TSLogger {
870 payload: raw_container.cast::<c_void>(),
871 log: Some(log),
872 }
873 } else {
874 ffi::TSLogger {
875 payload: ptr::null_mut(),
876 log: None,
877 }
878 };
879
880 unsafe { ffi::ts_parser_set_logger(self.0.as_ptr(), c_logger) };
881 }
882
883 #[doc(alias = "ts_parser_print_dot_graphs")]
888 #[cfg(not(target_os = "wasi"))]
889 #[cfg(feature = "std")]
890 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
891 pub fn print_dot_graphs(
892 &mut self,
893 #[cfg(unix)] file: &impl AsRawFd,
894 #[cfg(windows)] file: &impl AsRawHandle,
895 ) {
896 #[cfg(unix)]
897 {
898 let fd = file.as_raw_fd();
899 unsafe {
900 ffi::ts_parser_print_dot_graphs(self.0.as_ptr(), ffi::_ts_dup(fd));
901 }
902 }
903
904 #[cfg(windows)]
905 {
906 let handle = file.as_raw_handle();
907 unsafe {
908 ffi::ts_parser_print_dot_graphs(self.0.as_ptr(), ffi::_ts_dup(handle));
909 }
910 }
911 }
912
913 #[doc(alias = "ts_parser_print_dot_graphs")]
915 #[cfg(not(target_os = "wasi"))]
916 #[cfg(feature = "std")]
917 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
918 pub fn stop_printing_dot_graphs(&mut self) {
919 unsafe { ffi::ts_parser_print_dot_graphs(self.0.as_ptr(), -1) }
920 }
921
922 #[doc(alias = "ts_parser_parse")]
933 pub fn parse(&mut self, text: impl AsRef<[u8]>, old_tree: Option<&Tree>) -> Option<Tree> {
934 let bytes = text.as_ref();
935 let len = bytes.len();
936 self.parse_with_options(
937 &mut |i, _| {
938 if i < len {
939 &bytes[i..]
940 } else {
941 Default::default()
942 }
943 },
944 old_tree,
945 None,
946 )
947 }
948
949 pub fn parse_with_options<T: AsRef<[u8]>, F: FnMut(usize, Point) -> T>(
961 &mut self,
962 callback: &mut F,
963 old_tree: Option<&Tree>,
964 options: Option<ParseOptions>,
965 ) -> Option<Tree> {
966 type Payload<'a, F, T> = (&'a mut F, Option<T>);
967
968 unsafe extern "C" fn progress(state: *mut ffi::TSParseState) -> bool {
970 unsafe {
971 let callback = (*state)
972 .payload
973 .cast::<ParseProgressCallback>()
974 .as_mut()
975 .unwrap();
976 match callback(&ParseState::from_raw(state)) {
977 ControlFlow::Continue(()) => false,
978 ControlFlow::Break(()) => true,
979 }
980 }
981 }
982
983 unsafe extern "C" fn read<T: AsRef<[u8]>, F: FnMut(usize, Point) -> T>(
985 payload: *mut c_void,
986 byte_offset: u32,
987 position: ffi::TSPoint,
988 bytes_read: *mut u32,
989 ) -> *const c_char {
990 unsafe {
991 let (callback, text) = payload.cast::<Payload<F, T>>().as_mut().unwrap();
992 *text = Some(callback(byte_offset as usize, position.into()));
993 let slice = text.as_ref().unwrap().as_ref();
994 *bytes_read = slice.len() as u32;
995 slice.as_ptr().cast::<c_char>()
996 }
997 }
998
999 let empty_options = ffi::TSParseOptions {
1000 payload: ptr::null_mut(),
1001 progress_callback: None,
1002 };
1003
1004 let mut callback_ptr;
1005 let parse_options = if let Some(options) = options {
1006 if let Some(cb) = options.progress_callback {
1007 callback_ptr = cb;
1008 ffi::TSParseOptions {
1009 payload: core::ptr::addr_of_mut!(callback_ptr).cast::<c_void>(),
1010 progress_callback: Some(progress),
1011 }
1012 } else {
1013 empty_options
1014 }
1015 } else {
1016 empty_options
1017 };
1018
1019 let mut payload: Payload<F, T> = (callback, None);
1025
1026 let c_input = ffi::TSInput {
1027 payload: ptr::addr_of_mut!(payload).cast::<c_void>(),
1028 read: Some(read::<T, F>),
1029 encoding: ffi::TSInputEncodingUTF8,
1030 decode: None,
1031 };
1032
1033 let c_old_tree = old_tree.map_or(ptr::null_mut(), |t| t.0.as_ptr());
1034 unsafe {
1035 let c_new_tree = ffi::ts_parser_parse_with_options(
1036 self.0.as_ptr(),
1037 c_old_tree,
1038 c_input,
1039 parse_options,
1040 );
1041
1042 NonNull::new(c_new_tree).map(Tree)
1043 }
1044 }
1045
1046 pub fn parse_utf16_le(
1054 &mut self,
1055 input: impl AsRef<[u16]>,
1056 old_tree: Option<&Tree>,
1057 ) -> Option<Tree> {
1058 let code_points = input.as_ref();
1059 let len = code_points.len();
1060 self.parse_utf16_le_with_options(
1061 &mut |i, _| {
1062 if i < len {
1063 &code_points[i..]
1064 } else {
1065 Default::default()
1066 }
1067 },
1068 old_tree,
1069 None,
1070 )
1071 }
1072
1073 pub fn parse_utf16_le_with_options<T: AsRef<[u16]>, F: FnMut(usize, Point) -> T>(
1085 &mut self,
1086 callback: &mut F,
1087 old_tree: Option<&Tree>,
1088 options: Option<ParseOptions>,
1089 ) -> Option<Tree> {
1090 type Payload<'a, F, T> = (&'a mut F, Option<T>);
1091
1092 unsafe extern "C" fn progress(state: *mut ffi::TSParseState) -> bool {
1093 unsafe {
1094 let callback = (*state)
1095 .payload
1096 .cast::<ParseProgressCallback>()
1097 .as_mut()
1098 .unwrap();
1099 match callback(&ParseState::from_raw(state)) {
1100 ControlFlow::Continue(()) => false,
1101 ControlFlow::Break(()) => true,
1102 }
1103 }
1104 }
1105
1106 unsafe extern "C" fn read<T: AsRef<[u16]>, F: FnMut(usize, Point) -> T>(
1108 payload: *mut c_void,
1109 byte_offset: u32,
1110 position: ffi::TSPoint,
1111 bytes_read: *mut u32,
1112 ) -> *const c_char {
1113 unsafe {
1114 let (callback, text) = payload.cast::<Payload<F, T>>().as_mut().unwrap();
1115 *text = Some(callback(
1116 (byte_offset / 2) as usize,
1117 Point {
1118 row: position.row as usize,
1119 column: position.column as usize / 2,
1120 },
1121 ));
1122 let slice = text.as_ref().unwrap().as_ref();
1123 *bytes_read = slice.len() as u32 * 2;
1124 slice.as_ptr().cast::<c_char>()
1125 }
1126 }
1127
1128 let empty_options = ffi::TSParseOptions {
1129 payload: ptr::null_mut(),
1130 progress_callback: None,
1131 };
1132
1133 let mut callback_ptr;
1134 let parse_options = if let Some(options) = options {
1135 if let Some(cb) = options.progress_callback {
1136 callback_ptr = cb;
1137 ffi::TSParseOptions {
1138 payload: core::ptr::addr_of_mut!(callback_ptr).cast::<c_void>(),
1139 progress_callback: Some(progress),
1140 }
1141 } else {
1142 empty_options
1143 }
1144 } else {
1145 empty_options
1146 };
1147
1148 let mut payload: Payload<F, T> = (callback, None);
1154
1155 let c_input = ffi::TSInput {
1156 payload: core::ptr::addr_of_mut!(payload).cast::<c_void>(),
1157 read: Some(read::<T, F>),
1158 encoding: ffi::TSInputEncodingUTF16LE,
1159 decode: None,
1160 };
1161
1162 let c_old_tree = old_tree.map_or(ptr::null_mut(), |t| t.0.as_ptr());
1163 unsafe {
1164 let c_new_tree = ffi::ts_parser_parse_with_options(
1165 self.0.as_ptr(),
1166 c_old_tree,
1167 c_input,
1168 parse_options,
1169 );
1170
1171 NonNull::new(c_new_tree).map(Tree)
1172 }
1173 }
1174
1175 pub fn parse_utf16_be(
1183 &mut self,
1184 input: impl AsRef<[u16]>,
1185 old_tree: Option<&Tree>,
1186 ) -> Option<Tree> {
1187 let code_points = input.as_ref();
1188 let len = code_points.len();
1189 self.parse_utf16_be_with_options(
1190 &mut |i, _| if i < len { &code_points[i..] } else { &[] },
1191 old_tree,
1192 None,
1193 )
1194 }
1195
1196 pub fn parse_utf16_be_with_options<T: AsRef<[u16]>, F: FnMut(usize, Point) -> T>(
1208 &mut self,
1209 callback: &mut F,
1210 old_tree: Option<&Tree>,
1211 options: Option<ParseOptions>,
1212 ) -> Option<Tree> {
1213 type Payload<'a, F, T> = (&'a mut F, Option<T>);
1214
1215 unsafe extern "C" fn progress(state: *mut ffi::TSParseState) -> bool {
1217 unsafe {
1218 let callback = (*state)
1219 .payload
1220 .cast::<ParseProgressCallback>()
1221 .as_mut()
1222 .unwrap();
1223 match callback(&ParseState::from_raw(state)) {
1224 ControlFlow::Continue(()) => false,
1225 ControlFlow::Break(()) => true,
1226 }
1227 }
1228 }
1229
1230 unsafe extern "C" fn read<T: AsRef<[u16]>, F: FnMut(usize, Point) -> T>(
1232 payload: *mut c_void,
1233 byte_offset: u32,
1234 position: ffi::TSPoint,
1235 bytes_read: *mut u32,
1236 ) -> *const c_char {
1237 unsafe {
1238 let (callback, text) = payload.cast::<Payload<F, T>>().as_mut().unwrap();
1239 *text = Some(callback(
1240 (byte_offset / 2) as usize,
1241 Point {
1242 row: position.row as usize,
1243 column: position.column as usize / 2,
1244 },
1245 ));
1246 let slice = text.as_ref().unwrap().as_ref();
1247 *bytes_read = slice.len() as u32 * 2;
1248 slice.as_ptr().cast::<c_char>()
1249 }
1250 }
1251
1252 let empty_options = ffi::TSParseOptions {
1253 payload: ptr::null_mut(),
1254 progress_callback: None,
1255 };
1256
1257 let mut callback_ptr;
1258 let parse_options = if let Some(options) = options {
1259 if let Some(cb) = options.progress_callback {
1260 callback_ptr = cb;
1261 ffi::TSParseOptions {
1262 payload: core::ptr::addr_of_mut!(callback_ptr).cast::<c_void>(),
1263 progress_callback: Some(progress),
1264 }
1265 } else {
1266 empty_options
1267 }
1268 } else {
1269 empty_options
1270 };
1271
1272 let mut payload: Payload<F, T> = (callback, None);
1278
1279 let c_input = ffi::TSInput {
1280 payload: core::ptr::addr_of_mut!(payload).cast::<c_void>(),
1281 read: Some(read::<T, F>),
1282 encoding: ffi::TSInputEncodingUTF16BE,
1283 decode: None,
1284 };
1285
1286 let c_old_tree = old_tree.map_or(ptr::null_mut(), |t| t.0.as_ptr());
1287 unsafe {
1288 let c_new_tree = ffi::ts_parser_parse_with_options(
1289 self.0.as_ptr(),
1290 c_old_tree,
1291 c_input,
1292 parse_options,
1293 );
1294
1295 NonNull::new(c_new_tree).map(Tree)
1296 }
1297 }
1298
1299 pub fn parse_custom_encoding<D: Decode, T: AsRef<[u8]>, F: FnMut(usize, Point) -> T>(
1316 &mut self,
1317 callback: &mut F,
1318 old_tree: Option<&Tree>,
1319 options: Option<ParseOptions>,
1320 ) -> Option<Tree> {
1321 type Payload<'a, F, T> = (&'a mut F, Option<T>);
1322
1323 unsafe extern "C" fn progress(state: *mut ffi::TSParseState) -> bool {
1324 unsafe {
1325 let callback = (*state)
1326 .payload
1327 .cast::<ParseProgressCallback>()
1328 .as_mut()
1329 .unwrap();
1330 match callback(&ParseState::from_raw(state)) {
1331 ControlFlow::Continue(()) => false,
1332 ControlFlow::Break(()) => true,
1333 }
1334 }
1335 }
1336
1337 unsafe extern "C" fn decode_fn<D: Decode>(
1339 data: *const u8,
1340 len: u32,
1341 code_point: *mut i32,
1342 ) -> u32 {
1343 unsafe {
1344 let (c, len) = D::decode(core::slice::from_raw_parts(data, len as usize));
1345 if let Some(code_point) = code_point.as_mut() {
1346 *code_point = c;
1347 }
1348 len
1349 }
1350 }
1351
1352 unsafe extern "C" fn read<T: AsRef<[u8]>, F: FnMut(usize, Point) -> T>(
1354 payload: *mut c_void,
1355 byte_offset: u32,
1356 position: ffi::TSPoint,
1357 bytes_read: *mut u32,
1358 ) -> *const c_char {
1359 unsafe {
1360 let (callback, text) = payload.cast::<Payload<F, T>>().as_mut().unwrap();
1361 *text = Some(callback(byte_offset as usize, position.into()));
1362 let slice = text.as_ref().unwrap().as_ref();
1363 *bytes_read = slice.len() as u32;
1364 slice.as_ptr().cast::<c_char>()
1365 }
1366 }
1367
1368 let empty_options = ffi::TSParseOptions {
1369 payload: ptr::null_mut(),
1370 progress_callback: None,
1371 };
1372
1373 let mut callback_ptr;
1374 let parse_options = if let Some(options) = options {
1375 if let Some(cb) = options.progress_callback {
1376 callback_ptr = cb;
1377 ffi::TSParseOptions {
1378 payload: core::ptr::addr_of_mut!(callback_ptr).cast::<c_void>(),
1379 progress_callback: Some(progress),
1380 }
1381 } else {
1382 empty_options
1383 }
1384 } else {
1385 empty_options
1386 };
1387
1388 let mut payload: Payload<F, T> = (callback, None);
1394
1395 let c_input = ffi::TSInput {
1396 payload: core::ptr::addr_of_mut!(payload).cast::<c_void>(),
1397 read: Some(read::<T, F>),
1398 encoding: ffi::TSInputEncodingCustom,
1399 decode: Some(decode_fn::<D>),
1401 };
1402
1403 let c_old_tree = old_tree.map_or(ptr::null_mut(), |t| t.0.as_ptr());
1404 unsafe {
1405 let c_new_tree = ffi::ts_parser_parse_with_options(
1406 self.0.as_ptr(),
1407 c_old_tree,
1408 c_input,
1409 parse_options,
1410 );
1411
1412 NonNull::new(c_new_tree).map(Tree)
1413 }
1414 }
1415
1416 #[doc(alias = "ts_parser_reset")]
1423 pub fn reset(&mut self) {
1424 unsafe { ffi::ts_parser_reset(self.0.as_ptr()) }
1425 }
1426
1427 #[doc(alias = "ts_parser_set_included_ranges")]
1445 pub fn set_included_ranges(&mut self, ranges: &[Range]) -> Result<(), IncludedRangesError> {
1446 let ts_ranges = ranges.iter().copied().map(Into::into).collect::<Vec<_>>();
1447 let result = unsafe {
1448 ffi::ts_parser_set_included_ranges(
1449 self.0.as_ptr(),
1450 ts_ranges.as_ptr(),
1451 ts_ranges.len() as u32,
1452 )
1453 };
1454
1455 if result {
1456 Ok(())
1457 } else {
1458 let mut prev_end_byte = 0;
1459 for (i, range) in ranges.iter().enumerate() {
1460 if range.start_byte < prev_end_byte || range.end_byte < range.start_byte {
1461 return Err(IncludedRangesError(i));
1462 }
1463 prev_end_byte = range.end_byte;
1464 }
1465 Err(IncludedRangesError(0))
1466 }
1467 }
1468
1469 #[doc(alias = "ts_parser_included_ranges")]
1471 #[must_use]
1472 pub fn included_ranges(&self) -> Vec<Range> {
1473 let mut count = 0u32;
1474 unsafe {
1475 let ptr =
1476 ffi::ts_parser_included_ranges(self.0.as_ptr(), core::ptr::addr_of_mut!(count));
1477 let ranges = slice::from_raw_parts(ptr, count as usize);
1478 ranges.iter().copied().map(Into::into).collect()
1479 }
1480 }
1481}
1482
1483impl Drop for Parser {
1484 fn drop(&mut self) {
1485 #[cfg(feature = "std")]
1486 #[cfg(not(target_os = "wasi"))]
1487 {
1488 self.stop_printing_dot_graphs();
1489 }
1490 self.set_logger(None);
1491 unsafe { ffi::ts_parser_delete(self.0.as_ptr()) }
1492 }
1493}
1494
1495#[cfg(windows)]
1496unsafe extern "C" {
1497 fn _open_osfhandle(osfhandle: isize, flags: core::ffi::c_int) -> core::ffi::c_int;
1498}
1499
1500impl Tree {
1501 #[doc(alias = "ts_tree_root_node")]
1503 #[must_use]
1504 pub fn root_node(&self) -> Node {
1505 Node::new(unsafe { ffi::ts_tree_root_node(self.0.as_ptr()) }).unwrap()
1506 }
1507
1508 #[doc(alias = "ts_tree_root_node_with_offset")]
1511 #[must_use]
1512 pub fn root_node_with_offset(&self, offset_bytes: usize, offset_extent: Point) -> Node {
1513 Node::new(unsafe {
1514 ffi::ts_tree_root_node_with_offset(
1515 self.0.as_ptr(),
1516 offset_bytes as u32,
1517 offset_extent.into(),
1518 )
1519 })
1520 .unwrap()
1521 }
1522
1523 #[doc(alias = "ts_tree_language")]
1530 #[must_use]
1531 pub fn language(&self) -> LanguageRef {
1532 LanguageRef(
1533 unsafe { ffi::ts_tree_language(self.0.as_ptr()) },
1534 PhantomData,
1535 )
1536 }
1537
1538 #[doc(alias = "ts_tree_edit")]
1544 pub fn edit(&mut self, edit: &InputEdit) {
1545 let edit = edit.into();
1546 unsafe { ffi::ts_tree_edit(self.0.as_ptr(), &raw const edit) };
1547 }
1548
1549 #[must_use]
1551 pub fn walk(&self) -> TreeCursor {
1552 self.root_node().walk()
1553 }
1554
1555 #[doc(alias = "ts_tree_get_changed_ranges")]
1565 pub fn changed_ranges(&self, other: &Self) -> impl ExactSizeIterator<Item = Range> {
1566 let mut count = 0u32;
1567 unsafe {
1568 let ptr = ffi::ts_tree_get_changed_ranges(
1569 self.0.as_ptr(),
1570 other.0.as_ptr(),
1571 core::ptr::addr_of_mut!(count),
1572 );
1573 util::CBufferIter::new(ptr, count as usize).map(Into::into)
1574 }
1575 }
1576
1577 #[doc(alias = "ts_tree_included_ranges")]
1579 #[must_use]
1580 pub fn included_ranges(&self) -> Vec<Range> {
1581 let mut count = 0u32;
1582 unsafe {
1583 let ptr = ffi::ts_tree_included_ranges(self.0.as_ptr(), core::ptr::addr_of_mut!(count));
1584 let ranges = slice::from_raw_parts(ptr, count as usize);
1585 let result = ranges.iter().copied().map(Into::into).collect();
1586 ts_free(ptr.cast::<c_void>());
1587 result
1588 }
1589 }
1590
1591 #[doc(alias = "ts_tree_print_dot_graph")]
1596 #[cfg(not(target_os = "wasi"))]
1597 #[cfg(feature = "std")]
1598 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
1599 pub fn print_dot_graph(
1600 &self,
1601 #[cfg(unix)] file: &impl AsRawFd,
1602 #[cfg(windows)] file: &impl AsRawHandle,
1603 ) {
1604 #[cfg(unix)]
1605 {
1606 let fd = file.as_raw_fd();
1607 unsafe { ffi::ts_tree_print_dot_graph(self.0.as_ptr(), fd) }
1608 }
1609
1610 #[cfg(windows)]
1611 {
1612 let handle = file.as_raw_handle();
1613 let fd = unsafe { _open_osfhandle(handle as isize, 0) };
1614 unsafe { ffi::ts_tree_print_dot_graph(self.0.as_ptr(), fd) }
1615 }
1616 }
1617}
1618
1619impl fmt::Debug for Tree {
1620 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1621 write!(f, "{{Tree {:?}}}", self.root_node())
1622 }
1623}
1624
1625impl Drop for Tree {
1626 fn drop(&mut self) {
1627 unsafe { ffi::ts_tree_delete(self.0.as_ptr()) }
1628 }
1629}
1630
1631impl Clone for Tree {
1632 fn clone(&self) -> Self {
1633 unsafe { Self(NonNull::new_unchecked(ffi::ts_tree_copy(self.0.as_ptr()))) }
1634 }
1635}
1636
1637impl<'tree> Node<'tree> {
1638 fn new(node: ffi::TSNode) -> Option<Self> {
1639 (!node.id.is_null()).then_some(Node(node, PhantomData))
1640 }
1641
1642 #[must_use]
1653 pub fn id(&self) -> usize {
1654 self.0.id as usize
1655 }
1656
1657 #[doc(alias = "ts_node_symbol")]
1659 #[must_use]
1660 pub fn kind_id(&self) -> u16 {
1661 unsafe { ffi::ts_node_symbol(self.0) }
1662 }
1663
1664 #[doc(alias = "ts_node_grammar_symbol")]
1667 #[must_use]
1668 pub fn grammar_id(&self) -> u16 {
1669 unsafe { ffi::ts_node_grammar_symbol(self.0) }
1670 }
1671
1672 #[doc(alias = "ts_node_type")]
1674 #[must_use]
1675 pub fn kind(&self) -> &'tree str {
1676 let ptr = unsafe { ffi::ts_node_type(self.0) };
1677 assert!(!ptr.is_null());
1678 unsafe { CStr::from_ptr(ptr) }.to_str().unwrap()
1679 }
1680
1681 #[doc(alias = "ts_node_grammar_type")]
1684 #[must_use]
1685 pub fn grammar_name(&self) -> &'tree str {
1686 let ptr = unsafe { ffi::ts_node_grammar_type(self.0) };
1687 assert!(!ptr.is_null());
1688 unsafe { CStr::from_ptr(ptr) }.to_str().unwrap()
1689 }
1690
1691 #[doc(alias = "ts_node_language")]
1699 #[must_use]
1700 pub fn language(&self) -> LanguageRef<'tree> {
1701 LanguageRef(unsafe { ffi::ts_node_language(self.0) }, PhantomData)
1702 }
1703
1704 #[doc(alias = "ts_node_is_named")]
1709 #[must_use]
1710 pub fn is_named(&self) -> bool {
1711 unsafe { ffi::ts_node_is_named(self.0) }
1712 }
1713
1714 #[doc(alias = "ts_node_is_extra")]
1719 #[must_use]
1720 pub fn is_extra(&self) -> bool {
1721 unsafe { ffi::ts_node_is_extra(self.0) }
1722 }
1723
1724 #[doc(alias = "ts_node_has_changes")]
1726 #[must_use]
1727 pub fn has_changes(&self) -> bool {
1728 unsafe { ffi::ts_node_has_changes(self.0) }
1729 }
1730
1731 #[doc(alias = "ts_node_has_error")]
1734 #[must_use]
1735 pub fn has_error(&self) -> bool {
1736 unsafe { ffi::ts_node_has_error(self.0) }
1737 }
1738
1739 #[doc(alias = "ts_node_is_error")]
1744 #[must_use]
1745 pub fn is_error(&self) -> bool {
1746 unsafe { ffi::ts_node_is_error(self.0) }
1747 }
1748
1749 #[doc(alias = "ts_node_parse_state")]
1758 #[must_use]
1759 pub fn parse_state(&self) -> u16 {
1760 unsafe { ffi::ts_node_parse_state(self.0) }
1761 }
1762
1763 #[doc(alias = "ts_node_next_parse_state")]
1765 #[must_use]
1766 pub fn next_parse_state(&self) -> u16 {
1767 unsafe { ffi::ts_node_next_parse_state(self.0) }
1768 }
1769
1770 #[doc(alias = "ts_node_is_missing")]
1775 #[must_use]
1776 pub fn is_missing(&self) -> bool {
1777 unsafe { ffi::ts_node_is_missing(self.0) }
1778 }
1779
1780 #[doc(alias = "ts_node_start_byte")]
1782 #[must_use]
1783 pub fn start_byte(&self) -> usize {
1784 unsafe { ffi::ts_node_start_byte(self.0) as usize }
1785 }
1786
1787 #[doc(alias = "ts_node_end_byte")]
1789 #[must_use]
1790 pub fn end_byte(&self) -> usize {
1791 unsafe { ffi::ts_node_end_byte(self.0) as usize }
1792 }
1793
1794 #[must_use]
1796 pub fn byte_range(&self) -> core::ops::Range<usize> {
1797 self.start_byte()..self.end_byte()
1798 }
1799
1800 #[must_use]
1803 pub fn range(&self) -> Range {
1804 Range {
1805 start_byte: self.start_byte(),
1806 end_byte: self.end_byte(),
1807 start_point: self.start_position(),
1808 end_point: self.end_position(),
1809 }
1810 }
1811
1812 #[doc(alias = "ts_node_start_point")]
1814 #[must_use]
1815 pub fn start_position(&self) -> Point {
1816 let result = unsafe { ffi::ts_node_start_point(self.0) };
1817 result.into()
1818 }
1819
1820 #[doc(alias = "ts_node_end_point")]
1822 #[must_use]
1823 pub fn end_position(&self) -> Point {
1824 let result = unsafe { ffi::ts_node_end_point(self.0) };
1825 result.into()
1826 }
1827
1828 #[doc(alias = "ts_node_child")]
1835 #[must_use]
1836 pub fn child(&self, i: u32) -> Option<Self> {
1837 Self::new(unsafe { ffi::ts_node_child(self.0, i) })
1838 }
1839
1840 #[doc(alias = "ts_node_child_count")]
1842 #[must_use]
1843 pub fn child_count(&self) -> u32 {
1844 unsafe { ffi::ts_node_child_count(self.0) }
1845 }
1846
1847 #[doc(alias = "ts_node_named_child")]
1854 #[must_use]
1855 pub fn named_child(&self, i: u32) -> Option<Self> {
1856 Self::new(unsafe { ffi::ts_node_named_child(self.0, i) })
1857 }
1858
1859 #[doc(alias = "ts_node_named_child_count")]
1863 #[must_use]
1864 pub fn named_child_count(&self) -> usize {
1865 unsafe { ffi::ts_node_named_child_count(self.0) as usize }
1866 }
1867
1868 #[doc(alias = "ts_node_child_by_field_name")]
1873 #[must_use]
1874 pub fn child_by_field_name(&self, field_name: impl AsRef<[u8]>) -> Option<Self> {
1875 let field_name = field_name.as_ref();
1876 Self::new(unsafe {
1877 ffi::ts_node_child_by_field_name(
1878 self.0,
1879 field_name.as_ptr().cast::<c_char>(),
1880 field_name.len() as u32,
1881 )
1882 })
1883 }
1884
1885 #[doc(alias = "ts_node_child_by_field_id")]
1890 #[must_use]
1891 pub fn child_by_field_id(&self, field_id: u16) -> Option<Self> {
1892 Self::new(unsafe { ffi::ts_node_child_by_field_id(self.0, field_id) })
1893 }
1894
1895 #[doc(alias = "ts_node_field_name_for_child")]
1897 #[must_use]
1898 pub fn field_name_for_child(&self, child_index: u32) -> Option<&'tree str> {
1899 unsafe {
1900 let ptr = ffi::ts_node_field_name_for_child(self.0, child_index);
1901 (!ptr.is_null()).then(|| CStr::from_ptr(ptr).to_str().unwrap())
1902 }
1903 }
1904
1905 #[must_use]
1907 pub fn field_name_for_named_child(&self, named_child_index: u32) -> Option<&'tree str> {
1908 unsafe {
1909 let ptr = ffi::ts_node_field_name_for_named_child(self.0, named_child_index);
1910 (!ptr.is_null()).then(|| CStr::from_ptr(ptr).to_str().unwrap())
1911 }
1912 }
1913
1914 pub fn children<'cursor>(
1924 &self,
1925 cursor: &'cursor mut TreeCursor<'tree>,
1926 ) -> impl ExactSizeIterator<Item = Node<'tree>> + 'cursor {
1927 cursor.reset(*self);
1928 cursor.goto_first_child();
1929 (0..self.child_count()).map(move |_| {
1930 let result = cursor.node();
1931 cursor.goto_next_sibling();
1932 result
1933 })
1934 }
1935
1936 pub fn named_children<'cursor>(
1940 &self,
1941 cursor: &'cursor mut TreeCursor<'tree>,
1942 ) -> impl ExactSizeIterator<Item = Node<'tree>> + 'cursor {
1943 cursor.reset(*self);
1944 cursor.goto_first_child();
1945 (0..self.named_child_count()).map(move |_| {
1946 while !cursor.node().is_named() {
1947 if !cursor.goto_next_sibling() {
1948 break;
1949 }
1950 }
1951 let result = cursor.node();
1952 cursor.goto_next_sibling();
1953 result
1954 })
1955 }
1956
1957 pub fn children_by_field_name<'cursor>(
1961 &self,
1962 field_name: &str,
1963 cursor: &'cursor mut TreeCursor<'tree>,
1964 ) -> impl Iterator<Item = Node<'tree>> + 'cursor {
1965 let field_id = self.language().field_id_for_name(field_name);
1966 let mut done = field_id.is_none();
1967 if !done {
1968 cursor.reset(*self);
1969 cursor.goto_first_child();
1970 }
1971 iter::from_fn(move || {
1972 if !done {
1973 while cursor.field_id() != field_id {
1974 if !cursor.goto_next_sibling() {
1975 return None;
1976 }
1977 }
1978 let result = cursor.node();
1979 if !cursor.goto_next_sibling() {
1980 done = true;
1981 }
1982 return Some(result);
1983 }
1984 None
1985 })
1986 }
1987
1988 pub fn children_by_field_id<'cursor>(
1992 &self,
1993 field_id: FieldId,
1994 cursor: &'cursor mut TreeCursor<'tree>,
1995 ) -> impl Iterator<Item = Node<'tree>> + 'cursor {
1996 cursor.reset(*self);
1997 cursor.goto_first_child();
1998 let mut done = false;
1999 iter::from_fn(move || {
2000 if !done {
2001 while cursor.field_id() != Some(field_id) {
2002 if !cursor.goto_next_sibling() {
2003 return None;
2004 }
2005 }
2006 let result = cursor.node();
2007 if !cursor.goto_next_sibling() {
2008 done = true;
2009 }
2010 return Some(result);
2011 }
2012 None
2013 })
2014 }
2015
2016 #[doc(alias = "ts_node_parent")]
2020 #[must_use]
2021 pub fn parent(&self) -> Option<Self> {
2022 Self::new(unsafe { ffi::ts_node_parent(self.0) })
2023 }
2024
2025 #[doc(alias = "ts_node_child_with_descendant")]
2029 #[must_use]
2030 pub fn child_with_descendant(&self, descendant: Self) -> Option<Self> {
2031 Self::new(unsafe { ffi::ts_node_child_with_descendant(self.0, descendant.0) })
2032 }
2033
2034 #[doc(alias = "ts_node_next_sibling")]
2036 #[must_use]
2037 pub fn next_sibling(&self) -> Option<Self> {
2038 Self::new(unsafe { ffi::ts_node_next_sibling(self.0) })
2039 }
2040
2041 #[doc(alias = "ts_node_prev_sibling")]
2043 #[must_use]
2044 pub fn prev_sibling(&self) -> Option<Self> {
2045 Self::new(unsafe { ffi::ts_node_prev_sibling(self.0) })
2046 }
2047
2048 #[doc(alias = "ts_node_next_named_sibling")]
2050 #[must_use]
2051 pub fn next_named_sibling(&self) -> Option<Self> {
2052 Self::new(unsafe { ffi::ts_node_next_named_sibling(self.0) })
2053 }
2054
2055 #[doc(alias = "ts_node_prev_named_sibling")]
2057 #[must_use]
2058 pub fn prev_named_sibling(&self) -> Option<Self> {
2059 Self::new(unsafe { ffi::ts_node_prev_named_sibling(self.0) })
2060 }
2061
2062 #[doc(alias = "ts_node_first_child_for_byte")]
2064 #[must_use]
2065 pub fn first_child_for_byte(&self, byte: usize) -> Option<Self> {
2066 Self::new(unsafe { ffi::ts_node_first_child_for_byte(self.0, byte as u32) })
2067 }
2068
2069 #[doc(alias = "ts_node_first_named_child_for_point")]
2071 #[must_use]
2072 pub fn first_named_child_for_byte(&self, byte: usize) -> Option<Self> {
2073 Self::new(unsafe { ffi::ts_node_first_named_child_for_byte(self.0, byte as u32) })
2074 }
2075
2076 #[doc(alias = "ts_node_descendant_count")]
2078 #[must_use]
2079 pub fn descendant_count(&self) -> usize {
2080 unsafe { ffi::ts_node_descendant_count(self.0) as usize }
2081 }
2082
2083 #[doc(alias = "ts_node_descendant_for_byte_range")]
2085 #[must_use]
2086 pub fn descendant_for_byte_range(&self, start: usize, end: usize) -> Option<Self> {
2087 Self::new(unsafe {
2088 ffi::ts_node_descendant_for_byte_range(self.0, start as u32, end as u32)
2089 })
2090 }
2091
2092 #[doc(alias = "ts_node_named_descendant_for_byte_range")]
2094 #[must_use]
2095 pub fn named_descendant_for_byte_range(&self, start: usize, end: usize) -> Option<Self> {
2096 Self::new(unsafe {
2097 ffi::ts_node_named_descendant_for_byte_range(self.0, start as u32, end as u32)
2098 })
2099 }
2100
2101 #[doc(alias = "ts_node_descendant_for_point_range")]
2103 #[must_use]
2104 pub fn descendant_for_point_range(&self, start: Point, end: Point) -> Option<Self> {
2105 Self::new(unsafe {
2106 ffi::ts_node_descendant_for_point_range(self.0, start.into(), end.into())
2107 })
2108 }
2109
2110 #[doc(alias = "ts_node_named_descendant_for_point_range")]
2112 #[must_use]
2113 pub fn named_descendant_for_point_range(&self, start: Point, end: Point) -> Option<Self> {
2114 Self::new(unsafe {
2115 ffi::ts_node_named_descendant_for_point_range(self.0, start.into(), end.into())
2116 })
2117 }
2118
2119 #[doc(alias = "ts_node_string")]
2121 #[must_use]
2122 pub fn to_sexp(&self) -> String {
2123 let c_string = unsafe { ffi::ts_node_string(self.0) };
2124 let result = unsafe { CStr::from_ptr(c_string) }
2125 .to_str()
2126 .unwrap()
2127 .to_string();
2128 unsafe { ts_free(c_string.cast::<c_void>()) };
2129 result
2130 }
2131
2132 pub fn utf8_text<'a>(&self, source: &'a [u8]) -> Result<&'a str, str::Utf8Error> {
2133 str::from_utf8(&source[self.start_byte()..self.end_byte()])
2134 }
2135
2136 #[must_use]
2137 pub fn utf16_text<'a>(&self, source: &'a [u16]) -> &'a [u16] {
2138 &source[self.start_byte() / 2..self.end_byte() / 2]
2139 }
2140
2141 #[doc(alias = "ts_tree_cursor_new")]
2146 #[must_use]
2147 pub fn walk(&self) -> TreeCursor<'tree> {
2148 TreeCursor(unsafe { ffi::ts_tree_cursor_new(self.0) }, PhantomData)
2149 }
2150
2151 #[doc(alias = "ts_node_edit")]
2159 pub fn edit(&mut self, edit: &InputEdit) {
2160 let edit = edit.into();
2161 unsafe { ffi::ts_node_edit(core::ptr::addr_of_mut!(self.0), &raw const edit) }
2162 }
2163}
2164
2165impl PartialEq for Node<'_> {
2166 fn eq(&self, other: &Self) -> bool {
2167 core::ptr::eq(self.0.id, other.0.id)
2168 }
2169}
2170
2171impl Eq for Node<'_> {}
2172
2173impl hash::Hash for Node<'_> {
2174 fn hash<H: hash::Hasher>(&self, state: &mut H) {
2175 self.0.id.hash(state);
2176 self.0.context[0].hash(state);
2177 self.0.context[1].hash(state);
2178 self.0.context[2].hash(state);
2179 self.0.context[3].hash(state);
2180 }
2181}
2182
2183impl fmt::Debug for Node<'_> {
2184 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2185 write!(
2186 f,
2187 "{{Node {} {} - {}}}",
2188 self.kind(),
2189 self.start_position(),
2190 self.end_position()
2191 )
2192 }
2193}
2194
2195impl fmt::Display for Node<'_> {
2196 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2197 if !f.alternate() {
2198 return f.write_str(&self.to_sexp());
2199 }
2200 let c_string = unsafe { ts_node_string_pretty(self.0, f.width().unwrap_or(0)) };
2201 let result = unsafe { CStr::from_ptr(c_string) }
2202 .to_str()
2203 .unwrap()
2204 .to_string();
2205 unsafe { ts_free(c_string.cast::<c_void>()) };
2206 f.write_str(&result)
2207 }
2208}
2209
2210impl<'tree> TreeCursor<'tree> {
2211 #[doc(alias = "ts_tree_cursor_current_node")]
2213 #[must_use]
2214 pub fn node(&self) -> Node<'tree> {
2215 Node(
2216 unsafe { ffi::ts_tree_cursor_current_node(&raw const self.0) },
2217 PhantomData,
2218 )
2219 }
2220
2221 #[doc(alias = "ts_tree_cursor_current_field_id")]
2225 #[must_use]
2226 pub fn field_id(&self) -> Option<FieldId> {
2227 let id = unsafe { ffi::ts_tree_cursor_current_field_id(&raw const self.0) };
2228 FieldId::new(id)
2229 }
2230
2231 #[doc(alias = "ts_tree_cursor_current_field_name")]
2233 #[must_use]
2234 pub fn field_name(&self) -> Option<&'tree str> {
2235 unsafe {
2236 let ptr = ffi::ts_tree_cursor_current_field_name(&raw const self.0);
2237 (!ptr.is_null()).then(|| CStr::from_ptr(ptr).to_str().unwrap())
2238 }
2239 }
2240
2241 #[doc(alias = "ts_tree_cursor_current_depth")]
2244 #[must_use]
2245 pub fn depth(&self) -> u32 {
2246 unsafe { ffi::ts_tree_cursor_current_depth(&raw const self.0) }
2247 }
2248
2249 #[doc(alias = "ts_tree_cursor_current_descendant_index")]
2252 #[must_use]
2253 pub fn descendant_index(&self) -> usize {
2254 unsafe { ffi::ts_tree_cursor_current_descendant_index(&raw const self.0) as usize }
2255 }
2256
2257 #[doc(alias = "ts_tree_cursor_goto_first_child")]
2262 pub fn goto_first_child(&mut self) -> bool {
2263 unsafe { ffi::ts_tree_cursor_goto_first_child(&raw mut self.0) }
2264 }
2265
2266 #[doc(alias = "ts_tree_cursor_goto_last_child")]
2275 pub fn goto_last_child(&mut self) -> bool {
2276 unsafe { ffi::ts_tree_cursor_goto_last_child(&raw mut self.0) }
2277 }
2278
2279 #[doc(alias = "ts_tree_cursor_goto_parent")]
2288 pub fn goto_parent(&mut self) -> bool {
2289 unsafe { ffi::ts_tree_cursor_goto_parent(&raw mut self.0) }
2290 }
2291
2292 #[doc(alias = "ts_tree_cursor_goto_next_sibling")]
2300 pub fn goto_next_sibling(&mut self) -> bool {
2301 unsafe { ffi::ts_tree_cursor_goto_next_sibling(&raw mut self.0) }
2302 }
2303
2304 #[doc(alias = "ts_tree_cursor_goto_descendant")]
2308 pub fn goto_descendant(&mut self, descendant_index: usize) {
2309 unsafe { ffi::ts_tree_cursor_goto_descendant(&raw mut self.0, descendant_index as u32) }
2310 }
2311
2312 #[doc(alias = "ts_tree_cursor_goto_previous_sibling")]
2324 pub fn goto_previous_sibling(&mut self) -> bool {
2325 unsafe { ffi::ts_tree_cursor_goto_previous_sibling(&raw mut self.0) }
2326 }
2327
2328 #[doc(alias = "ts_tree_cursor_goto_first_child_for_byte")]
2334 pub fn goto_first_child_for_byte(&mut self, index: usize) -> Option<usize> {
2335 let result =
2336 unsafe { ffi::ts_tree_cursor_goto_first_child_for_byte(&raw mut self.0, index as u32) };
2337 result.try_into().ok()
2338 }
2339
2340 #[doc(alias = "ts_tree_cursor_goto_first_child_for_point")]
2346 pub fn goto_first_child_for_point(&mut self, point: Point) -> Option<usize> {
2347 let result = unsafe {
2348 ffi::ts_tree_cursor_goto_first_child_for_point(&raw mut self.0, point.into())
2349 };
2350 result.try_into().ok()
2351 }
2352
2353 #[doc(alias = "ts_tree_cursor_reset")]
2356 pub fn reset(&mut self, node: Node<'tree>) {
2357 unsafe { ffi::ts_tree_cursor_reset(&raw mut self.0, node.0) };
2358 }
2359
2360 #[doc(alias = "ts_tree_cursor_reset_to")]
2365 pub fn reset_to(&mut self, cursor: &Self) {
2366 unsafe { ffi::ts_tree_cursor_reset_to(&raw mut self.0, &raw const cursor.0) };
2367 }
2368}
2369
2370impl Clone for TreeCursor<'_> {
2371 fn clone(&self) -> Self {
2372 TreeCursor(
2373 unsafe { ffi::ts_tree_cursor_copy(&raw const self.0) },
2374 PhantomData,
2375 )
2376 }
2377}
2378
2379impl Drop for TreeCursor<'_> {
2380 fn drop(&mut self) {
2381 unsafe { ffi::ts_tree_cursor_delete(&raw mut self.0) }
2382 }
2383}
2384
2385impl LookaheadIterator {
2386 #[doc(alias = "ts_lookahead_iterator_language")]
2388 #[must_use]
2389 pub fn language(&self) -> LanguageRef<'_> {
2390 LanguageRef(
2391 unsafe { ffi::ts_lookahead_iterator_language(self.0.as_ptr()) },
2392 PhantomData,
2393 )
2394 }
2395
2396 #[doc(alias = "ts_lookahead_iterator_current_symbol")]
2404 #[must_use]
2405 pub fn current_symbol(&self) -> Option<u16> {
2406 let name = unsafe { ffi::ts_lookahead_iterator_current_symbol_name(self.0.as_ptr()) };
2408 (!name.is_null())
2409 .then(|| unsafe { ffi::ts_lookahead_iterator_current_symbol(self.0.as_ptr()) })
2410 }
2411
2412 #[doc(alias = "ts_lookahead_iterator_current_symbol_name")]
2416 #[must_use]
2417 pub fn current_symbol_name(&self) -> Option<&str> {
2418 unsafe {
2419 let name = ffi::ts_lookahead_iterator_current_symbol_name(self.0.as_ptr());
2420 if name.is_null() {
2421 None
2422 } else {
2423 Some(CStr::from_ptr(name).to_str().unwrap())
2424 }
2425 }
2426 }
2427
2428 #[doc(alias = "ts_lookahead_iterator_reset")]
2433 pub fn reset(&mut self, language: &Language, state: u16) -> bool {
2434 unsafe { ffi::ts_lookahead_iterator_reset(self.0.as_ptr(), language.0, state) }
2435 }
2436
2437 #[doc(alias = "ts_lookahead_iterator_reset_state")]
2442 pub fn reset_state(&mut self, state: u16) -> bool {
2443 unsafe { ffi::ts_lookahead_iterator_reset_state(self.0.as_ptr(), state) }
2444 }
2445
2446 pub fn iter_names(&mut self) -> impl iter::FusedIterator<Item = &str> + '_ {
2448 LookaheadNamesIterator(self)
2449 }
2450}
2451
2452impl<'a> Iterator for LookaheadNamesIterator<'a> {
2453 type Item = &'a str;
2454
2455 #[doc(alias = "ts_lookahead_iterator_next")]
2456 fn next(&mut self) -> Option<Self::Item> {
2457 let ptr = self.0.0.as_ptr();
2458 unsafe {
2462 ffi::ts_lookahead_iterator_next(ptr).then(|| {
2463 let name = ffi::ts_lookahead_iterator_current_symbol_name(ptr);
2464 debug_assert!(!name.is_null());
2465 CStr::from_ptr(name).to_str().unwrap()
2466 })
2467 }
2468 }
2469}
2470
2471impl iter::FusedIterator for LookaheadNamesIterator<'_> {}
2472
2473impl Iterator for LookaheadIterator {
2474 type Item = u16;
2475
2476 #[doc(alias = "ts_lookahead_iterator_next")]
2477 fn next(&mut self) -> Option<Self::Item> {
2478 unsafe { ffi::ts_lookahead_iterator_next(self.0.as_ptr()) }
2479 .then(|| unsafe { ffi::ts_lookahead_iterator_current_symbol(self.0.as_ptr()) })
2480 }
2481}
2482
2483impl iter::FusedIterator for LookaheadIterator {}
2484
2485impl Drop for LookaheadIterator {
2486 #[doc(alias = "ts_lookahead_iterator_delete")]
2487 fn drop(&mut self) {
2488 unsafe { ffi::ts_lookahead_iterator_delete(self.0.as_ptr()) }
2489 }
2490}
2491
2492impl Query {
2493 pub fn new(language: &Language, source: &str) -> Result<Self, QueryError> {
2503 let ptr = Self::new_raw(language, source)?;
2504 unsafe { Self::from_raw_parts(ptr, source) }
2505 }
2506
2507 pub fn new_raw(language: &Language, source: &str) -> Result<*mut ffi::TSQuery, QueryError> {
2513 let mut error_offset = 0u32;
2514 let mut error_type: ffi::TSQueryError = 0;
2515 let bytes = source.as_bytes();
2516
2517 let ptr = unsafe {
2519 ffi::ts_query_new(
2520 language.0,
2521 bytes.as_ptr().cast::<c_char>(),
2522 bytes.len() as u32,
2523 core::ptr::addr_of_mut!(error_offset),
2524 core::ptr::addr_of_mut!(error_type),
2525 )
2526 };
2527
2528 if !ptr.is_null() {
2529 return Ok(ptr);
2530 }
2531
2532 if error_type == ffi::TSQueryErrorLanguage {
2534 return Err(QueryError {
2535 row: 0,
2536 column: 0,
2537 offset: 0,
2538 message: LanguageError::Version(language.abi_version()).to_string(),
2539 kind: QueryErrorKind::Language,
2540 });
2541 }
2542
2543 let offset = error_offset as usize;
2544 let mut line_start = 0;
2545 let mut row = 0;
2546 let mut line_containing_error = None;
2547 for line in source.lines() {
2548 let line_end = line_start + line.len() + 1;
2549 if line_end > offset {
2550 line_containing_error = Some(line);
2551 break;
2552 }
2553 line_start = line_end;
2554 row += 1;
2555 }
2556 let column = offset - line_start;
2557
2558 let (message, kind) = match error_type {
2559 ffi::TSQueryErrorNodeType | ffi::TSQueryErrorField | ffi::TSQueryErrorCapture => {
2561 let suffix = source.split_at(offset).1;
2562 let in_quotes = offset > 0 && source.as_bytes()[offset - 1] == b'"';
2563 let mut backslashes = 0;
2564 let end_offset = suffix
2565 .find(|c| {
2566 if in_quotes {
2567 if c == '"' && backslashes % 2 == 0 {
2568 true
2569 } else if c == '\\' {
2570 backslashes += 1;
2571 false
2572 } else {
2573 backslashes = 0;
2574 false
2575 }
2576 } else {
2577 !char::is_alphanumeric(c) && c != '_' && c != '-'
2578 }
2579 })
2580 .unwrap_or(suffix.len());
2581 (
2582 format!("\"{}\"", suffix.split_at(end_offset).0),
2583 match error_type {
2584 ffi::TSQueryErrorNodeType => QueryErrorKind::NodeType,
2585 ffi::TSQueryErrorField => QueryErrorKind::Field,
2586 ffi::TSQueryErrorCapture => QueryErrorKind::Capture,
2587 _ => unreachable!(),
2588 },
2589 )
2590 }
2591
2592 _ => (
2594 line_containing_error.map_or_else(
2595 || "Unexpected EOF".to_string(),
2596 |line| line.to_string() + "\n" + &" ".repeat(offset - line_start) + "^",
2597 ),
2598 match error_type {
2599 ffi::TSQueryErrorStructure => QueryErrorKind::Structure,
2600 _ => QueryErrorKind::Syntax,
2601 },
2602 ),
2603 };
2604
2605 Err(QueryError {
2606 row,
2607 column,
2608 offset,
2609 message,
2610 kind,
2611 })
2612 }
2613
2614 #[doc(hidden)]
2615 unsafe fn from_raw_parts(ptr: *mut ffi::TSQuery, source: &str) -> Result<Self, QueryError> {
2616 let ptr = {
2617 struct TSQueryDrop(*mut ffi::TSQuery);
2618 impl Drop for TSQueryDrop {
2619 fn drop(&mut self) {
2620 unsafe { ffi::ts_query_delete(self.0) }
2621 }
2622 }
2623 TSQueryDrop(ptr)
2624 };
2625
2626 let string_count = unsafe { ffi::ts_query_string_count(ptr.0) };
2627 let capture_count = unsafe { ffi::ts_query_capture_count(ptr.0) };
2628 let pattern_count = unsafe { ffi::ts_query_pattern_count(ptr.0) as usize };
2629
2630 let mut capture_names = Vec::with_capacity(capture_count as usize);
2631 let mut capture_quantifiers_vec = Vec::with_capacity(pattern_count);
2632 let mut text_predicates_vec = Vec::with_capacity(pattern_count);
2633 let mut property_predicates_vec = Vec::with_capacity(pattern_count);
2634 let mut property_settings_vec = Vec::with_capacity(pattern_count);
2635 let mut general_predicates_vec = Vec::with_capacity(pattern_count);
2636
2637 for i in 0..capture_count {
2639 unsafe {
2640 let mut length = 0u32;
2641 let name =
2642 ffi::ts_query_capture_name_for_id(ptr.0, i, core::ptr::addr_of_mut!(length))
2643 .cast::<u8>();
2644 let name = slice::from_raw_parts(name, length as usize);
2645 let name = str::from_utf8_unchecked(name);
2646 capture_names.push(name);
2647 }
2648 }
2649
2650 for i in 0..pattern_count {
2652 let mut capture_quantifiers = Vec::with_capacity(capture_count as usize);
2653 for j in 0..capture_count {
2654 unsafe {
2655 let quantifier = ffi::ts_query_capture_quantifier_for_id(ptr.0, i as u32, j);
2656 capture_quantifiers.push(quantifier.into());
2657 }
2658 }
2659 capture_quantifiers_vec.push(capture_quantifiers.into());
2660 }
2661
2662 let string_values = (0..string_count)
2664 .map(|i| unsafe {
2665 let mut length = 0u32;
2666 let value =
2667 ffi::ts_query_string_value_for_id(ptr.0, i, core::ptr::addr_of_mut!(length))
2668 .cast::<u8>();
2669 let value = slice::from_raw_parts(value, length as usize);
2670 str::from_utf8_unchecked(value)
2671 })
2672 .collect::<Vec<_>>();
2673
2674 for i in 0..pattern_count {
2676 let predicate_steps = unsafe {
2677 let mut length = 0u32;
2678 let raw_predicates = ffi::ts_query_predicates_for_pattern(
2679 ptr.0,
2680 i as u32,
2681 core::ptr::addr_of_mut!(length),
2682 );
2683 if length > 0 {
2684 slice::from_raw_parts(raw_predicates, length as usize)
2685 } else {
2686 Default::default()
2687 }
2688 };
2689
2690 let byte_offset = unsafe { ffi::ts_query_start_byte_for_pattern(ptr.0, i as u32) };
2691 let row = source
2692 .char_indices()
2693 .take_while(|(i, _)| *i < byte_offset as usize)
2694 .filter(|(_, c)| *c == '\n')
2695 .count();
2696
2697 use ffi::TSQueryPredicateStepType as T;
2698 const TYPE_DONE: T = ffi::TSQueryPredicateStepTypeDone;
2699 const TYPE_CAPTURE: T = ffi::TSQueryPredicateStepTypeCapture;
2700 const TYPE_STRING: T = ffi::TSQueryPredicateStepTypeString;
2701
2702 let mut text_predicates = Vec::new();
2703 let mut property_predicates = Vec::new();
2704 let mut property_settings = Vec::new();
2705 let mut general_predicates = Vec::new();
2706 for p in predicate_steps.split(|s| s.type_ == TYPE_DONE) {
2707 if p.is_empty() {
2708 continue;
2709 }
2710
2711 if p[0].type_ != TYPE_STRING {
2712 return Err(predicate_error(
2713 row,
2714 format!(
2715 "Expected predicate to start with a function name. Got @{}.",
2716 capture_names[p[0].value_id as usize],
2717 ),
2718 ));
2719 }
2720
2721 let operator_name = string_values[p[0].value_id as usize];
2723 match operator_name {
2724 "eq?" | "not-eq?" | "any-eq?" | "any-not-eq?" => {
2725 if p.len() != 3 {
2726 return Err(predicate_error(
2727 row,
2728 format!(
2729 "Wrong number of arguments to #eq? predicate. Expected 2, got {}.",
2730 p.len() - 1
2731 ),
2732 ));
2733 }
2734 if p[1].type_ != TYPE_CAPTURE {
2735 return Err(predicate_error(
2736 row,
2737 format!(
2738 "First argument to #eq? predicate must be a capture name. Got literal \"{}\".",
2739 string_values[p[1].value_id as usize],
2740 ),
2741 ));
2742 }
2743
2744 let is_positive = operator_name == "eq?" || operator_name == "any-eq?";
2745 let match_all = match operator_name {
2746 "eq?" | "not-eq?" => true,
2747 "any-eq?" | "any-not-eq?" => false,
2748 _ => unreachable!(),
2749 };
2750 text_predicates.push(if p[2].type_ == TYPE_CAPTURE {
2751 TextPredicateCapture::EqCapture(
2752 p[1].value_id,
2753 p[2].value_id,
2754 is_positive,
2755 match_all,
2756 )
2757 } else {
2758 TextPredicateCapture::EqString(
2759 p[1].value_id,
2760 string_values[p[2].value_id as usize].to_string().into(),
2761 is_positive,
2762 match_all,
2763 )
2764 });
2765 }
2766
2767 "match?" | "not-match?" | "any-match?" | "any-not-match?" => {
2768 if p.len() != 3 {
2769 return Err(predicate_error(
2770 row,
2771 format!(
2772 "Wrong number of arguments to #match? predicate. Expected 2, got {}.",
2773 p.len() - 1
2774 ),
2775 ));
2776 }
2777 if p[1].type_ != TYPE_CAPTURE {
2778 return Err(predicate_error(
2779 row,
2780 format!(
2781 "First argument to #match? predicate must be a capture name. Got literal \"{}\".",
2782 string_values[p[1].value_id as usize],
2783 ),
2784 ));
2785 }
2786 if p[2].type_ == TYPE_CAPTURE {
2787 return Err(predicate_error(
2788 row,
2789 format!(
2790 "Second argument to #match? predicate must be a literal. Got capture @{}.",
2791 capture_names[p[2].value_id as usize],
2792 ),
2793 ));
2794 }
2795
2796 let is_positive =
2797 operator_name == "match?" || operator_name == "any-match?";
2798 let match_all = match operator_name {
2799 "match?" | "not-match?" => true,
2800 "any-match?" | "any-not-match?" => false,
2801 _ => unreachable!(),
2802 };
2803 let regex = &string_values[p[2].value_id as usize];
2804 text_predicates.push(TextPredicateCapture::MatchString(
2805 p[1].value_id,
2806 regex::bytes::Regex::new(regex).map_err(|_| {
2807 predicate_error(row, format!("Invalid regex '{regex}'"))
2808 })?,
2809 is_positive,
2810 match_all,
2811 ));
2812 }
2813
2814 "set!" => property_settings.push(Self::parse_property(
2815 row,
2816 operator_name,
2817 &capture_names,
2818 &string_values,
2819 &p[1..],
2820 )?),
2821
2822 "is?" | "is-not?" => property_predicates.push((
2823 Self::parse_property(
2824 row,
2825 operator_name,
2826 &capture_names,
2827 &string_values,
2828 &p[1..],
2829 )?,
2830 operator_name == "is?",
2831 )),
2832
2833 "any-of?" | "not-any-of?" => {
2834 if p.len() < 2 {
2835 return Err(predicate_error(
2836 row,
2837 format!(
2838 "Wrong number of arguments to #any-of? predicate. Expected at least 1, got {}.",
2839 p.len() - 1
2840 ),
2841 ));
2842 }
2843 if p[1].type_ != TYPE_CAPTURE {
2844 return Err(predicate_error(
2845 row,
2846 format!(
2847 "First argument to #any-of? predicate must be a capture name. Got literal \"{}\".",
2848 string_values[p[1].value_id as usize],
2849 ),
2850 ));
2851 }
2852
2853 let is_positive = operator_name == "any-of?";
2854 let mut values = Vec::new();
2855 for arg in &p[2..] {
2856 if arg.type_ == TYPE_CAPTURE {
2857 return Err(predicate_error(
2858 row,
2859 format!(
2860 "Arguments to #any-of? predicate must be literals. Got capture @{}.",
2861 capture_names[arg.value_id as usize],
2862 ),
2863 ));
2864 }
2865 values.push(string_values[arg.value_id as usize]);
2866 }
2867 text_predicates.push(TextPredicateCapture::AnyString(
2868 p[1].value_id,
2869 values
2870 .iter()
2871 .map(|x| (*x).to_string().into())
2872 .collect::<Vec<_>>()
2873 .into(),
2874 is_positive,
2875 ));
2876 }
2877
2878 _ => general_predicates.push(QueryPredicate {
2879 operator: operator_name.to_string().into(),
2880 args: p[1..]
2881 .iter()
2882 .map(|a| {
2883 if a.type_ == TYPE_CAPTURE {
2884 QueryPredicateArg::Capture(a.value_id)
2885 } else {
2886 QueryPredicateArg::String(
2887 string_values[a.value_id as usize].to_string().into(),
2888 )
2889 }
2890 })
2891 .collect(),
2892 }),
2893 }
2894 }
2895
2896 text_predicates_vec.push(text_predicates.into());
2897 property_predicates_vec.push(property_predicates.into());
2898 property_settings_vec.push(property_settings.into());
2899 general_predicates_vec.push(general_predicates.into());
2900 }
2901
2902 let result = Self {
2903 ptr: unsafe { NonNull::new_unchecked(ptr.0) },
2904 capture_names: capture_names.into(),
2905 capture_quantifiers: capture_quantifiers_vec.into(),
2906 text_predicates: text_predicates_vec.into(),
2907 property_predicates: property_predicates_vec.into(),
2908 property_settings: property_settings_vec.into(),
2909 general_predicates: general_predicates_vec.into(),
2910 };
2911
2912 core::mem::forget(ptr);
2913
2914 Ok(result)
2915 }
2916
2917 #[doc(alias = "ts_query_start_byte_for_pattern")]
2920 #[must_use]
2921 pub fn start_byte_for_pattern(&self, pattern_index: usize) -> usize {
2922 assert!(
2923 pattern_index < self.text_predicates.len(),
2924 "Pattern index is {pattern_index} but the pattern count is {}",
2925 self.text_predicates.len(),
2926 );
2927 unsafe {
2928 ffi::ts_query_start_byte_for_pattern(self.ptr.as_ptr(), pattern_index as u32) as usize
2929 }
2930 }
2931
2932 #[doc(alias = "ts_query_end_byte_for_pattern")]
2935 #[must_use]
2936 pub fn end_byte_for_pattern(&self, pattern_index: usize) -> usize {
2937 assert!(
2938 pattern_index < self.text_predicates.len(),
2939 "Pattern index is {pattern_index} but the pattern count is {}",
2940 self.text_predicates.len(),
2941 );
2942 unsafe {
2943 ffi::ts_query_end_byte_for_pattern(self.ptr.as_ptr(), pattern_index as u32) as usize
2944 }
2945 }
2946
2947 #[doc(alias = "ts_query_pattern_count")]
2949 #[must_use]
2950 pub fn pattern_count(&self) -> usize {
2951 unsafe { ffi::ts_query_pattern_count(self.ptr.as_ptr()) as usize }
2952 }
2953
2954 #[must_use]
2956 pub const fn capture_names(&self) -> &[&str] {
2957 &self.capture_names
2958 }
2959
2960 #[must_use]
2962 pub const fn capture_quantifiers(&self, index: usize) -> &[CaptureQuantifier] {
2963 &self.capture_quantifiers[index]
2964 }
2965
2966 #[must_use]
2968 pub fn capture_index_for_name(&self, name: &str) -> Option<u32> {
2969 self.capture_names
2970 .iter()
2971 .position(|n| *n == name)
2972 .map(|ix| ix as u32)
2973 }
2974
2975 #[must_use]
2979 pub const fn property_predicates(&self, index: usize) -> &[(QueryProperty, bool)] {
2980 &self.property_predicates[index]
2981 }
2982
2983 #[must_use]
2987 pub const fn property_settings(&self, index: usize) -> &[QueryProperty] {
2988 &self.property_settings[index]
2989 }
2990
2991 #[must_use]
2999 pub const fn general_predicates(&self, index: usize) -> &[QueryPredicate] {
3000 &self.general_predicates[index]
3001 }
3002
3003 #[doc(alias = "ts_query_disable_capture")]
3008 pub fn disable_capture(&mut self, name: &str) {
3009 unsafe {
3010 ffi::ts_query_disable_capture(
3011 self.ptr.as_ptr(),
3012 name.as_bytes().as_ptr().cast::<c_char>(),
3013 name.len() as u32,
3014 );
3015 }
3016 }
3017
3018 #[doc(alias = "ts_query_disable_pattern")]
3023 pub fn disable_pattern(&mut self, index: usize) {
3024 unsafe { ffi::ts_query_disable_pattern(self.ptr.as_ptr(), index as u32) }
3025 }
3026
3027 #[doc(alias = "ts_query_copy")]
3034 #[must_use]
3035 pub fn deep_clone(&self) -> Self {
3036 let ptr = unsafe { ffi::ts_query_copy(self.ptr.as_ptr()) };
3037 unsafe { Self::from_raw_parts(ptr, "").unwrap_unchecked() }
3042 }
3043
3044 #[doc(alias = "ts_query_is_pattern_rooted")]
3046 #[must_use]
3047 pub fn is_pattern_rooted(&self, index: usize) -> bool {
3048 unsafe { ffi::ts_query_is_pattern_rooted(self.ptr.as_ptr(), index as u32) }
3049 }
3050
3051 #[doc(alias = "ts_query_is_pattern_non_local")]
3053 #[must_use]
3054 pub fn is_pattern_non_local(&self, index: usize) -> bool {
3055 unsafe { ffi::ts_query_is_pattern_non_local(self.ptr.as_ptr(), index as u32) }
3056 }
3057
3058 #[doc(alias = "ts_query_is_pattern_guaranteed_at_step")]
3063 #[must_use]
3064 pub fn is_pattern_guaranteed_at_step(&self, byte_offset: usize) -> bool {
3065 unsafe {
3066 ffi::ts_query_is_pattern_guaranteed_at_step(self.ptr.as_ptr(), byte_offset as u32)
3067 }
3068 }
3069
3070 fn parse_property(
3071 row: usize,
3072 function_name: &str,
3073 capture_names: &[&str],
3074 string_values: &[&str],
3075 args: &[ffi::TSQueryPredicateStep],
3076 ) -> Result<QueryProperty, QueryError> {
3077 if args.is_empty() || args.len() > 3 {
3078 return Err(predicate_error(
3079 row,
3080 format!(
3081 "Wrong number of arguments to {function_name} predicate. Expected 1 to 3, got {}.",
3082 args.len(),
3083 ),
3084 ));
3085 }
3086
3087 let mut capture_id = None;
3088 let mut key = None;
3089 let mut value = None;
3090
3091 for arg in args {
3092 if arg.type_ == ffi::TSQueryPredicateStepTypeCapture {
3093 if capture_id.is_some() {
3094 return Err(predicate_error(
3095 row,
3096 format!(
3097 "Invalid arguments to {function_name} predicate. Unexpected second capture name @{}",
3098 capture_names[arg.value_id as usize]
3099 ),
3100 ));
3101 }
3102 capture_id = Some(arg.value_id as usize);
3103 } else if key.is_none() {
3104 key = Some(&string_values[arg.value_id as usize]);
3105 } else if value.is_none() {
3106 value = Some(string_values[arg.value_id as usize]);
3107 } else {
3108 return Err(predicate_error(
3109 row,
3110 format!(
3111 "Invalid arguments to {function_name} predicate. Unexpected third argument @{}",
3112 string_values[arg.value_id as usize]
3113 ),
3114 ));
3115 }
3116 }
3117
3118 if let Some(key) = key {
3119 Ok(QueryProperty::new(key, value, capture_id))
3120 } else {
3121 Err(predicate_error(
3122 row,
3123 format!("Invalid arguments to {function_name} predicate. Missing key argument"),
3124 ))
3125 }
3126 }
3127}
3128
3129impl Default for QueryCursor {
3130 fn default() -> Self {
3131 Self::new()
3132 }
3133}
3134
3135impl QueryCursor {
3136 #[doc(alias = "ts_query_cursor_new")]
3141 #[must_use]
3142 pub fn new() -> Self {
3143 Self {
3144 ptr: unsafe { NonNull::new_unchecked(ffi::ts_query_cursor_new()) },
3145 }
3146 }
3147
3148 #[doc(alias = "ts_query_cursor_match_limit")]
3150 #[must_use]
3151 pub fn match_limit(&self) -> u32 {
3152 unsafe { ffi::ts_query_cursor_match_limit(self.ptr.as_ptr()) }
3153 }
3154
3155 #[doc(alias = "ts_query_cursor_set_match_limit")]
3158 pub fn set_match_limit(&mut self, limit: u32) {
3159 unsafe {
3160 ffi::ts_query_cursor_set_match_limit(self.ptr.as_ptr(), limit);
3161 }
3162 }
3163
3164 #[doc(alias = "ts_query_cursor_did_exceed_match_limit")]
3167 #[must_use]
3168 pub fn did_exceed_match_limit(&self) -> bool {
3169 unsafe { ffi::ts_query_cursor_did_exceed_match_limit(self.ptr.as_ptr()) }
3170 }
3171
3172 #[doc(alias = "ts_query_cursor_exec")]
3183 pub fn matches<'query, 'cursor: 'query, 'tree, T: TextProvider<I>, I: AsRef<[u8]>>(
3184 &'cursor mut self,
3185 query: &'query Query,
3186 node: Node<'tree>,
3187 text_provider: T,
3188 ) -> QueryMatches<'query, 'tree, 'static, T, I> {
3189 let ptr = self.ptr.as_ptr();
3190 unsafe { ffi::ts_query_cursor_exec(ptr, query.ptr.as_ptr(), node.0) };
3191 QueryMatches {
3192 ptr,
3193 query,
3194 text_provider,
3195 buffer1: Vec::default(),
3196 buffer2: Vec::default(),
3197 current_match: None,
3198 _options: None,
3199 _phantom: PhantomData,
3200 }
3201 }
3202
3203 #[doc(alias = "ts_query_cursor_exec_with_options")]
3210 pub fn matches_with_options<
3211 'query,
3212 'cursor: 'query,
3213 'tree,
3214 'options,
3215 T: TextProvider<I>,
3216 I: AsRef<[u8]>,
3217 >(
3218 &'cursor mut self,
3219 query: &'query Query,
3220 node: Node<'tree>,
3221 text_provider: T,
3222 options: QueryCursorOptions<'options>,
3223 ) -> QueryMatches<'query, 'tree, 'options, T, I> {
3224 unsafe extern "C" fn progress(state: *mut ffi::TSQueryCursorState) -> bool {
3225 unsafe {
3226 let callback = (*state)
3227 .payload
3228 .cast::<QueryProgressCallback>()
3229 .as_mut()
3230 .unwrap();
3231 match callback(&QueryCursorState::from_raw(state)) {
3232 ControlFlow::Continue(()) => false,
3233 ControlFlow::Break(()) => true,
3234 }
3235 }
3236 }
3237
3238 let query_options = options.progress_callback.map(|cb| {
3239 QueryCursorOptionsDrop(
3240 Box::into_raw(Box::new(ffi::TSQueryCursorOptions {
3241 payload: Box::into_raw(Box::new(cb)).cast::<c_void>(),
3242 progress_callback: Some(progress),
3243 })),
3244 PhantomData,
3245 )
3246 });
3247
3248 let ptr = self.ptr.as_ptr();
3249 unsafe {
3250 ffi::ts_query_cursor_exec_with_options(
3251 ptr,
3252 query.ptr.as_ptr(),
3253 node.0,
3254 query_options.as_ref().map_or(ptr::null_mut(), |q| q.0),
3255 );
3256 }
3257 QueryMatches {
3258 ptr,
3259 query,
3260 text_provider,
3261 buffer1: Vec::default(),
3262 buffer2: Vec::default(),
3263 current_match: None,
3264 _options: query_options,
3265 _phantom: PhantomData,
3266 }
3267 }
3268
3269 #[doc(alias = "ts_query_cursor_exec")]
3279 pub fn captures<'query, 'cursor: 'query, 'tree, T: TextProvider<I>, I: AsRef<[u8]>>(
3280 &'cursor mut self,
3281 query: &'query Query,
3282 node: Node<'tree>,
3283 text_provider: T,
3284 ) -> QueryCaptures<'query, 'tree, 'static, T, I> {
3285 let ptr = self.ptr.as_ptr();
3286 unsafe { ffi::ts_query_cursor_exec(ptr, query.ptr.as_ptr(), node.0) };
3287 QueryCaptures {
3288 ptr,
3289 query,
3290 text_provider,
3291 buffer1: Vec::default(),
3292 buffer2: Vec::default(),
3293 current_match: None,
3294 _options: None,
3295 _phantom: PhantomData,
3296 }
3297 }
3298
3299 #[doc(alias = "ts_query_cursor_exec")]
3305 pub fn captures_with_options<
3306 'query,
3307 'cursor: 'query,
3308 'tree,
3309 'options,
3310 T: TextProvider<I>,
3311 I: AsRef<[u8]>,
3312 >(
3313 &'cursor mut self,
3314 query: &'query Query,
3315 node: Node<'tree>,
3316 text_provider: T,
3317 options: QueryCursorOptions<'options>,
3318 ) -> QueryCaptures<'query, 'tree, 'options, T, I> {
3319 unsafe extern "C" fn progress(state: *mut ffi::TSQueryCursorState) -> bool {
3320 unsafe {
3321 let callback = (*state)
3322 .payload
3323 .cast::<QueryProgressCallback>()
3324 .as_mut()
3325 .unwrap();
3326 match callback(&QueryCursorState::from_raw(state)) {
3327 ControlFlow::Continue(()) => false,
3328 ControlFlow::Break(()) => true,
3329 }
3330 }
3331 }
3332
3333 let query_options = options.progress_callback.map(|cb| {
3334 QueryCursorOptionsDrop(
3335 Box::into_raw(Box::new(ffi::TSQueryCursorOptions {
3336 payload: Box::into_raw(Box::new(cb)).cast::<c_void>(),
3337 progress_callback: Some(progress),
3338 })),
3339 PhantomData,
3340 )
3341 });
3342
3343 let ptr = self.ptr.as_ptr();
3344 unsafe {
3345 ffi::ts_query_cursor_exec_with_options(
3346 ptr,
3347 query.ptr.as_ptr(),
3348 node.0,
3349 query_options.as_ref().map_or(ptr::null_mut(), |q| q.0),
3350 );
3351 }
3352 QueryCaptures {
3353 ptr,
3354 query,
3355 text_provider,
3356 buffer1: Vec::default(),
3357 buffer2: Vec::default(),
3358 current_match: None,
3359 _options: query_options,
3360 _phantom: PhantomData,
3361 }
3362 }
3363
3364 #[doc(alias = "ts_query_cursor_set_byte_range")]
3367 pub fn set_byte_range(&mut self, range: ops::Range<usize>) -> &mut Self {
3368 unsafe {
3369 ffi::ts_query_cursor_set_byte_range(
3370 self.ptr.as_ptr(),
3371 range.start as u32,
3372 range.end as u32,
3373 );
3374 }
3375 self
3376 }
3377
3378 #[doc(alias = "ts_query_cursor_set_point_range")]
3381 pub fn set_point_range(&mut self, range: ops::Range<Point>) -> &mut Self {
3382 unsafe {
3383 ffi::ts_query_cursor_set_point_range(
3384 self.ptr.as_ptr(),
3385 range.start.into(),
3386 range.end.into(),
3387 );
3388 }
3389 self
3390 }
3391
3392 #[doc(alias = "ts_query_cursor_set_containing_byte_range")]
3400 pub fn set_containing_byte_range(&mut self, range: ops::Range<usize>) -> &mut Self {
3401 unsafe {
3402 ffi::ts_query_cursor_set_containing_byte_range(
3403 self.ptr.as_ptr(),
3404 range.start as u32,
3405 range.end as u32,
3406 );
3407 }
3408 self
3409 }
3410
3411 #[doc(alias = "ts_query_cursor_set_containing_point_range")]
3419 pub fn set_containing_point_range(&mut self, range: ops::Range<Point>) -> &mut Self {
3420 unsafe {
3421 ffi::ts_query_cursor_set_containing_point_range(
3422 self.ptr.as_ptr(),
3423 range.start.into(),
3424 range.end.into(),
3425 );
3426 }
3427 self
3428 }
3429
3430 #[doc(alias = "ts_query_cursor_set_max_start_depth")]
3445 pub fn set_max_start_depth(&mut self, max_start_depth: Option<u32>) -> &mut Self {
3446 unsafe {
3447 ffi::ts_query_cursor_set_max_start_depth(
3448 self.ptr.as_ptr(),
3449 max_start_depth.unwrap_or(u32::MAX),
3450 );
3451 }
3452 self
3453 }
3454}
3455
3456impl<'tree> QueryMatch<'_, 'tree> {
3457 #[must_use]
3458 pub const fn id(&self) -> u32 {
3459 self.id
3460 }
3461
3462 #[must_use]
3463 pub const fn captures(&self) -> &[QueryCapture<'tree>] {
3464 self.captures
3465 }
3466
3467 #[doc(alias = "ts_query_cursor_remove_match")]
3468 pub fn remove(&self) {
3469 unsafe { ffi::ts_query_cursor_remove_match(self.cursor, self.id) }
3470 }
3471
3472 pub fn nodes_for_capture_index(
3473 &self,
3474 capture_ix: u32,
3475 ) -> impl Iterator<Item = Node<'tree>> + '_ {
3476 self.captures
3477 .iter()
3478 .filter_map(move |capture| (capture.index == capture_ix).then_some(capture.node))
3479 }
3480
3481 fn new(m: &ffi::TSQueryMatch, cursor: *mut ffi::TSQueryCursor) -> Self {
3482 QueryMatch {
3483 cursor,
3484 id: m.id,
3485 pattern_index: m.pattern_index as usize,
3486 captures: if m.capture_count > 0 {
3487 unsafe {
3488 slice::from_raw_parts(
3489 m.captures.cast::<QueryCapture<'tree>>(),
3490 m.capture_count as usize,
3491 )
3492 }
3493 } else {
3494 Default::default()
3495 },
3496 }
3497 }
3498
3499 pub fn satisfies_text_predicates<I: AsRef<[u8]>>(
3500 &self,
3501 query: &Query,
3502 buffer1: &mut Vec<u8>,
3503 buffer2: &mut Vec<u8>,
3504 text_provider: &mut impl TextProvider<I>,
3505 ) -> bool {
3506 struct NodeText<'a, T> {
3507 buffer: &'a mut Vec<u8>,
3508 first_chunk: Option<T>,
3509 }
3510 impl<'a, T: AsRef<[u8]>> NodeText<'a, T> {
3511 const fn new(buffer: &'a mut Vec<u8>) -> Self {
3512 Self {
3513 buffer,
3514 first_chunk: None,
3515 }
3516 }
3517
3518 fn get_text(&mut self, chunks: &mut impl Iterator<Item = T>) -> &[u8] {
3519 self.first_chunk = chunks.next();
3520 if let Some(next_chunk) = chunks.next() {
3521 self.buffer.clear();
3522 self.buffer
3523 .extend_from_slice(self.first_chunk.as_ref().unwrap().as_ref());
3524 self.buffer.extend_from_slice(next_chunk.as_ref());
3525 for chunk in chunks {
3526 self.buffer.extend_from_slice(chunk.as_ref());
3527 }
3528 self.buffer.as_slice()
3529 } else if let Some(ref first_chunk) = self.first_chunk {
3530 first_chunk.as_ref()
3531 } else {
3532 &[]
3533 }
3534 }
3535 }
3536
3537 let mut node_text1 = NodeText::new(buffer1);
3538 let mut node_text2 = NodeText::new(buffer2);
3539
3540 query.text_predicates[self.pattern_index]
3541 .iter()
3542 .all(|predicate| match predicate {
3543 TextPredicateCapture::EqCapture(i, j, is_positive, match_all_nodes) => {
3544 let mut nodes_1 = self.nodes_for_capture_index(*i).peekable();
3545 let mut nodes_2 = self.nodes_for_capture_index(*j).peekable();
3546 while nodes_1.peek().is_some() && nodes_2.peek().is_some() {
3547 let node1 = nodes_1.next().unwrap();
3548 let node2 = nodes_2.next().unwrap();
3549 let mut text1 = text_provider.text(node1);
3550 let mut text2 = text_provider.text(node2);
3551 let text1 = node_text1.get_text(&mut text1);
3552 let text2 = node_text2.get_text(&mut text2);
3553 let is_positive_match = text1 == text2;
3554 if is_positive_match != *is_positive && *match_all_nodes {
3555 return false;
3556 }
3557 if is_positive_match == *is_positive && !*match_all_nodes {
3558 return true;
3559 }
3560 }
3561 nodes_1.next().is_none() && nodes_2.next().is_none()
3562 }
3563 TextPredicateCapture::EqString(i, s, is_positive, match_all_nodes) => {
3564 let nodes = self.nodes_for_capture_index(*i);
3565 for node in nodes {
3566 let mut text = text_provider.text(node);
3567 let text = node_text1.get_text(&mut text);
3568 let is_positive_match = text == s.as_bytes();
3569 if is_positive_match != *is_positive && *match_all_nodes {
3570 return false;
3571 }
3572 if is_positive_match == *is_positive && !*match_all_nodes {
3573 return true;
3574 }
3575 }
3576 true
3577 }
3578 TextPredicateCapture::MatchString(i, r, is_positive, match_all_nodes) => {
3579 let nodes = self.nodes_for_capture_index(*i);
3580 for node in nodes {
3581 let mut text = text_provider.text(node);
3582 let text = node_text1.get_text(&mut text);
3583 let is_positive_match = r.is_match(text);
3584 if is_positive_match != *is_positive && *match_all_nodes {
3585 return false;
3586 }
3587 if is_positive_match == *is_positive && !*match_all_nodes {
3588 return true;
3589 }
3590 }
3591 true
3592 }
3593 TextPredicateCapture::AnyString(i, v, is_positive) => {
3594 let nodes = self.nodes_for_capture_index(*i);
3595 for node in nodes {
3596 let mut text = text_provider.text(node);
3597 let text = node_text1.get_text(&mut text);
3598 if (v.iter().any(|s| text == s.as_bytes())) != *is_positive {
3599 return false;
3600 }
3601 }
3602 true
3603 }
3604 })
3605 }
3606}
3607
3608impl QueryProperty {
3609 #[must_use]
3610 pub fn new(key: &str, value: Option<&str>, capture_id: Option<usize>) -> Self {
3611 Self {
3612 capture_id,
3613 key: key.to_string().into(),
3614 value: value.map(|s| s.to_string().into()),
3615 }
3616 }
3617}
3618
3619impl<'query, 'tree, T: TextProvider<I>, I: AsRef<[u8]>> StreamingIterator
3623 for QueryMatches<'query, 'tree, '_, T, I>
3624{
3625 type Item = QueryMatch<'query, 'tree>;
3626
3627 fn advance(&mut self) {
3628 self.current_match = unsafe {
3629 loop {
3630 let mut m = MaybeUninit::<ffi::TSQueryMatch>::uninit();
3631 if ffi::ts_query_cursor_next_match(self.ptr, m.as_mut_ptr()) {
3632 let result = QueryMatch::new(&m.assume_init(), self.ptr);
3633 if result.satisfies_text_predicates(
3634 self.query,
3635 &mut self.buffer1,
3636 &mut self.buffer2,
3637 &mut self.text_provider,
3638 ) {
3639 break Some(result);
3640 }
3641 } else {
3642 break None;
3643 }
3644 }
3645 };
3646 }
3647
3648 fn get(&self) -> Option<&Self::Item> {
3649 self.current_match.as_ref()
3650 }
3651}
3652
3653impl<T: TextProvider<I>, I: AsRef<[u8]>> StreamingIteratorMut for QueryMatches<'_, '_, '_, T, I> {
3654 fn get_mut(&mut self) -> Option<&mut Self::Item> {
3655 self.current_match.as_mut()
3656 }
3657}
3658
3659impl<'query, 'tree, T: TextProvider<I>, I: AsRef<[u8]>> StreamingIterator
3660 for QueryCaptures<'query, 'tree, '_, T, I>
3661{
3662 type Item = (QueryMatch<'query, 'tree>, usize);
3663
3664 fn advance(&mut self) {
3665 self.current_match = unsafe {
3666 loop {
3667 let mut capture_index = 0u32;
3668 let mut m = MaybeUninit::<ffi::TSQueryMatch>::uninit();
3669 if ffi::ts_query_cursor_next_capture(
3670 self.ptr,
3671 m.as_mut_ptr(),
3672 core::ptr::addr_of_mut!(capture_index),
3673 ) {
3674 let result = QueryMatch::new(&m.assume_init(), self.ptr);
3675 if result.satisfies_text_predicates(
3676 self.query,
3677 &mut self.buffer1,
3678 &mut self.buffer2,
3679 &mut self.text_provider,
3680 ) {
3681 break Some((result, capture_index as usize));
3682 }
3683 result.remove();
3684 } else {
3685 break None;
3686 }
3687 }
3688 }
3689 }
3690
3691 fn get(&self) -> Option<&Self::Item> {
3692 self.current_match.as_ref()
3693 }
3694}
3695
3696impl<T: TextProvider<I>, I: AsRef<[u8]>> StreamingIteratorMut for QueryCaptures<'_, '_, '_, T, I> {
3697 fn get_mut(&mut self) -> Option<&mut Self::Item> {
3698 self.current_match.as_mut()
3699 }
3700}
3701
3702impl<T: TextProvider<I>, I: AsRef<[u8]>> QueryMatches<'_, '_, '_, T, I> {
3703 #[doc(alias = "ts_query_cursor_set_byte_range")]
3704 pub fn set_byte_range(&mut self, range: ops::Range<usize>) {
3705 unsafe {
3706 ffi::ts_query_cursor_set_byte_range(self.ptr, range.start as u32, range.end as u32);
3707 }
3708 }
3709
3710 #[doc(alias = "ts_query_cursor_set_point_range")]
3711 pub fn set_point_range(&mut self, range: ops::Range<Point>) {
3712 unsafe {
3713 ffi::ts_query_cursor_set_point_range(self.ptr, range.start.into(), range.end.into());
3714 }
3715 }
3716}
3717
3718impl<T: TextProvider<I>, I: AsRef<[u8]>> QueryCaptures<'_, '_, '_, T, I> {
3719 #[doc(alias = "ts_query_cursor_set_byte_range")]
3720 pub fn set_byte_range(&mut self, range: ops::Range<usize>) {
3721 unsafe {
3722 ffi::ts_query_cursor_set_byte_range(self.ptr, range.start as u32, range.end as u32);
3723 }
3724 }
3725
3726 #[doc(alias = "ts_query_cursor_set_point_range")]
3727 pub fn set_point_range(&mut self, range: ops::Range<Point>) {
3728 unsafe {
3729 ffi::ts_query_cursor_set_point_range(self.ptr, range.start.into(), range.end.into());
3730 }
3731 }
3732}
3733
3734impl fmt::Debug for QueryMatch<'_, '_> {
3735 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3736 write!(
3737 f,
3738 "QueryMatch {{ id: {}, pattern_index: {}, captures: {:?} }}",
3739 self.id, self.pattern_index, self.captures
3740 )
3741 }
3742}
3743
3744impl<F, R, I> TextProvider<I> for F
3745where
3746 F: FnMut(Node) -> R,
3747 R: Iterator<Item = I>,
3748 I: AsRef<[u8]>,
3749{
3750 type I = R;
3751
3752 fn text(&mut self, node: Node) -> Self::I {
3753 (self)(node)
3754 }
3755}
3756
3757impl<'a> TextProvider<&'a [u8]> for &'a [u8] {
3758 type I = iter::Once<&'a [u8]>;
3759
3760 fn text(&mut self, node: Node) -> Self::I {
3761 iter::once(&self[node.byte_range()])
3762 }
3763}
3764
3765impl PartialEq for Query {
3766 fn eq(&self, other: &Self) -> bool {
3767 self.ptr == other.ptr
3768 }
3769}
3770
3771impl Drop for Query {
3772 fn drop(&mut self) {
3773 unsafe { ffi::ts_query_delete(self.ptr.as_ptr()) }
3774 }
3775}
3776
3777impl Drop for QueryCursor {
3778 fn drop(&mut self) {
3779 unsafe { ffi::ts_query_cursor_delete(self.ptr.as_ptr()) }
3780 }
3781}
3782
3783impl Point {
3784 #[must_use]
3785 pub const fn new(row: usize, column: usize) -> Self {
3786 Self { row, column }
3787 }
3788}
3789
3790impl fmt::Display for Point {
3791 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3792 write!(f, "({}, {})", self.row, self.column)
3793 }
3794}
3795
3796impl From<Point> for ffi::TSPoint {
3797 fn from(val: Point) -> Self {
3798 Self {
3799 row: val.row as u32,
3800 column: val.column as u32,
3801 }
3802 }
3803}
3804
3805impl From<ffi::TSPoint> for Point {
3806 fn from(point: ffi::TSPoint) -> Self {
3807 Self {
3808 row: point.row as usize,
3809 column: point.column as usize,
3810 }
3811 }
3812}
3813
3814impl From<Range> for ffi::TSRange {
3815 fn from(val: Range) -> Self {
3816 Self {
3817 start_byte: val.start_byte as u32,
3818 end_byte: val.end_byte as u32,
3819 start_point: val.start_point.into(),
3820 end_point: val.end_point.into(),
3821 }
3822 }
3823}
3824
3825impl From<ffi::TSRange> for Range {
3826 fn from(range: ffi::TSRange) -> Self {
3827 Self {
3828 start_byte: range.start_byte as usize,
3829 end_byte: range.end_byte as usize,
3830 start_point: range.start_point.into(),
3831 end_point: range.end_point.into(),
3832 }
3833 }
3834}
3835
3836impl From<&InputEdit> for ffi::TSInputEdit {
3837 fn from(val: &InputEdit) -> Self {
3838 Self {
3839 start_byte: val.start_byte as u32,
3840 old_end_byte: val.old_end_byte as u32,
3841 new_end_byte: val.new_end_byte as u32,
3842 start_point: val.start_position.into(),
3843 old_end_point: val.old_end_position.into(),
3844 new_end_point: val.new_end_position.into(),
3845 }
3846 }
3847}
3848
3849impl<'a> LossyUtf8<'a> {
3850 #[must_use]
3851 pub const fn new(bytes: &'a [u8]) -> Self {
3852 LossyUtf8 {
3853 bytes,
3854 in_replacement: false,
3855 }
3856 }
3857}
3858
3859impl<'a> Iterator for LossyUtf8<'a> {
3860 type Item = &'a str;
3861
3862 fn next(&mut self) -> Option<&'a str> {
3863 if self.bytes.is_empty() {
3864 return None;
3865 }
3866 if self.in_replacement {
3867 self.in_replacement = false;
3868 return Some("\u{fffd}");
3869 }
3870 match core::str::from_utf8(self.bytes) {
3871 Ok(valid) => {
3872 self.bytes = &[];
3873 Some(valid)
3874 }
3875 Err(error) => {
3876 if let Some(error_len) = error.error_len() {
3877 let error_start = error.valid_up_to();
3878 if error_start > 0 {
3879 let result =
3880 unsafe { core::str::from_utf8_unchecked(&self.bytes[..error_start]) };
3881 self.bytes = &self.bytes[(error_start + error_len)..];
3882 self.in_replacement = true;
3883 Some(result)
3884 } else {
3885 self.bytes = &self.bytes[error_len..];
3886 Some("\u{fffd}")
3887 }
3888 } else {
3889 None
3890 }
3891 }
3892 }
3893 }
3894}
3895
3896#[must_use]
3897const fn predicate_error(row: usize, message: String) -> QueryError {
3898 QueryError {
3899 kind: QueryErrorKind::Predicate,
3900 row,
3901 column: 0,
3902 offset: 0,
3903 message,
3904 }
3905}
3906
3907impl fmt::Display for IncludedRangesError {
3908 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3909 write!(f, "Incorrect range by index: {}", self.0)
3910 }
3911}
3912
3913impl fmt::Display for LanguageError {
3914 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3915 match self {
3916 Self::Version(version) => {
3917 write!(
3918 f,
3919 "Incompatible language version {version:#x}. Expected {LANGUAGE_VERSION:#x}",
3920 )
3921 }
3922 Self::NotParseable => {
3923 write!(f, "Language cannot be used for parsing.")
3924 }
3925 #[cfg(feature = "wasm")]
3926 Self::Wasm => {
3927 write!(f, "Failed to load the Wasm store.")
3928 }
3929 }
3930 }
3931}
3932
3933impl fmt::Display for QueryError {
3934 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3935 let msg = match self.kind {
3936 QueryErrorKind::Field => "Invalid field name ",
3937 QueryErrorKind::NodeType => "Invalid node type ",
3938 QueryErrorKind::Capture => "Invalid capture name ",
3939 QueryErrorKind::Predicate => "Invalid predicate: ",
3940 QueryErrorKind::Structure => "Invalid pattern structure:\n",
3941 QueryErrorKind::Syntax => "Invalid syntax:\n",
3942 QueryErrorKind::Language => "",
3943 };
3944 if msg.is_empty() {
3945 write!(f, "{}", self.message)
3946 } else {
3947 write!(
3948 f,
3949 "Query error at {}:{}. {}{}",
3950 self.row + 1,
3951 self.column + 1,
3952 msg,
3953 self.message
3954 )
3955 }
3956 }
3957}
3958
3959#[doc(hidden)]
3960#[must_use]
3961pub fn format_sexp(sexp: &str, initial_indent_level: usize) -> String {
3962 let sexp = sexp.trim();
3963 let mut indent_level = initial_indent_level;
3964 let mut formatted = String::with_capacity(sexp.len());
3965 let mut has_field = false;
3966
3967 let mut c_iter = sexp.chars().peekable();
3968 let mut scratch = String::with_capacity(sexp.len());
3969 let mut quote = '\0';
3970 let mut saw_paren = false;
3971 let mut did_last = false;
3972 let mut first_token = true;
3973 let mut quote_suffixes = quote_suffix_minimum_depths(sexp);
3974 let mut byte_offset = 0;
3975
3976 let mut fetch_next_str = |next: &mut String, payload_quote: char, open_nodes: usize| {
3977 let root_token = first_token;
3978 first_token = false;
3979 let open_nodes = if root_token { 1 } else { open_nodes };
3980 next.clear();
3981 let mut separated = false;
3982 while let Some(c) = c_iter.next() {
3983 byte_offset += c.len_utf8();
3984 if quote != '\0' {
3985 if c == quote
3989 && quote_closing_depth(c_iter.clone()).is_some_and(|depth| depth <= open_nodes)
3990 {
3991 quote = '\0';
3992 }
3993 } else if next.is_empty() && c == payload_quote {
3994 let suffixes = &mut quote_suffixes[usize::from(c == '"')];
3995 while suffixes
3996 .last()
3997 .is_some_and(|&(offset, _)| offset < byte_offset)
3998 {
3999 suffixes.pop();
4000 }
4001 if suffixes
4002 .last()
4003 .is_some_and(|&(_, depth)| depth <= open_nodes)
4004 {
4005 quote = c;
4006 }
4007 } else if root_token
4008 && next == "("
4009 && c == '"'
4010 && sexp.len() > 3
4011 && sexp.ends_with("\")")
4012 {
4013 quote = c;
4014 } else if c == ' ' {
4015 separated = true;
4016 break;
4017 } else if c == ')' {
4018 saw_paren = true;
4019 break;
4020 }
4021 next.push(c);
4022 }
4023
4024 if c_iter.peek().is_none() && next.is_empty() {
4025 if saw_paren {
4026 saw_paren = false;
4027 return Some(false);
4028 }
4029 if !did_last {
4030 did_last = true;
4031 return Some(false);
4032 }
4033 return None;
4034 }
4035 let has_payload = separated
4036 && (next == "(MISSING" || next == "(UNEXPECTED")
4037 && c_iter.peek().is_some_and(|&c| c != '(' && c != ')')
4038 && !sexp_field_follows(c_iter.clone());
4039 Some(has_payload)
4040 };
4041
4042 while let Some(has_payload) = fetch_next_str(
4043 &mut scratch,
4044 '\0',
4045 indent_level.saturating_sub(initial_indent_level),
4046 ) {
4047 if scratch.is_empty() && indent_level > initial_indent_level {
4048 indent_level -= 1;
4049 write!(formatted, ")").unwrap();
4050 } else if scratch.starts_with('(') {
4051 if has_field {
4052 has_field = false;
4053 } else {
4054 if indent_level > 0 {
4055 writeln!(formatted).unwrap();
4056 for _ in 0..indent_level {
4057 write!(formatted, " ").unwrap();
4058 }
4059 }
4060 indent_level += 1;
4061 }
4062
4063 write!(formatted, "{scratch}").unwrap();
4064
4065 if has_payload {
4066 let payload_quote = if scratch == "(UNEXPECTED" { '\'' } else { '"' };
4067 fetch_next_str(
4068 &mut scratch,
4069 payload_quote,
4070 indent_level.saturating_sub(initial_indent_level),
4071 )
4072 .unwrap();
4073 if scratch.is_empty() {
4074 while indent_level > initial_indent_level {
4075 indent_level -= 1;
4076 write!(formatted, ")").unwrap();
4077 }
4078 } else {
4079 write!(formatted, " {scratch}").unwrap();
4080 }
4081 }
4082 } else if scratch.ends_with(':') {
4083 writeln!(formatted).unwrap();
4084 for _ in 0..indent_level {
4085 write!(formatted, " ").unwrap();
4086 }
4087 write!(formatted, "{scratch} ").unwrap();
4088 has_field = true;
4089 indent_level += 1;
4090 }
4091 }
4092
4093 formatted
4094}
4095
4096fn sexp_field_follows(mut chars: impl Iterator<Item = char>) -> bool {
4097 let mut last = None;
4098 for c in chars.by_ref() {
4099 match c {
4100 '(' | ')' | '\'' | '"' => return false,
4101 ' ' => break,
4102 _ => last = Some(c),
4103 }
4104 }
4105 last == Some(':') && chars.next() == Some('(')
4106}
4107
4108fn quote_suffix_minimum_depths(sexp: &str) -> [Vec<(usize, usize)>; 2] {
4109 let mut suffixes: [Vec<(usize, usize)>; 2] = [Vec::new(), Vec::new()];
4110 for (offset, c) in sexp.char_indices().rev() {
4111 if c != '\'' && c != '"' {
4112 continue;
4113 }
4114 if let Some(depth) = quote_closing_depth(sexp[offset + 1..].chars()) {
4115 let quotes = &mut suffixes[usize::from(c == '"')];
4116 if quotes.last().is_none_or(|&(_, minimum)| depth < minimum) {
4118 quotes.push((offset, depth));
4119 }
4120 }
4121 }
4122 suffixes
4123}
4124
4125fn quote_closing_depth(mut chars: impl Iterator<Item = char>) -> Option<usize> {
4126 match chars.next() {
4127 None => Some(0),
4128 Some(')') => {
4129 let mut depth = 1;
4130 for c in chars {
4131 match c {
4132 ')' => depth += 1,
4133 c if c.is_whitespace() => return Some(depth),
4134 _ => return None,
4135 }
4136 }
4137 Some(depth)
4138 }
4139 _ => None,
4140 }
4141}
4142
4143pub fn wasm_stdlib_symbols() -> impl Iterator<Item = &'static str> {
4144 const WASM_STDLIB_SYMBOLS: &str = include_str!(concat!(env!("OUT_DIR"), "/stdlib-symbols.txt"));
4145
4146 WASM_STDLIB_SYMBOLS
4147 .lines()
4148 .map(|s| s.trim_matches(|c| c == '"' || c == ','))
4149}
4150
4151unsafe extern "C" {
4152 fn ts_node_string_pretty(node: ffi::TSNode, initial_indent_level: usize) -> *mut c_char;
4153 static mut ts_current_free: unsafe extern "C" fn(ptr: *mut c_void);
4154}
4155
4156#[inline]
4159unsafe fn ts_free(ptr: *mut c_void) {
4160 let f = unsafe { core::ptr::addr_of!(ts_current_free).read() };
4161 unsafe { f(ptr) };
4162}
4163
4164#[derive(Copy, Clone)]
4166pub struct Allocator {
4167 pub malloc: unsafe extern "C" fn(size: usize) -> *mut c_void,
4168 pub calloc: unsafe extern "C" fn(nmemb: usize, size: usize) -> *mut c_void,
4169 pub realloc: unsafe extern "C" fn(ptr: *mut c_void, size: usize) -> *mut c_void,
4170 pub free: unsafe extern "C" fn(ptr: *mut c_void),
4171}
4172
4173#[doc(alias = "ts_set_allocator")]
4192pub unsafe fn set_allocator(allocator: Option<Allocator>) {
4193 let (m, c, r, f) = match allocator {
4194 Some(a) => (
4195 Some(a.malloc),
4196 Some(a.calloc),
4197 Some(a.realloc),
4198 Some(a.free),
4199 ),
4200 None => (None, None, None, None),
4201 };
4202 unsafe { ffi::ts_set_allocator(m, c, r, f) };
4203}
4204
4205#[cfg(feature = "std")]
4206#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
4207impl error::Error for IncludedRangesError {}
4208#[cfg(feature = "std")]
4209#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
4210impl error::Error for LanguageError {}
4211#[cfg(feature = "std")]
4212#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
4213impl error::Error for QueryError {}
4214
4215#[cfg(not(target_family = "wasm"))]
4216unsafe impl Send for Language {}
4217#[cfg(not(target_family = "wasm"))]
4218unsafe impl Sync for Language {}
4219
4220unsafe impl Send for Node<'_> {}
4221unsafe impl Sync for Node<'_> {}
4222
4223#[cfg(not(target_family = "wasm"))]
4224unsafe impl Send for LookaheadIterator {}
4225#[cfg(not(target_family = "wasm"))]
4226unsafe impl Sync for LookaheadIterator {}
4227
4228#[cfg(not(target_family = "wasm"))]
4229unsafe impl Send for LookaheadNamesIterator<'_> {}
4230#[cfg(not(target_family = "wasm"))]
4231unsafe impl Sync for LookaheadNamesIterator<'_> {}
4232
4233#[cfg(not(target_family = "wasm"))]
4234unsafe impl Send for Parser {}
4235#[cfg(not(target_family = "wasm"))]
4236unsafe impl Sync for Parser {}
4237
4238unsafe impl Send for Query {}
4239unsafe impl Sync for Query {}
4240
4241unsafe impl Send for QueryCursor {}
4242unsafe impl Sync for QueryCursor {}
4243
4244unsafe impl Send for Tree {}
4245unsafe impl Sync for Tree {}
4246
4247unsafe impl Send for TreeCursor<'_> {}
4248unsafe impl Sync for TreeCursor<'_> {}