You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

70 lines
2.0 KiB

4 years ago
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>{}