1use std::str::FromStr;
2
3use thiserror::Error;
4
5pub use crate::parser::common::{Directive, Text, Type, Value};
6use crate::parser::position::Pos;
7
8#[derive(Debug, Clone, Default, PartialEq)]
9pub struct Document<'a, T: Text<'a>> {
10 pub definitions: Vec<Definition<'a, T>>,
11}
12
13impl<'a> Document<'a, String> {
14 pub fn into_static(self) -> Document<'static, String> {
15 unsafe { std::mem::transmute::<_, Document<'static, String>>(self) }
29 }
30}
31
32#[derive(Debug, Clone, PartialEq)]
33pub enum Definition<'a, T: Text<'a>> {
34 SchemaDefinition(SchemaDefinition<'a, T>),
35 TypeDefinition(TypeDefinition<'a, T>),
36 TypeExtension(TypeExtension<'a, T>),
37 DirectiveDefinition(DirectiveDefinition<'a, T>),
38}
39
40#[derive(Debug, Clone, Default, PartialEq)]
41pub struct SchemaDefinition<'a, T: Text<'a>> {
42 pub position: Pos,
43 pub directives: Vec<Directive<'a, T>>,
44 pub query: Option<T::Value>,
45 pub mutation: Option<T::Value>,
46 pub subscription: Option<T::Value>,
47}
48
49#[derive(Debug, Clone, PartialEq)]
50pub enum TypeDefinition<'a, T: Text<'a>> {
51 Scalar(ScalarType<'a, T>),
52 Object(ObjectType<'a, T>),
53 Interface(InterfaceType<'a, T>),
54 Union(UnionType<'a, T>),
55 Enum(EnumType<'a, T>),
56 InputObject(InputObjectType<'a, T>),
57}
58
59#[derive(Debug, Clone, PartialEq)]
60pub enum TypeExtension<'a, T: Text<'a>> {
61 Scalar(ScalarTypeExtension<'a, T>),
62 Object(ObjectTypeExtension<'a, T>),
63 Interface(InterfaceTypeExtension<'a, T>),
64 Union(UnionTypeExtension<'a, T>),
65 Enum(EnumTypeExtension<'a, T>),
66 InputObject(InputObjectTypeExtension<'a, T>),
67}
68
69#[derive(Debug, Clone, PartialEq)]
70pub struct ScalarType<'a, T: Text<'a>> {
71 pub position: Pos,
72 pub description: Option<String>,
73 pub name: T::Value,
74 pub directives: Vec<Directive<'a, T>>,
75}
76
77impl<'a, T> ScalarType<'a, T>
78where
79 T: Text<'a>,
80{
81 pub fn new(name: T::Value) -> Self {
82 Self {
83 position: Pos::default(),
84 description: None,
85 name,
86 directives: vec![],
87 }
88 }
89}
90
91#[derive(Debug, Clone, PartialEq)]
92pub struct ScalarTypeExtension<'a, T: Text<'a>> {
93 pub position: Pos,
94 pub name: T::Value,
95 pub directives: Vec<Directive<'a, T>>,
96}
97
98impl<'a, T> ScalarTypeExtension<'a, T>
99where
100 T: Text<'a>,
101{
102 pub fn new(name: T::Value) -> Self {
103 Self {
104 position: Pos::default(),
105 name,
106 directives: vec![],
107 }
108 }
109}
110
111#[derive(Debug, Clone, PartialEq)]
112pub struct ObjectType<'a, T: Text<'a>> {
113 pub position: Pos,
114 pub description: Option<String>,
115 pub name: T::Value,
116 pub implements_interfaces: Vec<T::Value>,
117 pub directives: Vec<Directive<'a, T>>,
118 pub fields: Vec<Field<'a, T>>,
119}
120
121impl<'a, T> ObjectType<'a, T>
122where
123 T: Text<'a>,
124{
125 pub fn new(name: T::Value) -> Self {
126 Self {
127 position: Pos::default(),
128 description: None,
129 name,
130 implements_interfaces: vec![],
131 directives: vec![],
132 fields: vec![],
133 }
134 }
135}
136
137#[derive(Debug, Clone, PartialEq)]
138pub struct ObjectTypeExtension<'a, T: Text<'a>> {
139 pub position: Pos,
140 pub name: T::Value,
141 pub implements_interfaces: Vec<T::Value>,
142 pub directives: Vec<Directive<'a, T>>,
143 pub fields: Vec<Field<'a, T>>,
144}
145
146impl<'a, T> ObjectTypeExtension<'a, T>
147where
148 T: Text<'a>,
149{
150 pub fn new(name: T::Value) -> Self {
151 Self {
152 position: Pos::default(),
153 name,
154 implements_interfaces: vec![],
155 directives: vec![],
156 fields: vec![],
157 }
158 }
159}
160
161#[derive(Debug, Clone, PartialEq)]
162pub struct Field<'a, T: Text<'a>> {
163 pub position: Pos,
164 pub description: Option<String>,
165 pub name: T::Value,
166 pub arguments: Vec<InputValue<'a, T>>,
167 pub field_type: Type<'a, T>,
168 pub directives: Vec<Directive<'a, T>>,
169}
170
171#[derive(Debug, Clone, PartialEq)]
172pub struct InputValue<'a, T: Text<'a>> {
173 pub position: Pos,
174 pub description: Option<String>,
175 pub name: T::Value,
176 pub value_type: Type<'a, T>,
177 pub default_value: Option<Value<'a, T>>,
178 pub directives: Vec<Directive<'a, T>>,
179}
180
181#[derive(Debug, Clone, PartialEq)]
182pub struct InterfaceType<'a, T: Text<'a>> {
183 pub position: Pos,
184 pub description: Option<String>,
185 pub name: T::Value,
186 pub implements_interfaces: Vec<T::Value>,
187 pub directives: Vec<Directive<'a, T>>,
188 pub fields: Vec<Field<'a, T>>,
189}
190
191impl<'a, T> InterfaceType<'a, T>
192where
193 T: Text<'a>,
194{
195 pub fn new(name: T::Value) -> Self {
196 Self {
197 position: Pos::default(),
198 description: None,
199 name,
200 implements_interfaces: vec![],
201 directives: vec![],
202 fields: vec![],
203 }
204 }
205}
206
207#[derive(Debug, Clone, PartialEq)]
208pub struct InterfaceTypeExtension<'a, T: Text<'a>> {
209 pub position: Pos,
210 pub name: T::Value,
211 pub implements_interfaces: Vec<T::Value>,
212 pub directives: Vec<Directive<'a, T>>,
213 pub fields: Vec<Field<'a, T>>,
214}
215
216impl<'a, T> InterfaceTypeExtension<'a, T>
217where
218 T: Text<'a>,
219{
220 pub fn new(name: T::Value) -> Self {
221 Self {
222 position: Pos::default(),
223 name,
224 implements_interfaces: vec![],
225 directives: vec![],
226 fields: vec![],
227 }
228 }
229}
230
231#[derive(Debug, Clone, PartialEq)]
232pub struct UnionType<'a, T: Text<'a>> {
233 pub position: Pos,
234 pub description: Option<String>,
235 pub name: T::Value,
236 pub directives: Vec<Directive<'a, T>>,
237 pub types: Vec<T::Value>,
238}
239
240impl<'a, T> UnionType<'a, T>
241where
242 T: Text<'a>,
243{
244 pub fn new(name: T::Value) -> Self {
245 Self {
246 position: Pos::default(),
247 description: None,
248 name,
249 directives: vec![],
250 types: vec![],
251 }
252 }
253}
254
255#[derive(Debug, Clone, PartialEq)]
256pub struct UnionTypeExtension<'a, T: Text<'a>> {
257 pub position: Pos,
258 pub name: T::Value,
259 pub directives: Vec<Directive<'a, T>>,
260 pub types: Vec<T::Value>,
261}
262
263impl<'a, T> UnionTypeExtension<'a, T>
264where
265 T: Text<'a>,
266{
267 pub fn new(name: T::Value) -> Self {
268 Self {
269 position: Pos::default(),
270 name,
271 directives: vec![],
272 types: vec![],
273 }
274 }
275}
276
277#[derive(Debug, Clone, PartialEq)]
278pub struct EnumType<'a, T: Text<'a>> {
279 pub position: Pos,
280 pub description: Option<String>,
281 pub name: T::Value,
282 pub directives: Vec<Directive<'a, T>>,
283 pub values: Vec<EnumValue<'a, T>>,
284}
285
286impl<'a, T> EnumType<'a, T>
287where
288 T: Text<'a>,
289{
290 pub fn new(name: T::Value) -> Self {
291 Self {
292 position: Pos::default(),
293 description: None,
294 name,
295 directives: vec![],
296 values: vec![],
297 }
298 }
299}
300
301#[derive(Debug, Clone, PartialEq)]
302pub struct EnumValue<'a, T: Text<'a>> {
303 pub position: Pos,
304 pub description: Option<String>,
305 pub name: T::Value,
306 pub directives: Vec<Directive<'a, T>>,
307}
308
309impl<'a, T> EnumValue<'a, T>
310where
311 T: Text<'a>,
312{
313 pub fn new(name: T::Value) -> Self {
314 Self {
315 position: Pos::default(),
316 description: None,
317 name,
318 directives: vec![],
319 }
320 }
321}
322
323#[derive(Debug, Clone, PartialEq)]
324pub struct EnumTypeExtension<'a, T: Text<'a>> {
325 pub position: Pos,
326 pub name: T::Value,
327 pub directives: Vec<Directive<'a, T>>,
328 pub values: Vec<EnumValue<'a, T>>,
329}
330
331impl<'a, T> EnumTypeExtension<'a, T>
332where
333 T: Text<'a>,
334{
335 pub fn new(name: T::Value) -> Self {
336 Self {
337 position: Pos::default(),
338 name,
339 directives: vec![],
340 values: vec![],
341 }
342 }
343}
344
345#[derive(Debug, Clone, PartialEq)]
346pub struct InputObjectType<'a, T: Text<'a>> {
347 pub position: Pos,
348 pub description: Option<String>,
349 pub name: T::Value,
350 pub directives: Vec<Directive<'a, T>>,
351 pub fields: Vec<InputValue<'a, T>>,
352}
353
354impl<'a, T> InputObjectType<'a, T>
355where
356 T: Text<'a>,
357{
358 pub fn new(name: T::Value) -> Self {
359 Self {
360 position: Pos::default(),
361 description: None,
362 name,
363 directives: vec![],
364 fields: vec![],
365 }
366 }
367}
368
369#[derive(Debug, Clone, PartialEq)]
370pub struct InputObjectTypeExtension<'a, T: Text<'a>> {
371 pub position: Pos,
372 pub name: T::Value,
373 pub directives: Vec<Directive<'a, T>>,
374 pub fields: Vec<InputValue<'a, T>>,
375}
376
377impl<'a, T> InputObjectTypeExtension<'a, T>
378where
379 T: Text<'a>,
380{
381 pub fn new(name: T::Value) -> Self {
382 Self {
383 position: Pos::default(),
384 name,
385 directives: vec![],
386 fields: vec![],
387 }
388 }
389}
390
391#[derive(Debug, Clone, PartialEq, Eq, Hash)]
392pub enum DirectiveLocation {
393 Query,
395 Mutation,
396 Subscription,
397 Field,
398 FragmentDefinition,
399 FragmentSpread,
400 InlineFragment,
401
402 Schema,
404 Scalar,
405 Object,
406 FieldDefinition,
407 ArgumentDefinition,
408 Interface,
409 Union,
410 Enum,
411 EnumValue,
412 InputObject,
413 InputFieldDefinition,
414 VariableDefinition,
415}
416
417#[derive(Debug, Clone, PartialEq)]
418pub struct DirectiveDefinition<'a, T: Text<'a>> {
419 pub position: Pos,
420 pub description: Option<String>,
421 pub name: T::Value,
422 pub arguments: Vec<InputValue<'a, T>>,
423 pub repeatable: bool,
424 pub locations: Vec<DirectiveLocation>,
425}
426
427impl<'a, T> DirectiveDefinition<'a, T>
428where
429 T: Text<'a>,
430{
431 pub fn new(name: T::Value) -> Self {
432 Self {
433 position: Pos::default(),
434 description: None,
435 name,
436 arguments: vec![],
437 repeatable: false,
438 locations: vec![],
439 }
440 }
441}
442
443impl DirectiveLocation {
444 pub fn as_str(&self) -> &'static str {
446 use self::DirectiveLocation::*;
447 match *self {
448 Query => "QUERY",
449 Mutation => "MUTATION",
450 Subscription => "SUBSCRIPTION",
451 Field => "FIELD",
452 FragmentDefinition => "FRAGMENT_DEFINITION",
453 FragmentSpread => "FRAGMENT_SPREAD",
454 InlineFragment => "INLINE_FRAGMENT",
455 Schema => "SCHEMA",
456 Scalar => "SCALAR",
457 Object => "OBJECT",
458 FieldDefinition => "FIELD_DEFINITION",
459 ArgumentDefinition => "ARGUMENT_DEFINITION",
460 Interface => "INTERFACE",
461 Union => "UNION",
462 Enum => "ENUM",
463 EnumValue => "ENUM_VALUE",
464 InputObject => "INPUT_OBJECT",
465 InputFieldDefinition => "INPUT_FIELD_DEFINITION",
466 VariableDefinition => "VARIABLE_DEFINITION",
467 }
468 }
469
470 pub fn is_query(&self) -> bool {
472 use self::DirectiveLocation::*;
473 match *self {
474 Query | Mutation | Subscription | Field | FragmentDefinition | FragmentSpread
475 | InlineFragment => true,
476
477 Schema | Scalar | Object | FieldDefinition | ArgumentDefinition | Interface | Union
478 | Enum | EnumValue | InputObject | InputFieldDefinition | VariableDefinition => false,
479 }
480 }
481
482 pub fn is_schema(&self) -> bool {
484 !self.is_query()
485 }
486}
487
488#[derive(Debug, Error)]
489#[error("invalid directive location")]
490pub struct InvalidDirectiveLocation;
491
492impl FromStr for DirectiveLocation {
493 type Err = InvalidDirectiveLocation;
494 fn from_str(s: &str) -> Result<DirectiveLocation, InvalidDirectiveLocation> {
495 use self::DirectiveLocation::*;
496 let val = match s {
497 "QUERY" => Query,
498 "MUTATION" => Mutation,
499 "SUBSCRIPTION" => Subscription,
500 "FIELD" => Field,
501 "FRAGMENT_DEFINITION" => FragmentDefinition,
502 "FRAGMENT_SPREAD" => FragmentSpread,
503 "INLINE_FRAGMENT" => InlineFragment,
504 "SCHEMA" => Schema,
505 "SCALAR" => Scalar,
506 "OBJECT" => Object,
507 "FIELD_DEFINITION" => FieldDefinition,
508 "ARGUMENT_DEFINITION" => ArgumentDefinition,
509 "INTERFACE" => Interface,
510 "UNION" => Union,
511 "ENUM" => Enum,
512 "ENUM_VALUE" => EnumValue,
513 "INPUT_OBJECT" => InputObject,
514 "INPUT_FIELD_DEFINITION" => InputFieldDefinition,
515 "VARIABLE_DEFINITION" => VariableDefinition,
516 _ => return Err(InvalidDirectiveLocation),
517 };
518
519 Ok(val)
520 }
521}