1use super::{Encoding, FromReq, FromRes, IntoReq, IntoRes};
2use crate::{
3 error::{FromServerFnError, IntoAppError, ServerFnErrorErr},
4 request::{ClientReq, Req},
5 response::{ClientRes, TryRes},
6 ContentType, Decodes, Encodes,
7};
8use std::marker::PhantomData;
9
10pub struct Post<Codec>(PhantomData<Codec>);
12
13impl<Codec: ContentType> ContentType for Post<Codec> {
14 const CONTENT_TYPE: &'static str = Codec::CONTENT_TYPE;
15}
16
17impl<Codec: ContentType> Encoding for Post<Codec> {
18 const METHOD: http::Method = http::Method::POST;
19}
20
21impl<E, T, Encoding, Request> IntoReq<Post<Encoding>, Request, E> for T
22where
23 Request: ClientReq<E>,
24 Encoding: Encodes<T>,
25 E: FromServerFnError,
26{
27 fn into_req(self, path: &str, accepts: &str) -> Result<Request, E> {
28 let data = Encoding::encode(self).map_err(|e| {
29 ServerFnErrorErr::Serialization(e.to_string()).into_app_error()
30 })?;
31 Request::try_new_post_bytes(path, accepts, Encoding::CONTENT_TYPE, data)
32 }
33}
34
35impl<E, T, Request, Encoding> FromReq<Post<Encoding>, Request, E> for T
36where
37 Request: Req<E> + Send + 'static,
38 Encoding: Decodes<T>,
39 E: FromServerFnError,
40{
41 async fn from_req(req: Request) -> Result<Self, E> {
42 let data = req.try_into_bytes().await?;
43 let s = Encoding::decode(data).map_err(|e| {
44 ServerFnErrorErr::Deserialization(e.to_string()).into_app_error()
45 })?;
46 Ok(s)
47 }
48}
49
50impl<E, Response, Encoding, T> IntoRes<Post<Encoding>, Response, E> for T
51where
52 Response: TryRes<E>,
53 Encoding: Encodes<T>,
54 E: FromServerFnError + Send,
55 T: Send,
56{
57 async fn into_res(self) -> Result<Response, E> {
58 let data = Encoding::encode(self).map_err(|e| {
59 ServerFnErrorErr::Serialization(e.to_string()).into_app_error()
60 })?;
61 Response::try_from_bytes(Encoding::CONTENT_TYPE, data)
62 }
63}
64
65impl<E, Encoding, Response, T> FromRes<Post<Encoding>, Response, E> for T
66where
67 Response: ClientRes<E> + Send,
68 Encoding: Decodes<T>,
69 E: FromServerFnError,
70{
71 async fn from_res(res: Response) -> Result<Self, E> {
72 let data = res.try_into_bytes().await?;
73 let s = Encoding::decode(data).map_err(|e| {
74 ServerFnErrorErr::Deserialization(e.to_string()).into_app_error()
75 })?;
76 Ok(s)
77 }
78}