bluejay_validator/executable/document/rules/
argument_uniqueness.rs

1use crate::executable::{
2    document::{ArgumentError, Error, Path, Rule, Visitor},
3    Cache,
4};
5use crate::utils::duplicates;
6use bluejay_core::definition::SchemaDefinition;
7use bluejay_core::executable::{ExecutableDocument, Field};
8use bluejay_core::{Argument, AsIter, Directive};
9
10pub struct ArgumentUniqueness<'a, E: ExecutableDocument, S: SchemaDefinition> {
11    errors: Vec<Error<'a, E, S>>,
12}
13
14impl<'a, E: ExecutableDocument + 'a, S: SchemaDefinition + 'a> ArgumentUniqueness<'a, E, S> {
15    fn visit_arguments<
16        const CONST: bool,
17        F: Fn(ArgumentError<'a, CONST, E, S>) -> Error<'a, E, S>,
18    >(
19        &mut self,
20        arguments: Option<&'a E::Arguments<CONST>>,
21        build_error: F,
22    ) {
23        if let Some(arguments) = arguments {
24            self.errors
25                .extend(
26                    duplicates(arguments.iter(), Argument::name).map(|(name, arguments)| {
27                        build_error(ArgumentError::NonUniqueArgumentNames { name, arguments })
28                    }),
29                );
30        }
31    }
32}
33
34impl<'a, E: ExecutableDocument + 'a, S: SchemaDefinition + 'a> Visitor<'a, E, S>
35    for ArgumentUniqueness<'a, E, S>
36{
37    fn new(_: &'a E, _: &'a S, _: &'a Cache<'a, E, S>) -> Self {
38        Self { errors: Vec::new() }
39    }
40
41    fn visit_field(
42        &mut self,
43        field: &'a <E as ExecutableDocument>::Field,
44        _: &'a S::FieldDefinition,
45        _: &Path<'a, E>,
46    ) {
47        self.visit_arguments(field.arguments(), Error::InvalidVariableArgument)
48    }
49
50    fn visit_variable_directive(
51        &mut self,
52        directive: &'a <E as ExecutableDocument>::Directive<false>,
53        _: bluejay_core::definition::DirectiveLocation,
54    ) {
55        self.visit_arguments(directive.arguments(), Error::InvalidVariableArgument)
56    }
57
58    fn visit_const_directive(
59        &mut self,
60        directive: &'a <E as ExecutableDocument>::Directive<true>,
61        _: bluejay_core::definition::DirectiveLocation,
62    ) {
63        self.visit_arguments(directive.arguments(), Error::InvalidConstArgument)
64    }
65}
66
67impl<'a, E: ExecutableDocument + 'a, S: SchemaDefinition + 'a> Rule<'a, E, S>
68    for ArgumentUniqueness<'a, E, S>
69{
70    type Error = Error<'a, E, S>;
71    type Errors = std::vec::IntoIter<Error<'a, E, S>>;
72
73    fn into_errors(self) -> Self::Errors {
74        self.errors.into_iter()
75    }
76}