Skip to main content

cynic_parser/executable/
mod.rs

1use std::sync::Arc;
2
3use indexmap::IndexSet;
4
5pub mod ids;
6pub mod iter;
7pub mod writer;
8
9mod extensions;
10mod generated;
11mod string_literal;
12mod types;
13mod values;
14
15use crate::common::IdRange;
16
17pub use self::{
18    generated::{
19        argument::Argument,
20        definition::ExecutableDefinition,
21        descriptions::Description,
22        directive::Directive,
23        fragment::FragmentDefinition,
24        operation::OperationDefinition,
25        selections::{FieldSelection, FragmentSpread, InlineFragment, Selection},
26        variable::VariableDefinition,
27    },
28    iter::Iter,
29    types::Type,
30};
31
32use self::ids::ExecutableDefinitionId;
33
34#[derive(Default)]
35pub struct ExecutableDocument {
36    strings: Arc<IndexSet<Box<str>>>,
37    block_strings: Vec<Box<str>>,
38
39    definitions: Vec<storage::ExecutableDefinitionRecord>,
40    operations: Vec<storage::OperationDefinitionRecord>,
41    fragments: Vec<storage::FragmentDefinitionRecord>,
42
43    selections: Vec<storage::SelectionRecord>,
44    field_selections: Vec<storage::FieldSelectionRecord>,
45    inline_fragments: Vec<storage::InlineFragmentRecord>,
46    fragment_spreads: Vec<storage::FragmentSpreadRecord>,
47
48    directives: Vec<storage::DirectiveRecord>,
49    arguments: Vec<storage::ArgumentRecord>,
50    variables: Vec<storage::VariableDefinitionRecord>,
51    descriptions: Vec<storage::DescriptionRecord>,
52
53    types: Vec<types::TypeRecord>,
54
55    values: crate::values::ValueStore,
56}
57
58// TODO: Make this sealed maybe?  Could also move into id module...
59pub trait ExecutableId: Copy {
60    type Reader<'a>;
61
62    fn read(self, document: &ExecutableDocument) -> Self::Reader<'_>;
63}
64
65#[derive(Clone, Copy)]
66struct ReadContext<'a, I> {
67    id: I,
68    document: &'a ExecutableDocument,
69}
70
71impl ExecutableDocument {
72    pub fn read<T>(&self, id: T) -> T::Reader<'_>
73    where
74        T: ExecutableId,
75    {
76        id.read(self)
77    }
78}
79
80impl ExecutableDocument {
81    pub fn definitions(&self) -> Iter<'_, ExecutableDefinition<'_>> {
82        Iter::new(
83            IdRange::new(
84                ExecutableDefinitionId::new(0),
85                ExecutableDefinitionId::new(self.definitions.len()),
86            ),
87            self,
88        )
89    }
90
91    pub fn operations(&self) -> impl DoubleEndedIterator<Item = OperationDefinition<'_>> + '_ {
92        self.definitions().filter_map(|op| match op {
93            ExecutableDefinition::Operation(reader) => Some(reader),
94            ExecutableDefinition::Fragment(_) => None,
95        })
96    }
97
98    pub fn fragments(&self) -> impl DoubleEndedIterator<Item = FragmentDefinition<'_>> + '_ {
99        self.definitions().filter_map(|op| match op {
100            ExecutableDefinition::Operation(_) => None,
101            ExecutableDefinition::Fragment(reader) => Some(reader),
102        })
103    }
104}
105
106pub mod storage {
107    pub use super::{
108        generated::{
109            argument::ArgumentRecord,
110            definition::ExecutableDefinitionRecord,
111            descriptions::DescriptionRecord,
112            directive::DirectiveRecord,
113            fragment::FragmentDefinitionRecord,
114            operation::OperationDefinitionRecord,
115            selections::{
116                FieldSelectionRecord, FragmentSpreadRecord, InlineFragmentRecord, SelectionRecord,
117            },
118            variable::VariableDefinitionRecord,
119        },
120        types::TypeRecord,
121    };
122}