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