parent
5bc52f8d1c
commit
655207ab03
@ -0,0 +1,69 @@
|
|||||||
|
use super::*;
|
||||||
|
use std::borrow::Borrow;
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
use std::iter;
|
||||||
|
use std::collections::{
|
||||||
|
btree_map::Range,
|
||||||
|
VecDeque,
|
||||||
|
};
|
||||||
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct StoreSearchIter<'a, T: ?Sized>(&'a Store, Option<Range<'a, String, ArenaIndex>>, VecDeque<&'a sha256::Sha256Hash>, PhantomData<T>);
|
||||||
|
|
||||||
|
// Accessing
|
||||||
|
impl Store
|
||||||
|
{
|
||||||
|
/// Search for all entries with *any* of these provided tags.
|
||||||
|
///
|
||||||
|
/// # Notes
|
||||||
|
/// This is allowed to produce duplicate entries.
|
||||||
|
pub fn tag_search_many<T: Ord>(&self, tags: impl IntoIterator<Item= T>) -> StoreSearchIter<'_, T>
|
||||||
|
where String: Borrow<T>
|
||||||
|
{
|
||||||
|
let mut sorted: SmallVec<[_; 5]> = tags.into_iter().collect();
|
||||||
|
sorted.sort();
|
||||||
|
StoreSearchIter(self, Some(match (sorted.first(), sorted.last()) {
|
||||||
|
(Some(low), Some(high)) => self.tags.range(low..=high),
|
||||||
|
_ => return StoreSearchIter(self, None, Default::default(), PhantomData),
|
||||||
|
}), VecDeque::new(), PhantomData)
|
||||||
|
}
|
||||||
|
/// Search for all items with this provided tag.
|
||||||
|
///
|
||||||
|
/// # Notes
|
||||||
|
/// This is allowed to produce duplicate entries, if an entry has two of the same tags.
|
||||||
|
pub fn tag_search<'a, T: Ord>(&'a self, tag: T) -> StoreSearchIter<'a, T>
|
||||||
|
where String: Borrow<T>
|
||||||
|
{
|
||||||
|
let tag = &tag;
|
||||||
|
StoreSearchIter(self, Some(self.tags.range(tag..=tag)), VecDeque::new(), PhantomData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T: ?Sized> Iterator for StoreSearchIter<'a, T>
|
||||||
|
{
|
||||||
|
type Item = &'a Entry;
|
||||||
|
fn next(&mut self) -> Option<Self::Item>
|
||||||
|
{
|
||||||
|
if let Some(range) = &mut self.1 {
|
||||||
|
if let Some((_, &ti)) = range.next() {
|
||||||
|
// tag index get
|
||||||
|
let data_hashes = &self.0.data_hashes;
|
||||||
|
let iter = self.0.tag_mappings.get(ti)
|
||||||
|
.map_into_iter()
|
||||||
|
.filter_map(move |&idx| data_hashes.get(idx));
|
||||||
|
self.2.extend(iter);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
self.2.pop_front().map(|x| self.0.data.get(x)).flatten()
|
||||||
|
}
|
||||||
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
|
match self.1 {
|
||||||
|
None => (0, Some(0)),
|
||||||
|
Some(_) => (0, None),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'a, T: ?Sized> iter::FusedIterator for StoreSearchIter<'a, T>{}
|
@ -0,0 +1,70 @@
|
|||||||
|
use std::iter::FusedIterator;
|
||||||
|
|
||||||
|
/// An iterator that may be empty.
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct MaybeIter<I, T>(Option<I>)
|
||||||
|
where I: Iterator<Item=T>;
|
||||||
|
|
||||||
|
pub trait OptionIterExt<I, T>: Sized
|
||||||
|
where I: Iterator<Item=T>
|
||||||
|
{
|
||||||
|
/// Map this `Option<Iterator>` into an iterator that will yield the items of the iterator if it is present.
|
||||||
|
fn map_into_iter(self) -> MaybeIter<I, T>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E, T, I, Into: IntoIterator<IntoIter=I, Item=T>> OptionIterExt<I, T> for Result<Into, E>
|
||||||
|
where I: Iterator<Item = T>
|
||||||
|
{
|
||||||
|
#[inline] fn map_into_iter(self) -> MaybeIter<I, T> {
|
||||||
|
MaybeIter(self.ok().map(|x| x.into_iter()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<T, I, Into: IntoIterator<IntoIter=I, Item=T>> OptionIterExt<I, T> for Option<Into>
|
||||||
|
where I: Iterator<Item = T>
|
||||||
|
{
|
||||||
|
#[inline] fn map_into_iter(self) -> MaybeIter<I, T> {
|
||||||
|
MaybeIter(self.map(|x| x.into_iter()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I, T> Iterator for MaybeIter<I, T>
|
||||||
|
where I: Iterator<Item=T>
|
||||||
|
{
|
||||||
|
type Item = T;
|
||||||
|
fn next(&mut self) -> Option<Self::Item>
|
||||||
|
{
|
||||||
|
if let Some(ref mut iter) = self.0
|
||||||
|
{
|
||||||
|
iter.next()
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
|
match &self.0 {
|
||||||
|
Some(i) => i.size_hint(),
|
||||||
|
None => (0, Some(0)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I, T> FusedIterator for MaybeIter<I, T>
|
||||||
|
where I: Iterator<Item=T> + FusedIterator{}
|
||||||
|
|
||||||
|
impl<I, T> ExactSizeIterator for MaybeIter<I, T>
|
||||||
|
where I: Iterator<Item=T> + ExactSizeIterator{}
|
||||||
|
|
||||||
|
impl<I, T> DoubleEndedIterator for MaybeIter<I, T>
|
||||||
|
where I: Iterator<Item=T> + DoubleEndedIterator
|
||||||
|
{
|
||||||
|
fn next_back(&mut self) -> Option<Self::Item> {
|
||||||
|
if let Some(ref mut iter) = self.0
|
||||||
|
{
|
||||||
|
iter.next_back()
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in new issue