sark_core/http/response/
header.rs1use std::slice;
2
3use http::{HeaderName, HeaderValue};
4
5use super::HeaderNameRef;
6use crate::http::Field;
7
8#[derive(Clone, Default, PartialEq, Eq)]
9pub struct HeaderList {
10 entries: Vec<(HeaderName, HeaderValue)>,
11 wire_len: usize,
12}
13
14static EMPTY_HEADER_LIST: HeaderList = HeaderList {
15 entries: Vec::new(),
16 wire_len: 0,
17};
18
19impl std::fmt::Debug for HeaderList {
20 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
21 let mut list = f.debug_list();
22 for (name, value) in self {
23 list.entry(&(name, value));
24 }
25 list.finish()
26 }
27}
28
29pub struct HeaderIter<'a> {
30 inner: slice::Iter<'a, (HeaderName, HeaderValue)>,
31}
32
33impl<'a> Iterator for HeaderIter<'a> {
34 type Item = (&'a HeaderName, &'a HeaderValue);
35
36 fn next(&mut self) -> Option<Self::Item> {
37 self.inner.next().map(|(name, value)| (name, value))
38 }
39}
40
41impl HeaderList {
42 pub fn new() -> Self {
43 Self {
44 entries: Vec::new(),
45 wire_len: 0,
46 }
47 }
48
49 pub(super) fn empty_static() -> &'static Self {
50 &EMPTY_HEADER_LIST
51 }
52
53 pub fn with_capacity(capacity: usize) -> Self {
54 Self {
55 entries: Vec::with_capacity(capacity),
56 wire_len: 0,
57 }
58 }
59
60 pub fn is_empty(&self) -> bool {
61 self.entries.is_empty()
62 }
63
64 pub fn len(&self) -> usize {
65 self.entries.len()
66 }
67
68 pub fn iter(&self) -> HeaderIter<'_> {
69 HeaderIter {
70 inner: self.entries.iter(),
71 }
72 }
73
74 pub(crate) fn fields(&self) -> impl ExactSizeIterator<Item = Field<'_>> + '_ {
75 self.entries
76 .iter()
77 .map(|(name, value)| Field::new(name.as_str().as_bytes(), value.as_bytes()))
78 }
79
80 pub fn wire_len(&self) -> usize {
81 self.wire_len
82 }
83
84 pub fn get<K>(&self, name: K) -> Option<&HeaderValue>
85 where
86 K: HeaderNameRef,
87 {
88 self.entries
89 .iter()
90 .find(|(n, _)| n.as_str().eq_ignore_ascii_case(name.as_header_name()))
91 .map(|(_, v)| v)
92 }
93
94 pub fn contains_key<K>(&self, name: K) -> bool
95 where
96 K: HeaderNameRef,
97 {
98 self.get(name).is_some()
99 }
100
101 pub fn insert(&mut self, name: HeaderName, value: HeaderValue) -> Option<HeaderValue> {
102 if let Some(index) = self.entries.iter().position(|(n, _)| *n == name) {
103 let old = std::mem::replace(&mut self.entries[index].1, value);
104 self.dedup_by_name(&name, index + 1);
105 self.refresh_wire_len();
106 return Some(old);
107 }
108 self.entries.push((name, value));
109 self.refresh_wire_len();
110 None
111 }
112
113 pub fn extend_trailers(
114 &mut self,
115 trailers: impl IntoIterator<Item = (HeaderName, HeaderValue)>,
116 ) {
117 for (name, value) in trailers {
118 if is_forbidden_trailer(&name) {
119 continue;
120 }
121 let _ = self.insert(name, value);
122 }
123 }
124
125 pub fn remove<K>(&mut self, name: K) -> Option<HeaderValue>
126 where
127 K: HeaderNameRef,
128 {
129 let index = self
130 .entries
131 .iter()
132 .position(|(n, _)| n.as_str().eq_ignore_ascii_case(name.as_header_name()))?;
133 let (removed_name, removed_value) = self.entries.remove(index);
134 self.dedup_by_name(&removed_name, 0);
135 self.refresh_wire_len();
136 Some(removed_value)
137 }
138
139 fn dedup_by_name(&mut self, name: &HeaderName, start: usize) {
140 let mut scan = start;
141 while scan < self.entries.len() {
142 if self.entries[scan].0 == *name {
143 self.entries.remove(scan);
144 } else {
145 scan += 1;
146 }
147 }
148 }
149
150 fn refresh_wire_len(&mut self) {
151 self.wire_len = self.entries.iter().fold(0usize, |total, (name, value)| {
152 total.saturating_add(header_wire_len(name.as_str(), value.as_bytes()))
153 });
154 }
155}
156
157fn is_forbidden_trailer(name: &HeaderName) -> bool {
158 matches!(
159 name.as_str(),
160 "content-length"
161 | "transfer-encoding"
162 | "host"
163 | "trailer"
164 | "connection"
165 | "keep-alive"
166 | "te"
167 | "upgrade"
168 | "proxy-authenticate"
169 | "proxy-authorization"
170 )
171}
172
173fn header_wire_len(name: &str, value: &[u8]) -> usize {
174 name.len()
175 .saturating_add(2)
176 .saturating_add(value.len())
177 .saturating_add(2)
178}
179
180impl From<Vec<(HeaderName, HeaderValue)>> for HeaderList {
181 fn from(value: Vec<(HeaderName, HeaderValue)>) -> Self {
182 let mut headers = Self::with_capacity(value.len());
183 for (name, value) in value {
184 let _ = headers.insert(name, value);
185 }
186 headers
187 }
188}
189
190impl<'a> IntoIterator for &'a HeaderList {
191 type Item = (&'a HeaderName, &'a HeaderValue);
192 type IntoIter = HeaderIter<'a>;
193
194 fn into_iter(self) -> Self::IntoIter {
195 self.iter()
196 }
197}