tower_grpc/metadata/
encoding.rs

1use bytes::Bytes;
2use http::header::HeaderValue;
3use std::error::Error;
4use std::fmt;
5use std::hash::Hash;
6
7/// A possible error when converting a `MetadataValue` from a string or byte
8/// slice.
9#[derive(Debug)]
10pub struct InvalidMetadataValue {
11    _priv: (),
12}
13
14mod value_encoding {
15    use super::InvalidMetadataValueBytes;
16    use bytes::Bytes;
17    use http::header::HeaderValue;
18    use std::fmt;
19
20    pub trait Sealed {
21        #[doc(hidden)]
22        fn is_empty(value: &[u8]) -> bool;
23
24        #[doc(hidden)]
25        fn from_bytes(value: &[u8]) -> Result<HeaderValue, InvalidMetadataValueBytes>;
26
27        #[doc(hidden)]
28        fn from_shared(value: Bytes) -> Result<HeaderValue, InvalidMetadataValueBytes>;
29
30        #[doc(hidden)]
31        fn from_static(value: &'static str) -> HeaderValue;
32
33        #[doc(hidden)]
34        fn decode(value: &[u8]) -> Result<Bytes, InvalidMetadataValueBytes>;
35
36        #[doc(hidden)]
37        fn equals(a: &HeaderValue, b: &[u8]) -> bool;
38
39        #[doc(hidden)]
40        fn values_equal(a: &HeaderValue, b: &HeaderValue) -> bool;
41
42        #[doc(hidden)]
43        fn fmt(value: &HeaderValue, f: &mut fmt::Formatter<'_>) -> fmt::Result;
44    }
45}
46
47pub trait ValueEncoding: Clone + Eq + PartialEq + Hash + self::value_encoding::Sealed {
48    /// Returns true if the provided key is valid for this ValueEncoding type.
49    /// For example, `Ascii::is_valid_key("a") == true`,
50    /// `Ascii::is_valid_key("a-bin") == false`.
51    fn is_valid_key(key: &str) -> bool;
52}
53
54#[derive(Clone, Debug, Eq, PartialEq, Hash)]
55pub enum Ascii {}
56#[derive(Clone, Debug, Eq, PartialEq, Hash)]
57pub enum Binary {}
58
59// ===== impl ValueEncoding =====
60
61impl self::value_encoding::Sealed for Ascii {
62    fn is_empty(value: &[u8]) -> bool {
63        value.is_empty()
64    }
65
66    fn from_bytes(value: &[u8]) -> Result<HeaderValue, InvalidMetadataValueBytes> {
67        HeaderValue::from_bytes(value).map_err(|_| InvalidMetadataValueBytes::new())
68    }
69
70    fn from_shared(value: Bytes) -> Result<HeaderValue, InvalidMetadataValueBytes> {
71        HeaderValue::from_shared(value).map_err(|_| InvalidMetadataValueBytes::new())
72    }
73
74    fn from_static(value: &'static str) -> HeaderValue {
75        HeaderValue::from_static(value)
76    }
77
78    fn decode(value: &[u8]) -> Result<Bytes, InvalidMetadataValueBytes> {
79        Ok(Bytes::from(value))
80    }
81
82    fn equals(a: &HeaderValue, b: &[u8]) -> bool {
83        a.as_bytes() == b
84    }
85
86    fn values_equal(a: &HeaderValue, b: &HeaderValue) -> bool {
87        a == b
88    }
89
90    fn fmt(value: &HeaderValue, f: &mut fmt::Formatter<'_>) -> fmt::Result {
91        fmt::Debug::fmt(value, f)
92    }
93}
94
95impl ValueEncoding for Ascii {
96    fn is_valid_key(key: &str) -> bool {
97        !Binary::is_valid_key(key)
98    }
99}
100
101impl self::value_encoding::Sealed for Binary {
102    fn is_empty(value: &[u8]) -> bool {
103        for c in value {
104            if *c != b'=' {
105                return false;
106            }
107        }
108        true
109    }
110
111    fn from_bytes(value: &[u8]) -> Result<HeaderValue, InvalidMetadataValueBytes> {
112        let encoded_value: String = base64::encode_config(value, base64::STANDARD_NO_PAD);
113        HeaderValue::from_shared(encoded_value.into()).map_err(|_| InvalidMetadataValueBytes::new())
114    }
115
116    fn from_shared(value: Bytes) -> Result<HeaderValue, InvalidMetadataValueBytes> {
117        Self::from_bytes(value.as_ref())
118    }
119
120    fn from_static(value: &'static str) -> HeaderValue {
121        if !base64::decode(value).is_ok() {
122            panic!("Invalid base64 passed to from_static: {}", value);
123        }
124        unsafe {
125            // Because this is valid base64 this must be a valid HTTP header value,
126            // no need to check again by calling from_shared.
127            HeaderValue::from_shared_unchecked(Bytes::from_static(value.as_ref()))
128        }
129    }
130
131    fn decode(value: &[u8]) -> Result<Bytes, InvalidMetadataValueBytes> {
132        base64::decode(value)
133            .map(|bytes_vec| bytes_vec.into())
134            .map_err(|_| InvalidMetadataValueBytes::new())
135    }
136
137    fn equals(a: &HeaderValue, b: &[u8]) -> bool {
138        if let Ok(decoded) = base64::decode(a.as_bytes()) {
139            decoded == b
140        } else {
141            a.as_bytes() == b
142        }
143    }
144
145    fn values_equal(a: &HeaderValue, b: &HeaderValue) -> bool {
146        let decoded_a = Self::decode(a.as_bytes());
147        let decoded_b = Self::decode(b.as_bytes());
148        if decoded_a.is_ok() && decoded_b.is_ok() {
149            decoded_a.unwrap() == decoded_b.unwrap()
150        } else {
151            !decoded_a.is_ok() && !decoded_b.is_ok()
152        }
153    }
154
155    fn fmt(value: &HeaderValue, f: &mut fmt::Formatter<'_>) -> fmt::Result {
156        if let Ok(decoded) = Self::decode(value.as_bytes()) {
157            write!(f, "{:?}", decoded)
158        } else {
159            write!(f, "b[invalid]{:?}", value)
160        }
161    }
162}
163
164impl ValueEncoding for Binary {
165    fn is_valid_key(key: &str) -> bool {
166        key.ends_with("-bin")
167    }
168}
169
170// ===== impl InvalidMetadataValue =====
171
172impl InvalidMetadataValue {
173    pub(crate) fn new() -> Self {
174        InvalidMetadataValue { _priv: () }
175    }
176}
177
178impl fmt::Display for InvalidMetadataValue {
179    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
180        self.description().fmt(f)
181    }
182}
183
184impl Error for InvalidMetadataValue {
185    fn description(&self) -> &str {
186        "failed to parse metadata value"
187    }
188}
189
190/// A possible error when converting a `MetadataValue` from a string or byte
191/// slice.
192#[derive(Debug)]
193pub struct InvalidMetadataValueBytes(InvalidMetadataValue);
194
195// ===== impl InvalidMetadataValueBytes =====
196
197impl InvalidMetadataValueBytes {
198    pub(crate) fn new() -> Self {
199        InvalidMetadataValueBytes(InvalidMetadataValue::new())
200    }
201}
202
203impl fmt::Display for InvalidMetadataValueBytes {
204    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
205        self.0.fmt(f)
206    }
207}
208
209impl Error for InvalidMetadataValueBytes {
210    fn description(&self) -> &str {
211        self.0.description()
212    }
213}