1#![doc = include_str!("./README.md")]
2#![cfg_attr(not(feature = "std"), no_std)]
3#![cfg_attr(docsrs, feature(doc_cfg))]
4#![allow(clippy::all)]
6#![allow(mismatched_lifetime_syntaxes)]
7#![allow(rustdoc::broken_intra_doc_links)]
8#![allow(rustdoc::private_intra_doc_links)]
9
10pub mod ffi;
11mod util;
12
13#[cfg(not(feature = "std"))]
14extern crate alloc;
15#[cfg(not(feature = "std"))]
16use alloc::{boxed::Box, format, string::String, string::ToString, vec::Vec};
17use core::{
18 ffi::{c_char, c_void, CStr},
19 fmt::{self, Write},
20 hash, iter,
21 marker::PhantomData,
22 mem::MaybeUninit,
23 num::NonZeroU16,
24 ops::{self, Deref},
25 ptr::{self, NonNull},
26 slice, str,
27 sync::atomic::AtomicUsize,
28};
29#[cfg(feature = "std")]
30use std::error;
31#[cfg(all(unix, feature = "std"))]
32use std::os::fd::AsRawFd;
33#[cfg(all(windows, feature = "std"))]
34use std::os::windows::io::AsRawHandle;
35
36pub use streaming_iterator::{StreamingIterator, StreamingIteratorMut};
37use tree_sitter_language::LanguageFn;
38
39#[doc(alias = "TREE_SITTER_LANGUAGE_VERSION")]
47pub const LANGUAGE_VERSION: usize = ffi::TREE_SITTER_LANGUAGE_VERSION as usize;
48
49#[doc(alias = "TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION")]
52pub const MIN_COMPATIBLE_LANGUAGE_VERSION: usize =
53 ffi::TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION as usize;
54
55pub const PARSER_HEADER: &str = include_str!("../src/parser.h");
56
57#[doc(alias = "TSLanguage")]
60#[derive(Debug, PartialEq, Eq, Hash)]
61#[repr(transparent)]
62pub struct Language(*const ffi::TSLanguage);
63
64pub struct LanguageRef<'a>(*const ffi::TSLanguage, PhantomData<&'a ()>);
65
66#[doc(alias = "TSLanguageMetadata")]
73pub struct LanguageMetadata {
74 pub major_version: u8,
75 pub minor_version: u8,
76 pub patch_version: u8,
77}
78
79impl From<ffi::TSLanguageMetadata> for LanguageMetadata {
80 fn from(val: ffi::TSLanguageMetadata) -> Self {
81 Self {
82 major_version: val.major_version,
83 minor_version: val.minor_version,
84 patch_version: val.patch_version,
85 }
86 }
87}
88
89#[doc(alias = "TSTree")]
91pub struct Tree(NonNull<ffi::TSTree>);
92
93#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord)]
97pub struct Point {
98 pub row: usize,
99 pub column: usize,
100}
101
102#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
105pub struct Range {
106 pub start_byte: usize,
107 pub end_byte: usize,
108 pub start_point: Point,
109 pub end_point: Point,
110}
111
112#[derive(Clone, Copy, Debug, PartialEq, Eq)]
114pub struct InputEdit {
115 pub start_byte: usize,
116 pub old_end_byte: usize,
117 pub new_end_byte: usize,
118 pub start_position: Point,
119 pub old_end_position: Point,
120 pub new_end_position: Point,
121}
122
123#[doc(alias = "TSNode")]
125#[derive(Clone, Copy)]
126#[repr(transparent)]
127pub struct Node<'tree>(ffi::TSNode, PhantomData<&'tree ()>);
128
129#[doc(alias = "TSParser")]
132pub struct Parser(NonNull<ffi::TSParser>);
133
134#[doc(alias = "TSLookaheadIterator")]
137pub struct LookaheadIterator(NonNull<ffi::TSLookaheadIterator>);
138struct LookaheadNamesIterator<'a>(&'a mut LookaheadIterator);
139
140pub struct ParseState(NonNull<ffi::TSParseState>);
143
144impl ParseState {
145 #[must_use]
146 pub const fn current_byte_offset(&self) -> usize {
147 unsafe { self.0.as_ref() }.current_byte_offset as usize
148 }
149
150 #[must_use]
151 pub const fn has_error(&self) -> bool {
152 unsafe { self.0.as_ref() }.has_error
153 }
154}
155
156pub struct QueryCursorState(NonNull<ffi::TSQueryCursorState>);
159
160impl QueryCursorState {
161 #[must_use]
162 pub const fn current_byte_offset(&self) -> usize {
163 unsafe { self.0.as_ref() }.current_byte_offset as usize
164 }
165}
166
167#[derive(Default)]
168pub struct ParseOptions<'a> {
169 pub progress_callback: Option<ParseProgressCallback<'a>>,
170}
171
172impl<'a> ParseOptions<'a> {
173 #[must_use]
174 pub fn new() -> Self {
175 Self::default()
176 }
177
178 #[must_use]
179 pub fn progress_callback<F: FnMut(&ParseState) -> bool>(mut self, callback: &'a mut F) -> Self {
180 self.progress_callback = Some(callback);
181 self
182 }
183}
184
185#[derive(Default)]
186pub struct QueryCursorOptions<'a> {
187 pub progress_callback: Option<QueryProgressCallback<'a>>,
188}
189
190impl<'a> QueryCursorOptions<'a> {
191 #[must_use]
192 pub fn new() -> Self {
193 Self::default()
194 }
195
196 #[must_use]
197 pub fn progress_callback<F: FnMut(&QueryCursorState) -> bool>(
198 mut self,
199 callback: &'a mut F,
200 ) -> Self {
201 self.progress_callback = Some(callback);
202 self
203 }
204}
205
206struct QueryCursorOptionsDrop(*mut ffi::TSQueryCursorOptions);
207
208impl Drop for QueryCursorOptionsDrop {
209 fn drop(&mut self) {
210 unsafe {
211 if !(*self.0).payload.is_null() {
212 drop(Box::from_raw(
213 (*self.0).payload.cast::<QueryProgressCallback>(),
214 ));
215 }
216 drop(Box::from_raw(self.0));
217 }
218 }
219}
220
221#[derive(Debug, PartialEq, Eq)]
223pub enum LogType {
224 Parse,
225 Lex,
226}
227
228type FieldId = NonZeroU16;
229
230type Logger<'a> = Box<dyn FnMut(LogType, &str) + 'a>;
232
233type ParseProgressCallback<'a> = &'a mut dyn FnMut(&ParseState) -> bool;
235
236type QueryProgressCallback<'a> = &'a mut dyn FnMut(&QueryCursorState) -> bool;
238
239pub trait Decode {
240 fn decode(bytes: &[u8]) -> (i32, u32);
243}
244
245#[doc(alias = "TSTreeCursor")]
247pub struct TreeCursor<'cursor>(ffi::TSTreeCursor, PhantomData<&'cursor ()>);
248
249#[doc(alias = "TSQuery")]
251#[derive(Debug)]
252#[allow(clippy::type_complexity)]
253pub struct Query {
254 ptr: NonNull<ffi::TSQuery>,
255 capture_names: Box<[&'static str]>,
256 capture_quantifiers: Box<[Box<[CaptureQuantifier]>]>,
257 text_predicates: Box<[Box<[TextPredicateCapture]>]>,
258 property_settings: Box<[Box<[QueryProperty]>]>,
259 property_predicates: Box<[Box<[(QueryProperty, bool)]>]>,
260 general_predicates: Box<[Box<[QueryPredicate]>]>,
261}
262
263#[derive(Debug, PartialEq, Eq, Clone, Copy)]
265pub enum CaptureQuantifier {
266 Zero,
267 ZeroOrOne,
268 ZeroOrMore,
269 One,
270 OneOrMore,
271}
272
273impl From<ffi::TSQuantifier> for CaptureQuantifier {
274 fn from(value: ffi::TSQuantifier) -> Self {
275 match value {
276 ffi::TSQuantifierZero => Self::Zero,
277 ffi::TSQuantifierZeroOrOne => Self::ZeroOrOne,
278 ffi::TSQuantifierZeroOrMore => Self::ZeroOrMore,
279 ffi::TSQuantifierOne => Self::One,
280 ffi::TSQuantifierOneOrMore => Self::OneOrMore,
281 _ => panic!("Unrecognized quantifier: {value}"),
282 }
283 }
284}
285
286#[doc(alias = "TSQueryCursor")]
288pub struct QueryCursor {
289 ptr: NonNull<ffi::TSQueryCursor>,
290}
291
292#[derive(Debug, PartialEq, Eq)]
294pub struct QueryProperty {
295 pub key: Box<str>,
296 pub value: Option<Box<str>>,
297 pub capture_id: Option<usize>,
298}
299
300#[derive(Debug, PartialEq, Eq)]
301pub enum QueryPredicateArg {
302 Capture(u32),
303 String(Box<str>),
304}
305
306#[derive(Debug, PartialEq, Eq)]
308pub struct QueryPredicate {
309 pub operator: Box<str>,
310 pub args: Box<[QueryPredicateArg]>,
311}
312
313pub struct QueryMatch<'cursor, 'tree> {
315 pub pattern_index: usize,
316 pub captures: &'cursor [QueryCapture<'tree>],
317 id: u32,
318 cursor: *mut ffi::TSQueryCursor,
319}
320
321pub struct QueryMatches<'query, 'tree: 'query, T: TextProvider<I>, I: AsRef<[u8]>> {
323 ptr: *mut ffi::TSQueryCursor,
324 query: &'query Query,
325 text_provider: T,
326 buffer1: Vec<u8>,
327 buffer2: Vec<u8>,
328 current_match: Option<QueryMatch<'query, 'tree>>,
329 _options: Option<QueryCursorOptionsDrop>,
330 _phantom: PhantomData<(&'tree (), I)>,
331}
332
333pub struct QueryCaptures<'query, 'tree: 'query, T: TextProvider<I>, I: AsRef<[u8]>> {
338 ptr: *mut ffi::TSQueryCursor,
339 query: &'query Query,
340 text_provider: T,
341 buffer1: Vec<u8>,
342 buffer2: Vec<u8>,
343 current_match: Option<(QueryMatch<'query, 'tree>, usize)>,
344 _options: Option<QueryCursorOptionsDrop>,
345 _phantom: PhantomData<(&'tree (), I)>,
346}
347
348pub trait TextProvider<I>
349where
350 I: AsRef<[u8]>,
351{
352 type I: Iterator<Item = I>;
353 fn text(&mut self, node: Node) -> Self::I;
354}
355
356#[derive(Clone, Copy, Debug)]
359#[repr(C)]
360pub struct QueryCapture<'tree> {
361 pub node: Node<'tree>,
362 pub index: u32,
363}
364
365#[derive(Debug, PartialEq, Eq)]
368pub struct LanguageError {
369 version: usize,
370}
371
372#[derive(Debug, PartialEq, Eq)]
374pub struct IncludedRangesError(pub usize);
375
376#[derive(Debug, PartialEq, Eq)]
378pub struct QueryError {
379 pub row: usize,
380 pub column: usize,
381 pub offset: usize,
382 pub message: String,
383 pub kind: QueryErrorKind,
384}
385
386#[derive(Debug, PartialEq, Eq)]
387pub enum QueryErrorKind {
388 Syntax,
389 NodeType,
390 Field,
391 Capture,
392 Predicate,
393 Structure,
394 Language,
395}
396
397#[derive(Debug)]
398enum TextPredicateCapture {
404 EqString(u32, Box<str>, bool, bool),
405 EqCapture(u32, u32, bool, bool),
406 MatchString(u32, regex::bytes::Regex, bool, bool),
407 AnyString(u32, Box<[Box<str>]>, bool),
408}
409
410pub struct LossyUtf8<'a> {
413 bytes: &'a [u8],
414 in_replacement: bool,
415}
416
417impl Language {
418 #[must_use]
419 pub fn new(builder: LanguageFn) -> Self {
420 Self(unsafe { builder.into_raw()().cast() })
421 }
422
423 #[doc(alias = "ts_language_name")]
425 #[must_use]
426 pub fn name(&self) -> Option<&'static str> {
427 let ptr = unsafe { ffi::ts_language_name(self.0) };
428 (!ptr.is_null()).then(|| unsafe { CStr::from_ptr(ptr) }.to_str().unwrap())
429 }
430
431 #[doc(alias = "ts_language_version")]
434 #[deprecated(since = "0.25.0", note = "Use abi_version instead")]
435 #[must_use]
436 pub fn version(&self) -> usize {
437 unsafe { ffi::ts_language_version(self.0) as usize }
438 }
439
440 #[doc(alias = "ts_language_abi_version")]
443 #[must_use]
444 pub fn abi_version(&self) -> usize {
445 unsafe { ffi::ts_language_abi_version(self.0) as usize }
446 }
447
448 #[doc(alias = "ts_language_metadata")]
454 #[must_use]
455 pub fn metadata(&self) -> Option<LanguageMetadata> {
456 unsafe {
457 let ptr = ffi::ts_language_metadata(self.0);
458 (!ptr.is_null()).then(|| (*ptr).into())
459 }
460 }
461
462 #[doc(alias = "ts_language_symbol_count")]
464 #[must_use]
465 pub fn node_kind_count(&self) -> usize {
466 unsafe { ffi::ts_language_symbol_count(self.0) as usize }
467 }
468
469 #[doc(alias = "ts_language_state_count")]
471 #[must_use]
472 pub fn parse_state_count(&self) -> usize {
473 unsafe { ffi::ts_language_state_count(self.0) as usize }
474 }
475
476 #[doc(alias = "ts_language_supertypes")]
478 #[must_use]
479 pub fn supertypes(&self) -> &[u16] {
480 let mut length = 0u32;
481 unsafe {
482 let ptr = ffi::ts_language_supertypes(self.0, core::ptr::addr_of_mut!(length));
483 if length == 0 {
484 &[]
485 } else {
486 slice::from_raw_parts(ptr.cast_mut(), length as usize)
487 }
488 }
489 }
490
491 #[doc(alias = "ts_language_supertype_map")]
493 #[must_use]
494 pub fn subtypes_for_supertype(&self, supertype: u16) -> &[u16] {
495 unsafe {
496 let mut length = 0u32;
497 let ptr = ffi::ts_language_subtypes(self.0, supertype, core::ptr::addr_of_mut!(length));
498 if length == 0 {
499 &[]
500 } else {
501 slice::from_raw_parts(ptr.cast_mut(), length as usize)
502 }
503 }
504 }
505
506 #[doc(alias = "ts_language_symbol_name")]
508 #[must_use]
509 pub fn node_kind_for_id(&self, id: u16) -> Option<&'static str> {
510 let ptr = unsafe { ffi::ts_language_symbol_name(self.0, id) };
511 (!ptr.is_null()).then(|| unsafe { CStr::from_ptr(ptr) }.to_str().unwrap())
512 }
513
514 #[doc(alias = "ts_language_symbol_for_name")]
516 #[must_use]
517 pub fn id_for_node_kind(&self, kind: &str, named: bool) -> u16 {
518 unsafe {
519 ffi::ts_language_symbol_for_name(
520 self.0,
521 kind.as_bytes().as_ptr().cast::<c_char>(),
522 kind.len() as u32,
523 named,
524 )
525 }
526 }
527
528 #[must_use]
531 pub fn node_kind_is_named(&self, id: u16) -> bool {
532 unsafe { ffi::ts_language_symbol_type(self.0, id) == ffi::TSSymbolTypeRegular }
533 }
534
535 #[must_use]
538 pub fn node_kind_is_visible(&self, id: u16) -> bool {
539 unsafe { ffi::ts_language_symbol_type(self.0, id) <= ffi::TSSymbolTypeAnonymous }
540 }
541
542 #[must_use]
544 pub fn node_kind_is_supertype(&self, id: u16) -> bool {
545 unsafe { ffi::ts_language_symbol_type(self.0, id) == ffi::TSSymbolTypeSupertype }
546 }
547
548 #[doc(alias = "ts_language_field_count")]
550 #[must_use]
551 pub fn field_count(&self) -> usize {
552 unsafe { ffi::ts_language_field_count(self.0) as usize }
553 }
554
555 #[doc(alias = "ts_language_field_name_for_id")]
557 #[must_use]
558 pub fn field_name_for_id(&self, field_id: u16) -> Option<&'static str> {
559 let ptr = unsafe { ffi::ts_language_field_name_for_id(self.0, field_id) };
560 (!ptr.is_null()).then(|| unsafe { CStr::from_ptr(ptr) }.to_str().unwrap())
561 }
562
563 #[doc(alias = "ts_language_field_id_for_name")]
565 #[must_use]
566 pub fn field_id_for_name(&self, field_name: impl AsRef<[u8]>) -> Option<FieldId> {
567 let field_name = field_name.as_ref();
568 let id = unsafe {
569 ffi::ts_language_field_id_for_name(
570 self.0,
571 field_name.as_ptr().cast::<c_char>(),
572 field_name.len() as u32,
573 )
574 };
575 FieldId::new(id)
576 }
577
578 #[doc(alias = "ts_language_next_state")]
587 #[must_use]
588 pub fn next_state(&self, state: u16, id: u16) -> u16 {
589 unsafe { ffi::ts_language_next_state(self.0, state, id) }
590 }
591
592 #[doc(alias = "ts_lookahead_iterator_new")]
606 #[must_use]
607 pub fn lookahead_iterator(&self, state: u16) -> Option<LookaheadIterator> {
608 let ptr = unsafe { ffi::ts_lookahead_iterator_new(self.0, state) };
609 (!ptr.is_null()).then(|| unsafe { LookaheadIterator::from_raw(ptr) })
610 }
611}
612
613impl From<LanguageFn> for Language {
614 fn from(value: LanguageFn) -> Self {
615 Self::new(value)
616 }
617}
618
619impl Clone for Language {
620 fn clone(&self) -> Self {
621 unsafe { Self(ffi::ts_language_copy(self.0)) }
622 }
623}
624
625impl Drop for Language {
626 fn drop(&mut self) {
627 unsafe { ffi::ts_language_delete(self.0) }
628 }
629}
630
631impl Deref for LanguageRef<'_> {
632 type Target = Language;
633
634 fn deref(&self) -> &Self::Target {
635 unsafe { &*(core::ptr::addr_of!(self.0).cast::<Language>()) }
636 }
637}
638
639impl Default for Parser {
640 fn default() -> Self {
641 Self::new()
642 }
643}
644
645impl Parser {
646 #[doc(alias = "ts_parser_new")]
648 #[must_use]
649 pub fn new() -> Self {
650 unsafe {
651 let parser = ffi::ts_parser_new();
652 Self(NonNull::new_unchecked(parser))
653 }
654 }
655
656 #[doc(alias = "ts_parser_set_language")]
665 pub fn set_language(&mut self, language: &Language) -> Result<(), LanguageError> {
666 let version = language.abi_version();
667 if (MIN_COMPATIBLE_LANGUAGE_VERSION..=LANGUAGE_VERSION).contains(&version) {
668 unsafe {
669 ffi::ts_parser_set_language(self.0.as_ptr(), language.0);
670 }
671 Ok(())
672 } else {
673 Err(LanguageError { version })
674 }
675 }
676
677 #[doc(alias = "ts_parser_language")]
679 #[must_use]
680 pub fn language(&self) -> Option<LanguageRef<'_>> {
681 let ptr = unsafe { ffi::ts_parser_language(self.0.as_ptr()) };
682 (!ptr.is_null()).then_some(LanguageRef(ptr, PhantomData))
683 }
684
685 #[doc(alias = "ts_parser_logger")]
687 #[must_use]
688 pub fn logger(&self) -> Option<&Logger> {
689 let logger = unsafe { ffi::ts_parser_logger(self.0.as_ptr()) };
690 unsafe { logger.payload.cast::<Logger>().as_ref() }
691 }
692
693 #[doc(alias = "ts_parser_set_logger")]
695 pub fn set_logger(&mut self, logger: Option<Logger>) {
696 let prev_logger = unsafe { ffi::ts_parser_logger(self.0.as_ptr()) };
697 if !prev_logger.payload.is_null() {
698 drop(unsafe { Box::from_raw(prev_logger.payload.cast::<Logger>()) });
699 }
700
701 let c_logger = if let Some(logger) = logger {
702 let container = Box::new(logger);
703
704 unsafe extern "C" fn log(
705 payload: *mut c_void,
706 c_log_type: ffi::TSLogType,
707 c_message: *const c_char,
708 ) {
709 let callback = payload.cast::<Logger>().as_mut().unwrap();
710 if let Ok(message) = CStr::from_ptr(c_message).to_str() {
711 let log_type = if c_log_type == ffi::TSLogTypeParse {
712 LogType::Parse
713 } else {
714 LogType::Lex
715 };
716 callback(log_type, message);
717 }
718 }
719
720 let raw_container = Box::into_raw(container);
721
722 ffi::TSLogger {
723 payload: raw_container.cast::<c_void>(),
724 log: Some(log),
725 }
726 } else {
727 ffi::TSLogger {
728 payload: ptr::null_mut(),
729 log: None,
730 }
731 };
732
733 unsafe { ffi::ts_parser_set_logger(self.0.as_ptr(), c_logger) };
734 }
735
736 #[doc(alias = "ts_parser_print_dot_graphs")]
741 #[cfg(not(target_os = "wasi"))]
742 #[cfg(feature = "std")]
743 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
744 pub fn print_dot_graphs(
745 &mut self,
746 #[cfg(unix)] file: &impl AsRawFd,
747 #[cfg(windows)] file: &impl AsRawHandle,
748 ) {
749 #[cfg(unix)]
750 {
751 let fd = file.as_raw_fd();
752 unsafe {
753 ffi::ts_parser_print_dot_graphs(self.0.as_ptr(), ffi::_ts_dup(fd));
754 }
755 }
756
757 #[cfg(windows)]
758 {
759 let handle = file.as_raw_handle();
760 unsafe {
761 ffi::ts_parser_print_dot_graphs(self.0.as_ptr(), ffi::_ts_dup(handle));
762 }
763 }
764 }
765
766 #[doc(alias = "ts_parser_print_dot_graphs")]
768 #[cfg(not(target_os = "wasi"))]
769 #[cfg(feature = "std")]
770 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
771 pub fn stop_printing_dot_graphs(&mut self) {
772 unsafe { ffi::ts_parser_print_dot_graphs(self.0.as_ptr(), -1) }
773 }
774
775 #[doc(alias = "ts_parser_parse")]
788 pub fn parse(&mut self, text: impl AsRef<[u8]>, old_tree: Option<&Tree>) -> Option<Tree> {
789 let bytes = text.as_ref();
790 let len = bytes.len();
791 self.parse_with_options(
792 &mut |i, _| (i < len).then(|| &bytes[i..]).unwrap_or_default(),
793 old_tree,
794 None,
795 )
796 }
797
798 #[deprecated(since = "0.25.0", note = "Prefer parse_utf16_le instead")]
806 pub fn parse_utf16(
807 &mut self,
808 input: impl AsRef<[u16]>,
809 old_tree: Option<&Tree>,
810 ) -> Option<Tree> {
811 let code_points = input.as_ref();
812 let len = code_points.len();
813 self.parse_utf16_le_with_options(
814 &mut |i, _| (i < len).then(|| &code_points[i..]).unwrap_or_default(),
815 old_tree,
816 None,
817 )
818 }
819
820 #[deprecated(since = "0.25.0", note = "Prefer `parse_with_options` instead")]
831 pub fn parse_with<T: AsRef<[u8]>, F: FnMut(usize, Point) -> T>(
832 &mut self,
833 callback: &mut F,
834 old_tree: Option<&Tree>,
835 ) -> Option<Tree> {
836 self.parse_with_options(callback, old_tree, None)
837 }
838
839 pub fn parse_with_options<T: AsRef<[u8]>, F: FnMut(usize, Point) -> T>(
851 &mut self,
852 callback: &mut F,
853 old_tree: Option<&Tree>,
854 options: Option<ParseOptions>,
855 ) -> Option<Tree> {
856 type Payload<'a, F, T> = (&'a mut F, Option<T>);
857
858 unsafe extern "C" fn progress(state: *mut ffi::TSParseState) -> bool {
860 let callback = (*state)
861 .payload
862 .cast::<ParseProgressCallback>()
863 .as_mut()
864 .unwrap();
865 callback(&ParseState::from_raw(state))
866 }
867
868 unsafe extern "C" fn read<T: AsRef<[u8]>, F: FnMut(usize, Point) -> T>(
870 payload: *mut c_void,
871 byte_offset: u32,
872 position: ffi::TSPoint,
873 bytes_read: *mut u32,
874 ) -> *const c_char {
875 let (callback, text) = payload.cast::<Payload<F, T>>().as_mut().unwrap();
876 *text = Some(callback(byte_offset as usize, position.into()));
877 let slice = text.as_ref().unwrap().as_ref();
878 *bytes_read = slice.len() as u32;
879 slice.as_ptr().cast::<c_char>()
880 }
881
882 let empty_options = ffi::TSParseOptions {
883 payload: ptr::null_mut(),
884 progress_callback: None,
885 };
886
887 let mut callback_ptr;
888 let parse_options = if let Some(options) = options {
889 if let Some(cb) = options.progress_callback {
890 callback_ptr = cb;
891 ffi::TSParseOptions {
892 payload: core::ptr::addr_of_mut!(callback_ptr).cast::<c_void>(),
893 progress_callback: Some(progress),
894 }
895 } else {
896 empty_options
897 }
898 } else {
899 empty_options
900 };
901
902 let mut payload: Payload<F, T> = (callback, None);
908
909 let c_input = ffi::TSInput {
910 payload: ptr::addr_of_mut!(payload).cast::<c_void>(),
911 read: Some(read::<T, F>),
912 encoding: ffi::TSInputEncodingUTF8,
913 decode: None,
914 };
915
916 let c_old_tree = old_tree.map_or(ptr::null_mut(), |t| t.0.as_ptr());
917 unsafe {
918 let c_new_tree = ffi::ts_parser_parse_with_options(
919 self.0.as_ptr(),
920 c_old_tree,
921 c_input,
922 parse_options,
923 );
924
925 NonNull::new(c_new_tree).map(Tree)
926 }
927 }
928
929 #[deprecated(
940 since = "0.25.0",
941 note = "Prefer `parse_utf16_le_with_options` instead"
942 )]
943 pub fn parse_utf16_with<T: AsRef<[u16]>, F: FnMut(usize, Point) -> T>(
944 &mut self,
945 callback: &mut F,
946 old_tree: Option<&Tree>,
947 ) -> Option<Tree> {
948 self.parse_utf16_le_with_options(callback, old_tree, None)
949 }
950
951 pub fn parse_utf16_le(
959 &mut self,
960 input: impl AsRef<[u16]>,
961 old_tree: Option<&Tree>,
962 ) -> Option<Tree> {
963 let code_points = input.as_ref();
964 let len = code_points.len();
965 self.parse_utf16_le_with_options(
966 &mut |i, _| (i < len).then(|| &code_points[i..]).unwrap_or_default(),
967 old_tree,
968 None,
969 )
970 }
971
972 pub fn parse_utf16_le_with_options<T: AsRef<[u16]>, F: FnMut(usize, Point) -> T>(
984 &mut self,
985 callback: &mut F,
986 old_tree: Option<&Tree>,
987 options: Option<ParseOptions>,
988 ) -> Option<Tree> {
989 type Payload<'a, F, T> = (&'a mut F, Option<T>);
990
991 unsafe extern "C" fn progress(state: *mut ffi::TSParseState) -> bool {
992 let callback = (*state)
993 .payload
994 .cast::<ParseProgressCallback>()
995 .as_mut()
996 .unwrap();
997 callback(&ParseState::from_raw(state))
998 }
999
1000 unsafe extern "C" fn read<T: AsRef<[u16]>, F: FnMut(usize, Point) -> T>(
1002 payload: *mut c_void,
1003 byte_offset: u32,
1004 position: ffi::TSPoint,
1005 bytes_read: *mut u32,
1006 ) -> *const c_char {
1007 let (callback, text) = payload.cast::<Payload<F, T>>().as_mut().unwrap();
1008 *text = Some(callback(
1009 (byte_offset / 2) as usize,
1010 Point {
1011 row: position.row as usize,
1012 column: position.column as usize / 2,
1013 },
1014 ));
1015 let slice = text.as_ref().unwrap().as_ref();
1016 *bytes_read = slice.len() as u32 * 2;
1017 slice.as_ptr().cast::<c_char>()
1018 }
1019
1020 let empty_options = ffi::TSParseOptions {
1021 payload: ptr::null_mut(),
1022 progress_callback: None,
1023 };
1024
1025 let mut callback_ptr;
1026 let parse_options = if let Some(options) = options {
1027 if let Some(cb) = options.progress_callback {
1028 callback_ptr = cb;
1029 ffi::TSParseOptions {
1030 payload: core::ptr::addr_of_mut!(callback_ptr).cast::<c_void>(),
1031 progress_callback: Some(progress),
1032 }
1033 } else {
1034 empty_options
1035 }
1036 } else {
1037 empty_options
1038 };
1039
1040 let mut payload: Payload<F, T> = (callback, None);
1046
1047 let c_input = ffi::TSInput {
1048 payload: core::ptr::addr_of_mut!(payload).cast::<c_void>(),
1049 read: Some(read::<T, F>),
1050 encoding: ffi::TSInputEncodingUTF16LE,
1051 decode: None,
1052 };
1053
1054 let c_old_tree = old_tree.map_or(ptr::null_mut(), |t| t.0.as_ptr());
1055 unsafe {
1056 let c_new_tree = ffi::ts_parser_parse_with_options(
1057 self.0.as_ptr(),
1058 c_old_tree,
1059 c_input,
1060 parse_options,
1061 );
1062
1063 NonNull::new(c_new_tree).map(Tree)
1064 }
1065 }
1066
1067 pub fn parse_utf16_be(
1075 &mut self,
1076 input: impl AsRef<[u16]>,
1077 old_tree: Option<&Tree>,
1078 ) -> Option<Tree> {
1079 let code_points = input.as_ref();
1080 let len = code_points.len();
1081 self.parse_utf16_be_with_options(
1082 &mut |i, _| if i < len { &code_points[i..] } else { &[] },
1083 old_tree,
1084 None,
1085 )
1086 }
1087
1088 pub fn parse_utf16_be_with_options<T: AsRef<[u16]>, F: FnMut(usize, Point) -> T>(
1100 &mut self,
1101 callback: &mut F,
1102 old_tree: Option<&Tree>,
1103 options: Option<ParseOptions>,
1104 ) -> Option<Tree> {
1105 type Payload<'a, F, T> = (&'a mut F, Option<T>);
1106
1107 unsafe extern "C" fn progress(state: *mut ffi::TSParseState) -> bool {
1109 let callback = (*state)
1110 .payload
1111 .cast::<ParseProgressCallback>()
1112 .as_mut()
1113 .unwrap();
1114 callback(&ParseState::from_raw(state))
1115 }
1116
1117 unsafe extern "C" fn read<T: AsRef<[u16]>, F: FnMut(usize, Point) -> T>(
1119 payload: *mut c_void,
1120 byte_offset: u32,
1121 position: ffi::TSPoint,
1122 bytes_read: *mut u32,
1123 ) -> *const c_char {
1124 let (callback, text) = payload.cast::<Payload<F, T>>().as_mut().unwrap();
1125 *text = Some(callback(
1126 (byte_offset / 2) as usize,
1127 Point {
1128 row: position.row as usize,
1129 column: position.column as usize / 2,
1130 },
1131 ));
1132 let slice = text.as_ref().unwrap().as_ref();
1133 *bytes_read = slice.len() as u32 * 2;
1134 slice.as_ptr().cast::<c_char>()
1135 }
1136
1137 let empty_options = ffi::TSParseOptions {
1138 payload: ptr::null_mut(),
1139 progress_callback: None,
1140 };
1141
1142 let mut callback_ptr;
1143 let parse_options = if let Some(options) = options {
1144 if let Some(cb) = options.progress_callback {
1145 callback_ptr = cb;
1146 ffi::TSParseOptions {
1147 payload: core::ptr::addr_of_mut!(callback_ptr).cast::<c_void>(),
1148 progress_callback: Some(progress),
1149 }
1150 } else {
1151 empty_options
1152 }
1153 } else {
1154 empty_options
1155 };
1156
1157 let mut payload: Payload<F, T> = (callback, None);
1163
1164 let c_input = ffi::TSInput {
1165 payload: core::ptr::addr_of_mut!(payload).cast::<c_void>(),
1166 read: Some(read::<T, F>),
1167 encoding: ffi::TSInputEncodingUTF16BE,
1168 decode: None,
1169 };
1170
1171 let c_old_tree = old_tree.map_or(ptr::null_mut(), |t| t.0.as_ptr());
1172 unsafe {
1173 let c_new_tree = ffi::ts_parser_parse_with_options(
1174 self.0.as_ptr(),
1175 c_old_tree,
1176 c_input,
1177 parse_options,
1178 );
1179
1180 NonNull::new(c_new_tree).map(Tree)
1181 }
1182 }
1183
1184 pub fn parse_custom_encoding<D: Decode, T: AsRef<[u8]>, F: FnMut(usize, Point) -> T>(
1201 &mut self,
1202 callback: &mut F,
1203 old_tree: Option<&Tree>,
1204 options: Option<ParseOptions>,
1205 ) -> Option<Tree> {
1206 type Payload<'a, F, T> = (&'a mut F, Option<T>);
1207
1208 unsafe extern "C" fn progress(state: *mut ffi::TSParseState) -> bool {
1209 let callback = (*state)
1210 .payload
1211 .cast::<ParseProgressCallback>()
1212 .as_mut()
1213 .unwrap();
1214 callback(&ParseState::from_raw(state))
1215 }
1216
1217 unsafe extern "C" fn decode_fn<D: Decode>(
1219 data: *const u8,
1220 len: u32,
1221 code_point: *mut i32,
1222 ) -> u32 {
1223 let (c, len) = D::decode(core::slice::from_raw_parts(data, len as usize));
1224 if let Some(code_point) = code_point.as_mut() {
1225 *code_point = c;
1226 }
1227 len
1228 }
1229
1230 unsafe extern "C" fn read<T: AsRef<[u8]>, 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 let (callback, text) = payload.cast::<Payload<F, T>>().as_mut().unwrap();
1238 *text = Some(callback(byte_offset as usize, position.into()));
1239 let slice = text.as_ref().unwrap().as_ref();
1240 *bytes_read = slice.len() as u32;
1241 slice.as_ptr().cast::<c_char>()
1242 }
1243
1244 let empty_options = ffi::TSParseOptions {
1245 payload: ptr::null_mut(),
1246 progress_callback: None,
1247 };
1248
1249 let mut callback_ptr;
1250 let parse_options = if let Some(options) = options {
1251 if let Some(cb) = options.progress_callback {
1252 callback_ptr = cb;
1253 ffi::TSParseOptions {
1254 payload: core::ptr::addr_of_mut!(callback_ptr).cast::<c_void>(),
1255 progress_callback: Some(progress),
1256 }
1257 } else {
1258 empty_options
1259 }
1260 } else {
1261 empty_options
1262 };
1263
1264 let mut payload: Payload<F, T> = (callback, None);
1270
1271 let c_input = ffi::TSInput {
1272 payload: core::ptr::addr_of_mut!(payload).cast::<c_void>(),
1273 read: Some(read::<T, F>),
1274 encoding: ffi::TSInputEncodingCustom,
1275 decode: Some(decode_fn::<D>),
1277 };
1278
1279 let c_old_tree = old_tree.map_or(ptr::null_mut(), |t| t.0.as_ptr());
1280 unsafe {
1281 let c_new_tree = ffi::ts_parser_parse_with_options(
1282 self.0.as_ptr(),
1283 c_old_tree,
1284 c_input,
1285 parse_options,
1286 );
1287
1288 NonNull::new(c_new_tree).map(Tree)
1289 }
1290 }
1291
1292 #[doc(alias = "ts_parser_reset")]
1300 pub fn reset(&mut self) {
1301 unsafe { ffi::ts_parser_reset(self.0.as_ptr()) }
1302 }
1303
1304 #[doc(alias = "ts_parser_timeout_micros")]
1308 #[deprecated(
1309 since = "0.25.0",
1310 note = "Prefer using `parse_with_options` and using a callback"
1311 )]
1312 #[must_use]
1313 pub fn timeout_micros(&self) -> u64 {
1314 unsafe { ffi::ts_parser_timeout_micros(self.0.as_ptr()) }
1315 }
1316
1317 #[doc(alias = "ts_parser_set_timeout_micros")]
1323 #[deprecated(
1324 since = "0.25.0",
1325 note = "Prefer using `parse_with_options` and using a callback"
1326 )]
1327 pub fn set_timeout_micros(&mut self, timeout_micros: u64) {
1328 unsafe { ffi::ts_parser_set_timeout_micros(self.0.as_ptr(), timeout_micros) }
1329 }
1330
1331 #[doc(alias = "ts_parser_set_included_ranges")]
1349 pub fn set_included_ranges(&mut self, ranges: &[Range]) -> Result<(), IncludedRangesError> {
1350 let ts_ranges = ranges.iter().copied().map(Into::into).collect::<Vec<_>>();
1351 let result = unsafe {
1352 ffi::ts_parser_set_included_ranges(
1353 self.0.as_ptr(),
1354 ts_ranges.as_ptr(),
1355 ts_ranges.len() as u32,
1356 )
1357 };
1358
1359 if result {
1360 Ok(())
1361 } else {
1362 let mut prev_end_byte = 0;
1363 for (i, range) in ranges.iter().enumerate() {
1364 if range.start_byte < prev_end_byte || range.end_byte < range.start_byte {
1365 return Err(IncludedRangesError(i));
1366 }
1367 prev_end_byte = range.end_byte;
1368 }
1369 Err(IncludedRangesError(0))
1370 }
1371 }
1372
1373 #[doc(alias = "ts_parser_included_ranges")]
1375 #[must_use]
1376 pub fn included_ranges(&self) -> Vec<Range> {
1377 let mut count = 0u32;
1378 unsafe {
1379 let ptr =
1380 ffi::ts_parser_included_ranges(self.0.as_ptr(), core::ptr::addr_of_mut!(count));
1381 let ranges = slice::from_raw_parts(ptr, count as usize);
1382 let result = ranges.iter().copied().map(Into::into).collect();
1383 result
1384 }
1385 }
1386
1387 #[doc(alias = "ts_parser_cancellation_flag")]
1393 #[deprecated(
1394 since = "0.25.0",
1395 note = "Prefer using `parse_with_options` and using a callback"
1396 )]
1397 #[must_use]
1398 pub unsafe fn cancellation_flag(&self) -> Option<&AtomicUsize> {
1399 ffi::ts_parser_cancellation_flag(self.0.as_ptr())
1400 .cast::<AtomicUsize>()
1401 .as_ref()
1402 }
1403
1404 #[doc(alias = "ts_parser_set_cancellation_flag")]
1415 #[deprecated(
1416 since = "0.25.0",
1417 note = "Prefer using `parse_with_options` and using a callback"
1418 )]
1419 pub unsafe fn set_cancellation_flag(&mut self, flag: Option<&AtomicUsize>) {
1420 if let Some(flag) = flag {
1421 ffi::ts_parser_set_cancellation_flag(
1422 self.0.as_ptr(),
1423 core::ptr::from_ref::<AtomicUsize>(flag).cast::<usize>(),
1424 );
1425 } else {
1426 ffi::ts_parser_set_cancellation_flag(self.0.as_ptr(), ptr::null());
1427 }
1428 }
1429}
1430
1431impl Drop for Parser {
1432 fn drop(&mut self) {
1433 #[cfg(feature = "std")]
1434 #[cfg(not(target_os = "wasi"))]
1435 {
1436 self.stop_printing_dot_graphs();
1437 }
1438 self.set_logger(None);
1439 unsafe { ffi::ts_parser_delete(self.0.as_ptr()) }
1440 }
1441}
1442
1443#[cfg(windows)]
1444extern "C" {
1445 fn _open_osfhandle(osfhandle: isize, flags: core::ffi::c_int) -> core::ffi::c_int;
1446}
1447
1448impl Tree {
1449 #[doc(alias = "ts_tree_root_node")]
1451 #[must_use]
1452 pub fn root_node(&self) -> Node {
1453 Node::new(unsafe { ffi::ts_tree_root_node(self.0.as_ptr()) }).unwrap()
1454 }
1455
1456 #[doc(alias = "ts_tree_root_node_with_offset")]
1459 #[must_use]
1460 pub fn root_node_with_offset(&self, offset_bytes: usize, offset_extent: Point) -> Node {
1461 Node::new(unsafe {
1462 ffi::ts_tree_root_node_with_offset(
1463 self.0.as_ptr(),
1464 offset_bytes as u32,
1465 offset_extent.into(),
1466 )
1467 })
1468 .unwrap()
1469 }
1470
1471 #[doc(alias = "ts_tree_language")]
1473 #[must_use]
1474 pub fn language(&self) -> LanguageRef {
1475 LanguageRef(
1476 unsafe { ffi::ts_tree_language(self.0.as_ptr()) },
1477 PhantomData,
1478 )
1479 }
1480
1481 #[doc(alias = "ts_tree_edit")]
1487 pub fn edit(&mut self, edit: &InputEdit) {
1488 let edit = edit.into();
1489 unsafe { ffi::ts_tree_edit(self.0.as_ptr(), &edit) };
1490 }
1491
1492 #[must_use]
1494 pub fn walk(&self) -> TreeCursor {
1495 self.root_node().walk()
1496 }
1497
1498 #[doc(alias = "ts_tree_get_changed_ranges")]
1508 #[must_use]
1509 pub fn changed_ranges(&self, other: &Self) -> impl ExactSizeIterator<Item = Range> {
1510 let mut count = 0u32;
1511 unsafe {
1512 let ptr = ffi::ts_tree_get_changed_ranges(
1513 self.0.as_ptr(),
1514 other.0.as_ptr(),
1515 core::ptr::addr_of_mut!(count),
1516 );
1517 util::CBufferIter::new(ptr, count as usize).map(Into::into)
1518 }
1519 }
1520
1521 #[doc(alias = "ts_tree_included_ranges")]
1523 #[must_use]
1524 pub fn included_ranges(&self) -> Vec<Range> {
1525 let mut count = 0u32;
1526 unsafe {
1527 let ptr = ffi::ts_tree_included_ranges(self.0.as_ptr(), core::ptr::addr_of_mut!(count));
1528 let ranges = slice::from_raw_parts(ptr, count as usize);
1529 let result = ranges.iter().copied().map(Into::into).collect();
1530 (FREE_FN)(ptr.cast::<c_void>());
1531 result
1532 }
1533 }
1534
1535 #[doc(alias = "ts_tree_print_dot_graph")]
1540 #[cfg(not(target_os = "wasi"))]
1541 #[cfg(feature = "std")]
1542 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
1543 pub fn print_dot_graph(
1544 &self,
1545 #[cfg(unix)] file: &impl AsRawFd,
1546 #[cfg(windows)] file: &impl AsRawHandle,
1547 ) {
1548 #[cfg(unix)]
1549 {
1550 let fd = file.as_raw_fd();
1551 unsafe { ffi::ts_tree_print_dot_graph(self.0.as_ptr(), fd) }
1552 }
1553
1554 #[cfg(windows)]
1555 {
1556 let handle = file.as_raw_handle();
1557 let fd = unsafe { _open_osfhandle(handle as isize, 0) };
1558 unsafe { ffi::ts_tree_print_dot_graph(self.0.as_ptr(), fd) }
1559 }
1560 }
1561}
1562
1563impl fmt::Debug for Tree {
1564 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1565 write!(f, "{{Tree {:?}}}", self.root_node())
1566 }
1567}
1568
1569impl Drop for Tree {
1570 fn drop(&mut self) {
1571 unsafe { ffi::ts_tree_delete(self.0.as_ptr()) }
1572 }
1573}
1574
1575impl Clone for Tree {
1576 fn clone(&self) -> Self {
1577 unsafe { Self(NonNull::new_unchecked(ffi::ts_tree_copy(self.0.as_ptr()))) }
1578 }
1579}
1580
1581impl<'tree> Node<'tree> {
1582 fn new(node: ffi::TSNode) -> Option<Self> {
1583 (!node.id.is_null()).then_some(Node(node, PhantomData))
1584 }
1585
1586 #[must_use]
1597 pub fn id(&self) -> usize {
1598 self.0.id as usize
1599 }
1600
1601 #[doc(alias = "ts_node_symbol")]
1603 #[must_use]
1604 pub fn kind_id(&self) -> u16 {
1605 unsafe { ffi::ts_node_symbol(self.0) }
1606 }
1607
1608 #[doc(alias = "ts_node_grammar_symbol")]
1611 #[must_use]
1612 pub fn grammar_id(&self) -> u16 {
1613 unsafe { ffi::ts_node_grammar_symbol(self.0) }
1614 }
1615
1616 #[doc(alias = "ts_node_type")]
1618 #[must_use]
1619 pub fn kind(&self) -> &'static str {
1620 unsafe { CStr::from_ptr(ffi::ts_node_type(self.0)) }
1621 .to_str()
1622 .unwrap()
1623 }
1624
1625 #[doc(alias = "ts_node_grammar_type")]
1628 #[must_use]
1629 pub fn grammar_name(&self) -> &'static str {
1630 unsafe { CStr::from_ptr(ffi::ts_node_grammar_type(self.0)) }
1631 .to_str()
1632 .unwrap()
1633 }
1634
1635 #[doc(alias = "ts_node_language")]
1637 #[must_use]
1638 pub fn language(&self) -> LanguageRef {
1639 LanguageRef(unsafe { ffi::ts_node_language(self.0) }, PhantomData)
1640 }
1641
1642 #[doc(alias = "ts_node_is_named")]
1647 #[must_use]
1648 pub fn is_named(&self) -> bool {
1649 unsafe { ffi::ts_node_is_named(self.0) }
1650 }
1651
1652 #[doc(alias = "ts_node_is_extra")]
1657 #[must_use]
1658 pub fn is_extra(&self) -> bool {
1659 unsafe { ffi::ts_node_is_extra(self.0) }
1660 }
1661
1662 #[doc(alias = "ts_node_has_changes")]
1664 #[must_use]
1665 pub fn has_changes(&self) -> bool {
1666 unsafe { ffi::ts_node_has_changes(self.0) }
1667 }
1668
1669 #[doc(alias = "ts_node_has_error")]
1672 #[must_use]
1673 pub fn has_error(&self) -> bool {
1674 unsafe { ffi::ts_node_has_error(self.0) }
1675 }
1676
1677 #[doc(alias = "ts_node_is_error")]
1682 #[must_use]
1683 pub fn is_error(&self) -> bool {
1684 unsafe { ffi::ts_node_is_error(self.0) }
1685 }
1686
1687 #[doc(alias = "ts_node_parse_state")]
1689 #[must_use]
1690 pub fn parse_state(&self) -> u16 {
1691 unsafe { ffi::ts_node_parse_state(self.0) }
1692 }
1693
1694 #[doc(alias = "ts_node_next_parse_state")]
1696 #[must_use]
1697 pub fn next_parse_state(&self) -> u16 {
1698 unsafe { ffi::ts_node_next_parse_state(self.0) }
1699 }
1700
1701 #[doc(alias = "ts_node_is_missing")]
1706 #[must_use]
1707 pub fn is_missing(&self) -> bool {
1708 unsafe { ffi::ts_node_is_missing(self.0) }
1709 }
1710
1711 #[doc(alias = "ts_node_start_byte")]
1713 #[must_use]
1714 pub fn start_byte(&self) -> usize {
1715 unsafe { ffi::ts_node_start_byte(self.0) as usize }
1716 }
1717
1718 #[doc(alias = "ts_node_end_byte")]
1720 #[must_use]
1721 pub fn end_byte(&self) -> usize {
1722 unsafe { ffi::ts_node_end_byte(self.0) as usize }
1723 }
1724
1725 #[must_use]
1727 pub fn byte_range(&self) -> core::ops::Range<usize> {
1728 self.start_byte()..self.end_byte()
1729 }
1730
1731 #[must_use]
1734 pub fn range(&self) -> Range {
1735 Range {
1736 start_byte: self.start_byte(),
1737 end_byte: self.end_byte(),
1738 start_point: self.start_position(),
1739 end_point: self.end_position(),
1740 }
1741 }
1742
1743 #[doc(alias = "ts_node_start_point")]
1745 #[must_use]
1746 pub fn start_position(&self) -> Point {
1747 let result = unsafe { ffi::ts_node_start_point(self.0) };
1748 result.into()
1749 }
1750
1751 #[doc(alias = "ts_node_end_point")]
1753 #[must_use]
1754 pub fn end_position(&self) -> Point {
1755 let result = unsafe { ffi::ts_node_end_point(self.0) };
1756 result.into()
1757 }
1758
1759 #[doc(alias = "ts_node_child")]
1766 #[must_use]
1767 pub fn child(&self, i: usize) -> Option<Self> {
1768 Self::new(unsafe { ffi::ts_node_child(self.0, i as u32) })
1769 }
1770
1771 #[doc(alias = "ts_node_child_count")]
1773 #[must_use]
1774 pub fn child_count(&self) -> usize {
1775 unsafe { ffi::ts_node_child_count(self.0) as usize }
1776 }
1777
1778 #[doc(alias = "ts_node_named_child")]
1785 #[must_use]
1786 pub fn named_child(&self, i: usize) -> Option<Self> {
1787 Self::new(unsafe { ffi::ts_node_named_child(self.0, i as u32) })
1788 }
1789
1790 #[doc(alias = "ts_node_named_child_count")]
1794 #[must_use]
1795 pub fn named_child_count(&self) -> usize {
1796 unsafe { ffi::ts_node_named_child_count(self.0) as usize }
1797 }
1798
1799 #[doc(alias = "ts_node_child_by_field_name")]
1804 #[must_use]
1805 pub fn child_by_field_name(&self, field_name: impl AsRef<[u8]>) -> Option<Self> {
1806 let field_name = field_name.as_ref();
1807 Self::new(unsafe {
1808 ffi::ts_node_child_by_field_name(
1809 self.0,
1810 field_name.as_ptr().cast::<c_char>(),
1811 field_name.len() as u32,
1812 )
1813 })
1814 }
1815
1816 #[doc(alias = "ts_node_child_by_field_id")]
1821 #[must_use]
1822 pub fn child_by_field_id(&self, field_id: u16) -> Option<Self> {
1823 Self::new(unsafe { ffi::ts_node_child_by_field_id(self.0, field_id) })
1824 }
1825
1826 #[doc(alias = "ts_node_field_name_for_child")]
1828 #[must_use]
1829 pub fn field_name_for_child(&self, child_index: u32) -> Option<&'static str> {
1830 unsafe {
1831 let ptr = ffi::ts_node_field_name_for_child(self.0, child_index);
1832 (!ptr.is_null()).then(|| CStr::from_ptr(ptr).to_str().unwrap())
1833 }
1834 }
1835
1836 #[must_use]
1838 pub fn field_name_for_named_child(&self, named_child_index: u32) -> Option<&'static str> {
1839 unsafe {
1840 let ptr = ffi::ts_node_field_name_for_named_child(self.0, named_child_index);
1841 (!ptr.is_null()).then(|| CStr::from_ptr(ptr).to_str().unwrap())
1842 }
1843 }
1844
1845 pub fn children<'cursor>(
1855 &self,
1856 cursor: &'cursor mut TreeCursor<'tree>,
1857 ) -> impl ExactSizeIterator<Item = Node<'tree>> + 'cursor {
1858 cursor.reset(*self);
1859 cursor.goto_first_child();
1860 (0..self.child_count()).map(move |_| {
1861 let result = cursor.node();
1862 cursor.goto_next_sibling();
1863 result
1864 })
1865 }
1866
1867 pub fn named_children<'cursor>(
1871 &self,
1872 cursor: &'cursor mut TreeCursor<'tree>,
1873 ) -> impl ExactSizeIterator<Item = Node<'tree>> + 'cursor {
1874 cursor.reset(*self);
1875 cursor.goto_first_child();
1876 (0..self.named_child_count()).map(move |_| {
1877 while !cursor.node().is_named() {
1878 if !cursor.goto_next_sibling() {
1879 break;
1880 }
1881 }
1882 let result = cursor.node();
1883 cursor.goto_next_sibling();
1884 result
1885 })
1886 }
1887
1888 pub fn children_by_field_name<'cursor>(
1892 &self,
1893 field_name: &str,
1894 cursor: &'cursor mut TreeCursor<'tree>,
1895 ) -> impl Iterator<Item = Node<'tree>> + 'cursor {
1896 let field_id = self.language().field_id_for_name(field_name);
1897 let mut done = field_id.is_none();
1898 if !done {
1899 cursor.reset(*self);
1900 cursor.goto_first_child();
1901 }
1902 iter::from_fn(move || {
1903 if !done {
1904 while cursor.field_id() != field_id {
1905 if !cursor.goto_next_sibling() {
1906 return None;
1907 }
1908 }
1909 let result = cursor.node();
1910 if !cursor.goto_next_sibling() {
1911 done = true;
1912 }
1913 return Some(result);
1914 }
1915 None
1916 })
1917 }
1918
1919 pub fn children_by_field_id<'cursor>(
1923 &self,
1924 field_id: FieldId,
1925 cursor: &'cursor mut TreeCursor<'tree>,
1926 ) -> impl Iterator<Item = Node<'tree>> + 'cursor {
1927 cursor.reset(*self);
1928 cursor.goto_first_child();
1929 let mut done = false;
1930 iter::from_fn(move || {
1931 if !done {
1932 while cursor.field_id() != Some(field_id) {
1933 if !cursor.goto_next_sibling() {
1934 return None;
1935 }
1936 }
1937 let result = cursor.node();
1938 if !cursor.goto_next_sibling() {
1939 done = true;
1940 }
1941 return Some(result);
1942 }
1943 None
1944 })
1945 }
1946
1947 #[doc(alias = "ts_node_parent")]
1951 #[must_use]
1952 pub fn parent(&self) -> Option<Self> {
1953 Self::new(unsafe { ffi::ts_node_parent(self.0) })
1954 }
1955
1956 #[doc(alias = "ts_node_child_with_descendant")]
1960 #[must_use]
1961 pub fn child_with_descendant(&self, descendant: Self) -> Option<Self> {
1962 Self::new(unsafe { ffi::ts_node_child_with_descendant(self.0, descendant.0) })
1963 }
1964
1965 #[doc(alias = "ts_node_next_sibling")]
1967 #[must_use]
1968 pub fn next_sibling(&self) -> Option<Self> {
1969 Self::new(unsafe { ffi::ts_node_next_sibling(self.0) })
1970 }
1971
1972 #[doc(alias = "ts_node_prev_sibling")]
1974 #[must_use]
1975 pub fn prev_sibling(&self) -> Option<Self> {
1976 Self::new(unsafe { ffi::ts_node_prev_sibling(self.0) })
1977 }
1978
1979 #[doc(alias = "ts_node_next_named_sibling")]
1981 #[must_use]
1982 pub fn next_named_sibling(&self) -> Option<Self> {
1983 Self::new(unsafe { ffi::ts_node_next_named_sibling(self.0) })
1984 }
1985
1986 #[doc(alias = "ts_node_prev_named_sibling")]
1988 #[must_use]
1989 pub fn prev_named_sibling(&self) -> Option<Self> {
1990 Self::new(unsafe { ffi::ts_node_prev_named_sibling(self.0) })
1991 }
1992
1993 #[doc(alias = "ts_node_first_child_for_byte")]
1995 #[must_use]
1996 pub fn first_child_for_byte(&self, byte: usize) -> Option<Self> {
1997 Self::new(unsafe { ffi::ts_node_first_child_for_byte(self.0, byte as u32) })
1998 }
1999
2000 #[doc(alias = "ts_node_first_named_child_for_point")]
2002 #[must_use]
2003 pub fn first_named_child_for_byte(&self, byte: usize) -> Option<Self> {
2004 Self::new(unsafe { ffi::ts_node_first_named_child_for_byte(self.0, byte as u32) })
2005 }
2006
2007 #[doc(alias = "ts_node_descendant_count")]
2009 #[must_use]
2010 pub fn descendant_count(&self) -> usize {
2011 unsafe { ffi::ts_node_descendant_count(self.0) as usize }
2012 }
2013
2014 #[doc(alias = "ts_node_descendant_for_byte_range")]
2016 #[must_use]
2017 pub fn descendant_for_byte_range(&self, start: usize, end: usize) -> Option<Self> {
2018 Self::new(unsafe {
2019 ffi::ts_node_descendant_for_byte_range(self.0, start as u32, end as u32)
2020 })
2021 }
2022
2023 #[doc(alias = "ts_node_named_descendant_for_byte_range")]
2025 #[must_use]
2026 pub fn named_descendant_for_byte_range(&self, start: usize, end: usize) -> Option<Self> {
2027 Self::new(unsafe {
2028 ffi::ts_node_named_descendant_for_byte_range(self.0, start as u32, end as u32)
2029 })
2030 }
2031
2032 #[doc(alias = "ts_node_descendant_for_point_range")]
2034 #[must_use]
2035 pub fn descendant_for_point_range(&self, start: Point, end: Point) -> Option<Self> {
2036 Self::new(unsafe {
2037 ffi::ts_node_descendant_for_point_range(self.0, start.into(), end.into())
2038 })
2039 }
2040
2041 #[doc(alias = "ts_node_named_descendant_for_point_range")]
2043 #[must_use]
2044 pub fn named_descendant_for_point_range(&self, start: Point, end: Point) -> Option<Self> {
2045 Self::new(unsafe {
2046 ffi::ts_node_named_descendant_for_point_range(self.0, start.into(), end.into())
2047 })
2048 }
2049
2050 #[doc(alias = "ts_node_string")]
2052 #[must_use]
2053 pub fn to_sexp(&self) -> String {
2054 let c_string = unsafe { ffi::ts_node_string(self.0) };
2055 let result = unsafe { CStr::from_ptr(c_string) }
2056 .to_str()
2057 .unwrap()
2058 .to_string();
2059 unsafe { (FREE_FN)(c_string.cast::<c_void>()) };
2060 result
2061 }
2062
2063 pub fn utf8_text<'a>(&self, source: &'a [u8]) -> Result<&'a str, str::Utf8Error> {
2064 str::from_utf8(&source[self.start_byte()..self.end_byte()])
2065 }
2066
2067 #[must_use]
2068 pub fn utf16_text<'a>(&self, source: &'a [u16]) -> &'a [u16] {
2069 &source[self.start_byte() / 2..self.end_byte() / 2]
2070 }
2071
2072 #[doc(alias = "ts_tree_cursor_new")]
2077 #[must_use]
2078 pub fn walk(&self) -> TreeCursor<'tree> {
2079 TreeCursor(unsafe { ffi::ts_tree_cursor_new(self.0) }, PhantomData)
2080 }
2081
2082 #[doc(alias = "ts_node_edit")]
2090 pub fn edit(&mut self, edit: &InputEdit) {
2091 let edit = edit.into();
2092 unsafe { ffi::ts_node_edit(core::ptr::addr_of_mut!(self.0), &edit) }
2093 }
2094}
2095
2096impl PartialEq for Node<'_> {
2097 fn eq(&self, other: &Self) -> bool {
2098 core::ptr::eq(self.0.id, other.0.id)
2099 }
2100}
2101
2102impl Eq for Node<'_> {}
2103
2104impl hash::Hash for Node<'_> {
2105 fn hash<H: hash::Hasher>(&self, state: &mut H) {
2106 self.0.id.hash(state);
2107 self.0.context[0].hash(state);
2108 self.0.context[1].hash(state);
2109 self.0.context[2].hash(state);
2110 self.0.context[3].hash(state);
2111 }
2112}
2113
2114impl fmt::Debug for Node<'_> {
2115 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2116 write!(
2117 f,
2118 "{{Node {} {} - {}}}",
2119 self.kind(),
2120 self.start_position(),
2121 self.end_position()
2122 )
2123 }
2124}
2125
2126impl fmt::Display for Node<'_> {
2127 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2128 let sexp = self.to_sexp();
2129 if sexp.is_empty() {
2130 write!(f, "")
2131 } else if !f.alternate() {
2132 write!(f, "{sexp}")
2133 } else {
2134 write!(f, "{}", format_sexp(&sexp, f.width().unwrap_or(0)))
2135 }
2136 }
2137}
2138
2139impl<'cursor> TreeCursor<'cursor> {
2140 #[doc(alias = "ts_tree_cursor_current_node")]
2142 #[must_use]
2143 pub fn node(&self) -> Node<'cursor> {
2144 Node(
2145 unsafe { ffi::ts_tree_cursor_current_node(&self.0) },
2146 PhantomData,
2147 )
2148 }
2149
2150 #[doc(alias = "ts_tree_cursor_current_field_id")]
2154 #[must_use]
2155 pub fn field_id(&self) -> Option<FieldId> {
2156 let id = unsafe { ffi::ts_tree_cursor_current_field_id(&self.0) };
2157 FieldId::new(id)
2158 }
2159
2160 #[doc(alias = "ts_tree_cursor_current_field_name")]
2162 #[must_use]
2163 pub fn field_name(&self) -> Option<&'static str> {
2164 unsafe {
2165 let ptr = ffi::ts_tree_cursor_current_field_name(&self.0);
2166 (!ptr.is_null()).then(|| CStr::from_ptr(ptr).to_str().unwrap())
2167 }
2168 }
2169
2170 #[doc(alias = "ts_tree_cursor_current_depth")]
2173 #[must_use]
2174 pub fn depth(&self) -> u32 {
2175 unsafe { ffi::ts_tree_cursor_current_depth(&self.0) }
2176 }
2177
2178 #[doc(alias = "ts_tree_cursor_current_descendant_index")]
2181 #[must_use]
2182 pub fn descendant_index(&self) -> usize {
2183 unsafe { ffi::ts_tree_cursor_current_descendant_index(&self.0) as usize }
2184 }
2185
2186 #[doc(alias = "ts_tree_cursor_goto_first_child")]
2191 pub fn goto_first_child(&mut self) -> bool {
2192 unsafe { ffi::ts_tree_cursor_goto_first_child(&mut self.0) }
2193 }
2194
2195 #[doc(alias = "ts_tree_cursor_goto_last_child")]
2204 pub fn goto_last_child(&mut self) -> bool {
2205 unsafe { ffi::ts_tree_cursor_goto_last_child(&mut self.0) }
2206 }
2207
2208 #[doc(alias = "ts_tree_cursor_goto_parent")]
2217 pub fn goto_parent(&mut self) -> bool {
2218 unsafe { ffi::ts_tree_cursor_goto_parent(&mut self.0) }
2219 }
2220
2221 #[doc(alias = "ts_tree_cursor_goto_next_sibling")]
2229 pub fn goto_next_sibling(&mut self) -> bool {
2230 unsafe { ffi::ts_tree_cursor_goto_next_sibling(&mut self.0) }
2231 }
2232
2233 #[doc(alias = "ts_tree_cursor_goto_descendant")]
2237 pub fn goto_descendant(&mut self, descendant_index: usize) {
2238 unsafe { ffi::ts_tree_cursor_goto_descendant(&mut self.0, descendant_index as u32) }
2239 }
2240
2241 #[doc(alias = "ts_tree_cursor_goto_previous_sibling")]
2253 pub fn goto_previous_sibling(&mut self) -> bool {
2254 unsafe { ffi::ts_tree_cursor_goto_previous_sibling(&mut self.0) }
2255 }
2256
2257 #[doc(alias = "ts_tree_cursor_goto_first_child_for_byte")]
2263 pub fn goto_first_child_for_byte(&mut self, index: usize) -> Option<usize> {
2264 let result =
2265 unsafe { ffi::ts_tree_cursor_goto_first_child_for_byte(&mut self.0, index as u32) };
2266 result.try_into().ok()
2267 }
2268
2269 #[doc(alias = "ts_tree_cursor_goto_first_child_for_point")]
2275 pub fn goto_first_child_for_point(&mut self, point: Point) -> Option<usize> {
2276 let result =
2277 unsafe { ffi::ts_tree_cursor_goto_first_child_for_point(&mut self.0, point.into()) };
2278 result.try_into().ok()
2279 }
2280
2281 #[doc(alias = "ts_tree_cursor_reset")]
2284 pub fn reset(&mut self, node: Node<'cursor>) {
2285 unsafe { ffi::ts_tree_cursor_reset(&mut self.0, node.0) };
2286 }
2287
2288 #[doc(alias = "ts_tree_cursor_reset_to")]
2293 pub fn reset_to(&mut self, cursor: &Self) {
2294 unsafe { ffi::ts_tree_cursor_reset_to(&mut self.0, &cursor.0) };
2295 }
2296}
2297
2298impl Clone for TreeCursor<'_> {
2299 fn clone(&self) -> Self {
2300 TreeCursor(unsafe { ffi::ts_tree_cursor_copy(&self.0) }, PhantomData)
2301 }
2302}
2303
2304impl Drop for TreeCursor<'_> {
2305 fn drop(&mut self) {
2306 unsafe { ffi::ts_tree_cursor_delete(&mut self.0) }
2307 }
2308}
2309
2310impl LookaheadIterator {
2311 #[doc(alias = "ts_lookahead_iterator_language")]
2313 #[must_use]
2314 pub fn language(&self) -> LanguageRef<'_> {
2315 LanguageRef(
2316 unsafe { ffi::ts_lookahead_iterator_language(self.0.as_ptr()) },
2317 PhantomData,
2318 )
2319 }
2320
2321 #[doc(alias = "ts_lookahead_iterator_current_symbol")]
2323 #[must_use]
2324 pub fn current_symbol(&self) -> u16 {
2325 unsafe { ffi::ts_lookahead_iterator_current_symbol(self.0.as_ptr()) }
2326 }
2327
2328 #[doc(alias = "ts_lookahead_iterator_current_symbol_name")]
2330 #[must_use]
2331 pub fn current_symbol_name(&self) -> &'static str {
2332 unsafe {
2333 CStr::from_ptr(ffi::ts_lookahead_iterator_current_symbol_name(
2334 self.0.as_ptr(),
2335 ))
2336 .to_str()
2337 .unwrap()
2338 }
2339 }
2340
2341 #[doc(alias = "ts_lookahead_iterator_reset")]
2346 pub fn reset(&mut self, language: &Language, state: u16) -> bool {
2347 unsafe { ffi::ts_lookahead_iterator_reset(self.0.as_ptr(), language.0, state) }
2348 }
2349
2350 #[doc(alias = "ts_lookahead_iterator_reset_state")]
2355 pub fn reset_state(&mut self, state: u16) -> bool {
2356 unsafe { ffi::ts_lookahead_iterator_reset_state(self.0.as_ptr(), state) }
2357 }
2358
2359 pub fn iter_names(&mut self) -> impl Iterator<Item = &'static str> + '_ {
2361 LookaheadNamesIterator(self)
2362 }
2363}
2364
2365impl Iterator for LookaheadNamesIterator<'_> {
2366 type Item = &'static str;
2367
2368 #[doc(alias = "ts_lookahead_iterator_next")]
2369 fn next(&mut self) -> Option<Self::Item> {
2370 unsafe { ffi::ts_lookahead_iterator_next(self.0 .0.as_ptr()) }
2371 .then(|| self.0.current_symbol_name())
2372 }
2373}
2374
2375impl Iterator for LookaheadIterator {
2376 type Item = u16;
2377
2378 #[doc(alias = "ts_lookahead_iterator_next")]
2379 fn next(&mut self) -> Option<Self::Item> {
2380 unsafe { ffi::ts_lookahead_iterator_next(self.0.as_ptr()) }.then(|| self.current_symbol())
2382 }
2383}
2384
2385impl Drop for LookaheadIterator {
2386 #[doc(alias = "ts_lookahead_iterator_delete")]
2387 fn drop(&mut self) {
2388 unsafe { ffi::ts_lookahead_iterator_delete(self.0.as_ptr()) }
2389 }
2390}
2391
2392impl Query {
2393 pub fn new(language: &Language, source: &str) -> Result<Self, QueryError> {
2400 let mut error_offset = 0u32;
2401 let mut error_type: ffi::TSQueryError = 0;
2402 let bytes = source.as_bytes();
2403
2404 let ptr = unsafe {
2406 ffi::ts_query_new(
2407 language.0,
2408 bytes.as_ptr().cast::<c_char>(),
2409 bytes.len() as u32,
2410 core::ptr::addr_of_mut!(error_offset),
2411 core::ptr::addr_of_mut!(error_type),
2412 )
2413 };
2414
2415 if ptr.is_null() {
2417 if error_type == ffi::TSQueryErrorLanguage {
2418 return Err(QueryError {
2419 row: 0,
2420 column: 0,
2421 offset: 0,
2422 message: LanguageError {
2423 version: language.abi_version(),
2424 }
2425 .to_string(),
2426 kind: QueryErrorKind::Language,
2427 });
2428 }
2429
2430 let offset = error_offset as usize;
2431 let mut line_start = 0;
2432 let mut row = 0;
2433 let mut line_containing_error = None;
2434 for line in source.lines() {
2435 let line_end = line_start + line.len() + 1;
2436 if line_end > offset {
2437 line_containing_error = Some(line);
2438 break;
2439 }
2440 line_start = line_end;
2441 row += 1;
2442 }
2443 let column = offset - line_start;
2444
2445 let kind;
2446 let message;
2447 match error_type {
2448 ffi::TSQueryErrorNodeType | ffi::TSQueryErrorField | ffi::TSQueryErrorCapture => {
2450 let suffix = source.split_at(offset).1;
2451 let in_quotes = offset > 0 && source.as_bytes()[offset - 1] == b'"';
2452 let mut backslashes = 0;
2453 let end_offset = suffix
2454 .find(|c| {
2455 if in_quotes {
2456 if c == '"' && backslashes % 2 == 0 {
2457 true
2458 } else if c == '\\' {
2459 backslashes += 1;
2460 false
2461 } else {
2462 backslashes = 0;
2463 false
2464 }
2465 } else {
2466 !char::is_alphanumeric(c) && c != '_' && c != '-'
2467 }
2468 })
2469 .unwrap_or(suffix.len());
2470 message = suffix.split_at(end_offset).0.to_string();
2471 kind = match error_type {
2472 ffi::TSQueryErrorNodeType => QueryErrorKind::NodeType,
2473 ffi::TSQueryErrorField => QueryErrorKind::Field,
2474 ffi::TSQueryErrorCapture => QueryErrorKind::Capture,
2475 _ => unreachable!(),
2476 };
2477 }
2478
2479 _ => {
2481 message = line_containing_error.map_or_else(
2482 || "Unexpected EOF".to_string(),
2483 |line| line.to_string() + "\n" + &" ".repeat(offset - line_start) + "^",
2484 );
2485 kind = match error_type {
2486 ffi::TSQueryErrorStructure => QueryErrorKind::Structure,
2487 _ => QueryErrorKind::Syntax,
2488 };
2489 }
2490 }
2491
2492 return Err(QueryError {
2493 row,
2494 column,
2495 offset,
2496 message,
2497 kind,
2498 });
2499 }
2500
2501 unsafe { Self::from_raw_parts(ptr, source) }
2502 }
2503
2504 #[doc(hidden)]
2505 unsafe fn from_raw_parts(ptr: *mut ffi::TSQuery, source: &str) -> Result<Self, QueryError> {
2506 let ptr = {
2507 struct TSQueryDrop(*mut ffi::TSQuery);
2508 impl Drop for TSQueryDrop {
2509 fn drop(&mut self) {
2510 unsafe { ffi::ts_query_delete(self.0) }
2511 }
2512 }
2513 TSQueryDrop(ptr)
2514 };
2515
2516 let string_count = unsafe { ffi::ts_query_string_count(ptr.0) };
2517 let capture_count = unsafe { ffi::ts_query_capture_count(ptr.0) };
2518 let pattern_count = unsafe { ffi::ts_query_pattern_count(ptr.0) as usize };
2519
2520 let mut capture_names = Vec::with_capacity(capture_count as usize);
2521 let mut capture_quantifiers_vec = Vec::with_capacity(pattern_count as usize);
2522 let mut text_predicates_vec = Vec::with_capacity(pattern_count);
2523 let mut property_predicates_vec = Vec::with_capacity(pattern_count);
2524 let mut property_settings_vec = Vec::with_capacity(pattern_count);
2525 let mut general_predicates_vec = Vec::with_capacity(pattern_count);
2526
2527 for i in 0..capture_count {
2529 unsafe {
2530 let mut length = 0u32;
2531 let name =
2532 ffi::ts_query_capture_name_for_id(ptr.0, i, core::ptr::addr_of_mut!(length))
2533 .cast::<u8>();
2534 let name = slice::from_raw_parts(name, length as usize);
2535 let name = str::from_utf8_unchecked(name);
2536 capture_names.push(name);
2537 }
2538 }
2539
2540 for i in 0..pattern_count {
2542 let mut capture_quantifiers = Vec::with_capacity(capture_count as usize);
2543 for j in 0..capture_count {
2544 unsafe {
2545 let quantifier = ffi::ts_query_capture_quantifier_for_id(ptr.0, i as u32, j);
2546 capture_quantifiers.push(quantifier.into());
2547 }
2548 }
2549 capture_quantifiers_vec.push(capture_quantifiers.into());
2550 }
2551
2552 let string_values = (0..string_count)
2554 .map(|i| unsafe {
2555 let mut length = 0u32;
2556 let value =
2557 ffi::ts_query_string_value_for_id(ptr.0, i, core::ptr::addr_of_mut!(length))
2558 .cast::<u8>();
2559 let value = slice::from_raw_parts(value, length as usize);
2560 let value = str::from_utf8_unchecked(value);
2561 value
2562 })
2563 .collect::<Vec<_>>();
2564
2565 for i in 0..pattern_count {
2567 let predicate_steps = unsafe {
2568 let mut length = 0u32;
2569 let raw_predicates = ffi::ts_query_predicates_for_pattern(
2570 ptr.0,
2571 i as u32,
2572 core::ptr::addr_of_mut!(length),
2573 );
2574 (length > 0)
2575 .then(|| slice::from_raw_parts(raw_predicates, length as usize))
2576 .unwrap_or_default()
2577 };
2578
2579 let byte_offset = unsafe { ffi::ts_query_start_byte_for_pattern(ptr.0, i as u32) };
2580 let row = source
2581 .char_indices()
2582 .take_while(|(i, _)| *i < byte_offset as usize)
2583 .filter(|(_, c)| *c == '\n')
2584 .count();
2585
2586 use ffi::TSQueryPredicateStepType as T;
2587 const TYPE_DONE: T = ffi::TSQueryPredicateStepTypeDone;
2588 const TYPE_CAPTURE: T = ffi::TSQueryPredicateStepTypeCapture;
2589 const TYPE_STRING: T = ffi::TSQueryPredicateStepTypeString;
2590
2591 let mut text_predicates = Vec::new();
2592 let mut property_predicates = Vec::new();
2593 let mut property_settings = Vec::new();
2594 let mut general_predicates = Vec::new();
2595 for p in predicate_steps.split(|s| s.type_ == TYPE_DONE) {
2596 if p.is_empty() {
2597 continue;
2598 }
2599
2600 if p[0].type_ != TYPE_STRING {
2601 return Err(predicate_error(
2602 row,
2603 format!(
2604 "Expected predicate to start with a function name. Got @{}.",
2605 capture_names[p[0].value_id as usize],
2606 ),
2607 ));
2608 }
2609
2610 let operator_name = string_values[p[0].value_id as usize];
2612 match operator_name {
2613 "eq?" | "not-eq?" | "any-eq?" | "any-not-eq?" => {
2614 if p.len() != 3 {
2615 return Err(predicate_error(
2616 row,
2617 format!(
2618 "Wrong number of arguments to #eq? predicate. Expected 2, got {}.",
2619 p.len() - 1
2620 ),
2621 ));
2622 }
2623 if p[1].type_ != TYPE_CAPTURE {
2624 return Err(predicate_error(row, format!(
2625 "First argument to #eq? predicate must be a capture name. Got literal \"{}\".",
2626 string_values[p[1].value_id as usize],
2627 )));
2628 }
2629
2630 let is_positive = operator_name == "eq?" || operator_name == "any-eq?";
2631 let match_all = match operator_name {
2632 "eq?" | "not-eq?" => true,
2633 "any-eq?" | "any-not-eq?" => false,
2634 _ => unreachable!(),
2635 };
2636 text_predicates.push(if p[2].type_ == TYPE_CAPTURE {
2637 TextPredicateCapture::EqCapture(
2638 p[1].value_id,
2639 p[2].value_id,
2640 is_positive,
2641 match_all,
2642 )
2643 } else {
2644 TextPredicateCapture::EqString(
2645 p[1].value_id,
2646 string_values[p[2].value_id as usize].to_string().into(),
2647 is_positive,
2648 match_all,
2649 )
2650 });
2651 }
2652
2653 "match?" | "not-match?" | "any-match?" | "any-not-match?" => {
2654 if p.len() != 3 {
2655 return Err(predicate_error(row, format!(
2656 "Wrong number of arguments to #match? predicate. Expected 2, got {}.",
2657 p.len() - 1
2658 )));
2659 }
2660 if p[1].type_ != TYPE_CAPTURE {
2661 return Err(predicate_error(row, format!(
2662 "First argument to #match? predicate must be a capture name. Got literal \"{}\".",
2663 string_values[p[1].value_id as usize],
2664 )));
2665 }
2666 if p[2].type_ == TYPE_CAPTURE {
2667 return Err(predicate_error(row, format!(
2668 "Second argument to #match? predicate must be a literal. Got capture @{}.",
2669 capture_names[p[2].value_id as usize],
2670 )));
2671 }
2672
2673 let is_positive =
2674 operator_name == "match?" || operator_name == "any-match?";
2675 let match_all = match operator_name {
2676 "match?" | "not-match?" => true,
2677 "any-match?" | "any-not-match?" => false,
2678 _ => unreachable!(),
2679 };
2680 let regex = &string_values[p[2].value_id as usize];
2681 text_predicates.push(TextPredicateCapture::MatchString(
2682 p[1].value_id,
2683 regex::bytes::Regex::new(regex).map_err(|_| {
2684 predicate_error(row, format!("Invalid regex '{regex}'"))
2685 })?,
2686 is_positive,
2687 match_all,
2688 ));
2689 }
2690
2691 "set!" => property_settings.push(Self::parse_property(
2692 row,
2693 operator_name,
2694 &capture_names,
2695 &string_values,
2696 &p[1..],
2697 )?),
2698
2699 "is?" | "is-not?" => property_predicates.push((
2700 Self::parse_property(
2701 row,
2702 operator_name,
2703 &capture_names,
2704 &string_values,
2705 &p[1..],
2706 )?,
2707 operator_name == "is?",
2708 )),
2709
2710 "any-of?" | "not-any-of?" => {
2711 if p.len() < 2 {
2712 return Err(predicate_error(row, format!(
2713 "Wrong number of arguments to #any-of? predicate. Expected at least 1, got {}.",
2714 p.len() - 1
2715 )));
2716 }
2717 if p[1].type_ != TYPE_CAPTURE {
2718 return Err(predicate_error(row, format!(
2719 "First argument to #any-of? predicate must be a capture name. Got literal \"{}\".",
2720 string_values[p[1].value_id as usize],
2721 )));
2722 }
2723
2724 let is_positive = operator_name == "any-of?";
2725 let mut values = Vec::new();
2726 for arg in &p[2..] {
2727 if arg.type_ == TYPE_CAPTURE {
2728 return Err(predicate_error(row, format!(
2729 "Arguments to #any-of? predicate must be literals. Got capture @{}.",
2730 capture_names[arg.value_id as usize],
2731 )));
2732 }
2733 values.push(string_values[arg.value_id as usize]);
2734 }
2735 text_predicates.push(TextPredicateCapture::AnyString(
2736 p[1].value_id,
2737 values
2738 .iter()
2739 .map(|x| (*x).to_string().into())
2740 .collect::<Vec<_>>()
2741 .into(),
2742 is_positive,
2743 ));
2744 }
2745
2746 _ => general_predicates.push(QueryPredicate {
2747 operator: operator_name.to_string().into(),
2748 args: p[1..]
2749 .iter()
2750 .map(|a| {
2751 if a.type_ == TYPE_CAPTURE {
2752 QueryPredicateArg::Capture(a.value_id)
2753 } else {
2754 QueryPredicateArg::String(
2755 string_values[a.value_id as usize].to_string().into(),
2756 )
2757 }
2758 })
2759 .collect(),
2760 }),
2761 }
2762 }
2763
2764 text_predicates_vec.push(text_predicates.into());
2765 property_predicates_vec.push(property_predicates.into());
2766 property_settings_vec.push(property_settings.into());
2767 general_predicates_vec.push(general_predicates.into());
2768 }
2769
2770 let result = Self {
2771 ptr: unsafe { NonNull::new_unchecked(ptr.0) },
2772 capture_names: capture_names.into(),
2773 capture_quantifiers: capture_quantifiers_vec.into(),
2774 text_predicates: text_predicates_vec.into(),
2775 property_predicates: property_predicates_vec.into(),
2776 property_settings: property_settings_vec.into(),
2777 general_predicates: general_predicates_vec.into(),
2778 };
2779
2780 core::mem::forget(ptr);
2781
2782 Ok(result)
2783 }
2784
2785 #[doc(alias = "ts_query_start_byte_for_pattern")]
2788 #[must_use]
2789 pub fn start_byte_for_pattern(&self, pattern_index: usize) -> usize {
2790 assert!(
2791 pattern_index < self.text_predicates.len(),
2792 "Pattern index is {pattern_index} but the pattern count is {}",
2793 self.text_predicates.len(),
2794 );
2795 unsafe {
2796 ffi::ts_query_start_byte_for_pattern(self.ptr.as_ptr(), pattern_index as u32) as usize
2797 }
2798 }
2799
2800 #[doc(alias = "ts_query_end_byte_for_pattern")]
2803 #[must_use]
2804 pub fn end_byte_for_pattern(&self, pattern_index: usize) -> usize {
2805 assert!(
2806 pattern_index < self.text_predicates.len(),
2807 "Pattern index is {pattern_index} but the pattern count is {}",
2808 self.text_predicates.len(),
2809 );
2810 unsafe {
2811 ffi::ts_query_end_byte_for_pattern(self.ptr.as_ptr(), pattern_index as u32) as usize
2812 }
2813 }
2814
2815 #[doc(alias = "ts_query_pattern_count")]
2817 #[must_use]
2818 pub fn pattern_count(&self) -> usize {
2819 unsafe { ffi::ts_query_pattern_count(self.ptr.as_ptr()) as usize }
2820 }
2821
2822 #[must_use]
2824 pub const fn capture_names(&self) -> &[&str] {
2825 &self.capture_names
2826 }
2827
2828 #[must_use]
2830 pub const fn capture_quantifiers(&self, index: usize) -> &[CaptureQuantifier] {
2831 &self.capture_quantifiers[index]
2832 }
2833
2834 #[must_use]
2836 pub fn capture_index_for_name(&self, name: &str) -> Option<u32> {
2837 self.capture_names
2838 .iter()
2839 .position(|n| *n == name)
2840 .map(|ix| ix as u32)
2841 }
2842
2843 #[must_use]
2847 pub const fn property_predicates(&self, index: usize) -> &[(QueryProperty, bool)] {
2848 &self.property_predicates[index]
2849 }
2850
2851 #[must_use]
2855 pub const fn property_settings(&self, index: usize) -> &[QueryProperty] {
2856 &self.property_settings[index]
2857 }
2858
2859 #[must_use]
2867 pub const fn general_predicates(&self, index: usize) -> &[QueryPredicate] {
2868 &self.general_predicates[index]
2869 }
2870
2871 #[doc(alias = "ts_query_disable_capture")]
2876 pub fn disable_capture(&mut self, name: &str) {
2877 unsafe {
2878 ffi::ts_query_disable_capture(
2879 self.ptr.as_ptr(),
2880 name.as_bytes().as_ptr().cast::<c_char>(),
2881 name.len() as u32,
2882 );
2883 }
2884 }
2885
2886 #[doc(alias = "ts_query_disable_pattern")]
2891 pub fn disable_pattern(&mut self, index: usize) {
2892 unsafe { ffi::ts_query_disable_pattern(self.ptr.as_ptr(), index as u32) }
2893 }
2894
2895 #[doc(alias = "ts_query_is_pattern_rooted")]
2897 #[must_use]
2898 pub fn is_pattern_rooted(&self, index: usize) -> bool {
2899 unsafe { ffi::ts_query_is_pattern_rooted(self.ptr.as_ptr(), index as u32) }
2900 }
2901
2902 #[doc(alias = "ts_query_is_pattern_non_local")]
2904 #[must_use]
2905 pub fn is_pattern_non_local(&self, index: usize) -> bool {
2906 unsafe { ffi::ts_query_is_pattern_non_local(self.ptr.as_ptr(), index as u32) }
2907 }
2908
2909 #[doc(alias = "ts_query_is_pattern_guaranteed_at_step")]
2914 #[must_use]
2915 pub fn is_pattern_guaranteed_at_step(&self, byte_offset: usize) -> bool {
2916 unsafe {
2917 ffi::ts_query_is_pattern_guaranteed_at_step(self.ptr.as_ptr(), byte_offset as u32)
2918 }
2919 }
2920
2921 fn parse_property(
2922 row: usize,
2923 function_name: &str,
2924 capture_names: &[&str],
2925 string_values: &[&str],
2926 args: &[ffi::TSQueryPredicateStep],
2927 ) -> Result<QueryProperty, QueryError> {
2928 if args.is_empty() || args.len() > 3 {
2929 return Err(predicate_error(
2930 row,
2931 format!(
2932 "Wrong number of arguments to {function_name} predicate. Expected 1 to 3, got {}.",
2933 args.len(),
2934 ),
2935 ));
2936 }
2937
2938 let mut capture_id = None;
2939 let mut key = None;
2940 let mut value = None;
2941
2942 for arg in args {
2943 if arg.type_ == ffi::TSQueryPredicateStepTypeCapture {
2944 if capture_id.is_some() {
2945 return Err(predicate_error(
2946 row,
2947 format!(
2948 "Invalid arguments to {function_name} predicate. Unexpected second capture name @{}",
2949 capture_names[arg.value_id as usize]
2950 ),
2951 ));
2952 }
2953 capture_id = Some(arg.value_id as usize);
2954 } else if key.is_none() {
2955 key = Some(&string_values[arg.value_id as usize]);
2956 } else if value.is_none() {
2957 value = Some(string_values[arg.value_id as usize]);
2958 } else {
2959 return Err(predicate_error(
2960 row,
2961 format!(
2962 "Invalid arguments to {function_name} predicate. Unexpected third argument @{}",
2963 string_values[arg.value_id as usize]
2964 ),
2965 ));
2966 }
2967 }
2968
2969 if let Some(key) = key {
2970 Ok(QueryProperty::new(key, value, capture_id))
2971 } else {
2972 Err(predicate_error(
2973 row,
2974 format!("Invalid arguments to {function_name} predicate. Missing key argument",),
2975 ))
2976 }
2977 }
2978}
2979
2980impl Default for QueryCursor {
2981 fn default() -> Self {
2982 Self::new()
2983 }
2984}
2985
2986impl QueryCursor {
2987 #[doc(alias = "ts_query_cursor_new")]
2992 #[must_use]
2993 pub fn new() -> Self {
2994 Self {
2995 ptr: unsafe { NonNull::new_unchecked(ffi::ts_query_cursor_new()) },
2996 }
2997 }
2998
2999 #[doc(alias = "ts_query_cursor_match_limit")]
3001 #[must_use]
3002 pub fn match_limit(&self) -> u32 {
3003 unsafe { ffi::ts_query_cursor_match_limit(self.ptr.as_ptr()) }
3004 }
3005
3006 #[doc(alias = "ts_query_cursor_set_match_limit")]
3009 pub fn set_match_limit(&mut self, limit: u32) {
3010 unsafe {
3011 ffi::ts_query_cursor_set_match_limit(self.ptr.as_ptr(), limit);
3012 }
3013 }
3014
3015 #[doc(alias = "ts_query_cursor_set_timeout_micros")]
3020 #[deprecated(
3021 since = "0.25.0",
3022 note = "Prefer using `matches_with_options` or `captures_with_options` and using a callback"
3023 )]
3024 pub fn set_timeout_micros(&mut self, timeout: u64) {
3025 unsafe {
3026 ffi::ts_query_cursor_set_timeout_micros(self.ptr.as_ptr(), timeout);
3027 }
3028 }
3029
3030 #[doc(alias = "ts_query_cursor_timeout_micros")]
3034 #[deprecated(
3035 since = "0.25.0",
3036 note = "Prefer using `matches_with_options` or `captures_with_options` and using a callback"
3037 )]
3038 #[must_use]
3039 pub fn timeout_micros(&self) -> u64 {
3040 unsafe { ffi::ts_query_cursor_timeout_micros(self.ptr.as_ptr()) }
3041 }
3042
3043 #[doc(alias = "ts_query_cursor_did_exceed_match_limit")]
3046 #[must_use]
3047 pub fn did_exceed_match_limit(&self) -> bool {
3048 unsafe { ffi::ts_query_cursor_did_exceed_match_limit(self.ptr.as_ptr()) }
3049 }
3050
3051 #[doc(alias = "ts_query_cursor_exec")]
3062 pub fn matches<'query, 'cursor: 'query, 'tree, T: TextProvider<I>, I: AsRef<[u8]>>(
3063 &'cursor mut self,
3064 query: &'query Query,
3065 node: Node<'tree>,
3066 text_provider: T,
3067 ) -> QueryMatches<'query, 'tree, T, I> {
3068 let ptr = self.ptr.as_ptr();
3069 unsafe { ffi::ts_query_cursor_exec(ptr, query.ptr.as_ptr(), node.0) };
3070 QueryMatches {
3071 ptr,
3072 query,
3073 text_provider,
3074 buffer1: Vec::default(),
3075 buffer2: Vec::default(),
3076 current_match: None,
3077 _options: None,
3078 _phantom: PhantomData,
3079 }
3080 }
3081
3082 #[doc(alias = "ts_query_cursor_exec_with_options")]
3089 pub fn matches_with_options<
3090 'query,
3091 'cursor: 'query,
3092 'tree,
3093 T: TextProvider<I>,
3094 I: AsRef<[u8]>,
3095 >(
3096 &'cursor mut self,
3097 query: &'query Query,
3098 node: Node<'tree>,
3099 text_provider: T,
3100 options: QueryCursorOptions,
3101 ) -> QueryMatches<'query, 'tree, T, I> {
3102 unsafe extern "C" fn progress(state: *mut ffi::TSQueryCursorState) -> bool {
3103 let callback = (*state)
3104 .payload
3105 .cast::<QueryProgressCallback>()
3106 .as_mut()
3107 .unwrap();
3108 (callback)(&QueryCursorState::from_raw(state))
3109 }
3110
3111 let query_options = options.progress_callback.map(|cb| {
3112 QueryCursorOptionsDrop(Box::into_raw(Box::new(ffi::TSQueryCursorOptions {
3113 payload: Box::into_raw(Box::new(cb)).cast::<c_void>(),
3114 progress_callback: Some(progress),
3115 })))
3116 });
3117
3118 let ptr = self.ptr.as_ptr();
3119 unsafe {
3120 ffi::ts_query_cursor_exec_with_options(
3121 ptr,
3122 query.ptr.as_ptr(),
3123 node.0,
3124 query_options.as_ref().map_or(ptr::null_mut(), |q| q.0),
3125 );
3126 }
3127 QueryMatches {
3128 ptr,
3129 query,
3130 text_provider,
3131 buffer1: Vec::default(),
3132 buffer2: Vec::default(),
3133 current_match: None,
3134 _options: query_options,
3135 _phantom: PhantomData,
3136 }
3137 }
3138
3139 #[doc(alias = "ts_query_cursor_exec")]
3149 pub fn captures<'query, 'cursor: 'query, 'tree, T: TextProvider<I>, I: AsRef<[u8]>>(
3150 &'cursor mut self,
3151 query: &'query Query,
3152 node: Node<'tree>,
3153 text_provider: T,
3154 ) -> QueryCaptures<'query, 'tree, T, I> {
3155 let ptr = self.ptr.as_ptr();
3156 unsafe { ffi::ts_query_cursor_exec(ptr, query.ptr.as_ptr(), node.0) };
3157 QueryCaptures {
3158 ptr,
3159 query,
3160 text_provider,
3161 buffer1: Vec::default(),
3162 buffer2: Vec::default(),
3163 current_match: None,
3164 _options: None,
3165 _phantom: PhantomData,
3166 }
3167 }
3168
3169 #[doc(alias = "ts_query_cursor_exec")]
3175 pub fn captures_with_options<
3176 'query,
3177 'cursor: 'query,
3178 'tree,
3179 T: TextProvider<I>,
3180 I: AsRef<[u8]>,
3181 >(
3182 &'cursor mut self,
3183 query: &'query Query,
3184 node: Node<'tree>,
3185 text_provider: T,
3186 options: QueryCursorOptions,
3187 ) -> QueryCaptures<'query, 'tree, T, I> {
3188 unsafe extern "C" fn progress(state: *mut ffi::TSQueryCursorState) -> bool {
3189 let callback = (*state)
3190 .payload
3191 .cast::<QueryProgressCallback>()
3192 .as_mut()
3193 .unwrap();
3194 (callback)(&QueryCursorState::from_raw(state))
3195 }
3196
3197 let query_options = options.progress_callback.map(|cb| {
3198 QueryCursorOptionsDrop(Box::into_raw(Box::new(ffi::TSQueryCursorOptions {
3199 payload: Box::into_raw(Box::new(cb)).cast::<c_void>(),
3200 progress_callback: Some(progress),
3201 })))
3202 });
3203
3204 let ptr = self.ptr.as_ptr();
3205 unsafe {
3206 ffi::ts_query_cursor_exec_with_options(
3207 ptr,
3208 query.ptr.as_ptr(),
3209 node.0,
3210 query_options.as_ref().map_or(ptr::null_mut(), |q| q.0),
3211 );
3212 }
3213 QueryCaptures {
3214 ptr,
3215 query,
3216 text_provider,
3217 buffer1: Vec::default(),
3218 buffer2: Vec::default(),
3219 current_match: None,
3220 _options: query_options,
3221 _phantom: PhantomData,
3222 }
3223 }
3224
3225 #[doc(alias = "ts_query_cursor_set_byte_range")]
3228 pub fn set_byte_range(&mut self, range: ops::Range<usize>) -> &mut Self {
3229 unsafe {
3230 ffi::ts_query_cursor_set_byte_range(
3231 self.ptr.as_ptr(),
3232 range.start as u32,
3233 range.end as u32,
3234 );
3235 }
3236 self
3237 }
3238
3239 #[doc(alias = "ts_query_cursor_set_point_range")]
3242 pub fn set_point_range(&mut self, range: ops::Range<Point>) -> &mut Self {
3243 unsafe {
3244 ffi::ts_query_cursor_set_point_range(
3245 self.ptr.as_ptr(),
3246 range.start.into(),
3247 range.end.into(),
3248 );
3249 }
3250 self
3251 }
3252
3253 #[doc(alias = "ts_query_cursor_set_max_start_depth")]
3268 pub fn set_max_start_depth(&mut self, max_start_depth: Option<u32>) -> &mut Self {
3269 unsafe {
3270 ffi::ts_query_cursor_set_max_start_depth(
3271 self.ptr.as_ptr(),
3272 max_start_depth.unwrap_or(u32::MAX),
3273 );
3274 }
3275 self
3276 }
3277}
3278
3279impl<'tree> QueryMatch<'_, 'tree> {
3280 #[must_use]
3281 pub const fn id(&self) -> u32 {
3282 self.id
3283 }
3284
3285 #[doc(alias = "ts_query_cursor_remove_match")]
3286 pub fn remove(&self) {
3287 unsafe { ffi::ts_query_cursor_remove_match(self.cursor, self.id) }
3288 }
3289
3290 pub fn nodes_for_capture_index(
3291 &self,
3292 capture_ix: u32,
3293 ) -> impl Iterator<Item = Node<'tree>> + '_ {
3294 self.captures
3295 .iter()
3296 .filter_map(move |capture| (capture.index == capture_ix).then_some(capture.node))
3297 }
3298
3299 fn new(m: &ffi::TSQueryMatch, cursor: *mut ffi::TSQueryCursor) -> Self {
3300 QueryMatch {
3301 cursor,
3302 id: m.id,
3303 pattern_index: m.pattern_index as usize,
3304 captures: (m.capture_count > 0)
3305 .then(|| unsafe {
3306 slice::from_raw_parts(
3307 m.captures.cast::<QueryCapture<'tree>>(),
3308 m.capture_count as usize,
3309 )
3310 })
3311 .unwrap_or_default(),
3312 }
3313 }
3314
3315 pub fn satisfies_text_predicates<I: AsRef<[u8]>>(
3316 &self,
3317 query: &Query,
3318 buffer1: &mut Vec<u8>,
3319 buffer2: &mut Vec<u8>,
3320 text_provider: &mut impl TextProvider<I>,
3321 ) -> bool {
3322 struct NodeText<'a, T> {
3323 buffer: &'a mut Vec<u8>,
3324 first_chunk: Option<T>,
3325 }
3326 impl<'a, T: AsRef<[u8]>> NodeText<'a, T> {
3327 fn new(buffer: &'a mut Vec<u8>) -> Self {
3328 Self {
3329 buffer,
3330 first_chunk: None,
3331 }
3332 }
3333
3334 fn get_text(&mut self, chunks: &mut impl Iterator<Item = T>) -> &[u8] {
3335 self.first_chunk = chunks.next();
3336 if let Some(next_chunk) = chunks.next() {
3337 self.buffer.clear();
3338 self.buffer
3339 .extend_from_slice(self.first_chunk.as_ref().unwrap().as_ref());
3340 self.buffer.extend_from_slice(next_chunk.as_ref());
3341 for chunk in chunks {
3342 self.buffer.extend_from_slice(chunk.as_ref());
3343 }
3344 self.buffer.as_slice()
3345 } else if let Some(ref first_chunk) = self.first_chunk {
3346 first_chunk.as_ref()
3347 } else {
3348 &[]
3349 }
3350 }
3351 }
3352
3353 let mut node_text1 = NodeText::new(buffer1);
3354 let mut node_text2 = NodeText::new(buffer2);
3355
3356 query.text_predicates[self.pattern_index]
3357 .iter()
3358 .all(|predicate| match predicate {
3359 TextPredicateCapture::EqCapture(i, j, is_positive, match_all_nodes) => {
3360 let mut nodes_1 = self.nodes_for_capture_index(*i).peekable();
3361 let mut nodes_2 = self.nodes_for_capture_index(*j).peekable();
3362 while nodes_1.peek().is_some() && nodes_2.peek().is_some() {
3363 let node1 = nodes_1.next().unwrap();
3364 let node2 = nodes_2.next().unwrap();
3365 let mut text1 = text_provider.text(node1);
3366 let mut text2 = text_provider.text(node2);
3367 let text1 = node_text1.get_text(&mut text1);
3368 let text2 = node_text2.get_text(&mut text2);
3369 let is_positive_match = text1 == text2;
3370 if is_positive_match != *is_positive && *match_all_nodes {
3371 return false;
3372 }
3373 if is_positive_match == *is_positive && !*match_all_nodes {
3374 return true;
3375 }
3376 }
3377 nodes_1.next().is_none() && nodes_2.next().is_none()
3378 }
3379 TextPredicateCapture::EqString(i, s, is_positive, match_all_nodes) => {
3380 let nodes = self.nodes_for_capture_index(*i);
3381 for node in nodes {
3382 let mut text = text_provider.text(node);
3383 let text = node_text1.get_text(&mut text);
3384 let is_positive_match = text == s.as_bytes();
3385 if is_positive_match != *is_positive && *match_all_nodes {
3386 return false;
3387 }
3388 if is_positive_match == *is_positive && !*match_all_nodes {
3389 return true;
3390 }
3391 }
3392 true
3393 }
3394 TextPredicateCapture::MatchString(i, r, is_positive, match_all_nodes) => {
3395 let nodes = self.nodes_for_capture_index(*i);
3396 for node in nodes {
3397 let mut text = text_provider.text(node);
3398 let text = node_text1.get_text(&mut text);
3399 let is_positive_match = r.is_match(text);
3400 if is_positive_match != *is_positive && *match_all_nodes {
3401 return false;
3402 }
3403 if is_positive_match == *is_positive && !*match_all_nodes {
3404 return true;
3405 }
3406 }
3407 true
3408 }
3409 TextPredicateCapture::AnyString(i, v, is_positive) => {
3410 let nodes = self.nodes_for_capture_index(*i);
3411 for node in nodes {
3412 let mut text = text_provider.text(node);
3413 let text = node_text1.get_text(&mut text);
3414 if (v.iter().any(|s| text == s.as_bytes())) != *is_positive {
3415 return false;
3416 }
3417 }
3418 true
3419 }
3420 })
3421 }
3422}
3423
3424impl QueryProperty {
3425 #[must_use]
3426 pub fn new(key: &str, value: Option<&str>, capture_id: Option<usize>) -> Self {
3427 Self {
3428 capture_id,
3429 key: key.to_string().into(),
3430 value: value.map(|s| s.to_string().into()),
3431 }
3432 }
3433}
3434
3435impl<'query, 'tree: 'query, T: TextProvider<I>, I: AsRef<[u8]>> StreamingIterator
3439 for QueryMatches<'query, 'tree, T, I>
3440{
3441 type Item = QueryMatch<'query, 'tree>;
3442
3443 fn advance(&mut self) {
3444 self.current_match = unsafe {
3445 loop {
3446 let mut m = MaybeUninit::<ffi::TSQueryMatch>::uninit();
3447 if ffi::ts_query_cursor_next_match(self.ptr, m.as_mut_ptr()) {
3448 let result = QueryMatch::new(&m.assume_init(), self.ptr);
3449 if result.satisfies_text_predicates(
3450 self.query,
3451 &mut self.buffer1,
3452 &mut self.buffer2,
3453 &mut self.text_provider,
3454 ) {
3455 break Some(result);
3456 }
3457 } else {
3458 break None;
3459 }
3460 }
3461 };
3462 }
3463
3464 fn get(&self) -> Option<&Self::Item> {
3465 self.current_match.as_ref()
3466 }
3467}
3468
3469impl<'query, 'tree: 'query, T: TextProvider<I>, I: AsRef<[u8]>> StreamingIteratorMut
3470 for QueryMatches<'query, 'tree, T, I>
3471{
3472 fn get_mut(&mut self) -> Option<&mut Self::Item> {
3473 self.current_match.as_mut()
3474 }
3475}
3476
3477impl<'query, 'tree: 'query, T: TextProvider<I>, I: AsRef<[u8]>> StreamingIterator
3478 for QueryCaptures<'query, 'tree, T, I>
3479{
3480 type Item = (QueryMatch<'query, 'tree>, usize);
3481
3482 fn advance(&mut self) {
3483 self.current_match = unsafe {
3484 loop {
3485 let mut capture_index = 0u32;
3486 let mut m = MaybeUninit::<ffi::TSQueryMatch>::uninit();
3487 if ffi::ts_query_cursor_next_capture(
3488 self.ptr,
3489 m.as_mut_ptr(),
3490 core::ptr::addr_of_mut!(capture_index),
3491 ) {
3492 let result = QueryMatch::new(&m.assume_init(), self.ptr);
3493 if result.satisfies_text_predicates(
3494 self.query,
3495 &mut self.buffer1,
3496 &mut self.buffer2,
3497 &mut self.text_provider,
3498 ) {
3499 break Some((result, capture_index as usize));
3500 }
3501 result.remove();
3502 } else {
3503 break None;
3504 }
3505 }
3506 }
3507 }
3508
3509 fn get(&self) -> Option<&Self::Item> {
3510 self.current_match.as_ref()
3511 }
3512}
3513
3514impl<'query, 'tree: 'query, T: TextProvider<I>, I: AsRef<[u8]>> StreamingIteratorMut
3515 for QueryCaptures<'query, 'tree, T, I>
3516{
3517 fn get_mut(&mut self) -> Option<&mut Self::Item> {
3518 self.current_match.as_mut()
3519 }
3520}
3521
3522impl<T: TextProvider<I>, I: AsRef<[u8]>> QueryMatches<'_, '_, T, I> {
3523 #[doc(alias = "ts_query_cursor_set_byte_range")]
3524 pub fn set_byte_range(&mut self, range: ops::Range<usize>) {
3525 unsafe {
3526 ffi::ts_query_cursor_set_byte_range(self.ptr, range.start as u32, range.end as u32);
3527 }
3528 }
3529
3530 #[doc(alias = "ts_query_cursor_set_point_range")]
3531 pub fn set_point_range(&mut self, range: ops::Range<Point>) {
3532 unsafe {
3533 ffi::ts_query_cursor_set_point_range(self.ptr, range.start.into(), range.end.into());
3534 }
3535 }
3536}
3537
3538impl<T: TextProvider<I>, I: AsRef<[u8]>> QueryCaptures<'_, '_, T, I> {
3539 #[doc(alias = "ts_query_cursor_set_byte_range")]
3540 pub fn set_byte_range(&mut self, range: ops::Range<usize>) {
3541 unsafe {
3542 ffi::ts_query_cursor_set_byte_range(self.ptr, range.start as u32, range.end as u32);
3543 }
3544 }
3545
3546 #[doc(alias = "ts_query_cursor_set_point_range")]
3547 pub fn set_point_range(&mut self, range: ops::Range<Point>) {
3548 unsafe {
3549 ffi::ts_query_cursor_set_point_range(self.ptr, range.start.into(), range.end.into());
3550 }
3551 }
3552}
3553
3554impl fmt::Debug for QueryMatch<'_, '_> {
3555 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3556 write!(
3557 f,
3558 "QueryMatch {{ id: {}, pattern_index: {}, captures: {:?} }}",
3559 self.id, self.pattern_index, self.captures
3560 )
3561 }
3562}
3563
3564impl<F, R, I> TextProvider<I> for F
3565where
3566 F: FnMut(Node) -> R,
3567 R: Iterator<Item = I>,
3568 I: AsRef<[u8]>,
3569{
3570 type I = R;
3571
3572 fn text(&mut self, node: Node) -> Self::I {
3573 (self)(node)
3574 }
3575}
3576
3577impl<'a> TextProvider<&'a [u8]> for &'a [u8] {
3578 type I = iter::Once<&'a [u8]>;
3579
3580 fn text(&mut self, node: Node) -> Self::I {
3581 iter::once(&self[node.byte_range()])
3582 }
3583}
3584
3585impl PartialEq for Query {
3586 fn eq(&self, other: &Self) -> bool {
3587 self.ptr == other.ptr
3588 }
3589}
3590
3591impl Drop for Query {
3592 fn drop(&mut self) {
3593 unsafe { ffi::ts_query_delete(self.ptr.as_ptr()) }
3594 }
3595}
3596
3597impl Drop for QueryCursor {
3598 fn drop(&mut self) {
3599 unsafe { ffi::ts_query_cursor_delete(self.ptr.as_ptr()) }
3600 }
3601}
3602
3603impl Point {
3604 #[must_use]
3605 pub const fn new(row: usize, column: usize) -> Self {
3606 Self { row, column }
3607 }
3608}
3609
3610impl fmt::Display for Point {
3611 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3612 write!(f, "({}, {})", self.row, self.column)
3613 }
3614}
3615
3616impl From<Point> for ffi::TSPoint {
3617 fn from(val: Point) -> Self {
3618 Self {
3619 row: val.row as u32,
3620 column: val.column as u32,
3621 }
3622 }
3623}
3624
3625impl From<ffi::TSPoint> for Point {
3626 fn from(point: ffi::TSPoint) -> Self {
3627 Self {
3628 row: point.row as usize,
3629 column: point.column as usize,
3630 }
3631 }
3632}
3633
3634impl From<Range> for ffi::TSRange {
3635 fn from(val: Range) -> Self {
3636 Self {
3637 start_byte: val.start_byte as u32,
3638 end_byte: val.end_byte as u32,
3639 start_point: val.start_point.into(),
3640 end_point: val.end_point.into(),
3641 }
3642 }
3643}
3644
3645impl From<ffi::TSRange> for Range {
3646 fn from(range: ffi::TSRange) -> Self {
3647 Self {
3648 start_byte: range.start_byte as usize,
3649 end_byte: range.end_byte as usize,
3650 start_point: range.start_point.into(),
3651 end_point: range.end_point.into(),
3652 }
3653 }
3654}
3655
3656impl From<&'_ InputEdit> for ffi::TSInputEdit {
3657 fn from(val: &'_ InputEdit) -> Self {
3658 Self {
3659 start_byte: val.start_byte as u32,
3660 old_end_byte: val.old_end_byte as u32,
3661 new_end_byte: val.new_end_byte as u32,
3662 start_point: val.start_position.into(),
3663 old_end_point: val.old_end_position.into(),
3664 new_end_point: val.new_end_position.into(),
3665 }
3666 }
3667}
3668
3669impl<'a> LossyUtf8<'a> {
3670 #[must_use]
3671 pub const fn new(bytes: &'a [u8]) -> Self {
3672 LossyUtf8 {
3673 bytes,
3674 in_replacement: false,
3675 }
3676 }
3677}
3678
3679impl<'a> Iterator for LossyUtf8<'a> {
3680 type Item = &'a str;
3681
3682 fn next(&mut self) -> Option<&'a str> {
3683 if self.bytes.is_empty() {
3684 return None;
3685 }
3686 if self.in_replacement {
3687 self.in_replacement = false;
3688 return Some("\u{fffd}");
3689 }
3690 match core::str::from_utf8(self.bytes) {
3691 Ok(valid) => {
3692 self.bytes = &[];
3693 Some(valid)
3694 }
3695 Err(error) => {
3696 if let Some(error_len) = error.error_len() {
3697 let error_start = error.valid_up_to();
3698 if error_start > 0 {
3699 let result =
3700 unsafe { core::str::from_utf8_unchecked(&self.bytes[..error_start]) };
3701 self.bytes = &self.bytes[(error_start + error_len)..];
3702 self.in_replacement = true;
3703 Some(result)
3704 } else {
3705 self.bytes = &self.bytes[error_len..];
3706 Some("\u{fffd}")
3707 }
3708 } else {
3709 None
3710 }
3711 }
3712 }
3713 }
3714}
3715
3716#[must_use]
3717const fn predicate_error(row: usize, message: String) -> QueryError {
3718 QueryError {
3719 kind: QueryErrorKind::Predicate,
3720 row,
3721 column: 0,
3722 offset: 0,
3723 message,
3724 }
3725}
3726
3727impl fmt::Display for IncludedRangesError {
3728 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3729 write!(f, "Incorrect range by index: {}", self.0)
3730 }
3731}
3732
3733impl fmt::Display for LanguageError {
3734 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3735 write!(
3736 f,
3737 "Incompatible language version {}. Expected minimum {}, maximum {}",
3738 self.version, MIN_COMPATIBLE_LANGUAGE_VERSION, LANGUAGE_VERSION,
3739 )
3740 }
3741}
3742
3743impl fmt::Display for QueryError {
3744 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3745 let msg = match self.kind {
3746 QueryErrorKind::Field => "Invalid field name ",
3747 QueryErrorKind::NodeType => "Invalid node type ",
3748 QueryErrorKind::Capture => "Invalid capture name ",
3749 QueryErrorKind::Predicate => "Invalid predicate: ",
3750 QueryErrorKind::Structure => "Impossible pattern:\n",
3751 QueryErrorKind::Syntax => "Invalid syntax:\n",
3752 QueryErrorKind::Language => "",
3753 };
3754 if msg.is_empty() {
3755 write!(f, "{}", self.message)
3756 } else {
3757 write!(
3758 f,
3759 "Query error at {}:{}. {}{}",
3760 self.row + 1,
3761 self.column + 1,
3762 msg,
3763 self.message
3764 )
3765 }
3766 }
3767}
3768
3769#[doc(hidden)]
3770#[must_use]
3771pub fn format_sexp(sexp: &str, initial_indent_level: usize) -> String {
3772 let mut indent_level = initial_indent_level;
3773 let mut formatted = String::new();
3774 let mut has_field = false;
3775
3776 let mut c_iter = sexp.chars().peekable();
3777 let mut s = String::with_capacity(sexp.len());
3778 let mut quote = '\0';
3779 let mut saw_paren = false;
3780 let mut did_last = false;
3781
3782 let mut fetch_next_str = |next: &mut String| {
3783 next.clear();
3784 while let Some(c) = c_iter.next() {
3785 if c == '\'' || c == '"' {
3786 quote = c;
3787 } else if c == ' ' || (c == ')' && quote != '\0') {
3788 if let Some(next_c) = c_iter.peek() {
3789 if *next_c == quote {
3790 next.push(c);
3791 next.push(*next_c);
3792 c_iter.next();
3793 quote = '\0';
3794 continue;
3795 }
3796 }
3797 break;
3798 }
3799 if c == ')' {
3800 saw_paren = true;
3801 break;
3802 }
3803 next.push(c);
3804 }
3805
3806 if c_iter.peek().is_none() && next.is_empty() {
3808 if saw_paren {
3809 saw_paren = false;
3811 return Some(());
3812 }
3813 if !did_last {
3814 did_last = true;
3816 return Some(());
3817 }
3818 return None;
3819 }
3820 Some(())
3821 };
3822
3823 while fetch_next_str(&mut s).is_some() {
3824 if s.is_empty() && indent_level > 0 {
3825 indent_level -= 1;
3827 write!(formatted, ")").unwrap();
3828 } else if s.starts_with('(') {
3829 if has_field {
3830 has_field = false;
3831 } else {
3832 if indent_level > 0 {
3833 writeln!(formatted).unwrap();
3834 for _ in 0..indent_level {
3835 write!(formatted, " ").unwrap();
3836 }
3837 }
3838 indent_level += 1;
3839 }
3840
3841 write!(formatted, "{s}").unwrap();
3843
3844 if s.starts_with("(MISSING") || s.starts_with("(UNEXPECTED") {
3846 fetch_next_str(&mut s).unwrap();
3847 if s.is_empty() {
3848 while indent_level > 0 {
3849 indent_level -= 1;
3850 write!(formatted, ")").unwrap();
3851 }
3852 } else {
3853 write!(formatted, " {s}").unwrap();
3854 }
3855 }
3856 } else if s.ends_with(':') {
3857 writeln!(formatted).unwrap();
3859 for _ in 0..indent_level {
3860 write!(formatted, " ").unwrap();
3861 }
3862 write!(formatted, "{s} ").unwrap();
3863 has_field = true;
3864 indent_level += 1;
3865 }
3866 }
3867
3868 formatted
3869}
3870
3871pub fn wasm_stdlib_symbols() -> impl Iterator<Item = &'static str> {
3872 const WASM_STDLIB_SYMBOLS: &str = include_str!(concat!(env!("OUT_DIR"), "/stdlib-symbols.txt"));
3873
3874 WASM_STDLIB_SYMBOLS
3875 .lines()
3876 .map(|s| s.trim_matches(|c| c == '"' || c == ','))
3877}
3878
3879extern "C" {
3880 fn free(ptr: *mut c_void);
3881}
3882
3883static mut FREE_FN: unsafe extern "C" fn(ptr: *mut c_void) = free;
3884
3885#[doc(alias = "ts_set_allocator")]
3891pub unsafe fn set_allocator(
3892 new_malloc: Option<unsafe extern "C" fn(size: usize) -> *mut c_void>,
3893 new_calloc: Option<unsafe extern "C" fn(nmemb: usize, size: usize) -> *mut c_void>,
3894 new_realloc: Option<unsafe extern "C" fn(ptr: *mut c_void, size: usize) -> *mut c_void>,
3895 new_free: Option<unsafe extern "C" fn(ptr: *mut c_void)>,
3896) {
3897 FREE_FN = new_free.unwrap_or(free);
3898 ffi::ts_set_allocator(new_malloc, new_calloc, new_realloc, new_free);
3899}
3900
3901#[cfg(feature = "std")]
3902#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
3903impl error::Error for IncludedRangesError {}
3904#[cfg(feature = "std")]
3905#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
3906impl error::Error for LanguageError {}
3907#[cfg(feature = "std")]
3908#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
3909impl error::Error for QueryError {}
3910
3911unsafe impl Send for Language {}
3912unsafe impl Sync for Language {}
3913
3914unsafe impl Send for Node<'_> {}
3915unsafe impl Sync for Node<'_> {}
3916
3917unsafe impl Send for LookaheadIterator {}
3918unsafe impl Sync for LookaheadIterator {}
3919
3920unsafe impl Send for LookaheadNamesIterator<'_> {}
3921unsafe impl Sync for LookaheadNamesIterator<'_> {}
3922
3923unsafe impl Send for Parser {}
3924unsafe impl Sync for Parser {}
3925
3926unsafe impl Send for Query {}
3927unsafe impl Sync for Query {}
3928
3929unsafe impl Send for QueryCursor {}
3930unsafe impl Sync for QueryCursor {}
3931
3932unsafe impl Send for Tree {}
3933unsafe impl Sync for Tree {}
3934
3935unsafe impl Send for TreeCursor<'_> {}
3936unsafe impl Sync for TreeCursor<'_> {}