Skip to main content

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        unsafe {
89            MetadataValue {
90                inner: HeaderValue::from_maybe_shared_unchecked(src),
91                phantom: PhantomData,
92            }
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]
109    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]
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]
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]
176    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]
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]
205    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]
216    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]
224    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/// ```
253impl<VE: ValueEncoding> TryFrom<&[u8]> for MetadataValue<VE> {
254    type Error = InvalidMetadataValueBytes;
255
256    #[inline]
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/// ```
289impl<VE: ValueEncoding, const N: usize> TryFrom<&[u8; N]> for MetadataValue<VE> {
290    type Error = InvalidMetadataValueBytes;
291
292    #[inline]
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.
308impl<VE: ValueEncoding> TryFrom<Bytes> for MetadataValue<VE> {
309    type Error = InvalidMetadataValueBytes;
310
311    #[inline]
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.
330impl<VE: ValueEncoding> TryFrom<Vec<u8>> for MetadataValue<VE> {
331    type Error = InvalidMetadataValueBytes;
332
333    #[inline]
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).
345impl<'a> TryFrom<&'a str> for MetadataValue<Ascii> {
346    type Error = InvalidMetadataValue;
347
348    #[inline]
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).
360impl<'a> TryFrom<&'a String> for MetadataValue<Ascii> {
361    type Error = InvalidMetadataValue;
362
363    #[inline]
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).
375impl TryFrom<String> for MetadataValue<Ascii> {
376    type Error = InvalidMetadataValue;
377
378    #[inline]
379    fn try_from(s: String) -> Result<Self, Self::Error> {
380        s.parse()
381    }
382}
383
384impl MetadataValue<Ascii> {
385    /// Converts a MetadataKey into a `MetadataValue<Ascii>`.
386    ///
387    /// Since every valid MetadataKey is a valid MetadataValue this is done
388    /// infallibly.
389    ///
390    /// # Examples
391    ///
392    /// ```
393    /// # use tonic::metadata::*;
394    /// let val = AsciiMetadataValue::from_key::<Ascii>("accept".parse().unwrap());
395    /// assert_eq!(val, AsciiMetadataValue::try_from(b"accept").unwrap());
396    /// ```
397    #[inline]
398    pub fn from_key<KeyVE: ValueEncoding>(key: MetadataKey<KeyVE>) -> Self {
399        key.into()
400    }
401
402    /// Returns the length of `self`, in bytes.
403    ///
404    /// This method is not available for `MetadataValue<Binary>` because that
405    /// cannot be implemented in constant time, which most people would probably
406    /// expect. To get the length of `MetadataValue<Binary>`, convert it to a
407    /// Bytes value and measure its length.
408    ///
409    /// # Examples
410    ///
411    /// ```
412    /// # use tonic::metadata::*;
413    /// let val = AsciiMetadataValue::from_static("hello");
414    /// assert_eq!(val.len(), 5);
415    /// ```
416    #[inline]
417    pub fn len(&self) -> usize {
418        self.inner.len()
419    }
420
421    /// Yields a `&str` slice if the `MetadataValue` only contains visible ASCII
422    /// chars.
423    ///
424    /// This function will perform a scan of the metadata value, checking all the
425    /// characters.
426    ///
427    /// # Examples
428    ///
429    /// ```
430    /// # use tonic::metadata::*;
431    /// let val = AsciiMetadataValue::from_static("hello");
432    /// assert_eq!(val.to_str().unwrap(), "hello");
433    /// ```
434    pub fn to_str(&self) -> Result<&str, ToStrError> {
435        self.inner.to_str().map_err(|_| ToStrError::new())
436    }
437
438    /// Converts a `MetadataValue` to a byte slice. For Binary values, use
439    /// `to_bytes`.
440    ///
441    /// # Examples
442    ///
443    /// ```
444    /// # use tonic::metadata::*;
445    /// let val = AsciiMetadataValue::from_static("hello");
446    /// assert_eq!(val.as_bytes(), b"hello");
447    /// ```
448    #[inline]
449    pub fn as_bytes(&self) -> &[u8] {
450        self.inner.as_bytes()
451    }
452}
453
454impl MetadataValue<Binary> {
455    /// Convert a byte slice to a `MetadataValue<Binary>`.
456    ///
457    /// # Examples
458    ///
459    /// ```
460    /// # use tonic::metadata::*;
461    /// let val = BinaryMetadataValue::from_bytes(b"hello\xfa");
462    /// assert_eq!(val, &b"hello\xfa"[..]);
463    /// ```
464    #[inline]
465    pub fn from_bytes(src: &[u8]) -> Self {
466        // Only the Ascii version of try_from can fail.
467        Self::try_from(src).unwrap()
468    }
469}
470
471impl<VE: ValueEncoding> AsRef<[u8]> for MetadataValue<VE> {
472    #[inline]
473    fn as_ref(&self) -> &[u8] {
474        self.inner.as_ref()
475    }
476}
477
478impl<VE: ValueEncoding> fmt::Debug for MetadataValue<VE> {
479    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
480        VE::fmt(&self.inner, f)
481    }
482}
483
484impl<KeyVE: ValueEncoding> From<MetadataKey<KeyVE>> for MetadataValue<Ascii> {
485    #[inline]
486    fn from(h: MetadataKey<KeyVE>) -> MetadataValue<Ascii> {
487        MetadataValue {
488            inner: h.inner.into(),
489            phantom: PhantomData,
490        }
491    }
492}
493
494macro_rules! from_integers {
495    ($($name:ident: $t:ident => $max_len:expr),*) => {$(
496        impl From<$t> for MetadataValue<Ascii> {
497            fn from(num: $t) -> MetadataValue<Ascii> {
498                MetadataValue {
499                    inner: HeaderValue::from(num),
500                    phantom: PhantomData,
501                }
502            }
503        }
504
505        #[test]
506        fn $name() {
507            let n: $t = 55;
508            let val = AsciiMetadataValue::from(n);
509            assert_eq!(val, &n.to_string());
510
511            let n = $t::MAX;
512            let val = AsciiMetadataValue::from(n);
513            assert_eq!(val, &n.to_string());
514        }
515    )*};
516}
517
518from_integers! {
519    // integer type => maximum decimal length
520
521    // u8 purposely left off... AsciiMetadataValue::from(b'3') could be confusing
522    from_u16: u16 => 5,
523    from_i16: i16 => 6,
524    from_u32: u32 => 10,
525    from_i32: i32 => 11,
526    from_u64: u64 => 20,
527    from_i64: i64 => 20
528}
529
530#[cfg(target_pointer_width = "16")]
531from_integers! {
532    from_usize: usize => 5,
533    from_isize: isize => 6
534}
535
536#[cfg(target_pointer_width = "32")]
537from_integers! {
538    from_usize: usize => 10,
539    from_isize: isize => 11
540}
541
542#[cfg(target_pointer_width = "64")]
543from_integers! {
544    from_usize: usize => 20,
545    from_isize: isize => 20
546}
547
548#[cfg(test)]
549mod from_metadata_value_tests {
550    use super::*;
551    use crate::metadata::map::MetadataMap;
552
553    #[test]
554    fn it_can_insert_metadata_key_as_metadata_value() {
555        let mut map = MetadataMap::new();
556        map.insert(
557            "accept",
558            MetadataKey::<Ascii>::from_bytes(b"hello-world")
559                .unwrap()
560                .into(),
561        );
562
563        assert_eq!(
564            map.get("accept").unwrap(),
565            AsciiMetadataValue::try_from(b"hello-world").unwrap()
566        );
567    }
568}
569
570impl FromStr for MetadataValue<Ascii> {
571    type Err = InvalidMetadataValue;
572
573    #[inline]
574    fn from_str(s: &str) -> Result<MetadataValue<Ascii>, Self::Err> {
575        HeaderValue::from_str(s)
576            .map(|value| MetadataValue {
577                inner: value,
578                phantom: PhantomData,
579            })
580            .map_err(|_| InvalidMetadataValue::new())
581    }
582}
583
584impl<VE: ValueEncoding> From<MetadataValue<VE>> for Bytes {
585    #[inline]
586    fn from(value: MetadataValue<VE>) -> Bytes {
587        Bytes::copy_from_slice(value.inner.as_bytes())
588    }
589}
590
591impl<'a, VE: ValueEncoding> From<&'a MetadataValue<VE>> for MetadataValue<VE> {
592    #[inline]
593    fn from(t: &'a MetadataValue<VE>) -> Self {
594        t.clone()
595    }
596}
597
598// ===== ToStrError =====
599
600impl ToStrError {
601    pub(crate) fn new() -> Self {
602        ToStrError { _priv: () }
603    }
604}
605
606impl fmt::Display for ToStrError {
607    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
608        f.write_str("failed to convert metadata to a str")
609    }
610}
611
612impl Error for ToStrError {}
613
614impl Hash for MetadataValue<Ascii> {
615    fn hash<H: Hasher>(&self, state: &mut H) {
616        self.inner.hash(state)
617    }
618}
619
620impl Hash for MetadataValue<Binary> {
621    fn hash<H: Hasher>(&self, state: &mut H) {
622        match self.to_bytes() {
623            Ok(b) => b.hash(state),
624            Err(e) => e.hash(state),
625        }
626    }
627}
628
629// ===== PartialEq / PartialOrd =====
630
631impl<VE: ValueEncoding> PartialEq for MetadataValue<VE> {
632    #[inline]
633    fn eq(&self, other: &MetadataValue<VE>) -> bool {
634        // Note: Different binary strings that after base64 decoding
635        // will count as the same value for Binary values. Also,
636        // different invalid base64 values count as equal for Binary
637        // values.
638        VE::values_equal(&self.inner, &other.inner)
639    }
640}
641
642impl<VE: ValueEncoding> Eq for MetadataValue<VE> {}
643
644impl<VE: ValueEncoding> PartialOrd for MetadataValue<VE> {
645    #[inline]
646    fn partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering> {
647        Some(self.cmp(other))
648    }
649}
650
651impl<VE: ValueEncoding> Ord for MetadataValue<VE> {
652    #[inline]
653    fn cmp(&self, other: &Self) -> cmp::Ordering {
654        self.inner.cmp(&other.inner)
655    }
656}
657
658impl<VE: ValueEncoding> PartialEq<str> for MetadataValue<VE> {
659    #[inline]
660    fn eq(&self, other: &str) -> bool {
661        VE::equals(&self.inner, other.as_bytes())
662    }
663}
664
665impl<VE: ValueEncoding> PartialEq<[u8]> for MetadataValue<VE> {
666    #[inline]
667    fn eq(&self, other: &[u8]) -> bool {
668        VE::equals(&self.inner, other)
669    }
670}
671
672impl<VE: ValueEncoding> PartialOrd<str> for MetadataValue<VE> {
673    #[inline]
674    fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> {
675        self.inner.partial_cmp(other.as_bytes())
676    }
677}
678
679impl<VE: ValueEncoding> PartialOrd<[u8]> for MetadataValue<VE> {
680    #[inline]
681    fn partial_cmp(&self, other: &[u8]) -> Option<cmp::Ordering> {
682        self.inner.partial_cmp(other)
683    }
684}
685
686impl<VE: ValueEncoding> PartialEq<MetadataValue<VE>> for str {
687    #[inline]
688    fn eq(&self, other: &MetadataValue<VE>) -> bool {
689        *other == *self
690    }
691}
692
693impl<VE: ValueEncoding> PartialEq<MetadataValue<VE>> for [u8] {
694    #[inline]
695    fn eq(&self, other: &MetadataValue<VE>) -> bool {
696        *other == *self
697    }
698}
699
700impl<VE: ValueEncoding> PartialOrd<MetadataValue<VE>> for str {
701    #[inline]
702    fn partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering> {
703        self.as_bytes().partial_cmp(other.inner.as_bytes())
704    }
705}
706
707impl<VE: ValueEncoding> PartialOrd<MetadataValue<VE>> for [u8] {
708    #[inline]
709    fn partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering> {
710        self.partial_cmp(other.inner.as_bytes())
711    }
712}
713
714impl<VE: ValueEncoding> PartialEq<String> for MetadataValue<VE> {
715    #[inline]
716    fn eq(&self, other: &String) -> bool {
717        *self == other[..]
718    }
719}
720
721impl<VE: ValueEncoding> PartialOrd<String> for MetadataValue<VE> {
722    #[inline]
723    fn partial_cmp(&self, other: &String) -> Option<cmp::Ordering> {
724        self.inner.partial_cmp(other.as_bytes())
725    }
726}
727
728impl<VE: ValueEncoding> PartialEq<MetadataValue<VE>> for String {
729    #[inline]
730    fn eq(&self, other: &MetadataValue<VE>) -> bool {
731        *other == *self
732    }
733}
734
735impl<VE: ValueEncoding> PartialOrd<MetadataValue<VE>> for String {
736    #[inline]
737    fn partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering> {
738        self.as_bytes().partial_cmp(other.inner.as_bytes())
739    }
740}
741
742impl<VE: ValueEncoding> PartialEq<MetadataValue<VE>> for &MetadataValue<VE> {
743    #[inline]
744    fn eq(&self, other: &MetadataValue<VE>) -> bool {
745        **self == *other
746    }
747}
748
749impl<VE: ValueEncoding> PartialOrd<MetadataValue<VE>> for &MetadataValue<VE> {
750    #[inline]
751    fn partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering> {
752        (**self).partial_cmp(other)
753    }
754}
755
756impl<'a, VE: ValueEncoding, T: ?Sized> PartialEq<&'a T> for MetadataValue<VE>
757where
758    MetadataValue<VE>: PartialEq<T>,
759{
760    #[inline]
761    fn eq(&self, other: &&'a T) -> bool {
762        *self == **other
763    }
764}
765
766impl<'a, VE: ValueEncoding, T: ?Sized> PartialOrd<&'a T> for MetadataValue<VE>
767where
768    MetadataValue<VE>: PartialOrd<T>,
769{
770    #[inline]
771    fn partial_cmp(&self, other: &&'a T) -> Option<cmp::Ordering> {
772        self.partial_cmp(*other)
773    }
774}
775
776impl<VE: ValueEncoding> PartialEq<MetadataValue<VE>> for &str {
777    #[inline]
778    fn eq(&self, other: &MetadataValue<VE>) -> bool {
779        *other == *self
780    }
781}
782
783impl<VE: ValueEncoding> PartialOrd<MetadataValue<VE>> for &str {
784    #[inline]
785    fn partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering> {
786        self.as_bytes().partial_cmp(other.inner.as_bytes())
787    }
788}
789
790#[test]
791fn test_debug() {
792    let cases = &[
793        ("hello", "\"hello\""),
794        ("hello \"world\"", "\"hello \\\"world\\\"\""),
795        ("\u{7FFF}hello", "\"\\xe7\\xbf\\xbfhello\""),
796    ];
797
798    for &(value, expected) in cases {
799        let val = AsciiMetadataValue::try_from(value.as_bytes()).unwrap();
800        let actual = format!("{val:?}");
801        assert_eq!(expected, actual);
802    }
803
804    let mut sensitive = AsciiMetadataValue::from_static("password");
805    sensitive.set_sensitive(true);
806    assert_eq!("Sensitive", format!("{sensitive:?}"));
807}
808
809#[test]
810fn test_is_empty() {
811    fn from_str<VE: ValueEncoding>(s: &str) -> MetadataValue<VE> {
812        MetadataValue::<VE>::unchecked_from_header_value(s.parse().unwrap())
813    }
814
815    assert!(from_str::<Ascii>("").is_empty());
816    assert!(from_str::<Binary>("").is_empty());
817    assert!(!from_str::<Ascii>("a").is_empty());
818    assert!(!from_str::<Binary>("a").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    assert!(!from_str::<Ascii>("=====").is_empty());
824    assert!(from_str::<Binary>("=====").is_empty());
825}
826
827#[test]
828fn test_from_shared_base64_encodes() {
829    let value = BinaryMetadataValue::try_from(Bytes::from_static(b"Hello")).unwrap();
830    assert_eq!(value.as_encoded_bytes(), b"SGVsbG8");
831}
832
833#[test]
834fn test_value_eq_value() {
835    type Bmv = BinaryMetadataValue;
836    type Amv = AsciiMetadataValue;
837
838    assert_eq!(Amv::from_static("abc"), Amv::from_static("abc"));
839    assert_ne!(Amv::from_static("abc"), Amv::from_static("ABC"));
840
841    assert_eq!(Bmv::from_bytes(b"abc"), Bmv::from_bytes(b"abc"));
842    assert_ne!(Bmv::from_bytes(b"abc"), Bmv::from_bytes(b"ABC"));
843
844    // Padding is ignored.
845    assert_eq!(
846        Bmv::from_static("SGVsbG8hIQ=="),
847        Bmv::from_static("SGVsbG8hIQ")
848    );
849    // Invalid values are all just invalid from this point of view.
850    unsafe {
851        assert_eq!(
852            Bmv::from_shared_unchecked(Bytes::from_static(b"..{}")),
853            Bmv::from_shared_unchecked(Bytes::from_static(b"{}.."))
854        );
855    }
856}
857
858#[test]
859fn test_value_eq_str() {
860    type Bmv = BinaryMetadataValue;
861    type Amv = AsciiMetadataValue;
862
863    assert_eq!(Amv::from_static("abc"), "abc");
864    assert_ne!(Amv::from_static("abc"), "ABC");
865    assert_eq!("abc", Amv::from_static("abc"));
866    assert_ne!("ABC", Amv::from_static("abc"));
867
868    assert_eq!(Bmv::from_bytes(b"abc"), "abc");
869    assert_ne!(Bmv::from_bytes(b"abc"), "ABC");
870    assert_eq!("abc", Bmv::from_bytes(b"abc"));
871    assert_ne!("ABC", Bmv::from_bytes(b"abc"));
872
873    // Padding is ignored.
874    assert_eq!(Bmv::from_static("SGVsbG8hIQ=="), "Hello!!");
875    assert_eq!("Hello!!", Bmv::from_static("SGVsbG8hIQ=="));
876}
877
878#[test]
879fn test_value_eq_bytes() {
880    type Bmv = BinaryMetadataValue;
881    type Amv = AsciiMetadataValue;
882
883    assert_eq!(Amv::from_static("abc"), "abc".as_bytes());
884    assert_ne!(Amv::from_static("abc"), "ABC".as_bytes());
885    assert_eq!(*"abc".as_bytes(), Amv::from_static("abc"));
886    assert_ne!(*"ABC".as_bytes(), Amv::from_static("abc"));
887
888    assert_eq!(*"abc".as_bytes(), Bmv::from_bytes(b"abc"));
889    assert_ne!(*"ABC".as_bytes(), Bmv::from_bytes(b"abc"));
890
891    // Padding is ignored.
892    assert_eq!(Bmv::from_static("SGVsbG8hIQ=="), "Hello!!".as_bytes());
893    assert_eq!(*"Hello!!".as_bytes(), Bmv::from_static("SGVsbG8hIQ=="));
894}
895
896#[test]
897fn test_ascii_value_hash() {
898    use std::collections::hash_map::DefaultHasher;
899    type Amv = AsciiMetadataValue;
900
901    fn hash(value: Amv) -> u64 {
902        let mut hasher = DefaultHasher::new();
903        value.hash(&mut hasher);
904        hasher.finish()
905    }
906
907    let value1 = Amv::from_static("abc");
908    let value2 = Amv::from_static("abc");
909    assert_eq!(value1, value2);
910    assert_eq!(hash(value1), hash(value2));
911
912    let value1 = Amv::from_static("abc");
913    let value2 = Amv::from_static("xyz");
914
915    assert_ne!(value1, value2);
916    assert_ne!(hash(value1), hash(value2));
917}
918
919#[test]
920fn test_valid_binary_value_hash() {
921    use std::collections::hash_map::DefaultHasher;
922    type Bmv = BinaryMetadataValue;
923
924    fn hash(value: Bmv) -> u64 {
925        let mut hasher = DefaultHasher::new();
926        value.hash(&mut hasher);
927        hasher.finish()
928    }
929
930    let value1 = Bmv::from_bytes(b"abc");
931    let value2 = Bmv::from_bytes(b"abc");
932    assert_eq!(value1, value2);
933    assert_eq!(hash(value1), hash(value2));
934
935    let value1 = Bmv::from_bytes(b"abc");
936    let value2 = Bmv::from_bytes(b"xyz");
937    assert_ne!(value1, value2);
938    assert_ne!(hash(value1), hash(value2));
939}
940
941#[test]
942fn test_invalid_binary_value_hash() {
943    use std::collections::hash_map::DefaultHasher;
944    type Bmv = BinaryMetadataValue;
945
946    fn hash(value: Bmv) -> u64 {
947        let mut hasher = DefaultHasher::new();
948        value.hash(&mut hasher);
949        hasher.finish()
950    }
951
952    unsafe {
953        let value1 = Bmv::from_shared_unchecked(Bytes::from_static(b"..{}"));
954        let value2 = Bmv::from_shared_unchecked(Bytes::from_static(b"{}.."));
955        assert_eq!(value1, value2);
956        assert_eq!(hash(value1), hash(value2));
957    }
958
959    unsafe {
960        let valid = Bmv::from_bytes(b"abc");
961        let invalid = Bmv::from_shared_unchecked(Bytes::from_static(b"{}.."));
962        assert_ne!(valid, invalid);
963        assert_ne!(hash(valid), hash(invalid));
964    }
965}