tonic_arcanyx_fork/metadata/
value.rs1#![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#[derive(Clone)]
24#[repr(transparent)]
25pub struct MetadataValue<VE: ValueEncoding> {
26 pub(crate) inner: HeaderValue,
29 phantom: PhantomData<VE>,
30}
31
32#[derive(Debug)]
37pub struct ToStrError {
38 _priv: (),
39}
40
41pub type AsciiMetadataValue = MetadataValue<Ascii>;
43pub type BinaryMetadataValue = MetadataValue<Binary>;
45
46impl<VE: ValueEncoding> MetadataValue<VE> {
47 #[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 #[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 #[inline]
122 #[deprecated = "Use TryFrom instead"]
123 pub fn from_shared(src: Bytes) -> Result<Self, InvalidMetadataValueBytes> {
124 Self::try_from(src)
125 }
126
127 #[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 #[inline]
156 pub fn is_empty(&self) -> bool {
157 VE::is_empty(self.inner.as_bytes())
158 }
159
160 #[inline]
178 pub fn to_bytes(&self) -> Result<Bytes, InvalidMetadataValueBytes> {
179 VE::decode(self.inner.as_bytes())
180 }
181
182 #[inline]
197 pub fn set_sensitive(&mut self, val: bool) {
198 self.inner.set_sensitive(val);
199 }
200
201 #[inline]
223 pub fn is_sensitive(&self) -> bool {
224 self.inner.is_sensitive()
225 }
226
227 #[inline]
244 pub fn as_encoded_bytes(&self) -> &[u8] {
245 self.inner.as_bytes()
246 }
247
248 #[inline]
252 pub(crate) fn unchecked_from_header_value(value: HeaderValue) -> Self {
253 MetadataValue {
254 inner: value,
255 phantom: PhantomData,
256 }
257 }
258
259 #[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 #[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
276impl<'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
314impl<'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
349impl<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
371impl<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
390impl<'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
405impl<'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
420impl 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#[allow(clippy::len_without_is_empty)]
437impl MetadataValue<Ascii> {
438 #[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 #[inline]
481 pub fn from_key<KeyVE: ValueEncoding>(key: MetadataKey<KeyVE>) -> Self {
482 key.into()
483 }
484
485 #[inline]
500 pub fn len(&self) -> usize {
501 self.inner.len()
502 }
503
504 pub fn to_str(&self) -> Result<&str, ToStrError> {
518 self.inner.to_str().map_err(|_| ToStrError::new())
519 }
520
521 #[inline]
532 pub fn as_bytes(&self) -> &[u8] {
533 self.inner.as_bytes()
534 }
535}
536
537impl MetadataValue<Binary> {
538 #[inline]
548 pub fn from_bytes(src: &[u8]) -> Self {
549 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 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
681impl 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
712impl<VE: ValueEncoding> PartialEq for MetadataValue<VE> {
715 #[inline]
716 fn eq(&self, other: &MetadataValue<VE>) -> bool {
717 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 assert_eq!(
929 BMV::from_static("SGVsbG8hIQ=="),
930 BMV::from_static("SGVsbG8hIQ")
931 );
932 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 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 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}