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}