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