1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
use std::{
ops::{Range as StdRange, RangeInclusive},
time::Duration,
};
use rand::{
distributions::{Distribution, Uniform},
random,
rngs::ThreadRng,
thread_rng,
};
#[derive(Debug)]
pub struct Range {
distribution: Uniform<u64>,
rng: ThreadRng,
}
impl Range {
pub fn from_millis_exclusive(minimum: u64, maximum: u64) -> Self {
Range {
distribution: Uniform::new(minimum, maximum),
rng: thread_rng(),
}
}
pub fn from_millis_inclusive(minimum: u64, maximum: u64) -> Self {
Range {
distribution: Uniform::new_inclusive(minimum, maximum),
rng: thread_rng(),
}
}
}
impl Iterator for Range {
type Item = Duration;
fn next(&mut self) -> Option<Duration> {
Some(Duration::from_millis(
self.distribution.sample(&mut self.rng),
))
}
}
impl From<StdRange<Duration>> for Range {
fn from(range: StdRange<Duration>) -> Self {
Self::from_millis_exclusive(range.start.as_millis() as u64, range.end.as_millis() as u64)
}
}
impl From<RangeInclusive<Duration>> for Range {
fn from(range: RangeInclusive<Duration>) -> Self {
Self::from_millis_inclusive(
range.start().as_millis() as u64,
range.end().as_millis() as u64,
)
}
}
pub fn jitter(duration: Duration) -> Duration {
let jitter = random::<f64>();
let secs = ((duration.as_secs() as f64) * jitter).ceil() as u64;
let nanos = ((f64::from(duration.subsec_nanos())) * jitter).ceil() as u32;
Duration::new(secs, nanos)
}
#[test]
fn range_uniform() {
let mut range = Range::from_millis_exclusive(0, 1);
assert_eq!(Duration::from_millis(0), range.next().unwrap());
assert_eq!(Duration::from_millis(0), range.next().unwrap());
assert_eq!(Duration::from_millis(0), range.next().unwrap());
}
#[test]
#[should_panic]
fn range_uniform_wrong_input() {
Range::from_millis_exclusive(0, 0);
}
#[test]
fn test_jitter() {
assert_eq!(Duration::from_millis(0), jitter(Duration::from_millis(0)));
assert!(Duration::from_millis(0) < jitter(Duration::from_millis(2)));
}