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