1 use {
2 crate::{size_hint, Arbitrary, MaxRecursionReached, Result, Unstructured},
3 core::{
4 mem,
5 ops::{Bound, Range, RangeBounds, RangeFrom, RangeInclusive, RangeTo, RangeToInclusive},
6 },
7 };
8
9 macro_rules! impl_range {
10 (
11 $range:ty,
12 $value_closure:expr,
13 $value_ty:ty,
14 $fun:ident($fun_closure:expr),
15 $size_hint_closure:expr
16 ) => {
17 impl<'a, A> Arbitrary<'a> for $range
18 where
19 A: Arbitrary<'a> + Clone + PartialOrd,
20 {
21 fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> {
22 let value: $value_ty = Arbitrary::arbitrary(u)?;
23 Ok($fun(value, $fun_closure))
24 }
25
26 #[inline]
27 fn size_hint(depth: usize) -> (usize, Option<usize>) {
28 Self::try_size_hint(depth).unwrap_or_default()
29 }
30
31 #[inline]
32 fn try_size_hint(depth: usize) -> Result<(usize, Option<usize>), MaxRecursionReached> {
33 #[allow(clippy::redundant_closure_call)]
34 $size_hint_closure(depth)
35 }
36 }
37 };
38 }
39 impl_range!(
40 Range<A>,
41 |r: &Range<A>| (r.start.clone(), r.end.clone()),
42 (A, A),
43 bounded_range(|(a, b)| a..b),
44 |depth| Ok(crate::size_hint::and(
45 <A as Arbitrary>::try_size_hint(depth)?,
46 <A as Arbitrary>::try_size_hint(depth)?,
47 ))
48 );
49 impl_range!(
50 RangeFrom<A>,
51 |r: &RangeFrom<A>| r.start.clone(),
52 A,
53 unbounded_range(|a| a..),
54 |depth| <A as Arbitrary>::try_size_hint(depth)
55 );
56 impl_range!(
57 RangeInclusive<A>,
58 |r: &RangeInclusive<A>| (r.start().clone(), r.end().clone()),
59 (A, A),
60 bounded_range(|(a, b)| a..=b),
61 |depth| Ok(crate::size_hint::and(
62 <A as Arbitrary>::try_size_hint(depth)?,
63 <A as Arbitrary>::try_size_hint(depth)?,
64 ))
65 );
66 impl_range!(
67 RangeTo<A>,
68 |r: &RangeTo<A>| r.end.clone(),
69 A,
70 unbounded_range(|b| ..b),
71 |depth| <A as Arbitrary>::try_size_hint(depth)
72 );
73 impl_range!(
74 RangeToInclusive<A>,
75 |r: &RangeToInclusive<A>| r.end.clone(),
76 A,
77 unbounded_range(|b| ..=b),
78 |depth| <A as Arbitrary>::try_size_hint(depth)
79 );
80
bounded_range<CB, I, R>(bounds: (I, I), cb: CB) -> R where CB: Fn((I, I)) -> R, I: PartialOrd, R: RangeBounds<I>,81 pub(crate) fn bounded_range<CB, I, R>(bounds: (I, I), cb: CB) -> R
82 where
83 CB: Fn((I, I)) -> R,
84 I: PartialOrd,
85 R: RangeBounds<I>,
86 {
87 let (mut start, mut end) = bounds;
88 if start > end {
89 mem::swap(&mut start, &mut end);
90 }
91 cb((start, end))
92 }
93
unbounded_range<CB, I, R>(bound: I, cb: CB) -> R where CB: Fn(I) -> R, R: RangeBounds<I>,94 pub(crate) fn unbounded_range<CB, I, R>(bound: I, cb: CB) -> R
95 where
96 CB: Fn(I) -> R,
97 R: RangeBounds<I>,
98 {
99 cb(bound)
100 }
101
102 impl<'a, A> Arbitrary<'a> for Bound<A>
103 where
104 A: Arbitrary<'a>,
105 {
arbitrary(u: &mut Unstructured<'a>) -> Result<Self>106 fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> {
107 match u.int_in_range::<u8>(0..=2)? {
108 0 => Ok(Bound::Included(A::arbitrary(u)?)),
109 1 => Ok(Bound::Excluded(A::arbitrary(u)?)),
110 2 => Ok(Bound::Unbounded),
111 _ => unreachable!(),
112 }
113 }
114
115 #[inline]
size_hint(depth: usize) -> (usize, Option<usize>)116 fn size_hint(depth: usize) -> (usize, Option<usize>) {
117 Self::try_size_hint(depth).unwrap_or_default()
118 }
119
120 #[inline]
try_size_hint(depth: usize) -> Result<(usize, Option<usize>), MaxRecursionReached>121 fn try_size_hint(depth: usize) -> Result<(usize, Option<usize>), MaxRecursionReached> {
122 Ok(size_hint::or(
123 size_hint::and((1, Some(1)), A::try_size_hint(depth)?),
124 (1, Some(1)),
125 ))
126 }
127 }
128