pub mod fields;
use std::collections::HashMap;
use rocket::{
form::{error::ErrorKind, Contextual, Form},
serde::json::Json,
Responder
};
#[derive(Responder)]
pub enum ApiError {
#[response(status = 422)]
BadForm(Json<HashMap<String, Vec<String>>>)
}
#[allow(clippy::missing_errors_doc)]
#[deprecated(since = "0.2.0", note = "please use `unpack()` instead")]
pub fn unpack_field_errors<T>(
form: Form<Contextual<'_, T>>
) -> Result<T, ApiError>
where
T: std::fmt::Debug
{
unpack(form)
}
pub fn unpack<T>(form: Form<Contextual<'_, T>>) -> Result<T, ApiError>
where
T: std::fmt::Debug
{
let form = form.into_inner();
if let Some(form) = form.value {
Ok(form)
} else {
let mut field_errors = HashMap::new();
for err in form.context.errors() {
let Some(ref name) = err.name else {
continue;
};
let errmsg = match &err.kind {
ErrorKind::Validation(errmsg) => {
format!("validation failed; {errmsg}")
}
ErrorKind::InvalidLength { .. } => {
format!("invalid length; {}", err.kind)
}
ErrorKind::InvalidChoice { choices: _ } => "invalid choice".into(),
ErrorKind::OutOfRange { .. } => {
format!("out of range; {}", err.kind)
}
_ => {
eprintln!("Unhandled error kind: {err:?}");
continue;
}
};
field_errors
.entry(name.to_string())
.or_insert_with(Vec::<String>::new)
.push(errmsg);
}
Err(ApiError::BadForm(Json(field_errors)))
}
}