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, HeadersInner};
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 EncodedResponseInner<'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
22pub type EncodedResponse<B> = EncodedResponseInner<'static, B>;
23
24impl<'req, B, const N: usize> EncodedResponseInner<'req, B, N>
25where
26    B: EncodedBody,
27{
28    pub fn direct(
29        status: StatusCode,
30        static_headers: &'static [u8],
31        headers: HeadersInner<'req, N>,
32        body: B,
33    ) -> Self {
34        let body_len = body.encoded_len();
35        Self {
36            status,
37            head: HeadInner::new(static_headers, headers),
38            body,
39            body_len,
40        }
41    }
42
43    pub fn status(&self) -> StatusCode {
44        self.status
45    }
46
47    pub fn wire_headers(&self) -> Shared {
48        let mut out = Owned::with_capacity(self.head.wire_len());
49        self.head.write_into_owned(&mut out);
50        out.freeze()
51    }
52
53    fn head_write(&self) -> HeadWrite<'_, HeadInner<'req, N>, ContentLength> {
54        HeadWrite {
55            status_str: self.status.as_str().as_bytes(),
56            reason: self
57                .status
58                .canonical_reason()
59                .map(str::as_bytes)
60                .unwrap_or(b""),
61            headers: &self.head,
62            framing: ContentLength(self.body_len),
63        }
64    }
65
66    pub fn preserialize(&self) -> (Vec<u8>, usize) {
67        let head = self.head_write();
68        let head_len = head.wire_len();
69        let body_len = self.body_len;
70        let mut out = vec![0u8; head_len + body_len];
71        let mut offset = 0usize;
72        let date_offset = head.write(&mut out, &mut offset, PLACEHOLDER_DATE);
73        self.body.encode_into(&mut out[offset..offset + body_len]);
74        (out, date_offset)
75    }
76
77    pub fn write_into_slice(&self, out: &mut [u8], date: &[u8; 29]) -> Option<usize> {
78        let head = self.head_write();
79        let head_len = head.wire_len();
80        let body_len = self.body_len;
81        let total = head_len.checked_add(body_len)?;
82        if out.len() < total {
83            return None;
84        }
85        let mut offset = 0usize;
86        head.write(out, &mut offset, date);
87        self.body.encode_into(&mut out[offset..total]);
88        Some(total)
89    }
90
91    pub fn write_head_split(self, out: &mut [u8], date: &[u8; 29]) -> Option<(usize, Shared)> {
92        let head = self.head_write();
93        if out.len() < head.wire_len() {
94            return None;
95        }
96        let mut offset = 0usize;
97        head.write(out, &mut offset, date);
98        Some((offset, self.body.into_shared(self.body_len)))
99    }
100}