sark_core/http/response/
encoded.rs1use http::StatusCode;
2use o3::buffer::Shared;
3
4use super::wire_emit::{ContentLength, HeadWrite, PLACEHOLDER_DATE, ProvenWireWriter};
5use super::{
6 DEFAULT_HEADER_CAPACITY, HeadInner, HeaderTemplate, Headers, StaticHeaderBytes,
7 StaticHeaderFields, StaticHeaders,
8};
9
10pub trait EncodedBody: Sized {
11 type Error;
12
13 fn encoded_len(&self) -> usize;
14
15 fn encode_into(&self, out: &mut [u8]) -> Result<(), Self::Error>;
16
17 fn into_shared(self, encoded_len: usize) -> Result<Shared, Self::Error> {
18 let mut out = vec![0; encoded_len];
19 self.encode_into(&mut out)?;
20 Ok(Shared::from(out))
21 }
22}
23
24pub struct EncodedResponse<'req, B, const N: usize = DEFAULT_HEADER_CAPACITY, S = StaticHeaderBytes>
25{
26 pub(super) status: StatusCode,
27 pub(super) head: HeadInner<'req, N, S>,
28 pub(super) body: B,
29 pub(super) body_len: usize,
30}
31
32impl<'req, B, const N: usize> EncodedResponse<'req, B, N>
33where
34 B: EncodedBody,
35{
36 pub fn direct(
37 status: StatusCode,
38 static_headers: &'static [u8],
39 headers: Headers<'req, N>,
40 body: B,
41 ) -> Self {
42 let body_len = body.encoded_len();
43 Self {
44 status,
45 head: HeadInner::new(static_headers, headers),
46 body,
47 body_len,
48 }
49 }
50}
51
52impl<'req, B, const N: usize> EncodedResponse<'req, B, N, StaticHeaderFields>
53where
54 B: EncodedBody,
55{
56 #[doc(hidden)]
57 pub fn structured(
58 status: StatusCode,
59 static_headers: &'static HeaderTemplate,
60 headers: Headers<'req, N>,
61 body: B,
62 ) -> Self {
63 let body_len = body.encoded_len();
64 Self {
65 status,
66 head: HeadInner::structured(static_headers, headers),
67 body,
68 body_len,
69 }
70 }
71}
72
73impl<'req, B, const N: usize, S> EncodedResponse<'req, B, N, S>
74where
75 B: EncodedBody,
76 S: StaticHeaders,
77{
78 pub fn status(&self) -> StatusCode {
79 self.status
80 }
81
82 pub fn wire_headers(&self) -> Shared {
83 self.head.wire_headers()
84 }
85
86 pub(crate) fn encoded_body(&self) -> Option<Shared> {
87 let mut body = vec![0; self.body_len];
88 self.body.encode_into(&mut body).ok()?;
89 Some(Shared::from(body))
90 }
91
92 fn head_write(&self) -> HeadWrite<'_, HeadInner<'req, N, S>, ContentLength> {
93 HeadWrite {
94 status: self.status,
95 headers: &self.head,
96 framing: ContentLength(self.body_len),
97 }
98 }
99
100 pub fn preserialize(&self) -> Option<(Vec<u8>, usize)> {
101 let head = self.head_write();
102 let head_len = head.wire_len();
103 let body_len = self.body_len;
104 let total = head_len.checked_add(body_len)?;
105 let mut out = vec![0u8; total];
106 let mut writer = ProvenWireWriter::exact(&mut out);
107 let date_offset = head.emit(&mut writer, PLACEHOLDER_DATE);
108 self.body.encode_into(writer.take_exact(body_len)).ok()?;
109 writer.finish(total);
110 Some((out, date_offset))
111 }
112
113 pub fn write_into_slice(&self, out: &mut [u8], date: &[u8; 29]) -> Option<usize> {
114 let head = self.head_write();
115 let head_len = head.wire_len();
116 let body_len = self.body_len;
117 let total = head_len.checked_add(body_len)?;
118 let mut out = ProvenWireWriter::new(out, total)?;
119 head.emit(&mut out, date);
120 self.body.encode_into(out.take_exact(body_len)).ok()?;
121 Some(out.finish(total))
122 }
123
124 pub fn write_head_split(self, out: &mut [u8], date: &[u8; 29]) -> Option<(usize, Shared)> {
125 let head = self.head_write();
126 let head_len = head.wire_len();
127 let mut out = ProvenWireWriter::new(out, head_len)?;
128 head.emit(&mut out, date);
129 let written = out.finish(head_len);
130 let body = self.body.into_shared(self.body_len).ok()?;
131 Some((written, body))
132 }
133}