use crate::{
forest::TreeTypes,
index::{BranchIndex, CompactSeq, LeafIndex},
util::{MutBoolSliceExt, RangeBoundsExt},
};
use std::{fmt::Debug, ops::RangeBounds, sync::Arc};
pub trait Query<T: TreeTypes>: Debug + Send + Sync + 'static {
fn containing(&self, offset: u64, _index: &LeafIndex<T>, res: &mut [bool]);
fn intersecting(&self, offset: u64, _index: &BranchIndex<T>, res: &mut [bool]);
}
pub trait QueryExt<TT> {
fn boxed(self) -> Arc<dyn Query<TT>>;
}
impl<'a, TT: TreeTypes, Q: Query<TT> + 'static> QueryExt<TT> for Q {
fn boxed(self) -> Arc<dyn Query<TT>> {
Arc::new(self)
}
}
impl<T: TreeTypes> Query<T> for Arc<dyn Query<T>> {
fn containing(&self, offset: u64, x: &LeafIndex<T>, res: &mut [bool]) {
self.as_ref().containing(offset, x, res);
}
fn intersecting(&self, offset: u64, x: &BranchIndex<T>, res: &mut [bool]) {
self.as_ref().intersecting(offset, x, res);
}
}
#[derive(Debug, Clone)]
pub struct OffsetRangeQuery<R>(R);
impl<R: RangeBounds<u64>> From<R> for OffsetRangeQuery<R> {
fn from(value: R) -> Self {
Self(value)
}
}
impl<T: TreeTypes, R: RangeBounds<u64> + Debug + Sync + Send + 'static> Query<T>
for OffsetRangeQuery<R>
{
fn containing(&self, mut offset: u64, index: &LeafIndex<T>, res: &mut [bool]) {
let range = offset..offset + index.keys.count();
if !&self.0.intersects(&range) {
res.clear();
} else {
for i in 0..(index.keys.len()).min(res.len()) {
if res[i] {
res[i] = self.0.contains(&offset);
}
offset += 1;
}
}
}
fn intersecting(&self, offset: u64, index: &BranchIndex<T>, res: &mut [bool]) {
let range = offset..offset + index.count;
if !&self.0.intersects(&range) {
res.clear();
}
}
}
#[derive(Debug, Clone)]
pub struct EmptyQuery;
impl<T: TreeTypes> Query<T> for EmptyQuery {
fn containing(&self, _offset: u64, _index: &LeafIndex<T>, res: &mut [bool]) {
res.clear();
}
fn intersecting(&self, _offset: u64, _index: &BranchIndex<T>, res: &mut [bool]) {
res.clear();
}
}
#[derive(Debug, Clone)]
pub struct AllQuery;
impl<T: TreeTypes> Query<T> for AllQuery {
fn containing(&self, _offset: u64, _index: &LeafIndex<T>, _res: &mut [bool]) {
}
fn intersecting(&self, _offset: u64, _index: &BranchIndex<T>, _res: &mut [bool]) {
}
}
#[derive(Debug, Clone)]
pub struct AndQuery<A, B>(pub A, pub B);
impl<T: TreeTypes, A: Query<T>, B: Query<T>> Query<T> for AndQuery<A, B> {
fn containing(&self, offset: u64, index: &LeafIndex<T>, res: &mut [bool]) {
self.0.containing(offset, index, res);
self.1.containing(offset, index, res);
}
fn intersecting(&self, offset: u64, index: &BranchIndex<T>, res: &mut [bool]) {
self.0.intersecting(offset, index, res);
self.1.intersecting(offset, index, res);
}
}
#[derive(Debug, Clone)]
pub struct OrQuery<A, B>(pub A, pub B);
impl<T: TreeTypes, A: Query<T>, B: Query<T>> Query<T> for OrQuery<A, B> {
fn containing(&self, offset: u64, index: &LeafIndex<T>, res: &mut [bool]) {
let mut tmp = res.to_vec();
self.0.containing(offset, index, res);
self.1.containing(offset, index, &mut tmp);
res.or_with(&tmp);
}
fn intersecting(&self, offset: u64, index: &BranchIndex<T>, res: &mut [bool]) {
let mut tmp = res.to_vec();
self.0.intersecting(offset, index, res);
self.1.intersecting(offset, index, &mut tmp);
res.or_with(&tmp);
}
}
#[cfg(test)]
mod tests {}