Skip to main content

sark_core/http/response/
encoded.rs

1use http::StatusCode;
2use o3::buffer::{Owned, Shared};
3
4use super::wire_emit::{ContentLength, HeadWrite, PLACEHOLDER_DATE};
5use super::{DEFAULT_HEADER_CAPACITY, HeadInner, Headers};
6
7pub trait EncodedBody: Sized {
8    fn encoded_len(&self) -> usize;
9
10    fn encode_into(&self, out: &mut [u8]);
11
12    fn into_shared(self, encoded_len: usize) -> Shared;
13}
14
15pub struct EncodedResponse<'req, B, const N: usize = DEFAULT_HEADER_CAPACITY> {
16    status: StatusCode,
17    head: HeadInner<'req, N>,
18    body: B,
19    body_len: usize,
20}
21
22impl<'req, B, const N: usize> EncodedResponse<'req, B, N>
23where
24    B: EncodedBody,
25{
26    pub fn direct(
27        status: StatusCode,
28        static_headers: &'static [u8],
29        headers: Headers<'req, N>,
30        body: B,
31    ) -> Self {
32        let body_len = body.encoded_len();
33        Self {
34            status,
35            head: HeadInner::new(static_headers, headers),
36            body,
37            body_len,
38        }
39    }
40
41    pub fn status(&self) -> StatusCode {
42        self.status
43    }
44
45    pub fn wire_headers(&self) -> Shared {
46        let mut out = Owned::with_capacity(self.head.wire_len());
47        self.head.write_into_owned(&mut out);
48        out.freeze()
49    }
50
51    pub(crate) fn encoded_body(&self) -> Shared {
52        let mut body = vec![0; self.body_len];
53        self.body.encode_into(&mut body);
54        Shared::from(body)
55    }
56
57    fn head_write(&self) -> HeadWrite<'_, HeadInner<'req, N>, ContentLength> {
58        HeadWrite {
59            status_str: self.status.as_str().as_bytes(),
60            reason: self
61                .status
62                .canonical_reason()
63                .map(str::as_bytes)
64                .unwrap_or(b""),
65            headers: &self.head,
66            framing: ContentLength(self.body_len),
67        }
68    }
69
70    pub fn preserialize(&self) -> (Vec<u8>, usize) {
71        let head = self.head_write();
72        let head_len = head.wire_len();
73        let body_len = self.body_len;
74        let mut out = vec![0u8; head_len + body_len];
75        let written = head.write(&mut out, PLACEHOLDER_DATE);
76        self.body
77            .encode_into(&mut out[written.len..written.len + body_len]);
78        (out, written.date_offset)
79    }
80
81    pub fn write_into_slice(&self, out: &mut [u8], date: &[u8; 29]) -> Option<usize> {
82        let head = self.head_write();
83        let head_len = head.wire_len();
84        let body_len = self.body_len;
85        let total = head_len.checked_add(body_len)?;
86        if out.len() < total {
87            return None;
88        }
89        let written = head.write(out, date);
90        self.body.encode_into(&mut out[written.len..total]);
91        Some(total)
92    }
93
94    pub fn write_head_split(self, out: &mut [u8], date: &[u8; 29]) -> Option<(usize, Shared)> {
95        let head = self.head_write();
96        if out.len() < head.wire_len() {
97            return None;
98        }
99        let written = head.write(out, date);
100        Some((written.len, self.body.into_shared(self.body_len)))
101    }
102}