apollo_encoder/
directive_def.rs1use std::fmt;
2
3use crate::{ArgumentsDefinition, InputValueDefinition, StringValue};
4
5#[derive(Debug, Clone)]
34pub struct DirectiveDefinition {
35 name: String,
37 description: Option<StringValue>,
39 args: ArgumentsDefinition,
42 locations: Vec<String>,
45 repeatable: bool,
47}
48
49impl DirectiveDefinition {
50 pub fn new(name: String) -> Self {
52 Self {
53 name,
54 description: None,
55 args: ArgumentsDefinition::new(),
56 locations: Vec::new(),
57 repeatable: false,
58 }
59 }
60
61 pub fn description(&mut self, description: String) {
63 self.description = Some(StringValue::Top {
64 source: description,
65 });
66 }
67
68 pub fn location(&mut self, location: String) {
70 self.locations.push(location);
71 }
72
73 pub fn arg(&mut self, arg: InputValueDefinition) {
75 self.args.input_value(arg);
76 }
77
78 pub fn repeatable(&mut self) {
80 self.repeatable = true;
81 }
82}
83
84impl fmt::Display for DirectiveDefinition {
85 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
86 if let Some(description) = &self.description {
87 writeln!(f, "{description}")?;
88 }
89 write!(f, "directive @{}", self.name)?;
90
91 if !self.args.input_values.is_empty() {
92 write!(f, "{}", self.args)?;
93 }
94
95 if self.repeatable {
96 write!(f, " repeatable")?;
97 }
98
99 for (i, location) in self.locations.iter().enumerate() {
100 match i {
101 0 => write!(f, " on {location}")?,
102 _ => write!(f, " | {location}")?,
103 }
104 }
105
106 writeln!(f)
108 }
109}
110
111#[cfg(test)]
112mod tests {
113 use super::*;
114 use crate::Type_;
115 use pretty_assertions::assert_eq;
116
117 #[test]
118 fn it_encodes_directives_for_a_single_location() {
119 let mut directive = DirectiveDefinition::new("infer".to_string());
120 directive.description("Infer field types from field values.".to_string());
121 directive.location("OBJECT".to_string());
122
123 assert_eq!(
124 directive.to_string(),
125 r#""Infer field types from field values."
126directive @infer on OBJECT
127"#
128 );
129 }
130
131 #[test]
132 fn it_encodes_directives_for_multiple_location() {
133 let mut directive = DirectiveDefinition::new("infer".to_string());
134 directive.description("Infer field types\nfrom field values.".to_string());
135 directive.location("OBJECT".to_string());
136 directive.location("FIELD_DEFINITION".to_string());
137 directive.location("INPUT_FIELD_DEFINITION".to_string());
138
139 assert_eq!(
140 directive.to_string(),
141 r#""""
142Infer field types
143from field values.
144"""
145directive @infer on OBJECT | FIELD_DEFINITION | INPUT_FIELD_DEFINITION
146"#
147 );
148 }
149
150 #[test]
151 fn it_encodes_directives_with_arguments() {
152 let mut directive = DirectiveDefinition::new("infer".to_string());
153 directive.description("Infer field types from field values.".to_string());
154 directive.location("OBJECT".to_string());
155
156 let ty_1 = Type_::NamedType {
157 name: "SpaceProgram".to_string(),
158 };
159
160 let ty_2 = Type_::List { ty: Box::new(ty_1) };
161 let arg = InputValueDefinition::new("cat".to_string(), ty_2);
162 directive.arg(arg);
163
164 assert_eq!(
165 directive.to_string(),
166 r#""Infer field types from field values."
167directive @infer(cat: [SpaceProgram]) on OBJECT
168"#
169 );
170 }
171
172 #[test]
173 fn it_encodes_directives_with_arguments_with_description() {
174 let mut directive = DirectiveDefinition::new("infer".to_string());
175 directive.description("Infer field types from field values.".to_string());
176 directive.location("OBJECT".to_string());
177
178 let ty_1 = Type_::NamedType {
179 name: "SpaceProgram".to_string(),
180 };
181
182 let ty_2 = Type_::List { ty: Box::new(ty_1) };
183 let mut arg = InputValueDefinition::new("cat".to_string(), ty_2);
184 arg.description("Space Program for flying cats".to_string());
185 directive.arg(arg);
186
187 assert_eq!(
188 directive.to_string(),
189 r#""Infer field types from field values."
190directive @infer(
191 "Space Program for flying cats"
192 cat: [SpaceProgram]
193 ) on OBJECT
194"#
195 );
196 }
197}