Skip to main content

rango_core/
form.rs

1//! Form extraction and validation.
2
3pub use axum::extract::Form;
4
5/// Validation message for a single field.
6pub struct FieldError {
7    field: String,
8    message: String,
9}
10
11impl FieldError {
12    /// New error for the given field with the given message.
13    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
21/// Validation errors keyed by field name.
22pub struct Errors(Vec<FieldError>);
23
24impl Errors {
25    /// Empty error set.
26    pub fn new() -> Self {
27        Self(Vec::new())
28    }
29
30    /// Add an error for the given field.
31    pub fn push(&mut self, field: impl Into<String>, message: impl Into<String>) {
32        self.0.push(FieldError::new(field, message));
33    }
34
35    /// First message for the given field, or empty if none.
36    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    /// True when the form has no errors.
45    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
56/// Types that report their validation errors.
57pub trait Valid {
58    /// Validation errors for this value.
59    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}