start search_all

master
Avril 3 years ago
parent 655207ab03
commit 5c4c4bc08a
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -14,29 +14,47 @@ pub struct StoreSearchIter<'a, T: ?Sized>(&'a Store, Option<Range<'a, String, Ar
// Accessing
impl Store
{
//TODO: Parallelize this with futures::Stream ver to do the `tag_search` lookups in parallel.
pub fn tag_search_all<'a, T: ?Sized + Ord + 'a>(&'a self, tags: impl IntoIterator<Item= &'a T>) -> impl Iterator<Item = &'a Entry> + 'a
where String: Borrow<T>
{
let tags: SmallVec<[_; 5]> = tags.into_iter().collect();
tags.iter().flat_map(|&tag| self.tag_search(tag)).dedup_ref()
.filter(|x| x.tags.iter().map(|x| x.borrow()).filter(|tx| !tags.contains(tx)).count() == 0)
/* TODO: get rid of this ,replace `impl Iterator` return with its own type. */ .collect::<Vec<_>>().into_iter()
}
/// 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>
/// This is allowed to produce duplicate entries, if either:
/// * An entry has multiple of the same tag set
/// * An entry has multiple of the tags provided to this function set
pub fn tag_search_any<'a, T: ?Sized + Ord + 'a>(&self, tags: impl IntoIterator<Item= &'a 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),
(Some(&low), Some(&high)) => self.tags.range::<T, _>((std::ops::Bound::Included(low), std::ops::Bound::Included(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>
/// This is allowed to produce duplicate entries, if an entry has two of the same tags set.
pub fn tag_search<'a, T: ?Sized + 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)
let r= (std::ops::Bound::Included(tag), std::ops::Bound::Included(tag));
StoreSearchIter(self, Some(self.tags.range::<T, _>(r)), VecDeque::new(), PhantomData)
}
fn _assert_test_search(&self)
{
let _x: Vec<_> = self.tag_search_any(vec!["hello", "one", "two"]).dedup_ref().collect();
}
}

@ -1,4 +1,6 @@
use std::iter::FusedIterator;
use std::collections::BTreeSet;
use std::borrow::Borrow;
/// An iterator that may be empty.
#[derive(Debug, Clone)]
@ -67,4 +69,94 @@ where I: Iterator<Item=T> + DoubleEndedIterator
}
}
/// An iterator that deduplicates an iterator over references by pointer identity.
#[derive(Debug, Clone)]
pub struct DedupedRefIter<'a, I, T: ?Sized + 'a>(I, BTreeSet<*const T>)
where I: Iterator<Item = &'a T>;
pub trait DedupIterExt<'a, I, T: ?Sized + 'a>
where I: Iterator<Item = &'a T>
{
/// Deduplicate this iterator by pointer identity.
fn dedup_ref(self) -> DedupedRefIter<'a, I, T>;
}
impl<'a, I, T:?Sized+'a, IntoIter> DedupIterExt<'a, I, T> for IntoIter
where IntoIter: IntoIterator<IntoIter=I>,
I: Iterator<Item= &'a T>
{
fn dedup_ref(self) -> DedupedRefIter<'a, I, T> {
DedupedRefIter(self.into_iter(), BTreeSet::new())
}
}
impl<'a, I, T:?Sized + 'a> Iterator for DedupedRefIter<'a, I, T>
where I: Iterator<Item = &'a T>
{
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item>
{
Some(loop {
if let Some(next) = self.0.next()
{
if self.1.insert(next as *const T) {
break next;
}
} else {
return None;
}
})
}
fn size_hint(&self) -> (usize, Option<usize>) {
match self.0.size_hint()
{
(0, h) => (0, h),
(_, h) => (1, h),
}
}
}
impl<'a, I, T:?Sized + 'a> DoubleEndedIterator for DedupedRefIter<'a, I, T>
where I: Iterator<Item = &'a T> + DoubleEndedIterator
{
fn next_back(&mut self) -> Option<Self::Item> {
Some(loop {
if let Some(next) = self.0.next_back()
{
if self.1.insert(next as *const T) {
break next;
}
} else {
return None;
}
})
}
}
impl<'a, I, T:?Sized + 'a> FusedIterator for DedupedRefIter<'a, I, T>
where I: Iterator<Item = &'a T> + FusedIterator{}
pub trait ContainsAllExt<T, U, I>
where U: AsRef<T>,
I: IntoIterator<Item = U>,
{
fn contains_all(&self, items: I) -> bool;
}
impl<T, U, S, I> ContainsAllExt<T, U, I> for S
where S: AsRef<[T]>,
U: AsRef<T>,
I: IntoIterator<Item = U>,
T: PartialEq,
{
fn contains_all(&self, items: I) -> bool {
for x in items.into_iter()
{
if !self.as_ref().contains(x.as_ref()) {
return false;
}
}
true
}
}

Loading…
Cancel
Save