1pub use axum::extract::Form;
4
5pub struct FieldError {
7 field: String,
8 message: String,
9}
10
11impl FieldError {
12 pub fn new(field: impl Into<String>, message: impl Into<String>) -> Self {
14 Self {
15 field: field.into(),
16 message: message.into(),
17 }
18 }
19}
20
21pub struct Errors(Vec<FieldError>);
23
24impl Errors {
25 pub fn new() -> Self {
27 Self(Vec::new())
28 }
29
30 pub fn push(&mut self, field: impl Into<String>, message: impl Into<String>) {
32 self.0.push(FieldError::new(field, message));
33 }
34
35 pub fn message(&self, field: &str) -> &str {
37 self.0
38 .iter()
39 .find(|error| error.field == field)
40 .map(|error| error.message.as_str())
41 .unwrap_or("")
42 }
43
44 pub fn valid(&self) -> bool {
46 self.0.is_empty()
47 }
48}
49
50impl Default for Errors {
51 fn default() -> Self {
52 Self::new()
53 }
54}
55
56pub trait Valid {
58 fn errors(&self) -> Errors;
60}
61
62#[cfg(test)]
63mod tests {
64 use super::*;
65
66 #[test]
67 fn errors() {
68 let mut errors = Errors::new();
69 assert!(errors.valid());
70 assert_eq!(errors.message("name"), "");
71 errors.push("name", "required");
72 errors.push("name", "too short");
73 errors.push("age", "too old");
74 assert!(!errors.valid());
75 assert_eq!(errors.message("name"), "required");
76 assert_eq!(errors.message("age"), "too old");
77 assert_eq!(errors.message("missing"), "");
78 }
79}