proptest_arbitrary/_std/
collections.rs

1//! Arbitrary implementations for `std::collections`.
2
3#![cfg_attr(feature="cargo-clippy", allow(implicit_hasher))]
4
5//==============================================================================
6// Imports:
7//==============================================================================
8
9use super::*;
10
11use std::hash::Hash;
12use std::vec::Vec;
13use std::rc::Rc;
14use std::sync::Arc;
15use std::collections::*;
16
17use proptest::collection::*;
18
19//==============================================================================
20// Macros:
21//==============================================================================
22
23/// Parameters for configuring the generation of `StrategyFor<...<A>>`.
24type RangedParams1<A> = product_type![SizeBounds, A];
25
26/// Parameters for configuring the generation of `StrategyFor<...<A, B>>`.
27type RangedParams2<A, B> = product_type![SizeBounds, A, B];
28
29macro_rules! impl_1 {
30    ($typ: ident, $strat: ident, $($bound : path),* => $fun: ident) => {
31        arbitrary!([A: Arbitrary<'a> $(+ $bound)*] $typ<A>,
32            $strat<A::Strategy>, RangedParams1<A::Parameters>;
33            args => {
34                let product_unpack![range, a] = args;
35                $fun(any_with::<A>(a), range.into())
36            });
37    };
38}
39
40macro_rules! impl_2 {
41    ($typ: ident, $strat: ident, $($bound : path),* => $fun: ident) => {
42        arbitrary!([A: Arbitrary<'a> $(+ $bound)*, B: Arbitrary<'a>]
43            $typ<A, B>, $strat<A::Strategy, B::Strategy>,
44            RangedParams2<A::Parameters, B::Parameters>;
45            args => {
46                let product_unpack![range, a, b] = args;
47                $fun(any_with::<A>(a), any_with::<B>(b), range.into())
48            });
49    };
50}
51
52//==============================================================================
53// Vec, VecDeque, LinkedList, BTreeSet, BinaryHeap, HashSet, HashMap:
54//==============================================================================
55
56macro_rules! dst_wrapped {
57    ($($w: ident),*) => {
58        $(arbitrary!([A: Arbitrary<'a>] $w<[A]>,
59            FMapped<'a, Vec<A>, Self>, <Vec<A> as Arbitrary<'a>>::Parameters;
60            a => any_with_sinto::<Vec<A>, _>(a)
61        );)*
62    };
63}
64
65impl_1!(Vec, VecStrategy, => vec);
66dst_wrapped!(Box, Rc, Arc);
67impl_1!(VecDeque, VecDequeStrategy, => vec_deque);
68impl_1!(LinkedList, LinkedListStrategy, => linked_list);
69impl_1!(BTreeSet, BTreeSetStrategy, Ord => btree_set);
70impl_1!(BinaryHeap, BinaryHeapStrategy, Ord => binary_heap);
71impl_1!(HashSet, HashSetStrategy, Hash, Eq => hash_set);
72impl_2!(HashMap, HashMapStrategy, Hash, Eq => hash_map);
73
74//==============================================================================
75// BTreeMap:
76//==============================================================================
77
78impl<'a, A, B> Arbitrary<'a> for BTreeMap<A, B>
79where
80    A: Arbitrary<'static> + Ord,
81    B: Arbitrary<'static>,
82    StrategyFor<A>: 'static,
83    StrategyFor<B>: 'static,
84{
85    valuetree!();
86    type Parameters = RangedParams2<A::Parameters, B::Parameters>;
87    type Strategy = BTreeMapStrategy<A::Strategy, B::Strategy>;
88    fn arbitrary_with(args: Self::Parameters) -> Self::Strategy {
89        let product_unpack![range, a, b] = args;
90        btree_map(any_with::<A>(a), any_with::<B>(b), range.into())
91    }
92}
93
94//==============================================================================
95// IntoIterator:
96//==============================================================================
97
98macro_rules! into_iter_1 {
99    ($module: ident, $type: ident $(, $bound : path)*) => {
100        arbitrary!([A: Arbitrary<'a> $(+ $bound)*]
101            $module::IntoIter<A>,
102            SMapped<'a, $type<A>, Self>,
103            <$type<A> as Arbitrary<'a>>::Parameters;
104            args => any_with_smap(args, $type::into_iter));
105    };
106}
107
108macro_rules! into_iter_2 {
109    ($module: ident, $type: ident $(, $bound : path)*) => {
110        arbitrary!([A: Arbitrary<'a> $(+ $bound)*, B: Arbitrary<'a>]
111            $module::IntoIter<A, B>,
112            SMapped<'a, $type<A, B>, Self>,
113            <$type<A, B> as Arbitrary<'a>>::Parameters;
114            args => any_with_smap(args, $type::into_iter));
115    };
116}
117
118use std::vec;
119into_iter_1!(vec, Vec);
120use std::collections::vec_deque;
121into_iter_1!(vec_deque, VecDeque);
122use std::collections::linked_list;
123into_iter_1!(linked_list, LinkedList);
124use std::collections::btree_set;
125into_iter_1!(btree_set, BTreeSet, Ord);
126use std::collections::binary_heap;
127into_iter_1!(binary_heap, BinaryHeap, Ord);
128use std::collections::hash_set;
129into_iter_1!(hash_set, HashSet, Hash, Eq);
130use std::collections::hash_map;
131into_iter_2!(hash_map, HashMap, Hash, Eq);
132
133use std::collections::btree_map;
134
135impl<'a, A, B> Arbitrary<'a> for btree_map::IntoIter<A, B>
136where
137    A: Arbitrary<'static> + Ord,
138    B: Arbitrary<'static>,
139    StrategyFor<A>: 'static,
140    StrategyFor<B>: 'static,
141{
142    valuetree!();
143    type Parameters = <BTreeMap<A, B> as Arbitrary<'a>>::Parameters;
144    type Strategy = SMapped<'a, BTreeMap<A, B>, Self>;
145    fn arbitrary_with(args: Self::Parameters) -> Self::Strategy {
146        any_with_smap(args, BTreeMap::into_iter)        
147    }
148}
149
150//==============================================================================
151// Bound:
152//==============================================================================
153
154impl<'a, A: Arbitrary<'a> + Clone> Arbitrary<'a> for Bound<A>
155where
156    ParamsType<'a, A>: Clone,
157{
158    valuetree!();
159    type Parameters = A::Parameters;
160    type Strategy =
161        TupleUnion<(
162            W<SMapped<'a, A, Self>>,
163            W<SMapped<'a, A, Self>>,
164            W<Just<Self>>
165        )>;
166
167    fn arbitrary_with(args: Self::Parameters) -> Self::Strategy {
168        prop_oneof![
169            2 => any_with_smap(args.clone(), Bound::Included),
170            2 => any_with_smap(args, Bound::Excluded),
171            1 => Just(Bound::Unbounded),
172        ]
173    }
174}
175
176#[cfg(test)]
177mod test {
178    no_panic_test!(
179        vec => Vec<u8>,
180        box_slice => Box<[u8]>,
181        rc_slice  => Rc<[u8]>,
182        arc_slice  => Arc<[u8]>,
183        vec_deque => VecDeque<u8>,
184        linked_list => LinkedList<u8>,
185        btree_set => BTreeSet<u8>,
186        btree_map => BTreeMap<u8, u8>,
187        hash_set => HashSet<u8>,
188        hash_map => HashMap<u8, u8>,
189        bound => Bound<u8>,
190        binary_heap => BinaryHeap<u8>,
191        into_iter_vec => vec::IntoIter<u8>,
192        into_iter_vec_deque => vec_deque::IntoIter<u8>,
193        into_iter_linked_list => linked_list::IntoIter<u8>,
194        into_iter_binary_heap => binary_heap::IntoIter<u8>,
195        into_iter_btree_set => btree_set::IntoIter<u8>,
196        into_iter_btree_map => btree_map::IntoIter<u8, u8>,
197        into_iter_hash_set => hash_set::IntoIter<u8>,
198        into_iter_hash_map => hash_map::IntoIter<u8, u8>
199    );
200}