1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
use std::{self, fmt}; use std::borrow::Cow; use std::collections::HashMap; use serde_json::{Value, to_value}; use serde::ser::Serialize; #[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] pub struct ValidationError { pub code: Cow<'static, str>, pub message: Option<Cow<'static, str>>, pub params: HashMap<Cow<'static, str>, Value>, } impl ValidationError { pub fn new(code: &'static str) -> ValidationError { ValidationError { code: Cow::from(code), message: None, params: HashMap::new(), } } pub fn add_param<T: Serialize>(&mut self, name: Cow<'static, str>, val: &T) { self.params.insert(name, to_value(val).unwrap()); } } impl fmt::Display for ValidationError { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { write!(fmt, "Validation error: {} [{:?}]", self.code, self.params) } } impl std::error::Error for ValidationError { fn description(&self) -> &str { &self.code } fn cause(&self) -> Option<&std::error::Error> { None } } #[derive(Debug, Serialize, Clone, PartialEq)] pub struct ValidationErrors(HashMap<&'static str, Vec<ValidationError>>); impl ValidationErrors { pub fn new() -> ValidationErrors { ValidationErrors(HashMap::new()) } pub fn inner(self) -> HashMap<&'static str, Vec<ValidationError>> { self.0 } pub fn add(&mut self, field: &'static str, error: ValidationError) { self.0.entry(field).or_insert_with(|| vec![]).push(error); } pub fn is_empty(&self) -> bool { self.0.is_empty() } } impl std::error::Error for ValidationErrors { fn description(&self) -> &str { "Validation failed" } fn cause(&self) -> Option<&std::error::Error> { None } } impl fmt::Display for ValidationErrors { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(self, fmt) } }