tonic/metadata/
value.rs

1use super::encoding::{
2    Ascii, Binary, InvalidMetadataValue, InvalidMetadataValueBytes, ValueEncoding,
3};
4use super::key::MetadataKey;
5
6use bytes::Bytes;
7use http::header::HeaderValue;
8use std::error::Error;
9use std::hash::{Hash, Hasher};
10use std::marker::PhantomData;
11use std::str::FromStr;
12use 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)]
22pub 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)]
34pub struct ToStrError {
35    _priv: (),
36}
37
38/// An ascii metadata value.
39pub type AsciiMetadataValue = MetadataValue<Ascii>;
40/// A binary metadata value.
41pub type BinaryMetadataValue = MetadataValue<Binary>;
42
43impl<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    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]
87    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]
107    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]
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]
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]
174    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]
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]
203    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]
214    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]
222    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/// ```
251impl<'a, VE: ValueEncoding> TryFrom<&'a [u8]> for MetadataValue<VE> {
252    type Error = InvalidMetadataValueBytes;
253
254    #[inline]
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/// ```
287impl<'a, VE: ValueEncoding, const N: usize> TryFrom<&'a [u8; N]> for MetadataValue<VE> {
288    type Error = InvalidMetadataValueBytes;
289
290    #[inline]
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.
306impl<VE: ValueEncoding> TryFrom<Bytes> for MetadataValue<VE> {
307    type Error = InvalidMetadataValueBytes;
308
309    #[inline]
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.
328impl<VE: ValueEncoding> TryFrom<Vec<u8>> for MetadataValue<VE> {
329    type Error = InvalidMetadataValueBytes;
330
331    #[inline]
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).
343impl<'a> TryFrom<&'a str> for MetadataValue<Ascii> {
344    type Error = InvalidMetadataValue;
345
346    #[inline]
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).
358impl<'a> TryFrom<&'a String> for MetadataValue<Ascii> {
359    type Error = InvalidMetadataValue;
360
361    #[inline]
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).
373impl TryFrom<String> for MetadataValue<Ascii> {
374    type Error = InvalidMetadataValue;
375
376    #[inline]
377    fn try_from(s: String) -> Result<Self, Self::Error> {
378        s.parse()
379    }
380}
381
382impl 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    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]
415    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    /// ```
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]
447    pub fn as_bytes(&self) -> &[u8] {
448        self.inner.as_bytes()
449    }
450}
451
452impl 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    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
469impl<VE: ValueEncoding> AsRef<[u8]> for MetadataValue<VE> {
470    #[inline]
471    fn as_ref(&self) -> &[u8] {
472        self.inner.as_ref()
473    }
474}
475
476impl<VE: ValueEncoding> fmt::Debug for MetadataValue<VE> {
477    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
478        VE::fmt(&self.inner, f)
479    }
480}
481
482impl<KeyVE: ValueEncoding> From<MetadataKey<KeyVE>> for MetadataValue<Ascii> {
483    #[inline]
484    fn from(h: MetadataKey<KeyVE>) -> MetadataValue<Ascii> {
485        MetadataValue {
486            inner: h.inner.into(),
487            phantom: PhantomData,
488        }
489    }
490}
491
492macro_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
516from_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")]
529from_integers! {
530    from_usize: usize => 5,
531    from_isize: isize => 6
532}
533
534#[cfg(target_pointer_width = "32")]
535from_integers! {
536    from_usize: usize => 10,
537    from_isize: isize => 11
538}
539
540#[cfg(target_pointer_width = "64")]
541from_integers! {
542    from_usize: usize => 20,
543    from_isize: isize => 20
544}
545
546#[cfg(test)]
547mod 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
568impl FromStr for MetadataValue<Ascii> {
569    type Err = InvalidMetadataValue;
570
571    #[inline]
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
582impl<VE: ValueEncoding> From<MetadataValue<VE>> for Bytes {
583    #[inline]
584    fn from(value: MetadataValue<VE>) -> Bytes {
585        Bytes::copy_from_slice(value.inner.as_bytes())
586    }
587}
588
589impl<'a, VE: ValueEncoding> From<&'a MetadataValue<VE>> for MetadataValue<VE> {
590    #[inline]
591    fn from(t: &'a MetadataValue<VE>) -> Self {
592        t.clone()
593    }
594}
595
596// ===== ToStrError =====
597
598impl ToStrError {
599    pub(crate) fn new() -> Self {
600        ToStrError { _priv: () }
601    }
602}
603
604impl fmt::Display for ToStrError {
605    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
606        f.write_str("failed to convert metadata to a str")
607    }
608}
609
610impl Error for ToStrError {}
611
612impl Hash for MetadataValue<Ascii> {
613    fn hash<H: Hasher>(&self, state: &mut H) {
614        self.inner.hash(state)
615    }
616}
617
618impl Hash for MetadataValue<Binary> {
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
629impl<VE: ValueEncoding> PartialEq for MetadataValue<VE> {
630    #[inline]
631    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
640impl<VE: ValueEncoding> Eq for MetadataValue<VE> {}
641
642impl<VE: ValueEncoding> PartialOrd for MetadataValue<VE> {
643    #[inline]
644    fn partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering> {
645        Some(self.cmp(other))
646    }
647}
648
649impl<VE: ValueEncoding> Ord for MetadataValue<VE> {
650    #[inline]
651    fn cmp(&self, other: &Self) -> cmp::Ordering {
652        self.inner.cmp(&other.inner)
653    }
654}
655
656impl<VE: ValueEncoding> PartialEq<str> for MetadataValue<VE> {
657    #[inline]
658    fn eq(&self, other: &str) -> bool {
659        VE::equals(&self.inner, other.as_bytes())
660    }
661}
662
663impl<VE: ValueEncoding> PartialEq<[u8]> for MetadataValue<VE> {
664    #[inline]
665    fn eq(&self, other: &[u8]) -> bool {
666        VE::equals(&self.inner, other)
667    }
668}
669
670impl<VE: ValueEncoding> PartialOrd<str> for MetadataValue<VE> {
671    #[inline]
672    fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> {
673        self.inner.partial_cmp(other.as_bytes())
674    }
675}
676
677impl<VE: ValueEncoding> PartialOrd<[u8]> for MetadataValue<VE> {
678    #[inline]
679    fn partial_cmp(&self, other: &[u8]) -> Option<cmp::Ordering> {
680        self.inner.partial_cmp(other)
681    }
682}
683
684impl<VE: ValueEncoding> PartialEq<MetadataValue<VE>> for str {
685    #[inline]
686    fn eq(&self, other: &MetadataValue<VE>) -> bool {
687        *other == *self
688    }
689}
690
691impl<VE: ValueEncoding> PartialEq<MetadataValue<VE>> for [u8] {
692    #[inline]
693    fn eq(&self, other: &MetadataValue<VE>) -> bool {
694        *other == *self
695    }
696}
697
698impl<VE: ValueEncoding> PartialOrd<MetadataValue<VE>> for str {
699    #[inline]
700    fn partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering> {
701        self.as_bytes().partial_cmp(other.inner.as_bytes())
702    }
703}
704
705impl<VE: ValueEncoding> PartialOrd<MetadataValue<VE>> for [u8] {
706    #[inline]
707    fn partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering> {
708        self.partial_cmp(other.inner.as_bytes())
709    }
710}
711
712impl<VE: ValueEncoding> PartialEq<String> for MetadataValue<VE> {
713    #[inline]
714    fn eq(&self, other: &String) -> bool {
715        *self == other[..]
716    }
717}
718
719impl<VE: ValueEncoding> PartialOrd<String> for MetadataValue<VE> {
720    #[inline]
721    fn partial_cmp(&self, other: &String) -> Option<cmp::Ordering> {
722        self.inner.partial_cmp(other.as_bytes())
723    }
724}
725
726impl<VE: ValueEncoding> PartialEq<MetadataValue<VE>> for String {
727    #[inline]
728    fn eq(&self, other: &MetadataValue<VE>) -> bool {
729        *other == *self
730    }
731}
732
733impl<VE: ValueEncoding> PartialOrd<MetadataValue<VE>> for String {
734    #[inline]
735    fn partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering> {
736        self.as_bytes().partial_cmp(other.inner.as_bytes())
737    }
738}
739
740impl<'a, VE: ValueEncoding> PartialEq<MetadataValue<VE>> for &'a MetadataValue<VE> {
741    #[inline]
742    fn eq(&self, other: &MetadataValue<VE>) -> bool {
743        **self == *other
744    }
745}
746
747impl<'a, VE: ValueEncoding> PartialOrd<MetadataValue<VE>> for &'a MetadataValue<VE> {
748    #[inline]
749    fn partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering> {
750        (**self).partial_cmp(other)
751    }
752}
753
754impl<'a, VE: ValueEncoding, T: ?Sized> PartialEq<&'a T> for MetadataValue<VE>
755where
756    MetadataValue<VE>: PartialEq<T>,
757{
758    #[inline]
759    fn eq(&self, other: &&'a T) -> bool {
760        *self == **other
761    }
762}
763
764impl<'a, VE: ValueEncoding, T: ?Sized> PartialOrd<&'a T> for MetadataValue<VE>
765where
766    MetadataValue<VE>: PartialOrd<T>,
767{
768    #[inline]
769    fn partial_cmp(&self, other: &&'a T) -> Option<cmp::Ordering> {
770        self.partial_cmp(*other)
771    }
772}
773
774impl<'a, VE: ValueEncoding> PartialEq<MetadataValue<VE>> for &'a str {
775    #[inline]
776    fn eq(&self, other: &MetadataValue<VE>) -> bool {
777        *other == *self
778    }
779}
780
781impl<'a, VE: ValueEncoding> PartialOrd<MetadataValue<VE>> for &'a str {
782    #[inline]
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]
789fn 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]
808fn 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]
826fn 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]
832fn 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]
857fn 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]
877fn 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]
895fn 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]
918fn 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]
940fn 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}