use std::collections::{HashMap, HashSet};
use std::ops::Range;
use number::Number;
use position::{Position, Manager as PositionManager};
use bloom::Bloom;
use filter::Filter;
use config::Config;
use database::BloomDatabase;
pub struct BloomChain<'a> {
positioner: PositionManager,
db: &'a BloomDatabase,
}
impl<'a> BloomChain<'a> {
pub fn new(config: Config, db: &'a BloomDatabase) -> Self {
let positioner = PositionManager::new(config.elements_per_index, config.levels);
BloomChain {
positioner: positioner,
db: db,
}
}
fn blocks(&self, range: &Range<Number>, bloom: &Bloom, level: usize, offset: usize) -> Option<Vec<usize>> {
let index = self.positioner.position(offset, level);
match self.db.bloom_at(&index) {
None => return None,
Some(level_bloom) => match level {
0 if level_bloom.contains_bloom(bloom) => return Some(vec![offset]),
_ if !level_bloom.contains_bloom(bloom) => return None,
_ => ()
}
};
let level_size = self.positioner.level_size(level - 1);
let from_position = self.positioner.position(range.start, level - 1);
let to_position = self.positioner.position(range.end, level - 1);
let res: Vec<usize> = self.positioner.lower_level_positions(&index).into_iter()
.filter(|li| li.index >= from_position.index && li.index <= to_position.index)
.map(|li| li.index * level_size)
.filter_map(|off| self.blocks(range, bloom, level - 1, off))
.flat_map(|v| v)
.collect();
Some(res)
}
pub fn insert(&self, number: Number, bloom: Bloom) -> HashMap<Position, Bloom> {
let mut result: HashMap<Position, Bloom> = HashMap::new();
for level in 0..self.positioner.levels() {
let position = self.positioner.position(number, level);
let new_bloom = match self.db.bloom_at(&position) {
Some(mut old_bloom) => {
old_bloom.accrue_bloom(&bloom);
old_bloom
},
None => bloom.clone(),
};
result.insert(position, new_bloom);
}
result
}
pub fn replace(&self, range: &Range<Number>, blooms: Vec<Bloom>) -> HashMap<Position, Bloom> {
let mut result: HashMap<Position, Bloom> = HashMap::new();
for (i, bloom) in blooms.iter().enumerate() {
result.insert(self.positioner.position(range.start + i, 0), bloom.clone());
}
for reset_number in range.start + blooms.len()..(range.end + 1) {
result.insert(self.positioner.position(reset_number, 0), Bloom::default());
}
for level in 1..self.positioner.levels() {
for i in 0..blooms.len() {
let index = self.positioner.position(range.start + i, level);
let new_bloom = {
let bloom_at = | index | { result.get(&index).cloned().or_else(|| self.db.bloom_at(&index)) };
self.positioner.lower_level_positions(&index)
.into_iter()
.filter_map(bloom_at)
.fold(Bloom::default(), |mut acc, bloom| {
acc.accrue_bloom(&bloom);
acc
})
};
result.insert(index, new_bloom);
}
}
result
}
pub fn with_bloom(&self, range: &Range<Number>, bloom: &Bloom) -> Vec<Number> {
let mut result = vec![];
let max_level = self.positioner.max_level();
let level_size = self.positioner.level_size(max_level);
let from_position = self.positioner.position(range.start, max_level);
let to_position = self.positioner.position(range.end, max_level);
for index in from_position.index..to_position.index + 1 {
let offset = level_size * index;
if let Some(blocks) = self.blocks(range, bloom, max_level, offset) {
result.extend(blocks);
}
}
result
}
pub fn filter(&self, filter: &Filter) -> Vec<Number> {
let range = filter.range();
let mut blocks = filter.bloom_possibilities()
.into_iter()
.flat_map(|ref bloom| self.with_bloom(&range, bloom))
.collect::<HashSet<Number>>()
.into_iter()
.collect::<Vec<Number>>();
blocks.sort();
blocks
}
}