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