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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
use axol_http::typed_headers::{Error as HeaderError, Header, HeaderName, HeaderValue};

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Encoding {
    Identity,
    Gzip,
    Deflate,
    Snappy,
    Other(String),
}

impl Default for Encoding {
    fn default() -> Self {
        Encoding::Identity
    }
}

impl Encoding {
    fn from_str(value: &str) -> Self {
        match value {
            "identity" => Encoding::Identity,
            "gzip" => Encoding::Gzip,
            "deflate" => Encoding::Deflate,
            "snappy" => Encoding::Snappy,
            x => Encoding::Other(x.to_string()),
        }
    }

    fn as_str(&self) -> &str {
        match self {
            Encoding::Identity => "identity",
            Encoding::Gzip => "gzip",
            Encoding::Deflate => "deflate",
            Encoding::Snappy => "snappy",
            Encoding::Other(x) => x,
        }
    }
}

static GRPC_ENCODING: HeaderName = HeaderName::from_static("grpc-encoding");
static GRPC_ACCEPT_ENCODING: HeaderName = HeaderName::from_static("grpc-accept-encoding");

impl Header for Encoding {
    fn name() -> &'static HeaderName {
        &GRPC_ENCODING
    }

    fn decode<'i, I: Iterator<Item = &'i HeaderValue>>(values: &mut I) -> Result<Self, HeaderError>
    where
        Self: Sized,
    {
        let value = values.next().ok_or_else(|| HeaderError::invalid())?;
        let value = value.to_str().map_err(|_| HeaderError::invalid())?;
        Ok(Encoding::from_str(value))
    }

    fn encode<E: Extend<HeaderValue>>(&self, values: &mut E) {
        values.extend(std::iter::once(
            HeaderValue::from_str(self.as_str()).unwrap(),
        ));
    }
}

#[derive(Clone, Debug)]
pub struct AcceptEncoding(pub Vec<Encoding>);

impl Header for AcceptEncoding {
    fn name() -> &'static HeaderName {
        &GRPC_ACCEPT_ENCODING
    }

    fn decode<'i, I: Iterator<Item = &'i HeaderValue>>(values: &mut I) -> Result<Self, HeaderError>
    where
        Self: Sized,
    {
        let mut out = AcceptEncoding(vec![]);
        for value in values {
            let value = value.to_str().map_err(|_| HeaderError::invalid())?;
            for value in value.split(',').map(|x| x.trim()).filter(|x| !x.is_empty()) {
                out.0.push(Encoding::from_str(value));
            }
        }
        Ok(out)
    }

    fn encode<E: Extend<HeaderValue>>(&self, values: &mut E) {
        let raw = self
            .0
            .iter()
            .map(|x| x.as_str())
            .collect::<Vec<_>>()
            .join(",");
        values.extend(std::iter::once(HeaderValue::from_str(&raw).unwrap()));
    }
}