Skip to main content

rusdantic_core/
traits.rs

1//! Core validation traits.
2//!
3//! The [`Validate`] trait is the central abstraction of Rusdantic. It is
4//! automatically implemented by the `#[derive(Rusdantic)]` macro and can
5//! also be implemented manually for custom types.
6
7use crate::error::ValidationErrors;
8
9/// The core validation trait for Rusdantic.
10///
11/// This trait is automatically implemented by `#[derive(Rusdantic)]`.
12/// It validates all fields of a struct according to their declared rules
13/// and returns all validation errors at once (collect-all, not fail-fast).
14///
15/// # Example
16///
17/// ```ignore
18/// use rusdantic::{Rusdantic, Validate};
19///
20/// #[derive(Rusdantic)]
21/// struct User {
22///     #[rusdantic(email)]
23///     email: String,
24/// }
25///
26/// let user = User { email: "not-an-email".to_string() };
27/// assert!(user.validate().is_err());
28/// ```
29pub trait Validate {
30    /// Validate this value, collecting all validation errors.
31    ///
32    /// Returns `Ok(())` if all validation rules pass, or `Err(ValidationErrors)`
33    /// containing all validation failures with their field paths.
34    fn validate(&self) -> Result<(), ValidationErrors>;
35
36    /// Validate with external context (database connection, config, etc.).
37    ///
38    /// This method enables validators that need access to external resources.
39    /// The default implementation ignores the context and delegates to `validate()`.
40    ///
41    /// # Example
42    ///
43    /// ```ignore
44    /// struct DbContext { /* ... */ }
45    ///
46    /// let user = User { email: "user@example.com".to_string() };
47    /// let ctx = DbContext { /* ... */ };
48    /// user.validate_with_context(&ctx)?;
49    /// ```
50    fn validate_with_context(&self, _ctx: &dyn std::any::Any) -> Result<(), ValidationErrors> {
51        self.validate()
52    }
53}
54
55// Implement Validate for common wrapper types so they can be used
56// transparently in validated structs.
57
58impl<T: Validate> Validate for Box<T> {
59    fn validate(&self) -> Result<(), ValidationErrors> {
60        (**self).validate()
61    }
62}
63
64impl<T: Validate> Validate for std::sync::Arc<T> {
65    fn validate(&self) -> Result<(), ValidationErrors> {
66        (**self).validate()
67    }
68}
69
70impl<T: Validate> Validate for std::rc::Rc<T> {
71    fn validate(&self) -> Result<(), ValidationErrors> {
72        (**self).validate()
73    }
74}