Skip to main content

cynic_parser/executable/
writer.rs

1use std::sync::Arc;
2
3use indexmap::IndexSet;
4
5use crate::common::IdRange;
6
7use super::{ExecutableDocument, ids::*, storage::*};
8
9pub struct ExecutableAstWriter {
10    pub values: crate::values::writer::ValueWriter,
11
12    strings: IndexSet<Box<str>>,
13    block_strings: Vec<Box<str>>,
14
15    definitions: Vec<ExecutableDefinitionRecord>,
16    operations: Vec<OperationDefinitionRecord>,
17    fragments: Vec<FragmentDefinitionRecord>,
18
19    selections: Vec<SelectionRecord>,
20    field_selections: Vec<FieldSelectionRecord>,
21    inline_fragments: Vec<InlineFragmentRecord>,
22    fragment_spreads: Vec<FragmentSpreadRecord>,
23
24    directives: Vec<DirectiveRecord>,
25    arguments: Vec<ArgumentRecord>,
26    variables: Vec<VariableDefinitionRecord>,
27    descriptions: Vec<DescriptionRecord>,
28
29    types: Vec<TypeRecord>,
30
31    directive_cursor: DirectiveId,
32    variable_definition_cursor: VariableDefinitionId,
33}
34
35impl Default for ExecutableAstWriter {
36    fn default() -> Self {
37        Self {
38            strings: Default::default(),
39            block_strings: Default::default(),
40            definitions: Default::default(),
41            operations: Default::default(),
42            fragments: Default::default(),
43            selections: Default::default(),
44            field_selections: Default::default(),
45            inline_fragments: Default::default(),
46            fragment_spreads: Default::default(),
47            directives: Default::default(),
48            arguments: Default::default(),
49            variables: Default::default(),
50            descriptions: Default::default(),
51            types: Default::default(),
52            values: Default::default(),
53            directive_cursor: DirectiveId::new(0),
54            variable_definition_cursor: VariableDefinitionId::new(0),
55        }
56    }
57}
58
59impl ExecutableAstWriter {
60    pub fn new() -> Self {
61        Self::default()
62    }
63
64    pub fn finish(self) -> ExecutableDocument {
65        // TODO: Possibly assert things in here for safety...
66        let ExecutableAstWriter {
67            strings,
68            block_strings,
69            definitions,
70            operations,
71            fragments,
72            selections,
73            field_selections,
74            inline_fragments,
75            fragment_spreads,
76            directives,
77            arguments,
78            variables,
79            descriptions,
80            types,
81            values,
82            directive_cursor: _,
83            variable_definition_cursor: _,
84        } = self;
85
86        let strings = Arc::new(strings);
87        let values = values.finish(Arc::clone(&strings));
88
89        ExecutableDocument {
90            strings,
91            block_strings,
92            definitions,
93            operations,
94            fragments,
95            selections,
96            field_selections,
97            inline_fragments,
98            fragment_spreads,
99            directives,
100            arguments,
101            variables,
102            descriptions,
103            types,
104            values,
105        }
106    }
107
108    pub fn operation_definition(
109        &mut self,
110        definition: OperationDefinitionRecord,
111    ) -> ExecutableDefinitionId {
112        let id = OperationDefinitionId::new(self.operations.len());
113        self.operations.push(definition);
114
115        let definition_id = ExecutableDefinitionId::new(self.definitions.len());
116        self.definitions
117            .push(ExecutableDefinitionRecord::Operation(id));
118
119        definition_id
120    }
121
122    pub fn fragment_definition(
123        &mut self,
124        definition: FragmentDefinitionRecord,
125    ) -> ExecutableDefinitionId {
126        let id = FragmentDefinitionId::new(self.fragments.len());
127        self.fragments.push(definition);
128
129        let definition_id = ExecutableDefinitionId::new(self.definitions.len());
130        self.definitions
131            .push(ExecutableDefinitionRecord::Fragment(id));
132
133        definition_id
134    }
135
136    pub fn description(&mut self, description: DescriptionRecord) -> DescriptionId {
137        let id = DescriptionId::new(self.descriptions.len());
138        self.descriptions.push(description);
139        id
140    }
141
142    pub fn variable_definition(
143        &mut self,
144        record: VariableDefinitionRecord,
145    ) -> VariableDefinitionId {
146        let id = VariableDefinitionId::new(self.variables.len());
147        self.variables.push(record);
148        id
149    }
150
151    pub fn variable_definition_range(
152        &mut self,
153        expected_count: Option<usize>,
154    ) -> IdRange<VariableDefinitionId> {
155        let start = self.variable_definition_cursor;
156        let end = VariableDefinitionId::new(self.variables.len());
157        self.variable_definition_cursor = end;
158        let range = IdRange::new(start, end);
159
160        assert_eq!(range.len(), expected_count.unwrap_or_default());
161
162        range
163    }
164
165    pub fn type_reference(&mut self, ty: TypeRecord) -> TypeId {
166        let ty_id = TypeId::new(self.types.len());
167        self.types.push(ty);
168        ty_id
169    }
170
171    pub fn selection_set(
172        &mut self,
173        mut selection_set: Vec<SelectionRecord>,
174    ) -> IdRange<SelectionId> {
175        let start_range = SelectionId::new(self.selections.len());
176        self.selections.append(&mut selection_set);
177        let end_range = SelectionId::new(self.selections.len());
178
179        IdRange::new(start_range, end_range)
180    }
181
182    pub fn field_selection(&mut self, record: FieldSelectionRecord) -> FieldSelectionId {
183        let id = FieldSelectionId::new(self.field_selections.len());
184        self.field_selections.push(record);
185        id
186    }
187
188    pub fn fragment_spread(&mut self, record: FragmentSpreadRecord) -> FragmentSpreadId {
189        let id = FragmentSpreadId::new(self.fragment_spreads.len());
190        self.fragment_spreads.push(record);
191        id
192    }
193
194    pub fn inline_fragment(&mut self, record: InlineFragmentRecord) -> InlineFragmentId {
195        let id = InlineFragmentId::new(self.inline_fragments.len());
196        self.inline_fragments.push(record);
197        id
198    }
199
200    pub fn arguments(&mut self, mut records: Vec<ArgumentRecord>) -> IdRange<ArgumentId> {
201        let start = ArgumentId::new(self.arguments.len());
202        self.arguments.append(&mut records);
203        let end = ArgumentId::new(self.arguments.len());
204
205        IdRange::new(start, end)
206    }
207
208    pub fn directive(&mut self, directive: DirectiveRecord) -> DirectiveId {
209        let id = DirectiveId::new(self.directives.len());
210        self.directives.push(directive);
211        id
212    }
213
214    pub fn directive_range(&mut self, expected_count: Option<usize>) -> IdRange<DirectiveId> {
215        let start = self.directive_cursor;
216        let end = DirectiveId::new(self.directives.len());
217        self.directive_cursor = end;
218        let range = IdRange::new(start, end);
219
220        assert_eq!(range.len(), expected_count.unwrap_or_default());
221
222        range
223    }
224
225    pub fn block_string(&mut self, string: &str) -> BlockStringLiteralId {
226        let literal_id = BlockStringLiteralId::new(self.block_strings.len());
227        self.block_strings.push(string.into());
228
229        literal_id
230    }
231
232    pub fn ident(&mut self, ident: &str) -> StringId {
233        self.intern_string(ident)
234    }
235
236    // TOOD: should this be pub? not sure...
237    pub fn intern_string(&mut self, string: &str) -> StringId {
238        let (id, _) = self.strings.insert_full(string.into());
239        StringId::new(id)
240    }
241
242    // TOOD: should this be pub? not sure...
243    pub fn intern_owned_string(&mut self, string: String) -> StringId {
244        let (id, _) = self.strings.insert_full(string.into());
245        StringId::new(id)
246    }
247}