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#[derive(Clone)]
21#[repr(transparent)]
22pub struct MetadataValue<VE: ValueEncoding> {
23 pub(crate) inner: HeaderValue,
26 phantom: PhantomData<VE>,
27}
28
29#[derive(Debug)]
34pub struct ToStrError {
35 _priv: (),
36}
37
38pub type AsciiMetadataValue = MetadataValue<Ascii>;
40pub type BinaryMetadataValue = MetadataValue<Binary>;
42
43impl<VE: ValueEncoding> MetadataValue<VE> {
44 #[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 #[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 #[inline]
109 pub fn is_empty(&self) -> bool {
110 VE::is_empty(self.inner.as_bytes())
111 }
112
113 #[inline]
131 pub fn to_bytes(&self) -> Result<Bytes, InvalidMetadataValueBytes> {
132 VE::decode(self.inner.as_bytes())
133 }
134
135 #[inline]
150 pub fn set_sensitive(&mut self, val: bool) {
151 self.inner.set_sensitive(val);
152 }
153
154 #[inline]
176 pub fn is_sensitive(&self) -> bool {
177 self.inner.is_sensitive()
178 }
179
180 #[inline]
197 pub fn as_encoded_bytes(&self) -> &[u8] {
198 self.inner.as_bytes()
199 }
200
201 #[inline]
205 pub(crate) fn unchecked_from_header_value(value: HeaderValue) -> Self {
206 MetadataValue {
207 inner: value,
208 phantom: PhantomData,
209 }
210 }
211
212 #[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 #[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
229impl<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
265impl<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
298impl<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
320impl<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
339impl<'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
354impl<'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
369impl 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 #[inline]
398 pub fn from_key<KeyVE: ValueEncoding>(key: MetadataKey<KeyVE>) -> Self {
399 key.into()
400 }
401
402 #[inline]
417 pub fn len(&self) -> usize {
418 self.inner.len()
419 }
420
421 pub fn to_str(&self) -> Result<&str, ToStrError> {
435 self.inner.to_str().map_err(|_| ToStrError::new())
436 }
437
438 #[inline]
449 pub fn as_bytes(&self) -> &[u8] {
450 self.inner.as_bytes()
451 }
452}
453
454impl MetadataValue<Binary> {
455 #[inline]
465 pub fn from_bytes(src: &[u8]) -> Self {
466 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 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
598impl 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
629impl<VE: ValueEncoding> PartialEq for MetadataValue<VE> {
632 #[inline]
633 fn eq(&self, other: &MetadataValue<VE>) -> bool {
634 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 assert_eq!(
846 Bmv::from_static("SGVsbG8hIQ=="),
847 Bmv::from_static("SGVsbG8hIQ")
848 );
849 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 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 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}