1#![cfg_attr(not(any(test, doctest)), doc = include_str!("./README.md"))]
2#![cfg_attr(not(feature = "std"), no_std)]
3#![cfg_attr(docsrs, feature(doc_cfg))]
4
5pub mod ffi;
6mod util;
7
8#[cfg(not(tree_sitter_c_core))]
9#[path = "../src_rust/mod.rs"]
10mod core_impl;
11
12#[cfg(not(feature = "std"))]
13extern crate alloc;
14#[cfg(not(feature = "std"))]
15use alloc::{boxed::Box, format, string::String, string::ToString, vec::Vec};
16use core::{
17 ffi::{c_char, c_void, CStr},
18 fmt::{self, Write},
19 hash, iter,
20 marker::PhantomData,
21 mem::MaybeUninit,
22 num::NonZeroU16,
23 ops::{self, ControlFlow, Deref},
24 ptr::{self, NonNull},
25 slice, str,
26};
27#[cfg(feature = "std")]
28use std::error;
29#[cfg(all(unix, feature = "std"))]
30use std::os::fd::AsRawFd;
31#[cfg(all(windows, feature = "std"))]
32use std::os::windows::io::AsRawHandle;
33
34pub use streaming_iterator::{StreamingIterator, StreamingIteratorMut};
35use tree_sitter_language::LanguageFn;
36
37#[doc(alias = "TREE_SITTER_LANGUAGE_VERSION")]
45pub const LANGUAGE_VERSION: usize = ffi::TREE_SITTER_LANGUAGE_VERSION as usize;
46
47#[doc(alias = "TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION")]
50pub const MIN_COMPATIBLE_LANGUAGE_VERSION: usize =
51 ffi::TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION as usize;
52
53pub const PARSER_HEADER: &str = include_str!("../src/parser.h");
54
55#[doc(alias = "TSLanguage")]
58#[derive(Clone, Debug, PartialEq, Eq, Hash)]
59#[repr(transparent)]
60pub struct Language(*const ffi::TSLanguage);
61
62pub struct LanguageRef<'a>(*const ffi::TSLanguage, PhantomData<&'a ()>);
63
64#[doc(alias = "TSLanguageMetadata")]
71pub struct LanguageMetadata {
72 pub major_version: u8,
73 pub minor_version: u8,
74 pub patch_version: u8,
75}
76
77impl From<ffi::TSLanguageMetadata> for LanguageMetadata {
78 fn from(val: ffi::TSLanguageMetadata) -> Self {
79 Self {
80 major_version: val.major_version,
81 minor_version: val.minor_version,
82 patch_version: val.patch_version,
83 }
84 }
85}
86
87#[doc(alias = "TSTree")]
89pub struct Tree(NonNull<ffi::TSTree>);
90
91#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord)]
95pub struct Point {
96 pub row: usize,
97 pub column: usize,
98}
99
100#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
103pub struct Range {
104 pub start_byte: usize,
105 pub end_byte: usize,
106 pub start_point: Point,
107 pub end_point: Point,
108}
109
110#[derive(Clone, Copy, Debug, PartialEq, Eq)]
112pub struct InputEdit {
113 pub start_byte: usize,
114 pub old_end_byte: usize,
115 pub new_end_byte: usize,
116 pub start_position: Point,
117 pub old_end_position: Point,
118 pub new_end_position: Point,
119}
120
121impl InputEdit {
122 #[doc(alias = "ts_point_edit")]
128 pub fn edit_point(&self, point: &mut Point, byte: &mut usize) {
129 let edit = self.into();
130 let mut ts_point = (*point).into();
131 let mut ts_byte = *byte as u32;
132
133 unsafe {
134 ffi::ts_point_edit(
135 core::ptr::addr_of_mut!(ts_point),
136 core::ptr::addr_of_mut!(ts_byte),
137 &edit,
138 );
139 }
140
141 *point = ts_point.into();
142 *byte = ts_byte as usize;
143 }
144
145 #[doc(alias = "ts_range_edit")]
151 pub fn edit_range(&self, range: &mut Range) {
152 let edit = self.into();
153 let mut ts_range = (*range).into();
154
155 unsafe {
156 ffi::ts_range_edit(core::ptr::addr_of_mut!(ts_range), &edit);
157 }
158
159 *range = ts_range.into();
160 }
161}
162
163#[doc(alias = "TSNode")]
165#[derive(Clone, Copy)]
166#[repr(transparent)]
167pub struct Node<'tree>(ffi::TSNode, PhantomData<&'tree ()>);
168
169#[doc(alias = "TSParser")]
172pub struct Parser(NonNull<ffi::TSParser>);
173
174#[doc(alias = "TSLookaheadIterator")]
177pub struct LookaheadIterator(NonNull<ffi::TSLookaheadIterator>);
178struct LookaheadNamesIterator<'a>(&'a mut LookaheadIterator);
179
180pub struct ParseState(NonNull<ffi::TSParseState>);
183
184impl ParseState {
185 #[must_use]
186 pub const fn current_byte_offset(&self) -> usize {
187 unsafe { self.0.as_ref() }.current_byte_offset as usize
188 }
189
190 #[must_use]
191 pub const fn has_error(&self) -> bool {
192 unsafe { self.0.as_ref() }.has_error
193 }
194}
195
196pub struct QueryCursorState(NonNull<ffi::TSQueryCursorState>);
199
200impl QueryCursorState {
201 #[must_use]
202 pub const fn current_byte_offset(&self) -> usize {
203 unsafe { self.0.as_ref() }.current_byte_offset as usize
204 }
205}
206
207#[derive(Default)]
208pub struct ParseOptions<'a> {
209 pub progress_callback: Option<ParseProgressCallback<'a>>,
210}
211
212impl<'a> ParseOptions<'a> {
213 #[must_use]
214 pub fn new() -> Self {
215 Self::default()
216 }
217
218 #[must_use]
219 pub fn progress_callback<F: FnMut(&ParseState) -> ControlFlow<()>>(
220 mut self,
221 callback: &'a mut F,
222 ) -> Self {
223 self.progress_callback = Some(callback);
224 self
225 }
226
227 #[must_use]
232 pub fn reborrow(&mut self) -> ParseOptions {
233 ParseOptions {
234 progress_callback: match &mut self.progress_callback {
235 Some(cb) => Some(*cb),
236 None => None,
237 },
238 }
239 }
240}
241
242#[derive(Default)]
243pub struct QueryCursorOptions<'a> {
244 pub progress_callback: Option<QueryProgressCallback<'a>>,
245}
246
247impl<'a> QueryCursorOptions<'a> {
248 #[must_use]
249 pub fn new() -> Self {
250 Self::default()
251 }
252
253 #[must_use]
254 pub fn progress_callback<F: FnMut(&QueryCursorState) -> ControlFlow<()>>(
255 mut self,
256 callback: &'a mut F,
257 ) -> Self {
258 self.progress_callback = Some(callback);
259 self
260 }
261
262 #[must_use]
267 pub fn reborrow(&mut self) -> QueryCursorOptions {
268 QueryCursorOptions {
269 progress_callback: match &mut self.progress_callback {
270 Some(cb) => Some(*cb),
271 None => None,
272 },
273 }
274 }
275}
276
277struct QueryCursorOptionsDrop(*mut ffi::TSQueryCursorOptions);
278
279impl Drop for QueryCursorOptionsDrop {
280 fn drop(&mut self) {
281 unsafe {
282 if !(*self.0).payload.is_null() {
283 drop(Box::from_raw(
284 (*self.0).payload.cast::<QueryProgressCallback>(),
285 ));
286 }
287 drop(Box::from_raw(self.0));
288 }
289 }
290}
291
292#[derive(Debug, PartialEq, Eq)]
294pub enum LogType {
295 Parse,
296 Lex,
297}
298
299type FieldId = NonZeroU16;
300
301type Logger<'a> = Box<dyn FnMut(LogType, &str) + 'a>;
303
304type ParseProgressCallback<'a> = &'a mut dyn FnMut(&ParseState) -> ControlFlow<()>;
306
307type QueryProgressCallback<'a> = &'a mut dyn FnMut(&QueryCursorState) -> ControlFlow<()>;
309
310pub trait Decode {
311 fn decode(bytes: &[u8]) -> (i32, u32);
314}
315
316#[doc(alias = "TSTreeCursor")]
318pub struct TreeCursor<'tree>(ffi::TSTreeCursor, PhantomData<&'tree ()>);
319
320#[doc(alias = "TSQuery")]
322#[derive(Debug)]
323#[allow(clippy::type_complexity)]
324pub struct Query {
325 ptr: NonNull<ffi::TSQuery>,
326 capture_names: Box<[&'static str]>,
327 capture_quantifiers: Box<[Box<[CaptureQuantifier]>]>,
328 text_predicates: Box<[Box<[TextPredicateCapture]>]>,
329 property_settings: Box<[Box<[QueryProperty]>]>,
330 property_predicates: Box<[Box<[(QueryProperty, bool)]>]>,
331 general_predicates: Box<[Box<[QueryPredicate]>]>,
332}
333
334#[derive(Debug, PartialEq, Eq, Clone, Copy)]
336pub enum CaptureQuantifier {
337 Zero,
338 ZeroOrOne,
339 ZeroOrMore,
340 One,
341 OneOrMore,
342}
343
344impl From<ffi::TSQuantifier> for CaptureQuantifier {
345 fn from(value: ffi::TSQuantifier) -> Self {
346 match value {
347 ffi::TSQuantifierZero => Self::Zero,
348 ffi::TSQuantifierZeroOrOne => Self::ZeroOrOne,
349 ffi::TSQuantifierZeroOrMore => Self::ZeroOrMore,
350 ffi::TSQuantifierOne => Self::One,
351 ffi::TSQuantifierOneOrMore => Self::OneOrMore,
352 _ => unreachable!(),
353 }
354 }
355}
356
357#[doc(alias = "TSQueryCursor")]
359pub struct QueryCursor {
360 ptr: NonNull<ffi::TSQueryCursor>,
361}
362
363#[derive(Debug, PartialEq, Eq)]
365pub struct QueryProperty {
366 pub key: Box<str>,
367 pub value: Option<Box<str>>,
368 pub capture_id: Option<usize>,
369}
370
371#[derive(Debug, PartialEq, Eq)]
372pub enum QueryPredicateArg {
373 Capture(u32),
374 String(Box<str>),
375}
376
377#[derive(Debug, PartialEq, Eq)]
379pub struct QueryPredicate {
380 pub operator: Box<str>,
381 pub args: Box<[QueryPredicateArg]>,
382}
383
384pub struct QueryMatch<'cursor, 'tree> {
386 pub pattern_index: usize,
387 pub captures: &'cursor [QueryCapture<'tree>],
388 id: u32,
389 cursor: *mut ffi::TSQueryCursor,
390}
391
392pub struct QueryMatches<'query, 'tree, T: TextProvider<I>, I: AsRef<[u8]>> {
394 ptr: *mut ffi::TSQueryCursor,
395 query: &'query Query,
396 text_provider: T,
397 buffer1: Vec<u8>,
398 buffer2: Vec<u8>,
399 current_match: Option<QueryMatch<'query, 'tree>>,
400 _options: Option<QueryCursorOptionsDrop>,
401 _phantom: PhantomData<(&'tree (), I)>,
402}
403
404pub struct QueryCaptures<'query, 'tree, T: TextProvider<I>, I: AsRef<[u8]>> {
409 ptr: *mut ffi::TSQueryCursor,
410 query: &'query Query,
411 text_provider: T,
412 buffer1: Vec<u8>,
413 buffer2: Vec<u8>,
414 current_match: Option<(QueryMatch<'query, 'tree>, usize)>,
415 _options: Option<QueryCursorOptionsDrop>,
416 _phantom: PhantomData<(&'tree (), I)>,
417}
418
419pub trait TextProvider<I>
420where
421 I: AsRef<[u8]>,
422{
423 type I: Iterator<Item = I>;
424 fn text(&mut self, node: Node) -> Self::I;
425}
426
427#[derive(Clone, Copy, Debug)]
430#[repr(C)]
431pub struct QueryCapture<'tree> {
432 pub node: Node<'tree>,
433 pub index: u32,
434}
435
436#[derive(Debug, PartialEq, Eq)]
439pub enum LanguageError {
440 Version(usize),
441}
442
443#[derive(Debug, PartialEq, Eq)]
445pub struct IncludedRangesError(pub usize);
446
447#[derive(Debug, PartialEq, Eq)]
449pub struct QueryError {
450 pub row: usize,
451 pub column: usize,
452 pub offset: usize,
453 pub message: String,
454 pub kind: QueryErrorKind,
455}
456
457#[derive(Debug, PartialEq, Eq)]
458pub enum QueryErrorKind {
459 Syntax,
460 NodeType,
461 Field,
462 Capture,
463 Predicate,
464 Structure,
465 Language,
466}
467
468#[derive(Debug)]
469enum TextPredicateCapture {
475 EqString(u32, Box<str>, bool, bool),
476 EqCapture(u32, u32, bool, bool),
477 MatchString(u32, regex::bytes::Regex, bool, bool),
478 AnyString(u32, Box<[Box<str>]>, bool),
479}
480
481pub struct LossyUtf8<'a> {
484 bytes: &'a [u8],
485 in_replacement: bool,
486}
487
488impl Language {
489 #[must_use]
490 pub fn new(builder: LanguageFn) -> Self {
491 Self(unsafe { builder.into_raw()().cast() })
492 }
493
494 #[doc(alias = "ts_language_name")]
496 #[must_use]
497 pub fn name(&self) -> Option<&'static str> {
498 let ptr = unsafe { ffi::ts_language_name(self.0) };
499 (!ptr.is_null()).then(|| unsafe { CStr::from_ptr(ptr) }.to_str().unwrap())
500 }
501
502 #[doc(alias = "ts_language_abi_version")]
505 #[must_use]
506 pub fn abi_version(&self) -> usize {
507 unsafe { ffi::ts_language_abi_version(self.0) as usize }
508 }
509
510 #[doc(alias = "ts_language_metadata")]
516 #[must_use]
517 pub fn metadata(&self) -> Option<LanguageMetadata> {
518 unsafe {
519 let ptr = ffi::ts_language_metadata(self.0);
520 (!ptr.is_null()).then(|| (*ptr).into())
521 }
522 }
523
524 #[doc(alias = "ts_language_symbol_count")]
526 #[must_use]
527 pub fn node_kind_count(&self) -> usize {
528 unsafe { ffi::ts_language_symbol_count(self.0) as usize }
529 }
530
531 #[doc(alias = "ts_language_state_count")]
533 #[must_use]
534 pub fn parse_state_count(&self) -> usize {
535 unsafe { ffi::ts_language_state_count(self.0) as usize }
536 }
537
538 #[doc(alias = "ts_language_supertypes")]
540 #[must_use]
541 pub fn supertypes(&self) -> &[u16] {
542 let mut length = 0u32;
543 unsafe {
544 let ptr = ffi::ts_language_supertypes(self.0, core::ptr::addr_of_mut!(length));
545 if length == 0 {
546 &[]
547 } else {
548 slice::from_raw_parts(ptr.cast_mut(), length as usize)
549 }
550 }
551 }
552
553 #[doc(alias = "ts_language_supertype_map")]
555 #[must_use]
556 pub fn subtypes_for_supertype(&self, supertype: u16) -> &[u16] {
557 unsafe {
558 let mut length = 0u32;
559 let ptr = ffi::ts_language_subtypes(self.0, supertype, core::ptr::addr_of_mut!(length));
560 if length == 0 {
561 &[]
562 } else {
563 slice::from_raw_parts(ptr.cast_mut(), length as usize)
564 }
565 }
566 }
567
568 #[doc(alias = "ts_language_symbol_name")]
570 #[must_use]
571 pub fn node_kind_for_id(&self, id: u16) -> Option<&'static str> {
572 let ptr = unsafe { ffi::ts_language_symbol_name(self.0, id) };
573 (!ptr.is_null()).then(|| unsafe { CStr::from_ptr(ptr) }.to_str().unwrap())
574 }
575
576 #[doc(alias = "ts_language_symbol_for_name")]
578 #[must_use]
579 pub fn id_for_node_kind(&self, kind: &str, named: bool) -> u16 {
580 unsafe {
581 ffi::ts_language_symbol_for_name(
582 self.0,
583 kind.as_bytes().as_ptr().cast::<c_char>(),
584 kind.len() as u32,
585 named,
586 )
587 }
588 }
589
590 #[must_use]
593 pub fn node_kind_is_named(&self, id: u16) -> bool {
594 unsafe { ffi::ts_language_symbol_type(self.0, id) == ffi::TSSymbolTypeRegular }
595 }
596
597 #[must_use]
600 pub fn node_kind_is_visible(&self, id: u16) -> bool {
601 unsafe { ffi::ts_language_symbol_type(self.0, id) <= ffi::TSSymbolTypeAnonymous }
602 }
603
604 #[must_use]
606 pub fn node_kind_is_supertype(&self, id: u16) -> bool {
607 unsafe { ffi::ts_language_symbol_type(self.0, id) == ffi::TSSymbolTypeSupertype }
608 }
609
610 #[doc(alias = "ts_language_field_count")]
612 #[must_use]
613 pub fn field_count(&self) -> usize {
614 unsafe { ffi::ts_language_field_count(self.0) as usize }
615 }
616
617 #[doc(alias = "ts_language_field_name_for_id")]
619 #[must_use]
620 pub fn field_name_for_id(&self, field_id: u16) -> Option<&'static str> {
621 let ptr = unsafe { ffi::ts_language_field_name_for_id(self.0, field_id) };
622 (!ptr.is_null()).then(|| unsafe { CStr::from_ptr(ptr) }.to_str().unwrap())
623 }
624
625 #[doc(alias = "ts_language_field_id_for_name")]
627 #[must_use]
628 pub fn field_id_for_name(&self, field_name: impl AsRef<[u8]>) -> Option<FieldId> {
629 let field_name = field_name.as_ref();
630 let id = unsafe {
631 ffi::ts_language_field_id_for_name(
632 self.0,
633 field_name.as_ptr().cast::<c_char>(),
634 field_name.len() as u32,
635 )
636 };
637 FieldId::new(id)
638 }
639
640 #[doc(alias = "ts_language_next_state")]
649 #[must_use]
650 pub fn next_state(&self, state: u16, id: u16) -> u16 {
651 unsafe { ffi::ts_language_next_state(self.0, state, id) }
652 }
653
654 #[doc(alias = "ts_lookahead_iterator_new")]
668 #[must_use]
669 pub fn lookahead_iterator(&self, state: u16) -> Option<LookaheadIterator> {
670 let ptr = unsafe { ffi::ts_lookahead_iterator_new(self.0, state) };
671 (!ptr.is_null()).then(|| unsafe { LookaheadIterator::from_raw(ptr) })
672 }
673}
674
675impl From<LanguageFn> for Language {
676 fn from(value: LanguageFn) -> Self {
677 Self::new(value)
678 }
679}
680
681impl Deref for LanguageRef<'_> {
682 type Target = Language;
683
684 fn deref(&self) -> &Self::Target {
685 unsafe { &*(core::ptr::addr_of!(self.0).cast::<Language>()) }
686 }
687}
688
689impl Default for Parser {
690 fn default() -> Self {
691 Self::new()
692 }
693}
694
695impl Parser {
696 #[doc(alias = "ts_parser_new")]
698 #[must_use]
699 pub fn new() -> Self {
700 unsafe {
701 let parser = ffi::ts_parser_new();
702 Self(NonNull::new_unchecked(parser))
703 }
704 }
705
706 #[doc(alias = "ts_parser_set_language")]
715 pub fn set_language(&mut self, language: &Language) -> Result<(), LanguageError> {
716 let version = language.abi_version();
717 if (MIN_COMPATIBLE_LANGUAGE_VERSION..=LANGUAGE_VERSION).contains(&version) {
718 unsafe { ffi::ts_parser_set_language(self.0.as_ptr(), language.0) };
719 Ok(())
720 } else {
721 Err(LanguageError::Version(version))
722 }
723 }
724
725 #[doc(alias = "ts_parser_language")]
727 #[must_use]
728 pub fn language(&self) -> Option<LanguageRef<'_>> {
729 let ptr = unsafe { ffi::ts_parser_language(self.0.as_ptr()) };
730 (!ptr.is_null()).then_some(LanguageRef(ptr, PhantomData))
731 }
732
733 #[doc(alias = "ts_parser_logger")]
735 #[must_use]
736 pub fn logger(&self) -> Option<&Logger> {
737 let logger = unsafe { ffi::ts_parser_logger(self.0.as_ptr()) };
738 unsafe { logger.payload.cast::<Logger>().as_ref() }
739 }
740
741 #[doc(alias = "ts_parser_set_logger")]
743 pub fn set_logger(&mut self, logger: Option<Logger>) {
744 let prev_logger = unsafe { ffi::ts_parser_logger(self.0.as_ptr()) };
745 if !prev_logger.payload.is_null() {
746 drop(unsafe { Box::from_raw(prev_logger.payload.cast::<Logger>()) });
747 }
748
749 let c_logger = if let Some(logger) = logger {
750 let container = Box::new(logger);
751
752 unsafe extern "C" fn log(
753 payload: *mut c_void,
754 c_log_type: ffi::TSLogType,
755 c_message: *const c_char,
756 ) {
757 let callback = payload.cast::<Logger>().as_mut().unwrap();
758 if let Ok(message) = CStr::from_ptr(c_message).to_str() {
759 let log_type = if c_log_type == ffi::TSLogTypeParse {
760 LogType::Parse
761 } else {
762 LogType::Lex
763 };
764 callback(log_type, message);
765 }
766 }
767
768 let raw_container = Box::into_raw(container);
769
770 ffi::TSLogger {
771 payload: raw_container.cast::<c_void>(),
772 log: Some(log),
773 }
774 } else {
775 ffi::TSLogger {
776 payload: ptr::null_mut(),
777 log: None,
778 }
779 };
780
781 unsafe { ffi::ts_parser_set_logger(self.0.as_ptr(), c_logger) };
782 }
783
784 #[doc(alias = "ts_parser_print_dot_graphs")]
789 #[cfg(not(target_os = "wasi"))]
790 #[cfg(feature = "std")]
791 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
792 pub fn print_dot_graphs(
793 &mut self,
794 #[cfg(unix)] file: &impl AsRawFd,
795 #[cfg(windows)] file: &impl AsRawHandle,
796 ) {
797 #[cfg(unix)]
798 {
799 let fd = file.as_raw_fd();
800 unsafe {
801 ffi::ts_parser_print_dot_graphs(self.0.as_ptr(), ffi::_ts_dup(fd));
802 }
803 }
804
805 #[cfg(windows)]
806 {
807 let handle = file.as_raw_handle();
808 unsafe {
809 ffi::ts_parser_print_dot_graphs(self.0.as_ptr(), ffi::_ts_dup(handle));
810 }
811 }
812 }
813
814 #[doc(alias = "ts_parser_print_dot_graphs")]
816 #[cfg(not(target_os = "wasi"))]
817 #[cfg(feature = "std")]
818 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
819 pub fn stop_printing_dot_graphs(&mut self) {
820 unsafe { ffi::ts_parser_print_dot_graphs(self.0.as_ptr(), -1) }
821 }
822
823 #[doc(alias = "ts_parser_parse")]
832 pub fn parse(&mut self, text: impl AsRef<[u8]>, old_tree: Option<&Tree>) -> Option<Tree> {
833 let bytes = text.as_ref();
834 let len = bytes.len();
835 self.parse_with_options(
836 &mut |i, _| (i < len).then(|| &bytes[i..]).unwrap_or_default(),
837 old_tree,
838 None,
839 )
840 }
841
842 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 match callback(&ParseState::from_raw(state)) {
867 ControlFlow::Continue(()) => false,
868 ControlFlow::Break(()) => true,
869 }
870 }
871
872 unsafe extern "C" fn read<T: AsRef<[u8]>, F: FnMut(usize, Point) -> T>(
874 payload: *mut c_void,
875 byte_offset: u32,
876 position: ffi::TSPoint,
877 bytes_read: *mut u32,
878 ) -> *const c_char {
879 let (callback, text) = payload.cast::<Payload<F, T>>().as_mut().unwrap();
880 *text = Some(callback(byte_offset as usize, position.into()));
881 let slice = text.as_ref().unwrap().as_ref();
882 *bytes_read = slice.len() as u32;
883 slice.as_ptr().cast::<c_char>()
884 }
885
886 let empty_options = ffi::TSParseOptions {
887 payload: ptr::null_mut(),
888 progress_callback: None,
889 };
890
891 let mut callback_ptr;
892 let parse_options = if let Some(options) = options {
893 if let Some(cb) = options.progress_callback {
894 callback_ptr = cb;
895 ffi::TSParseOptions {
896 payload: core::ptr::addr_of_mut!(callback_ptr).cast::<c_void>(),
897 progress_callback: Some(progress),
898 }
899 } else {
900 empty_options
901 }
902 } else {
903 empty_options
904 };
905
906 let mut payload: Payload<F, T> = (callback, None);
912
913 let c_input = ffi::TSInput {
914 payload: ptr::addr_of_mut!(payload).cast::<c_void>(),
915 read: Some(read::<T, F>),
916 encoding: ffi::TSInputEncodingUTF8,
917 decode: None,
918 };
919
920 let c_old_tree = old_tree.map_or(ptr::null_mut(), |t| t.0.as_ptr());
921 unsafe {
922 let c_new_tree = ffi::ts_parser_parse_with_options(
923 self.0.as_ptr(),
924 c_old_tree,
925 c_input,
926 parse_options,
927 );
928
929 NonNull::new(c_new_tree).map(Tree)
930 }
931 }
932
933 pub fn parse_utf16_le(
939 &mut self,
940 input: impl AsRef<[u16]>,
941 old_tree: Option<&Tree>,
942 ) -> Option<Tree> {
943 let code_points = input.as_ref();
944 let len = code_points.len();
945 self.parse_utf16_le_with_options(
946 &mut |i, _| (i < len).then(|| &code_points[i..]).unwrap_or_default(),
947 old_tree,
948 None,
949 )
950 }
951
952 pub fn parse_utf16_le_with_options<T: AsRef<[u16]>, F: FnMut(usize, Point) -> T>(
962 &mut self,
963 callback: &mut F,
964 old_tree: Option<&Tree>,
965 options: Option<ParseOptions>,
966 ) -> Option<Tree> {
967 type Payload<'a, F, T> = (&'a mut F, Option<T>);
968
969 unsafe extern "C" fn progress(state: *mut ffi::TSParseState) -> bool {
970 let callback = (*state)
971 .payload
972 .cast::<ParseProgressCallback>()
973 .as_mut()
974 .unwrap();
975 match callback(&ParseState::from_raw(state)) {
976 ControlFlow::Continue(()) => false,
977 ControlFlow::Break(()) => true,
978 }
979 }
980
981 unsafe extern "C" fn read<T: AsRef<[u16]>, F: FnMut(usize, Point) -> T>(
983 payload: *mut c_void,
984 byte_offset: u32,
985 position: ffi::TSPoint,
986 bytes_read: *mut u32,
987 ) -> *const c_char {
988 let (callback, text) = payload.cast::<Payload<F, T>>().as_mut().unwrap();
989 *text = Some(callback(
990 (byte_offset / 2) as usize,
991 Point {
992 row: position.row as usize,
993 column: position.column as usize / 2,
994 },
995 ));
996 let slice = text.as_ref().unwrap().as_ref();
997 *bytes_read = slice.len() as u32 * 2;
998 slice.as_ptr().cast::<c_char>()
999 }
1000
1001 let empty_options = ffi::TSParseOptions {
1002 payload: ptr::null_mut(),
1003 progress_callback: None,
1004 };
1005
1006 let mut callback_ptr;
1007 let parse_options = if let Some(options) = options {
1008 if let Some(cb) = options.progress_callback {
1009 callback_ptr = cb;
1010 ffi::TSParseOptions {
1011 payload: core::ptr::addr_of_mut!(callback_ptr).cast::<c_void>(),
1012 progress_callback: Some(progress),
1013 }
1014 } else {
1015 empty_options
1016 }
1017 } else {
1018 empty_options
1019 };
1020
1021 let mut payload: Payload<F, T> = (callback, None);
1027
1028 let c_input = ffi::TSInput {
1029 payload: core::ptr::addr_of_mut!(payload).cast::<c_void>(),
1030 read: Some(read::<T, F>),
1031 encoding: ffi::TSInputEncodingUTF16LE,
1032 decode: None,
1033 };
1034
1035 let c_old_tree = old_tree.map_or(ptr::null_mut(), |t| t.0.as_ptr());
1036 unsafe {
1037 let c_new_tree = ffi::ts_parser_parse_with_options(
1038 self.0.as_ptr(),
1039 c_old_tree,
1040 c_input,
1041 parse_options,
1042 );
1043
1044 NonNull::new(c_new_tree).map(Tree)
1045 }
1046 }
1047
1048 pub fn parse_utf16_be(
1054 &mut self,
1055 input: impl AsRef<[u16]>,
1056 old_tree: Option<&Tree>,
1057 ) -> Option<Tree> {
1058 let code_points = input.as_ref();
1059 let len = code_points.len();
1060 self.parse_utf16_be_with_options(
1061 &mut |i, _| if i < len { &code_points[i..] } else { &[] },
1062 old_tree,
1063 None,
1064 )
1065 }
1066
1067 pub fn parse_utf16_be_with_options<T: AsRef<[u16]>, F: FnMut(usize, Point) -> T>(
1077 &mut self,
1078 callback: &mut F,
1079 old_tree: Option<&Tree>,
1080 options: Option<ParseOptions>,
1081 ) -> Option<Tree> {
1082 type Payload<'a, F, T> = (&'a mut F, Option<T>);
1083
1084 unsafe extern "C" fn progress(state: *mut ffi::TSParseState) -> bool {
1086 let callback = (*state)
1087 .payload
1088 .cast::<ParseProgressCallback>()
1089 .as_mut()
1090 .unwrap();
1091 match callback(&ParseState::from_raw(state)) {
1092 ControlFlow::Continue(()) => false,
1093 ControlFlow::Break(()) => true,
1094 }
1095 }
1096
1097 unsafe extern "C" fn read<T: AsRef<[u16]>, F: FnMut(usize, Point) -> T>(
1099 payload: *mut c_void,
1100 byte_offset: u32,
1101 position: ffi::TSPoint,
1102 bytes_read: *mut u32,
1103 ) -> *const c_char {
1104 let (callback, text) = payload.cast::<Payload<F, T>>().as_mut().unwrap();
1105 *text = Some(callback(
1106 (byte_offset / 2) as usize,
1107 Point {
1108 row: position.row as usize,
1109 column: position.column as usize / 2,
1110 },
1111 ));
1112 let slice = text.as_ref().unwrap().as_ref();
1113 *bytes_read = slice.len() as u32 * 2;
1114 slice.as_ptr().cast::<c_char>()
1115 }
1116
1117 let empty_options = ffi::TSParseOptions {
1118 payload: ptr::null_mut(),
1119 progress_callback: None,
1120 };
1121
1122 let mut callback_ptr;
1123 let parse_options = if let Some(options) = options {
1124 if let Some(cb) = options.progress_callback {
1125 callback_ptr = cb;
1126 ffi::TSParseOptions {
1127 payload: core::ptr::addr_of_mut!(callback_ptr).cast::<c_void>(),
1128 progress_callback: Some(progress),
1129 }
1130 } else {
1131 empty_options
1132 }
1133 } else {
1134 empty_options
1135 };
1136
1137 let mut payload: Payload<F, T> = (callback, None);
1143
1144 let c_input = ffi::TSInput {
1145 payload: core::ptr::addr_of_mut!(payload).cast::<c_void>(),
1146 read: Some(read::<T, F>),
1147 encoding: ffi::TSInputEncodingUTF16BE,
1148 decode: None,
1149 };
1150
1151 let c_old_tree = old_tree.map_or(ptr::null_mut(), |t| t.0.as_ptr());
1152 unsafe {
1153 let c_new_tree = ffi::ts_parser_parse_with_options(
1154 self.0.as_ptr(),
1155 c_old_tree,
1156 c_input,
1157 parse_options,
1158 );
1159
1160 NonNull::new(c_new_tree).map(Tree)
1161 }
1162 }
1163
1164 pub fn parse_custom_encoding<D: Decode, T: AsRef<[u8]>, F: FnMut(usize, Point) -> T>(
1179 &mut self,
1180 callback: &mut F,
1181 old_tree: Option<&Tree>,
1182 options: Option<ParseOptions>,
1183 ) -> Option<Tree> {
1184 type Payload<'a, F, T> = (&'a mut F, Option<T>);
1185
1186 unsafe extern "C" fn progress(state: *mut ffi::TSParseState) -> bool {
1187 let callback = (*state)
1188 .payload
1189 .cast::<ParseProgressCallback>()
1190 .as_mut()
1191 .unwrap();
1192 match callback(&ParseState::from_raw(state)) {
1193 ControlFlow::Continue(()) => false,
1194 ControlFlow::Break(()) => true,
1195 }
1196 }
1197
1198 unsafe extern "C" fn decode_fn<D: Decode>(
1200 data: *const u8,
1201 len: u32,
1202 code_point: *mut i32,
1203 ) -> u32 {
1204 let (c, len) = D::decode(core::slice::from_raw_parts(data, len as usize));
1205 if let Some(code_point) = code_point.as_mut() {
1206 *code_point = c;
1207 }
1208 len
1209 }
1210
1211 unsafe extern "C" fn read<T: AsRef<[u8]>, F: FnMut(usize, Point) -> T>(
1213 payload: *mut c_void,
1214 byte_offset: u32,
1215 position: ffi::TSPoint,
1216 bytes_read: *mut u32,
1217 ) -> *const c_char {
1218 let (callback, text) = payload.cast::<Payload<F, T>>().as_mut().unwrap();
1219 *text = Some(callback(byte_offset as usize, position.into()));
1220 let slice = text.as_ref().unwrap().as_ref();
1221 *bytes_read = slice.len() as u32;
1222 slice.as_ptr().cast::<c_char>()
1223 }
1224
1225 let empty_options = ffi::TSParseOptions {
1226 payload: ptr::null_mut(),
1227 progress_callback: None,
1228 };
1229
1230 let mut callback_ptr;
1231 let parse_options = if let Some(options) = options {
1232 if let Some(cb) = options.progress_callback {
1233 callback_ptr = cb;
1234 ffi::TSParseOptions {
1235 payload: core::ptr::addr_of_mut!(callback_ptr).cast::<c_void>(),
1236 progress_callback: Some(progress),
1237 }
1238 } else {
1239 empty_options
1240 }
1241 } else {
1242 empty_options
1243 };
1244
1245 let mut payload: Payload<F, T> = (callback, None);
1251
1252 let c_input = ffi::TSInput {
1253 payload: core::ptr::addr_of_mut!(payload).cast::<c_void>(),
1254 read: Some(read::<T, F>),
1255 encoding: ffi::TSInputEncodingCustom,
1256 decode: Some(decode_fn::<D>),
1258 };
1259
1260 let c_old_tree = old_tree.map_or(ptr::null_mut(), |t| t.0.as_ptr());
1261 unsafe {
1262 let c_new_tree = ffi::ts_parser_parse_with_options(
1263 self.0.as_ptr(),
1264 c_old_tree,
1265 c_input,
1266 parse_options,
1267 );
1268
1269 NonNull::new(c_new_tree).map(Tree)
1270 }
1271 }
1272
1273 #[doc(alias = "ts_parser_reset")]
1280 pub fn reset(&mut self) {
1281 unsafe { ffi::ts_parser_reset(self.0.as_ptr()) }
1282 }
1283
1284 #[doc(alias = "ts_parser_set_included_ranges")]
1302 pub fn set_included_ranges(&mut self, ranges: &[Range]) -> Result<(), IncludedRangesError> {
1303 let ts_ranges = ranges.iter().copied().map(Into::into).collect::<Vec<_>>();
1304 let result = unsafe {
1305 ffi::ts_parser_set_included_ranges(
1306 self.0.as_ptr(),
1307 ts_ranges.as_ptr(),
1308 ts_ranges.len() as u32,
1309 )
1310 };
1311
1312 if result {
1313 Ok(())
1314 } else {
1315 let mut prev_end_byte = 0;
1316 for (i, range) in ranges.iter().enumerate() {
1317 if range.start_byte < prev_end_byte || range.end_byte < range.start_byte {
1318 return Err(IncludedRangesError(i));
1319 }
1320 prev_end_byte = range.end_byte;
1321 }
1322 Err(IncludedRangesError(0))
1323 }
1324 }
1325
1326 #[doc(alias = "ts_parser_included_ranges")]
1328 #[must_use]
1329 pub fn included_ranges(&self) -> Vec<Range> {
1330 let mut count = 0u32;
1331 unsafe {
1332 let ptr =
1333 ffi::ts_parser_included_ranges(self.0.as_ptr(), core::ptr::addr_of_mut!(count));
1334 let ranges = slice::from_raw_parts(ptr, count as usize);
1335 let result = ranges.iter().copied().map(Into::into).collect();
1336 result
1337 }
1338 }
1339}
1340
1341impl Drop for Parser {
1342 fn drop(&mut self) {
1343 #[cfg(feature = "std")]
1344 #[cfg(not(target_os = "wasi"))]
1345 {
1346 self.stop_printing_dot_graphs();
1347 }
1348 self.set_logger(None);
1349 unsafe { ffi::ts_parser_delete(self.0.as_ptr()) }
1350 }
1351}
1352
1353#[cfg(windows)]
1354extern "C" {
1355 fn _open_osfhandle(osfhandle: isize, flags: core::ffi::c_int) -> core::ffi::c_int;
1356}
1357
1358impl Tree {
1359 #[doc(alias = "ts_tree_root_node")]
1361 #[must_use]
1362 pub fn root_node(&self) -> Node {
1363 Node::new(unsafe { ffi::ts_tree_root_node(self.0.as_ptr()) }).unwrap()
1364 }
1365
1366 #[doc(alias = "ts_tree_root_node_with_offset")]
1369 #[must_use]
1370 pub fn root_node_with_offset(&self, offset_bytes: usize, offset_extent: Point) -> Node {
1371 Node::new(unsafe {
1372 ffi::ts_tree_root_node_with_offset(
1373 self.0.as_ptr(),
1374 offset_bytes as u32,
1375 offset_extent.into(),
1376 )
1377 })
1378 .unwrap()
1379 }
1380
1381 #[doc(alias = "ts_tree_language")]
1383 #[must_use]
1384 pub fn language(&self) -> LanguageRef {
1385 LanguageRef(
1386 unsafe { ffi::ts_tree_language(self.0.as_ptr()) },
1387 PhantomData,
1388 )
1389 }
1390
1391 #[doc(alias = "ts_tree_edit")]
1397 pub fn edit(&mut self, edit: &InputEdit) {
1398 let edit = edit.into();
1399 unsafe { ffi::ts_tree_edit(self.0.as_ptr(), &edit) };
1400 }
1401
1402 #[must_use]
1404 pub fn walk(&self) -> TreeCursor {
1405 self.root_node().walk()
1406 }
1407
1408 #[doc(alias = "ts_tree_get_changed_ranges")]
1416 #[must_use]
1417 pub fn changed_ranges(&self, other: &Self) -> impl ExactSizeIterator<Item = Range> {
1418 let mut count = 0u32;
1419 unsafe {
1420 let ptr = ffi::ts_tree_get_changed_ranges(
1421 self.0.as_ptr(),
1422 other.0.as_ptr(),
1423 core::ptr::addr_of_mut!(count),
1424 );
1425 util::CBufferIter::new(ptr, count as usize).map(Into::into)
1426 }
1427 }
1428
1429 #[doc(alias = "ts_tree_included_ranges")]
1431 #[must_use]
1432 pub fn included_ranges(&self) -> Vec<Range> {
1433 let mut count = 0u32;
1434 unsafe {
1435 let ptr = ffi::ts_tree_included_ranges(self.0.as_ptr(), core::ptr::addr_of_mut!(count));
1436 let ranges = slice::from_raw_parts(ptr, count as usize);
1437 let result = ranges.iter().copied().map(Into::into).collect();
1438 (FREE_FN)(ptr.cast::<c_void>());
1439 result
1440 }
1441 }
1442
1443 #[doc(alias = "ts_tree_print_dot_graph")]
1448 #[cfg(not(target_os = "wasi"))]
1449 #[cfg(feature = "std")]
1450 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
1451 pub fn print_dot_graph(
1452 &self,
1453 #[cfg(unix)] file: &impl AsRawFd,
1454 #[cfg(windows)] file: &impl AsRawHandle,
1455 ) {
1456 #[cfg(unix)]
1457 {
1458 let fd = file.as_raw_fd();
1459 unsafe { ffi::ts_tree_print_dot_graph(self.0.as_ptr(), fd) }
1460 }
1461
1462 #[cfg(windows)]
1463 {
1464 let handle = file.as_raw_handle();
1465 let fd = unsafe { _open_osfhandle(handle as isize, 0) };
1466 unsafe { ffi::ts_tree_print_dot_graph(self.0.as_ptr(), fd) }
1467 }
1468 }
1469}
1470
1471impl fmt::Debug for Tree {
1472 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1473 write!(f, "{{Tree {:?}}}", self.root_node())
1474 }
1475}
1476
1477impl Drop for Tree {
1478 fn drop(&mut self) {
1479 unsafe { ffi::ts_tree_delete(self.0.as_ptr()) }
1480 }
1481}
1482
1483impl Clone for Tree {
1484 fn clone(&self) -> Self {
1485 unsafe { Self(NonNull::new_unchecked(ffi::ts_tree_copy(self.0.as_ptr()))) }
1486 }
1487}
1488
1489impl<'tree> Node<'tree> {
1490 fn new(node: ffi::TSNode) -> Option<Self> {
1491 (!node.id.is_null()).then_some(Node(node, PhantomData))
1492 }
1493
1494 #[must_use]
1499 pub fn id(&self) -> usize {
1500 self.0.id as usize
1501 }
1502
1503 #[doc(alias = "ts_node_symbol")]
1505 #[must_use]
1506 pub fn kind_id(&self) -> u16 {
1507 unsafe { ffi::ts_node_symbol(self.0) }
1508 }
1509
1510 #[doc(alias = "ts_node_grammar_symbol")]
1513 #[must_use]
1514 pub fn grammar_id(&self) -> u16 {
1515 unsafe { ffi::ts_node_grammar_symbol(self.0) }
1516 }
1517
1518 #[doc(alias = "ts_node_type")]
1520 #[must_use]
1521 pub fn kind(&self) -> &'static str {
1522 unsafe { CStr::from_ptr(ffi::ts_node_type(self.0)) }
1523 .to_str()
1524 .unwrap()
1525 }
1526
1527 #[doc(alias = "ts_node_grammar_type")]
1530 #[must_use]
1531 pub fn grammar_name(&self) -> &'static str {
1532 unsafe { CStr::from_ptr(ffi::ts_node_grammar_type(self.0)) }
1533 .to_str()
1534 .unwrap()
1535 }
1536
1537 #[doc(alias = "ts_node_language")]
1539 #[must_use]
1540 pub fn language(&self) -> LanguageRef<'tree> {
1541 LanguageRef(unsafe { ffi::ts_node_language(self.0) }, PhantomData)
1542 }
1543
1544 #[doc(alias = "ts_node_is_named")]
1549 #[must_use]
1550 pub fn is_named(&self) -> bool {
1551 unsafe { ffi::ts_node_is_named(self.0) }
1552 }
1553
1554 #[doc(alias = "ts_node_is_extra")]
1559 #[must_use]
1560 pub fn is_extra(&self) -> bool {
1561 unsafe { ffi::ts_node_is_extra(self.0) }
1562 }
1563
1564 #[doc(alias = "ts_node_has_changes")]
1566 #[must_use]
1567 pub fn has_changes(&self) -> bool {
1568 unsafe { ffi::ts_node_has_changes(self.0) }
1569 }
1570
1571 #[doc(alias = "ts_node_has_error")]
1574 #[must_use]
1575 pub fn has_error(&self) -> bool {
1576 unsafe { ffi::ts_node_has_error(self.0) }
1577 }
1578
1579 #[doc(alias = "ts_node_is_error")]
1584 #[must_use]
1585 pub fn is_error(&self) -> bool {
1586 unsafe { ffi::ts_node_is_error(self.0) }
1587 }
1588
1589 #[doc(alias = "ts_node_parse_state")]
1591 #[must_use]
1592 pub fn parse_state(&self) -> u16 {
1593 unsafe { ffi::ts_node_parse_state(self.0) }
1594 }
1595
1596 #[doc(alias = "ts_node_next_parse_state")]
1598 #[must_use]
1599 pub fn next_parse_state(&self) -> u16 {
1600 unsafe { ffi::ts_node_next_parse_state(self.0) }
1601 }
1602
1603 #[doc(alias = "ts_node_is_missing")]
1608 #[must_use]
1609 pub fn is_missing(&self) -> bool {
1610 unsafe { ffi::ts_node_is_missing(self.0) }
1611 }
1612
1613 #[doc(alias = "ts_node_start_byte")]
1615 #[must_use]
1616 pub fn start_byte(&self) -> usize {
1617 unsafe { ffi::ts_node_start_byte(self.0) as usize }
1618 }
1619
1620 #[doc(alias = "ts_node_end_byte")]
1622 #[must_use]
1623 pub fn end_byte(&self) -> usize {
1624 unsafe { ffi::ts_node_end_byte(self.0) as usize }
1625 }
1626
1627 #[must_use]
1629 pub fn byte_range(&self) -> core::ops::Range<usize> {
1630 self.start_byte()..self.end_byte()
1631 }
1632
1633 #[must_use]
1636 pub fn range(&self) -> Range {
1637 Range {
1638 start_byte: self.start_byte(),
1639 end_byte: self.end_byte(),
1640 start_point: self.start_position(),
1641 end_point: self.end_position(),
1642 }
1643 }
1644
1645 #[doc(alias = "ts_node_start_point")]
1647 #[must_use]
1648 pub fn start_position(&self) -> Point {
1649 let result = unsafe { ffi::ts_node_start_point(self.0) };
1650 result.into()
1651 }
1652
1653 #[doc(alias = "ts_node_end_point")]
1655 #[must_use]
1656 pub fn end_position(&self) -> Point {
1657 let result = unsafe { ffi::ts_node_end_point(self.0) };
1658 result.into()
1659 }
1660
1661 #[doc(alias = "ts_node_child")]
1668 #[must_use]
1669 pub fn child(&self, i: u32) -> Option<Self> {
1670 Self::new(unsafe { ffi::ts_node_child(self.0, i) })
1671 }
1672
1673 #[doc(alias = "ts_node_child_count")]
1675 #[must_use]
1676 pub fn child_count(&self) -> usize {
1677 unsafe { ffi::ts_node_child_count(self.0) as usize }
1678 }
1679
1680 #[doc(alias = "ts_node_named_child")]
1687 #[must_use]
1688 pub fn named_child(&self, i: u32) -> Option<Self> {
1689 Self::new(unsafe { ffi::ts_node_named_child(self.0, i) })
1690 }
1691
1692 #[doc(alias = "ts_node_named_child_count")]
1696 #[must_use]
1697 pub fn named_child_count(&self) -> usize {
1698 unsafe { ffi::ts_node_named_child_count(self.0) as usize }
1699 }
1700
1701 #[doc(alias = "ts_node_child_by_field_name")]
1706 #[must_use]
1707 pub fn child_by_field_name(&self, field_name: impl AsRef<[u8]>) -> Option<Self> {
1708 let field_name = field_name.as_ref();
1709 Self::new(unsafe {
1710 ffi::ts_node_child_by_field_name(
1711 self.0,
1712 field_name.as_ptr().cast::<c_char>(),
1713 field_name.len() as u32,
1714 )
1715 })
1716 }
1717
1718 #[doc(alias = "ts_node_child_by_field_id")]
1723 #[must_use]
1724 pub fn child_by_field_id(&self, field_id: u16) -> Option<Self> {
1725 Self::new(unsafe { ffi::ts_node_child_by_field_id(self.0, field_id) })
1726 }
1727
1728 #[doc(alias = "ts_node_field_name_for_child")]
1730 #[must_use]
1731 pub fn field_name_for_child(&self, child_index: u32) -> Option<&'static str> {
1732 unsafe {
1733 let ptr = ffi::ts_node_field_name_for_child(self.0, child_index);
1734 (!ptr.is_null()).then(|| CStr::from_ptr(ptr).to_str().unwrap())
1735 }
1736 }
1737
1738 #[must_use]
1740 pub fn field_name_for_named_child(&self, named_child_index: u32) -> Option<&'static str> {
1741 unsafe {
1742 let ptr = ffi::ts_node_field_name_for_named_child(self.0, named_child_index);
1743 (!ptr.is_null()).then(|| CStr::from_ptr(ptr).to_str().unwrap())
1744 }
1745 }
1746
1747 pub fn children<'cursor>(
1757 &self,
1758 cursor: &'cursor mut TreeCursor<'tree>,
1759 ) -> impl ExactSizeIterator<Item = Node<'tree>> + 'cursor {
1760 cursor.reset(*self);
1761 cursor.goto_first_child();
1762 (0..self.child_count()).map(move |_| {
1763 let result = cursor.node();
1764 cursor.goto_next_sibling();
1765 result
1766 })
1767 }
1768
1769 pub fn named_children<'cursor>(
1773 &self,
1774 cursor: &'cursor mut TreeCursor<'tree>,
1775 ) -> impl ExactSizeIterator<Item = Node<'tree>> + 'cursor {
1776 cursor.reset(*self);
1777 cursor.goto_first_child();
1778 (0..self.named_child_count()).map(move |_| {
1779 while !cursor.node().is_named() {
1780 if !cursor.goto_next_sibling() {
1781 break;
1782 }
1783 }
1784 let result = cursor.node();
1785 cursor.goto_next_sibling();
1786 result
1787 })
1788 }
1789
1790 pub fn children_by_field_name<'cursor>(
1794 &self,
1795 field_name: &str,
1796 cursor: &'cursor mut TreeCursor<'tree>,
1797 ) -> impl Iterator<Item = Node<'tree>> + 'cursor {
1798 let field_id = self.language().field_id_for_name(field_name);
1799 let mut done = field_id.is_none();
1800 if !done {
1801 cursor.reset(*self);
1802 cursor.goto_first_child();
1803 }
1804 iter::from_fn(move || {
1805 if !done {
1806 while cursor.field_id() != field_id {
1807 if !cursor.goto_next_sibling() {
1808 return None;
1809 }
1810 }
1811 let result = cursor.node();
1812 if !cursor.goto_next_sibling() {
1813 done = true;
1814 }
1815 return Some(result);
1816 }
1817 None
1818 })
1819 }
1820
1821 pub fn children_by_field_id<'cursor>(
1825 &self,
1826 field_id: FieldId,
1827 cursor: &'cursor mut TreeCursor<'tree>,
1828 ) -> impl Iterator<Item = Node<'tree>> + 'cursor {
1829 cursor.reset(*self);
1830 cursor.goto_first_child();
1831 let mut done = false;
1832 iter::from_fn(move || {
1833 if !done {
1834 while cursor.field_id() != Some(field_id) {
1835 if !cursor.goto_next_sibling() {
1836 return None;
1837 }
1838 }
1839 let result = cursor.node();
1840 if !cursor.goto_next_sibling() {
1841 done = true;
1842 }
1843 return Some(result);
1844 }
1845 None
1846 })
1847 }
1848
1849 #[doc(alias = "ts_node_parent")]
1853 #[must_use]
1854 pub fn parent(&self) -> Option<Self> {
1855 Self::new(unsafe { ffi::ts_node_parent(self.0) })
1856 }
1857
1858 #[doc(alias = "ts_node_child_with_descendant")]
1862 #[must_use]
1863 pub fn child_with_descendant(&self, descendant: Self) -> Option<Self> {
1864 Self::new(unsafe { ffi::ts_node_child_with_descendant(self.0, descendant.0) })
1865 }
1866
1867 #[doc(alias = "ts_node_next_sibling")]
1869 #[must_use]
1870 pub fn next_sibling(&self) -> Option<Self> {
1871 Self::new(unsafe { ffi::ts_node_next_sibling(self.0) })
1872 }
1873
1874 #[doc(alias = "ts_node_prev_sibling")]
1876 #[must_use]
1877 pub fn prev_sibling(&self) -> Option<Self> {
1878 Self::new(unsafe { ffi::ts_node_prev_sibling(self.0) })
1879 }
1880
1881 #[doc(alias = "ts_node_next_named_sibling")]
1883 #[must_use]
1884 pub fn next_named_sibling(&self) -> Option<Self> {
1885 Self::new(unsafe { ffi::ts_node_next_named_sibling(self.0) })
1886 }
1887
1888 #[doc(alias = "ts_node_prev_named_sibling")]
1890 #[must_use]
1891 pub fn prev_named_sibling(&self) -> Option<Self> {
1892 Self::new(unsafe { ffi::ts_node_prev_named_sibling(self.0) })
1893 }
1894
1895 #[doc(alias = "ts_node_first_child_for_byte")]
1897 #[must_use]
1898 pub fn first_child_for_byte(&self, byte: usize) -> Option<Self> {
1899 Self::new(unsafe { ffi::ts_node_first_child_for_byte(self.0, byte as u32) })
1900 }
1901
1902 #[doc(alias = "ts_node_first_named_child_for_point")]
1904 #[must_use]
1905 pub fn first_named_child_for_byte(&self, byte: usize) -> Option<Self> {
1906 Self::new(unsafe { ffi::ts_node_first_named_child_for_byte(self.0, byte as u32) })
1907 }
1908
1909 #[doc(alias = "ts_node_descendant_count")]
1911 #[must_use]
1912 pub fn descendant_count(&self) -> usize {
1913 unsafe { ffi::ts_node_descendant_count(self.0) as usize }
1914 }
1915
1916 #[doc(alias = "ts_node_descendant_for_byte_range")]
1918 #[must_use]
1919 pub fn descendant_for_byte_range(&self, start: usize, end: usize) -> Option<Self> {
1920 Self::new(unsafe {
1921 ffi::ts_node_descendant_for_byte_range(self.0, start as u32, end as u32)
1922 })
1923 }
1924
1925 #[doc(alias = "ts_node_named_descendant_for_byte_range")]
1927 #[must_use]
1928 pub fn named_descendant_for_byte_range(&self, start: usize, end: usize) -> Option<Self> {
1929 Self::new(unsafe {
1930 ffi::ts_node_named_descendant_for_byte_range(self.0, start as u32, end as u32)
1931 })
1932 }
1933
1934 #[doc(alias = "ts_node_descendant_for_point_range")]
1936 #[must_use]
1937 pub fn descendant_for_point_range(&self, start: Point, end: Point) -> Option<Self> {
1938 Self::new(unsafe {
1939 ffi::ts_node_descendant_for_point_range(self.0, start.into(), end.into())
1940 })
1941 }
1942
1943 #[doc(alias = "ts_node_named_descendant_for_point_range")]
1945 #[must_use]
1946 pub fn named_descendant_for_point_range(&self, start: Point, end: Point) -> Option<Self> {
1947 Self::new(unsafe {
1948 ffi::ts_node_named_descendant_for_point_range(self.0, start.into(), end.into())
1949 })
1950 }
1951
1952 #[doc(alias = "ts_node_string")]
1954 #[must_use]
1955 pub fn to_sexp(&self) -> String {
1956 let c_string = unsafe { ffi::ts_node_string(self.0) };
1957 let result = unsafe { CStr::from_ptr(c_string) }
1958 .to_str()
1959 .unwrap()
1960 .to_string();
1961 unsafe { (FREE_FN)(c_string.cast::<c_void>()) };
1962 result
1963 }
1964
1965 pub fn utf8_text<'a>(&self, source: &'a [u8]) -> Result<&'a str, str::Utf8Error> {
1966 str::from_utf8(&source[self.start_byte()..self.end_byte()])
1967 }
1968
1969 #[must_use]
1970 pub fn utf16_text<'a>(&self, source: &'a [u16]) -> &'a [u16] {
1971 &source[self.start_byte() / 2..self.end_byte() / 2]
1972 }
1973
1974 #[doc(alias = "ts_tree_cursor_new")]
1979 #[must_use]
1980 pub fn walk(&self) -> TreeCursor<'tree> {
1981 TreeCursor(unsafe { ffi::ts_tree_cursor_new(self.0) }, PhantomData)
1982 }
1983
1984 #[doc(alias = "ts_node_edit")]
1992 pub fn edit(&mut self, edit: &InputEdit) {
1993 let edit = edit.into();
1994 unsafe { ffi::ts_node_edit(core::ptr::addr_of_mut!(self.0), &edit) }
1995 }
1996}
1997
1998impl PartialEq for Node<'_> {
1999 fn eq(&self, other: &Self) -> bool {
2000 core::ptr::eq(self.0.id, other.0.id)
2001 }
2002}
2003
2004impl Eq for Node<'_> {}
2005
2006impl hash::Hash for Node<'_> {
2007 fn hash<H: hash::Hasher>(&self, state: &mut H) {
2008 self.0.id.hash(state);
2009 self.0.context[0].hash(state);
2010 self.0.context[1].hash(state);
2011 self.0.context[2].hash(state);
2012 self.0.context[3].hash(state);
2013 }
2014}
2015
2016impl fmt::Debug for Node<'_> {
2017 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2018 write!(
2019 f,
2020 "{{Node {} {} - {}}}",
2021 self.kind(),
2022 self.start_position(),
2023 self.end_position()
2024 )
2025 }
2026}
2027
2028impl fmt::Display for Node<'_> {
2029 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2030 let sexp = self.to_sexp();
2031 if sexp.is_empty() {
2032 write!(f, "")
2033 } else if !f.alternate() {
2034 write!(f, "{sexp}")
2035 } else {
2036 write!(f, "{}", format_sexp(&sexp, f.width().unwrap_or(0)))
2037 }
2038 }
2039}
2040
2041impl<'tree> TreeCursor<'tree> {
2042 #[doc(alias = "ts_tree_cursor_current_node")]
2044 #[must_use]
2045 pub fn node(&self) -> Node<'tree> {
2046 Node(
2047 unsafe { ffi::ts_tree_cursor_current_node(&self.0) },
2048 PhantomData,
2049 )
2050 }
2051
2052 #[doc(alias = "ts_tree_cursor_current_field_id")]
2056 #[must_use]
2057 pub fn field_id(&self) -> Option<FieldId> {
2058 let id = unsafe { ffi::ts_tree_cursor_current_field_id(&self.0) };
2059 FieldId::new(id)
2060 }
2061
2062 #[doc(alias = "ts_tree_cursor_current_field_name")]
2064 #[must_use]
2065 pub fn field_name(&self) -> Option<&'static str> {
2066 unsafe {
2067 let ptr = ffi::ts_tree_cursor_current_field_name(&self.0);
2068 (!ptr.is_null()).then(|| CStr::from_ptr(ptr).to_str().unwrap())
2069 }
2070 }
2071
2072 #[doc(alias = "ts_tree_cursor_current_depth")]
2075 #[must_use]
2076 pub fn depth(&self) -> u32 {
2077 unsafe { ffi::ts_tree_cursor_current_depth(&self.0) }
2078 }
2079
2080 #[doc(alias = "ts_tree_cursor_current_descendant_index")]
2083 #[must_use]
2084 pub fn descendant_index(&self) -> usize {
2085 unsafe { ffi::ts_tree_cursor_current_descendant_index(&self.0) as usize }
2086 }
2087
2088 #[doc(alias = "ts_tree_cursor_goto_first_child")]
2093 pub fn goto_first_child(&mut self) -> bool {
2094 unsafe { ffi::ts_tree_cursor_goto_first_child(&mut self.0) }
2095 }
2096
2097 #[doc(alias = "ts_tree_cursor_goto_last_child")]
2106 pub fn goto_last_child(&mut self) -> bool {
2107 unsafe { ffi::ts_tree_cursor_goto_last_child(&mut self.0) }
2108 }
2109
2110 #[doc(alias = "ts_tree_cursor_goto_parent")]
2119 pub fn goto_parent(&mut self) -> bool {
2120 unsafe { ffi::ts_tree_cursor_goto_parent(&mut self.0) }
2121 }
2122
2123 #[doc(alias = "ts_tree_cursor_goto_next_sibling")]
2131 pub fn goto_next_sibling(&mut self) -> bool {
2132 unsafe { ffi::ts_tree_cursor_goto_next_sibling(&mut self.0) }
2133 }
2134
2135 #[doc(alias = "ts_tree_cursor_goto_descendant")]
2139 pub fn goto_descendant(&mut self, descendant_index: usize) {
2140 unsafe { ffi::ts_tree_cursor_goto_descendant(&mut self.0, descendant_index as u32) }
2141 }
2142
2143 #[doc(alias = "ts_tree_cursor_goto_previous_sibling")]
2155 pub fn goto_previous_sibling(&mut self) -> bool {
2156 unsafe { ffi::ts_tree_cursor_goto_previous_sibling(&mut self.0) }
2157 }
2158
2159 #[doc(alias = "ts_tree_cursor_goto_first_child_for_byte")]
2165 pub fn goto_first_child_for_byte(&mut self, index: usize) -> Option<usize> {
2166 let result =
2167 unsafe { ffi::ts_tree_cursor_goto_first_child_for_byte(&mut self.0, index as u32) };
2168 result.try_into().ok()
2169 }
2170
2171 #[doc(alias = "ts_tree_cursor_goto_first_child_for_point")]
2177 pub fn goto_first_child_for_point(&mut self, point: Point) -> Option<usize> {
2178 let result =
2179 unsafe { ffi::ts_tree_cursor_goto_first_child_for_point(&mut self.0, point.into()) };
2180 result.try_into().ok()
2181 }
2182
2183 #[doc(alias = "ts_tree_cursor_reset")]
2186 pub fn reset(&mut self, node: Node<'tree>) {
2187 unsafe { ffi::ts_tree_cursor_reset(&mut self.0, node.0) };
2188 }
2189
2190 #[doc(alias = "ts_tree_cursor_reset_to")]
2195 pub fn reset_to(&mut self, cursor: &Self) {
2196 unsafe { ffi::ts_tree_cursor_reset_to(&mut self.0, &cursor.0) };
2197 }
2198}
2199
2200impl Clone for TreeCursor<'_> {
2201 fn clone(&self) -> Self {
2202 TreeCursor(unsafe { ffi::ts_tree_cursor_copy(&self.0) }, PhantomData)
2203 }
2204}
2205
2206impl Drop for TreeCursor<'_> {
2207 fn drop(&mut self) {
2208 unsafe { ffi::ts_tree_cursor_delete(&mut self.0) }
2209 }
2210}
2211
2212impl LookaheadIterator {
2213 #[doc(alias = "ts_lookahead_iterator_language")]
2215 #[must_use]
2216 pub fn language(&self) -> LanguageRef<'_> {
2217 LanguageRef(
2218 unsafe { ffi::ts_lookahead_iterator_language(self.0.as_ptr()) },
2219 PhantomData,
2220 )
2221 }
2222
2223 #[doc(alias = "ts_lookahead_iterator_current_symbol")]
2225 #[must_use]
2226 pub fn current_symbol(&self) -> u16 {
2227 unsafe { ffi::ts_lookahead_iterator_current_symbol(self.0.as_ptr()) }
2228 }
2229
2230 #[doc(alias = "ts_lookahead_iterator_current_symbol_name")]
2232 #[must_use]
2233 pub fn current_symbol_name(&self) -> &'static str {
2234 unsafe {
2235 CStr::from_ptr(ffi::ts_lookahead_iterator_current_symbol_name(
2236 self.0.as_ptr(),
2237 ))
2238 .to_str()
2239 .unwrap()
2240 }
2241 }
2242
2243 #[doc(alias = "ts_lookahead_iterator_reset")]
2248 pub fn reset(&mut self, language: &Language, state: u16) -> bool {
2249 unsafe { ffi::ts_lookahead_iterator_reset(self.0.as_ptr(), language.0, state) }
2250 }
2251
2252 #[doc(alias = "ts_lookahead_iterator_reset_state")]
2257 pub fn reset_state(&mut self, state: u16) -> bool {
2258 unsafe { ffi::ts_lookahead_iterator_reset_state(self.0.as_ptr(), state) }
2259 }
2260
2261 pub fn iter_names(&mut self) -> impl Iterator<Item = &'static str> + '_ {
2263 LookaheadNamesIterator(self)
2264 }
2265}
2266
2267impl Iterator for LookaheadNamesIterator<'_> {
2268 type Item = &'static str;
2269
2270 #[doc(alias = "ts_lookahead_iterator_next")]
2271 fn next(&mut self) -> Option<Self::Item> {
2272 unsafe { ffi::ts_lookahead_iterator_next(self.0 .0.as_ptr()) }
2273 .then(|| self.0.current_symbol_name())
2274 }
2275}
2276
2277impl Iterator for LookaheadIterator {
2278 type Item = u16;
2279
2280 #[doc(alias = "ts_lookahead_iterator_next")]
2281 fn next(&mut self) -> Option<Self::Item> {
2282 unsafe { ffi::ts_lookahead_iterator_next(self.0.as_ptr()) }.then(|| self.current_symbol())
2284 }
2285}
2286
2287impl Drop for LookaheadIterator {
2288 #[doc(alias = "ts_lookahead_iterator_delete")]
2289 fn drop(&mut self) {
2290 unsafe { ffi::ts_lookahead_iterator_delete(self.0.as_ptr()) }
2291 }
2292}
2293
2294impl Query {
2295 pub fn new(language: &Language, source: &str) -> Result<Self, QueryError> {
2302 let ptr = Self::new_raw(language, source)?;
2303 unsafe { Self::from_raw_parts(ptr, source) }
2304 }
2305
2306 pub fn new_raw(language: &Language, source: &str) -> Result<*mut ffi::TSQuery, QueryError> {
2312 let mut error_offset = 0u32;
2313 let mut error_type: ffi::TSQueryError = 0;
2314 let bytes = source.as_bytes();
2315
2316 let ptr = unsafe {
2318 ffi::ts_query_new(
2319 language.0,
2320 bytes.as_ptr().cast::<c_char>(),
2321 bytes.len() as u32,
2322 core::ptr::addr_of_mut!(error_offset),
2323 core::ptr::addr_of_mut!(error_type),
2324 )
2325 };
2326
2327 if !ptr.is_null() {
2328 return Ok(ptr);
2329 }
2330
2331 if error_type == ffi::TSQueryErrorLanguage {
2333 return Err(QueryError {
2334 row: 0,
2335 column: 0,
2336 offset: 0,
2337 message: LanguageError::Version(language.abi_version()).to_string(),
2338 kind: QueryErrorKind::Language,
2339 });
2340 }
2341
2342 let offset = error_offset as usize;
2343 let mut line_start = 0;
2344 let mut row = 0;
2345 let mut line_containing_error = None;
2346 for line in source.lines() {
2347 let line_end = line_start + line.len() + 1;
2348 if line_end > offset {
2349 line_containing_error = Some(line);
2350 break;
2351 }
2352 line_start = line_end;
2353 row += 1;
2354 }
2355 let column = offset - line_start;
2356
2357 let kind;
2358 let message;
2359 match error_type {
2360 ffi::TSQueryErrorNodeType | ffi::TSQueryErrorField | ffi::TSQueryErrorCapture => {
2362 let suffix = source.split_at(offset).1;
2363 let in_quotes = offset > 0 && source.as_bytes()[offset - 1] == b'"';
2364 let mut backslashes = 0;
2365 let end_offset = suffix
2366 .find(|c| {
2367 if in_quotes {
2368 if c == '"' && backslashes % 2 == 0 {
2369 true
2370 } else if c == '\\' {
2371 backslashes += 1;
2372 false
2373 } else {
2374 backslashes = 0;
2375 false
2376 }
2377 } else {
2378 !char::is_alphanumeric(c) && c != '_' && c != '-'
2379 }
2380 })
2381 .unwrap_or(suffix.len());
2382 message = format!("\"{}\"", suffix.split_at(end_offset).0);
2383 kind = match error_type {
2384 ffi::TSQueryErrorNodeType => QueryErrorKind::NodeType,
2385 ffi::TSQueryErrorField => QueryErrorKind::Field,
2386 ffi::TSQueryErrorCapture => QueryErrorKind::Capture,
2387 _ => unreachable!(),
2388 };
2389 }
2390
2391 _ => {
2393 message = line_containing_error.map_or_else(
2394 || "Unexpected EOF".to_string(),
2395 |line| line.to_string() + "\n" + &" ".repeat(offset - line_start) + "^",
2396 );
2397 kind = match error_type {
2398 ffi::TSQueryErrorStructure => QueryErrorKind::Structure,
2399 _ => QueryErrorKind::Syntax,
2400 };
2401 }
2402 }
2403
2404 Err(QueryError {
2405 row,
2406 column,
2407 offset,
2408 message,
2409 kind,
2410 })
2411 }
2412
2413 #[doc(hidden)]
2414 unsafe fn from_raw_parts(ptr: *mut ffi::TSQuery, source: &str) -> Result<Self, QueryError> {
2415 let ptr = {
2416 struct TSQueryDrop(*mut ffi::TSQuery);
2417 impl Drop for TSQueryDrop {
2418 fn drop(&mut self) {
2419 unsafe { ffi::ts_query_delete(self.0) }
2420 }
2421 }
2422 TSQueryDrop(ptr)
2423 };
2424
2425 let string_count = unsafe { ffi::ts_query_string_count(ptr.0) };
2426 let capture_count = unsafe { ffi::ts_query_capture_count(ptr.0) };
2427 let pattern_count = unsafe { ffi::ts_query_pattern_count(ptr.0) as usize };
2428
2429 let mut capture_names = Vec::with_capacity(capture_count as usize);
2430 let mut capture_quantifiers_vec = Vec::with_capacity(pattern_count);
2431 let mut text_predicates_vec = Vec::with_capacity(pattern_count);
2432 let mut property_predicates_vec = Vec::with_capacity(pattern_count);
2433 let mut property_settings_vec = Vec::with_capacity(pattern_count);
2434 let mut general_predicates_vec = Vec::with_capacity(pattern_count);
2435
2436 for i in 0..capture_count {
2438 unsafe {
2439 let mut length = 0u32;
2440 let name =
2441 ffi::ts_query_capture_name_for_id(ptr.0, i, core::ptr::addr_of_mut!(length))
2442 .cast::<u8>();
2443 let name = slice::from_raw_parts(name, length as usize);
2444 let name = str::from_utf8_unchecked(name);
2445 capture_names.push(name);
2446 }
2447 }
2448
2449 for i in 0..pattern_count {
2451 let mut capture_quantifiers = Vec::with_capacity(capture_count as usize);
2452 for j in 0..capture_count {
2453 unsafe {
2454 let quantifier = ffi::ts_query_capture_quantifier_for_id(ptr.0, i as u32, j);
2455 capture_quantifiers.push(quantifier.into());
2456 }
2457 }
2458 capture_quantifiers_vec.push(capture_quantifiers.into());
2459 }
2460
2461 let string_values = (0..string_count)
2463 .map(|i| unsafe {
2464 let mut length = 0u32;
2465 let value =
2466 ffi::ts_query_string_value_for_id(ptr.0, i, core::ptr::addr_of_mut!(length))
2467 .cast::<u8>();
2468 let value = slice::from_raw_parts(value, length as usize);
2469 let value = str::from_utf8_unchecked(value);
2470 value
2471 })
2472 .collect::<Vec<_>>();
2473
2474 for i in 0..pattern_count {
2476 let predicate_steps = unsafe {
2477 let mut length = 0u32;
2478 let raw_predicates = ffi::ts_query_predicates_for_pattern(
2479 ptr.0,
2480 i as u32,
2481 core::ptr::addr_of_mut!(length),
2482 );
2483 (length > 0)
2484 .then(|| slice::from_raw_parts(raw_predicates, length as usize))
2485 .unwrap_or_default()
2486 };
2487
2488 let byte_offset = unsafe { ffi::ts_query_start_byte_for_pattern(ptr.0, i as u32) };
2489 let row = source
2490 .char_indices()
2491 .take_while(|(i, _)| *i < byte_offset as usize)
2492 .filter(|(_, c)| *c == '\n')
2493 .count();
2494
2495 use ffi::TSQueryPredicateStepType as T;
2496 const TYPE_DONE: T = ffi::TSQueryPredicateStepTypeDone;
2497 const TYPE_CAPTURE: T = ffi::TSQueryPredicateStepTypeCapture;
2498 const TYPE_STRING: T = ffi::TSQueryPredicateStepTypeString;
2499
2500 let mut text_predicates = Vec::new();
2501 let mut property_predicates = Vec::new();
2502 let mut property_settings = Vec::new();
2503 let mut general_predicates = Vec::new();
2504 for p in predicate_steps.split(|s| s.type_ == TYPE_DONE) {
2505 if p.is_empty() {
2506 continue;
2507 }
2508
2509 if p[0].type_ != TYPE_STRING {
2510 return Err(predicate_error(
2511 row,
2512 format!(
2513 "Expected predicate to start with a function name. Got @{}.",
2514 capture_names[p[0].value_id as usize],
2515 ),
2516 ));
2517 }
2518
2519 let operator_name = string_values[p[0].value_id as usize];
2521 match operator_name {
2522 "eq?" | "not-eq?" | "any-eq?" | "any-not-eq?" => {
2523 if p.len() != 3 {
2524 return Err(predicate_error(
2525 row,
2526 format!(
2527 "Wrong number of arguments to #eq? predicate. Expected 2, got {}.",
2528 p.len() - 1
2529 ),
2530 ));
2531 }
2532 if p[1].type_ != TYPE_CAPTURE {
2533 return Err(predicate_error(row, format!(
2534 "First argument to #eq? predicate must be a capture name. Got literal \"{}\".",
2535 string_values[p[1].value_id as usize],
2536 )));
2537 }
2538
2539 let is_positive = operator_name == "eq?" || operator_name == "any-eq?";
2540 let match_all = match operator_name {
2541 "eq?" | "not-eq?" => true,
2542 "any-eq?" | "any-not-eq?" => false,
2543 _ => unreachable!(),
2544 };
2545 text_predicates.push(if p[2].type_ == TYPE_CAPTURE {
2546 TextPredicateCapture::EqCapture(
2547 p[1].value_id,
2548 p[2].value_id,
2549 is_positive,
2550 match_all,
2551 )
2552 } else {
2553 TextPredicateCapture::EqString(
2554 p[1].value_id,
2555 string_values[p[2].value_id as usize].to_string().into(),
2556 is_positive,
2557 match_all,
2558 )
2559 });
2560 }
2561
2562 "match?" | "not-match?" | "any-match?" | "any-not-match?" => {
2563 if p.len() != 3 {
2564 return Err(predicate_error(row, format!(
2565 "Wrong number of arguments to #match? predicate. Expected 2, got {}.",
2566 p.len() - 1
2567 )));
2568 }
2569 if p[1].type_ != TYPE_CAPTURE {
2570 return Err(predicate_error(row, format!(
2571 "First argument to #match? predicate must be a capture name. Got literal \"{}\".",
2572 string_values[p[1].value_id as usize],
2573 )));
2574 }
2575 if p[2].type_ == TYPE_CAPTURE {
2576 return Err(predicate_error(row, format!(
2577 "Second argument to #match? predicate must be a literal. Got capture @{}.",
2578 capture_names[p[2].value_id as usize],
2579 )));
2580 }
2581
2582 let is_positive =
2583 operator_name == "match?" || operator_name == "any-match?";
2584 let match_all = match operator_name {
2585 "match?" | "not-match?" => true,
2586 "any-match?" | "any-not-match?" => false,
2587 _ => unreachable!(),
2588 };
2589 let regex = &string_values[p[2].value_id as usize];
2590 text_predicates.push(TextPredicateCapture::MatchString(
2591 p[1].value_id,
2592 regex::bytes::Regex::new(regex).map_err(|_| {
2593 predicate_error(row, format!("Invalid regex '{regex}'"))
2594 })?,
2595 is_positive,
2596 match_all,
2597 ));
2598 }
2599
2600 "set!" => property_settings.push(Self::parse_property(
2601 row,
2602 operator_name,
2603 &capture_names,
2604 &string_values,
2605 &p[1..],
2606 )?),
2607
2608 "is?" | "is-not?" => property_predicates.push((
2609 Self::parse_property(
2610 row,
2611 operator_name,
2612 &capture_names,
2613 &string_values,
2614 &p[1..],
2615 )?,
2616 operator_name == "is?",
2617 )),
2618
2619 "any-of?" | "not-any-of?" => {
2620 if p.len() < 2 {
2621 return Err(predicate_error(row, format!(
2622 "Wrong number of arguments to #any-of? predicate. Expected at least 1, got {}.",
2623 p.len() - 1
2624 )));
2625 }
2626 if p[1].type_ != TYPE_CAPTURE {
2627 return Err(predicate_error(row, format!(
2628 "First argument to #any-of? predicate must be a capture name. Got literal \"{}\".",
2629 string_values[p[1].value_id as usize],
2630 )));
2631 }
2632
2633 let is_positive = operator_name == "any-of?";
2634 let mut values = Vec::new();
2635 for arg in &p[2..] {
2636 if arg.type_ == TYPE_CAPTURE {
2637 return Err(predicate_error(row, format!(
2638 "Arguments to #any-of? predicate must be literals. Got capture @{}.",
2639 capture_names[arg.value_id as usize],
2640 )));
2641 }
2642 values.push(string_values[arg.value_id as usize]);
2643 }
2644 text_predicates.push(TextPredicateCapture::AnyString(
2645 p[1].value_id,
2646 values
2647 .iter()
2648 .map(|x| (*x).to_string().into())
2649 .collect::<Vec<_>>()
2650 .into(),
2651 is_positive,
2652 ));
2653 }
2654
2655 _ => general_predicates.push(QueryPredicate {
2656 operator: operator_name.to_string().into(),
2657 args: p[1..]
2658 .iter()
2659 .map(|a| {
2660 if a.type_ == TYPE_CAPTURE {
2661 QueryPredicateArg::Capture(a.value_id)
2662 } else {
2663 QueryPredicateArg::String(
2664 string_values[a.value_id as usize].to_string().into(),
2665 )
2666 }
2667 })
2668 .collect(),
2669 }),
2670 }
2671 }
2672
2673 text_predicates_vec.push(text_predicates.into());
2674 property_predicates_vec.push(property_predicates.into());
2675 property_settings_vec.push(property_settings.into());
2676 general_predicates_vec.push(general_predicates.into());
2677 }
2678
2679 let result = Self {
2680 ptr: unsafe { NonNull::new_unchecked(ptr.0) },
2681 capture_names: capture_names.into(),
2682 capture_quantifiers: capture_quantifiers_vec.into(),
2683 text_predicates: text_predicates_vec.into(),
2684 property_predicates: property_predicates_vec.into(),
2685 property_settings: property_settings_vec.into(),
2686 general_predicates: general_predicates_vec.into(),
2687 };
2688
2689 core::mem::forget(ptr);
2690
2691 Ok(result)
2692 }
2693
2694 #[doc(alias = "ts_query_start_byte_for_pattern")]
2697 #[must_use]
2698 pub fn start_byte_for_pattern(&self, pattern_index: usize) -> usize {
2699 assert!(
2700 pattern_index < self.text_predicates.len(),
2701 "Pattern index is {pattern_index} but the pattern count is {}",
2702 self.text_predicates.len(),
2703 );
2704 unsafe {
2705 ffi::ts_query_start_byte_for_pattern(self.ptr.as_ptr(), pattern_index as u32) as usize
2706 }
2707 }
2708
2709 #[doc(alias = "ts_query_end_byte_for_pattern")]
2712 #[must_use]
2713 pub fn end_byte_for_pattern(&self, pattern_index: usize) -> usize {
2714 assert!(
2715 pattern_index < self.text_predicates.len(),
2716 "Pattern index is {pattern_index} but the pattern count is {}",
2717 self.text_predicates.len(),
2718 );
2719 unsafe {
2720 ffi::ts_query_end_byte_for_pattern(self.ptr.as_ptr(), pattern_index as u32) as usize
2721 }
2722 }
2723
2724 #[doc(alias = "ts_query_pattern_count")]
2726 #[must_use]
2727 pub fn pattern_count(&self) -> usize {
2728 unsafe { ffi::ts_query_pattern_count(self.ptr.as_ptr()) as usize }
2729 }
2730
2731 #[must_use]
2733 pub const fn capture_names(&self) -> &[&str] {
2734 &self.capture_names
2735 }
2736
2737 #[must_use]
2739 pub const fn capture_quantifiers(&self, index: usize) -> &[CaptureQuantifier] {
2740 &self.capture_quantifiers[index]
2741 }
2742
2743 #[must_use]
2745 pub fn capture_index_for_name(&self, name: &str) -> Option<u32> {
2746 self.capture_names
2747 .iter()
2748 .position(|n| *n == name)
2749 .map(|ix| ix as u32)
2750 }
2751
2752 #[must_use]
2756 pub const fn property_predicates(&self, index: usize) -> &[(QueryProperty, bool)] {
2757 &self.property_predicates[index]
2758 }
2759
2760 #[must_use]
2764 pub const fn property_settings(&self, index: usize) -> &[QueryProperty] {
2765 &self.property_settings[index]
2766 }
2767
2768 #[must_use]
2776 pub const fn general_predicates(&self, index: usize) -> &[QueryPredicate] {
2777 &self.general_predicates[index]
2778 }
2779
2780 #[doc(alias = "ts_query_disable_capture")]
2785 pub fn disable_capture(&mut self, name: &str) {
2786 unsafe {
2787 ffi::ts_query_disable_capture(
2788 self.ptr.as_ptr(),
2789 name.as_bytes().as_ptr().cast::<c_char>(),
2790 name.len() as u32,
2791 );
2792 }
2793 }
2794
2795 #[doc(alias = "ts_query_disable_pattern")]
2800 pub fn disable_pattern(&mut self, index: usize) {
2801 unsafe { ffi::ts_query_disable_pattern(self.ptr.as_ptr(), index as u32) }
2802 }
2803
2804 #[doc(alias = "ts_query_is_pattern_rooted")]
2806 #[must_use]
2807 pub fn is_pattern_rooted(&self, index: usize) -> bool {
2808 unsafe { ffi::ts_query_is_pattern_rooted(self.ptr.as_ptr(), index as u32) }
2809 }
2810
2811 #[doc(alias = "ts_query_is_pattern_non_local")]
2813 #[must_use]
2814 pub fn is_pattern_non_local(&self, index: usize) -> bool {
2815 unsafe { ffi::ts_query_is_pattern_non_local(self.ptr.as_ptr(), index as u32) }
2816 }
2817
2818 #[doc(alias = "ts_query_is_pattern_guaranteed_at_step")]
2823 #[must_use]
2824 pub fn is_pattern_guaranteed_at_step(&self, byte_offset: usize) -> bool {
2825 unsafe {
2826 ffi::ts_query_is_pattern_guaranteed_at_step(self.ptr.as_ptr(), byte_offset as u32)
2827 }
2828 }
2829
2830 fn parse_property(
2831 row: usize,
2832 function_name: &str,
2833 capture_names: &[&str],
2834 string_values: &[&str],
2835 args: &[ffi::TSQueryPredicateStep],
2836 ) -> Result<QueryProperty, QueryError> {
2837 if args.is_empty() || args.len() > 3 {
2838 return Err(predicate_error(
2839 row,
2840 format!(
2841 "Wrong number of arguments to {function_name} predicate. Expected 1 to 3, got {}.",
2842 args.len(),
2843 ),
2844 ));
2845 }
2846
2847 let mut capture_id = None;
2848 let mut key = None;
2849 let mut value = None;
2850
2851 for arg in args {
2852 if arg.type_ == ffi::TSQueryPredicateStepTypeCapture {
2853 if capture_id.is_some() {
2854 return Err(predicate_error(
2855 row,
2856 format!(
2857 "Invalid arguments to {function_name} predicate. Unexpected second capture name @{}",
2858 capture_names[arg.value_id as usize]
2859 ),
2860 ));
2861 }
2862 capture_id = Some(arg.value_id as usize);
2863 } else if key.is_none() {
2864 key = Some(&string_values[arg.value_id as usize]);
2865 } else if value.is_none() {
2866 value = Some(string_values[arg.value_id as usize]);
2867 } else {
2868 return Err(predicate_error(
2869 row,
2870 format!(
2871 "Invalid arguments to {function_name} predicate. Unexpected third argument @{}",
2872 string_values[arg.value_id as usize]
2873 ),
2874 ));
2875 }
2876 }
2877
2878 if let Some(key) = key {
2879 Ok(QueryProperty::new(key, value, capture_id))
2880 } else {
2881 Err(predicate_error(
2882 row,
2883 format!("Invalid arguments to {function_name} predicate. Missing key argument"),
2884 ))
2885 }
2886 }
2887}
2888
2889impl Default for QueryCursor {
2890 fn default() -> Self {
2891 Self::new()
2892 }
2893}
2894
2895impl QueryCursor {
2896 #[doc(alias = "ts_query_cursor_new")]
2901 #[must_use]
2902 pub fn new() -> Self {
2903 Self {
2904 ptr: unsafe { NonNull::new_unchecked(ffi::ts_query_cursor_new()) },
2905 }
2906 }
2907
2908 #[doc(alias = "ts_query_cursor_match_limit")]
2910 #[must_use]
2911 pub fn match_limit(&self) -> u32 {
2912 unsafe { ffi::ts_query_cursor_match_limit(self.ptr.as_ptr()) }
2913 }
2914
2915 #[doc(alias = "ts_query_cursor_set_match_limit")]
2918 pub fn set_match_limit(&mut self, limit: u32) {
2919 unsafe {
2920 ffi::ts_query_cursor_set_match_limit(self.ptr.as_ptr(), limit);
2921 }
2922 }
2923
2924 #[doc(alias = "ts_query_cursor_did_exceed_match_limit")]
2927 #[must_use]
2928 pub fn did_exceed_match_limit(&self) -> bool {
2929 unsafe { ffi::ts_query_cursor_did_exceed_match_limit(self.ptr.as_ptr()) }
2930 }
2931
2932 #[doc(alias = "ts_query_cursor_exec")]
2943 pub fn matches<'query, 'cursor: 'query, 'tree, T: TextProvider<I>, I: AsRef<[u8]>>(
2944 &'cursor mut self,
2945 query: &'query Query,
2946 node: Node<'tree>,
2947 text_provider: T,
2948 ) -> QueryMatches<'query, 'tree, T, I> {
2949 let ptr = self.ptr.as_ptr();
2950 unsafe { ffi::ts_query_cursor_exec(ptr, query.ptr.as_ptr(), node.0) };
2951 QueryMatches {
2952 ptr,
2953 query,
2954 text_provider,
2955 buffer1: Vec::default(),
2956 buffer2: Vec::default(),
2957 current_match: None,
2958 _options: None,
2959 _phantom: PhantomData,
2960 }
2961 }
2962
2963 #[doc(alias = "ts_query_cursor_exec_with_options")]
2970 pub fn matches_with_options<
2971 'query,
2972 'cursor: 'query,
2973 'tree,
2974 T: TextProvider<I>,
2975 I: AsRef<[u8]>,
2976 >(
2977 &'cursor mut self,
2978 query: &'query Query,
2979 node: Node<'tree>,
2980 text_provider: T,
2981 options: QueryCursorOptions,
2982 ) -> QueryMatches<'query, 'tree, T, I> {
2983 unsafe extern "C" fn progress(state: *mut ffi::TSQueryCursorState) -> bool {
2984 let callback = (*state)
2985 .payload
2986 .cast::<QueryProgressCallback>()
2987 .as_mut()
2988 .unwrap();
2989 match callback(&QueryCursorState::from_raw(state)) {
2990 ControlFlow::Continue(()) => false,
2991 ControlFlow::Break(()) => true,
2992 }
2993 }
2994
2995 let query_options = options.progress_callback.map(|cb| {
2996 QueryCursorOptionsDrop(Box::into_raw(Box::new(ffi::TSQueryCursorOptions {
2997 payload: Box::into_raw(Box::new(cb)).cast::<c_void>(),
2998 progress_callback: Some(progress),
2999 })))
3000 });
3001
3002 let ptr = self.ptr.as_ptr();
3003 unsafe {
3004 ffi::ts_query_cursor_exec_with_options(
3005 ptr,
3006 query.ptr.as_ptr(),
3007 node.0,
3008 query_options.as_ref().map_or(ptr::null_mut(), |q| q.0),
3009 );
3010 }
3011 QueryMatches {
3012 ptr,
3013 query,
3014 text_provider,
3015 buffer1: Vec::default(),
3016 buffer2: Vec::default(),
3017 current_match: None,
3018 _options: query_options,
3019 _phantom: PhantomData,
3020 }
3021 }
3022
3023 #[doc(alias = "ts_query_cursor_exec")]
3033 pub fn captures<'query, 'cursor: 'query, 'tree, T: TextProvider<I>, I: AsRef<[u8]>>(
3034 &'cursor mut self,
3035 query: &'query Query,
3036 node: Node<'tree>,
3037 text_provider: T,
3038 ) -> QueryCaptures<'query, 'tree, T, I> {
3039 let ptr = self.ptr.as_ptr();
3040 unsafe { ffi::ts_query_cursor_exec(ptr, query.ptr.as_ptr(), node.0) };
3041 QueryCaptures {
3042 ptr,
3043 query,
3044 text_provider,
3045 buffer1: Vec::default(),
3046 buffer2: Vec::default(),
3047 current_match: None,
3048 _options: None,
3049 _phantom: PhantomData,
3050 }
3051 }
3052
3053 #[doc(alias = "ts_query_cursor_exec")]
3059 pub fn captures_with_options<
3060 'query,
3061 'cursor: 'query,
3062 'tree,
3063 T: TextProvider<I>,
3064 I: AsRef<[u8]>,
3065 >(
3066 &'cursor mut self,
3067 query: &'query Query,
3068 node: Node<'tree>,
3069 text_provider: T,
3070 options: QueryCursorOptions,
3071 ) -> QueryCaptures<'query, 'tree, T, I> {
3072 unsafe extern "C" fn progress(state: *mut ffi::TSQueryCursorState) -> bool {
3073 let callback = (*state)
3074 .payload
3075 .cast::<QueryProgressCallback>()
3076 .as_mut()
3077 .unwrap();
3078 match callback(&QueryCursorState::from_raw(state)) {
3079 ControlFlow::Continue(()) => false,
3080 ControlFlow::Break(()) => true,
3081 }
3082 }
3083
3084 let query_options = options.progress_callback.map(|cb| {
3085 QueryCursorOptionsDrop(Box::into_raw(Box::new(ffi::TSQueryCursorOptions {
3086 payload: Box::into_raw(Box::new(cb)).cast::<c_void>(),
3087 progress_callback: Some(progress),
3088 })))
3089 });
3090
3091 let ptr = self.ptr.as_ptr();
3092 unsafe {
3093 ffi::ts_query_cursor_exec_with_options(
3094 ptr,
3095 query.ptr.as_ptr(),
3096 node.0,
3097 query_options.as_ref().map_or(ptr::null_mut(), |q| q.0),
3098 );
3099 }
3100 QueryCaptures {
3101 ptr,
3102 query,
3103 text_provider,
3104 buffer1: Vec::default(),
3105 buffer2: Vec::default(),
3106 current_match: None,
3107 _options: query_options,
3108 _phantom: PhantomData,
3109 }
3110 }
3111
3112 #[doc(alias = "ts_query_cursor_set_byte_range")]
3115 pub fn set_byte_range(&mut self, range: ops::Range<usize>) -> &mut Self {
3116 unsafe {
3117 ffi::ts_query_cursor_set_byte_range(
3118 self.ptr.as_ptr(),
3119 range.start as u32,
3120 range.end as u32,
3121 );
3122 }
3123 self
3124 }
3125
3126 #[doc(alias = "ts_query_cursor_set_point_range")]
3129 pub fn set_point_range(&mut self, range: ops::Range<Point>) -> &mut Self {
3130 unsafe {
3131 ffi::ts_query_cursor_set_point_range(
3132 self.ptr.as_ptr(),
3133 range.start.into(),
3134 range.end.into(),
3135 );
3136 }
3137 self
3138 }
3139
3140 #[doc(alias = "ts_query_cursor_set_containing_byte_range")]
3148 pub fn set_containing_byte_range(&mut self, range: ops::Range<usize>) -> &mut Self {
3149 unsafe {
3150 ffi::ts_query_cursor_set_containing_byte_range(
3151 self.ptr.as_ptr(),
3152 range.start as u32,
3153 range.end as u32,
3154 );
3155 }
3156 self
3157 }
3158
3159 #[doc(alias = "ts_query_cursor_set_containing_point_range")]
3167 pub fn set_containing_point_range(&mut self, range: ops::Range<Point>) -> &mut Self {
3168 unsafe {
3169 ffi::ts_query_cursor_set_containing_point_range(
3170 self.ptr.as_ptr(),
3171 range.start.into(),
3172 range.end.into(),
3173 );
3174 }
3175 self
3176 }
3177
3178 #[doc(alias = "ts_query_cursor_set_max_start_depth")]
3193 pub fn set_max_start_depth(&mut self, max_start_depth: Option<u32>) -> &mut Self {
3194 unsafe {
3195 ffi::ts_query_cursor_set_max_start_depth(
3196 self.ptr.as_ptr(),
3197 max_start_depth.unwrap_or(u32::MAX),
3198 );
3199 }
3200 self
3201 }
3202}
3203
3204impl<'tree> QueryMatch<'_, 'tree> {
3205 #[must_use]
3206 pub const fn id(&self) -> u32 {
3207 self.id
3208 }
3209
3210 #[doc(alias = "ts_query_cursor_remove_match")]
3211 pub fn remove(&self) {
3212 unsafe { ffi::ts_query_cursor_remove_match(self.cursor, self.id) }
3213 }
3214
3215 pub fn nodes_for_capture_index(
3216 &self,
3217 capture_ix: u32,
3218 ) -> impl Iterator<Item = Node<'tree>> + '_ {
3219 self.captures
3220 .iter()
3221 .filter_map(move |capture| (capture.index == capture_ix).then_some(capture.node))
3222 }
3223
3224 fn new(m: &ffi::TSQueryMatch, cursor: *mut ffi::TSQueryCursor) -> Self {
3225 QueryMatch {
3226 cursor,
3227 id: m.id,
3228 pattern_index: m.pattern_index as usize,
3229 captures: (m.capture_count > 0)
3230 .then(|| unsafe {
3231 slice::from_raw_parts(
3232 m.captures.cast::<QueryCapture<'tree>>(),
3233 m.capture_count as usize,
3234 )
3235 })
3236 .unwrap_or_default(),
3237 }
3238 }
3239
3240 pub fn satisfies_text_predicates<I: AsRef<[u8]>>(
3241 &self,
3242 query: &Query,
3243 buffer1: &mut Vec<u8>,
3244 buffer2: &mut Vec<u8>,
3245 text_provider: &mut impl TextProvider<I>,
3246 ) -> bool {
3247 struct NodeText<'a, T> {
3248 buffer: &'a mut Vec<u8>,
3249 first_chunk: Option<T>,
3250 }
3251 impl<'a, T: AsRef<[u8]>> NodeText<'a, T> {
3252 fn new(buffer: &'a mut Vec<u8>) -> Self {
3253 Self {
3254 buffer,
3255 first_chunk: None,
3256 }
3257 }
3258
3259 fn get_text(&mut self, chunks: &mut impl Iterator<Item = T>) -> &[u8] {
3260 self.first_chunk = chunks.next();
3261 if let Some(next_chunk) = chunks.next() {
3262 self.buffer.clear();
3263 self.buffer
3264 .extend_from_slice(self.first_chunk.as_ref().unwrap().as_ref());
3265 self.buffer.extend_from_slice(next_chunk.as_ref());
3266 for chunk in chunks {
3267 self.buffer.extend_from_slice(chunk.as_ref());
3268 }
3269 self.buffer.as_slice()
3270 } else if let Some(ref first_chunk) = self.first_chunk {
3271 first_chunk.as_ref()
3272 } else {
3273 &[]
3274 }
3275 }
3276 }
3277
3278 let mut node_text1 = NodeText::new(buffer1);
3279 let mut node_text2 = NodeText::new(buffer2);
3280
3281 query.text_predicates[self.pattern_index]
3282 .iter()
3283 .all(|predicate| match predicate {
3284 TextPredicateCapture::EqCapture(i, j, is_positive, match_all_nodes) => {
3285 let mut nodes_1 = self.nodes_for_capture_index(*i).peekable();
3286 let mut nodes_2 = self.nodes_for_capture_index(*j).peekable();
3287 while nodes_1.peek().is_some() && nodes_2.peek().is_some() {
3288 let node1 = nodes_1.next().unwrap();
3289 let node2 = nodes_2.next().unwrap();
3290 let mut text1 = text_provider.text(node1);
3291 let mut text2 = text_provider.text(node2);
3292 let text1 = node_text1.get_text(&mut text1);
3293 let text2 = node_text2.get_text(&mut text2);
3294 let is_positive_match = text1 == text2;
3295 if is_positive_match != *is_positive && *match_all_nodes {
3296 return false;
3297 }
3298 if is_positive_match == *is_positive && !*match_all_nodes {
3299 return true;
3300 }
3301 }
3302 nodes_1.next().is_none() && nodes_2.next().is_none()
3303 }
3304 TextPredicateCapture::EqString(i, s, is_positive, match_all_nodes) => {
3305 let nodes = self.nodes_for_capture_index(*i);
3306 for node in nodes {
3307 let mut text = text_provider.text(node);
3308 let text = node_text1.get_text(&mut text);
3309 let is_positive_match = text == s.as_bytes();
3310 if is_positive_match != *is_positive && *match_all_nodes {
3311 return false;
3312 }
3313 if is_positive_match == *is_positive && !*match_all_nodes {
3314 return true;
3315 }
3316 }
3317 true
3318 }
3319 TextPredicateCapture::MatchString(i, r, is_positive, match_all_nodes) => {
3320 let nodes = self.nodes_for_capture_index(*i);
3321 for node in nodes {
3322 let mut text = text_provider.text(node);
3323 let text = node_text1.get_text(&mut text);
3324 let is_positive_match = r.is_match(text);
3325 if is_positive_match != *is_positive && *match_all_nodes {
3326 return false;
3327 }
3328 if is_positive_match == *is_positive && !*match_all_nodes {
3329 return true;
3330 }
3331 }
3332 true
3333 }
3334 TextPredicateCapture::AnyString(i, v, is_positive) => {
3335 let nodes = self.nodes_for_capture_index(*i);
3336 for node in nodes {
3337 let mut text = text_provider.text(node);
3338 let text = node_text1.get_text(&mut text);
3339 if (v.iter().any(|s| text == s.as_bytes())) != *is_positive {
3340 return false;
3341 }
3342 }
3343 true
3344 }
3345 })
3346 }
3347}
3348
3349impl QueryProperty {
3350 #[must_use]
3351 pub fn new(key: &str, value: Option<&str>, capture_id: Option<usize>) -> Self {
3352 Self {
3353 capture_id,
3354 key: key.to_string().into(),
3355 value: value.map(|s| s.to_string().into()),
3356 }
3357 }
3358}
3359
3360impl<'query, 'tree, T: TextProvider<I>, I: AsRef<[u8]>> StreamingIterator
3364 for QueryMatches<'query, 'tree, T, I>
3365{
3366 type Item = QueryMatch<'query, 'tree>;
3367
3368 fn advance(&mut self) {
3369 self.current_match = unsafe {
3370 loop {
3371 let mut m = MaybeUninit::<ffi::TSQueryMatch>::uninit();
3372 if ffi::ts_query_cursor_next_match(self.ptr, m.as_mut_ptr()) {
3373 let result = QueryMatch::new(&m.assume_init(), self.ptr);
3374 if result.satisfies_text_predicates(
3375 self.query,
3376 &mut self.buffer1,
3377 &mut self.buffer2,
3378 &mut self.text_provider,
3379 ) {
3380 break Some(result);
3381 }
3382 } else {
3383 break None;
3384 }
3385 }
3386 };
3387 }
3388
3389 fn get(&self) -> Option<&Self::Item> {
3390 self.current_match.as_ref()
3391 }
3392}
3393
3394impl<T: TextProvider<I>, I: AsRef<[u8]>> StreamingIteratorMut for QueryMatches<'_, '_, T, I> {
3395 fn get_mut(&mut self) -> Option<&mut Self::Item> {
3396 self.current_match.as_mut()
3397 }
3398}
3399
3400impl<'query, 'tree, T: TextProvider<I>, I: AsRef<[u8]>> StreamingIterator
3401 for QueryCaptures<'query, 'tree, T, I>
3402{
3403 type Item = (QueryMatch<'query, 'tree>, usize);
3404
3405 fn advance(&mut self) {
3406 self.current_match = unsafe {
3407 loop {
3408 let mut capture_index = 0u32;
3409 let mut m = MaybeUninit::<ffi::TSQueryMatch>::uninit();
3410 if ffi::ts_query_cursor_next_capture(
3411 self.ptr,
3412 m.as_mut_ptr(),
3413 core::ptr::addr_of_mut!(capture_index),
3414 ) {
3415 let result = QueryMatch::new(&m.assume_init(), self.ptr);
3416 if result.satisfies_text_predicates(
3417 self.query,
3418 &mut self.buffer1,
3419 &mut self.buffer2,
3420 &mut self.text_provider,
3421 ) {
3422 break Some((result, capture_index as usize));
3423 }
3424 result.remove();
3425 } else {
3426 break None;
3427 }
3428 }
3429 }
3430 }
3431
3432 fn get(&self) -> Option<&Self::Item> {
3433 self.current_match.as_ref()
3434 }
3435}
3436
3437impl<T: TextProvider<I>, I: AsRef<[u8]>> StreamingIteratorMut for QueryCaptures<'_, '_, T, I> {
3438 fn get_mut(&mut self) -> Option<&mut Self::Item> {
3439 self.current_match.as_mut()
3440 }
3441}
3442
3443impl<T: TextProvider<I>, I: AsRef<[u8]>> QueryMatches<'_, '_, T, I> {
3444 #[doc(alias = "ts_query_cursor_set_byte_range")]
3445 pub fn set_byte_range(&mut self, range: ops::Range<usize>) {
3446 unsafe {
3447 ffi::ts_query_cursor_set_byte_range(self.ptr, range.start as u32, range.end as u32);
3448 }
3449 }
3450
3451 #[doc(alias = "ts_query_cursor_set_point_range")]
3452 pub fn set_point_range(&mut self, range: ops::Range<Point>) {
3453 unsafe {
3454 ffi::ts_query_cursor_set_point_range(self.ptr, range.start.into(), range.end.into());
3455 }
3456 }
3457}
3458
3459impl<T: TextProvider<I>, I: AsRef<[u8]>> QueryCaptures<'_, '_, T, I> {
3460 #[doc(alias = "ts_query_cursor_set_byte_range")]
3461 pub fn set_byte_range(&mut self, range: ops::Range<usize>) {
3462 unsafe {
3463 ffi::ts_query_cursor_set_byte_range(self.ptr, range.start as u32, range.end as u32);
3464 }
3465 }
3466
3467 #[doc(alias = "ts_query_cursor_set_point_range")]
3468 pub fn set_point_range(&mut self, range: ops::Range<Point>) {
3469 unsafe {
3470 ffi::ts_query_cursor_set_point_range(self.ptr, range.start.into(), range.end.into());
3471 }
3472 }
3473}
3474
3475impl fmt::Debug for QueryMatch<'_, '_> {
3476 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3477 write!(
3478 f,
3479 "QueryMatch {{ id: {}, pattern_index: {}, captures: {:?} }}",
3480 self.id, self.pattern_index, self.captures
3481 )
3482 }
3483}
3484
3485impl<F, R, I> TextProvider<I> for F
3486where
3487 F: FnMut(Node) -> R,
3488 R: Iterator<Item = I>,
3489 I: AsRef<[u8]>,
3490{
3491 type I = R;
3492
3493 fn text(&mut self, node: Node) -> Self::I {
3494 (self)(node)
3495 }
3496}
3497
3498impl<'a> TextProvider<&'a [u8]> for &'a [u8] {
3499 type I = iter::Once<&'a [u8]>;
3500
3501 fn text(&mut self, node: Node) -> Self::I {
3502 iter::once(&self[node.byte_range()])
3503 }
3504}
3505
3506impl PartialEq for Query {
3507 fn eq(&self, other: &Self) -> bool {
3508 self.ptr == other.ptr
3509 }
3510}
3511
3512impl Drop for Query {
3513 fn drop(&mut self) {
3514 unsafe { ffi::ts_query_delete(self.ptr.as_ptr()) }
3515 }
3516}
3517
3518impl Drop for QueryCursor {
3519 fn drop(&mut self) {
3520 unsafe { ffi::ts_query_cursor_delete(self.ptr.as_ptr()) }
3521 }
3522}
3523
3524impl Point {
3525 #[must_use]
3526 pub const fn new(row: usize, column: usize) -> Self {
3527 Self { row, column }
3528 }
3529}
3530
3531impl fmt::Display for Point {
3532 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3533 write!(f, "({}, {})", self.row, self.column)
3534 }
3535}
3536
3537impl From<Point> for ffi::TSPoint {
3538 fn from(val: Point) -> Self {
3539 Self {
3540 row: val.row as u32,
3541 column: val.column as u32,
3542 }
3543 }
3544}
3545
3546impl From<ffi::TSPoint> for Point {
3547 fn from(point: ffi::TSPoint) -> Self {
3548 Self {
3549 row: point.row as usize,
3550 column: point.column as usize,
3551 }
3552 }
3553}
3554
3555impl From<Range> for ffi::TSRange {
3556 fn from(val: Range) -> Self {
3557 Self {
3558 start_byte: val.start_byte as u32,
3559 end_byte: val.end_byte as u32,
3560 start_point: val.start_point.into(),
3561 end_point: val.end_point.into(),
3562 }
3563 }
3564}
3565
3566impl From<ffi::TSRange> for Range {
3567 fn from(range: ffi::TSRange) -> Self {
3568 Self {
3569 start_byte: range.start_byte as usize,
3570 end_byte: range.end_byte as usize,
3571 start_point: range.start_point.into(),
3572 end_point: range.end_point.into(),
3573 }
3574 }
3575}
3576
3577impl From<&InputEdit> for ffi::TSInputEdit {
3578 fn from(val: &InputEdit) -> Self {
3579 Self {
3580 start_byte: val.start_byte as u32,
3581 old_end_byte: val.old_end_byte as u32,
3582 new_end_byte: val.new_end_byte as u32,
3583 start_point: val.start_position.into(),
3584 old_end_point: val.old_end_position.into(),
3585 new_end_point: val.new_end_position.into(),
3586 }
3587 }
3588}
3589
3590impl<'a> LossyUtf8<'a> {
3591 #[must_use]
3592 pub const fn new(bytes: &'a [u8]) -> Self {
3593 LossyUtf8 {
3594 bytes,
3595 in_replacement: false,
3596 }
3597 }
3598}
3599
3600impl<'a> Iterator for LossyUtf8<'a> {
3601 type Item = &'a str;
3602
3603 fn next(&mut self) -> Option<&'a str> {
3604 if self.bytes.is_empty() {
3605 return None;
3606 }
3607 if self.in_replacement {
3608 self.in_replacement = false;
3609 return Some("\u{fffd}");
3610 }
3611 match core::str::from_utf8(self.bytes) {
3612 Ok(valid) => {
3613 self.bytes = &[];
3614 Some(valid)
3615 }
3616 Err(error) => {
3617 if let Some(error_len) = error.error_len() {
3618 let error_start = error.valid_up_to();
3619 if error_start > 0 {
3620 let result =
3621 unsafe { core::str::from_utf8_unchecked(&self.bytes[..error_start]) };
3622 self.bytes = &self.bytes[(error_start + error_len)..];
3623 self.in_replacement = true;
3624 Some(result)
3625 } else {
3626 self.bytes = &self.bytes[error_len..];
3627 Some("\u{fffd}")
3628 }
3629 } else {
3630 None
3631 }
3632 }
3633 }
3634 }
3635}
3636
3637#[must_use]
3638const fn predicate_error(row: usize, message: String) -> QueryError {
3639 QueryError {
3640 kind: QueryErrorKind::Predicate,
3641 row,
3642 column: 0,
3643 offset: 0,
3644 message,
3645 }
3646}
3647
3648impl fmt::Display for IncludedRangesError {
3649 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3650 write!(f, "Incorrect range by index: {}", self.0)
3651 }
3652}
3653
3654impl fmt::Display for LanguageError {
3655 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3656 match self {
3657 Self::Version(version) => {
3658 write!(
3659 f,
3660 "Incompatible language version {version}. Expected minimum {MIN_COMPATIBLE_LANGUAGE_VERSION}, maximum {LANGUAGE_VERSION}",
3661 )
3662 }
3663 }
3664 }
3665}
3666
3667impl fmt::Display for QueryError {
3668 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3669 let msg = match self.kind {
3670 QueryErrorKind::Field => "Invalid field name ",
3671 QueryErrorKind::NodeType => "Invalid node type ",
3672 QueryErrorKind::Capture => "Invalid capture name ",
3673 QueryErrorKind::Predicate => "Invalid predicate: ",
3674 QueryErrorKind::Structure => "Impossible pattern:\n",
3675 QueryErrorKind::Syntax => "Invalid syntax:\n",
3676 QueryErrorKind::Language => "",
3677 };
3678 if msg.is_empty() {
3679 write!(f, "{}", self.message)
3680 } else {
3681 write!(
3682 f,
3683 "Query error at {}:{}. {}{}",
3684 self.row + 1,
3685 self.column + 1,
3686 msg,
3687 self.message
3688 )
3689 }
3690 }
3691}
3692
3693#[doc(hidden)]
3694#[must_use]
3695pub fn format_sexp(sexp: &str, initial_indent_level: usize) -> String {
3696 let mut indent_level = initial_indent_level;
3697 let mut formatted = String::new();
3698 let mut has_field = false;
3699
3700 let mut c_iter = sexp.chars().peekable();
3701 let mut s = String::with_capacity(sexp.len());
3702 let mut quote = '\0';
3703 let mut saw_paren = false;
3704 let mut did_last = false;
3705
3706 let mut fetch_next_str = |next: &mut String| {
3707 next.clear();
3708 while let Some(c) = c_iter.next() {
3709 if c == '\'' || c == '"' {
3710 quote = c;
3711 } else if c == ' ' || (c == ')' && quote != '\0') {
3712 if let Some(next_c) = c_iter.peek() {
3713 if *next_c == quote {
3714 next.push(c);
3715 next.push(*next_c);
3716 c_iter.next();
3717 quote = '\0';
3718 continue;
3719 }
3720 }
3721 break;
3722 }
3723 if c == ')' {
3724 saw_paren = true;
3725 break;
3726 }
3727 next.push(c);
3728 }
3729
3730 if c_iter.peek().is_none() && next.is_empty() {
3732 if saw_paren {
3733 saw_paren = false;
3735 return Some(());
3736 }
3737 if !did_last {
3738 did_last = true;
3740 return Some(());
3741 }
3742 return None;
3743 }
3744 Some(())
3745 };
3746
3747 while fetch_next_str(&mut s).is_some() {
3748 if s.is_empty() && indent_level > 0 {
3749 indent_level -= 1;
3751 write!(formatted, ")").unwrap();
3752 } else if s.starts_with('(') {
3753 if has_field {
3754 has_field = false;
3755 } else {
3756 if indent_level > 0 {
3757 writeln!(formatted).unwrap();
3758 for _ in 0..indent_level {
3759 write!(formatted, " ").unwrap();
3760 }
3761 }
3762 indent_level += 1;
3763 }
3764
3765 write!(formatted, "{s}").unwrap();
3767
3768 if s.starts_with("(MISSING") || s.starts_with("(UNEXPECTED") {
3770 fetch_next_str(&mut s).unwrap();
3771 if s.is_empty() {
3772 while indent_level > 0 {
3773 indent_level -= 1;
3774 write!(formatted, ")").unwrap();
3775 }
3776 } else {
3777 write!(formatted, " {s}").unwrap();
3778 }
3779 }
3780 } else if s.ends_with(':') {
3781 writeln!(formatted).unwrap();
3783 for _ in 0..indent_level {
3784 write!(formatted, " ").unwrap();
3785 }
3786 write!(formatted, "{s} ").unwrap();
3787 has_field = true;
3788 indent_level += 1;
3789 }
3790 }
3791
3792 formatted
3793}
3794
3795pub fn wasm_stdlib_symbols() -> impl Iterator<Item = &'static str> {
3796 const WASM_STDLIB_SYMBOLS: &str = include_str!(concat!(env!("OUT_DIR"), "/stdlib-symbols.txt"));
3797
3798 WASM_STDLIB_SYMBOLS
3799 .lines()
3800 .map(|s| s.trim_matches(|c| c == '"' || c == ','))
3801}
3802
3803extern "C" {
3804 fn free(ptr: *mut c_void);
3805}
3806
3807static mut FREE_FN: unsafe extern "C" fn(ptr: *mut c_void) = free;
3808
3809#[doc(alias = "ts_set_allocator")]
3815pub unsafe fn set_allocator(
3816 new_malloc: Option<unsafe extern "C" fn(size: usize) -> *mut c_void>,
3817 new_calloc: Option<unsafe extern "C" fn(nmemb: usize, size: usize) -> *mut c_void>,
3818 new_realloc: Option<unsafe extern "C" fn(ptr: *mut c_void, size: usize) -> *mut c_void>,
3819 new_free: Option<unsafe extern "C" fn(ptr: *mut c_void)>,
3820) {
3821 FREE_FN = new_free.unwrap_or(free);
3822 ffi::ts_set_allocator(new_malloc, new_calloc, new_realloc, new_free);
3823}
3824
3825#[cfg(feature = "std")]
3826#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
3827impl error::Error for IncludedRangesError {}
3828#[cfg(feature = "std")]
3829#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
3830impl error::Error for LanguageError {}
3831#[cfg(feature = "std")]
3832#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
3833impl error::Error for QueryError {}
3834
3835unsafe impl Send for Language {}
3836unsafe impl Sync for Language {}
3837
3838unsafe impl Send for Node<'_> {}
3839unsafe impl Sync for Node<'_> {}
3840
3841unsafe impl Send for LookaheadIterator {}
3842unsafe impl Sync for LookaheadIterator {}
3843
3844unsafe impl Send for LookaheadNamesIterator<'_> {}
3845unsafe impl Sync for LookaheadNamesIterator<'_> {}
3846
3847unsafe impl Send for Parser {}
3848unsafe impl Sync for Parser {}
3849
3850unsafe impl Send for Query {}
3851unsafe impl Sync for Query {}
3852
3853unsafe impl Send for QueryCursor {}
3854unsafe impl Sync for QueryCursor {}
3855
3856unsafe impl Send for Tree {}
3857unsafe impl Sync for Tree {}
3858
3859unsafe impl Send for TreeCursor<'_> {}
3860unsafe impl Sync for TreeCursor<'_> {}