1use crate::std_facade::{
19 binary_heap, btree_map, btree_set, fmt, linked_list, vec, vec_deque, Arc,
20 BTreeMap, BTreeSet, BinaryHeap, Box, LinkedList, Rc, Vec, VecDeque,
21};
22use core::hash::Hash;
23use core::ops::{Bound, RangeInclusive};
24
25#[cfg(feature = "std")]
26use crate::std_facade::{hash_map, hash_set, HashMap, HashSet};
27
28use crate::arbitrary::*;
29use crate::collection::*;
30use crate::strategy::statics::static_map;
31use crate::strategy::*;
32
33type RangedParams1<A> = product_type![SizeRange, A];
39
40type RangedParams2<A, B> = product_type![SizeRange, A, B];
42
43macro_rules! impl_1 {
44 ($typ: ident, $strat: ident, $($bound : path),* => $fun: ident) => {
45 arbitrary!([A: Arbitrary $(+ $bound)*] $typ<A>,
46 $strat<A::Strategy>, RangedParams1<A::Parameters>;
47 args => {
48 let product_unpack![range, a] = args;
49 $fun(any_with::<A>(a), range)
50 });
51
52 lift1!([$($bound+)*] $typ<A>, SizeRange;
53 base, args => $fun(base, args));
54 };
55}
56
57arbitrary!(SizeRange, MapInto<StrategyFor<RangeInclusive<usize>>, Self>;
58 any::<RangeInclusive<usize>>().prop_map_into()
59);
60
61macro_rules! dst_wrapped {
66 ($($w: ident),*) => {
67 $(arbitrary!([A: Arbitrary] $w<[A]>,
68 MapInto<StrategyFor<Vec<A>>, Self>,
69 <Vec<A> as Arbitrary>::Parameters;
70 a => any_with::<Vec<A>>(a).prop_map_into()
71 );)*
72 };
73}
74
75impl_1!(Vec, VecStrategy, => vec);
76dst_wrapped!(Box, Rc, Arc);
77impl_1!(VecDeque, VecDequeStrategy, => vec_deque);
78impl_1!(LinkedList, LinkedListStrategy, => linked_list);
79impl_1!(BTreeSet, BTreeSetStrategy, Ord => btree_set);
80impl_1!(BinaryHeap, BinaryHeapStrategy, Ord => binary_heap);
81#[cfg(feature = "std")]
82impl_1!(HashSet, HashSetStrategy, Hash, Eq => hash_set);
83
84macro_rules! into_iter_1 {
89 ($module: ident, $type: ident $(, $bound : path)*) => {
90 arbitrary!([A: Arbitrary $(+ $bound)*]
91 $module::IntoIter<A>,
92 SMapped<$type<A>, Self>,
93 <$type<A> as Arbitrary>::Parameters;
94 args => static_map(any_with::<$type<A>>(args), $type::into_iter));
95
96 lift1!(['static + $($bound+)*] $module::IntoIter<A>, SizeRange;
97 base, args =>
98 $module(base, args).prop_map($type::into_iter));
99 };
100}
101
102into_iter_1!(vec, Vec);
103into_iter_1!(vec_deque, VecDeque);
104into_iter_1!(linked_list, LinkedList);
105into_iter_1!(btree_set, BTreeSet, Ord);
106into_iter_1!(binary_heap, BinaryHeap, Ord);
107#[cfg(feature = "std")]
108into_iter_1!(hash_set, HashSet, Hash, Eq);
109
110#[cfg(feature = "std")]
115arbitrary!([A: Arbitrary + Hash + Eq, B: Arbitrary] HashMap<A, B>,
116HashMapStrategy<A::Strategy, B::Strategy>,
117RangedParams2<A::Parameters, B::Parameters>;
118args => {
119 let product_unpack![range, a, b] = args;
120 hash_map(any_with::<A>(a), any_with::<B>(b), range)
121});
122
123#[cfg(feature = "std")]
124arbitrary!([A: Arbitrary + Hash + Eq, B: Arbitrary] hash_map::IntoIter<A, B>,
125 SMapped<HashMap<A, B>, Self>,
126 <HashMap<A, B> as Arbitrary>::Parameters;
127 args => static_map(any_with::<HashMap<A, B>>(args), HashMap::into_iter));
128
129#[cfg(feature = "std")]
130lift1!([, K: Hash + Eq + Arbitrary + 'static] HashMap<K, A>,
131 RangedParams1<K::Parameters>;
132 base, args => {
133 let product_unpack![range, k] = args;
134 hash_map(any_with::<K>(k), base, range)
135 }
136);
137
138#[cfg(feature = "std")]
139lift1!(['static, K: Hash + Eq + Arbitrary + 'static] hash_map::IntoIter<K, A>,
140 RangedParams1<K::Parameters>;
141 base, args => {
142 let product_unpack![range, k] = args;
143 static_map(hash_map(any_with::<K>(k), base, range), HashMap::into_iter)
144 }
145);
146
147#[cfg(feature = "std")]
148impl<A: fmt::Debug + Eq + Hash, B: fmt::Debug> functor::ArbitraryF2<A, B>
149 for HashMap<A, B>
150{
151 type Parameters = SizeRange;
152
153 fn lift2_with<AS, BS>(
154 fst: AS,
155 snd: BS,
156 args: Self::Parameters,
157 ) -> BoxedStrategy<Self>
158 where
159 AS: Strategy<Value = A> + 'static,
160 BS: Strategy<Value = B> + 'static,
161 {
162 hash_map(fst, snd, args).boxed()
163 }
164}
165
166#[cfg(feature = "std")]
167impl<A: fmt::Debug + Eq + Hash + 'static, B: fmt::Debug + 'static>
168 functor::ArbitraryF2<A, B> for hash_map::IntoIter<A, B>
169{
170 type Parameters = SizeRange;
171
172 fn lift2_with<AS, BS>(
173 fst: AS,
174 snd: BS,
175 args: Self::Parameters,
176 ) -> BoxedStrategy<Self>
177 where
178 AS: Strategy<Value = A> + 'static,
179 BS: Strategy<Value = B> + 'static,
180 {
181 static_map(hash_map(fst, snd, args), HashMap::into_iter).boxed()
182 }
183}
184
185arbitrary!([A: Arbitrary + Ord, B: Arbitrary] BTreeMap<A, B>,
190BTreeMapStrategy<A::Strategy, B::Strategy>,
191RangedParams2<A::Parameters, B::Parameters>;
192args => {
193 let product_unpack![range, a, b] = args;
194 btree_map(any_with::<A>(a), any_with::<B>(b), range)
195});
196
197lift1!([, K: Ord + Arbitrary + 'static] BTreeMap<K, A>,
198 RangedParams1<K::Parameters>;
199 base, args => {
200 let product_unpack![range, k] = args;
201 btree_map(any_with::<K>(k), base, range)
202 }
203);
204
205impl<A: fmt::Debug + Ord, B: fmt::Debug> functor::ArbitraryF2<A, B>
206 for BTreeMap<A, B>
207{
208 type Parameters = SizeRange;
209 fn lift2_with<AS, BS>(
210 fst: AS,
211 snd: BS,
212 args: Self::Parameters,
213 ) -> BoxedStrategy<Self>
214 where
215 AS: Strategy<Value = A> + 'static,
216 BS: Strategy<Value = B> + 'static,
217 {
218 btree_map(fst, snd, args).boxed()
219 }
220}
221
222arbitrary!([A: Arbitrary + Ord, B: Arbitrary] btree_map::IntoIter<A, B>,
223 SMapped<BTreeMap<A, B>, Self>,
224 <BTreeMap<A, B> as Arbitrary>::Parameters;
225 args => static_map(any_with::<BTreeMap<A, B>>(args), BTreeMap::into_iter));
226
227impl<A: fmt::Debug + Ord + 'static, B: fmt::Debug + 'static>
228 functor::ArbitraryF2<A, B> for btree_map::IntoIter<A, B>
229{
230 type Parameters = SizeRange;
231
232 fn lift2_with<AS, BS>(
233 fst: AS,
234 snd: BS,
235 args: Self::Parameters,
236 ) -> BoxedStrategy<Self>
237 where
238 AS: Strategy<Value = A> + 'static,
239 BS: Strategy<Value = B> + 'static,
240 {
241 static_map(btree_map(fst, snd, args), BTreeMap::into_iter).boxed()
242 }
243}
244
245arbitrary!([A: Arbitrary] Bound<A>,
250 TupleUnion<(
251 WA<SFnPtrMap<Arc<A::Strategy>, Self>>,
252 WA<SFnPtrMap<Arc<A::Strategy>, Self>>,
253 WA<LazyJustFn<Self>>
254 )>,
255 A::Parameters;
256 args => {
257 let base = Arc::new(any_with::<A>(args));
258 prop_oneof![
259 2 => static_map(base.clone(), Bound::Included),
260 2 => static_map(base, Bound::Excluded),
261 1 => LazyJust::new(|| Bound::Unbounded),
262 ]
263 }
264);
265
266lift1!(['static] Bound<A>; base => {
267 let base = Rc::new(base);
268 prop_oneof![
269 2 => base.clone().prop_map(Bound::Included),
270 2 => base.prop_map(Bound::Excluded),
271 1 => LazyJustFn::new(|| Bound::Unbounded),
272 ]
273});
274
275#[cfg(test)]
276mod test {
277 no_panic_test!(
278 size_bounds => SizeRange,
279 vec => Vec<u8>,
280 box_slice => Box<[u8]>,
281 rc_slice => Rc<[u8]>,
282 arc_slice => Arc<[u8]>,
283 vec_deque => VecDeque<u8>,
284 linked_list => LinkedList<u8>,
285 btree_set => BTreeSet<u8>,
286 btree_map => BTreeMap<u8, u8>,
287 bound => Bound<u8>,
288 binary_heap => BinaryHeap<u8>,
289 into_iter_vec => vec::IntoIter<u8>,
290 into_iter_vec_deque => vec_deque::IntoIter<u8>,
291 into_iter_linked_list => linked_list::IntoIter<u8>,
292 into_iter_binary_heap => binary_heap::IntoIter<u8>,
293 into_iter_btree_set => btree_set::IntoIter<u8>,
294 into_iter_btree_map => btree_map::IntoIter<u8, u8>
295 );
296
297 #[cfg(feature = "std")]
298 no_panic_test!(
299 hash_set => HashSet<u8>,
300 hash_map => HashMap<u8, u8>,
301 into_iter_hash_set => hash_set::IntoIter<u8>,
302 into_iter_hash_map => hash_map::IntoIter<u8, u8>
303 );
304}