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
#[derive(Debug, PartialEq)]
pub struct BackoffAlgorithm {
pub max: usize,
pub base: usize,
power: usize,
pub value: usize,
pub rand: Option<usize>,
}
impl BackoffAlgorithm {
pub fn new(base: usize, max: usize, rand: Option<usize>) -> BackoffAlgorithm {
BackoffAlgorithm {
base,
max,
power: base,
value: base,
rand,
}
}
pub fn get(&self) -> usize {
self.value
}
}
impl Iterator for BackoffAlgorithm {
type Item = usize;
fn next(&mut self) -> Option<Self::Item> {
self.value = self.power + self.rand.unwrap_or_default() % self.power;
self.power += self.power;
if self.value <= self.max {
Some(self.value)
} else {
None
}
}
}
#[cfg(test)]
mod tests {
use rand::random;
use crate::backoff_algo;
#[test]
fn next_test() {
let mut bfa = backoff_algo::BackoffAlgorithm::new(1, 16, None);
assert_eq!(bfa.next(), Some(1));
assert_eq!(bfa.get(), 1);
assert_eq!(bfa.next(), Some(2));
assert_eq!(bfa.get(), 2);
assert_eq!(bfa.next(), Some(4));
assert_eq!(bfa.get(), 4);
assert_eq!(bfa.next(), Some(8));
assert_eq!(bfa.next(), Some(16));
assert_eq!(bfa.get(), 16);
assert_eq!(bfa.next(), None);
assert_eq!(bfa.get(), 32);
}
#[test]
fn next_with_random_test() {
let mut bfa = backoff_algo::BackoffAlgorithm::new(8, 64, random());
println!("{}", bfa.get());
assert!(bfa.next() <= Some(16));
println!("{}", bfa.get());
assert!(bfa.next() <= Some(32));
println!("{}", bfa.get());
assert!(bfa.next() <= Some(64));
println!("{}", bfa.get());
}
}