sark_core/http/response/
mono.rs1use http::{HeaderName, HeaderValue, StatusCode};
2use o3::buffer::Shared;
3
4use super::wire_emit::{CRLF, ContentLength, HeadWrite, HeaderSection, WireWriter};
5use super::{DEFAULT_HEADER_CAPACITY, HeaderList, HotBodyInner, HotHeadInner};
6
7struct MonoHeaders<'a, 'req, const N: usize> {
8 head: &'a HotHeadInner<'req, N>,
9 dynamic: Option<&'a HeaderList>,
10}
11
12impl<const N: usize> HeaderSection for MonoHeaders<'_, '_, N> {
13 fn header_len(&self) -> usize {
14 let head = match self.head {
15 HotHeadInner::Wire(bytes) => bytes.len(),
16 HotHeadInner::Direct(head) => head.wire_len(),
17 };
18 head + self.dynamic.map_or(0, HeaderList::wire_len)
19 }
20
21 fn write_headers(&self, out: &mut WireWriter<'_>) {
22 match self.head {
23 HotHeadInner::Wire(bytes) => out.put(bytes),
24 HotHeadInner::Direct(head) => head.write_headers(out),
25 }
26 if let Some(h) = self.dynamic {
27 for (name, value) in h.iter() {
28 out.put(name.as_str().as_bytes());
29 out.put(b": ");
30 out.put(value.as_bytes());
31 out.put(CRLF);
32 }
33 }
34 }
35}
36
37#[derive(Clone, Debug)]
38pub struct MonoResponseInner<'req, const N: usize = DEFAULT_HEADER_CAPACITY> {
39 pub(super) status: StatusCode,
40 pub(super) headers: Option<Box<HeaderList>>,
41 pub(super) head: HotHeadInner<'req, N>,
42 pub(super) body: HotBodyInner<'req>,
43}
44
45impl<'req, const N: usize> MonoResponseInner<'req, N> {
46 pub fn status(&self) -> StatusCode {
47 self.status
48 }
49
50 pub fn headers(&self) -> &HeaderList {
51 match &self.headers {
52 Some(h) => h.as_ref(),
53 None => HeaderList::empty_static(),
54 }
55 }
56
57 pub fn headers_mut(&mut self) -> &mut HeaderList {
58 self.headers
59 .get_or_insert_with(|| Box::new(HeaderList::new()))
60 .as_mut()
61 }
62
63 pub fn insert_header(&mut self, name: HeaderName, value: HeaderValue) -> &mut Self {
64 let _ = self.headers_mut().insert(name, value);
65 self
66 }
67
68 pub fn wire_headers(&self) -> Shared {
69 let section = MonoHeaders {
70 head: &self.head,
71 dynamic: self.headers.as_deref(),
72 };
73 let mut bytes = vec![0; section.header_len()];
74 section.write_headers(&mut WireWriter::new(&mut bytes));
75 Shared::from(bytes)
76 }
77
78 pub fn write_into_slice(&self, out: &mut [u8], date: &[u8; 29]) -> Option<usize> {
79 let (mut off, _) = self.write_head_into(out, date)?;
80 let body_len = self.body.body_len();
81 if out.len() - off < body_len {
82 return None;
83 }
84 off += self.body.write_to(&mut out[off..off + body_len]);
85 Some(off)
86 }
87
88 pub fn write_head_split(self, out: &mut [u8], date: &[u8; 29]) -> Option<(usize, Shared)> {
89 let (off, _) = self.write_head_into(out, date)?;
90 Some((off, self.body.into_shared()))
91 }
92
93 fn with_head<R>(
94 &self,
95 f: impl FnOnce(&HeadWrite<'_, MonoHeaders<'_, 'req, N>, ContentLength>) -> R,
96 ) -> R {
97 let section = MonoHeaders {
98 head: &self.head,
99 dynamic: self.headers.as_deref(),
100 };
101 let head = HeadWrite {
102 status_str: self.status.as_str().as_bytes(),
103 reason: self
104 .status
105 .canonical_reason()
106 .map(str::as_bytes)
107 .unwrap_or(b""),
108 headers: §ion,
109 framing: ContentLength(self.body.body_len()),
110 };
111 f(&head)
112 }
113
114 fn write_head_into(&self, out: &mut [u8], date: &[u8; 29]) -> Option<(usize, usize)> {
115 self.with_head(|head| {
116 if out.len() < head.wire_len() {
117 return None;
118 }
119 let written = head.write(out, date);
120 Some((written.len, written.date_offset))
121 })
122 }
123}