diff --git a/backon/src/backoff/constant.rs b/backon/src/backoff/constant.rs index 277abd6..486ca34 100644 --- a/backon/src/backoff/constant.rs +++ b/backon/src/backoff/constant.rs @@ -41,6 +41,13 @@ pub struct ConstantBuilder { impl Default for ConstantBuilder { fn default() -> Self { + Self::new() + } +} + +impl ConstantBuilder { + /// Create a new `ConstantBuilder` with default values. + pub const fn new() -> Self { Self { delay: Duration::from_secs(1), max_times: Some(3), @@ -48,17 +55,15 @@ impl Default for ConstantBuilder { seed: None, } } -} -impl ConstantBuilder { /// Set the delay for the backoff. - pub fn with_delay(mut self, delay: Duration) -> Self { + pub const fn with_delay(mut self, delay: Duration) -> Self { self.delay = delay; self } /// Set the maximum number of attempts to be made. - pub fn with_max_times(mut self, max_times: usize) -> Self { + pub const fn with_max_times(mut self, max_times: usize) -> Self { self.max_times = Some(max_times); self } @@ -66,7 +71,7 @@ impl ConstantBuilder { /// Enable jitter for the backoff. /// /// Jitter is a random value added to the delay to prevent a thundering herd problem. - pub fn with_jitter(mut self) -> Self { + pub const fn with_jitter(mut self) -> Self { self.jitter = true; self } @@ -82,7 +87,7 @@ impl ConstantBuilder { /// The backoff will not stop by itself. /// /// _The backoff could stop reaching `usize::MAX` attempts but this is **unrealistic**._ - pub fn without_max_times(mut self) -> Self { + pub const fn without_max_times(mut self) -> Self { self.max_times = None; self } @@ -159,13 +164,16 @@ impl Iterator for ConstantBackoff { #[cfg(test)] mod tests { + use super::*; use core::time::Duration; #[cfg(target_arch = "wasm32")] use wasm_bindgen_test::wasm_bindgen_test as test; - use crate::BackoffBuilder; - use crate::ConstantBuilder; + const TEST_BUILDER: ConstantBuilder = ConstantBuilder::new() + .with_delay(Duration::from_secs(2)) + .with_max_times(5) + .with_jitter(); #[test] fn test_constant_default() { @@ -214,4 +222,13 @@ mod tests { assert_eq!(Some(Duration::from_secs(1)), it.next()); } } + + // allow assertions on constants because they are not optimized out by unit tests + #[allow(clippy::assertions_on_constants)] + #[test] + fn test_constant_const_builder() { + assert_eq!(TEST_BUILDER.delay, Duration::from_secs(2)); + assert_eq!(TEST_BUILDER.max_times, Some(5)); + assert!(TEST_BUILDER.jitter); + } } diff --git a/backon/src/backoff/exponential.rs b/backon/src/backoff/exponential.rs index 202c314..3bb32c2 100644 --- a/backon/src/backoff/exponential.rs +++ b/backon/src/backoff/exponential.rs @@ -46,6 +46,13 @@ pub struct ExponentialBuilder { impl Default for ExponentialBuilder { fn default() -> Self { + Self::new() + } +} + +impl ExponentialBuilder { + /// Create a new `ExponentialBuilder` with default values. + pub const fn new() -> Self { Self { jitter: false, factor: 2.0, @@ -55,14 +62,12 @@ impl Default for ExponentialBuilder { seed: None, } } -} -impl ExponentialBuilder { /// Enable jitter for the backoff. /// /// When jitter is enabled, [`ExponentialBackoff`] will add a random jitter within `(0, min_delay)` /// to the current delay. - pub fn with_jitter(mut self) -> Self { + pub const fn with_jitter(mut self) -> Self { self.jitter = true; self } @@ -78,7 +83,7 @@ impl ExponentialBuilder { /// # Panics /// /// This function will panic if the input factor is less than `1.0`. - pub fn with_factor(mut self, factor: f32) -> Self { + pub const fn with_factor(mut self, factor: f32) -> Self { debug_assert!(factor >= 1.0, "invalid factor that lower than 1"); self.factor = factor; @@ -86,7 +91,7 @@ impl ExponentialBuilder { } /// Set the minimum delay for the backoff. - pub fn with_min_delay(mut self, min_delay: Duration) -> Self { + pub const fn with_min_delay(mut self, min_delay: Duration) -> Self { self.min_delay = min_delay; self } @@ -94,7 +99,7 @@ impl ExponentialBuilder { /// Set the maximum delay for the backoff. /// /// The delay will not increase if the current delay exceeds the maximum delay. - pub fn with_max_delay(mut self, max_delay: Duration) -> Self { + pub const fn with_max_delay(mut self, max_delay: Duration) -> Self { self.max_delay = Some(max_delay); self } @@ -104,7 +109,7 @@ impl ExponentialBuilder { /// The delay will keep increasing. /// /// _The delay will saturate at `Duration::MAX` which is an **unrealistic** delay._ - pub fn without_max_delay(mut self) -> Self { + pub const fn without_max_delay(mut self) -> Self { self.max_delay = None; self } @@ -112,7 +117,7 @@ impl ExponentialBuilder { /// Set the maximum number of attempts for the current backoff. /// /// The backoff will stop if the maximum number of attempts is reached. - pub fn with_max_times(mut self, max_times: usize) -> Self { + pub const fn with_max_times(mut self, max_times: usize) -> Self { self.max_times = Some(max_times); self } @@ -122,7 +127,7 @@ impl ExponentialBuilder { /// The backoff will not stop by itself. /// /// _The backoff could stop reaching `usize::MAX` attempts but this is **unrealistic**._ - pub fn without_max_times(mut self) -> Self { + pub const fn without_max_times(mut self) -> Self { self.max_times = None; self } @@ -235,6 +240,13 @@ mod tests { use crate::BackoffBuilder; use crate::ExponentialBuilder; + const TEST_BUILDER: ExponentialBuilder = ExponentialBuilder::new() + .with_jitter() + .with_factor(1.5) + .with_min_delay(Duration::from_secs(2)) + .with_max_delay(Duration::from_secs(30)) + .with_max_times(5); + #[test] fn test_exponential_default() { let mut exp = ExponentialBuilder::default().build(); @@ -389,4 +401,15 @@ mod tests { assert_eq!(Some(Duration::from_secs(1)), exp.next()); assert_eq!(None, exp.next()); } + + // allow assertions on constants because they are not optimized out by unit tests + #[allow(clippy::assertions_on_constants)] + #[test] + fn test_exponential_const_builder() { + assert!(TEST_BUILDER.jitter); + assert_eq!(TEST_BUILDER.factor, 1.5); + assert_eq!(TEST_BUILDER.min_delay, Duration::from_secs(2)); + assert_eq!(TEST_BUILDER.max_delay, Some(Duration::from_secs(30))); + assert_eq!(TEST_BUILDER.max_times, Some(5)); + } } diff --git a/backon/src/backoff/fibonacci.rs b/backon/src/backoff/fibonacci.rs index 27bf5ae..22d13eb 100644 --- a/backon/src/backoff/fibonacci.rs +++ b/backon/src/backoff/fibonacci.rs @@ -44,6 +44,13 @@ pub struct FibonacciBuilder { impl Default for FibonacciBuilder { fn default() -> Self { + Self::new() + } +} + +impl FibonacciBuilder { + /// Create a new `FibonacciBuilder` with default values. + pub const fn new() -> Self { Self { jitter: false, seed: None, @@ -52,13 +59,11 @@ impl Default for FibonacciBuilder { max_times: Some(3), } } -} -impl FibonacciBuilder { /// Set the jitter for the backoff. /// /// When jitter is enabled, FibonacciBackoff will add a random jitter between `(0, min_delay)` to the delay. - pub fn with_jitter(mut self) -> Self { + pub const fn with_jitter(mut self) -> Self { self.jitter = true; self } @@ -70,7 +75,7 @@ impl FibonacciBuilder { } /// Set the minimum delay for the backoff. - pub fn with_min_delay(mut self, min_delay: Duration) -> Self { + pub const fn with_min_delay(mut self, min_delay: Duration) -> Self { self.min_delay = min_delay; self } @@ -78,7 +83,7 @@ impl FibonacciBuilder { /// Set the maximum delay for the current backoff. /// /// The delay will not increase if the current delay exceeds the maximum delay. - pub fn with_max_delay(mut self, max_delay: Duration) -> Self { + pub const fn with_max_delay(mut self, max_delay: Duration) -> Self { self.max_delay = Some(max_delay); self } @@ -88,7 +93,7 @@ impl FibonacciBuilder { /// The delay will keep increasing. /// /// _The delay will saturate at `Duration::MAX` which is an **unrealistic** delay._ - pub fn without_max_delay(mut self) -> Self { + pub const fn without_max_delay(mut self) -> Self { self.max_delay = None; self } @@ -96,7 +101,7 @@ impl FibonacciBuilder { /// Set the maximum number of attempts for the current backoff. /// /// The backoff will stop if the maximum number of attempts is reached. - pub fn with_max_times(mut self, max_times: usize) -> Self { + pub const fn with_max_times(mut self, max_times: usize) -> Self { self.max_times = Some(max_times); self } @@ -106,7 +111,7 @@ impl FibonacciBuilder { /// The backoff will not stop by itself. /// /// _The backoff could stop reaching `usize::MAX` attempts but this is **unrealistic**._ - pub fn without_max_times(mut self) -> Self { + pub const fn without_max_times(mut self) -> Self { self.max_times = None; self } @@ -212,13 +217,17 @@ impl Iterator for FibonacciBackoff { #[cfg(test)] mod tests { + use super::*; use core::time::Duration; #[cfg(target_arch = "wasm32")] use wasm_bindgen_test::wasm_bindgen_test as test; - use crate::BackoffBuilder; - use crate::FibonacciBuilder; + const TEST_BUILDER: FibonacciBuilder = FibonacciBuilder::new() + .with_jitter() + .with_min_delay(Duration::from_secs(2)) + .with_max_delay(Duration::from_secs(30)) + .with_max_times(5); #[test] fn test_fibonacci_default() { @@ -322,4 +331,14 @@ mod tests { assert_eq!(Some(Duration::from_secs(0)), fib.next()); } } + + // allow assertions on constants because they are not optimized out by unit tests + #[allow(clippy::assertions_on_constants)] + #[test] + fn test_fibonacci_const_builder() { + assert!(TEST_BUILDER.jitter); + assert_eq!(TEST_BUILDER.min_delay, Duration::from_secs(2)); + assert_eq!(TEST_BUILDER.max_delay, Some(Duration::from_secs(30))); + assert_eq!(TEST_BUILDER.max_times, Some(5)); + } }