use std::time::Duration;
use std::u64::MAX as U64_MAX;
#[cfg(feature = "random")]
mod random;
#[cfg(feature = "random")]
pub use random::{jitter, Range};
#[derive(Debug)]
pub struct Opportunity(pub Vec<u64>);
impl IntoIterator for Opportunity {
type Item = Duration;
type IntoIter = std::iter::Map<std::vec::IntoIter<u64>, fn(u64) -> Duration>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter().map(Duration::from_millis)
}
}
#[test]
fn test_opportunity() {
let mut iter = Opportunity(vec![100, 200, 300]).into_iter();
assert_eq!(iter.next(), Some(Duration::from_millis(100)));
assert_eq!(iter.next(), Some(Duration::from_millis(200)));
assert_eq!(iter.next(), Some(Duration::from_millis(300)));
assert_eq!(iter.next(), None);
}
#[derive(Debug)]
pub struct Exponential {
current: u64,
factor: f64,
}
impl Exponential {
pub fn from_millis(base: u64) -> Self {
Exponential {
current: base,
factor: 2.0,
}
}
pub fn from_millis_with_base_factor(base: u64) -> Self {
Exponential {
current: base,
factor: base as f64,
}
}
pub fn from_millis_with_factor(base: u64, factor: f64) -> Self {
Exponential {
current: base,
factor,
}
}
}
impl Iterator for Exponential {
type Item = Duration;
fn next(&mut self) -> Option<Duration> {
let duration = Duration::from_millis(self.current);
let next = (self.current as f64) * self.factor;
self.current = if next > (U64_MAX as f64) {
U64_MAX
} else {
next as u64
};
Some(duration)
}
}
impl From<Duration> for Exponential {
fn from(duration: Duration) -> Self {
Self::from_millis(duration.as_millis() as u64)
}
}
#[test]
fn exponential_with_factor() {
let mut iter = Exponential::from_millis_with_factor(1000, 2.0);
assert_eq!(iter.next(), Some(Duration::from_millis(1000)));
assert_eq!(iter.next(), Some(Duration::from_millis(2000)));
assert_eq!(iter.next(), Some(Duration::from_millis(4000)));
assert_eq!(iter.next(), Some(Duration::from_millis(8000)));
assert_eq!(iter.next(), Some(Duration::from_millis(16000)));
assert_eq!(iter.next(), Some(Duration::from_millis(32000)));
}
#[test]
fn exponential_overflow() {
let mut iter = Exponential::from_millis(U64_MAX);
assert_eq!(iter.next(), Some(Duration::from_millis(U64_MAX)));
assert_eq!(iter.next(), Some(Duration::from_millis(U64_MAX)));
}
#[derive(Debug)]
pub struct Fibonacci {
curr: u64,
next: u64,
}
impl Fibonacci {
pub fn from_millis(millis: u64) -> Fibonacci {
Fibonacci {
curr: millis,
next: millis,
}
}
}
impl Iterator for Fibonacci {
type Item = Duration;
fn next(&mut self) -> Option<Duration> {
let duration = Duration::from_millis(self.curr);
if let Some(next_next) = self.curr.checked_add(self.next) {
self.curr = self.next;
self.next = next_next;
} else {
self.curr = self.next;
self.next = U64_MAX;
}
Some(duration)
}
}
impl From<Duration> for Fibonacci {
fn from(duration: Duration) -> Self {
Self::from_millis(duration.as_millis() as u64)
}
}
#[test]
fn fibonacci() {
let mut iter = Fibonacci::from_millis(10);
assert_eq!(iter.next(), Some(Duration::from_millis(10)));
assert_eq!(iter.next(), Some(Duration::from_millis(10)));
assert_eq!(iter.next(), Some(Duration::from_millis(20)));
assert_eq!(iter.next(), Some(Duration::from_millis(30)));
assert_eq!(iter.next(), Some(Duration::from_millis(50)));
assert_eq!(iter.next(), Some(Duration::from_millis(80)));
}
#[test]
fn fibonacci_saturated() {
let mut iter = Fibonacci::from_millis(U64_MAX);
assert_eq!(iter.next(), Some(Duration::from_millis(U64_MAX)));
assert_eq!(iter.next(), Some(Duration::from_millis(U64_MAX)));
}
#[derive(Debug)]
pub struct Fixed {
duration: Duration,
}
impl Fixed {
pub fn from_millis(millis: u64) -> Self {
Fixed {
duration: Duration::from_millis(millis),
}
}
}
impl Iterator for Fixed {
type Item = Duration;
fn next(&mut self) -> Option<Duration> {
Some(self.duration)
}
}
impl From<Duration> for Fixed {
fn from(delay: Duration) -> Self {
Self {
duration: delay.into(),
}
}
}
#[derive(Debug)]
pub struct NoDelay;
impl Iterator for NoDelay {
type Item = Duration;
fn next(&mut self) -> Option<Duration> {
Some(Duration::default())
}
}