fj_core/layers/
validation.rs

1//! Layer infrastructure for [`Validation`]
2
3use crate::{
4    geometry::Geometry,
5    objects::{AnyObject, Stored},
6    validation::{Validation, ValidationError, ValidationErrors},
7};
8
9use super::{Command, Event, Layer};
10
11impl Layer<Validation> {
12    /// Take all errors stored in the validation layer
13    pub fn take_errors(&mut self) -> Result<(), ValidationErrors> {
14        self.process(TakeErrors, &mut Vec::new())
15    }
16}
17
18/// Validate an object
19pub struct ValidateObject<'r> {
20    /// The object to validate
21    pub object: AnyObject<Stored>,
22
23    /// Reference to `Geometry`, which is required for validation
24    pub geometry: &'r Geometry,
25}
26
27impl Command<Validation> for ValidateObject<'_> {
28    type Result = ();
29    type Event = ValidationFailed;
30
31    fn decide(self, state: &Validation, events: &mut Vec<Self::Event>) {
32        let mut errors = Vec::new();
33        self.object
34            .validate(&state.config, &mut errors, self.geometry);
35
36        for err in errors {
37            events.push(ValidationFailed {
38                object: self.object.clone(),
39                err,
40            });
41        }
42    }
43}
44
45/// Take all errors stored in the validation layer
46///
47/// Serves both as a command for and event produced by `Layer<Validation>`.
48pub struct TakeErrors;
49
50impl Command<Validation> for TakeErrors {
51    type Result = Result<(), ValidationErrors>;
52    type Event = Self;
53
54    fn decide(
55        self,
56        state: &Validation,
57        events: &mut Vec<Self::Event>,
58    ) -> Self::Result {
59        let errors = ValidationErrors(state.errors.values().cloned().collect());
60
61        events.push(self);
62
63        if errors.0.is_empty() {
64            Ok(())
65        } else {
66            Err(errors)
67        }
68    }
69}
70
71impl Event<Validation> for TakeErrors {
72    fn evolve(&self, state: &mut Validation) {
73        state.errors.clear();
74    }
75}
76
77/// Validation of an object failed
78///
79/// Event produced by `Layer<Validation>`.
80#[derive(Clone)]
81pub struct ValidationFailed {
82    /// The object for which validation failed
83    pub object: AnyObject<Stored>,
84
85    /// The validation error
86    pub err: ValidationError,
87}
88
89impl Event<Validation> for ValidationFailed {
90    fn evolve(&self, state: &mut Validation) {
91        state.errors.insert(self.object.id(), self.err.clone());
92    }
93}