tonic_arcanyx_fork/metadata/
value.rs

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