proptest/arbitrary/_core/
iter.rs

1//-
2// Copyright 2017, 2018 The proptest developers
3//
4// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
5// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
7// option. This file may not be copied, modified, or distributed
8// except according to those terms.
9
10//! Arbitrary implementations for `std::iter`.
11
12use core::fmt;
13use core::iter::Fuse;
14use core::iter::*;
15
16use crate::arbitrary::*;
17use crate::strategy::statics::static_map;
18use crate::strategy::*;
19
20// TODO: Filter, FilterMap, FlatMap, Map, Inspect, Scan, SkipWhile
21// Might be possible with CoArbitrary
22
23wrap_ctor!(Once, once);
24wrap_ctor!([Clone] Repeat, repeat);
25wrap_ctor!([Iterator + Clone] Cycle, Iterator::cycle);
26wrap_ctor!([Iterator] Enumerate, Iterator::enumerate);
27wrap_ctor!([Iterator] Fuse, Iterator::fuse);
28wrap_ctor!([Iterator<Item = T>, T: fmt::Debug] Peekable, Iterator::peekable);
29wrap_ctor!([DoubleEndedIterator] Rev, Iterator::rev);
30
31arbitrary!(['a, T: 'a + Clone, A: Arbitrary + Iterator<Item = &'a T>]
32    Cloned<A>, SMapped<A, Self>, A::Parameters;
33    args => static_map(any_with::<A>(args), Iterator::cloned));
34
35impl<
36        T: 'static + Clone,
37        A: fmt::Debug + 'static + Iterator<Item = &'static T>,
38    > functor::ArbitraryF1<A> for Cloned<A>
39{
40    type Parameters = ();
41
42    fn lift1_with<S>(base: S, _args: Self::Parameters) -> BoxedStrategy<Self>
43    where
44        S: Strategy<Value = A> + 'static,
45    {
46        base.prop_map(Iterator::cloned).boxed()
47    }
48}
49
50arbitrary!([A] Empty<A>; empty());
51
52arbitrary!(
53    [A: Arbitrary + Iterator, B: Arbitrary + Iterator]
54    Zip<A, B>, SMapped<(A, B), Self>,
55    product_type![A::Parameters, B::Parameters];
56    args => static_map(any_with::<(A, B)>(args), |(a, b)| a.zip(b))
57);
58
59lift1!(
60    [fmt::Debug + 'static + Iterator, B: 'static + Arbitrary + Iterator]
61    Zip<B, A>,
62    B::Parameters;
63    base, args =>
64        (any_with::<B>(args), base).prop_map(|(b, a)| b.zip(a)).boxed()
65);
66
67impl<A: fmt::Debug + Iterator, B: fmt::Debug + Iterator>
68    functor::ArbitraryF2<A, B> for Zip<A, B>
69{
70    type Parameters = ();
71
72    fn lift2_with<AS, BS>(
73        fst: AS,
74        snd: BS,
75        _args: Self::Parameters,
76    ) -> BoxedStrategy<Self>
77    where
78        AS: Strategy<Value = A> + 'static,
79        BS: Strategy<Value = B> + 'static,
80    {
81        (fst, snd).prop_map(|(a, b)| a.zip(b)).boxed()
82    }
83}
84
85arbitrary!(
86    [T,
87     A: Arbitrary + Iterator<Item = T>,
88     B: Arbitrary + Iterator<Item = T>]
89    Chain<A, B>, SMapped<(A, B), Self>,
90    product_type![A::Parameters, B::Parameters];
91    args => static_map(any_with::<(A, B)>(args), |(a, b)| a.chain(b))
92);
93
94lift1!([fmt::Debug + 'static + Iterator<Item = T>,
95        B: 'static + Arbitrary + Iterator<Item = T>,
96        T]
97    Chain<B, A>,
98    B::Parameters;
99    base, args =>
100        (any_with::<B>(args), base).prop_map(|(b, a)| b.chain(a)).boxed()
101);
102
103impl<
104        T,
105        A: fmt::Debug + Iterator<Item = T>,
106        B: fmt::Debug + Iterator<Item = T>,
107    > functor::ArbitraryF2<A, B> for Chain<A, B>
108{
109    type Parameters = ();
110
111    fn lift2_with<AS, BS>(
112        fst: AS,
113        snd: BS,
114        _args: Self::Parameters,
115    ) -> BoxedStrategy<Self>
116    where
117        AS: Strategy<Value = A> + 'static,
118        BS: Strategy<Value = B> + 'static,
119    {
120        (fst, snd).prop_map(|(a, b)| a.chain(b)).boxed()
121    }
122}
123
124macro_rules! usize_mod {
125    ($type: ident, $mapper: ident) => {
126        arbitrary!([A: Arbitrary + Iterator] $type<A>,
127            SMapped<(A, usize), Self>, A::Parameters;
128            a => static_map(
129                any_with::<(A, usize)>(product_pack![a, ()]),
130                |(a, b)| a.$mapper(b)
131            )
132        );
133
134        lift1!([Iterator] $type<A>;
135            base => (base, any::<usize>()).prop_map(|(a, b)| a.$mapper(b))
136        );
137    };
138}
139
140usize_mod!(Skip, skip);
141usize_mod!(Take, take);
142
143#[cfg(feature = "unstable")]
144usize_mod!(StepBy, step_by);
145
146#[cfg(test)]
147mod test {
148    use super::*;
149
150    use std::ops::Range;
151    const DUMMY: &'static [u8] = &[0, 1, 2, 3, 4];
152    #[derive(Debug)]
153    struct Dummy(u8);
154    arbitrary!(Dummy, SFnPtrMap<Range<u8>, Self>; static_map(0..5, Dummy));
155    impl Iterator for Dummy {
156        type Item = &'static u8;
157        fn next(&mut self) -> Option<Self::Item> {
158            if self.0 < 5 {
159                let r = &DUMMY[self.0 as usize];
160                self.0 += 1;
161                Some(r)
162            } else {
163                None
164            }
165        }
166    }
167
168    no_panic_test!(
169        empty     => Empty<u8>,
170        once      => Once<u8>,
171        repeat    => Repeat<u8>,
172        cloned    => Cloned<super::Dummy>,
173        cycle     => Cycle<Once<u8>>,
174        enumerate => Enumerate<Repeat<u8>>,
175        fuse      => Fuse<Once<u8>>,
176        peekable  => Peekable<Repeat<u8>>,
177        rev       => Rev<::std::vec::IntoIter<u8>>,
178        zip       => Zip<Repeat<u8>, Repeat<u16>>,
179        chain     => Chain<Once<u8>, Once<u8>>,
180        skip      => Skip<Repeat<u8>>,
181        take      => Take<Repeat<u8>>
182    );
183
184    #[cfg(feature = "unstable")]
185    no_panic_test!(
186        step_by   => StepBy<Repeat<u8>>
187    );
188}