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