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);