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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
/*
 * serde-validate - A library for validating deserialized structs and enums
 *
 * Copyright (C) 2024 Lucas M. de Jong Larrarte
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
 */

//! # serde-validate
//!
//! The `serde-validate` crate provides utilities for validating deserialized structs and enums in Rust.
//!
//! The core of the crate is the `Validate` trait, which defines a method for validating instances of types
//! and returning a custom error type if validation fails. The crate also includes a procedural serde-validate-macro,
//! `serde-validate`, that generates deserialization code that validates the deserialized data.
//!
//! ## Example
//!
//! ```rust
//! use serde_validate::{Validate, validate_deser};
//!
//! #[validate_deser]
//! struct MyStruct {
//!     value: i32,
//! }
//!
//! impl Validate for MyStruct {
//!     type Error = String;
//!
//!     fn validate(&self) -> Result<(), Self::Error> {
//!         if self.value < 0 {
//!             Err("Value must be non-negative".into())
//!         } else {
//!             Ok(())
//!         }
//!     }
//! }
//!
//! // Assuming you have a JSON input as below:
//! let good_json_input = r#"{ "value": 10 }"#;
//!
//! // Deserialize and validate the JSON input
//! let my_struct: Result<MyStruct, _> = serde_json::from_str(good_json_input);
//! assert!(my_struct.is_ok());
//!
//! // Assuming you have a JSON input as below:
//! let bad_json_input = r#"{ "value": -10 }"#;
//!
//! // Deserialize and validate the JSON input
//! let my_struct: Result<MyStruct, _> = serde_json::from_str(bad_json_input);
//! assert!(my_struct.is_err());
//! ```

/// The `Validate` trait defines the contract for validating deserialized structs.
///
/// Implementors of this trait are required to provide their own validation logic
/// and an associated error type.
///
/// # Example
///
/// ```
/// use serde_validate::Validate;
///
/// struct MyStruct {
///     value: i32,
/// }
///
/// impl Validate for MyStruct {
///     type Error = String;
///
///     fn validate(&self) -> Result<(), Self::Error> {
///         if self.value < 0 {
///             Err("Value must be non-negative".into())
///         } else {
///             Ok(())
///         }
///     }
/// }
///
/// let my_struct = MyStruct { value: 10 };
/// assert!(my_struct.validate().is_ok());
/// ```
pub trait Validate: Sized {
    /// The error type returned by the `validate` method.
    type Error;

    /// Validates the instance, returning `Ok(())` if serde-validate, or an `Error` otherwise.
    fn validate(&self) -> Result<(), Self::Error>;

    /// Consumes the instance, validating it and returning the instance itself if serde-validate.
    ///
    /// This method provides a convenient way to validate and immediately use the instance.
    fn validated(self) -> Result<Self, Self::Error> {
        self.validate().map(|_| self)
    }
}

#[cfg(feature = "macro")]
pub use serde_validate_macro::validate_deser;