tower_fault/latency/
distribution.rs1use rand::Rng;
2use std::{ops, time::Duration};
3
4pub trait Distribution<R> {
6 fn sample(&self, req: &R) -> Duration;
8}
9
10macro_rules! impl_distribution_fixed {
11 ($t:ty, $ret:tt) => {
12 impl<R> Distribution<R> for $t {
13 fn sample(&self, _req: &R) -> Duration {
14 #[allow(clippy::redundant_closure_call)]
15 $ret(*self)
16 }
17 }
18 };
19}
20impl_distribution_fixed! { f64, (|value| Duration::from_secs_f64(value / 1000.0)) }
21impl_distribution_fixed! { u64, (Duration::from_millis) }
22impl_distribution_fixed! { Duration, (|value| value) }
23
24macro_rules! impl_distribution_range {
25 ($t:ty, $ret:tt) => {
26 impl<R> Distribution<R> for ops::Range<$t> {
27 fn sample(&self, _req: &R) -> Duration {
28 let mut rng = rand::thread_rng();
29 let value = rng.gen_range(self.clone());
30 #[allow(clippy::redundant_closure_call)]
31 $ret(value)
32 }
33 }
34
35 impl<R> Distribution<R> for ops::RangeInclusive<$t> {
36 fn sample(&self, _req: &R) -> Duration {
37 let mut rng = rand::thread_rng();
38 let value = rng.gen_range(self.clone());
39 #[allow(clippy::redundant_closure_call)]
40 $ret(value)
41 }
42 }
43 };
44}
45impl_distribution_range! { f64, (|value| Duration::from_secs_f64(value / 1000.0)) }
46impl_distribution_range! { u64, (Duration::from_millis) }
47impl_distribution_range! { Duration, (|value| value) }
48
49impl<F, R> Distribution<R> for F
50where
51 F: Fn(&R) -> Duration,
52{
53 fn sample(&self, req: &R) -> Duration {
54 self(req)
55 }
56}