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 let added = header_wire_len(name.as_str(), value.as_bytes());
103 if let Some(index) = self.entries.iter().position(|(n, _)| *n == name) {
104 let removed_old = header_wire_len(
105 self.entries[index].0.as_str(),
106 self.entries[index].1.as_bytes(),
107 );
108 let old = std::mem::replace(&mut self.entries[index].1, value);
109 self.wire_len = self.wire_len + added - removed_old;
110 self.dedup_by_name(&name, index + 1);
111 return Some(old);
112 }
113 self.entries.push((name, value));
114 self.wire_len += added;
115 None
116 }
117
118 pub fn extend_trailers(
119 &mut self,
120 trailers: impl IntoIterator<Item = (HeaderName, HeaderValue)>,
121 ) {
122 for (name, value) in trailers {
123 if is_forbidden_trailer(&name) {
124 continue;
125 }
126 let _ = self.insert(name, value);
127 }
128 }
129
130 pub fn remove<K>(&mut self, name: K) -> Option<HeaderValue>
131 where
132 K: HeaderNameRef,
133 {
134 let index = self
135 .entries
136 .iter()
137 .position(|(n, _)| n.as_str().eq_ignore_ascii_case(name.as_header_name()))?;
138 let (removed_name, removed_value) = self.entries.remove(index);
139 self.wire_len -= header_wire_len(removed_name.as_str(), removed_value.as_bytes());
140 self.dedup_by_name(&removed_name, 0);
141 Some(removed_value)
142 }
143
144 fn dedup_by_name(&mut self, name: &HeaderName, start: usize) {
145 let mut scan = start;
146 while scan < self.entries.len() {
147 if self.entries[scan].0 == *name {
148 self.wire_len -= header_wire_len(
149 self.entries[scan].0.as_str(),
150 self.entries[scan].1.as_bytes(),
151 );
152 self.entries.remove(scan);
153 } else {
154 scan += 1;
155 }
156 }
157 }
158}
159
160fn is_forbidden_trailer(name: &HeaderName) -> bool {
161 matches!(
162 name.as_str(),
163 "content-length"
164 | "transfer-encoding"
165 | "host"
166 | "trailer"
167 | "connection"
168 | "keep-alive"
169 | "te"
170 | "upgrade"
171 | "proxy-authenticate"
172 | "proxy-authorization"
173 )
174}
175
176fn header_wire_len(name: &str, value: &[u8]) -> usize {
177 name.len() + 2 + value.len() + 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}