server_fn/codec/
post.rs

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
10/// A codec that encodes the data in the post body
11pub 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}