Skip to main content

sz_orm_core/validation/
mod.rs

1//! # 数据验证框架(`data-validation` feature)
2//!
3//! 提供 `Validate` trait + `ValidationError` + 8 种字段级校验规则,
4//! 支持 `#[derive(Validate)]` 自动生成验证代码。
5
6pub mod rules;
7
8#[cfg(feature = "validate-on-write")]
9pub mod model_integration;
10
11#[cfg(test)]
12mod derive_tests;
13
14/// 验证错误
15///
16/// 字段级含义由各 variant 的 `#[error(...)]` 文案描述(field/min/max/value 等)。
17#[allow(missing_docs)]
18#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
19pub enum ValidationError {
20    /// 必填字段为空
21    #[error("field `{field}` is required but empty")]
22    Required { field: String },
23    /// 长度超出范围
24    #[error("field `{field}` length {actual} not in [{min}, {max}]")]
25    Length {
26        field: String,
27        min: usize,
28        max: usize,
29        actual: usize,
30    },
31    /// 数值超出范围
32    #[error("field `{field}` value {actual} not in [{min}, {max}]")]
33    Range {
34        field: String,
35        min: String,
36        max: String,
37        actual: String,
38    },
39    /// 邮箱格式无效
40    #[error("field `{field}` value `{value}` is not a valid email")]
41    Email { field: String, value: String },
42    /// 正则不匹配
43    #[error("field `{field}` value `{value}` does not match pattern `{pattern}`")]
44    Regex {
45        field: String,
46        pattern: String,
47        value: String,
48    },
49    /// 不包含所需子串
50    #[error("field `{field}` does not contain `{substring}`")]
51    Contains { field: String, substring: String },
52    /// 包含禁止子串
53    #[error("field `{field}` contains forbidden `{substring}`")]
54    DoesNotContain { field: String, substring: String },
55    /// 自定义校验失败
56    #[error("field `{field}` custom validation failed: {reason}")]
57    Custom { field: String, reason: String },
58    /// 聚合错误(非短路,收集全部失败)
59    #[error("validation failed with {count} error(s)")]
60    Aggregate {
61        errors: Vec<ValidationError>,
62        count: usize,
63    },
64}
65
66/// 验证 trait
67pub trait Validate {
68    /// 执行验证,返回 Ok 或聚合错误
69    fn validate(&self) -> Result<(), ValidationError>;
70}
71
72/// 聚合多个验证结果(非短路,收集全部错误)
73pub fn aggregate(results: Vec<Result<(), ValidationError>>) -> Result<(), ValidationError> {
74    let errors: Vec<ValidationError> = results.into_iter().filter_map(|r| r.err()).collect();
75    match errors.len() {
76        0 => Ok(()),
77        1 => Err(errors.into_iter().next().unwrap()),
78        n => Err(ValidationError::Aggregate { errors, count: n }),
79    }
80}