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
use util::pick;
use binjs_meta::spec::*;
use std::iter;
use rand;
use rand::distributions::Alphanumeric;
use serde_json::Value as JSON;
pub trait Pick {
fn random<T: rand::Rng>(&self, syntax: &Spec, rng: &mut T, depth_limit: isize) -> JSON;
}
pub struct Picker;
impl Pick for Picker {
fn random<T: rand::Rng>(&self, syntax: &Spec, rng: &mut T, depth_limit: isize) -> JSON {
syntax.get_root().random(syntax, rng, depth_limit)
}
}
impl Pick for NamedType {
fn random<T: rand::Rng>(&self, syntax: &Spec, rng: &mut T, depth_limit: isize) -> JSON {
match *self {
NamedType::Interface(ref interface) => interface.random(syntax, rng, depth_limit),
NamedType::Typedef(ref typedef) => typedef.random(syntax, rng, depth_limit),
NamedType::StringEnum(ref string_enum) => {
let string = pick(rng, &string_enum.strings());
JSON::from(string.clone())
}
}
}
}
impl Pick for TypeSpec {
fn random<T: rand::Rng>(&self, syntax: &Spec, rng: &mut T, depth_limit: isize) -> JSON {
const MAX_ARRAY_LEN: usize = 16;
match *self {
TypeSpec::Array {
supports_empty,
contents: ref type_,
} => {
if supports_empty && depth_limit <= 0 {
return JSON::Array(vec![]);
}
let min = if supports_empty { 0 } else { 1 };
let len = rng.gen_range(min, MAX_ARRAY_LEN);
let mut buf = Vec::with_capacity(len);
for _ in 0..len {
buf.push(type_.random(syntax, rng, depth_limit - 1));
}
JSON::Array(buf)
}
TypeSpec::NamedType(ref name) => {
if let Some(named) = syntax.get_type_by_name(name) {
named.random(syntax, rng, depth_limit)
} else {
panic!("Could not find named type {:?}", name)
}
}
TypeSpec::TypeSum(ref types) => {
let type_ = pick(rng, types.types());
type_.random(syntax, rng, depth_limit)
}
TypeSpec::Boolean => JSON::Bool(rng.gen()),
TypeSpec::String | TypeSpec::PropertyKey | TypeSpec::IdentifierName => {
const MAX_STRING_LEN: usize = 10;
let len = rng.gen_range(0, MAX_STRING_LEN);
let string: String = iter::repeat(())
.map(|()| rng.sample(Alphanumeric))
.take(len)
.collect();
JSON::from(string)
}
TypeSpec::Number => JSON::from(rng.gen::<f64>()),
TypeSpec::Void => JSON::Null,
TypeSpec::Offset | TypeSpec::UnsignedLong => {
JSON::from(rng.gen_range(0, u32::max_value()))
}
}
}
}
impl Pick for Type {
fn random<T: rand::Rng>(&self, syntax: &Spec, rng: &mut T, depth_limit: isize) -> JSON {
if self.is_optional() {
if depth_limit <= 0 || rng.gen_range(0, 10) > 0 {
return JSON::Null;
}
}
self.spec.random(syntax, rng, depth_limit)
}
}
impl Pick for Interface {
fn random<T: rand::Rng>(&self, syntax: &Spec, rng: &mut T, depth_limit: isize) -> JSON {
let mut obj = serde_json::Map::with_capacity(self.contents().fields().len());
for field in self.contents().fields() {
let value = field.type_().random(syntax, rng, depth_limit - 1);
obj.insert(field.name().to_str().to_string(), value);
}
serde_json::Value::Object(obj)
}
}
impl Pick for Spec {
fn random<T: rand::Rng>(&self, _: &Spec, rng: &mut T, depth_limit: isize) -> JSON {
let root = self
.interfaces_by_name()
.get(&self.get_root_name())
.expect("Root interface doesn't exist");
root.random(self, rng, depth_limit)
}
}