sark_core/http/response/direct/
headers.rs1use o3::buffer::{Borrowed, ByteSink, Bytes, Retained, Shared};
2
3use super::value::{HeaderItem, HeaderValueInner, InlineHeaderValue};
4use crate::http::Field;
5
6pub const DEFAULT_HEADER_CAPACITY: usize = 4;
7pub struct Headers<'req, const N: usize = DEFAULT_HEADER_CAPACITY> {
8 entries: [HeaderItem<'req>; N],
9 len: usize,
10 wire_len: usize,
11}
12
13impl<'req, const N: usize> Clone for Headers<'req, N> {
14 fn clone(&self) -> Self {
15 let len = self.len;
16 let entries = std::array::from_fn(|idx| {
17 if idx < len {
18 self.entries[idx].clone()
19 } else {
20 HeaderItem::placeholder()
21 }
22 });
23 Self {
24 entries,
25 len: self.len,
26 wire_len: self.wire_len,
27 }
28 }
29}
30
31impl<'req, const N: usize> std::fmt::Debug for Headers<'req, N> {
32 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
33 f.debug_struct("Headers")
34 .field("len", &self.len)
35 .field("wire_len", &self.wire_len)
36 .finish()
37 }
38}
39
40impl<'req, const N: usize> Default for Headers<'req, N> {
41 fn default() -> Self {
42 Self::new()
43 }
44}
45
46impl<'req, const N: usize> Headers<'req, N> {
47 pub fn new() -> Self {
48 Self {
49 entries: std::array::from_fn(|_| HeaderItem::placeholder()),
50 len: 0,
51 wire_len: 0,
52 }
53 }
54
55 pub fn from_items(items: [HeaderItem<'req>; N]) -> Self {
56 let wire_len = items.iter().map(HeaderItem::wire_len).sum();
57 Self {
58 entries: items,
59 len: N,
60 wire_len,
61 }
62 }
63
64 pub fn is_empty(&self) -> bool {
65 self.len == 0
66 }
67
68 pub fn len(&self) -> usize {
69 self.len
70 }
71
72 pub fn wire_len(&self) -> usize {
73 self.wire_len
74 }
75
76 pub fn has_content_encoding(&self) -> bool {
77 self.entries[..self.len]
78 .iter()
79 .any(|e| e.name.as_str().eq_ignore_ascii_case("content-encoding"))
80 }
81
82 pub(crate) fn fields(&self) -> impl ExactSizeIterator<Item = Field<'_>> + '_ {
83 self.entries[..self.len]
84 .iter()
85 .map(|item| Field::new(item.name_bytes(), item.value_bytes()))
86 }
87
88 pub fn push_static(
89 &mut self,
90 name: HeaderNameToken,
91 value: HeaderStaticValueToken,
92 ) -> &mut Self {
93 self.push_value(name, HeaderValueInner::Static(value.as_bytes()))
94 }
95
96 pub fn push_shared(&mut self, name: HeaderNameToken, value: Shared) -> &mut Self {
97 self.push_value(name, HeaderValueInner::Shared(value))
98 }
99
100 pub fn push_inline(&mut self, name: HeaderNameToken, value: InlineHeaderValue) -> &mut Self {
101 self.push_value(name, HeaderValueInner::Inline(value))
102 }
103
104 pub fn push_borrowed(
105 &mut self,
106 name: HeaderNameToken,
107 value: Bytes<Borrowed<'req>>,
108 ) -> &mut Self {
109 self.push_value(name, HeaderValueInner::Borrowed(value))
110 }
111
112 pub fn push_retained(&mut self, name: HeaderNameToken, value: Bytes<Retained>) -> &mut Self {
113 self.push_value(name, HeaderValueInner::Retained(value))
114 }
115
116 pub(super) fn write_into<W: ByteSink>(&self, out: &mut W) -> Result<(), W::Error> {
117 for idx in 0..self.len {
118 let header = &self.entries[idx];
119 out.write_slices([header.name_bytes(), b": ", header.value_bytes(), b"\r\n"])?;
120 }
121 Ok(())
122 }
123
124 pub(super) fn write_wire(&self, out: &mut super::super::wire_emit::WireWriter<'_>) {
125 for idx in 0..self.len {
126 let header = &self.entries[idx];
127 out.put(header.name_bytes());
128 out.put(b": ");
129 out.put(header.value_bytes());
130 out.put(b"\r\n");
131 }
132 }
133
134 pub fn write(&self, out: &mut [u8]) -> usize {
135 let mut off = 0usize;
136 for idx in 0..self.len {
137 let header = &self.entries[idx];
138 let name = header.name_bytes();
139 let value = header.value_bytes();
140 let name_end = off + name.len();
141 out[off..name_end].copy_from_slice(name);
142 off = name_end;
143 out[off..off + 2].copy_from_slice(b": ");
144 off += 2;
145 let value_end = off + value.len();
146 out[off..value_end].copy_from_slice(value);
147 off = value_end;
148 out[off..off + 2].copy_from_slice(b"\r\n");
149 off += 2;
150 }
151 off
152 }
153
154 fn push_value(&mut self, name: HeaderNameToken, value: HeaderValueInner<'req>) -> &mut Self {
155 assert!(self.len < N, "direct header overflow: max {}", N);
156 self.wire_len += name.as_str().len() + 2 + value.len() + 2;
157 self.entries[self.len] = HeaderItem { name, value };
158 self.len += 1;
159 self
160 }
161}
162
163#[derive(Clone, Copy, Debug, PartialEq, Eq)]
164pub struct HeaderNameToken(&'static str);
165
166impl HeaderNameToken {
167 pub const fn new(name: &'static str) -> Self {
168 Self::validate(name);
169 Self(name)
170 }
171
172 const fn validate(name: &str) {
173 assert!(
174 sark_protocol::validate_response_header_name(name).is_ok(),
175 "direct response header name must be valid and unmanaged"
176 );
177 }
178
179 pub(crate) const fn empty_placeholder() -> Self {
180 Self("")
181 }
182
183 pub const fn as_str(self) -> &'static str {
184 self.0
185 }
186
187 pub const fn as_bytes(self) -> &'static [u8] {
188 self.0.as_bytes()
189 }
190}
191
192#[derive(Clone, Copy, Debug, PartialEq, Eq)]
193pub struct HeaderStaticValueToken(&'static str);
194
195impl HeaderStaticValueToken {
196 pub const fn new(value: &'static str) -> Self {
197 Self::validate(value);
198 Self(value)
199 }
200
201 pub(super) const fn validate(value: &str) {
202 Self::validate_bytes(value.as_bytes());
203 }
204
205 pub(super) const fn validate_bytes(value: &[u8]) {
206 assert!(
207 sark_protocol::validate_header_value(value).is_ok(),
208 "direct header value must not contain CR/LF"
209 );
210 }
211
212 pub const fn as_str(self) -> &'static str {
213 self.0
214 }
215
216 pub const fn as_bytes(self) -> &'static [u8] {
217 self.0.as_bytes()
218 }
219}