Skip to main content

sark_core/http/response/
mono.rs

1use http::{HeaderName, HeaderValue, StatusCode};
2use o3::buffer::Shared;
3
4use super::wire_emit::{CRLF, ContentLength, HeadWrite, HeaderSection, ProvenWireWriter};
5use super::{Body, DEFAULT_HEADER_CAPACITY, HeaderList, 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 wire_len(&self) -> usize {
14        let head = match self.head {
15            HotHeadInner::Wire(bytes) => bytes.len(),
16            HotHeadInner::Direct(head) => HeaderSection::wire_len(head),
17        };
18        head.saturating_add(self.dynamic.map_or(0, HeaderList::wire_len))
19    }
20
21    fn write_headers(&self, out: &mut ProvenWireWriter<'_>) {
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: Body<'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 = self.header_section();
70        let len = section.wire_len();
71        let mut bytes = vec![0; len];
72        let mut out = ProvenWireWriter::exact(&mut bytes);
73        section.write_headers(&mut out);
74        out.finish(len);
75        Shared::from(bytes)
76    }
77
78    pub fn write_into_slice(&self, out: &mut [u8], date: &[u8; 29]) -> Option<usize> {
79        let section = self.header_section();
80        let head = HeadWrite {
81            status: self.status,
82            headers: &section,
83            framing: ContentLength(self.body.body_len()),
84        };
85        let total = head.wire_len().checked_add(self.body.body_len())?;
86        let mut out = ProvenWireWriter::new(out, total)?;
87        head.emit(&mut out, date);
88        out.put(self.body.as_bytes());
89        Some(out.finish(total))
90    }
91
92    pub fn write_head_split(self, out: &mut [u8], date: &[u8; 29]) -> Option<(usize, Shared)> {
93        let section = self.header_section();
94        let head = HeadWrite {
95            status: self.status,
96            headers: &section,
97            framing: ContentLength(self.body.body_len()),
98        };
99        let head_len = head.wire_len();
100        let mut out = ProvenWireWriter::new(out, head_len)?;
101        head.emit(&mut out, date);
102        let written = out.finish(head_len);
103        Some((written, self.body.into_shared()))
104    }
105
106    fn header_section(&self) -> MonoHeaders<'_, 'req, N> {
107        MonoHeaders {
108            head: &self.head,
109            dynamic: self.headers.as_deref(),
110        }
111    }
112}