mirror of
https://github.com/fafhrd91/actix-web
synced 2024-11-27 17:52:56 +01:00
add headermap::retain (#2955)
* add headermap::retain * update changelog and docs * fix retain doc test
This commit is contained in:
parent
7b936bc443
commit
fbd0e5dd0a
@ -4,6 +4,7 @@
|
|||||||
### Added
|
### Added
|
||||||
- Implement `MessageBody` for `&mut B` where `B: MessageBody + Unpin`. [#2868]
|
- Implement `MessageBody` for `&mut B` where `B: MessageBody + Unpin`. [#2868]
|
||||||
- Implement `MessageBody` for `Pin<B>` where `B::Target: MessageBody`. [#2868]
|
- Implement `MessageBody` for `Pin<B>` where `B::Target: MessageBody`. [#2868]
|
||||||
|
- `HeaderMap::retain()` [#2955].
|
||||||
- Header name constants in `header` module. [#2956]
|
- Header name constants in `header` module. [#2956]
|
||||||
- `CROSS_ORIGIN_EMBEDDER_POLICY`
|
- `CROSS_ORIGIN_EMBEDDER_POLICY`
|
||||||
- `CROSS_ORIGIN_OPENER_POLICY`
|
- `CROSS_ORIGIN_OPENER_POLICY`
|
||||||
@ -17,6 +18,7 @@
|
|||||||
|
|
||||||
[#2868]: https://github.com/actix/actix-web/pull/2868
|
[#2868]: https://github.com/actix/actix-web/pull/2868
|
||||||
[#2890]: https://github.com/actix/actix-web/pull/2890
|
[#2890]: https://github.com/actix/actix-web/pull/2890
|
||||||
|
[#2955]: https://github.com/actix/actix-web/pull/2955
|
||||||
[#2956]: https://github.com/actix/actix-web/pull/2956
|
[#2956]: https://github.com/actix/actix-web/pull/2956
|
||||||
|
|
||||||
|
|
||||||
|
@ -150,9 +150,7 @@ impl HeaderMap {
|
|||||||
/// assert_eq!(map.len(), 3);
|
/// assert_eq!(map.len(), 3);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
self.inner
|
self.inner.values().map(|vals| vals.len()).sum()
|
||||||
.iter()
|
|
||||||
.fold(0, |acc, (_, values)| acc + values.len())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the number of _keys_ stored in the map.
|
/// Returns the number of _keys_ stored in the map.
|
||||||
@ -552,6 +550,39 @@ impl HeaderMap {
|
|||||||
Keys(self.inner.keys())
|
Keys(self.inner.keys())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Retains only the headers specified by the predicate.
|
||||||
|
///
|
||||||
|
/// In other words, removes all headers `(name, val)` for which `retain_fn(&name, &mut val)`
|
||||||
|
/// returns false.
|
||||||
|
///
|
||||||
|
/// The order in which headers are visited should be considered arbitrary.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
/// ```
|
||||||
|
/// # use actix_http::header::{self, HeaderMap, HeaderValue};
|
||||||
|
/// let mut map = HeaderMap::new();
|
||||||
|
///
|
||||||
|
/// map.append(header::HOST, HeaderValue::from_static("duck.com"));
|
||||||
|
/// map.append(header::SET_COOKIE, HeaderValue::from_static("one=1"));
|
||||||
|
/// map.append(header::SET_COOKIE, HeaderValue::from_static("two=2"));
|
||||||
|
///
|
||||||
|
/// map.retain(|name, val| val.as_bytes().starts_with(b"one"));
|
||||||
|
///
|
||||||
|
/// assert_eq!(map.len(), 1);
|
||||||
|
/// assert!(map.contains_key(&header::SET_COOKIE));
|
||||||
|
/// ```
|
||||||
|
pub fn retain<F>(&mut self, mut retain_fn: F)
|
||||||
|
where
|
||||||
|
F: FnMut(&HeaderName, &mut HeaderValue) -> bool,
|
||||||
|
{
|
||||||
|
self.inner.retain(|name, vals| {
|
||||||
|
vals.inner.retain(|val| retain_fn(name, val));
|
||||||
|
|
||||||
|
// invariant: make sure newly empty value lists are removed
|
||||||
|
!vals.is_empty()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Clears the map, returning all name-value sets as an iterator.
|
/// Clears the map, returning all name-value sets as an iterator.
|
||||||
///
|
///
|
||||||
/// Header names will only be yielded for the first value in each set. All items that are
|
/// Header names will only be yielded for the first value in each set. All items that are
|
||||||
@ -943,6 +974,55 @@ mod tests {
|
|||||||
assert!(map.is_empty());
|
assert!(map.is_empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn retain() {
|
||||||
|
let mut map = HeaderMap::new();
|
||||||
|
|
||||||
|
map.append(header::LOCATION, HeaderValue::from_static("/test"));
|
||||||
|
map.append(header::HOST, HeaderValue::from_static("duck.com"));
|
||||||
|
map.append(header::COOKIE, HeaderValue::from_static("one=1"));
|
||||||
|
map.append(header::COOKIE, HeaderValue::from_static("two=2"));
|
||||||
|
|
||||||
|
assert_eq!(map.len(), 4);
|
||||||
|
|
||||||
|
// by value
|
||||||
|
map.retain(|_, val| !val.as_bytes().contains(&b'/'));
|
||||||
|
assert_eq!(map.len(), 3);
|
||||||
|
|
||||||
|
// by name
|
||||||
|
map.retain(|name, _| name.as_str() != "cookie");
|
||||||
|
assert_eq!(map.len(), 1);
|
||||||
|
|
||||||
|
// keep but mutate value
|
||||||
|
map.retain(|_, val| {
|
||||||
|
*val = HeaderValue::from_static("replaced");
|
||||||
|
true
|
||||||
|
});
|
||||||
|
assert_eq!(map.len(), 1);
|
||||||
|
assert_eq!(map.get("host").unwrap(), "replaced");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn retain_removes_empty_value_lists() {
|
||||||
|
let mut map = HeaderMap::with_capacity(3);
|
||||||
|
|
||||||
|
map.append(header::HOST, HeaderValue::from_static("duck.com"));
|
||||||
|
map.append(header::HOST, HeaderValue::from_static("duck.com"));
|
||||||
|
|
||||||
|
assert_eq!(map.len(), 2);
|
||||||
|
assert_eq!(map.len_keys(), 1);
|
||||||
|
assert_eq!(map.inner.len(), 1);
|
||||||
|
assert_eq!(map.capacity(), 3);
|
||||||
|
|
||||||
|
// remove everything
|
||||||
|
map.retain(|_n, _v| false);
|
||||||
|
|
||||||
|
assert_eq!(map.len(), 0);
|
||||||
|
assert_eq!(map.len_keys(), 0);
|
||||||
|
assert_eq!(map.inner.len(), 0);
|
||||||
|
assert_eq!(map.capacity(), 3);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn entries_into_iter() {
|
fn entries_into_iter() {
|
||||||
let mut map = HeaderMap::new();
|
let mut map = HeaderMap::new();
|
||||||
|
Loading…
Reference in New Issue
Block a user