xref: /tonic/tonic/src/metadata/value.rs (revision b129320a)
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]
from_static(src: &'static str) -> Self71     pub fn from_static(src: &'static str) -> Self {
72         MetadataValue {
73             inner: VE::from_static(src),
74             phantom: PhantomData,
75         }
76     }
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]
from_shared_unchecked(src: Bytes) -> Self87     pub unsafe fn from_shared_unchecked(src: Bytes) -> Self {
88         MetadataValue {
89             inner: HeaderValue::from_maybe_shared_unchecked(src),
90             phantom: PhantomData,
91         }
92     }
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]
is_empty(&self) -> bool107     pub fn is_empty(&self) -> bool {
108         VE::is_empty(self.inner.as_bytes())
109     }
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]
to_bytes(&self) -> Result<Bytes, InvalidMetadataValueBytes>129     pub fn to_bytes(&self) -> Result<Bytes, InvalidMetadataValueBytes> {
130         VE::decode(self.inner.as_bytes())
131     }
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]
set_sensitive(&mut self, val: bool)148     pub fn set_sensitive(&mut self, val: bool) {
149         self.inner.set_sensitive(val);
150     }
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]
is_sensitive(&self) -> bool174     pub fn is_sensitive(&self) -> bool {
175         self.inner.is_sensitive()
176     }
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]
as_encoded_bytes(&self) -> &[u8]195     pub fn as_encoded_bytes(&self) -> &[u8] {
196         self.inner.as_bytes()
197     }
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]
unchecked_from_header_value(value: HeaderValue) -> Self203     pub(crate) fn unchecked_from_header_value(value: HeaderValue) -> Self {
204         MetadataValue {
205             inner: value,
206             phantom: PhantomData,
207         }
208     }
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]
unchecked_from_header_value_ref(header_value: &HeaderValue) -> &Self214     pub(crate) fn unchecked_from_header_value_ref(header_value: &HeaderValue) -> &Self {
215         unsafe { &*(header_value as *const HeaderValue as *const Self) }
216     }
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]
unchecked_from_mut_header_value_ref(header_value: &mut HeaderValue) -> &mut Self222     pub(crate) fn unchecked_from_mut_header_value_ref(header_value: &mut HeaderValue) -> &mut Self {
223         unsafe { &mut *(header_value as *mut HeaderValue as *mut Self) }
224     }
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]
try_from(src: &[u8]) -> Result<Self, Self::Error>255     fn try_from(src: &[u8]) -> Result<Self, Self::Error> {
256         VE::from_bytes(src).map(|value| MetadataValue {
257             inner: value,
258             phantom: PhantomData,
259         })
260     }
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]
try_from(src: &[u8; N]) -> Result<Self, Self::Error>291     fn try_from(src: &[u8; N]) -> Result<Self, Self::Error> {
292         Self::try_from(src.as_ref())
293     }
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]
try_from(src: Bytes) -> Result<Self, Self::Error>310     fn try_from(src: Bytes) -> Result<Self, Self::Error> {
311         VE::from_shared(src).map(|value| MetadataValue {
312             inner: value,
313             phantom: PhantomData,
314         })
315     }
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]
try_from(src: Vec<u8>) -> Result<Self, Self::Error>332     fn try_from(src: Vec<u8>) -> Result<Self, Self::Error> {
333         Self::try_from(src.as_slice())
334     }
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]
try_from(s: &'a str) -> Result<Self, Self::Error>347     fn try_from(s: &'a str) -> Result<Self, Self::Error> {
348         s.parse()
349     }
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]
try_from(s: &'a String) -> Result<Self, Self::Error>362     fn try_from(s: &'a String) -> Result<Self, Self::Error> {
363         s.parse()
364     }
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]
try_from(s: String) -> Result<Self, Self::Error>377     fn try_from(s: String) -> Result<Self, Self::Error> {
378         s.parse()
379     }
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]
from_key<KeyVE: ValueEncoding>(key: MetadataKey<KeyVE>) -> Self396     pub fn from_key<KeyVE: ValueEncoding>(key: MetadataKey<KeyVE>) -> Self {
397         key.into()
398     }
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]
len(&self) -> usize415     pub fn len(&self) -> usize {
416         self.inner.len()
417     }
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     /// ```
to_str(&self) -> Result<&str, ToStrError>432     pub fn to_str(&self) -> Result<&str, ToStrError> {
433         self.inner.to_str().map_err(|_| ToStrError::new())
434     }
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]
as_bytes(&self) -> &[u8]447     pub fn as_bytes(&self) -> &[u8] {
448         self.inner.as_bytes()
449     }
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]
from_bytes(src: &[u8]) -> Self463     pub fn from_bytes(src: &[u8]) -> Self {
464         // Only the Ascii version of try_from can fail.
465         Self::try_from(src).unwrap()
466     }
467 }
468 
469 impl<VE: ValueEncoding> AsRef<[u8]> for MetadataValue<VE> {
470     #[inline]
as_ref(&self) -> &[u8]471     fn as_ref(&self) -> &[u8] {
472         self.inner.as_ref()
473     }
474 }
475 
476 impl<VE: ValueEncoding> fmt::Debug for MetadataValue<VE> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result477     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
478         VE::fmt(&self.inner, f)
479     }
480 }
481 
482 impl<KeyVE: ValueEncoding> From<MetadataKey<KeyVE>> for MetadataValue<Ascii> {
483     #[inline]
from(h: MetadataKey<KeyVE>) -> MetadataValue<Ascii>484     fn from(h: MetadataKey<KeyVE>) -> MetadataValue<Ascii> {
485         MetadataValue {
486             inner: h.inner.into(),
487             phantom: PhantomData,
488         }
489     }
490 }
491 
492 macro_rules! from_integers {
493     ($($name:ident: $t:ident => $max_len:expr),*) => {$(
494         impl From<$t> for MetadataValue<Ascii> {
495             fn from(num: $t) -> MetadataValue<Ascii> {
496                 MetadataValue {
497                     inner: HeaderValue::from(num),
498                     phantom: PhantomData,
499                 }
500             }
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]
it_can_insert_metadata_key_as_metadata_value()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]
from_str(s: &str) -> Result<MetadataValue<Ascii>, Self::Err>572     fn from_str(s: &str) -> Result<MetadataValue<Ascii>, Self::Err> {
573         HeaderValue::from_str(s)
574             .map(|value| MetadataValue {
575                 inner: value,
576                 phantom: PhantomData,
577             })
578             .map_err(|_| InvalidMetadataValue::new())
579     }
580 }
581 
582 impl<VE: ValueEncoding> From<MetadataValue<VE>> for Bytes {
583     #[inline]
from(value: MetadataValue<VE>) -> Bytes584     fn from(value: MetadataValue<VE>) -> Bytes {
585         Bytes::copy_from_slice(value.inner.as_bytes())
586     }
587 }
588 
589 impl<'a, VE: ValueEncoding> From<&'a MetadataValue<VE>> for MetadataValue<VE> {
590     #[inline]
from(t: &'a MetadataValue<VE>) -> Self591     fn from(t: &'a MetadataValue<VE>) -> Self {
592         t.clone()
593     }
594 }
595 
596 // ===== ToStrError =====
597 
598 impl ToStrError {
new() -> Self599     pub(crate) fn new() -> Self {
600         ToStrError { _priv: () }
601     }
602 }
603 
604 impl fmt::Display for ToStrError {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result605     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
606         f.write_str("failed to convert metadata to a str")
607     }
608 }
609 
610 impl Error for ToStrError {}
611 
612 impl Hash for MetadataValue<Ascii> {
hash<H: Hasher>(&self, state: &mut H)613     fn hash<H: Hasher>(&self, state: &mut H) {
614         self.inner.hash(state)
615     }
616 }
617 
618 impl Hash for MetadataValue<Binary> {
hash<H: Hasher>(&self, state: &mut H)619     fn hash<H: Hasher>(&self, state: &mut H) {
620         match self.to_bytes() {
621             Ok(b) => b.hash(state),
622             Err(e) => e.hash(state),
623         }
624     }
625 }
626 
627 // ===== PartialEq / PartialOrd =====
628 
629 impl<VE: ValueEncoding> PartialEq for MetadataValue<VE> {
630     #[inline]
eq(&self, other: &MetadataValue<VE>) -> bool631     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         VE::values_equal(&self.inner, &other.inner)
637     }
638 }
639 
640 impl<VE: ValueEncoding> Eq for MetadataValue<VE> {}
641 
642 impl<VE: ValueEncoding> PartialOrd for MetadataValue<VE> {
643     #[inline]
partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering>644     fn partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering> {
645         Some(self.cmp(other))
646     }
647 }
648 
649 impl<VE: ValueEncoding> Ord for MetadataValue<VE> {
650     #[inline]
cmp(&self, other: &Self) -> cmp::Ordering651     fn cmp(&self, other: &Self) -> cmp::Ordering {
652         self.inner.cmp(&other.inner)
653     }
654 }
655 
656 impl<VE: ValueEncoding> PartialEq<str> for MetadataValue<VE> {
657     #[inline]
eq(&self, other: &str) -> bool658     fn eq(&self, other: &str) -> bool {
659         VE::equals(&self.inner, other.as_bytes())
660     }
661 }
662 
663 impl<VE: ValueEncoding> PartialEq<[u8]> for MetadataValue<VE> {
664     #[inline]
eq(&self, other: &[u8]) -> bool665     fn eq(&self, other: &[u8]) -> bool {
666         VE::equals(&self.inner, other)
667     }
668 }
669 
670 impl<VE: ValueEncoding> PartialOrd<str> for MetadataValue<VE> {
671     #[inline]
partial_cmp(&self, other: &str) -> Option<cmp::Ordering>672     fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> {
673         self.inner.partial_cmp(other.as_bytes())
674     }
675 }
676 
677 impl<VE: ValueEncoding> PartialOrd<[u8]> for MetadataValue<VE> {
678     #[inline]
partial_cmp(&self, other: &[u8]) -> Option<cmp::Ordering>679     fn partial_cmp(&self, other: &[u8]) -> Option<cmp::Ordering> {
680         self.inner.partial_cmp(other)
681     }
682 }
683 
684 impl<VE: ValueEncoding> PartialEq<MetadataValue<VE>> for str {
685     #[inline]
eq(&self, other: &MetadataValue<VE>) -> bool686     fn eq(&self, other: &MetadataValue<VE>) -> bool {
687         *other == *self
688     }
689 }
690 
691 impl<VE: ValueEncoding> PartialEq<MetadataValue<VE>> for [u8] {
692     #[inline]
eq(&self, other: &MetadataValue<VE>) -> bool693     fn eq(&self, other: &MetadataValue<VE>) -> bool {
694         *other == *self
695     }
696 }
697 
698 impl<VE: ValueEncoding> PartialOrd<MetadataValue<VE>> for str {
699     #[inline]
partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering>700     fn partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering> {
701         self.as_bytes().partial_cmp(other.inner.as_bytes())
702     }
703 }
704 
705 impl<VE: ValueEncoding> PartialOrd<MetadataValue<VE>> for [u8] {
706     #[inline]
partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering>707     fn partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering> {
708         self.partial_cmp(other.inner.as_bytes())
709     }
710 }
711 
712 impl<VE: ValueEncoding> PartialEq<String> for MetadataValue<VE> {
713     #[inline]
eq(&self, other: &String) -> bool714     fn eq(&self, other: &String) -> bool {
715         *self == other[..]
716     }
717 }
718 
719 impl<VE: ValueEncoding> PartialOrd<String> for MetadataValue<VE> {
720     #[inline]
partial_cmp(&self, other: &String) -> Option<cmp::Ordering>721     fn partial_cmp(&self, other: &String) -> Option<cmp::Ordering> {
722         self.inner.partial_cmp(other.as_bytes())
723     }
724 }
725 
726 impl<VE: ValueEncoding> PartialEq<MetadataValue<VE>> for String {
727     #[inline]
eq(&self, other: &MetadataValue<VE>) -> bool728     fn eq(&self, other: &MetadataValue<VE>) -> bool {
729         *other == *self
730     }
731 }
732 
733 impl<VE: ValueEncoding> PartialOrd<MetadataValue<VE>> for String {
734     #[inline]
partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering>735     fn partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering> {
736         self.as_bytes().partial_cmp(other.inner.as_bytes())
737     }
738 }
739 
740 impl<VE: ValueEncoding> PartialEq<MetadataValue<VE>> for &MetadataValue<VE> {
741     #[inline]
eq(&self, other: &MetadataValue<VE>) -> bool742     fn eq(&self, other: &MetadataValue<VE>) -> bool {
743         **self == *other
744     }
745 }
746 
747 impl<VE: ValueEncoding> PartialOrd<MetadataValue<VE>> for &MetadataValue<VE> {
748     #[inline]
partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering>749     fn partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering> {
750         (**self).partial_cmp(other)
751     }
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]
eq(&self, other: &&'a T) -> bool759     fn eq(&self, other: &&'a T) -> bool {
760         *self == **other
761     }
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]
partial_cmp(&self, other: &&'a T) -> Option<cmp::Ordering>769     fn partial_cmp(&self, other: &&'a T) -> Option<cmp::Ordering> {
770         self.partial_cmp(*other)
771     }
772 }
773 
774 impl<VE: ValueEncoding> PartialEq<MetadataValue<VE>> for &str {
775     #[inline]
eq(&self, other: &MetadataValue<VE>) -> bool776     fn eq(&self, other: &MetadataValue<VE>) -> bool {
777         *other == *self
778     }
779 }
780 
781 impl<VE: ValueEncoding> PartialOrd<MetadataValue<VE>> for &str {
782     #[inline]
partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering>783     fn partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering> {
784         self.as_bytes().partial_cmp(other.inner.as_bytes())
785     }
786 }
787 
788 #[test]
test_debug()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]
test_is_empty()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]
test_from_shared_base64_encodes()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]
test_value_eq_value()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]
test_value_eq_str()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]
test_value_eq_bytes()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]
test_ascii_value_hash()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]
test_valid_binary_value_hash()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]
test_invalid_binary_value_hash()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 }
964