use std::collections::HashSet;
use http::header::{HeaderMap, HeaderName, HeaderValue};
#[derive(Debug, Default)]
pub struct PendingHeaders {
insert: HeaderMap,
append: HeaderMap,
remove: HashSet<HeaderName>,
}
impl PendingHeaders {
pub fn len(&self) -> usize {
self.insert.len() + self.append.len()
}
pub fn apply(self, headers: &mut HeaderMap) {
for name in self.remove.iter() {
headers.remove(name);
}
headers.extend(self.insert);
let mut name = None;
for (curr, val) in self.append.into_iter() {
if curr.is_some() {
name = curr;
}
if let Some(name) = name.as_ref() {
headers.append(name, val);
}
}
}
pub fn insert(&mut self, name: HeaderName, value: HeaderValue) {
self.append.remove(&name);
self.insert.insert(name, value);
}
pub fn append(&mut self, name: HeaderName, value: HeaderValue) {
self.append.append(name, value);
}
pub fn remove(&mut self, name: HeaderName) {
self.insert.remove(&name);
self.append.remove(&name);
self.remove.insert(name);
}
}
#[cfg(test)]
mod tests {
use super::*;
const HEADER_FOO: HeaderName = HeaderName::from_static("foo");
const HEADER_BAR: HeaderName = HeaderName::from_static("bar");
const VALUE_1: HeaderValue = HeaderValue::from_static("1");
const VALUE_2: HeaderValue = HeaderValue::from_static("2");
const VALUE_3: HeaderValue = HeaderValue::from_static("3");
#[test]
fn test_pending_headers_insert_empty() {
let mut headers = HeaderMap::default();
let mut pending = PendingHeaders::default();
pending.insert(HEADER_FOO, VALUE_1);
pending.apply(&mut headers);
assert_eq!(headers.len(), 1);
assert_eq!(headers.get(HEADER_FOO).unwrap(), VALUE_1);
}
#[test]
fn test_pending_headers_insert_disjoint() {
let mut headers = HeaderMap::default();
let mut pending = PendingHeaders::default();
headers.insert(HEADER_BAR, VALUE_1);
pending.insert(HEADER_FOO, VALUE_2);
pending.apply(&mut headers);
assert_eq!(headers.len(), 2);
assert_eq!(headers.get(HEADER_BAR).unwrap(), VALUE_1);
assert_eq!(headers.get(HEADER_FOO).unwrap(), VALUE_2);
}
#[test]
fn test_pending_headers_insert_overwrite() {
let mut headers = HeaderMap::default();
let mut pending = PendingHeaders::default();
headers.insert(HEADER_FOO, VALUE_1);
pending.insert(HEADER_FOO, VALUE_2);
pending.apply(&mut headers);
assert_eq!(headers.len(), 1);
assert_eq!(headers.get(HEADER_FOO).unwrap(), VALUE_2);
}
#[test]
fn test_pending_headers_insert_conflicting() {
let mut headers = HeaderMap::default();
let mut pending = PendingHeaders::default();
pending.insert(HEADER_FOO, VALUE_1);
pending.insert(HEADER_FOO, VALUE_2);
pending.insert(HEADER_FOO, VALUE_3);
pending.apply(&mut headers);
assert_eq!(headers.len(), 1);
assert_eq!(headers.get(HEADER_FOO).unwrap(), VALUE_3);
}
#[test]
fn test_pending_headers_append_empty() {
let mut headers = HeaderMap::default();
let mut pending = PendingHeaders::default();
pending.append(HEADER_FOO, VALUE_1);
pending.apply(&mut headers);
assert_eq!(headers.len(), 1);
assert_eq!(headers.get(HEADER_FOO).unwrap(), VALUE_1);
}
#[test]
fn test_pending_headers_append_disjoint() {
let mut headers = HeaderMap::default();
let mut pending = PendingHeaders::default();
headers.append(HEADER_BAR, VALUE_1);
pending.append(HEADER_FOO, VALUE_2);
pending.apply(&mut headers);
assert_eq!(headers.len(), 2);
assert_eq!(headers.get(HEADER_BAR).unwrap(), VALUE_1);
assert_eq!(headers.get(HEADER_FOO).unwrap(), VALUE_2);
}
#[test]
fn test_pending_headers_append_overlap() {
let mut headers = HeaderMap::default();
let mut pending = PendingHeaders::default();
headers.append(HEADER_FOO, VALUE_1);
pending.append(HEADER_FOO, VALUE_2);
pending.apply(&mut headers);
assert_eq!(headers.len(), 2);
assert_eq!(
headers.get_all(HEADER_FOO).into_iter().collect::<Vec<_>>(),
&[VALUE_1, VALUE_2]
);
}
#[test]
fn test_pending_headers_remove_empty() {
let mut headers = HeaderMap::default();
let mut pending = PendingHeaders::default();
pending.remove(HEADER_FOO);
pending.apply(&mut headers);
assert_eq!(headers.len(), 0);
assert_eq!(headers.get(HEADER_FOO), None);
}
#[test]
fn test_pending_headers_remove_disjoint() {
let mut headers = HeaderMap::default();
let mut pending = PendingHeaders::default();
headers.insert(HEADER_BAR, VALUE_1);
pending.remove(HEADER_FOO);
pending.apply(&mut headers);
assert_eq!(headers.len(), 1);
assert_eq!(headers.get(HEADER_BAR).unwrap(), VALUE_1);
assert_eq!(headers.get(HEADER_FOO), None);
}
#[test]
fn test_pending_headers_remove_overlap() {
let mut headers = HeaderMap::default();
let mut pending = PendingHeaders::default();
headers.insert(HEADER_FOO, VALUE_1);
pending.remove(HEADER_FOO);
pending.apply(&mut headers);
assert_eq!(headers.len(), 0);
assert_eq!(headers.get(HEADER_FOO), None);
}
#[test]
fn test_pending_headers_remove_after_insertion() {
let mut headers = HeaderMap::default();
let mut pending = PendingHeaders::default();
pending.insert(HEADER_FOO, VALUE_1);
pending.append(HEADER_FOO, VALUE_2);
pending.remove(HEADER_FOO);
pending.apply(&mut headers);
assert_eq!(headers.len(), 0);
assert_eq!(headers.get(HEADER_FOO), None);
}
#[test]
fn test_pending_headers_insertion_after_remove() {
let mut headers = HeaderMap::default();
let mut pending = PendingHeaders::default();
pending.remove(HEADER_FOO);
pending.insert(HEADER_FOO, VALUE_1);
pending.append(HEADER_FOO, VALUE_2);
pending.apply(&mut headers);
assert_eq!(headers.len(), 2);
assert_eq!(
headers.get_all(HEADER_FOO).into_iter().collect::<Vec<_>>(),
&[VALUE_1, VALUE_2]
);
}
#[test]
fn test_pending_headers_insert_after_append() {
let mut headers = HeaderMap::default();
let mut pending = PendingHeaders::default();
pending.append(HEADER_FOO, VALUE_1);
pending.append(HEADER_FOO, VALUE_2);
pending.insert(HEADER_FOO, VALUE_3);
pending.apply(&mut headers);
assert_eq!(headers.len(), 1);
assert_eq!(headers.get(HEADER_FOO).unwrap(), VALUE_3);
}
}