checkito/
standard.rs

1use crate::{
2    convert::Convert,
3    generate::{FullGenerate, Generate, State},
4    shrink::Shrink,
5};
6use core::{marker::PhantomData, mem::take};
7use std::{rc::Rc, sync::Arc};
8
9pub mod option {
10    use super::*;
11    use crate::generate::FullGenerate;
12
13    #[derive(Clone, Debug)]
14    pub struct Generator<G>(pub(crate) G);
15
16    #[derive(Debug, Clone)]
17    pub struct Shrinker<S>(bool, Option<S>);
18
19    impl<G: FullGenerate> FullGenerate for Option<G> {
20        type Generator = Generator<G::Generator>;
21        type Item = Option<G::Item>;
22
23        fn generator() -> Self::Generator {
24            Generator(G::generator())
25        }
26    }
27
28    impl<G: Generate> Generate for Generator<G> {
29        type Item = Option<G::Item>;
30        type Shrink = Shrinker<G::Shrink>;
31
32        fn generate(&self, state: &mut State) -> Self::Shrink {
33            if state.random().bool() {
34                Shrinker(true, Some(self.0.generate(state)))
35            } else {
36                Shrinker(false, None)
37            }
38        }
39
40        fn constant(&self) -> bool {
41            false
42        }
43    }
44
45    impl<G: Generate> Generate for Option<G> {
46        type Item = Option<G::Item>;
47        type Shrink = Shrinker<G::Shrink>;
48
49        fn generate(&self, state: &mut State) -> Self::Shrink {
50            Shrinker(
51                true,
52                self.as_ref().map(|generator| generator.generate(state)),
53            )
54        }
55
56        fn constant(&self) -> bool {
57            self.as_ref().map_or(true, Generate::constant)
58        }
59    }
60
61    impl<S: Shrink> Shrink for Shrinker<S> {
62        type Item = Option<S::Item>;
63
64        fn item(&self) -> Self::Item {
65            Some(self.1.as_ref()?.item())
66        }
67
68        fn shrink(&mut self) -> Option<Self> {
69            Some(if take(&mut self.0) {
70                Self(false, None)
71            } else {
72                Self(false, Some(self.1.as_mut()?.shrink()?))
73            })
74        }
75    }
76}
77
78pub mod result {
79    use super::*;
80
81    #[derive(Clone, Debug)]
82    pub struct Generator<T, E>(T, E);
83    #[derive(Clone, Debug)]
84    pub struct Shrinker<T, E>(Result<T, E>);
85
86    impl<T: FullGenerate, E: FullGenerate> FullGenerate for Result<T, E> {
87        type Generator = Generator<T::Generator, E::Generator>;
88        type Item = Result<T::Item, E::Item>;
89
90        fn generator() -> Self::Generator {
91            Generator(T::generator(), E::generator())
92        }
93    }
94
95    impl<T: Generate, E: Generate> Generate for Generator<T, E> {
96        type Item = Result<T::Item, E::Item>;
97        type Shrink = Shrinker<T::Shrink, E::Shrink>;
98
99        fn generate(&self, state: &mut State) -> Self::Shrink {
100            Shrinker(if state.random().bool() {
101                Ok(self.0.generate(state))
102            } else {
103                Err(self.1.generate(state))
104            })
105        }
106
107        fn constant(&self) -> bool {
108            false
109        }
110    }
111
112    impl<T: Generate, E: Generate> Generate for Result<T, E> {
113        type Item = Result<T::Item, E::Item>;
114        type Shrink = Shrinker<T::Shrink, E::Shrink>;
115
116        fn generate(&self, state: &mut State) -> Self::Shrink {
117            Shrinker(match self {
118                Ok(generator) => Ok(generator.generate(state)),
119                Err(generator) => Err(generator.generate(state)),
120            })
121        }
122
123        fn constant(&self) -> bool {
124            match self {
125                Ok(generator) => generator.constant(),
126                Err(generator) => generator.constant(),
127            }
128        }
129    }
130
131    impl<T: Shrink, E: Shrink> Shrink for Shrinker<T, E> {
132        type Item = Result<T::Item, E::Item>;
133
134        fn item(&self) -> Self::Item {
135            match &self.0 {
136                Ok(shrinker) => Ok(shrinker.item()),
137                Err(shrinker) => Err(shrinker.item()),
138            }
139        }
140
141        fn shrink(&mut self) -> Option<Self> {
142            Some(Self(match &mut self.0 {
143                Ok(shrinker) => Ok(shrinker.shrink()?),
144                Err(shrinker) => Err(shrinker.shrink()?),
145            }))
146        }
147    }
148}
149
150macro_rules! pointer {
151    ($m: ident, $t: ident) => {
152        mod $m {
153            use super::*;
154
155            impl<G: FullGenerate + ?Sized> FullGenerate for $t<G> {
156                type Generator = Convert<G::Generator, Self::Item>;
157                type Item = $t<G::Item>;
158
159                fn generator() -> Self::Generator {
160                    Convert(PhantomData, G::generator())
161                }
162            }
163
164            impl<G: Generate + ?Sized> Generate for $t<G> {
165                type Item = G::Item;
166                type Shrink = G::Shrink;
167
168                fn generate(&self, state: &mut State) -> Self::Shrink {
169                    G::generate(self, state)
170                }
171
172                fn constant(&self) -> bool {
173                    G::constant(self)
174                }
175            }
176        }
177    };
178}
179
180pointer!(boxed, Box);
181pointer!(rc, Rc);
182pointer!(arc, Arc);