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