use crate::fixed_frequency::storage::LevelMetadata;
pub struct LevelView<'a, T> {
data: &'a [T],
level: &'a LevelMetadata,
}
impl<'a, T> LevelView<'a, T> {
pub(crate) fn new(data: &'a [T], level: &'a LevelMetadata) -> Self { Self { data, level } }
pub fn len(&self) -> usize { self.level.sample_capacity() }
pub fn is_empty(&self) -> bool { self.len() == 0 }
pub fn get(&self, index: usize) -> Option<&'a T> {
if index >= self.len() {
return None;
}
Some(&self.data[self.level.readable_position(index)])
}
pub fn iter_oldest_first(&self) -> LevelIter<'a, T> {
LevelIter {
data: self.data,
level: self.level,
index: 0,
}
}
}
pub struct LevelIter<'a, T> {
data: &'a [T],
level: &'a LevelMetadata,
index: usize,
}
impl<'a, T> Iterator for LevelIter<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
if self.index >= self.level.sample_capacity() {
return None;
}
let pos = self.level.readable_position(self.index);
self.index += 1;
Some(&self.data[pos])
}
fn size_hint(&self) -> (usize, Option<usize>) {
let remaining = self.level.sample_capacity() - self.index;
(remaining, Some(remaining))
}
}
impl<T> ExactSizeIterator for LevelIter<'_, T> {}
#[cfg(all(test, feature = "reducers"))]
mod tests {
use crate::{FixedFrequencyBuilder, FixedWriter, reducers};
use alloc::vec::Vec;
use core::num::NonZeroUsize;
const fn nz(value: usize) -> NonZeroUsize { NonZeroUsize::new(value).expect("expected non-zero value") }
fn storage() -> FixedWriter<f32> {
FixedFrequencyBuilder::new(nz(3))
.level(nz(2), nz(2), reducers::average_f32())
.build()
}
#[test]
fn view_get_skips_aggregation_window() {
let mut s = storage();
for value in 1..=9 {
s.push(value as f32);
}
let view = s.storage().level(0).unwrap();
assert_eq!(view.len(), 3);
assert!(!view.is_empty());
assert_eq!(view.get(0), Some(&7.0));
assert_eq!(view.get(1), Some(&8.0));
assert_eq!(view.get(2), Some(&9.0));
assert_eq!(view.get(3), None);
}
#[test]
fn iter_yields_oldest_first_after_wraparound() {
let mut s = storage();
for value in 1..=9 {
s.push(value as f32);
}
let values: Vec<_> = s.storage().level(0).unwrap().iter_oldest_first().copied().collect();
assert_eq!(values, [7.0, 8.0, 9.0]);
}
#[test]
fn final_level_view_reads_all_slots() {
let mut s = storage();
for value in 1..=9 {
s.push(value as f32);
}
let values: Vec<_> = s.storage().level(1).unwrap().iter_oldest_first().copied().collect();
assert_eq!(values, [3.5, 5.5]);
}
#[test]
fn iter_size_hint_tracks_remaining_items() {
let mut s = storage();
for value in 1..=9 {
s.push(value as f32);
}
let view = s.storage().level(0).unwrap();
let mut iter = view.iter_oldest_first();
assert_eq!(iter.size_hint(), (3, Some(3)));
assert_eq!(iter.next(), Some(&7.0));
assert_eq!(iter.size_hint(), (2, Some(2)));
assert_eq!(iter.next(), Some(&8.0));
assert_eq!(iter.next(), Some(&9.0));
assert_eq!(iter.size_hint(), (0, Some(0)));
assert_eq!(iter.next(), None);
}
}