trillium_api/
try_from_conn.rs1use crate::{ApiConnExt, FromConn};
2use trillium::{async_trait, Conn, Handler};
3#[async_trait]
11pub trait TryFromConn: Send + Sync + Sized + 'static {
12 type Error: Send + Sync + Sized + 'static;
15
16 async fn try_from_conn(conn: &mut Conn) -> Result<Self, Self::Error>;
18}
19
20#[async_trait]
21impl TryFromConn for serde_json::Value {
22 type Error = crate::Error;
23 async fn try_from_conn(conn: &mut Conn) -> Result<Self, Self::Error> {
24 conn.deserialize().await
25 }
26}
27
28#[async_trait]
29impl<T: FromConn> TryFromConn for T {
30 type Error = ();
31
32 async fn try_from_conn(conn: &mut Conn) -> Result<Self, Self::Error> {
33 Self::from_conn(conn).await.ok_or(())
34 }
35}
36
37#[async_trait]
38impl TryFromConn for Vec<u8> {
39 type Error = crate::Error;
40 async fn try_from_conn(conn: &mut Conn) -> Result<Self, Self::Error> {
41 conn.request_body()
42 .await
43 .read_bytes()
44 .await
45 .map_err(Into::into)
46 }
47}
48
49#[async_trait]
50impl TryFromConn for String {
51 type Error = crate::Error;
52 async fn try_from_conn(conn: &mut Conn) -> Result<Self, Self::Error> {
53 conn.request_body_string().await.map_err(Into::into)
54 }
55}
56
57#[cfg(feature = "url")]
58#[async_trait]
59impl TryFromConn for url::Url {
60 type Error = trillium::Status;
61 async fn try_from_conn(conn: &mut Conn) -> Result<Self, Self::Error> {
62 let path = conn.path();
63 let host = conn
64 .request_headers()
65 .get_str(trillium::KnownHeaderName::Host)
66 .ok_or(trillium::Status::BadRequest)?;
67 let proto = if conn.is_secure() { "https" } else { "http" };
68 url::Url::parse(&format!("{proto}://{host}{path}"))
69 .map_err(|_| trillium::Status::BadRequest)
70 }
71}
72
73macro_rules! impl_try_from_conn_tuple {
74 ($($name:ident)+) => (
75 #[async_trait]
76 impl<$($name),*> TryFromConn for ($($name,)*) where $($name: TryFromConn, <$name as TryFromConn>::Error: Handler),* {
77 type Error = Box<dyn Handler>;
78 #[allow(non_snake_case)]
79 async fn try_from_conn(conn: &mut Conn) -> Result<Self, Self::Error> {
80 $(let $name = <$name as TryFromConn>::try_from_conn(conn)
81 .await
82 .map_err(|h| Box::new(h) as Box<dyn Handler>)?;)*
83 Ok(($($name, )*))
84 }
85 }
86 )
87}
88
89impl_try_from_conn_tuple! { A B }
90impl_try_from_conn_tuple! { A B C }
91impl_try_from_conn_tuple! { A B C D }
92impl_try_from_conn_tuple! { A B C D E }
93impl_try_from_conn_tuple! { A B C D E F }
94impl_try_from_conn_tuple! { A B C D E F G }
95impl_try_from_conn_tuple! { A B C D E F G H }
96impl_try_from_conn_tuple! { A B C D E F G H I }
97impl_try_from_conn_tuple! { A B C D E F G H I J }
98impl_try_from_conn_tuple! { A B C D E F G H I J K }
99impl_try_from_conn_tuple! { A B C D E F G H I J K L }