Skip to main content

rustapi_core/
validation.rs

1use crate::error::{ApiError, FieldError};
2
3/// Unified validation trait for synchronous validation
4///
5/// This trait allows uniform access to both `validator` (external) and
6/// `rustapi_validate::v2` (internal) validation engines.
7pub trait Validatable {
8    /// Perform synchronous validation
9    fn do_validate(&self) -> Result<(), ApiError>;
10}
11
12// Blanket implementation for types implementing the external validator::Validate trait
13impl<T: validator::Validate> Validatable for T {
14    fn do_validate(&self) -> Result<(), ApiError> {
15        match validator::Validate::validate(self) {
16            Ok(_) => Ok(()),
17            Err(e) => Err(convert_validator_errors(e)),
18        }
19    }
20}
21
22/// Helper to convert validator::ValidationErrors to rustapi_core::error::ApiError
23pub fn convert_validator_errors(errors: validator::ValidationErrors) -> ApiError {
24    let field_errors =
25        errors
26            .field_errors()
27            .iter()
28            .flat_map(|(field, errs)| {
29                let field_name = field.to_string();
30                errs.iter().map(move |e| FieldError {
31                    field: field_name.clone(),
32                    code: e.code.to_string(),
33                    message: e.message.clone().map(|m| m.to_string()).unwrap_or_else(|| {
34                        format!("Validation failed for field '{}'", &field_name)
35                    }),
36                })
37            })
38            .collect();
39    ApiError::validation(field_errors)
40}
41
42/// Helper to convert rustapi_validate::v2::ValidationErrors to rustapi_core::error::ApiError
43pub fn convert_v2_errors(errors: rustapi_validate::v2::ValidationErrors) -> ApiError {
44    let field_errors = errors
45        .fields
46        .iter()
47        .flat_map(|(field, errs)| {
48            let field_name = field.to_string();
49            errs.iter().map(move |e| FieldError {
50                field: field_name.clone(),
51                code: e.code.to_string(),
52                message: e.message.clone(),
53            })
54        })
55        .collect();
56    ApiError::validation(field_errors)
57}