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