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
119
120
121
122
123
124
125
126
127
use arbitrary::Result;
use crate::DocumentBuilder;
const CHARSET_LETTERS: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_";
const CHARSET_NUMBERS: &[u8] = b"0123456789";
const RESERVED_KEYWORDS: &[&str] = &[
"on",
"Int",
"Float",
"String",
"Boolean",
"ID",
"type",
"enum",
"union",
"extend",
"scalar",
"directive",
"query",
"mutation",
"subscription",
"schema",
"interface",
];
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Name {
pub(crate) name: String,
}
impl From<Name> for String {
fn from(val: Name) -> Self {
val.name
}
}
impl Name {
pub const fn new(name: String) -> Self {
Self { name }
}
}
impl<'a> DocumentBuilder<'a> {
pub fn name(&mut self) -> Result<Name> {
Ok(Name::new(self.limited_string(30)?))
}
pub fn type_name(&mut self) -> Result<Name> {
let mut new_name = self.limited_string(30)?;
if self.list_existing_type_names().any(|n| n.name == new_name) {
new_name.push_str(&format!(
"{}",
self.object_type_defs.len() + self.enum_type_defs.len() + self.directive_defs.len()
));
}
Ok(Name::new(new_name))
}
pub fn name_with_index(&mut self, index: usize) -> Result<Name> {
let mut name = self.limited_string(30)?;
name.push_str(&format!("{}", index));
Ok(Name::new(name))
}
pub(crate) fn limited_string(&mut self, max_size: usize) -> Result<String> {
loop {
let size = self.u.int_in_range(0..=max_size)?;
let gen_str = String::from_utf8(
(0..size)
.map(|curr_idx| {
let idx = self.u.arbitrary::<usize>()?;
let ch = if curr_idx == 0 {
CHARSET_LETTERS[idx % (CHARSET_LETTERS.len() - 1)]
} else {
let idx = idx % (CHARSET_LETTERS.len() + CHARSET_NUMBERS.len());
if idx < CHARSET_LETTERS.len() {
CHARSET_LETTERS[idx]
} else {
CHARSET_NUMBERS[idx - CHARSET_LETTERS.len()]
}
};
Ok(ch)
})
.collect::<Result<Vec<u8>>>()?,
)
.unwrap();
let new_gen = gen_str.trim_end_matches('_');
if !new_gen.is_empty() && !RESERVED_KEYWORDS.contains(&new_gen) {
break Ok(new_gen.to_string());
}
}
}
fn list_existing_type_names(&self) -> impl Iterator<Item = &Name> {
self.object_type_defs
.iter()
.map(|o| &o.name)
.chain(self.interface_type_defs.iter().map(|itf| &itf.name))
.chain(self.enum_type_defs.iter().map(|itf| &itf.name))
.chain(self.directive_defs.iter().map(|itf| &itf.name))
.chain(self.union_type_defs.iter().map(|itf| &itf.name))
.chain(self.input_object_type_defs.iter().map(|itf| &itf.name))
.chain(self.scalar_type_defs.iter().map(|itf| &itf.name))
.chain(self.directive_defs.iter().map(|itf| &itf.name))
.chain(self.fragment_defs.iter().map(|itf| &itf.name))
.chain(self.operation_defs.iter().filter_map(|op| op.name.as_ref()))
}
}