tag searching

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

7
Cargo.lock generated

@ -462,6 +462,7 @@ dependencies = [
"jemallocator", "jemallocator",
"memmap", "memmap",
"serde", "serde",
"smallvec",
"tokio", "tokio",
] ]
@ -701,6 +702,12 @@ version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
[[package]]
name = "smallvec"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae524f056d7d770e174287294f562e95044c68e88dec909a00d2094805db9d75"
[[package]] [[package]]
name = "socket2" name = "socket2"
version = "0.3.18" version = "0.3.18"

@ -15,4 +15,5 @@ generational-arena = "0.2.8"
jemallocator = "0.3.2" jemallocator = "0.3.2"
memmap = "0.7.0" memmap = "0.7.0"
serde = {version = "1.0.118", features= ["derive"]} serde = {version = "1.0.118", features= ["derive"]}
smallvec = "1.5.1"
tokio = {version = "0.2", features = ["full"]} tokio = {version = "0.2", features = ["full"]}

@ -27,6 +27,9 @@ pub use metadata::StoreMetadata;
mod freeze; mod freeze;
pub use freeze::Freeze; pub use freeze::Freeze;
mod search;
pub use search::*;
#[derive(Debug)] #[derive(Debug)]
pub struct Store pub struct Store
{ {

@ -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
}
}
}

@ -16,6 +16,9 @@ macro_rules! io_err {
($msg:expr) => (io_err!(Other, $msg)); ($msg:expr) => (io_err!(Other, $msg));
} }
mod ext;
use ext::*;
mod slice; mod slice;
mod data; mod data;

Loading…
Cancel
Save