Skip to main content

sark_core/decode/
call.rs

1use std::mem;
2
3use sark_http::request::body::Ref;
4
5use crate::{body, duplex, manifold, request, request::frame::proof, route};
6
7/// A route call whose body has already passed its request projection.
8#[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);