bluejay_validator/executable/document/rules/
named_operation_name_uniqueness.rs

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