tonic/metadata/
encoding.rs1use bytes::Bytes;
2use http::header::HeaderValue;
3use std::error::Error;
4use std::fmt;
5use std::hash::Hash;
6
7#[derive(Debug, Hash)]
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)]
55#[doc(hidden)]
56pub enum Ascii {}
57#[derive(Clone, Debug, Eq, PartialEq, Hash)]
58#[doc(hidden)]
59pub enum Binary {}
60
61impl self::value_encoding::Sealed for Ascii {
64 fn is_empty(value: &[u8]) -> bool {
65 value.is_empty()
66 }
67
68 fn from_bytes(value: &[u8]) -> Result<HeaderValue, InvalidMetadataValueBytes> {
69 HeaderValue::from_bytes(value).map_err(|_| InvalidMetadataValueBytes::new())
70 }
71
72 fn from_shared(value: Bytes) -> Result<HeaderValue, InvalidMetadataValueBytes> {
73 HeaderValue::from_maybe_shared(value).map_err(|_| InvalidMetadataValueBytes::new())
74 }
75
76 fn from_static(value: &'static str) -> HeaderValue {
77 HeaderValue::from_static(value)
78 }
79
80 fn decode(value: &[u8]) -> Result<Bytes, InvalidMetadataValueBytes> {
81 Ok(Bytes::copy_from_slice(value))
82 }
83
84 fn equals(a: &HeaderValue, b: &[u8]) -> bool {
85 a.as_bytes() == b
86 }
87
88 fn values_equal(a: &HeaderValue, b: &HeaderValue) -> bool {
89 a == b
90 }
91
92 fn fmt(value: &HeaderValue, f: &mut fmt::Formatter<'_>) -> fmt::Result {
93 fmt::Debug::fmt(value, f)
94 }
95}
96
97impl ValueEncoding for Ascii {
98 fn is_valid_key(key: &str) -> bool {
99 !Binary::is_valid_key(key)
100 }
101}
102
103impl self::value_encoding::Sealed for Binary {
104 fn is_empty(value: &[u8]) -> bool {
105 for c in value {
106 if *c != b'=' {
107 return false;
108 }
109 }
110 true
111 }
112
113 fn from_bytes(value: &[u8]) -> Result<HeaderValue, InvalidMetadataValueBytes> {
114 let encoded_value: String = base64::encode_config(value, base64::STANDARD_NO_PAD);
115 HeaderValue::from_maybe_shared(Bytes::from(encoded_value))
116 .map_err(|_| InvalidMetadataValueBytes::new())
117 }
118
119 fn from_shared(value: Bytes) -> Result<HeaderValue, InvalidMetadataValueBytes> {
120 Self::from_bytes(value.as_ref())
121 }
122
123 fn from_static(value: &'static str) -> HeaderValue {
124 if base64::decode(value).is_err() {
125 panic!("Invalid base64 passed to from_static: {}", value);
126 }
127 unsafe {
128 HeaderValue::from_maybe_shared_unchecked(Bytes::from_static(value.as_ref()))
131 }
132 }
133
134 fn decode(value: &[u8]) -> Result<Bytes, InvalidMetadataValueBytes> {
135 base64::decode(value)
136 .map(|bytes_vec| bytes_vec.into())
137 .map_err(|_| InvalidMetadataValueBytes::new())
138 }
139
140 fn equals(a: &HeaderValue, b: &[u8]) -> bool {
141 if let Ok(decoded) = base64::decode(a.as_bytes()) {
142 decoded == b
143 } else {
144 a.as_bytes() == b
145 }
146 }
147
148 fn values_equal(a: &HeaderValue, b: &HeaderValue) -> bool {
149 match (Self::decode(a.as_bytes()), Self::decode(b.as_bytes())) {
150 (Ok(a), Ok(b)) => a == b,
151 (Err(_), Err(_)) => true,
152 _ => false,
153 }
154 }
155
156 fn fmt(value: &HeaderValue, f: &mut fmt::Formatter<'_>) -> fmt::Result {
157 if let Ok(decoded) = Self::decode(value.as_bytes()) {
158 write!(f, "{:?}", decoded)
159 } else {
160 write!(f, "b[invalid]{:?}", value)
161 }
162 }
163}
164
165impl ValueEncoding for Binary {
166 fn is_valid_key(key: &str) -> bool {
167 key.ends_with("-bin")
168 }
169}
170
171impl InvalidMetadataValue {
174 pub(crate) fn new() -> Self {
175 InvalidMetadataValue { _priv: () }
176 }
177}
178
179impl fmt::Display for InvalidMetadataValue {
180 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
181 f.write_str("failed to parse metadata value")
182 }
183}
184
185impl Error for InvalidMetadataValue {}
186
187#[derive(Debug, Hash)]
190pub struct InvalidMetadataValueBytes(InvalidMetadataValue);
191
192impl InvalidMetadataValueBytes {
195 pub(crate) fn new() -> Self {
196 InvalidMetadataValueBytes(InvalidMetadataValue::new())
197 }
198}
199
200impl fmt::Display for InvalidMetadataValueBytes {
201 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
202 self.0.fmt(f)
203 }
204}
205
206impl Error for InvalidMetadataValueBytes {}