graphql_query/validate/
context.rs

1use bumpalo::collections::Vec;
2use bumpalo::Bump;
3
4use crate::error::Error;
5use crate::{ast::ASTContext, error::ErrorType};
6
7/// The `ValidationContext` carrying a reference to the AST Context's arena and a list of errors.
8///
9/// New errors are added to the list as validation continues to issue error messages if validation
10/// has failed on a document.
11pub struct ValidationContext<'a> {
12    pub arena: &'a Bump,
13    pub errors: Vec<'a, &'a str>,
14}
15
16impl<'a> ValidationContext<'a> {
17    /// Create a new `ValidationContext` given an AST Context.
18    pub fn new(ctx: &'a ASTContext) -> Self {
19        ValidationContext {
20            arena: &ctx.arena,
21            errors: Vec::new_in(&ctx.arena),
22        }
23    }
24
25    /// Add an error to the list of errors in the `ValidationContext`.
26    ///
27    /// This is called inside of validation rules to add an error to the list and fail validation
28    /// of the currently validating document.
29    pub fn add_error<S: AsRef<str>>(&mut self, str: S) {
30        self.errors.push(self.arena.alloc_str(str.as_ref()));
31    }
32
33    /// Convert the context into a result which carries an error if validation has failed on the
34    /// current document.
35    ///
36    /// This is used by `ValidateNode` and the `ValidationRule`'s `validate` method to convert the
37    /// context into a result.
38    pub fn to_result(self) -> Result<(), Error> {
39        if self.errors.is_empty() {
40            Ok(())
41        } else {
42            let mut context = String::new();
43            let mut is_first = true;
44            for error in self.errors {
45                if is_first {
46                    is_first = false;
47                } else {
48                    context.push('\n');
49                }
50                context.push_str("- ");
51                context.push_str(error.as_ref());
52            }
53            Err(Error::new_with_context(
54                "Document failed validation",
55                None,
56                &context,
57                Some(ErrorType::GraphQL),
58            ))
59        }
60    }
61}