graphql_query/validate/
validate.rs

1use super::context::ValidationContext;
2use crate::ast::{ASTContext, Document};
3use crate::error::Result;
4use crate::visit::{ComposedVisitor, VisitNode, Visitor};
5use std::borrow::Borrow;
6
7/// Trait for a `ValidationRule` that checks a given `GraphQl` document against its rules using a
8/// visitor.
9///
10/// A rule always implements a visitor and accepts the [`ValidationContext`] structure as
11/// its passed context.
12///
13/// Rules implement the `Default` trait, which allows them to be instantiated easily.
14/// The intention of using `Default` is for rules to not carry any external
15/// state as for GraphQL validation no external state is needed.
16pub trait ValidationRule<'a>: Visitor<'a, ValidationContext<'a>> + Default {
17    /// Run this `ValidationRule` against the given document and return a result which errors if
18    /// the rule fails on the document.
19    #[inline]
20    fn validate(ctx: &'a ASTContext, document: &'a Document<'a>) -> Result<()> {
21        let mut validation = ValidationContext::new(ctx);
22        let mut visitor = Self::default();
23        document.visit(&mut validation, &mut visitor);
24        validation.to_result()
25    }
26}
27
28impl<'a, A, B> Default for ComposedVisitor<'a, ValidationContext<'a>, A, B>
29where
30    A: ValidationRule<'a>,
31    B: ValidationRule<'a>,
32{
33    #[inline]
34    fn default() -> Self {
35        ComposedVisitor::new(A::default(), B::default())
36    }
37}
38
39impl<'a, A, B> ValidationRule<'a> for ComposedVisitor<'a, ValidationContext<'a>, A, B>
40where
41    A: ValidationRule<'a>,
42    B: ValidationRule<'a>,
43{
44}
45
46/// Trait to run a [`ValidationRule`] on a given GraphQL Document node.
47pub trait ValidateNode<'a>
48where
49    Self: Borrow<Document<'a>>,
50{
51    /// Run the generic validation rule on the document node and return a result which errors if
52    /// the validation rule fails on the current document.
53    ///
54    /// `document.validate::<YourValidationRule>(&ctx)`
55    #[inline]
56    fn validate<Rule: ValidationRule<'a>>(&'a self, ctx: &'a ASTContext) -> Result<()> {
57        Rule::validate(ctx, self.borrow())
58    }
59}
60
61impl<'a> ValidateNode<'a> for Document<'a> {}