launchdarkly_server_sdk/
sampler.rs

1use rand::Rng;
2
3pub trait Sampler {
4    fn sample(&mut self, ratio: u32) -> bool;
5}
6
7pub struct ThreadRngSampler<R: Rng> {
8    rng: R,
9}
10
11impl<R: Rng> ThreadRngSampler<R> {
12    pub fn new(rng: R) -> Self {
13        ThreadRngSampler { rng }
14    }
15}
16
17impl<R: Rng> Sampler for ThreadRngSampler<R> {
18    fn sample(&mut self, ratio: u32) -> bool {
19        if ratio == 0 {
20            return false;
21        }
22
23        if ratio == 1 {
24            return true;
25        }
26
27        self.rng.random_ratio(1, ratio)
28    }
29}
30
31#[cfg(test)]
32mod tests {
33    use rand::{rngs::StdRng, SeedableRng};
34
35    use super::*;
36
37    #[test]
38    fn test_zero_is_false() {
39        let mut sampler = ThreadRngSampler::new(rand::rng());
40        assert!(!sampler.sample(0));
41    }
42
43    #[test]
44    fn test_one_is_true() {
45        let mut sampler = ThreadRngSampler::new(rand::rng());
46        assert!(sampler.sample(1));
47    }
48
49    #[test]
50    fn test_can_affect_sampling_ratio() {
51        let rng = StdRng::seed_from_u64(0);
52        let mut sampler = ThreadRngSampler::new(rng);
53        let sampled_size = (0..1_000).filter(|_| sampler.sample(10)).count();
54
55        assert_eq!(sampled_size, 110);
56    }
57}