use crate::query::match_captures::QueryMatchCaptures;
use crate::{raw, Query};
use std::fmt::Debug;
use streaming_iterator::StreamingIterator;
#[cfg(not(feature = "yak-sitter"))]
use tree_sitter::Point;
#[cfg(feature = "yak-sitter")]
use yak_sitter::PointRange;
#[cfg(feature = "yak-sitter")]
pub struct QueryMatches<'query, 'tree: 'query, Query: crate::Query> {
typed_query: &'query Query,
untyped_matches: raw::QueryMatches<'query, 'tree>,
current_match: Option<*const Query::Match<'query, 'tree>>,
}
#[cfg(not(feature = "yak-sitter"))]
pub struct QueryMatches<
'query,
'tree: 'query,
Query: crate::Query + 'tree,
Text: raw::TextProvider<I>,
I: AsRef<[u8]>,
> {
typed_query: &'query Query,
untyped_matches: raw::QueryMatches<'query, 'tree, Text, I>,
current_match: Option<*const Query::Match<'query, 'tree>>,
}
pub trait QueryMatch<'query, 'tree: 'query>: Debug {
type Query: Query<Match<'query, 'tree> = Self>;
fn query(&self) -> &'query Self::Query;
#[cfg(feature = "yak-sitter")]
fn tree(&self) -> &'tree raw::Tree;
fn raw(&self) -> &raw::QueryMatch<'query, 'tree>;
fn into_raw(self) -> raw::QueryMatch<'query, 'tree>;
#[cfg(feature = "yak-sitter")]
#[inline]
fn captures(&self) -> QueryMatchCaptures<'query, 'tree, Self::Query> {
unsafe {
QueryMatchCaptures::new(self.query(), self.raw().as_inner().captures, self.tree())
}
}
#[cfg(not(feature = "yak-sitter"))]
#[inline]
fn captures(&self) -> QueryMatchCaptures<'query, 'tree, Self::Query> {
unsafe { QueryMatchCaptures::new(self.query(), self.raw().captures) }
}
#[inline]
fn remove(self)
where
Self: Sized,
'tree: 'query,
{
self.into_raw().remove()
}
}
#[cfg(feature = "yak-sitter")]
impl<'query, 'tree: 'query, Query: crate::Query + 'tree> QueryMatches<'query, 'tree, Query> {
#[inline]
pub(super) unsafe fn from_raw(
typed_query: &'query Query,
untyped_matches: raw::QueryMatches<'query, 'tree>,
) -> Self {
Self {
typed_query,
untyped_matches,
current_match: None,
}
}
#[inline]
pub fn set_byte_range(&mut self, range: std::ops::Range<usize>) {
self.untyped_matches.set_byte_range(range)
}
#[inline]
#[cfg(feature = "yak-sitter")]
pub fn set_point_range(&mut self, range: PointRange) {
self.untyped_matches.set_point_range(range)
}
}
#[cfg(not(feature = "yak-sitter"))]
impl<
'query,
'tree: 'query,
Query: crate::Query + 'tree,
Text: raw::TextProvider<I>,
I: AsRef<[u8]>,
> QueryMatches<'query, 'tree, Query, Text, I>
{
#[inline]
pub(super) unsafe fn from_raw(
typed_query: &'query Query,
untyped_matches: raw::QueryMatches<'query, 'tree, Text, I>,
) -> Self {
Self {
typed_query,
untyped_matches,
current_match: None,
}
}
#[inline]
pub fn set_byte_range(&mut self, range: std::ops::Range<usize>) {
self.untyped_matches.set_byte_range(range)
}
#[inline]
pub fn set_point_range(&mut self, range: std::ops::Range<Point>) {
self.untyped_matches.set_point_range(range)
}
}
#[cfg(feature = "yak-sitter")]
impl<'query, 'tree: 'query, Query: crate::Query + 'tree> StreamingIterator
for QueryMatches<'query, 'tree, Query>
{
type Item = Query::Match<'query, 'tree>;
#[inline]
fn advance(&mut self) {
self.untyped_matches.advance();
self.current_match = unsafe {
self.untyped_matches
.get()
.map(|m| self.typed_query.wrap_match_ref(m) as *const _)
}
}
#[inline]
fn get(&self) -> Option<&Self::Item> {
self.current_match.map(|m| unsafe { &*m })
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.untyped_matches.size_hint()
}
}
#[cfg(not(feature = "yak-sitter"))]
impl<
'query,
'tree: 'query,
Query: crate::Query + 'tree,
Text: raw::TextProvider<I>,
I: AsRef<[u8]>,
> StreamingIterator for QueryMatches<'query, 'tree, Query, Text, I>
{
type Item = Query::Match<'query, 'tree>;
#[inline]
fn advance(&mut self) {
self.untyped_matches.advance();
self.current_match = unsafe {
self.untyped_matches
.get()
.map(|m| self.typed_query.wrap_match_ref(m) as *const _)
}
}
#[inline]
fn get(&self) -> Option<&Self::Item> {
self.current_match.map(|m| unsafe { &*m })
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.untyped_matches.size_hint()
}
}