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 MetadataValue {
89 inner: HeaderValue::from_maybe_shared_unchecked(src),
90 phantom: PhantomData,
91 }
92 }
93
94 #[inline]
107 pub fn is_empty(&self) -> bool {
108 VE::is_empty(self.inner.as_bytes())
109 }
110
111 #[inline]
129 pub fn to_bytes(&self) -> Result<Bytes, InvalidMetadataValueBytes> {
130 VE::decode(self.inner.as_bytes())
131 }
132
133 #[inline]
148 pub fn set_sensitive(&mut self, val: bool) {
149 self.inner.set_sensitive(val);
150 }
151
152 #[inline]
174 pub fn is_sensitive(&self) -> bool {
175 self.inner.is_sensitive()
176 }
177
178 #[inline]
195 pub fn as_encoded_bytes(&self) -> &[u8] {
196 self.inner.as_bytes()
197 }
198
199 #[inline]
203 pub(crate) fn unchecked_from_header_value(value: HeaderValue) -> Self {
204 MetadataValue {
205 inner: value,
206 phantom: PhantomData,
207 }
208 }
209
210 #[inline]
214 pub(crate) fn unchecked_from_header_value_ref(header_value: &HeaderValue) -> &Self {
215 unsafe { &*(header_value as *const HeaderValue as *const Self) }
216 }
217
218 #[inline]
222 pub(crate) fn unchecked_from_mut_header_value_ref(header_value: &mut HeaderValue) -> &mut Self {
223 unsafe { &mut *(header_value as *mut HeaderValue as *mut Self) }
224 }
225}
226
227impl<'a, VE: ValueEncoding> TryFrom<&'a [u8]> for MetadataValue<VE> {
252 type Error = InvalidMetadataValueBytes;
253
254 #[inline]
255 fn try_from(src: &[u8]) -> Result<Self, Self::Error> {
256 VE::from_bytes(src).map(|value| MetadataValue {
257 inner: value,
258 phantom: PhantomData,
259 })
260 }
261}
262
263impl<'a, VE: ValueEncoding, const N: usize> TryFrom<&'a [u8; N]> for MetadataValue<VE> {
288 type Error = InvalidMetadataValueBytes;
289
290 #[inline]
291 fn try_from(src: &[u8; N]) -> Result<Self, Self::Error> {
292 Self::try_from(src.as_ref())
293 }
294}
295
296impl<VE: ValueEncoding> TryFrom<Bytes> for MetadataValue<VE> {
307 type Error = InvalidMetadataValueBytes;
308
309 #[inline]
310 fn try_from(src: Bytes) -> Result<Self, Self::Error> {
311 VE::from_shared(src).map(|value| MetadataValue {
312 inner: value,
313 phantom: PhantomData,
314 })
315 }
316}
317
318impl<VE: ValueEncoding> TryFrom<Vec<u8>> for MetadataValue<VE> {
329 type Error = InvalidMetadataValueBytes;
330
331 #[inline]
332 fn try_from(src: Vec<u8>) -> Result<Self, Self::Error> {
333 Self::try_from(src.as_slice())
334 }
335}
336
337impl<'a> TryFrom<&'a str> for MetadataValue<Ascii> {
344 type Error = InvalidMetadataValue;
345
346 #[inline]
347 fn try_from(s: &'a str) -> Result<Self, Self::Error> {
348 s.parse()
349 }
350}
351
352impl<'a> TryFrom<&'a String> for MetadataValue<Ascii> {
359 type Error = InvalidMetadataValue;
360
361 #[inline]
362 fn try_from(s: &'a String) -> Result<Self, Self::Error> {
363 s.parse()
364 }
365}
366
367impl TryFrom<String> for MetadataValue<Ascii> {
374 type Error = InvalidMetadataValue;
375
376 #[inline]
377 fn try_from(s: String) -> Result<Self, Self::Error> {
378 s.parse()
379 }
380}
381
382impl MetadataValue<Ascii> {
383 #[inline]
396 pub fn from_key<KeyVE: ValueEncoding>(key: MetadataKey<KeyVE>) -> Self {
397 key.into()
398 }
399
400 #[inline]
415 pub fn len(&self) -> usize {
416 self.inner.len()
417 }
418
419 pub fn to_str(&self) -> Result<&str, ToStrError> {
433 self.inner.to_str().map_err(|_| ToStrError::new())
434 }
435
436 #[inline]
447 pub fn as_bytes(&self) -> &[u8] {
448 self.inner.as_bytes()
449 }
450}
451
452impl MetadataValue<Binary> {
453 #[inline]
463 pub fn from_bytes(src: &[u8]) -> Self {
464 Self::try_from(src).unwrap()
466 }
467}
468
469impl<VE: ValueEncoding> AsRef<[u8]> for MetadataValue<VE> {
470 #[inline]
471 fn as_ref(&self) -> &[u8] {
472 self.inner.as_ref()
473 }
474}
475
476impl<VE: ValueEncoding> fmt::Debug for MetadataValue<VE> {
477 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
478 VE::fmt(&self.inner, f)
479 }
480}
481
482impl<KeyVE: ValueEncoding> From<MetadataKey<KeyVE>> for MetadataValue<Ascii> {
483 #[inline]
484 fn from(h: MetadataKey<KeyVE>) -> MetadataValue<Ascii> {
485 MetadataValue {
486 inner: h.inner.into(),
487 phantom: PhantomData,
488 }
489 }
490}
491
492macro_rules! from_integers {
493 ($($name:ident: $t:ident => $max_len:expr),*) => {$(
494 impl From<$t> for MetadataValue<Ascii> {
495 fn from(num: $t) -> MetadataValue<Ascii> {
496 MetadataValue {
497 inner: HeaderValue::from(num),
498 phantom: PhantomData,
499 }
500 }
501 }
502
503 #[test]
504 fn $name() {
505 let n: $t = 55;
506 let val = AsciiMetadataValue::from(n);
507 assert_eq!(val, &n.to_string());
508
509 let n = $t::MAX;
510 let val = AsciiMetadataValue::from(n);
511 assert_eq!(val, &n.to_string());
512 }
513 )*};
514}
515
516from_integers! {
517 from_u16: u16 => 5,
521 from_i16: i16 => 6,
522 from_u32: u32 => 10,
523 from_i32: i32 => 11,
524 from_u64: u64 => 20,
525 from_i64: i64 => 20
526}
527
528#[cfg(target_pointer_width = "16")]
529from_integers! {
530 from_usize: usize => 5,
531 from_isize: isize => 6
532}
533
534#[cfg(target_pointer_width = "32")]
535from_integers! {
536 from_usize: usize => 10,
537 from_isize: isize => 11
538}
539
540#[cfg(target_pointer_width = "64")]
541from_integers! {
542 from_usize: usize => 20,
543 from_isize: isize => 20
544}
545
546#[cfg(test)]
547mod from_metadata_value_tests {
548 use super::*;
549 use crate::metadata::map::MetadataMap;
550
551 #[test]
552 fn it_can_insert_metadata_key_as_metadata_value() {
553 let mut map = MetadataMap::new();
554 map.insert(
555 "accept",
556 MetadataKey::<Ascii>::from_bytes(b"hello-world")
557 .unwrap()
558 .into(),
559 );
560
561 assert_eq!(
562 map.get("accept").unwrap(),
563 AsciiMetadataValue::try_from(b"hello-world").unwrap()
564 );
565 }
566}
567
568impl FromStr for MetadataValue<Ascii> {
569 type Err = InvalidMetadataValue;
570
571 #[inline]
572 fn from_str(s: &str) -> Result<MetadataValue<Ascii>, Self::Err> {
573 HeaderValue::from_str(s)
574 .map(|value| MetadataValue {
575 inner: value,
576 phantom: PhantomData,
577 })
578 .map_err(|_| InvalidMetadataValue::new())
579 }
580}
581
582impl<VE: ValueEncoding> From<MetadataValue<VE>> for Bytes {
583 #[inline]
584 fn from(value: MetadataValue<VE>) -> Bytes {
585 Bytes::copy_from_slice(value.inner.as_bytes())
586 }
587}
588
589impl<'a, VE: ValueEncoding> From<&'a MetadataValue<VE>> for MetadataValue<VE> {
590 #[inline]
591 fn from(t: &'a MetadataValue<VE>) -> Self {
592 t.clone()
593 }
594}
595
596impl ToStrError {
599 pub(crate) fn new() -> Self {
600 ToStrError { _priv: () }
601 }
602}
603
604impl fmt::Display for ToStrError {
605 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
606 f.write_str("failed to convert metadata to a str")
607 }
608}
609
610impl Error for ToStrError {}
611
612impl Hash for MetadataValue<Ascii> {
613 fn hash<H: Hasher>(&self, state: &mut H) {
614 self.inner.hash(state)
615 }
616}
617
618impl Hash for MetadataValue<Binary> {
619 fn hash<H: Hasher>(&self, state: &mut H) {
620 match self.to_bytes() {
621 Ok(b) => b.hash(state),
622 Err(e) => e.hash(state),
623 }
624 }
625}
626
627impl<VE: ValueEncoding> PartialEq for MetadataValue<VE> {
630 #[inline]
631 fn eq(&self, other: &MetadataValue<VE>) -> bool {
632 VE::values_equal(&self.inner, &other.inner)
637 }
638}
639
640impl<VE: ValueEncoding> Eq for MetadataValue<VE> {}
641
642impl<VE: ValueEncoding> PartialOrd for MetadataValue<VE> {
643 #[inline]
644 fn partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering> {
645 Some(self.cmp(other))
646 }
647}
648
649impl<VE: ValueEncoding> Ord for MetadataValue<VE> {
650 #[inline]
651 fn cmp(&self, other: &Self) -> cmp::Ordering {
652 self.inner.cmp(&other.inner)
653 }
654}
655
656impl<VE: ValueEncoding> PartialEq<str> for MetadataValue<VE> {
657 #[inline]
658 fn eq(&self, other: &str) -> bool {
659 VE::equals(&self.inner, other.as_bytes())
660 }
661}
662
663impl<VE: ValueEncoding> PartialEq<[u8]> for MetadataValue<VE> {
664 #[inline]
665 fn eq(&self, other: &[u8]) -> bool {
666 VE::equals(&self.inner, other)
667 }
668}
669
670impl<VE: ValueEncoding> PartialOrd<str> for MetadataValue<VE> {
671 #[inline]
672 fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> {
673 self.inner.partial_cmp(other.as_bytes())
674 }
675}
676
677impl<VE: ValueEncoding> PartialOrd<[u8]> for MetadataValue<VE> {
678 #[inline]
679 fn partial_cmp(&self, other: &[u8]) -> Option<cmp::Ordering> {
680 self.inner.partial_cmp(other)
681 }
682}
683
684impl<VE: ValueEncoding> PartialEq<MetadataValue<VE>> for str {
685 #[inline]
686 fn eq(&self, other: &MetadataValue<VE>) -> bool {
687 *other == *self
688 }
689}
690
691impl<VE: ValueEncoding> PartialEq<MetadataValue<VE>> for [u8] {
692 #[inline]
693 fn eq(&self, other: &MetadataValue<VE>) -> bool {
694 *other == *self
695 }
696}
697
698impl<VE: ValueEncoding> PartialOrd<MetadataValue<VE>> for str {
699 #[inline]
700 fn partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering> {
701 self.as_bytes().partial_cmp(other.inner.as_bytes())
702 }
703}
704
705impl<VE: ValueEncoding> PartialOrd<MetadataValue<VE>> for [u8] {
706 #[inline]
707 fn partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering> {
708 self.partial_cmp(other.inner.as_bytes())
709 }
710}
711
712impl<VE: ValueEncoding> PartialEq<String> for MetadataValue<VE> {
713 #[inline]
714 fn eq(&self, other: &String) -> bool {
715 *self == other[..]
716 }
717}
718
719impl<VE: ValueEncoding> PartialOrd<String> for MetadataValue<VE> {
720 #[inline]
721 fn partial_cmp(&self, other: &String) -> Option<cmp::Ordering> {
722 self.inner.partial_cmp(other.as_bytes())
723 }
724}
725
726impl<VE: ValueEncoding> PartialEq<MetadataValue<VE>> for String {
727 #[inline]
728 fn eq(&self, other: &MetadataValue<VE>) -> bool {
729 *other == *self
730 }
731}
732
733impl<VE: ValueEncoding> PartialOrd<MetadataValue<VE>> for String {
734 #[inline]
735 fn partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering> {
736 self.as_bytes().partial_cmp(other.inner.as_bytes())
737 }
738}
739
740impl<'a, VE: ValueEncoding> PartialEq<MetadataValue<VE>> for &'a MetadataValue<VE> {
741 #[inline]
742 fn eq(&self, other: &MetadataValue<VE>) -> bool {
743 **self == *other
744 }
745}
746
747impl<'a, VE: ValueEncoding> PartialOrd<MetadataValue<VE>> for &'a MetadataValue<VE> {
748 #[inline]
749 fn partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering> {
750 (**self).partial_cmp(other)
751 }
752}
753
754impl<'a, VE: ValueEncoding, T: ?Sized> PartialEq<&'a T> for MetadataValue<VE>
755where
756 MetadataValue<VE>: PartialEq<T>,
757{
758 #[inline]
759 fn eq(&self, other: &&'a T) -> bool {
760 *self == **other
761 }
762}
763
764impl<'a, VE: ValueEncoding, T: ?Sized> PartialOrd<&'a T> for MetadataValue<VE>
765where
766 MetadataValue<VE>: PartialOrd<T>,
767{
768 #[inline]
769 fn partial_cmp(&self, other: &&'a T) -> Option<cmp::Ordering> {
770 self.partial_cmp(*other)
771 }
772}
773
774impl<'a, VE: ValueEncoding> PartialEq<MetadataValue<VE>> for &'a str {
775 #[inline]
776 fn eq(&self, other: &MetadataValue<VE>) -> bool {
777 *other == *self
778 }
779}
780
781impl<'a, VE: ValueEncoding> PartialOrd<MetadataValue<VE>> for &'a str {
782 #[inline]
783 fn partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering> {
784 self.as_bytes().partial_cmp(other.inner.as_bytes())
785 }
786}
787
788#[test]
789fn test_debug() {
790 let cases = &[
791 ("hello", "\"hello\""),
792 ("hello \"world\"", "\"hello \\\"world\\\"\""),
793 ("\u{7FFF}hello", "\"\\xe7\\xbf\\xbfhello\""),
794 ];
795
796 for &(value, expected) in cases {
797 let val = AsciiMetadataValue::try_from(value.as_bytes()).unwrap();
798 let actual = format!("{:?}", val);
799 assert_eq!(expected, actual);
800 }
801
802 let mut sensitive = AsciiMetadataValue::from_static("password");
803 sensitive.set_sensitive(true);
804 assert_eq!("Sensitive", format!("{:?}", sensitive));
805}
806
807#[test]
808fn test_is_empty() {
809 fn from_str<VE: ValueEncoding>(s: &str) -> MetadataValue<VE> {
810 MetadataValue::<VE>::unchecked_from_header_value(s.parse().unwrap())
811 }
812
813 assert!(from_str::<Ascii>("").is_empty());
814 assert!(from_str::<Binary>("").is_empty());
815 assert!(!from_str::<Ascii>("a").is_empty());
816 assert!(!from_str::<Binary>("a").is_empty());
817 assert!(!from_str::<Ascii>("=").is_empty());
818 assert!(from_str::<Binary>("=").is_empty());
819 assert!(!from_str::<Ascii>("===").is_empty());
820 assert!(from_str::<Binary>("===").is_empty());
821 assert!(!from_str::<Ascii>("=====").is_empty());
822 assert!(from_str::<Binary>("=====").is_empty());
823}
824
825#[test]
826fn test_from_shared_base64_encodes() {
827 let value = BinaryMetadataValue::try_from(Bytes::from_static(b"Hello")).unwrap();
828 assert_eq!(value.as_encoded_bytes(), b"SGVsbG8");
829}
830
831#[test]
832fn test_value_eq_value() {
833 type Bmv = BinaryMetadataValue;
834 type Amv = AsciiMetadataValue;
835
836 assert_eq!(Amv::from_static("abc"), Amv::from_static("abc"));
837 assert_ne!(Amv::from_static("abc"), Amv::from_static("ABC"));
838
839 assert_eq!(Bmv::from_bytes(b"abc"), Bmv::from_bytes(b"abc"));
840 assert_ne!(Bmv::from_bytes(b"abc"), Bmv::from_bytes(b"ABC"));
841
842 assert_eq!(
844 Bmv::from_static("SGVsbG8hIQ=="),
845 Bmv::from_static("SGVsbG8hIQ")
846 );
847 unsafe {
849 assert_eq!(
850 Bmv::from_shared_unchecked(Bytes::from_static(b"..{}")),
851 Bmv::from_shared_unchecked(Bytes::from_static(b"{}.."))
852 );
853 }
854}
855
856#[test]
857fn test_value_eq_str() {
858 type Bmv = BinaryMetadataValue;
859 type Amv = AsciiMetadataValue;
860
861 assert_eq!(Amv::from_static("abc"), "abc");
862 assert_ne!(Amv::from_static("abc"), "ABC");
863 assert_eq!("abc", Amv::from_static("abc"));
864 assert_ne!("ABC", Amv::from_static("abc"));
865
866 assert_eq!(Bmv::from_bytes(b"abc"), "abc");
867 assert_ne!(Bmv::from_bytes(b"abc"), "ABC");
868 assert_eq!("abc", Bmv::from_bytes(b"abc"));
869 assert_ne!("ABC", Bmv::from_bytes(b"abc"));
870
871 assert_eq!(Bmv::from_static("SGVsbG8hIQ=="), "Hello!!");
873 assert_eq!("Hello!!", Bmv::from_static("SGVsbG8hIQ=="));
874}
875
876#[test]
877fn test_value_eq_bytes() {
878 type Bmv = BinaryMetadataValue;
879 type Amv = AsciiMetadataValue;
880
881 assert_eq!(Amv::from_static("abc"), "abc".as_bytes());
882 assert_ne!(Amv::from_static("abc"), "ABC".as_bytes());
883 assert_eq!(*"abc".as_bytes(), Amv::from_static("abc"));
884 assert_ne!(*"ABC".as_bytes(), Amv::from_static("abc"));
885
886 assert_eq!(*"abc".as_bytes(), Bmv::from_bytes(b"abc"));
887 assert_ne!(*"ABC".as_bytes(), Bmv::from_bytes(b"abc"));
888
889 assert_eq!(Bmv::from_static("SGVsbG8hIQ=="), "Hello!!".as_bytes());
891 assert_eq!(*"Hello!!".as_bytes(), Bmv::from_static("SGVsbG8hIQ=="));
892}
893
894#[test]
895fn test_ascii_value_hash() {
896 use std::collections::hash_map::DefaultHasher;
897 type Amv = AsciiMetadataValue;
898
899 fn hash(value: Amv) -> u64 {
900 let mut hasher = DefaultHasher::new();
901 value.hash(&mut hasher);
902 hasher.finish()
903 }
904
905 let value1 = Amv::from_static("abc");
906 let value2 = Amv::from_static("abc");
907 assert_eq!(value1, value2);
908 assert_eq!(hash(value1), hash(value2));
909
910 let value1 = Amv::from_static("abc");
911 let value2 = Amv::from_static("xyz");
912
913 assert_ne!(value1, value2);
914 assert_ne!(hash(value1), hash(value2));
915}
916
917#[test]
918fn test_valid_binary_value_hash() {
919 use std::collections::hash_map::DefaultHasher;
920 type Bmv = BinaryMetadataValue;
921
922 fn hash(value: Bmv) -> u64 {
923 let mut hasher = DefaultHasher::new();
924 value.hash(&mut hasher);
925 hasher.finish()
926 }
927
928 let value1 = Bmv::from_bytes(b"abc");
929 let value2 = Bmv::from_bytes(b"abc");
930 assert_eq!(value1, value2);
931 assert_eq!(hash(value1), hash(value2));
932
933 let value1 = Bmv::from_bytes(b"abc");
934 let value2 = Bmv::from_bytes(b"xyz");
935 assert_ne!(value1, value2);
936 assert_ne!(hash(value1), hash(value2));
937}
938
939#[test]
940fn test_invalid_binary_value_hash() {
941 use std::collections::hash_map::DefaultHasher;
942 type Bmv = BinaryMetadataValue;
943
944 fn hash(value: Bmv) -> u64 {
945 let mut hasher = DefaultHasher::new();
946 value.hash(&mut hasher);
947 hasher.finish()
948 }
949
950 unsafe {
951 let value1 = Bmv::from_shared_unchecked(Bytes::from_static(b"..{}"));
952 let value2 = Bmv::from_shared_unchecked(Bytes::from_static(b"{}.."));
953 assert_eq!(value1, value2);
954 assert_eq!(hash(value1), hash(value2));
955 }
956
957 unsafe {
958 let valid = Bmv::from_bytes(b"abc");
959 let invalid = Bmv::from_shared_unchecked(Bytes::from_static(b"{}.."));
960 assert_ne!(valid, invalid);
961 assert_ne!(hash(valid), hash(invalid));
962 }
963}