infinity_sampler/rate.rs
1use core::hint::unreachable_unchecked;
2
3/// A simple sampler.
4///
5/// ```
6/// use infinity_sampler::SamplingRate;
7///
8/// let mut sampler = SamplingRate::new(2);
9/// assert_eq!(sampler.step(), false);
10/// assert_eq!(sampler.step(), true);
11/// assert_eq!(sampler.step(), false);
12/// assert_eq!(sampler.step(), true);
13///
14/// sampler.div(2);
15/// assert_eq!(sampler.step(), false);
16/// assert_eq!(sampler.step(), false);
17/// assert_eq!(sampler.step(), false);
18/// assert_eq!(sampler.step(), true);
19/// assert_eq!(sampler.step(), false);
20/// assert_eq!(sampler.step(), false);
21/// assert_eq!(sampler.step(), false);
22/// assert_eq!(sampler.step(), true);
23///
24#[derive(Copy, Clone)]
25pub struct SamplingRate {
26 divisor: u32,
27 counter: u32,
28}
29
30impl SamplingRate {
31 pub const fn new(divisor: u32) -> Self {
32 assert!(divisor > 0);
33 Self {
34 divisor,
35 counter: 0,
36 }
37 }
38
39 /// Returns true if the sampler should sample.
40 pub fn step(&mut self) -> bool {
41 if self.divisor == 0 {
42 unsafe { unreachable_unchecked() };
43 }
44 self.counter += 1;
45 self.counter %= self.divisor;
46 self.counter == 0
47 }
48
49 /// Reduce the sampling rate by a ratio.
50 pub fn div(&mut self, ratio: u32) {
51 assert!(ratio > 0);
52 self.divisor *= ratio;
53 }
54
55 pub fn divisor(&self) -> u32 {
56 self.divisor
57 }
58}