1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#[cfg(test)]
extern crate arbitrary;
extern crate syn;
#[macro_use]
extern crate synstructure;
extern crate proc_macro2;
use proc_macro2::TokenStream;
decl_derive!([Arbitrary] => arbitrary_derive);
fn arbitrary_derive(s: synstructure::Structure) -> TokenStream {
if s.variants().len() == 1 {
let con = s.variants()[0].construct(|_, _| quote! { Arbitrary::arbitrary(u)? });
s.gen_impl(quote! {
extern crate arbitrary;
use arbitrary::{Arbitrary, Unstructured};
gen impl Arbitrary for @Self {
fn arbitrary<U: Unstructured + ?Sized>(u: &mut U) -> Result<Self, U::Error> {
Ok(#con)
}
}
})
} else {
let mut variant_tokens = TokenStream::new();
for (count, variant) in s.variants().iter().enumerate() {
let count = count as u64;
let constructor = variant.construct(|_, _| quote! { Arbitrary::arbitrary(u)? });
variant_tokens.extend(quote! { #count => #constructor, });
}
let count = s.variants().len() as u64;
s.gen_impl(quote! {
extern crate arbitrary;
use arbitrary::{Arbitrary, Unstructured};
gen impl Arbitrary for @Self {
fn arbitrary<U: Unstructured + ?Sized>(u: &mut U) -> Result<Self, U::Error> {
Ok(match (u64::from(<u32 as Arbitrary>::arbitrary(u)?) * #count) >> 32 {
#variant_tokens
_ => unreachable!()
})
}
}
})
}
}
#[test]
fn test_arbitrary_struct() {
test_derive!{
arbitrary_derive {
#[derive(Clone)]
struct ArbitraryTest(u8, bool);
}
expands to {
#[allow(non_upper_case_globals)]
const _DERIVE_Arbitrary_FOR_ArbitraryTest : () = {
extern crate arbitrary;
use arbitrary::{Arbitrary, Unstructured};
impl Arbitrary for ArbitraryTest {
fn arbitrary<U: Unstructured + ?Sized>(u: & mut U) -> Result<Self, U::Error> {
Ok(ArbitraryTest(Arbitrary::arbitrary(u)?,
Arbitrary::arbitrary(u)?, ))
}
}
};
}
}
}
#[test]
fn test_arbitrary_enum() {
test_derive!{
arbitrary_derive {
#[derive(Clone)]
enum ArbitraryTest {
A,
B(usize, u32),
C{ b: bool, d: (u16, u16) }
}
}
expands to {
#[allow(non_upper_case_globals)]
const _DERIVE_Arbitrary_FOR_ArbitraryTest : () = {
extern crate arbitrary;
use arbitrary::{Arbitrary, Unstructured};
impl Arbitrary for ArbitraryTest {
fn arbitrary<U: Unstructured + ?Sized>(u: & mut U) -> Result<Self, U::Error> {
Ok(match (u64::from(<u32 as Arbitrary>::arbitrary(u)?) * 3u64) >> 32 {
0u64 => ArbitraryTest::A,
1u64 => ArbitraryTest::B(Arbitrary::arbitrary(u)?,
Arbitrary::arbitrary(u)?,
),
2u64 => ArbitraryTest::C {
b : Arbitrary::arbitrary(u)?,
d : Arbitrary::arbitrary(u)?,
},
_ => unreachable!()
})
}
}
};
}
}
}