use std::collections::{btree_map, BTreeMap};
use std::ops;
use block::BlockSize;
use lump::LumpId;
use storage::portion::{DataPortion, Portion, PortionU64};
use storage::StorageUsage;
#[derive(Debug, Clone, Default)]
pub struct LumpIndex {
map: BTreeMap<LumpId, PortionU64>,
}
impl LumpIndex {
pub fn new() -> Self {
LumpIndex {
map: BTreeMap::new(),
}
}
pub fn usage_range(&self, range: ops::Range<LumpId>, block_size: BlockSize) -> StorageUsage {
StorageUsage::approximate(self.map.range(range).fold(0, |acc, (_, p)| {
acc + Portion::from(*p).len(block_size) as u64
}))
}
pub fn get(&self, lump_id: &LumpId) -> Option<Portion> {
self.map.get(lump_id).map(|p| p.clone().into())
}
pub fn insert(&mut self, lump_id: LumpId, portion: Portion) {
self.map.insert(lump_id, portion.into());
}
pub fn remove(&mut self, lump_id: &LumpId) -> Option<Portion> {
self.map.remove(lump_id).map(std::convert::Into::into)
}
pub fn list(&self) -> Vec<LumpId> {
self.map.keys().cloned().collect()
}
pub fn len(&self) -> u64 {
self.map.len() as u64
}
pub fn data_portions(&self) -> DataPortions {
DataPortions(self.map.values())
}
pub fn list_range(&self, range: ops::Range<LumpId>) -> Vec<LumpId> {
let btree_range = self.map.range(range);
btree_range.map(|(k, _)| *k).collect()
}
}
#[derive(Debug)]
pub struct DataPortions<'a>(btree_map::Values<'a, LumpId, PortionU64>);
impl<'a> Iterator for DataPortions<'a> {
type Item = DataPortion;
fn next(&mut self) -> Option<Self::Item> {
while let Some(portion) = self.0.next() {
if let Portion::Data(portion) = portion.clone().into() {
return Some(portion);
}
}
None
}
}