1use std::mem;
2
3use sark_http::request::body::Ref;
4
5use crate::{body, duplex, manifold, request, request::frame::proof, route};
6
7#[repr(C)]
9pub struct Call<H, B> {
10 request: H,
11 body: B,
12}
13
14impl<H, B> Call<H, B> {
15 #[doc(hidden)]
16 pub const fn new(request: H, body: B) -> Self {
17 Self { request, body }
18 }
19
20 #[doc(hidden)]
21 pub fn into_parts(self) -> (H, B) {
22 (self.request, self.body)
23 }
24}
25
26impl<'req, 'd: 'req, R: route::Project>
27 Call<
28 request::raw::Parsed<request::Head<&'req [u8], R::Frame>, R>,
29 body::Scoped<'req, 'd, R::Body>,
30 >
31{
32 pub fn try_invoke<'state, T, S>(
33 self,
34 state: &'state S,
35 ) -> Result<T::Response<'req, 'd>, <R as route::Project>::Error<'req>>
36 where
37 T: route::Spec<Request = R> + manifold::Route<S>,
38 'req: 'state,
39 {
40 let (params, request, headers, body) = self.try_parse()?;
41 Ok(T::invoke((params, &request, headers, body, state)))
42 }
43
44 #[doc(hidden)]
45 pub fn try_open<'state, T, S>(
46 self,
47 state: &'state S,
48 ) -> Result<T::Session, <R as route::Project>::Error<'req>>
49 where
50 T: route::Spec<Request = R> + duplex::Route<'state, S>,
51 T::Session: duplex::Session<'d>,
52 'd: 'state,
53 {
54 let (params, request, headers, body) = self.try_parse()?;
55 Ok(T::open(params, &request, headers, body, state))
56 }
57
58 fn try_parse(self) -> Result<Parts<'req, 'd, R>, <R as route::Project>::Error<'req>> {
59 let body = self.body.into_inner();
60 let view = body.into();
61 let params = R::from_params(&self.request)?;
62 let headers = R::from_headers(&self.request)?;
63 let body = R::parse_body(body)?;
64 let request = request::View::from_head(self.request.into_owner(), view);
65 Ok((params, request, headers, body))
66 }
67}
68
69const _: () = assert!(
70 mem::size_of::<Call<request::Head<&'static [u8]>, Ref<'static, 'static>>>()
71 == mem::size_of::<request::View<'static, 'static>>()
72);
73const _: () = assert!(
74 mem::size_of::<
75 Call<
76 request::Head<&'static [u8], proof::Peer>,
77 body::Scoped<'static, 'static, body::Contiguous>,
78 >,
79 >() < mem::size_of::<request::View<'static, 'static, proof::Peer>>()
80);
81
82type Parts<'req, 'd, R> = (
83 <R as route::Project>::Params<'req>,
84 request::View<'req, 'd, <R as route::Schema>::Frame>,
85 <R as route::Project>::Headers<'req>,
86 <R as route::Project>::ParsedBody<'req, 'd>,
87);