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