1mod debug;
2mod directive_definitions;
3mod directives;
4mod entity;
5mod enum_definitions;
6mod enum_values;
7mod extensions;
8mod ids;
9mod input_value_definitions;
10mod objects;
11mod root_operation_types;
12mod scalar_definitions;
13mod r#type;
14mod view;
15
16pub use self::{
17 directive_definitions::*,
18 directives::*,
19 entity::*,
20 enum_definitions::EnumDefinitionRecord,
21 enum_values::{EnumValue, EnumValueRecord},
22 extensions::*,
23 ids::*,
24 root_operation_types::RootOperationTypes,
25 scalar_definitions::ScalarDefinitionRecord,
26 r#type::{Definition, Type},
27 view::{View, ViewNested},
28};
29pub use std::fmt;
30pub use wrapping::Wrapping;
31
32use crate::directives::*;
33use enum_definitions::EnumDefinition;
34use scalar_definitions::ScalarDefinition;
35use std::ops::Range;
36
37#[derive(Clone, Default)]
38pub struct FederatedGraph {
39 pub subgraphs: Vec<Subgraph>,
40 pub extensions: Vec<Extension>,
41 pub root_operation_types: RootOperationTypes,
42 pub objects: Vec<Object>,
43 pub interfaces: Vec<Interface>,
44 pub fields: Vec<Field>,
45
46 pub directive_definitions: Vec<DirectiveDefinitionRecord>,
47 pub directive_definition_arguments: Vec<DirectiveDefinitionArgument>,
48 pub scalar_definitions: Vec<ScalarDefinitionRecord>,
49 pub enum_definitions: Vec<EnumDefinitionRecord>,
50 pub unions: Vec<Union>,
51 pub input_objects: Vec<InputObject>,
52 pub enum_values: Vec<EnumValueRecord>,
53
54 pub input_value_definitions: Vec<InputValueDefinition>,
56
57 pub strings: Vec<String>,
59}
60
61impl FederatedGraph {
62 #[cfg(feature = "from_sdl")]
63 pub fn from_sdl(sdl: &str) -> Result<Self, crate::DomainError> {
64 if sdl.trim().is_empty() {
65 return Ok(Default::default());
66 }
67 crate::from_sdl::from_sdl(sdl)
68 }
69
70 pub fn definition_name(&self, definition: Definition) -> &str {
71 let name_id = match definition {
72 Definition::Scalar(scalar_id) => self[scalar_id].name,
73 Definition::Object(object_id) => self.at(object_id).name,
74 Definition::Interface(interface_id) => self.at(interface_id).name,
75 Definition::Union(union_id) => self[union_id].name,
76 Definition::Enum(enum_id) => self[enum_id].name,
77 Definition::InputObject(input_object_id) => self[input_object_id].name,
78 };
79
80 &self[name_id]
81 }
82
83 pub fn iter_interfaces(&self) -> impl ExactSizeIterator<Item = View<InterfaceId, &Interface>> {
84 (0..self.interfaces.len()).map(|idx| self.view(InterfaceId::from(idx)))
85 }
86
87 pub fn iter_objects(&self) -> impl ExactSizeIterator<Item = View<ObjectId, &Object>> {
88 (0..self.objects.len()).map(|idx| self.view(ObjectId::from(idx)))
89 }
90
91 pub fn iter_scalar_definitions(&self) -> impl Iterator<Item = ScalarDefinition<'_>> {
92 self.scalar_definitions
93 .iter()
94 .enumerate()
95 .map(|(idx, _)| self.at(ScalarDefinitionId::from(idx)))
96 }
97
98 pub fn iter_enum_definitions(&self) -> impl Iterator<Item = EnumDefinition<'_>> {
99 self.enum_definitions
100 .iter()
101 .enumerate()
102 .map(|(idx, _)| self.at(EnumDefinitionId::from(idx)))
103 }
104}
105
106#[derive(Clone, Debug)]
107pub struct Subgraph {
108 pub name: StringId,
109 pub join_graph_enum_value: EnumValueId,
110 pub url: Option<StringId>,
111}
112
113#[derive(Clone, Debug)]
114pub struct Union {
115 pub name: StringId,
116 pub description: Option<StringId>,
117 pub members: Vec<ObjectId>,
118 pub directives: Vec<Directive>,
119}
120
121#[derive(Clone, Debug)]
122pub struct InputObject {
123 pub name: StringId,
124 pub description: Option<StringId>,
125 pub fields: InputValueDefinitions,
126 pub directives: Vec<Directive>,
127}
128
129#[derive(Default, Clone, PartialEq, PartialOrd, Debug)]
130#[allow(clippy::enum_variant_names)]
131pub enum Value {
132 #[default]
133 Null,
134 String(StringId),
135 Int(i64),
136 Float(f64),
137 Boolean(bool),
138 UnboundEnumValue(StringId),
144 EnumValue(EnumValueId),
145 Object(Box<[(StringId, Value)]>),
146 List(Box<[Value]>),
147}
148
149#[derive(Clone, Debug)]
150pub struct Object {
151 pub name: StringId,
152 pub directives: Vec<Directive>,
153 pub description: Option<StringId>,
154 pub implements_interfaces: Vec<InterfaceId>,
155 pub fields: Fields,
156}
157
158#[derive(Clone, Debug)]
159pub struct Interface {
160 pub name: StringId,
161 pub directives: Vec<Directive>,
162 pub description: Option<StringId>,
163 pub implements_interfaces: Vec<InterfaceId>,
164 pub fields: Fields,
165}
166
167#[derive(Clone, Debug)]
168pub struct Field {
169 pub parent_entity_id: EntityDefinitionId,
170 pub name: StringId,
171 pub description: Option<StringId>,
172 pub r#type: Type,
173 pub arguments: InputValueDefinitions,
174 pub directives: Vec<Directive>,
175}
176
177impl Value {
178 pub fn is_list(&self) -> bool {
179 matches!(self, Value::List(_))
180 }
181
182 pub fn is_null(&self) -> bool {
183 matches!(self, Value::Null)
184 }
185}
186
187#[derive(Clone, PartialEq, Debug)]
188pub struct InputValueDefinition {
189 pub name: StringId,
190 pub r#type: Type,
191 pub directives: Vec<Directive>,
192 pub description: Option<StringId>,
193 pub default: Option<Value>,
194}
195
196#[derive(Clone)]
198pub struct FieldProvides {
199 pub subgraph_id: SubgraphId,
200 pub fields: SelectionSet,
201}
202
203#[derive(Clone)]
205pub struct FieldRequires {
206 pub subgraph_id: SubgraphId,
207 pub fields: SelectionSet,
208}
209
210#[derive(Clone, Debug, PartialEq, PartialOrd)]
211pub struct SelectionSet(pub Vec<Selection>);
212
213impl From<Vec<Selection>> for SelectionSet {
214 fn from(selections: Vec<Selection>) -> Self {
215 SelectionSet(selections)
216 }
217}
218
219impl FromIterator<Selection> for SelectionSet {
220 fn from_iter<I: IntoIterator<Item = Selection>>(iter: I) -> Self {
221 SelectionSet(iter.into_iter().collect())
222 }
223}
224
225impl std::ops::Deref for SelectionSet {
226 type Target = Vec<Selection>;
227 fn deref(&self) -> &Self::Target {
228 &self.0
229 }
230}
231
232impl std::ops::DerefMut for SelectionSet {
233 fn deref_mut(&mut self) -> &mut Self::Target {
234 &mut self.0
235 }
236}
237
238impl SelectionSet {
239 pub fn find_field(&self, field_id: FieldId) -> Option<&FieldSelection> {
240 for selection in &self.0 {
241 match selection {
242 Selection::Field(field) => {
243 if field.field_id == field_id {
244 return Some(field);
245 }
246 }
247 Selection::InlineFragment { subselection, .. } => {
248 if let Some(found) = subselection.find_field(field_id) {
249 return Some(found);
250 }
251 }
252 }
253 }
254 None
255 }
256}
257
258#[derive(Clone, Debug, PartialEq, PartialOrd)]
259pub enum Selection {
260 Field(FieldSelection),
261 InlineFragment { on: Definition, subselection: SelectionSet },
262}
263
264#[derive(Clone, Debug, PartialEq, PartialOrd)]
265pub struct FieldSelection {
266 pub field_id: FieldId,
267 pub arguments: Vec<(InputValueDefinitionId, Value)>,
268 pub subselection: SelectionSet,
269}
270
271#[derive(Clone, Debug)]
272pub struct Key {
273 pub subgraph_id: SubgraphId,
275
276 pub fields: SelectionSet,
278
279 pub is_interface_object: bool,
281
282 pub resolvable: bool,
283}
284
285impl std::ops::Index<InputValueDefinitions> for FederatedGraph {
286 type Output = [InputValueDefinition];
287
288 fn index(&self, index: InputValueDefinitions) -> &Self::Output {
289 let (start, len) = index;
290 &self.input_value_definitions[usize::from(start)..(usize::from(start) + len)]
291 }
292}
293
294impl std::ops::Index<Fields> for FederatedGraph {
295 type Output = [Field];
296
297 fn index(&self, index: Fields) -> &Self::Output {
298 &self.fields[usize::from(index.start)..usize::from(index.end)]
299 }
300}
301
302pub type InputValueDefinitionSet = Vec<InputValueDefinitionSetItem>;
303
304#[derive(serde::Serialize, serde::Deserialize, Clone, Debug, PartialEq, PartialOrd)]
305pub struct InputValueDefinitionSetItem {
306 pub input_value_definition: InputValueDefinitionId,
307 pub subselection: InputValueDefinitionSet,
308}
309
310pub type Fields = Range<FieldId>;
312pub type InputValueDefinitions = (InputValueDefinitionId, usize);
314
315pub const NO_INPUT_VALUE_DEFINITION: InputValueDefinitions = (InputValueDefinitionId::const_from_usize(0), 0);
316pub const NO_FIELDS: Fields = Range {
317 start: FieldId::const_from_usize(0),
318 end: FieldId::const_from_usize(0),
319};
320
321pub type FieldSet = Vec<FieldSetItem>;
322
323#[derive(Clone, PartialEq, PartialOrd)]
324pub struct FieldSetItem {
325 pub field: FieldId,
326 pub arguments: Vec<(InputValueDefinitionId, Value)>,
327 pub subselection: FieldSet,
328}
329
330#[cfg(test)]
331mod tests {
332 use super::*;
333
334 #[test]
335 fn override_label() {
336 assert!("".parse::<OverrideLabel>().is_err());
337 assert!("percent(heh)".parse::<OverrideLabel>().is_err());
338 assert!("percent(30".parse::<OverrideLabel>().is_err());
339
340 assert_eq!(
341 "percent(30)".parse::<OverrideLabel>().unwrap().as_percent().unwrap(),
342 30
343 );
344 }
345}