hdrhistogram/iterators/
linear.rs

1use crate::core::counter::Counter;
2use crate::iterators::{HistogramIterator, PickMetadata, PickyIterator};
3use crate::Histogram;
4
5/// An iterator that will yield at fixed-size steps through the histogram's value range.
6pub struct Iter<'a, T: 'a + Counter> {
7    hist: &'a Histogram<T>,
8
9    // > 0
10    value_units_per_bucket: u64,
11    current_step_highest_value_reporting_level: u64,
12    current_step_lowest_value_reporting_level: u64,
13}
14
15impl<'a, T: 'a + Counter> Iter<'a, T> {
16    /// Construct a new linear iterator. See `Histogram::iter_linear` for details.
17    pub fn new(
18        hist: &'a Histogram<T>,
19        value_units_per_bucket: u64,
20    ) -> HistogramIterator<'a, T, Iter<'a, T>> {
21        assert!(
22            value_units_per_bucket > 0,
23            "value_units_per_bucket must be > 0"
24        );
25
26        let new_lowest = hist.lowest_equivalent(value_units_per_bucket - 1);
27        HistogramIterator::new(
28            hist,
29            Iter {
30                hist,
31                value_units_per_bucket,
32                // won't underflow because value_units_per_bucket > 0
33                current_step_highest_value_reporting_level: value_units_per_bucket - 1,
34                current_step_lowest_value_reporting_level: new_lowest,
35            },
36        )
37    }
38}
39
40impl<'a, T: 'a + Counter> PickyIterator<T> for Iter<'a, T> {
41    fn pick(&mut self, index: usize, _: u64, _: T) -> Option<PickMetadata> {
42        let val = self.hist.value_for(index);
43        if val >= self.current_step_lowest_value_reporting_level || index == self.hist.last_index()
44        {
45            let metadata =
46                PickMetadata::new(None, Some(self.current_step_highest_value_reporting_level));
47            self.current_step_highest_value_reporting_level += self.value_units_per_bucket;
48            self.current_step_lowest_value_reporting_level = self
49                .hist
50                .lowest_equivalent(self.current_step_highest_value_reporting_level);
51            Some(metadata)
52        } else {
53            None
54        }
55    }
56
57    fn more(&mut self, index_to_pick: usize) -> bool {
58        // If the next iterate will not move to the next sub bucket index (which is empty if
59        // if we reached this point), then we are not yet done iterating (we want to iterate
60        // until we are no longer on a value that has a count, rather than until we first reach
61        // the last value that has a count. The difference is subtle but important)...
62        // When this is called, we're about to begin the "next" iteration, so
63        // current_step_highest_value_reporting_level has already been incremented,
64        // and we use it without incrementing its value.
65        let next_index = index_to_pick.checked_add(1).expect("usize overflow");
66        self.current_step_highest_value_reporting_level < self.hist.value_for(next_index)
67    }
68}