bolero_generator/
time.rs

1use crate::{
2    bounded::{BoundExt, BoundedValue},
3    Driver, TypeGenerator, TypeGeneratorWithParams, TypeValueGenerator, ValueGenerator,
4};
5use core::{ops::Range, time::Duration};
6
7pub struct DurationGenerator<Seconds, Nanos> {
8    seconds: Seconds,
9    nanos: Nanos,
10}
11
12const VALID_NANOS_RANGE: Range<u32> = 0..1_000_000_000;
13
14impl<Seconds, Nanos> DurationGenerator<Seconds, Nanos>
15where
16    Seconds: ValueGenerator<Output = u64>,
17    Nanos: ValueGenerator<Output = u32>,
18{
19    pub fn seconds<NewS: ValueGenerator<Output = u64>>(
20        self,
21        seconds: NewS,
22    ) -> DurationGenerator<NewS, Nanos> {
23        DurationGenerator {
24            seconds,
25            nanos: self.nanos,
26        }
27    }
28
29    pub fn map_seconds<NewS: ValueGenerator<Output = u64>, F: Fn(Seconds) -> NewS>(
30        self,
31        map: F,
32    ) -> DurationGenerator<NewS, Nanos> {
33        DurationGenerator {
34            seconds: map(self.seconds),
35            nanos: self.nanos,
36        }
37    }
38
39    pub fn nanos<NewE: ValueGenerator<Output = u32>>(
40        self,
41        nanos: NewE,
42    ) -> DurationGenerator<Seconds, NewE> {
43        DurationGenerator {
44            seconds: self.seconds,
45            nanos,
46        }
47    }
48
49    pub fn map_nanos<NewE: ValueGenerator<Output = u64>, F: Fn(Nanos) -> NewE>(
50        self,
51        map: F,
52    ) -> DurationGenerator<Seconds, NewE> {
53        DurationGenerator {
54            seconds: self.seconds,
55            nanos: map(self.nanos),
56        }
57    }
58}
59
60impl<Seconds, Nanos> ValueGenerator for DurationGenerator<Seconds, Nanos>
61where
62    Seconds: ValueGenerator<Output = u64>,
63    Nanos: ValueGenerator<Output = u32>,
64{
65    type Output = Duration;
66
67    fn generate<D: Driver>(&self, driver: &mut D) -> Option<Self::Output> {
68        driver.enter_product::<Duration, _, _>(|driver| {
69            let seconds = self.seconds.generate(driver);
70            let nanos = self.nanos.generate(driver);
71            Some(Duration::new(seconds?, nanos?))
72        })
73    }
74
75    fn mutate<D: Driver>(&self, driver: &mut D, value: &mut Duration) -> Option<()> {
76        driver.enter_product::<Duration, _, _>(|driver| {
77            let mut seconds = value.as_secs();
78            self.seconds.mutate(driver, &mut seconds)?;
79            let mut nanos = value.subsec_nanos();
80            self.nanos.mutate(driver, &mut nanos)?;
81            *value = Duration::new(seconds, nanos);
82            Some(())
83        })
84    }
85}
86
87impl TypeGenerator for Duration {
88    fn generate<D: Driver>(driver: &mut D) -> Option<Self> {
89        Self::gen_with().generate(driver)
90    }
91
92    fn mutate<D: Driver>(&mut self, driver: &mut D) -> Option<()> {
93        Self::gen_with().mutate(driver, self)
94    }
95}
96
97impl TypeGeneratorWithParams for Duration {
98    type Output = DurationGenerator<TypeValueGenerator<u64>, Range<u32>>;
99
100    fn gen_with() -> Self::Output {
101        DurationGenerator {
102            seconds: Default::default(),
103            nanos: VALID_NANOS_RANGE,
104        }
105    }
106}
107
108impl BoundedValue for Duration {
109    #[inline]
110    fn gen_bounded<D: Driver>(
111        driver: &mut D,
112        min: core::ops::Bound<&Self>,
113        max: core::ops::Bound<&Self>,
114    ) -> Option<Self> {
115        let min = BoundExt::map(min, |min| min.as_nanos());
116        let max = BoundExt::map(max, |max| max.as_nanos());
117        let value = u128::gen_bounded(driver, BoundExt::as_ref(&min), BoundExt::as_ref(&max))?;
118        let value = value.try_into().ok()?;
119        let value = Duration::from_nanos(value);
120        Some(value)
121    }
122}
123
124#[test]
125fn duration_test() {
126    let _ = generator_test!(produce::<Duration>());
127}