graphql_federated_graph/federated_graph/
directive_definitions.rs

1use super::*;
2
3pub type DirectiveDefinition<'a> = super::view::ViewNested<'a, DirectiveDefinitionId, DirectiveDefinitionRecord>;
4
5#[derive(Debug, Clone)]
6pub struct DirectiveDefinitionRecord {
7    pub namespace: Option<StringId>,
8    pub name: StringId,
9    pub locations: DirectiveLocations,
10    pub repeatable: bool,
11}
12
13#[derive(Debug, Clone)]
14pub struct DirectiveDefinitionArgument {
15    pub directive_definition_id: DirectiveDefinitionId,
16    pub input_value_definition: InputValueDefinition,
17}
18
19impl FederatedGraph {
20    pub fn iter_directive_definitions(&self) -> impl ExactSizeIterator<Item = DirectiveDefinition<'_>> {
21        self.directive_definitions
22            .iter()
23            .enumerate()
24            .map(move |(idx, record)| DirectiveDefinition {
25                graph: self,
26                view: View { id: idx.into(), record },
27            })
28    }
29
30    pub fn push_directive_definition_argument(
31        &mut self,
32        directive_definition_id: DirectiveDefinitionId,
33        argument: InputValueDefinition,
34    ) {
35        self.directive_definition_arguments.push(DirectiveDefinitionArgument {
36            directive_definition_id,
37            input_value_definition: argument,
38        })
39    }
40
41    pub fn push_directive_definition(
42        &mut self,
43        directive_definitons: DirectiveDefinitionRecord,
44    ) -> DirectiveDefinitionId {
45        let id = self.directive_definitions.len().into();
46        self.directive_definitions.push(directive_definitons);
47        id
48    }
49}
50
51bitflags::bitflags! {
52    /// https://spec.graphql.org/October2021/#sec-The-__Directive-Type
53    #[derive(Default, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug)]
54    pub struct DirectiveLocations: u32 {
55        const QUERY = 0b1 << 0;
56        const MUTATION = 0b1 << 1;
57        const SUBSCRIPTION = 0b1 << 2;
58        const FIELD = 0b1 << 3;
59        const FRAGMENT_DEFINITION = 0b1 << 4;
60        const FRAGMENT_SPREAD = 0b1 << 5;
61        const INLINE_FRAGMENT = 0b1 << 6;
62        const VARIABLE_DEFINITION = 0b1 << 7;
63        const SCHEMA = 0b1 << 8;
64        const SCALAR = 0b1 << 9;
65        const OBJECT = 0b1 << 10;
66        const FIELD_DEFINITION = 0b1 << 11;
67        const ARGUMENT_DEFINITION = 0b1 << 12;
68        const INTERFACE = 0b1 << 13;
69        const UNION = 0b1 << 14;
70        const ENUM = 0b1 << 15;
71        const ENUM_VALUE = 0b1 << 16;
72        const INPUT_OBJECT = 0b1 << 17;
73        const INPUT_FIELD_DEFINITION = 0b1 << 18;
74    }
75}
76
77impl fmt::Display for DirectiveLocations {
78    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
79        let mut locations = self.iter().peekable();
80
81        while let Some(location) = locations.next() {
82            let name = match location {
83                DirectiveLocations::QUERY => "QUERY",
84                DirectiveLocations::MUTATION => "MUTATION",
85                DirectiveLocations::SUBSCRIPTION => "SUBSCRIPTION",
86                DirectiveLocations::FIELD => "FIELD",
87                DirectiveLocations::FRAGMENT_DEFINITION => "FRAGMENT_DEFINITION",
88                DirectiveLocations::FRAGMENT_SPREAD => "FRAGMENT_SPREAD",
89                DirectiveLocations::INLINE_FRAGMENT => "INLINE_FRAGMENT",
90                DirectiveLocations::VARIABLE_DEFINITION => "VARIABLE_DEFINITION",
91                DirectiveLocations::SCHEMA => "SCHEMA",
92                DirectiveLocations::SCALAR => "SCALAR",
93                DirectiveLocations::OBJECT => "OBJECT",
94                DirectiveLocations::FIELD_DEFINITION => "FIELD_DEFINITION",
95                DirectiveLocations::ARGUMENT_DEFINITION => "ARGUMENT_DEFINITION",
96                DirectiveLocations::INTERFACE => "INTERFACE",
97                DirectiveLocations::UNION => "UNION",
98                DirectiveLocations::ENUM => "ENUM",
99                DirectiveLocations::ENUM_VALUE => "ENUM_VALUE",
100                DirectiveLocations::INPUT_OBJECT => "INPUT_OBJECT",
101                DirectiveLocations::INPUT_FIELD_DEFINITION => "INPUT_FIELD_DEFINITION",
102                _ => unreachable!(),
103            };
104
105            f.write_str(name)?;
106
107            if locations.peek().is_some() {
108                f.write_str(" | ")?;
109            }
110        }
111
112        Ok(())
113    }
114}
115
116#[cfg(test)]
117mod tests {
118    use super::*;
119
120    #[test]
121    fn directive_definitions_display() {
122        let all = DirectiveLocations::all().to_string();
123
124        let expected = "QUERY | MUTATION | SUBSCRIPTION | FIELD | FRAGMENT_DEFINITION | FRAGMENT_SPREAD | INLINE_FRAGMENT | VARIABLE_DEFINITION | SCHEMA | SCALAR | OBJECT | FIELD_DEFINITION | ARGUMENT_DEFINITION | INTERFACE | UNION | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION";
125
126        assert_eq!(all, expected);
127    }
128}