1use std::{
4 cmp,
5 error::Error,
6 fmt,
7 hash::{Hash, Hasher},
8 marker::PhantomData,
9 str::FromStr,
10};
11
12use bytes::Bytes;
13use http::header::HeaderValue;
14
15use super::{
16 encoding::{Ascii, Binary, InvalidMetadataValue, InvalidMetadataValueBytes, ValueEncoding},
17 key::MetadataKey,
18};
19
20#[derive(Clone)]
27#[repr(transparent)]
28pub struct MetadataValue<VE: ValueEncoding> {
29 pub(crate) inner: HeaderValue,
32 phantom: PhantomData<VE>,
33}
34
35#[derive(Debug)]
40pub struct ToStrError {
41 _priv: (),
42}
43
44pub type AsciiMetadataValue = MetadataValue<Ascii>;
46pub type BinaryMetadataValue = MetadataValue<Binary>;
48
49impl<VE: ValueEncoding> MetadataValue<VE> {
50 #[inline]
77 pub fn from_static(src: &'static str) -> Self {
78 Self {
79 inner: VE::from_static(src),
80 phantom: PhantomData,
81 }
82 }
83
84 #[inline]
112 pub fn try_from_bytes(src: &[u8]) -> Result<Self, InvalidMetadataValueBytes> {
113 VE::from_bytes(src).map(|value| Self {
114 inner: value,
115 phantom: PhantomData,
116 })
117 }
118
119 #[inline]
133 pub fn from_shared(src: Bytes) -> Result<Self, InvalidMetadataValueBytes> {
134 VE::from_shared(src).map(|value| Self {
135 inner: value,
136 phantom: PhantomData,
137 })
138 }
139
140 #[inline]
148 pub unsafe fn from_shared_unchecked(src: Bytes) -> Self {
149 Self {
150 inner: unsafe { HeaderValue::from_maybe_shared_unchecked(src) },
151 phantom: PhantomData,
152 }
153 }
154
155 #[inline]
168 pub fn is_empty(&self) -> bool {
169 VE::is_empty(self.inner.as_bytes())
170 }
171
172 #[inline]
190 pub fn to_bytes(&self) -> Result<Bytes, InvalidMetadataValueBytes> {
191 VE::decode(self.inner.as_bytes())
192 }
193
194 #[inline]
209 pub fn set_sensitive(&mut self, val: bool) {
210 self.inner.set_sensitive(val);
211 }
212
213 #[inline]
235 pub fn is_sensitive(&self) -> bool {
236 self.inner.is_sensitive()
237 }
238
239 #[inline]
256 pub fn as_encoded_bytes(&self) -> &[u8] {
257 self.inner.as_bytes()
258 }
259
260 #[inline]
264 pub(crate) fn unchecked_from_header_value(value: HeaderValue) -> Self {
265 Self {
266 inner: value,
267 phantom: PhantomData,
268 }
269 }
270
271 #[inline]
275 pub(crate) fn unchecked_from_header_value_ref(header_value: &HeaderValue) -> &Self {
276 unsafe { &*(header_value as *const HeaderValue as *const Self) }
278 }
279
280 #[inline]
284 pub(crate) fn unchecked_from_mut_header_value_ref(header_value: &mut HeaderValue) -> &mut Self {
285 unsafe { &mut *(header_value as *mut HeaderValue as *mut Self) }
287 }
288}
289
290#[allow(clippy::len_without_is_empty)]
292impl MetadataValue<Ascii> {
293 #[allow(clippy::should_implement_trait)]
319 #[inline]
320 pub fn from_str(src: &str) -> Result<Self, InvalidMetadataValue> {
321 HeaderValue::from_str(src)
322 .map(|value| Self {
323 inner: value,
324 phantom: PhantomData,
325 })
326 .map_err(|_| InvalidMetadataValue::new())
327 }
328
329 #[inline]
342 pub fn from_key<KeyVE: ValueEncoding>(key: MetadataKey<KeyVE>) -> Self {
343 key.into()
344 }
345
346 #[inline]
361 pub fn len(&self) -> usize {
362 self.inner.len()
363 }
364
365 pub fn to_str(&self) -> Result<&str, ToStrError> {
379 self.inner.to_str().map_err(|_| ToStrError::new())
380 }
381
382 #[inline]
393 pub fn as_bytes(&self) -> &[u8] {
394 self.inner.as_bytes()
395 }
396}
397
398impl MetadataValue<Binary> {
399 #[inline]
409 pub fn from_bytes(src: &[u8]) -> Self {
410 Self::try_from_bytes(src).unwrap()
412 }
413}
414
415impl<VE: ValueEncoding> AsRef<[u8]> for MetadataValue<VE> {
416 #[inline]
417 fn as_ref(&self) -> &[u8] {
418 self.inner.as_ref()
419 }
420}
421
422impl<VE: ValueEncoding> fmt::Debug for MetadataValue<VE> {
423 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
424 VE::fmt(&self.inner, f)
425 }
426}
427
428impl<KeyVE: ValueEncoding> From<MetadataKey<KeyVE>> for MetadataValue<Ascii> {
429 #[inline]
430 fn from(h: MetadataKey<KeyVE>) -> Self {
431 Self {
432 inner: h.inner.into(),
433 phantom: PhantomData,
434 }
435 }
436}
437
438macro_rules! from_integers {
439 ($($name:ident: $t:ident => $max_len:expr),*) => {$(
440 impl From<$t> for MetadataValue<Ascii> {
441 fn from(num: $t) -> MetadataValue<Ascii> {
442 MetadataValue {
443 inner: HeaderValue::from(num),
444 phantom: PhantomData,
445 }
446 }
447 }
448
449 #[test]
450 fn $name() {
451 let n: $t = 55;
452 let val = AsciiMetadataValue::from(n);
453 assert_eq!(val, &n.to_string());
454
455 let n = $t::MAX;
456 let val = AsciiMetadataValue::from(n);
457 assert_eq!(val, &n.to_string());
458 }
459 )*};
460}
461
462from_integers! {
463 from_u16: u16 => 5,
467 from_i16: i16 => 6,
468 from_u32: u32 => 10,
469 from_i32: i32 => 11,
470 from_u64: u64 => 20,
471 from_i64: i64 => 20
472}
473
474#[cfg(target_pointer_width = "16")]
475from_integers! {
476 from_usize: usize => 5,
477 from_isize: isize => 6
478}
479
480#[cfg(target_pointer_width = "32")]
481from_integers! {
482 from_usize: usize => 10,
483 from_isize: isize => 11
484}
485
486#[cfg(target_pointer_width = "64")]
487from_integers! {
488 from_usize: usize => 20,
489 from_isize: isize => 20
490}
491
492#[cfg(test)]
493mod from_metadata_value_tests {
494 use super::*;
495 use crate::metadata::MetadataMap;
496
497 #[test]
498 fn it_can_insert_metadata_key_as_metadata_value() {
499 let mut map = MetadataMap::new();
500 map.insert(
501 "accept",
502 MetadataKey::<Ascii>::from_bytes(b"hello-world")
503 .unwrap()
504 .into(),
505 );
506
507 assert_eq!(
508 map.get("accept").unwrap(),
509 AsciiMetadataValue::try_from_bytes(b"hello-world").unwrap()
510 );
511 }
512}
513
514impl FromStr for MetadataValue<Ascii> {
515 type Err = InvalidMetadataValue;
516
517 #[inline]
518 fn from_str(s: &str) -> Result<Self, Self::Err> {
519 Self::from_str(s)
520 }
521}
522
523impl<VE: ValueEncoding> From<MetadataValue<VE>> for Bytes {
524 #[inline]
525 fn from(value: MetadataValue<VE>) -> Bytes {
526 Bytes::copy_from_slice(value.inner.as_bytes())
527 }
528}
529
530impl<'a, VE: ValueEncoding> From<&'a MetadataValue<VE>> for MetadataValue<VE> {
531 #[inline]
532 fn from(t: &'a MetadataValue<VE>) -> Self {
533 t.clone()
534 }
535}
536
537impl ToStrError {
540 pub(crate) fn new() -> Self {
541 Self { _priv: () }
542 }
543}
544
545impl fmt::Display for ToStrError {
546 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
547 f.write_str("failed to convert metadata to a str")
548 }
549}
550
551impl Error for ToStrError {}
552
553impl Hash for MetadataValue<Ascii> {
554 fn hash<H: Hasher>(&self, state: &mut H) {
555 self.inner.hash(state)
556 }
557}
558
559impl Hash for MetadataValue<Binary> {
560 fn hash<H: Hasher>(&self, state: &mut H) {
561 match self.to_bytes() {
562 Ok(b) => b.hash(state),
563 Err(e) => e.hash(state),
564 }
565 }
566}
567
568impl<VE: ValueEncoding> PartialEq for MetadataValue<VE> {
571 #[inline]
572 fn eq(&self, other: &MetadataValue<VE>) -> bool {
573 VE::values_equal(&self.inner, &other.inner)
578 }
579}
580
581impl<VE: ValueEncoding> Eq for MetadataValue<VE> {}
582
583impl<VE: ValueEncoding> PartialOrd for MetadataValue<VE> {
584 #[inline]
585 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
586 Some(self.cmp(other))
587 }
588}
589
590impl<VE: ValueEncoding> Ord for MetadataValue<VE> {
591 #[inline]
592 fn cmp(&self, other: &Self) -> cmp::Ordering {
593 self.inner.cmp(&other.inner)
594 }
595}
596
597impl<VE: ValueEncoding> PartialEq<str> for MetadataValue<VE> {
598 #[inline]
599 fn eq(&self, other: &str) -> bool {
600 VE::equals(&self.inner, other.as_bytes())
601 }
602}
603
604impl<VE: ValueEncoding> PartialEq<[u8]> for MetadataValue<VE> {
605 #[inline]
606 fn eq(&self, other: &[u8]) -> bool {
607 VE::equals(&self.inner, other)
608 }
609}
610
611impl<VE: ValueEncoding> PartialOrd<str> for MetadataValue<VE> {
612 #[inline]
613 fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> {
614 self.inner.partial_cmp(other.as_bytes())
615 }
616}
617
618impl<VE: ValueEncoding> PartialOrd<[u8]> for MetadataValue<VE> {
619 #[inline]
620 fn partial_cmp(&self, other: &[u8]) -> Option<cmp::Ordering> {
621 self.inner.partial_cmp(other)
622 }
623}
624
625impl<VE: ValueEncoding> PartialEq<MetadataValue<VE>> for str {
626 #[inline]
627 fn eq(&self, other: &MetadataValue<VE>) -> bool {
628 *other == *self
629 }
630}
631
632impl<VE: ValueEncoding> PartialEq<MetadataValue<VE>> for [u8] {
633 #[inline]
634 fn eq(&self, other: &MetadataValue<VE>) -> bool {
635 *other == *self
636 }
637}
638
639impl<VE: ValueEncoding> PartialOrd<MetadataValue<VE>> for str {
640 #[inline]
641 fn partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering> {
642 self.as_bytes().partial_cmp(other.inner.as_bytes())
643 }
644}
645
646impl<VE: ValueEncoding> PartialOrd<MetadataValue<VE>> for [u8] {
647 #[inline]
648 fn partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering> {
649 self.partial_cmp(other.inner.as_bytes())
650 }
651}
652
653impl<VE: ValueEncoding> PartialEq<String> for MetadataValue<VE> {
654 #[inline]
655 fn eq(&self, other: &String) -> bool {
656 *self == other[..]
657 }
658}
659
660impl<VE: ValueEncoding> PartialOrd<String> for MetadataValue<VE> {
661 #[inline]
662 fn partial_cmp(&self, other: &String) -> Option<cmp::Ordering> {
663 self.inner.partial_cmp(other.as_bytes())
664 }
665}
666
667impl<VE: ValueEncoding> PartialEq<MetadataValue<VE>> for String {
668 #[inline]
669 fn eq(&self, other: &MetadataValue<VE>) -> bool {
670 *other == *self
671 }
672}
673
674impl<VE: ValueEncoding> PartialOrd<MetadataValue<VE>> for String {
675 #[inline]
676 fn partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering> {
677 self.as_bytes().partial_cmp(other.inner.as_bytes())
678 }
679}
680
681impl<VE: ValueEncoding> PartialEq<MetadataValue<VE>> for &MetadataValue<VE> {
682 #[inline]
683 fn eq(&self, other: &MetadataValue<VE>) -> bool {
684 **self == *other
685 }
686}
687
688impl<VE: ValueEncoding> PartialOrd<MetadataValue<VE>> for &MetadataValue<VE> {
689 #[inline]
690 fn partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering> {
691 (**self).partial_cmp(other)
692 }
693}
694
695impl<'a, VE: ValueEncoding, T: ?Sized> PartialEq<&'a T> for MetadataValue<VE>
696where
697 MetadataValue<VE>: PartialEq<T>,
698{
699 #[inline]
700 fn eq(&self, other: &&'a T) -> bool {
701 *self == **other
702 }
703}
704
705impl<'a, VE: ValueEncoding, T: ?Sized> PartialOrd<&'a T> for MetadataValue<VE>
706where
707 MetadataValue<VE>: PartialOrd<T>,
708{
709 #[inline]
710 fn partial_cmp(&self, other: &&'a T) -> Option<cmp::Ordering> {
711 self.partial_cmp(*other)
712 }
713}
714
715impl<VE: ValueEncoding> PartialEq<MetadataValue<VE>> for &str {
716 #[inline]
717 fn eq(&self, other: &MetadataValue<VE>) -> bool {
718 *other == *self
719 }
720}
721
722impl<VE: ValueEncoding> PartialOrd<MetadataValue<VE>> for &str {
723 #[inline]
724 fn partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering> {
725 self.as_bytes().partial_cmp(other.inner.as_bytes())
726 }
727}
728
729#[test]
730fn test_debug() {
731 let cases = &[
732 ("hello", "\"hello\""),
733 ("hello \"world\"", "\"hello \\\"world\\\"\""),
734 ("\u{7FFF}hello", "\"\\xe7\\xbf\\xbfhello\""),
735 ];
736
737 for &(value, expected) in cases {
738 let val = AsciiMetadataValue::try_from_bytes(value.as_bytes()).unwrap();
739 let actual = format!("{val:?}");
740 assert_eq!(expected, actual);
741 }
742
743 let mut sensitive = AsciiMetadataValue::from_static("password");
744 sensitive.set_sensitive(true);
745 assert_eq!("Sensitive", format!("{sensitive:?}"));
746}
747
748#[test]
749fn test_is_empty() {
750 fn from_str<VE: ValueEncoding>(s: &str) -> MetadataValue<VE> {
751 MetadataValue::<VE>::unchecked_from_header_value(s.parse().unwrap())
752 }
753
754 assert!(from_str::<Ascii>("").is_empty());
755 assert!(from_str::<Binary>("").is_empty());
756 assert!(!from_str::<Ascii>("a").is_empty());
757 assert!(!from_str::<Binary>("a").is_empty());
758 assert!(!from_str::<Ascii>("=").is_empty());
759 assert!(from_str::<Binary>("=").is_empty());
760 assert!(!from_str::<Ascii>("===").is_empty());
761 assert!(from_str::<Binary>("===").is_empty());
762 assert!(!from_str::<Ascii>("=====").is_empty());
763 assert!(from_str::<Binary>("=====").is_empty());
764}
765
766#[test]
767fn test_from_shared_base64_encodes() {
768 let value = BinaryMetadataValue::from_shared(Bytes::from_static(b"Hello")).unwrap();
769 assert_eq!(value.as_encoded_bytes(), b"SGVsbG8");
770}
771
772#[test]
773fn test_value_eq_value() {
774 type Bmv = BinaryMetadataValue;
775 type Amv = AsciiMetadataValue;
776
777 assert_eq!(Amv::from_static("abc"), Amv::from_static("abc"));
778 assert_ne!(Amv::from_static("abc"), Amv::from_static("ABC"));
779
780 assert_eq!(Bmv::from_bytes(b"abc"), Bmv::from_bytes(b"abc"));
781 assert_ne!(Bmv::from_bytes(b"abc"), Bmv::from_bytes(b"ABC"));
782
783 assert_eq!(
785 Bmv::from_static("SGVsbG8hIQ=="),
786 Bmv::from_static("SGVsbG8hIQ")
787 );
788 unsafe {
791 assert_eq!(
792 Bmv::from_shared_unchecked(Bytes::from_static(b"..{}")),
793 Bmv::from_shared_unchecked(Bytes::from_static(b"{}.."))
794 );
795 }
796}
797
798#[test]
799fn test_value_eq_str() {
800 type Bmv = BinaryMetadataValue;
801 type Amv = AsciiMetadataValue;
802
803 assert_eq!(Amv::from_static("abc"), "abc");
804 assert_ne!(Amv::from_static("abc"), "ABC");
805 assert_eq!("abc", Amv::from_static("abc"));
806 assert_ne!("ABC", Amv::from_static("abc"));
807
808 assert_eq!(Bmv::from_bytes(b"abc"), "abc");
809 assert_ne!(Bmv::from_bytes(b"abc"), "ABC");
810 assert_eq!("abc", Bmv::from_bytes(b"abc"));
811 assert_ne!("ABC", Bmv::from_bytes(b"abc"));
812
813 assert_eq!(Bmv::from_static("SGVsbG8hIQ=="), "Hello!!");
815 assert_eq!("Hello!!", Bmv::from_static("SGVsbG8hIQ=="));
816}
817
818#[test]
819fn test_value_eq_bytes() {
820 type Bmv = BinaryMetadataValue;
821 type Amv = AsciiMetadataValue;
822
823 assert_eq!(Amv::from_static("abc"), "abc".as_bytes());
824 assert_ne!(Amv::from_static("abc"), "ABC".as_bytes());
825 assert_eq!(*"abc".as_bytes(), Amv::from_static("abc"));
826 assert_ne!(*"ABC".as_bytes(), Amv::from_static("abc"));
827
828 assert_eq!(*"abc".as_bytes(), Bmv::from_bytes(b"abc"));
829 assert_ne!(*"ABC".as_bytes(), Bmv::from_bytes(b"abc"));
830
831 assert_eq!(Bmv::from_static("SGVsbG8hIQ=="), "Hello!!".as_bytes());
833 assert_eq!(*"Hello!!".as_bytes(), Bmv::from_static("SGVsbG8hIQ=="));
834}
835
836#[test]
837fn test_ascii_value_hash() {
838 use std::collections::hash_map::DefaultHasher;
839 type Amv = AsciiMetadataValue;
840
841 fn hash(value: Amv) -> u64 {
842 let mut hasher = DefaultHasher::new();
843 value.hash(&mut hasher);
844 hasher.finish()
845 }
846
847 let value1 = Amv::from_static("abc");
848 let value2 = Amv::from_static("abc");
849 assert_eq!(value1, value2);
850 assert_eq!(hash(value1), hash(value2));
851
852 let value1 = Amv::from_static("abc");
853 let value2 = Amv::from_static("xyz");
854
855 assert_ne!(value1, value2);
856 assert_ne!(hash(value1), hash(value2));
857}
858
859#[test]
860fn test_valid_binary_value_hash() {
861 use std::collections::hash_map::DefaultHasher;
862 type Bmv = BinaryMetadataValue;
863
864 fn hash(value: Bmv) -> u64 {
865 let mut hasher = DefaultHasher::new();
866 value.hash(&mut hasher);
867 hasher.finish()
868 }
869
870 let value1 = Bmv::from_bytes(b"abc");
871 let value2 = Bmv::from_bytes(b"abc");
872 assert_eq!(value1, value2);
873 assert_eq!(hash(value1), hash(value2));
874
875 let value1 = Bmv::from_bytes(b"abc");
876 let value2 = Bmv::from_bytes(b"xyz");
877 assert_ne!(value1, value2);
878 assert_ne!(hash(value1), hash(value2));
879}
880
881#[test]
882fn test_invalid_binary_value_hash() {
883 use std::collections::hash_map::DefaultHasher;
884 type Bmv = BinaryMetadataValue;
885
886 fn hash(value: Bmv) -> u64 {
887 let mut hasher = DefaultHasher::new();
888 value.hash(&mut hasher);
889 hasher.finish()
890 }
891
892 unsafe {
894 let value1 = Bmv::from_shared_unchecked(Bytes::from_static(b"..{}"));
895 let value2 = Bmv::from_shared_unchecked(Bytes::from_static(b"{}.."));
896 assert_eq!(value1, value2);
897 assert_eq!(hash(value1), hash(value2));
898 }
899
900 unsafe {
902 let valid = Bmv::from_bytes(b"abc");
903 let invalid = Bmv::from_shared_unchecked(Bytes::from_static(b"{}.."));
904 assert_ne!(valid, invalid);
905 assert_ne!(hash(valid), hash(invalid));
906 }
907}