Skip to main content

sark_core/http/response/
header.rs

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