aboutsummaryrefslogtreecommitdiff
path: root/src/encoding/headermap.rs
blob: 01e196292bb21623cc6aca575625a4b34296ec82 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
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<H: Header>(mut self, h: H) -> Self {
        self.0.push((H::NAME.to_string(), format!("{h}")));
        self
    }
    pub fn insert<H: Header>(&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<H: Header>(&self) -> Option<Result<H>> {
        self.get_raw(H::NAME).map(H::from_str)
    }
    pub fn get_res<H: Header>(&self) -> Result<H> {
        self.get().ok_or(anyhow!("{} header missing", H::NAME))?
    }
    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<Item = &'a str>) -> Result<Self> {
        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<T: IntoIterator<Item = (String, String)>>(iter: T) -> Self {
        Self(Vec::from_iter(iter))
    }
}