actori_http/header/map.rs
1use std::collections::hash_map::{self, Entry};
2use std::convert::TryFrom;
3
4use either::Either;
5use fxhash::FxHashMap;
6use http::header::{HeaderName, HeaderValue};
7
8/// A set of HTTP headers
9///
10/// `HeaderMap` is an multimap of [`HeaderName`] to values.
11///
12/// [`HeaderName`]: struct.HeaderName.html
13#[derive(Debug, Clone)]
14pub struct HeaderMap {
15 pub(crate) inner: FxHashMap<HeaderName, Value>,
16}
17
18#[derive(Debug, Clone)]
19pub(crate) enum Value {
20 One(HeaderValue),
21 Multi(Vec<HeaderValue>),
22}
23
24impl Value {
25 fn get(&self) -> &HeaderValue {
26 match self {
27 Value::One(ref val) => val,
28 Value::Multi(ref val) => &val[0],
29 }
30 }
31
32 fn get_mut(&mut self) -> &mut HeaderValue {
33 match self {
34 Value::One(ref mut val) => val,
35 Value::Multi(ref mut val) => &mut val[0],
36 }
37 }
38
39 fn append(&mut self, val: HeaderValue) {
40 match self {
41 Value::One(_) => {
42 let data = std::mem::replace(self, Value::Multi(vec![val]));
43 match data {
44 Value::One(val) => self.append(val),
45 Value::Multi(_) => unreachable!(),
46 }
47 }
48 Value::Multi(ref mut vec) => vec.push(val),
49 }
50 }
51}
52
53impl HeaderMap {
54 /// Create an empty `HeaderMap`.
55 ///
56 /// The map will be created without any capacity. This function will not
57 /// allocate.
58 pub fn new() -> Self {
59 HeaderMap {
60 inner: FxHashMap::default(),
61 }
62 }
63
64 /// Create an empty `HeaderMap` with the specified capacity.
65 ///
66 /// The returned map will allocate internal storage in order to hold about
67 /// `capacity` elements without reallocating. However, this is a "best
68 /// effort" as there are usage patterns that could cause additional
69 /// allocations before `capacity` headers are stored in the map.
70 ///
71 /// More capacity than requested may be allocated.
72 pub fn with_capacity(capacity: usize) -> HeaderMap {
73 HeaderMap {
74 inner: FxHashMap::with_capacity_and_hasher(capacity, Default::default()),
75 }
76 }
77
78 /// Returns the number of keys stored in the map.
79 ///
80 /// This number could be be less than or equal to actual headers stored in
81 /// the map.
82 pub fn len(&self) -> usize {
83 self.inner.len()
84 }
85
86 /// Returns true if the map contains no elements.
87 pub fn is_empty(&self) -> bool {
88 self.inner.len() == 0
89 }
90
91 /// Clears the map, removing all key-value pairs. Keeps the allocated memory
92 /// for reuse.
93 pub fn clear(&mut self) {
94 self.inner.clear();
95 }
96
97 /// Returns the number of headers the map can hold without reallocating.
98 ///
99 /// This number is an approximation as certain usage patterns could cause
100 /// additional allocations before the returned capacity is filled.
101 pub fn capacity(&self) -> usize {
102 self.inner.capacity()
103 }
104
105 /// Reserves capacity for at least `additional` more headers to be inserted
106 /// into the `HeaderMap`.
107 ///
108 /// The header map may reserve more space to avoid frequent reallocations.
109 /// Like with `with_capacity`, this will be a "best effort" to avoid
110 /// allocations until `additional` more headers are inserted. Certain usage
111 /// patterns could cause additional allocations before the number is
112 /// reached.
113 pub fn reserve(&mut self, additional: usize) {
114 self.inner.reserve(additional)
115 }
116
117 /// Returns a reference to the value associated with the key.
118 ///
119 /// If there are multiple values associated with the key, then the first one
120 /// is returned. Use `get_all` to get all values associated with a given
121 /// key. Returns `None` if there are no values associated with the key.
122 pub fn get<N: AsName>(&self, name: N) -> Option<&HeaderValue> {
123 self.get2(name).map(|v| v.get())
124 }
125
126 fn get2<N: AsName>(&self, name: N) -> Option<&Value> {
127 match name.as_name() {
128 Either::Left(name) => self.inner.get(name),
129 Either::Right(s) => {
130 if let Ok(name) = HeaderName::try_from(s) {
131 self.inner.get(&name)
132 } else {
133 None
134 }
135 }
136 }
137 }
138
139 /// Returns a view of all values associated with a key.
140 ///
141 /// The returned view does not incur any allocations and allows iterating
142 /// the values associated with the key. See [`GetAll`] for more details.
143 /// Returns `None` if there are no values associated with the key.
144 ///
145 /// [`GetAll`]: struct.GetAll.html
146 pub fn get_all<N: AsName>(&self, name: N) -> GetAll<'_> {
147 GetAll {
148 idx: 0,
149 item: self.get2(name),
150 }
151 }
152
153 /// Returns a mutable reference to the value associated with the key.
154 ///
155 /// If there are multiple values associated with the key, then the first one
156 /// is returned. Use `entry` to get all values associated with a given
157 /// key. Returns `None` if there are no values associated with the key.
158 pub fn get_mut<N: AsName>(&mut self, name: N) -> Option<&mut HeaderValue> {
159 match name.as_name() {
160 Either::Left(name) => self.inner.get_mut(name).map(|v| v.get_mut()),
161 Either::Right(s) => {
162 if let Ok(name) = HeaderName::try_from(s) {
163 self.inner.get_mut(&name).map(|v| v.get_mut())
164 } else {
165 None
166 }
167 }
168 }
169 }
170
171 /// Returns true if the map contains a value for the specified key.
172 pub fn contains_key<N: AsName>(&self, key: N) -> bool {
173 match key.as_name() {
174 Either::Left(name) => self.inner.contains_key(name),
175 Either::Right(s) => {
176 if let Ok(name) = HeaderName::try_from(s) {
177 self.inner.contains_key(&name)
178 } else {
179 false
180 }
181 }
182 }
183 }
184
185 /// An iterator visiting all key-value pairs.
186 ///
187 /// The iteration order is arbitrary, but consistent across platforms for
188 /// the same crate version. Each key will be yielded once per associated
189 /// value. So, if a key has 3 associated values, it will be yielded 3 times.
190 pub fn iter(&self) -> Iter<'_> {
191 Iter::new(self.inner.iter())
192 }
193
194 /// An iterator visiting all keys.
195 ///
196 /// The iteration order is arbitrary, but consistent across platforms for
197 /// the same crate version. Each key will be yielded only once even if it
198 /// has multiple associated values.
199 pub fn keys(&self) -> Keys<'_> {
200 Keys(self.inner.keys())
201 }
202
203 /// Inserts a key-value pair into the map.
204 ///
205 /// If the map did not previously have this key present, then `None` is
206 /// returned.
207 ///
208 /// If the map did have this key present, the new value is associated with
209 /// the key and all previous values are removed. **Note** that only a single
210 /// one of the previous values is returned. If there are multiple values
211 /// that have been previously associated with the key, then the first one is
212 /// returned. See `insert_mult` on `OccupiedEntry` for an API that returns
213 /// all values.
214 ///
215 /// The key is not updated, though; this matters for types that can be `==`
216 /// without being identical.
217 pub fn insert(&mut self, key: HeaderName, val: HeaderValue) {
218 let _ = self.inner.insert(key, Value::One(val));
219 }
220
221 /// Inserts a key-value pair into the map.
222 ///
223 /// If the map did not previously have this key present, then `false` is
224 /// returned.
225 ///
226 /// If the map did have this key present, the new value is pushed to the end
227 /// of the list of values currently associated with the key. The key is not
228 /// updated, though; this matters for types that can be `==` without being
229 /// identical.
230 pub fn append(&mut self, key: HeaderName, value: HeaderValue) {
231 match self.inner.entry(key) {
232 Entry::Occupied(mut entry) => entry.get_mut().append(value),
233 Entry::Vacant(entry) => {
234 entry.insert(Value::One(value));
235 }
236 }
237 }
238
239 /// Removes all headers for a particular header name from the map.
240 pub fn remove<N: AsName>(&mut self, key: N) {
241 match key.as_name() {
242 Either::Left(name) => {
243 let _ = self.inner.remove(name);
244 }
245 Either::Right(s) => {
246 if let Ok(name) = HeaderName::try_from(s) {
247 let _ = self.inner.remove(&name);
248 }
249 }
250 }
251 }
252}
253
254#[doc(hidden)]
255pub trait AsName {
256 fn as_name(&self) -> Either<&HeaderName, &str>;
257}
258
259impl AsName for HeaderName {
260 fn as_name(&self) -> Either<&HeaderName, &str> {
261 Either::Left(self)
262 }
263}
264
265impl<'a> AsName for &'a HeaderName {
266 fn as_name(&self) -> Either<&HeaderName, &str> {
267 Either::Left(self)
268 }
269}
270
271impl<'a> AsName for &'a str {
272 fn as_name(&self) -> Either<&HeaderName, &str> {
273 Either::Right(self)
274 }
275}
276
277impl AsName for String {
278 fn as_name(&self) -> Either<&HeaderName, &str> {
279 Either::Right(self.as_str())
280 }
281}
282
283impl<'a> AsName for &'a String {
284 fn as_name(&self) -> Either<&HeaderName, &str> {
285 Either::Right(self.as_str())
286 }
287}
288
289pub struct GetAll<'a> {
290 idx: usize,
291 item: Option<&'a Value>,
292}
293
294impl<'a> Iterator for GetAll<'a> {
295 type Item = &'a HeaderValue;
296
297 #[inline]
298 fn next(&mut self) -> Option<&'a HeaderValue> {
299 if let Some(ref val) = self.item {
300 match val {
301 Value::One(ref val) => {
302 self.item.take();
303 Some(val)
304 }
305 Value::Multi(ref vec) => {
306 if self.idx < vec.len() {
307 let item = Some(&vec[self.idx]);
308 self.idx += 1;
309 item
310 } else {
311 self.item.take();
312 None
313 }
314 }
315 }
316 } else {
317 None
318 }
319 }
320}
321
322pub struct Keys<'a>(hash_map::Keys<'a, HeaderName, Value>);
323
324impl<'a> Iterator for Keys<'a> {
325 type Item = &'a HeaderName;
326
327 #[inline]
328 fn next(&mut self) -> Option<&'a HeaderName> {
329 self.0.next()
330 }
331}
332
333impl<'a> IntoIterator for &'a HeaderMap {
334 type Item = (&'a HeaderName, &'a HeaderValue);
335 type IntoIter = Iter<'a>;
336
337 fn into_iter(self) -> Self::IntoIter {
338 self.iter()
339 }
340}
341
342pub struct Iter<'a> {
343 idx: usize,
344 current: Option<(&'a HeaderName, &'a Vec<HeaderValue>)>,
345 iter: hash_map::Iter<'a, HeaderName, Value>,
346}
347
348impl<'a> Iter<'a> {
349 fn new(iter: hash_map::Iter<'a, HeaderName, Value>) -> Self {
350 Self {
351 iter,
352 idx: 0,
353 current: None,
354 }
355 }
356}
357
358impl<'a> Iterator for Iter<'a> {
359 type Item = (&'a HeaderName, &'a HeaderValue);
360
361 #[inline]
362 fn next(&mut self) -> Option<(&'a HeaderName, &'a HeaderValue)> {
363 if let Some(ref mut item) = self.current {
364 if self.idx < item.1.len() {
365 let item = (item.0, &item.1[self.idx]);
366 self.idx += 1;
367 return Some(item);
368 } else {
369 self.idx = 0;
370 self.current.take();
371 }
372 }
373 if let Some(item) = self.iter.next() {
374 match item.1 {
375 Value::One(ref value) => Some((item.0, value)),
376 Value::Multi(ref vec) => {
377 self.current = Some((item.0, vec));
378 self.next()
379 }
380 }
381 } else {
382 None
383 }
384 }
385}