use actix_web::{dev::Payload, http::StatusCode, FromRequest, HttpRequest, ResponseError}; use serde::Deserialize; use serde_qs::Config; use std::{future::Future, pin::Pin}; use thiserror::Error; pub struct QsForm(pub T) where T: for<'de> Deserialize<'de>; #[derive(Debug, Error)] pub enum QsFormError { #[error("{}", .0)] FutureError(#[from] actix_web::Error), #[error("{}", .0)] ParseError(#[from] serde_qs::Error), } impl ResponseError for QsFormError { fn status_code(&self) -> StatusCode { StatusCode::BAD_REQUEST } } impl FromRequest for QsForm where T: for<'de> Deserialize<'de>, { type Error = QsFormError; type Future = Pin, Self::Error>>>>; fn from_request(req: &HttpRequest, payload: &mut Payload) -> Self::Future { let data = String::from_request(req, payload); Box::pin(async move { let data = data.await?; let config = Config::new(10, false); let form: T = config.deserialize_str(&data)?; Ok(QsForm(form)) }) } }