1#![doc = include_str!("../README.md")]
2
3pub(crate) mod argument;
4pub(crate) mod description;
5pub(crate) mod directive;
6pub(crate) mod document;
7pub(crate) mod enum_;
8pub(crate) mod field;
9pub(crate) mod fragment;
10pub(crate) mod input_object;
11pub(crate) mod input_value;
12pub(crate) mod interface;
13pub(crate) mod name;
14pub(crate) mod object;
15pub(crate) mod operation;
16pub(crate) mod response;
17pub(crate) mod scalar;
18pub(crate) mod schema;
19pub(crate) mod selection_set;
20#[cfg(test)]
21pub(crate) mod snapshot_tests;
22pub(crate) mod ty;
23pub(crate) mod union;
24pub(crate) mod variable;
25
26use indexmap::IndexMap;
27use std::fmt::Debug;
28
29#[derive(Debug, Clone, thiserror::Error)]
30pub enum FromError {
31 #[error("parse tree is missing a node")]
32 MissingNode,
33 #[error("invalid i32")]
34 ParseIntError(#[from] std::num::ParseIntError),
35 #[error("invalid f64")]
36 ParseFloatError(#[from] std::num::ParseFloatError),
37 #[error("invalid boolean")]
38 ParseBoolError(#[from] std::str::ParseBoolError),
39}
40
41pub use arbitrary::Result;
42pub use arbitrary::Unstructured;
43use argument::Argument;
44pub use directive::DirectiveDef;
45pub use document::Document;
46pub use enum_::EnumTypeDef;
47use field::FieldDef;
48pub use fragment::FragmentDef;
49pub use input_object::InputObjectTypeDef;
50pub use interface::InterfaceTypeDef;
51use name::Name;
52pub use object::ObjectTypeDef;
53pub use operation::OperationDef;
54pub use response::Generator;
55pub use response::ResponseBuilder;
56pub use scalar::ScalarTypeDef;
57pub use schema::SchemaDef;
58pub use serde_json_bytes::Value;
59use ty::Ty;
60pub use union::UnionTypeDef;
61
62pub struct DocumentBuilder<'a> {
82 pub(crate) u: &'a mut Unstructured<'a>,
83 pub(crate) input_object_type_defs: Vec<InputObjectTypeDef>,
84 pub(crate) object_type_defs: Vec<ObjectTypeDef>,
85 pub(crate) interface_type_defs: Vec<InterfaceTypeDef>,
86 pub(crate) union_type_defs: Vec<UnionTypeDef>,
87 pub(crate) enum_type_defs: Vec<EnumTypeDef>,
88 pub(crate) scalar_type_defs: Vec<ScalarTypeDef>,
89 pub(crate) schema_def: Option<SchemaDef>,
90 pub(crate) directive_defs: Vec<DirectiveDef>,
91 pub(crate) operation_defs: Vec<OperationDef>,
92 pub(crate) fragment_defs: Vec<FragmentDef>,
93 pub(crate) stack: Vec<Box<dyn StackedEntity>>,
95 pub(crate) chosen_arguments: IndexMap<Name, Vec<Argument>>,
97 pub(crate) chosen_aliases: IndexMap<Name, Name>,
99}
100
101impl Debug for DocumentBuilder<'_> {
102 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
103 f.debug_struct("DocumentBuilder")
104 .field("input_object_type_defs", &self.input_object_type_defs)
105 .field("object_type_defs", &self.object_type_defs)
106 .field("interface_type_defs", &self.interface_type_defs)
107 .field("union_type_defs", &self.union_type_defs)
108 .field("enum_type_defs", &self.enum_type_defs)
109 .field("scalar_type_defs", &self.scalar_type_defs)
110 .field("schema_def", &self.schema_def)
111 .field("directive_defs", &self.directive_defs)
112 .field("operation_defs", &self.operation_defs)
113 .field("fragment_defs", &self.fragment_defs)
114 .finish()
115 }
116}
117
118impl<'a> DocumentBuilder<'a> {
119 pub fn new(u: &'a mut Unstructured<'a>) -> Result<Self> {
121 let mut builder = Self {
122 u,
123 object_type_defs: Vec::new(),
124 interface_type_defs: Vec::new(),
125 enum_type_defs: Vec::new(),
126 schema_def: None,
127 directive_defs: Vec::new(),
128 operation_defs: Vec::new(),
129 fragment_defs: Vec::new(),
130 scalar_type_defs: Vec::new(),
131 union_type_defs: Vec::new(),
132 input_object_type_defs: Vec::new(),
133 stack: Vec::new(),
134 chosen_arguments: IndexMap::new(),
135 chosen_aliases: IndexMap::new(),
136 };
137
138 for _ in 0..builder.u.int_in_range(1..=50)? {
139 let scalar_type_def = builder.scalar_type_definition()?;
140 builder.scalar_type_defs.push(scalar_type_def);
141 }
142
143 for _ in 0..builder.u.int_in_range(1..=50)? {
144 let enum_type_def = builder.enum_type_definition()?;
145 builder.enum_type_defs.push(enum_type_def);
146 }
147
148 for _ in 0..builder.u.int_in_range(1..=50)? {
149 let interface_type_def = builder.interface_type_definition()?;
150 builder.interface_type_defs.push(interface_type_def);
151 }
152
153 for _ in 0..builder.u.int_in_range(1..=50)? {
154 let object_type_def = builder.object_type_definition()?;
155 builder.object_type_defs.push(object_type_def);
156 }
157
158 for _ in 0..builder.u.int_in_range(1..=50)? {
159 let union_type_def = builder.union_type_definition()?;
160 builder.union_type_defs.push(union_type_def);
161 }
162
163 for _ in 0..builder.u.int_in_range(1..=50)? {
164 let input_object_type_def = builder.input_object_type_definition()?;
165 builder.input_object_type_defs.push(input_object_type_def);
166 }
167
168 for _ in 0..builder.u.int_in_range(1..=50)? {
169 let fragment_def = builder.fragment_definition()?;
170 builder.fragment_defs.push(fragment_def);
171 }
172
173 for _ in 0..builder.u.int_in_range(1..=50)? {
174 let directive_def = builder.directive_def()?;
175 builder.directive_defs.push(directive_def);
176 }
177
178 let schema_def = builder.schema_definition()?;
179 builder.schema_def = Some(schema_def);
180
181 for _ in 0..builder.u.int_in_range(1..=50)? {
182 let operation_def = builder.operation_definition()?;
183 if let Some(operation_def) = operation_def {
185 builder.operation_defs.push(operation_def);
186 }
187 }
188
189 Ok(builder)
190 }
191
192 pub fn with_document(u: &'a mut Unstructured<'a>, document: Document) -> Result<Self> {
195 let builder = Self {
196 u,
197 object_type_defs: document.object_type_definitions,
198 interface_type_defs: document.interface_type_definitions,
199 enum_type_defs: document.enum_type_definitions,
200 schema_def: document.schema_definition,
201 directive_defs: document.directive_definitions,
202 operation_defs: document.operation_definitions,
203 fragment_defs: document.fragment_definitions,
204 scalar_type_defs: document.scalar_type_definitions,
205 union_type_defs: document.union_type_definitions,
206 input_object_type_defs: document.input_object_type_definitions,
207 stack: Vec::new(),
208 chosen_arguments: IndexMap::new(),
209 chosen_aliases: IndexMap::new(),
210 };
211
212 Ok(builder)
213 }
214
215 pub fn input_exhausted(&self) -> bool {
217 self.u.is_empty()
218 }
219
220 pub fn finish(self) -> Document {
222 Document {
223 schema_definition: self.schema_def,
224 object_type_definitions: self.object_type_defs,
225 interface_type_definitions: self.interface_type_defs,
226 enum_type_definitions: self.enum_type_defs,
227 directive_definitions: self.directive_defs,
228 operation_definitions: self.operation_defs,
229 fragment_definitions: self.fragment_defs,
230 scalar_type_definitions: self.scalar_type_defs,
231 union_type_definitions: self.union_type_defs,
232 input_object_type_definitions: self.input_object_type_defs,
233 }
234 }
235
236 pub(crate) fn stack_ty(&mut self, ty: &Ty) -> bool {
237 if ty.is_builtin() {
238 return false;
239 }
240 let type_name = ty.name();
241
242 if let Some(object_ty) = self
243 .object_type_defs
244 .iter()
245 .find(|object_ty_def| &object_ty_def.name == type_name)
246 .cloned()
247 {
248 self.stack.push(Box::new(object_ty));
249 true
250 } else if let Some(itf_type) = self
251 .interface_type_defs
252 .iter()
253 .find(|itf_type_def| &itf_type_def.name == type_name)
254 .cloned()
255 {
256 self.stack.push(Box::new(itf_type));
257 true
258 } else if let Some(_enum_ty) = self
259 .enum_type_defs
260 .iter()
261 .find(|object_ty_def| &object_ty_def.name == type_name)
262 .cloned()
263 {
264 false
265 } else {
266 todo!("'{:?}' need to implement for union, scalar, ...", type_name);
267 }
268 }
269}
270
271pub(crate) trait StackedEntity {
272 fn name(&self) -> &Name;
273 fn fields_def(&self) -> &[FieldDef];
274}