bluejay_parser/ast/executable/
operation_definition.rs1use crate::ast::executable::{SelectionSet, VariableDefinitions};
2use crate::ast::{
3 FromTokens, IsMatch, OperationType, ParseError, Tokens, TryFromTokens, VariableDirectives,
4};
5use crate::lexical_token::Name;
6use crate::{HasSpan, Span};
7use bluejay_core::{
8 executable::{OperationDefinition as CoreOperationDefinition, OperationDefinitionReference},
9 Indexable,
10};
11
12#[derive(Debug)]
13pub enum OperationDefinition<'a> {
14 Explicit(ExplicitOperationDefinition<'a>),
15 Implicit(ImplicitOperationDefinition<'a>),
16}
17
18impl<'a> OperationDefinition<'a> {
19 pub fn selection_set(&self) -> &SelectionSet<'a> {
20 match self {
21 Self::Explicit(e) => &e.selection_set,
22 Self::Implicit(i) => &i.selection_set,
23 }
24 }
25}
26
27impl<'a> Indexable for OperationDefinition<'a> {
28 type Id = Span;
29
30 fn id(&self) -> &Self::Id {
31 self.span()
32 }
33}
34
35impl<'a> CoreOperationDefinition for OperationDefinition<'a> {
36 type ExplicitOperationDefinition = ExplicitOperationDefinition<'a>;
37 type ImplicitOperationDefinition = ImplicitOperationDefinition<'a>;
38
39 fn as_ref(&self) -> OperationDefinitionReference<'_, Self> {
40 match self {
41 Self::Explicit(e) => OperationDefinitionReference::Explicit(e),
42 Self::Implicit(i) => OperationDefinitionReference::Implicit(i),
43 }
44 }
45}
46
47impl<'a> FromTokens<'a> for OperationDefinition<'a> {
48 #[inline]
49 fn from_tokens(tokens: &mut impl Tokens<'a>) -> Result<Self, ParseError> {
50 if let Some(operation_type) = OperationType::try_from_tokens(tokens).transpose()? {
51 let name = tokens.next_if_name();
52 let variable_definitions = VariableDefinitions::try_from_tokens(tokens).transpose()?;
53 let directives = VariableDirectives::try_from_tokens(tokens).transpose()?;
54 let selection_set = SelectionSet::from_tokens(tokens)?;
55 let span = operation_type.span().merge(selection_set.span());
56 Ok(Self::Explicit(ExplicitOperationDefinition {
57 operation_type,
58 name,
59 variable_definitions,
60 directives,
61 selection_set,
62 span,
63 }))
64 } else if let Some(selection_set) = SelectionSet::try_from_tokens(tokens).transpose()? {
65 Ok(Self::Implicit(ImplicitOperationDefinition {
66 selection_set,
67 }))
68 } else {
69 Err(tokens.unexpected_token())
70 }
71 }
72}
73
74impl<'a> IsMatch<'a> for OperationDefinition<'a> {
75 #[inline]
76 fn is_match(tokens: &mut impl Tokens<'a>) -> bool {
77 OperationType::is_match(tokens) || SelectionSet::is_match(tokens)
78 }
79}
80
81impl<'a> HasSpan for OperationDefinition<'a> {
82 fn span(&self) -> &Span {
83 match self {
84 Self::Explicit(e) => e.span(),
85 Self::Implicit(i) => i.span(),
86 }
87 }
88}
89
90#[derive(Debug)]
91pub struct ExplicitOperationDefinition<'a> {
92 operation_type: OperationType,
93 name: Option<Name<'a>>,
94 variable_definitions: Option<VariableDefinitions<'a>>,
95 directives: Option<VariableDirectives<'a>>,
96 selection_set: SelectionSet<'a>,
97 span: Span,
98}
99
100impl<'a> bluejay_core::executable::ExplicitOperationDefinition for ExplicitOperationDefinition<'a> {
101 type VariableDefinitions = VariableDefinitions<'a>;
102 type Directives = VariableDirectives<'a>;
103 type SelectionSet = SelectionSet<'a>;
104
105 fn operation_type(&self) -> bluejay_core::OperationType {
106 (&self.operation_type).into()
107 }
108
109 fn name(&self) -> Option<&str> {
110 self.name.as_ref().map(|name| name.as_ref())
111 }
112
113 fn variable_definitions(&self) -> Option<&Self::VariableDefinitions> {
114 self.variable_definitions.as_ref()
115 }
116
117 fn directives(&self) -> Option<&Self::Directives> {
118 self.directives.as_ref()
119 }
120
121 fn selection_set(&self) -> &Self::SelectionSet {
122 &self.selection_set
123 }
124}
125
126impl<'a> ExplicitOperationDefinition<'a> {
127 pub fn name(&self) -> Option<&Name<'a>> {
128 self.name.as_ref()
129 }
130
131 pub fn operation_type(&self) -> &OperationType {
132 &self.operation_type
133 }
134}
135
136impl<'a> HasSpan for ExplicitOperationDefinition<'a> {
137 fn span(&self) -> &Span {
138 &self.span
139 }
140}
141
142#[derive(Debug)]
143pub struct ImplicitOperationDefinition<'a> {
144 selection_set: SelectionSet<'a>,
145}
146
147impl<'a> bluejay_core::executable::ImplicitOperationDefinition for ImplicitOperationDefinition<'a> {
148 type SelectionSet = SelectionSet<'a>;
149
150 fn selection_set(&self) -> &Self::SelectionSet {
151 &self.selection_set
152 }
153}
154
155impl<'a> HasSpan for ImplicitOperationDefinition<'a> {
156 fn span(&self) -> &Span {
157 self.selection_set.span()
158 }
159}