1 use base64::Engine as _;
2 use bytes::Bytes;
3 use http::header::HeaderValue;
4 use std::error::Error;
5 use std::fmt;
6 use std::hash::Hash;
7 
8 /// A possible error when converting a `MetadataValue` from a string or byte
9 /// slice.
10 #[derive(Debug, Hash)]
11 pub struct InvalidMetadataValue {
12     _priv: (),
13 }
14 
15 mod value_encoding {
16     use super::InvalidMetadataValueBytes;
17     use bytes::Bytes;
18     use http::header::HeaderValue;
19     use std::fmt;
20 
21     pub trait Sealed {
22         #[doc(hidden)]
is_empty(value: &[u8]) -> bool23         fn is_empty(value: &[u8]) -> bool;
24 
25         #[doc(hidden)]
from_bytes(value: &[u8]) -> Result<HeaderValue, InvalidMetadataValueBytes>26         fn from_bytes(value: &[u8]) -> Result<HeaderValue, InvalidMetadataValueBytes>;
27 
28         #[doc(hidden)]
from_shared(value: Bytes) -> Result<HeaderValue, InvalidMetadataValueBytes>29         fn from_shared(value: Bytes) -> Result<HeaderValue, InvalidMetadataValueBytes>;
30 
31         #[doc(hidden)]
from_static(value: &'static str) -> HeaderValue32         fn from_static(value: &'static str) -> HeaderValue;
33 
34         #[doc(hidden)]
decode(value: &[u8]) -> Result<Bytes, InvalidMetadataValueBytes>35         fn decode(value: &[u8]) -> Result<Bytes, InvalidMetadataValueBytes>;
36 
37         #[doc(hidden)]
equals(a: &HeaderValue, b: &[u8]) -> bool38         fn equals(a: &HeaderValue, b: &[u8]) -> bool;
39 
40         #[doc(hidden)]
values_equal(a: &HeaderValue, b: &HeaderValue) -> bool41         fn values_equal(a: &HeaderValue, b: &HeaderValue) -> bool;
42 
43         #[doc(hidden)]
fmt(value: &HeaderValue, f: &mut fmt::Formatter<'_>) -> fmt::Result44         fn fmt(value: &HeaderValue, f: &mut fmt::Formatter<'_>) -> fmt::Result;
45     }
46 }
47 
48 pub trait ValueEncoding: Clone + Eq + PartialEq + Hash + self::value_encoding::Sealed {
49     /// Returns true if the provided key is valid for this ValueEncoding type.
50     /// For example, `Ascii::is_valid_key("a") == true`,
51     /// `Ascii::is_valid_key("a-bin") == false`.
is_valid_key(key: &str) -> bool52     fn is_valid_key(key: &str) -> bool;
53 }
54 
55 /// gRPC metadata values can be either ASCII strings or binary. Note that only
56 /// visible ASCII characters (32-127) are permitted.
57 /// This type should never be instantiated -- in fact, it's impossible
58 /// to, because there's no variants to instantiate. Instead, it's just used as
59 /// a type parameter for [`MetadataKey`] and [`MetadataValue`].
60 ///
61 /// [`MetadataKey`]: struct.MetadataKey.html
62 /// [`MetadataValue`]: struct.MetadataValue.html
63 #[derive(Clone, Debug, Eq, PartialEq, Hash)]
64 #[non_exhaustive]
65 pub enum Ascii {}
66 
67 /// gRPC metadata values can be either ASCII strings or binary.
68 /// This type should never be instantiated -- in fact, it's impossible
69 /// to, because there's no variants to instantiate. Instead, it's just used as
70 /// a type parameter for [`MetadataKey`] and [`MetadataValue`].
71 ///
72 /// [`MetadataKey`]: struct.MetadataKey.html
73 /// [`MetadataValue`]: struct.MetadataValue.html
74 #[derive(Clone, Debug, Eq, PartialEq, Hash)]
75 #[non_exhaustive]
76 pub enum Binary {}
77 
78 // ===== impl ValueEncoding =====
79 
80 impl self::value_encoding::Sealed for Ascii {
is_empty(value: &[u8]) -> bool81     fn is_empty(value: &[u8]) -> bool {
82         value.is_empty()
83     }
84 
from_bytes(value: &[u8]) -> Result<HeaderValue, InvalidMetadataValueBytes>85     fn from_bytes(value: &[u8]) -> Result<HeaderValue, InvalidMetadataValueBytes> {
86         HeaderValue::from_bytes(value).map_err(|_| InvalidMetadataValueBytes::new())
87     }
88 
from_shared(value: Bytes) -> Result<HeaderValue, InvalidMetadataValueBytes>89     fn from_shared(value: Bytes) -> Result<HeaderValue, InvalidMetadataValueBytes> {
90         HeaderValue::from_maybe_shared(value).map_err(|_| InvalidMetadataValueBytes::new())
91     }
92 
from_static(value: &'static str) -> HeaderValue93     fn from_static(value: &'static str) -> HeaderValue {
94         HeaderValue::from_static(value)
95     }
96 
decode(value: &[u8]) -> Result<Bytes, InvalidMetadataValueBytes>97     fn decode(value: &[u8]) -> Result<Bytes, InvalidMetadataValueBytes> {
98         Ok(Bytes::copy_from_slice(value))
99     }
100 
equals(a: &HeaderValue, b: &[u8]) -> bool101     fn equals(a: &HeaderValue, b: &[u8]) -> bool {
102         a.as_bytes() == b
103     }
104 
values_equal(a: &HeaderValue, b: &HeaderValue) -> bool105     fn values_equal(a: &HeaderValue, b: &HeaderValue) -> bool {
106         a == b
107     }
108 
fmt(value: &HeaderValue, f: &mut fmt::Formatter<'_>) -> fmt::Result109     fn fmt(value: &HeaderValue, f: &mut fmt::Formatter<'_>) -> fmt::Result {
110         fmt::Debug::fmt(value, f)
111     }
112 }
113 
114 impl ValueEncoding for Ascii {
is_valid_key(key: &str) -> bool115     fn is_valid_key(key: &str) -> bool {
116         !Binary::is_valid_key(key)
117     }
118 }
119 
120 impl self::value_encoding::Sealed for Binary {
is_empty(value: &[u8]) -> bool121     fn is_empty(value: &[u8]) -> bool {
122         for c in value {
123             if *c != b'=' {
124                 return false;
125             }
126         }
127         true
128     }
129 
from_bytes(value: &[u8]) -> Result<HeaderValue, InvalidMetadataValueBytes>130     fn from_bytes(value: &[u8]) -> Result<HeaderValue, InvalidMetadataValueBytes> {
131         let encoded_value: String = crate::util::base64::STANDARD_NO_PAD.encode(value);
132         HeaderValue::from_maybe_shared(Bytes::from(encoded_value))
133             .map_err(|_| InvalidMetadataValueBytes::new())
134     }
135 
from_shared(value: Bytes) -> Result<HeaderValue, InvalidMetadataValueBytes>136     fn from_shared(value: Bytes) -> Result<HeaderValue, InvalidMetadataValueBytes> {
137         Self::from_bytes(value.as_ref())
138     }
139 
from_static(value: &'static str) -> HeaderValue140     fn from_static(value: &'static str) -> HeaderValue {
141         if crate::util::base64::STANDARD.decode(value).is_err() {
142             panic!("Invalid base64 passed to from_static: {}", value);
143         }
144         unsafe {
145             // Because this is valid base64 this must be a valid HTTP header value,
146             // no need to check again by calling from_shared.
147             HeaderValue::from_maybe_shared_unchecked(Bytes::from_static(value.as_ref()))
148         }
149     }
150 
decode(value: &[u8]) -> Result<Bytes, InvalidMetadataValueBytes>151     fn decode(value: &[u8]) -> Result<Bytes, InvalidMetadataValueBytes> {
152         crate::util::base64::STANDARD
153             .decode(value)
154             .map(|bytes_vec| bytes_vec.into())
155             .map_err(|_| InvalidMetadataValueBytes::new())
156     }
157 
equals(a: &HeaderValue, b: &[u8]) -> bool158     fn equals(a: &HeaderValue, b: &[u8]) -> bool {
159         if let Ok(decoded) = crate::util::base64::STANDARD.decode(a.as_bytes()) {
160             decoded == b
161         } else {
162             a.as_bytes() == b
163         }
164     }
165 
values_equal(a: &HeaderValue, b: &HeaderValue) -> bool166     fn values_equal(a: &HeaderValue, b: &HeaderValue) -> bool {
167         match (Self::decode(a.as_bytes()), Self::decode(b.as_bytes())) {
168             (Ok(a), Ok(b)) => a == b,
169             (Err(_), Err(_)) => true,
170             _ => false,
171         }
172     }
173 
fmt(value: &HeaderValue, f: &mut fmt::Formatter<'_>) -> fmt::Result174     fn fmt(value: &HeaderValue, f: &mut fmt::Formatter<'_>) -> fmt::Result {
175         if let Ok(decoded) = Self::decode(value.as_bytes()) {
176             write!(f, "{:?}", decoded)
177         } else {
178             write!(f, "b[invalid]{:?}", value)
179         }
180     }
181 }
182 
183 impl ValueEncoding for Binary {
is_valid_key(key: &str) -> bool184     fn is_valid_key(key: &str) -> bool {
185         key.ends_with("-bin")
186     }
187 }
188 
189 // ===== impl InvalidMetadataValue =====
190 
191 impl InvalidMetadataValue {
new() -> Self192     pub(crate) fn new() -> Self {
193         InvalidMetadataValue { _priv: () }
194     }
195 }
196 
197 impl fmt::Display for InvalidMetadataValue {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result198     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
199         f.write_str("failed to parse metadata value")
200     }
201 }
202 
203 impl Error for InvalidMetadataValue {}
204 
205 /// A possible error when converting a `MetadataValue` from a string or byte
206 /// slice.
207 #[derive(Debug, Hash)]
208 pub struct InvalidMetadataValueBytes(InvalidMetadataValue);
209 
210 // ===== impl InvalidMetadataValueBytes =====
211 
212 impl InvalidMetadataValueBytes {
new() -> Self213     pub(crate) fn new() -> Self {
214         InvalidMetadataValueBytes(InvalidMetadataValue::new())
215     }
216 }
217 
218 impl fmt::Display for InvalidMetadataValueBytes {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result219     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
220         self.0.fmt(f)
221     }
222 }
223 
224 impl Error for InvalidMetadataValueBytes {}
225