Skip to main content

ferro_rs/validation/
mod.rs

1//! Request validation for Ferro framework.
2//!
3//! Provides Laravel-inspired validation with declarative rules.
4//!
5//! ## Flash round-trip (Phase 137)
6//!
7//! On validation failure a POST handler can redirect back and preserve both
8//! errors and old form input in the session flash:
9//!
10//! ```rust,ignore
11//! use ferro_rs::validation::{Validator, rules::*};
12//! use ferro_rs::rules;
13//!
14//! // POST handler
15//! let data = req.input::<serde_json::Value>().await?;
16//! if let Err(e) = Validator::new(&data)
17//!     .rules("name", rules![required()])
18//!     .validate()
19//! {
20//!     let referer = req.header("Referer");
21//!     return e.with_old_input(&data).redirect_back(referer);
22//! }
23//!
24//! // GET handler — repopulate form fields
25//! InputProps {
26//!     default_value: req.old("name"),
27//!     error: req.validation_error("name"),
28//!     ..Default::default()
29//! }
30//! ```
31//!
32//! # Example
33//!
34//! ```rust,ignore
35//! use ferro_rs::validation::{Validator, rules};
36//!
37//! let data = serde_json::json!({
38//!     "email": "user@example.com",
39//!     "password": "secret123",
40//!     "age": 25
41//! });
42//!
43//! let validator = Validator::new(&data)
44//!     .rules("email", rules![required, email])
45//!     .rules("password", rules![required, min(8)])
46//!     .rules("age", rules![required, integer, min(18)]);
47//!
48//! if let Err(errors) = validator.validate() {
49//!     println!("Validation failed: {:?}", errors);
50//! }
51//! ```
52
53mod bridge;
54mod error;
55mod rule;
56mod rules;
57mod validatable;
58mod validator;
59
60pub(crate) use bridge::translate_validation;
61pub use bridge::{register_validation_translator, TranslatorFn};
62pub use error::ValidationError;
63pub use rule::Rule;
64pub use rules::*;
65pub use validatable::Validatable;
66pub use validator::{validate, Validator};
67
68/// Macro for creating a vector of boxed validation rules.
69///
70/// This macro boxes each rule, allowing different rule types to be stored
71/// together in a single vector.
72///
73/// # Example
74///
75/// ```rust,ignore
76/// use ferro_rs::validation::{Validator, rules::*};
77/// use ferro_rs::rules;
78///
79/// let validator = Validator::new(&data)
80///     .rules("email", rules![required(), email()])
81///     .rules("name", rules![required(), string(), max(255)]);
82/// ```
83#[macro_export]
84macro_rules! rules {
85    ($($rule:expr),* $(,)?) => {
86        vec![$(Box::new($rule) as Box<dyn $crate::validation::Rule>),*]
87    };
88}