use std::collections::HashMap;
use std::convert::TryInto;
use std::iter::IntoIterator;
mod constants;
mod header_name;
mod header_value;
mod into_iter;
mod iter;
mod iter_mut;
mod names;
mod to_header_values;
mod values;
pub use constants::*;
pub use header_name::HeaderName;
pub use header_value::HeaderValue;
pub use into_iter::IntoIter;
pub use iter::Iter;
pub use iter_mut::IterMut;
pub use names::Names;
pub use to_header_values::ToHeaderValues;
pub use values::Values;
#[derive(Debug)]
pub struct Headers {
pub(crate) headers: HashMap<HeaderName, Vec<HeaderValue>>,
}
impl Headers {
pub(crate) fn new() -> Self {
Self {
headers: HashMap::new(),
}
}
pub fn insert(
&mut self,
name: impl TryInto<HeaderName>,
values: impl ToHeaderValues,
) -> crate::Result<Option<Vec<HeaderValue>>> {
let name = name
.try_into()
.map_err(|_| crate::format_err!("Could not convert into header name"))?;
let values: Vec<HeaderValue> = values.to_header_values()?.collect();
Ok(self.headers.insert(name, values))
}
pub fn append(
&mut self,
name: impl TryInto<HeaderName>,
values: impl ToHeaderValues,
) -> crate::Result<()> {
let name = name
.try_into()
.map_err(|_| crate::format_err!("Could not convert into header name"))?;
match self.get_mut(&name) {
Some(headers) => {
let mut values: Vec<HeaderValue> = values.to_header_values()?.collect();
headers.append(&mut values);
}
None => {
self.insert(name, values)?;
}
}
Ok(())
}
pub fn get(&self, name: &HeaderName) -> Option<&Vec<HeaderValue>> {
self.headers.get(name)
}
pub fn get_mut(&mut self, name: &HeaderName) -> Option<&mut Vec<HeaderValue>> {
self.headers.get_mut(name)
}
pub fn remove(&mut self, name: &HeaderName) -> Option<Vec<HeaderValue>> {
self.headers.remove(name)
}
pub fn iter(&self) -> Iter<'_> {
Iter {
inner: self.headers.iter(),
}
}
pub fn iter_mut(&mut self) -> IterMut<'_> {
IterMut {
inner: self.headers.iter_mut(),
}
}
pub fn names(&self) -> Names<'_> {
Names {
inner: self.headers.keys(),
}
}
pub fn values(&self) -> Values<'_> {
Values::new(self.headers.values())
}
}
impl IntoIterator for Headers {
type Item = (HeaderName, Vec<HeaderValue>);
type IntoIter = IntoIter;
#[inline]
fn into_iter(self) -> Self::IntoIter {
IntoIter {
inner: self.headers.into_iter(),
}
}
}
impl<'a> IntoIterator for &'a Headers {
type Item = (&'a HeaderName, &'a Vec<HeaderValue>);
type IntoIter = Iter<'a>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a> IntoIterator for &'a mut Headers {
type Item = (&'a HeaderName, &'a mut Vec<HeaderValue>);
type IntoIter = IterMut<'a>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter_mut()
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::str::FromStr;
const STATIC_HEADER: HeaderName = HeaderName::from_lowercase_str("hello");
#[test]
fn test_header_name_static_non_static() -> crate::Result<()> {
let static_header = HeaderName::from_lowercase_str("hello");
let non_static_header = HeaderName::from_str("hello")?;
let mut headers = Headers::new();
headers.append(STATIC_HEADER, "foo0")?;
headers.append(static_header.clone(), "foo1")?;
headers.append(non_static_header.clone(), "foo2")?;
assert_eq!(
&headers.get(&STATIC_HEADER).unwrap()[..],
&["foo0", "foo1", "foo2",][..]
);
assert_eq!(
&headers.get(&static_header).unwrap()[..],
&["foo0", "foo1", "foo2",][..]
);
assert_eq!(
&headers.get(&non_static_header).unwrap()[..],
&["foo0", "foo1", "foo2",][..]
);
Ok(())
}
}