request_pretreat/prefabs/
json.rs1use std::{
2 fmt::{Debug, Display},
3 marker::PhantomData,
4 pin::Pin,
5 task::Poll,
6};
7
8use actix_web::{error::JsonPayloadError, web, FromRequest};
9use futures::{ready, Future};
10use pin_project::pin_project;
11
12use serde::Deserialize;
13
14use crate::Treater;
15
16use super::RawError;
17
18pub struct JsonPayload<T: for<'de> Deserialize<'de>>(PhantomData<T>);
19
20impl<T> Treater for JsonPayload<T>
21where
22 T: for<'de> Deserialize<'de>,
23{
24 type Fut = JsonTreaterFut<T>;
25
26 type Resp = T;
27
28 type Err = JsonError;
29
30 fn proc(req: &actix_web::HttpRequest, payload: &mut actix_web::dev::Payload) -> Self::Fut {
31 let task = web::Json::<T>::from_request(req, payload);
32 JsonTreaterFut { task }
33 }
34}
35
36pub struct JsonError(RawError<JsonPayloadError>);
37
38impl Debug for JsonError {
39 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
40 Debug::fmt(&self.0, f)
41 }
42}
43
44impl Display for JsonError {
45 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
46 Display::fmt(&self.0, f)
47 }
48}
49impl std::error::Error for JsonError {}
50
51#[pin_project]
52pub struct JsonTreaterFut<T>
53where
54 T: for<'de> Deserialize<'de>,
55{
56 #[pin]
57 task: <actix_web::web::Json<T> as FromRequest>::Future,
58}
59
60impl<T> Future for JsonTreaterFut<T>
61where
62 T: for<'de> Deserialize<'de>,
63{
64 type Output = Result<T, JsonError>;
65
66 fn poll(self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll<Self::Output> {
67 let this = self.project();
68
69 let result = ready!(this.task.poll(cx));
70
71 Poll::Ready(match result {
72 Ok(data) => Ok(data.into_inner()),
73 Err(err) => Err(JsonError(RawError::new(err))),
74 })
75 }
76}