use std::{collections::BTreeMap, thread};
use crate::{
objects::{BehindHandle, Object, ObjectSet},
storage::ObjectId,
validate::ValidationError,
};
use super::State;
#[derive(Default)]
pub struct Validation {
errors: BTreeMap<ObjectId, ValidationError>,
}
impl Drop for Validation {
fn drop(&mut self) {
let num_errors = self.errors.len();
if num_errors > 0 {
println!(
"Dropping `Validation` with {num_errors} unhandled validation \
errors:"
);
for err in self.errors.values() {
println!("{}", err);
}
if !thread::panicking() {
panic!();
}
}
}
}
impl State for Validation {
type Command = ValidationCommand;
type Event = ValidationEvent;
fn decide(&self, command: Self::Command, events: &mut Vec<Self::Event>) {
let mut errors = Vec::new();
match command {
ValidationCommand::ValidateObject { object } => {
object.validate(&mut errors);
for err in errors {
events.push(ValidationEvent::ValidationFailed {
object: object.clone(),
err,
});
}
}
ValidationCommand::OnlyValidate { objects } => {
events.push(ValidationEvent::ClearErrors);
for object in objects {
object.validate(&mut errors);
for err in errors.drain(..) {
events.push(ValidationEvent::ValidationFailed {
object: object.clone(),
err,
});
}
}
}
}
}
fn evolve(&mut self, event: &Self::Event) {
match event {
ValidationEvent::ValidationFailed { object, err } => {
self.errors.insert(object.id(), err.clone());
}
ValidationEvent::ClearErrors => self.errors.clear(),
}
}
}
pub enum ValidationCommand {
ValidateObject {
object: Object<BehindHandle>,
},
OnlyValidate {
objects: ObjectSet,
},
}
#[derive(Clone)]
pub enum ValidationEvent {
ValidationFailed {
object: Object<BehindHandle>,
err: ValidationError,
},
ClearErrors,
}