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
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<N>(&mut self, name: N, value: HeaderValue) -> Option<HeaderValue>
95    where
96        N: IntoHeaderName,
97    {
98        let name = name.into_header_name();
99        let added = HeaderEntryWire::len(name.as_str(), value.as_bytes());
100        if let Some(index) = self.entries.iter().position(|(n, _)| *n == name) {
101            let removed_old = HeaderEntryWire::len(
102                self.entries[index].0.as_str(),
103                self.entries[index].1.as_bytes(),
104            );
105            let old = std::mem::replace(&mut self.entries[index].1, value);
106            self.wire_len = self.wire_len + added - removed_old;
107            self.dedup_by_name(&name, index + 1);
108            return Some(old);
109        }
110        self.entries.push((name, value));
111        self.wire_len += added;
112        None
113    }
114
115    pub fn remove<K>(&mut self, name: K) -> Option<HeaderValue>
116    where
117        K: HeaderNameRef,
118    {
119        let index = self
120            .entries
121            .iter()
122            .position(|(n, _)| n.as_str().eq_ignore_ascii_case(name.as_header_name()))?;
123        let (removed_name, removed_value) = self.entries.remove(index);
124        self.wire_len -= HeaderEntryWire::len(removed_name.as_str(), removed_value.as_bytes());
125        self.dedup_by_name(&removed_name, 0);
126        Some(removed_value)
127    }
128
129    fn dedup_by_name(&mut self, name: &HeaderName, start: usize) {
130        let mut scan = start;
131        while scan < self.entries.len() {
132            if self.entries[scan].0 == *name {
133                self.wire_len -= HeaderEntryWire::len(
134                    self.entries[scan].0.as_str(),
135                    self.entries[scan].1.as_bytes(),
136                );
137                self.entries.remove(scan);
138            } else {
139                scan += 1;
140            }
141        }
142    }
143}
144
145struct HeaderEntryWire;
146
147impl HeaderEntryWire {
148    fn len(name: &str, value: &[u8]) -> usize {
149        name.len() + 2 + value.len() + 2
150    }
151}
152
153impl From<Vec<(HeaderName, HeaderValue)>> for HeaderList {
154    fn from(value: Vec<(HeaderName, HeaderValue)>) -> Self {
155        let mut headers = Self::with_capacity(value.len());
156        for (name, value) in value {
157            let _ = headers.insert(name, value);
158        }
159        headers
160    }
161}
162
163impl<'a> IntoIterator for &'a HeaderList {
164    type Item = (&'a HeaderName, &'a HeaderValue);
165    type IntoIter = HeaderIter<'a>;
166
167    fn into_iter(self) -> Self::IntoIter {
168        self.iter()
169    }
170}