sark_core/http/response/
encoded.rs1use 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}