#[cfg(feature = "validator")]
use crate::result::{ApiResult, FieldError};
#[cfg(feature = "validator")]
use validator::{ValidationErrors, ValidationErrorsKind};
#[cfg(feature = "validator")]
pub fn validation_errors_to_field_errors(errors: &ValidationErrors) -> Vec<FieldError> {
let mut result = Vec::new();
collect_field_errors(errors, "", &mut result);
result
}
#[cfg(feature = "validator")]
fn collect_field_errors(errors: &ValidationErrors, parent_prefix: &str, acc: &mut Vec<FieldError>) {
for (field_name, kind) in errors.errors() {
let prefixed_name = if parent_prefix.is_empty() {
field_name.to_string()
} else {
format!("{}.{}", parent_prefix, field_name)
};
match kind {
ValidationErrorsKind::Field(vec) => {
for validation_error in vec {
let message = format_validation_error_message(validation_error);
acc.push(FieldError::new(&prefixed_name, message));
}
}
ValidationErrorsKind::Struct(nested) => {
collect_field_errors(nested, &prefixed_name, acc);
}
ValidationErrorsKind::List(map) => {
for (index, nested) in map {
let list_prefix = format!("{}.{}", prefixed_name, index);
collect_field_errors(nested, &list_prefix, acc);
}
}
}
}
}
#[cfg(feature = "validator")]
fn format_validation_error_message(err: &validator::ValidationError) -> String {
match &err.message {
Some(msg) => msg.to_string(),
None => err.to_string(),
}
}
#[cfg(feature = "validator")]
impl<T> From<ValidationErrors> for ApiResult<T> {
fn from(errors: ValidationErrors) -> Self {
let field_errors = validation_errors_to_field_errors(&errors);
ApiResult::validation_errors(field_errors)
}
}