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