use super::headers::Header; use anyhow::{anyhow, Result}; use std::fmt::Display; #[derive(Debug, Clone)] pub struct HeaderMap(pub Vec<(String, String)>); impl HeaderMap { pub fn new() -> Self { Self(vec![]) } pub fn add(mut self, h: H) -> Self { self.0.push((H::NAME.to_string(), format!("{h}"))); self } pub fn insert(&mut self, h: H) { self.0.push((H::NAME.to_string(), format!("{h}"))); } pub fn get_raw(&self, name: &str) -> Option<&str> { self.0 .iter() .find(|(k, _)| k.eq_ignore_ascii_case(name)) .map(|(_, v)| v.as_str()) } pub fn get(&self) -> Option> { self.get_raw(H::NAME).map(H::from_str) } pub fn insert_raw(&mut self, key: String, value: String) { self.0.push((key, value)) } } impl Display for HeaderMap { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { for (k, v) in &self.0 { write!(f, "{k}: {v}\r\n")?; } Ok(()) } } impl HeaderMap { pub fn parse<'a>(lines: &mut impl Iterator) -> Result { let mut headers = HeaderMap::new(); for line in lines { // TODO multiline values let (key, value) = line.split_once(":").ok_or(anyhow!("header malformed"))?; headers.insert_raw(key.trim().to_string(), value.trim().to_string()) } Ok(headers) } } impl FromIterator<(String, String)> for HeaderMap { fn from_iter>(iter: T) -> Self { Self(Vec::from_iter(iter)) } }