bluejay_validator/executable/document/rules/
fragment_name_uniqueness.rs

1use crate::executable::{
2    document::{Error, Rule, Visitor},
3    Cache,
4};
5use bluejay_core::definition::SchemaDefinition;
6use bluejay_core::executable::{ExecutableDocument, FragmentDefinition};
7use std::collections::BTreeMap;
8
9pub struct FragmentNameUniqueness<'a, E: ExecutableDocument> {
10    fragment_definitions: BTreeMap<&'a str, Vec<&'a E::FragmentDefinition>>,
11}
12
13impl<'a, E: ExecutableDocument, S: SchemaDefinition> Visitor<'a, E, S>
14    for FragmentNameUniqueness<'a, E>
15{
16    fn new(_: &'a E, _: &'a S, _: &'a Cache<'a, E, S>) -> Self {
17        Self {
18            fragment_definitions: BTreeMap::new(),
19        }
20    }
21
22    fn visit_fragment_definition(&mut self, fragment_definition: &'a E::FragmentDefinition) {
23        self.fragment_definitions
24            .entry(fragment_definition.name())
25            .or_default()
26            .push(fragment_definition);
27    }
28}
29
30impl<'a, E: ExecutableDocument + 'a, S: SchemaDefinition + 'a> Rule<'a, E, S>
31    for FragmentNameUniqueness<'a, E>
32{
33    type Error = Error<'a, E, S>;
34    type Errors = std::iter::FilterMap<
35        std::collections::btree_map::IntoIter<&'a str, Vec<&'a E::FragmentDefinition>>,
36        fn((&'a str, Vec<&'a E::FragmentDefinition>)) -> Option<Error<'a, E, S>>,
37    >;
38
39    fn into_errors(self) -> Self::Errors {
40        self.fragment_definitions
41            .into_iter()
42            .filter_map(|(name, fragment_definitions)| {
43                (fragment_definitions.len() > 1).then_some(
44                    Error::NonUniqueFragmentDefinitionNames {
45                        name,
46                        fragment_definitions,
47                    },
48                )
49            })
50    }
51}