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
#[derive(Debug, Clone)]
pub struct Cookie<'a> {
    pub name: &'a str,
    pub value: &'a str,
}

impl<'a> Cookie<'a> {
    pub fn parse(src: &'a str) -> Result<Self, ParseError> {
        let src = src.trim_matches(&[' ', '\t'][..]);
        let eq_idx = src.find('=').ok_or(ParseError::NoEquals)?;

        let name = &src[0..eq_idx];

        let value = &src[(eq_idx + 1)..];
        let value = if value.starts_with('"') && value.ends_with('"') {
            &value[1..(value.len() - 1)]
        } else {
            value
        };

        Ok(Cookie {
            name,
            value,
        })
    }
}

#[derive(Debug, PartialEq, Eq, Clone, Copy, thiserror::Error)]
pub enum ParseError {
    #[error("No = in cookie-pair")]
    NoEquals,
}

pub fn parse_cookies<'a>(src: &'a str) -> impl std::iter::Iterator<Item = Result<Cookie<'a>, ParseError>> + 'a {
    src.split(';').map(Cookie::parse)
}