use crate::compactor::Compactor;
use crate::TotalOrd;
pub struct ReqSketchIterator<'a, T>
where
T: Clone + TotalOrd + PartialEq,
{
compactors: &'a [Compactor<T>],
current_level: usize,
current_level_iter: Option<std::slice::Iter<'a, T>>,
current_weight: u64,
}
impl<'a, T> ReqSketchIterator<'a, T>
where
T: Clone + TotalOrd + PartialEq,
{
pub(crate) fn new(compactors: &'a [Compactor<T>]) -> Self {
let mut iter = Self {
compactors,
current_level: 0,
current_level_iter: None,
current_weight: 0,
};
iter.advance_to_next_level();
iter
}
fn advance_to_next_level(&mut self) {
while self.current_level < self.compactors.len() {
let compactor = &self.compactors[self.current_level];
let items_slice = compactor.items_slice();
if !items_slice.is_empty() {
self.current_level_iter = Some(items_slice.iter());
self.current_weight = compactor.weight();
return;
}
self.current_level += 1;
}
self.current_level_iter = None;
}
}
impl<'a, T> Iterator for ReqSketchIterator<'a, T>
where
T: Clone + TotalOrd + PartialEq,
{
type Item = (T, u64);
fn next(&mut self) -> Option<Self::Item> {
loop {
if let Some(ref mut level_iter) = self.current_level_iter {
if let Some(item) = level_iter.next() {
return Some((item.clone(), self.current_weight));
}
}
self.current_level += 1;
self.advance_to_next_level();
self.current_level_iter.as_ref()?;
}
}
}
pub struct CompactorIterator<'a, T>
where
T: Clone + TotalOrd + PartialEq,
{
items_iter: std::slice::Iter<'a, T>,
weight: u64,
}
impl<'a, T> CompactorIterator<'a, T>
where
T: Clone + TotalOrd + PartialEq,
{
pub fn new(compactor: &'a Compactor<T>) -> Self {
Self {
items_iter: compactor.items_slice().iter(),
weight: compactor.weight(),
}
}
}
impl<'a, T> Iterator for CompactorIterator<'a, T>
where
T: Clone + TotalOrd + PartialEq,
{
type Item = (T, u64);
fn next(&mut self) -> Option<Self::Item> {
self.items_iter
.next()
.map(|item| (item.clone(), self.weight))
}
}
#[cfg(test)]
mod tests {
use crate::ReqSketch;
#[test]
fn test_sketch_iterator() {
let mut sketch = ReqSketch::new();
for i in 0..10 {
sketch.update(i);
}
let items: Vec<(i32, u64)> = sketch.iter().collect();
assert_eq!(items.len(), 10);
for (_, weight) in &items {
assert_eq!(*weight, 1);
}
let values: Vec<i32> = items.into_iter().map(|(item, _)| item).collect();
for i in 0..10 {
assert!(values.contains(&i));
}
}
#[test]
fn test_empty_iterator() {
let sketch: ReqSketch<i32> = ReqSketch::new();
let items: Vec<(i32, u64)> = sketch.iter().collect();
assert!(items.is_empty());
}
}