exponential_backoff/
into_iter.rs1use super::Backoff;
2use fastrand::Rng;
3use std::{iter, time::Duration};
4
5#[derive(Debug, Clone)]
7pub struct IntoIter {
8 inner: Backoff,
9 rng: Rng,
10 attempts: u32,
11}
12
13impl IntoIter {
14 pub(crate) fn new(inner: Backoff) -> Self {
15 Self {
16 attempts: 0,
17 rng: Rng::new(),
18 inner,
19 }
20 }
21}
22
23impl iter::Iterator for IntoIter {
24 type Item = Option<Duration>;
25
26 #[inline]
27 fn next(&mut self) -> Option<Self::Item> {
28 if self.attempts == self.inner.max_attempts {
32 return None;
33 } else if self.attempts == self.inner.max_attempts - 1 {
34 self.attempts = self.attempts.saturating_add(1);
35 return Some(None);
36 }
37
38 self.attempts = self.attempts.saturating_add(1);
39
40 let exponent = self.inner.factor.saturating_pow(self.attempts);
42 let duration = self.inner.min.saturating_mul(exponent);
43
44 let jitter_factor = (self.inner.jitter * 100f32) as u32;
46 let random = self.rng.u32(0..jitter_factor * 2);
47 let mut duration = duration.saturating_mul(100);
48 if random < jitter_factor {
49 let jitter = duration.saturating_mul(random) / 100;
50 duration = duration.saturating_sub(jitter);
51 } else {
52 let jitter = duration.saturating_mul(random / 2) / 100;
53 duration = duration.saturating_add(jitter);
54 };
55 duration /= 100;
56
57 duration = duration.clamp(self.inner.min, self.inner.max);
59
60 Some(Some(duration))
61 }
62}