tower_grpc/metadata/
encoding.rs1use bytes::Bytes;
2use http::header::HeaderValue;
3use std::error::Error;
4use std::fmt;
5use std::hash::Hash;
6
7#[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 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
59impl 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 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
170impl 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#[derive(Debug)]
193pub struct InvalidMetadataValueBytes(InvalidMetadataValue);
194
195impl 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}