/rust/registry/src/index.crates.io-1949cf8c6b5b557f/tonic-0.13.0/src/metadata/value.rs
Line | Count | Source |
1 | | use super::encoding::{ |
2 | | Ascii, Binary, InvalidMetadataValue, InvalidMetadataValueBytes, ValueEncoding, |
3 | | }; |
4 | | use super::key::MetadataKey; |
5 | | |
6 | | use bytes::Bytes; |
7 | | use http::header::HeaderValue; |
8 | | use std::error::Error; |
9 | | use std::hash::{Hash, Hasher}; |
10 | | use std::marker::PhantomData; |
11 | | use std::str::FromStr; |
12 | | use std::{cmp, fmt}; |
13 | | |
14 | | /// Represents a custom metadata field value. |
15 | | /// |
16 | | /// `MetadataValue` is used as the [`MetadataMap`] value. |
17 | | /// |
18 | | /// [`HeaderMap`]: struct.HeaderMap.html |
19 | | /// [`MetadataMap`]: struct.MetadataMap.html |
20 | | #[derive(Clone)] |
21 | | #[repr(transparent)] |
22 | | pub struct MetadataValue<VE: ValueEncoding> { |
23 | | // Note: There are unsafe transmutes that assume that the memory layout |
24 | | // of MetadataValue is identical to HeaderValue |
25 | | pub(crate) inner: HeaderValue, |
26 | | phantom: PhantomData<VE>, |
27 | | } |
28 | | |
29 | | /// A possible error when converting a `MetadataValue` to a string representation. |
30 | | /// |
31 | | /// Metadata field values may contain opaque bytes, in which case it is not |
32 | | /// possible to represent the value as a string. |
33 | | #[derive(Debug)] |
34 | | pub struct ToStrError { |
35 | | _priv: (), |
36 | | } |
37 | | |
38 | | /// An ascii metadata value. |
39 | | pub type AsciiMetadataValue = MetadataValue<Ascii>; |
40 | | /// A binary metadata value. |
41 | | pub type BinaryMetadataValue = MetadataValue<Binary>; |
42 | | |
43 | | impl<VE: ValueEncoding> MetadataValue<VE> { |
44 | | /// Convert a static string to a `MetadataValue`. |
45 | | /// |
46 | | /// This function will not perform any copying, however the string is |
47 | | /// checked to ensure that no invalid characters are present. |
48 | | /// |
49 | | /// For Ascii values, only visible ASCII characters (32-127) are permitted. |
50 | | /// For Binary values, the string must be valid base64. |
51 | | /// |
52 | | /// # Panics |
53 | | /// |
54 | | /// This function panics if the argument contains invalid metadata value |
55 | | /// characters. |
56 | | /// |
57 | | /// # Examples |
58 | | /// |
59 | | /// ``` |
60 | | /// # use tonic::metadata::*; |
61 | | /// let val = AsciiMetadataValue::from_static("hello"); |
62 | | /// assert_eq!(val, "hello"); |
63 | | /// ``` |
64 | | /// |
65 | | /// ``` |
66 | | /// # use tonic::metadata::*; |
67 | | /// let val = BinaryMetadataValue::from_static("SGVsbG8hIQ=="); |
68 | | /// assert_eq!(val, "Hello!!"); |
69 | | /// ``` |
70 | | #[inline] |
71 | 0 | pub fn from_static(src: &'static str) -> Self { |
72 | 0 | MetadataValue { |
73 | 0 | inner: VE::from_static(src), |
74 | 0 | phantom: PhantomData, |
75 | 0 | } |
76 | 0 | } |
77 | | |
78 | | /// Convert a `Bytes` directly into a `MetadataValue` without validating. |
79 | | /// For `MetadataValue<Binary>` the provided parameter must be base64 |
80 | | /// encoded without padding bytes at the end. |
81 | | /// |
82 | | /// # Safety |
83 | | /// |
84 | | /// This function does NOT validate that illegal bytes are not contained |
85 | | /// within the buffer. |
86 | | #[inline] |
87 | 0 | pub unsafe fn from_shared_unchecked(src: Bytes) -> Self { |
88 | 0 | MetadataValue { |
89 | 0 | inner: HeaderValue::from_maybe_shared_unchecked(src), |
90 | 0 | phantom: PhantomData, |
91 | 0 | } |
92 | 0 | } |
93 | | |
94 | | /// Returns true if the `MetadataValue` has a length of zero bytes. |
95 | | /// |
96 | | /// # Examples |
97 | | /// |
98 | | /// ``` |
99 | | /// # use tonic::metadata::*; |
100 | | /// let val = AsciiMetadataValue::from_static(""); |
101 | | /// assert!(val.is_empty()); |
102 | | /// |
103 | | /// let val = AsciiMetadataValue::from_static("hello"); |
104 | | /// assert!(!val.is_empty()); |
105 | | /// ``` |
106 | | #[inline] |
107 | 0 | pub fn is_empty(&self) -> bool { |
108 | 0 | VE::is_empty(self.inner.as_bytes()) |
109 | 0 | } |
110 | | |
111 | | /// Converts a `MetadataValue` to a Bytes buffer. This method cannot |
112 | | /// fail for Ascii values. For Ascii values, `as_bytes` is more convenient |
113 | | /// to use. |
114 | | /// |
115 | | /// # Examples |
116 | | /// |
117 | | /// ``` |
118 | | /// # use tonic::metadata::*; |
119 | | /// let val = AsciiMetadataValue::from_static("hello"); |
120 | | /// assert_eq!(val.to_bytes().unwrap().as_ref(), b"hello"); |
121 | | /// ``` |
122 | | /// |
123 | | /// ``` |
124 | | /// # use tonic::metadata::*; |
125 | | /// let val = BinaryMetadataValue::from_bytes(b"hello"); |
126 | | /// assert_eq!(val.to_bytes().unwrap().as_ref(), b"hello"); |
127 | | /// ``` |
128 | | #[inline] |
129 | 0 | pub fn to_bytes(&self) -> Result<Bytes, InvalidMetadataValueBytes> { |
130 | 0 | VE::decode(self.inner.as_bytes()) |
131 | 0 | } |
132 | | |
133 | | /// Mark that the metadata value represents sensitive information. |
134 | | /// |
135 | | /// # Examples |
136 | | /// |
137 | | /// ``` |
138 | | /// # use tonic::metadata::*; |
139 | | /// let mut val = AsciiMetadataValue::from_static("my secret"); |
140 | | /// |
141 | | /// val.set_sensitive(true); |
142 | | /// assert!(val.is_sensitive()); |
143 | | /// |
144 | | /// val.set_sensitive(false); |
145 | | /// assert!(!val.is_sensitive()); |
146 | | /// ``` |
147 | | #[inline] |
148 | 0 | pub fn set_sensitive(&mut self, val: bool) { |
149 | 0 | self.inner.set_sensitive(val); |
150 | 0 | } |
151 | | |
152 | | /// Returns `true` if the value represents sensitive data. |
153 | | /// |
154 | | /// Sensitive data could represent passwords or other data that should not |
155 | | /// be stored on disk or in memory. This setting can be used by components |
156 | | /// like caches to avoid storing the value. HPACK encoders must set the |
157 | | /// metadata field to never index when `is_sensitive` returns true. |
158 | | /// |
159 | | /// Note that sensitivity is not factored into equality or ordering. |
160 | | /// |
161 | | /// # Examples |
162 | | /// |
163 | | /// ``` |
164 | | /// # use tonic::metadata::*; |
165 | | /// let mut val = AsciiMetadataValue::from_static("my secret"); |
166 | | /// |
167 | | /// val.set_sensitive(true); |
168 | | /// assert!(val.is_sensitive()); |
169 | | /// |
170 | | /// val.set_sensitive(false); |
171 | | /// assert!(!val.is_sensitive()); |
172 | | /// ``` |
173 | | #[inline] |
174 | 0 | pub fn is_sensitive(&self) -> bool { |
175 | 0 | self.inner.is_sensitive() |
176 | 0 | } |
177 | | |
178 | | /// Converts a `MetadataValue` to a byte slice. For Binary values, the |
179 | | /// return value is base64 encoded. |
180 | | /// |
181 | | /// # Examples |
182 | | /// |
183 | | /// ``` |
184 | | /// # use tonic::metadata::*; |
185 | | /// let val = AsciiMetadataValue::from_static("hello"); |
186 | | /// assert_eq!(val.as_encoded_bytes(), b"hello"); |
187 | | /// ``` |
188 | | /// |
189 | | /// ``` |
190 | | /// # use tonic::metadata::*; |
191 | | /// let val = BinaryMetadataValue::from_bytes(b"Hello!"); |
192 | | /// assert_eq!(val.as_encoded_bytes(), b"SGVsbG8h"); |
193 | | /// ``` |
194 | | #[inline] |
195 | 0 | pub fn as_encoded_bytes(&self) -> &[u8] { |
196 | 0 | self.inner.as_bytes() |
197 | 0 | } |
198 | | |
199 | | /// Converts a HeaderValue to a MetadataValue. This method assumes that the |
200 | | /// caller has made sure that the value is of the correct Ascii or Binary |
201 | | /// value encoding. |
202 | | #[inline] |
203 | 0 | pub(crate) fn unchecked_from_header_value(value: HeaderValue) -> Self { |
204 | 0 | MetadataValue { |
205 | 0 | inner: value, |
206 | 0 | phantom: PhantomData, |
207 | 0 | } |
208 | 0 | } |
209 | | |
210 | | /// Converts a HeaderValue reference to a MetadataValue. This method assumes |
211 | | /// that the caller has made sure that the value is of the correct Ascii or |
212 | | /// Binary value encoding. |
213 | | #[inline] |
214 | 0 | pub(crate) fn unchecked_from_header_value_ref(header_value: &HeaderValue) -> &Self { |
215 | 0 | unsafe { &*(header_value as *const HeaderValue as *const Self) } |
216 | 0 | } Unexecuted instantiation: <tonic::metadata::value::MetadataValue<tonic::metadata::encoding::Ascii>>::unchecked_from_header_value_ref Unexecuted instantiation: <tonic::metadata::value::MetadataValue<tonic::metadata::encoding::Binary>>::unchecked_from_header_value_ref |
217 | | |
218 | | /// Converts a HeaderValue reference to a MetadataValue. This method assumes |
219 | | /// that the caller has made sure that the value is of the correct Ascii or |
220 | | /// Binary value encoding. |
221 | | #[inline] |
222 | 0 | pub(crate) fn unchecked_from_mut_header_value_ref(header_value: &mut HeaderValue) -> &mut Self { |
223 | 0 | unsafe { &mut *(header_value as *mut HeaderValue as *mut Self) } |
224 | 0 | } Unexecuted instantiation: <tonic::metadata::value::MetadataValue<tonic::metadata::encoding::Ascii>>::unchecked_from_mut_header_value_ref Unexecuted instantiation: <tonic::metadata::value::MetadataValue<tonic::metadata::encoding::Binary>>::unchecked_from_mut_header_value_ref |
225 | | } |
226 | | |
227 | | /// Attempt to convert a byte slice to a `MetadataValue`. |
228 | | /// |
229 | | /// For Ascii metadata values, If the argument contains invalid metadata |
230 | | /// value bytes, an error is returned. Only byte values between 32 and 255 |
231 | | /// (inclusive) are permitted, excluding byte 127 (DEL). |
232 | | /// |
233 | | /// For Binary metadata values this method cannot fail. See also the Binary |
234 | | /// only version of this method `from_bytes`. |
235 | | /// |
236 | | /// # Examples |
237 | | /// |
238 | | /// ``` |
239 | | /// # use tonic::metadata::*; |
240 | | /// let val = AsciiMetadataValue::try_from(b"hello\xfa").unwrap(); |
241 | | /// assert_eq!(val, &b"hello\xfa"[..]); |
242 | | /// ``` |
243 | | /// |
244 | | /// An invalid value |
245 | | /// |
246 | | /// ``` |
247 | | /// # use tonic::metadata::*; |
248 | | /// let val = AsciiMetadataValue::try_from(b"\n"); |
249 | | /// assert!(val.is_err()); |
250 | | /// ``` |
251 | | impl<VE: ValueEncoding> TryFrom<&[u8]> for MetadataValue<VE> { |
252 | | type Error = InvalidMetadataValueBytes; |
253 | | |
254 | | #[inline] |
255 | 0 | fn try_from(src: &[u8]) -> Result<Self, Self::Error> { |
256 | 0 | VE::from_bytes(src).map(|value| MetadataValue { |
257 | 0 | inner: value, |
258 | 0 | phantom: PhantomData, |
259 | 0 | }) |
260 | 0 | } |
261 | | } |
262 | | |
263 | | /// Attempt to convert a byte slice to a `MetadataValue`. |
264 | | /// |
265 | | /// For Ascii metadata values, If the argument contains invalid metadata |
266 | | /// value bytes, an error is returned. Only byte values between 32 and 255 |
267 | | /// (inclusive) are permitted, excluding byte 127 (DEL). |
268 | | /// |
269 | | /// For Binary metadata values this method cannot fail. See also the Binary |
270 | | /// only version of this method `from_bytes`. |
271 | | /// |
272 | | /// # Examples |
273 | | /// |
274 | | /// ``` |
275 | | /// # use tonic::metadata::*; |
276 | | /// let val = AsciiMetadataValue::try_from(b"hello\xfa").unwrap(); |
277 | | /// assert_eq!(val, &b"hello\xfa"[..]); |
278 | | /// ``` |
279 | | /// |
280 | | /// An invalid value |
281 | | /// |
282 | | /// ``` |
283 | | /// # use tonic::metadata::*; |
284 | | /// let val = AsciiMetadataValue::try_from(b"\n"); |
285 | | /// assert!(val.is_err()); |
286 | | /// ``` |
287 | | impl<VE: ValueEncoding, const N: usize> TryFrom<&[u8; N]> for MetadataValue<VE> { |
288 | | type Error = InvalidMetadataValueBytes; |
289 | | |
290 | | #[inline] |
291 | 0 | fn try_from(src: &[u8; N]) -> Result<Self, Self::Error> { |
292 | 0 | Self::try_from(src.as_ref()) |
293 | 0 | } |
294 | | } |
295 | | |
296 | | /// Attempt to convert a `Bytes` buffer to a `MetadataValue`. |
297 | | /// |
298 | | /// For `MetadataValue<Ascii>`, if the argument contains invalid metadata |
299 | | /// value bytes, an error is returned. Only byte values between 32 and 255 |
300 | | /// (inclusive) are permitted, excluding byte 127 (DEL). |
301 | | /// |
302 | | /// For `MetadataValue<Binary>`, if the argument is not valid base64, an |
303 | | /// error is returned. In use cases where the input is not base64 encoded, |
304 | | /// use `from_bytes`; if the value has to be encoded it's not possible to |
305 | | /// share the memory anyways. |
306 | | impl<VE: ValueEncoding> TryFrom<Bytes> for MetadataValue<VE> { |
307 | | type Error = InvalidMetadataValueBytes; |
308 | | |
309 | | #[inline] |
310 | 0 | fn try_from(src: Bytes) -> Result<Self, Self::Error> { |
311 | 0 | VE::from_shared(src).map(|value| MetadataValue { |
312 | 0 | inner: value, |
313 | 0 | phantom: PhantomData, |
314 | 0 | }) |
315 | 0 | } |
316 | | } |
317 | | |
318 | | /// Attempt to convert a Vec of bytes to a `MetadataValue`. |
319 | | /// |
320 | | /// For `MetadataValue<Ascii>`, if the argument contains invalid metadata |
321 | | /// value bytes, an error is returned. Only byte values between 32 and 255 |
322 | | /// (inclusive) are permitted, excluding byte 127 (DEL). |
323 | | /// |
324 | | /// For `MetadataValue<Binary>`, if the argument is not valid base64, an |
325 | | /// error is returned. In use cases where the input is not base64 encoded, |
326 | | /// use `from_bytes`; if the value has to be encoded it's not possible to |
327 | | /// share the memory anyways. |
328 | | impl<VE: ValueEncoding> TryFrom<Vec<u8>> for MetadataValue<VE> { |
329 | | type Error = InvalidMetadataValueBytes; |
330 | | |
331 | | #[inline] |
332 | 0 | fn try_from(src: Vec<u8>) -> Result<Self, Self::Error> { |
333 | 0 | Self::try_from(src.as_slice()) |
334 | 0 | } |
335 | | } |
336 | | |
337 | | /// Attempt to convert a string to a `MetadataValue<Ascii>`. |
338 | | /// |
339 | | /// If the argument contains invalid metadata value characters, an error is |
340 | | /// returned. Only visible ASCII characters (32-127) are permitted. Use |
341 | | /// `from_bytes` to create a `MetadataValue` that includes opaque octets |
342 | | /// (128-255). |
343 | | impl<'a> TryFrom<&'a str> for MetadataValue<Ascii> { |
344 | | type Error = InvalidMetadataValue; |
345 | | |
346 | | #[inline] |
347 | 0 | fn try_from(s: &'a str) -> Result<Self, Self::Error> { |
348 | 0 | s.parse() |
349 | 0 | } |
350 | | } |
351 | | |
352 | | /// Attempt to convert a string to a `MetadataValue<Ascii>`. |
353 | | /// |
354 | | /// If the argument contains invalid metadata value characters, an error is |
355 | | /// returned. Only visible ASCII characters (32-127) are permitted. Use |
356 | | /// `from_bytes` to create a `MetadataValue` that includes opaque octets |
357 | | /// (128-255). |
358 | | impl<'a> TryFrom<&'a String> for MetadataValue<Ascii> { |
359 | | type Error = InvalidMetadataValue; |
360 | | |
361 | | #[inline] |
362 | 0 | fn try_from(s: &'a String) -> Result<Self, Self::Error> { |
363 | 0 | s.parse() |
364 | 0 | } |
365 | | } |
366 | | |
367 | | /// Attempt to convert a string to a `MetadataValue<Ascii>`. |
368 | | /// |
369 | | /// If the argument contains invalid metadata value characters, an error is |
370 | | /// returned. Only visible ASCII characters (32-127) are permitted. Use |
371 | | /// `from_bytes` to create a `MetadataValue` that includes opaque octets |
372 | | /// (128-255). |
373 | | impl TryFrom<String> for MetadataValue<Ascii> { |
374 | | type Error = InvalidMetadataValue; |
375 | | |
376 | | #[inline] |
377 | 0 | fn try_from(s: String) -> Result<Self, Self::Error> { |
378 | 0 | s.parse() |
379 | 0 | } |
380 | | } |
381 | | |
382 | | impl MetadataValue<Ascii> { |
383 | | /// Converts a MetadataKey into a `MetadataValue<Ascii>`. |
384 | | /// |
385 | | /// Since every valid MetadataKey is a valid MetadataValue this is done |
386 | | /// infallibly. |
387 | | /// |
388 | | /// # Examples |
389 | | /// |
390 | | /// ``` |
391 | | /// # use tonic::metadata::*; |
392 | | /// let val = AsciiMetadataValue::from_key::<Ascii>("accept".parse().unwrap()); |
393 | | /// assert_eq!(val, AsciiMetadataValue::try_from(b"accept").unwrap()); |
394 | | /// ``` |
395 | | #[inline] |
396 | 0 | pub fn from_key<KeyVE: ValueEncoding>(key: MetadataKey<KeyVE>) -> Self { |
397 | 0 | key.into() |
398 | 0 | } |
399 | | |
400 | | /// Returns the length of `self`, in bytes. |
401 | | /// |
402 | | /// This method is not available for `MetadataValue<Binary>` because that |
403 | | /// cannot be implemented in constant time, which most people would probably |
404 | | /// expect. To get the length of `MetadataValue<Binary>`, convert it to a |
405 | | /// Bytes value and measure its length. |
406 | | /// |
407 | | /// # Examples |
408 | | /// |
409 | | /// ``` |
410 | | /// # use tonic::metadata::*; |
411 | | /// let val = AsciiMetadataValue::from_static("hello"); |
412 | | /// assert_eq!(val.len(), 5); |
413 | | /// ``` |
414 | | #[inline] |
415 | 0 | pub fn len(&self) -> usize { |
416 | 0 | self.inner.len() |
417 | 0 | } |
418 | | |
419 | | /// Yields a `&str` slice if the `MetadataValue` only contains visible ASCII |
420 | | /// chars. |
421 | | /// |
422 | | /// This function will perform a scan of the metadata value, checking all the |
423 | | /// characters. |
424 | | /// |
425 | | /// # Examples |
426 | | /// |
427 | | /// ``` |
428 | | /// # use tonic::metadata::*; |
429 | | /// let val = AsciiMetadataValue::from_static("hello"); |
430 | | /// assert_eq!(val.to_str().unwrap(), "hello"); |
431 | | /// ``` |
432 | 0 | pub fn to_str(&self) -> Result<&str, ToStrError> { |
433 | 0 | self.inner.to_str().map_err(|_| ToStrError::new()) |
434 | 0 | } |
435 | | |
436 | | /// Converts a `MetadataValue` to a byte slice. For Binary values, use |
437 | | /// `to_bytes`. |
438 | | /// |
439 | | /// # Examples |
440 | | /// |
441 | | /// ``` |
442 | | /// # use tonic::metadata::*; |
443 | | /// let val = AsciiMetadataValue::from_static("hello"); |
444 | | /// assert_eq!(val.as_bytes(), b"hello"); |
445 | | /// ``` |
446 | | #[inline] |
447 | 0 | pub fn as_bytes(&self) -> &[u8] { |
448 | 0 | self.inner.as_bytes() |
449 | 0 | } |
450 | | } |
451 | | |
452 | | impl MetadataValue<Binary> { |
453 | | /// Convert a byte slice to a `MetadataValue<Binary>`. |
454 | | /// |
455 | | /// # Examples |
456 | | /// |
457 | | /// ``` |
458 | | /// # use tonic::metadata::*; |
459 | | /// let val = BinaryMetadataValue::from_bytes(b"hello\xfa"); |
460 | | /// assert_eq!(val, &b"hello\xfa"[..]); |
461 | | /// ``` |
462 | | #[inline] |
463 | 0 | pub fn from_bytes(src: &[u8]) -> Self { |
464 | | // Only the Ascii version of try_from can fail. |
465 | 0 | Self::try_from(src).unwrap() |
466 | 0 | } |
467 | | } |
468 | | |
469 | | impl<VE: ValueEncoding> AsRef<[u8]> for MetadataValue<VE> { |
470 | | #[inline] |
471 | 0 | fn as_ref(&self) -> &[u8] { |
472 | 0 | self.inner.as_ref() |
473 | 0 | } |
474 | | } |
475 | | |
476 | | impl<VE: ValueEncoding> fmt::Debug for MetadataValue<VE> { |
477 | 0 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
478 | 0 | VE::fmt(&self.inner, f) |
479 | 0 | } |
480 | | } |
481 | | |
482 | | impl<KeyVE: ValueEncoding> From<MetadataKey<KeyVE>> for MetadataValue<Ascii> { |
483 | | #[inline] |
484 | 0 | fn from(h: MetadataKey<KeyVE>) -> MetadataValue<Ascii> { |
485 | 0 | MetadataValue { |
486 | 0 | inner: h.inner.into(), |
487 | 0 | phantom: PhantomData, |
488 | 0 | } |
489 | 0 | } |
490 | | } |
491 | | |
492 | | macro_rules! from_integers { |
493 | | ($($name:ident: $t:ident => $max_len:expr),*) => {$( |
494 | | impl From<$t> for MetadataValue<Ascii> { |
495 | 0 | fn from(num: $t) -> MetadataValue<Ascii> { |
496 | 0 | MetadataValue { |
497 | 0 | inner: HeaderValue::from(num), |
498 | 0 | phantom: PhantomData, |
499 | 0 | } |
500 | 0 | } Unexecuted instantiation: <tonic::metadata::value::MetadataValue<tonic::metadata::encoding::Ascii> as core::convert::From<u16>>::from Unexecuted instantiation: <tonic::metadata::value::MetadataValue<tonic::metadata::encoding::Ascii> as core::convert::From<i16>>::from Unexecuted instantiation: <tonic::metadata::value::MetadataValue<tonic::metadata::encoding::Ascii> as core::convert::From<u32>>::from Unexecuted instantiation: <tonic::metadata::value::MetadataValue<tonic::metadata::encoding::Ascii> as core::convert::From<i32>>::from Unexecuted instantiation: <tonic::metadata::value::MetadataValue<tonic::metadata::encoding::Ascii> as core::convert::From<u64>>::from Unexecuted instantiation: <tonic::metadata::value::MetadataValue<tonic::metadata::encoding::Ascii> as core::convert::From<i64>>::from Unexecuted instantiation: <tonic::metadata::value::MetadataValue<tonic::metadata::encoding::Ascii> as core::convert::From<usize>>::from Unexecuted instantiation: <tonic::metadata::value::MetadataValue<tonic::metadata::encoding::Ascii> as core::convert::From<isize>>::from |
501 | | } |
502 | | |
503 | | #[test] |
504 | | fn $name() { |
505 | | let n: $t = 55; |
506 | | let val = AsciiMetadataValue::from(n); |
507 | | assert_eq!(val, &n.to_string()); |
508 | | |
509 | | let n = $t::MAX; |
510 | | let val = AsciiMetadataValue::from(n); |
511 | | assert_eq!(val, &n.to_string()); |
512 | | } |
513 | | )*}; |
514 | | } |
515 | | |
516 | | from_integers! { |
517 | | // integer type => maximum decimal length |
518 | | |
519 | | // u8 purposely left off... AsciiMetadataValue::from(b'3') could be confusing |
520 | | from_u16: u16 => 5, |
521 | | from_i16: i16 => 6, |
522 | | from_u32: u32 => 10, |
523 | | from_i32: i32 => 11, |
524 | | from_u64: u64 => 20, |
525 | | from_i64: i64 => 20 |
526 | | } |
527 | | |
528 | | #[cfg(target_pointer_width = "16")] |
529 | | from_integers! { |
530 | | from_usize: usize => 5, |
531 | | from_isize: isize => 6 |
532 | | } |
533 | | |
534 | | #[cfg(target_pointer_width = "32")] |
535 | | from_integers! { |
536 | | from_usize: usize => 10, |
537 | | from_isize: isize => 11 |
538 | | } |
539 | | |
540 | | #[cfg(target_pointer_width = "64")] |
541 | | from_integers! { |
542 | | from_usize: usize => 20, |
543 | | from_isize: isize => 20 |
544 | | } |
545 | | |
546 | | #[cfg(test)] |
547 | | mod from_metadata_value_tests { |
548 | | use super::*; |
549 | | use crate::metadata::map::MetadataMap; |
550 | | |
551 | | #[test] |
552 | | fn it_can_insert_metadata_key_as_metadata_value() { |
553 | | let mut map = MetadataMap::new(); |
554 | | map.insert( |
555 | | "accept", |
556 | | MetadataKey::<Ascii>::from_bytes(b"hello-world") |
557 | | .unwrap() |
558 | | .into(), |
559 | | ); |
560 | | |
561 | | assert_eq!( |
562 | | map.get("accept").unwrap(), |
563 | | AsciiMetadataValue::try_from(b"hello-world").unwrap() |
564 | | ); |
565 | | } |
566 | | } |
567 | | |
568 | | impl FromStr for MetadataValue<Ascii> { |
569 | | type Err = InvalidMetadataValue; |
570 | | |
571 | | #[inline] |
572 | 0 | fn from_str(s: &str) -> Result<MetadataValue<Ascii>, Self::Err> { |
573 | 0 | HeaderValue::from_str(s) |
574 | 0 | .map(|value| MetadataValue { |
575 | 0 | inner: value, |
576 | 0 | phantom: PhantomData, |
577 | 0 | }) Unexecuted instantiation: <tonic::metadata::value::MetadataValue<tonic::metadata::encoding::Ascii> as core::str::traits::FromStr>::from_str::{closure#0}Unexecuted instantiation: <tonic::metadata::value::MetadataValue<tonic::metadata::encoding::Ascii> as core::str::traits::FromStr>::from_str::{closure#0} |
578 | 0 | .map_err(|_| InvalidMetadataValue::new()) Unexecuted instantiation: <tonic::metadata::value::MetadataValue<tonic::metadata::encoding::Ascii> as core::str::traits::FromStr>::from_str::{closure#1}Unexecuted instantiation: <tonic::metadata::value::MetadataValue<tonic::metadata::encoding::Ascii> as core::str::traits::FromStr>::from_str::{closure#1} |
579 | 0 | } Unexecuted instantiation: <tonic::metadata::value::MetadataValue<tonic::metadata::encoding::Ascii> as core::str::traits::FromStr>::from_str Unexecuted instantiation: <tonic::metadata::value::MetadataValue<tonic::metadata::encoding::Ascii> as core::str::traits::FromStr>::from_str |
580 | | } |
581 | | |
582 | | impl<VE: ValueEncoding> From<MetadataValue<VE>> for Bytes { |
583 | | #[inline] |
584 | 0 | fn from(value: MetadataValue<VE>) -> Bytes { |
585 | 0 | Bytes::copy_from_slice(value.inner.as_bytes()) |
586 | 0 | } |
587 | | } |
588 | | |
589 | | impl<'a, VE: ValueEncoding> From<&'a MetadataValue<VE>> for MetadataValue<VE> { |
590 | | #[inline] |
591 | 0 | fn from(t: &'a MetadataValue<VE>) -> Self { |
592 | 0 | t.clone() |
593 | 0 | } |
594 | | } |
595 | | |
596 | | // ===== ToStrError ===== |
597 | | |
598 | | impl ToStrError { |
599 | 0 | pub(crate) fn new() -> Self { |
600 | 0 | ToStrError { _priv: () } |
601 | 0 | } |
602 | | } |
603 | | |
604 | | impl fmt::Display for ToStrError { |
605 | 0 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
606 | 0 | f.write_str("failed to convert metadata to a str") |
607 | 0 | } |
608 | | } |
609 | | |
610 | | impl Error for ToStrError {} |
611 | | |
612 | | impl Hash for MetadataValue<Ascii> { |
613 | 0 | fn hash<H: Hasher>(&self, state: &mut H) { |
614 | 0 | self.inner.hash(state) |
615 | 0 | } |
616 | | } |
617 | | |
618 | | impl Hash for MetadataValue<Binary> { |
619 | 0 | fn hash<H: Hasher>(&self, state: &mut H) { |
620 | 0 | match self.to_bytes() { |
621 | 0 | Ok(b) => b.hash(state), |
622 | 0 | Err(e) => e.hash(state), |
623 | | } |
624 | 0 | } |
625 | | } |
626 | | |
627 | | // ===== PartialEq / PartialOrd ===== |
628 | | |
629 | | impl<VE: ValueEncoding> PartialEq for MetadataValue<VE> { |
630 | | #[inline] |
631 | 0 | fn eq(&self, other: &MetadataValue<VE>) -> bool { |
632 | | // Note: Different binary strings that after base64 decoding |
633 | | // will count as the same value for Binary values. Also, |
634 | | // different invalid base64 values count as equal for Binary |
635 | | // values. |
636 | 0 | VE::values_equal(&self.inner, &other.inner) |
637 | 0 | } |
638 | | } |
639 | | |
640 | | impl<VE: ValueEncoding> Eq for MetadataValue<VE> {} |
641 | | |
642 | | impl<VE: ValueEncoding> PartialOrd for MetadataValue<VE> { |
643 | | #[inline] |
644 | 0 | fn partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering> { |
645 | 0 | Some(self.cmp(other)) |
646 | 0 | } |
647 | | } |
648 | | |
649 | | impl<VE: ValueEncoding> Ord for MetadataValue<VE> { |
650 | | #[inline] |
651 | 0 | fn cmp(&self, other: &Self) -> cmp::Ordering { |
652 | 0 | self.inner.cmp(&other.inner) |
653 | 0 | } |
654 | | } |
655 | | |
656 | | impl<VE: ValueEncoding> PartialEq<str> for MetadataValue<VE> { |
657 | | #[inline] |
658 | 0 | fn eq(&self, other: &str) -> bool { |
659 | 0 | VE::equals(&self.inner, other.as_bytes()) |
660 | 0 | } |
661 | | } |
662 | | |
663 | | impl<VE: ValueEncoding> PartialEq<[u8]> for MetadataValue<VE> { |
664 | | #[inline] |
665 | 0 | fn eq(&self, other: &[u8]) -> bool { |
666 | 0 | VE::equals(&self.inner, other) |
667 | 0 | } |
668 | | } |
669 | | |
670 | | impl<VE: ValueEncoding> PartialOrd<str> for MetadataValue<VE> { |
671 | | #[inline] |
672 | 0 | fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> { |
673 | 0 | self.inner.partial_cmp(other.as_bytes()) |
674 | 0 | } |
675 | | } |
676 | | |
677 | | impl<VE: ValueEncoding> PartialOrd<[u8]> for MetadataValue<VE> { |
678 | | #[inline] |
679 | 0 | fn partial_cmp(&self, other: &[u8]) -> Option<cmp::Ordering> { |
680 | 0 | self.inner.partial_cmp(other) |
681 | 0 | } |
682 | | } |
683 | | |
684 | | impl<VE: ValueEncoding> PartialEq<MetadataValue<VE>> for str { |
685 | | #[inline] |
686 | 0 | fn eq(&self, other: &MetadataValue<VE>) -> bool { |
687 | 0 | *other == *self |
688 | 0 | } |
689 | | } |
690 | | |
691 | | impl<VE: ValueEncoding> PartialEq<MetadataValue<VE>> for [u8] { |
692 | | #[inline] |
693 | 0 | fn eq(&self, other: &MetadataValue<VE>) -> bool { |
694 | 0 | *other == *self |
695 | 0 | } |
696 | | } |
697 | | |
698 | | impl<VE: ValueEncoding> PartialOrd<MetadataValue<VE>> for str { |
699 | | #[inline] |
700 | 0 | fn partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering> { |
701 | 0 | self.as_bytes().partial_cmp(other.inner.as_bytes()) |
702 | 0 | } |
703 | | } |
704 | | |
705 | | impl<VE: ValueEncoding> PartialOrd<MetadataValue<VE>> for [u8] { |
706 | | #[inline] |
707 | 0 | fn partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering> { |
708 | 0 | self.partial_cmp(other.inner.as_bytes()) |
709 | 0 | } |
710 | | } |
711 | | |
712 | | impl<VE: ValueEncoding> PartialEq<String> for MetadataValue<VE> { |
713 | | #[inline] |
714 | 0 | fn eq(&self, other: &String) -> bool { |
715 | 0 | *self == other[..] |
716 | 0 | } |
717 | | } |
718 | | |
719 | | impl<VE: ValueEncoding> PartialOrd<String> for MetadataValue<VE> { |
720 | | #[inline] |
721 | 0 | fn partial_cmp(&self, other: &String) -> Option<cmp::Ordering> { |
722 | 0 | self.inner.partial_cmp(other.as_bytes()) |
723 | 0 | } |
724 | | } |
725 | | |
726 | | impl<VE: ValueEncoding> PartialEq<MetadataValue<VE>> for String { |
727 | | #[inline] |
728 | 0 | fn eq(&self, other: &MetadataValue<VE>) -> bool { |
729 | 0 | *other == *self |
730 | 0 | } |
731 | | } |
732 | | |
733 | | impl<VE: ValueEncoding> PartialOrd<MetadataValue<VE>> for String { |
734 | | #[inline] |
735 | 0 | fn partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering> { |
736 | 0 | self.as_bytes().partial_cmp(other.inner.as_bytes()) |
737 | 0 | } |
738 | | } |
739 | | |
740 | | impl<VE: ValueEncoding> PartialEq<MetadataValue<VE>> for &MetadataValue<VE> { |
741 | | #[inline] |
742 | 0 | fn eq(&self, other: &MetadataValue<VE>) -> bool { |
743 | 0 | **self == *other |
744 | 0 | } |
745 | | } |
746 | | |
747 | | impl<VE: ValueEncoding> PartialOrd<MetadataValue<VE>> for &MetadataValue<VE> { |
748 | | #[inline] |
749 | 0 | fn partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering> { |
750 | 0 | (**self).partial_cmp(other) |
751 | 0 | } |
752 | | } |
753 | | |
754 | | impl<'a, VE: ValueEncoding, T: ?Sized> PartialEq<&'a T> for MetadataValue<VE> |
755 | | where |
756 | | MetadataValue<VE>: PartialEq<T>, |
757 | | { |
758 | | #[inline] |
759 | 0 | fn eq(&self, other: &&'a T) -> bool { |
760 | 0 | *self == **other |
761 | 0 | } |
762 | | } |
763 | | |
764 | | impl<'a, VE: ValueEncoding, T: ?Sized> PartialOrd<&'a T> for MetadataValue<VE> |
765 | | where |
766 | | MetadataValue<VE>: PartialOrd<T>, |
767 | | { |
768 | | #[inline] |
769 | 0 | fn partial_cmp(&self, other: &&'a T) -> Option<cmp::Ordering> { |
770 | 0 | self.partial_cmp(*other) |
771 | 0 | } |
772 | | } |
773 | | |
774 | | impl<VE: ValueEncoding> PartialEq<MetadataValue<VE>> for &str { |
775 | | #[inline] |
776 | 0 | fn eq(&self, other: &MetadataValue<VE>) -> bool { |
777 | 0 | *other == *self |
778 | 0 | } |
779 | | } |
780 | | |
781 | | impl<VE: ValueEncoding> PartialOrd<MetadataValue<VE>> for &str { |
782 | | #[inline] |
783 | 0 | fn partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering> { |
784 | 0 | self.as_bytes().partial_cmp(other.inner.as_bytes()) |
785 | 0 | } |
786 | | } |
787 | | |
788 | | #[test] |
789 | | fn test_debug() { |
790 | | let cases = &[ |
791 | | ("hello", "\"hello\""), |
792 | | ("hello \"world\"", "\"hello \\\"world\\\"\""), |
793 | | ("\u{7FFF}hello", "\"\\xe7\\xbf\\xbfhello\""), |
794 | | ]; |
795 | | |
796 | | for &(value, expected) in cases { |
797 | | let val = AsciiMetadataValue::try_from(value.as_bytes()).unwrap(); |
798 | | let actual = format!("{:?}", val); |
799 | | assert_eq!(expected, actual); |
800 | | } |
801 | | |
802 | | let mut sensitive = AsciiMetadataValue::from_static("password"); |
803 | | sensitive.set_sensitive(true); |
804 | | assert_eq!("Sensitive", format!("{:?}", sensitive)); |
805 | | } |
806 | | |
807 | | #[test] |
808 | | fn test_is_empty() { |
809 | | fn from_str<VE: ValueEncoding>(s: &str) -> MetadataValue<VE> { |
810 | | MetadataValue::<VE>::unchecked_from_header_value(s.parse().unwrap()) |
811 | | } |
812 | | |
813 | | assert!(from_str::<Ascii>("").is_empty()); |
814 | | assert!(from_str::<Binary>("").is_empty()); |
815 | | assert!(!from_str::<Ascii>("a").is_empty()); |
816 | | assert!(!from_str::<Binary>("a").is_empty()); |
817 | | assert!(!from_str::<Ascii>("=").is_empty()); |
818 | | assert!(from_str::<Binary>("=").is_empty()); |
819 | | assert!(!from_str::<Ascii>("===").is_empty()); |
820 | | assert!(from_str::<Binary>("===").is_empty()); |
821 | | assert!(!from_str::<Ascii>("=====").is_empty()); |
822 | | assert!(from_str::<Binary>("=====").is_empty()); |
823 | | } |
824 | | |
825 | | #[test] |
826 | | fn test_from_shared_base64_encodes() { |
827 | | let value = BinaryMetadataValue::try_from(Bytes::from_static(b"Hello")).unwrap(); |
828 | | assert_eq!(value.as_encoded_bytes(), b"SGVsbG8"); |
829 | | } |
830 | | |
831 | | #[test] |
832 | | fn test_value_eq_value() { |
833 | | type Bmv = BinaryMetadataValue; |
834 | | type Amv = AsciiMetadataValue; |
835 | | |
836 | | assert_eq!(Amv::from_static("abc"), Amv::from_static("abc")); |
837 | | assert_ne!(Amv::from_static("abc"), Amv::from_static("ABC")); |
838 | | |
839 | | assert_eq!(Bmv::from_bytes(b"abc"), Bmv::from_bytes(b"abc")); |
840 | | assert_ne!(Bmv::from_bytes(b"abc"), Bmv::from_bytes(b"ABC")); |
841 | | |
842 | | // Padding is ignored. |
843 | | assert_eq!( |
844 | | Bmv::from_static("SGVsbG8hIQ=="), |
845 | | Bmv::from_static("SGVsbG8hIQ") |
846 | | ); |
847 | | // Invalid values are all just invalid from this point of view. |
848 | | unsafe { |
849 | | assert_eq!( |
850 | | Bmv::from_shared_unchecked(Bytes::from_static(b"..{}")), |
851 | | Bmv::from_shared_unchecked(Bytes::from_static(b"{}..")) |
852 | | ); |
853 | | } |
854 | | } |
855 | | |
856 | | #[test] |
857 | | fn test_value_eq_str() { |
858 | | type Bmv = BinaryMetadataValue; |
859 | | type Amv = AsciiMetadataValue; |
860 | | |
861 | | assert_eq!(Amv::from_static("abc"), "abc"); |
862 | | assert_ne!(Amv::from_static("abc"), "ABC"); |
863 | | assert_eq!("abc", Amv::from_static("abc")); |
864 | | assert_ne!("ABC", Amv::from_static("abc")); |
865 | | |
866 | | assert_eq!(Bmv::from_bytes(b"abc"), "abc"); |
867 | | assert_ne!(Bmv::from_bytes(b"abc"), "ABC"); |
868 | | assert_eq!("abc", Bmv::from_bytes(b"abc")); |
869 | | assert_ne!("ABC", Bmv::from_bytes(b"abc")); |
870 | | |
871 | | // Padding is ignored. |
872 | | assert_eq!(Bmv::from_static("SGVsbG8hIQ=="), "Hello!!"); |
873 | | assert_eq!("Hello!!", Bmv::from_static("SGVsbG8hIQ==")); |
874 | | } |
875 | | |
876 | | #[test] |
877 | | fn test_value_eq_bytes() { |
878 | | type Bmv = BinaryMetadataValue; |
879 | | type Amv = AsciiMetadataValue; |
880 | | |
881 | | assert_eq!(Amv::from_static("abc"), "abc".as_bytes()); |
882 | | assert_ne!(Amv::from_static("abc"), "ABC".as_bytes()); |
883 | | assert_eq!(*"abc".as_bytes(), Amv::from_static("abc")); |
884 | | assert_ne!(*"ABC".as_bytes(), Amv::from_static("abc")); |
885 | | |
886 | | assert_eq!(*"abc".as_bytes(), Bmv::from_bytes(b"abc")); |
887 | | assert_ne!(*"ABC".as_bytes(), Bmv::from_bytes(b"abc")); |
888 | | |
889 | | // Padding is ignored. |
890 | | assert_eq!(Bmv::from_static("SGVsbG8hIQ=="), "Hello!!".as_bytes()); |
891 | | assert_eq!(*"Hello!!".as_bytes(), Bmv::from_static("SGVsbG8hIQ==")); |
892 | | } |
893 | | |
894 | | #[test] |
895 | | fn test_ascii_value_hash() { |
896 | | use std::collections::hash_map::DefaultHasher; |
897 | | type Amv = AsciiMetadataValue; |
898 | | |
899 | | fn hash(value: Amv) -> u64 { |
900 | | let mut hasher = DefaultHasher::new(); |
901 | | value.hash(&mut hasher); |
902 | | hasher.finish() |
903 | | } |
904 | | |
905 | | let value1 = Amv::from_static("abc"); |
906 | | let value2 = Amv::from_static("abc"); |
907 | | assert_eq!(value1, value2); |
908 | | assert_eq!(hash(value1), hash(value2)); |
909 | | |
910 | | let value1 = Amv::from_static("abc"); |
911 | | let value2 = Amv::from_static("xyz"); |
912 | | |
913 | | assert_ne!(value1, value2); |
914 | | assert_ne!(hash(value1), hash(value2)); |
915 | | } |
916 | | |
917 | | #[test] |
918 | | fn test_valid_binary_value_hash() { |
919 | | use std::collections::hash_map::DefaultHasher; |
920 | | type Bmv = BinaryMetadataValue; |
921 | | |
922 | | fn hash(value: Bmv) -> u64 { |
923 | | let mut hasher = DefaultHasher::new(); |
924 | | value.hash(&mut hasher); |
925 | | hasher.finish() |
926 | | } |
927 | | |
928 | | let value1 = Bmv::from_bytes(b"abc"); |
929 | | let value2 = Bmv::from_bytes(b"abc"); |
930 | | assert_eq!(value1, value2); |
931 | | assert_eq!(hash(value1), hash(value2)); |
932 | | |
933 | | let value1 = Bmv::from_bytes(b"abc"); |
934 | | let value2 = Bmv::from_bytes(b"xyz"); |
935 | | assert_ne!(value1, value2); |
936 | | assert_ne!(hash(value1), hash(value2)); |
937 | | } |
938 | | |
939 | | #[test] |
940 | | fn test_invalid_binary_value_hash() { |
941 | | use std::collections::hash_map::DefaultHasher; |
942 | | type Bmv = BinaryMetadataValue; |
943 | | |
944 | | fn hash(value: Bmv) -> u64 { |
945 | | let mut hasher = DefaultHasher::new(); |
946 | | value.hash(&mut hasher); |
947 | | hasher.finish() |
948 | | } |
949 | | |
950 | | unsafe { |
951 | | let value1 = Bmv::from_shared_unchecked(Bytes::from_static(b"..{}")); |
952 | | let value2 = Bmv::from_shared_unchecked(Bytes::from_static(b"{}..")); |
953 | | assert_eq!(value1, value2); |
954 | | assert_eq!(hash(value1), hash(value2)); |
955 | | } |
956 | | |
957 | | unsafe { |
958 | | let valid = Bmv::from_bytes(b"abc"); |
959 | | let invalid = Bmv::from_shared_unchecked(Bytes::from_static(b"{}..")); |
960 | | assert_ne!(valid, invalid); |
961 | | assert_ne!(hash(valid), hash(invalid)); |
962 | | } |
963 | | } |