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::marker::PhantomData;
10use std::str::FromStr;
11use std::{cmp, fmt};
12
13#[derive(Clone, Hash)]
19#[repr(transparent)]
20pub struct MetadataValue<VE: ValueEncoding> {
21 pub(crate) inner: HeaderValue,
24 phantom: PhantomData<VE>,
25}
26
27#[derive(Debug)]
32pub struct ToStrError {
33 _priv: (),
34}
35
36pub type AsciiMetadataValue = MetadataValue<Ascii>;
37pub type BinaryMetadataValue = MetadataValue<Binary>;
38
39impl<VE: ValueEncoding> MetadataValue<VE> {
40 #[inline]
67 pub fn from_static(src: &'static str) -> Self {
68 MetadataValue {
69 inner: VE::from_static(src),
70 phantom: PhantomData,
71 }
72 }
73
74 #[inline]
102 pub fn try_from_bytes(src: &[u8]) -> Result<Self, InvalidMetadataValueBytes> {
103 VE::from_bytes(src).map(|value| MetadataValue {
104 inner: value,
105 phantom: PhantomData,
106 })
107 }
108
109 #[inline]
123 pub fn from_shared(src: Bytes) -> Result<Self, InvalidMetadataValueBytes> {
124 VE::from_shared(src).map(|value| MetadataValue {
125 inner: value,
126 phantom: PhantomData,
127 })
128 }
129
130 #[inline]
137 pub unsafe fn from_shared_unchecked(src: Bytes) -> Self {
138 MetadataValue {
139 inner: HeaderValue::from_shared_unchecked(src),
140 phantom: PhantomData,
141 }
142 }
143
144 #[inline]
157 pub fn is_empty(&self) -> bool {
158 VE::is_empty(self.inner.as_bytes())
159 }
160
161 #[inline]
179 pub fn to_bytes(&self) -> Result<Bytes, InvalidMetadataValueBytes> {
180 VE::decode(self.inner.as_bytes())
181 }
182
183 #[inline]
198 pub fn set_sensitive(&mut self, val: bool) {
199 self.inner.set_sensitive(val);
200 }
201
202 #[inline]
224 pub fn is_sensitive(&self) -> bool {
225 self.inner.is_sensitive()
226 }
227
228 #[inline]
245 pub fn as_encoded_bytes(&self) -> &[u8] {
246 self.inner.as_bytes()
247 }
248
249 #[inline]
253 pub(crate) fn unchecked_from_header_value(value: HeaderValue) -> Self {
254 MetadataValue {
255 inner: value,
256 phantom: PhantomData,
257 }
258 }
259
260 #[inline]
264 pub(crate) fn unchecked_from_header_value_ref(header_value: &HeaderValue) -> &Self {
265 unsafe { &*(header_value as *const HeaderValue as *const Self) }
266 }
267
268 #[inline]
272 pub(crate) fn unchecked_from_mut_header_value_ref(header_value: &mut HeaderValue) -> &mut Self {
273 unsafe { &mut *(header_value as *mut HeaderValue as *mut Self) }
274 }
275}
276
277impl MetadataValue<Ascii> {
278 #[inline]
304 pub fn from_str(src: &str) -> Result<Self, InvalidMetadataValue> {
305 HeaderValue::from_str(src)
306 .map(|value| MetadataValue {
307 inner: value,
308 phantom: PhantomData,
309 })
310 .map_err(|_| InvalidMetadataValue::new())
311 }
312
313 #[inline]
326 pub fn from_key<KeyVE: ValueEncoding>(key: MetadataKey<KeyVE>) -> Self {
327 key.into()
328 }
329
330 #[inline]
345 pub fn len(&self) -> usize {
346 self.inner.len()
347 }
348
349 pub fn to_str(&self) -> Result<&str, ToStrError> {
363 return self.inner.to_str().map_err(|_| ToStrError::new());
364 }
365
366 #[inline]
377 pub fn as_bytes(&self) -> &[u8] {
378 self.inner.as_bytes()
379 }
380}
381
382impl MetadataValue<Binary> {
383 #[inline]
393 pub fn from_bytes(src: &[u8]) -> Self {
394 Self::try_from_bytes(src).unwrap()
396 }
397}
398
399impl<VE: ValueEncoding> AsRef<[u8]> for MetadataValue<VE> {
400 #[inline]
401 fn as_ref(&self) -> &[u8] {
402 self.inner.as_ref()
403 }
404}
405
406impl<VE: ValueEncoding> fmt::Debug for MetadataValue<VE> {
407 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
408 VE::fmt(&self.inner, f)
409 }
410}
411
412impl<KeyVE: ValueEncoding> From<MetadataKey<KeyVE>> for MetadataValue<Ascii> {
413 #[inline]
414 fn from(h: MetadataKey<KeyVE>) -> MetadataValue<Ascii> {
415 MetadataValue {
416 inner: h.inner.into(),
417 phantom: PhantomData,
418 }
419 }
420}
421
422macro_rules! from_integers {
423 ($($name:ident: $t:ident => $max_len:expr),*) => {$(
424 impl From<$t> for MetadataValue<Ascii> {
425 fn from(num: $t) -> MetadataValue<Ascii> {
426 MetadataValue {
427 inner: HeaderValue::from(num),
428 phantom: PhantomData,
429 }
430 }
431 }
432
433 #[test]
434 fn $name() {
435 let n: $t = 55;
436 let val = AsciiMetadataValue::from(n);
437 assert_eq!(val, &n.to_string());
438
439 let n = ::std::$t::MAX;
440 let val = AsciiMetadataValue::from(n);
441 assert_eq!(val, &n.to_string());
442 }
443 )*};
444}
445
446from_integers! {
447 from_u16: u16 => 5,
451 from_i16: i16 => 6,
452 from_u32: u32 => 10,
453 from_i32: i32 => 11,
454 from_u64: u64 => 20,
455 from_i64: i64 => 20
456}
457
458#[cfg(target_pointer_width = "16")]
459from_integers! {
460 from_usize: usize => 5,
461 from_isize: isize => 6
462}
463
464#[cfg(target_pointer_width = "32")]
465from_integers! {
466 from_usize: usize => 10,
467 from_isize: isize => 11
468}
469
470#[cfg(target_pointer_width = "64")]
471from_integers! {
472 from_usize: usize => 20,
473 from_isize: isize => 20
474}
475
476#[cfg(test)]
477mod from_metadata_value_tests {
478 use super::*;
479 use crate::metadata::map::MetadataMap;
480
481 #[test]
482 fn it_can_insert_metadata_key_as_metadata_value() {
483 let mut map = MetadataMap::new();
484 map.insert(
485 "accept",
486 MetadataKey::<Ascii>::from_bytes(b"hello-world")
487 .unwrap()
488 .into(),
489 );
490
491 assert_eq!(
492 map.get("accept").unwrap(),
493 AsciiMetadataValue::try_from_bytes(b"hello-world").unwrap()
494 );
495 }
496}
497
498impl FromStr for MetadataValue<Ascii> {
499 type Err = InvalidMetadataValue;
500
501 #[inline]
502 fn from_str(s: &str) -> Result<MetadataValue<Ascii>, Self::Err> {
503 MetadataValue::<Ascii>::from_str(s)
504 }
505}
506
507impl<VE: ValueEncoding> From<MetadataValue<VE>> for Bytes {
508 #[inline]
509 fn from(value: MetadataValue<VE>) -> Bytes {
510 Bytes::from(value.inner)
511 }
512}
513
514impl<'a, VE: ValueEncoding> From<&'a MetadataValue<VE>> for MetadataValue<VE> {
515 #[inline]
516 fn from(t: &'a MetadataValue<VE>) -> Self {
517 t.clone()
518 }
519}
520
521impl ToStrError {
524 pub(crate) fn new() -> Self {
525 ToStrError { _priv: () }
526 }
527}
528
529impl fmt::Display for ToStrError {
530 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
531 self.description().fmt(f)
532 }
533}
534
535impl Error for ToStrError {
536 fn description(&self) -> &str {
537 "failed to convert metadata to a str"
538 }
539}
540
541impl<VE: ValueEncoding> PartialEq for MetadataValue<VE> {
544 #[inline]
545 fn eq(&self, other: &MetadataValue<VE>) -> bool {
546 VE::values_equal(&self.inner, &other.inner)
551 }
552}
553
554impl<VE: ValueEncoding> Eq for MetadataValue<VE> {}
555
556impl<VE: ValueEncoding> PartialOrd for MetadataValue<VE> {
557 #[inline]
558 fn partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering> {
559 self.inner.partial_cmp(&other.inner)
560 }
561}
562
563impl<VE: ValueEncoding> Ord for MetadataValue<VE> {
564 #[inline]
565 fn cmp(&self, other: &Self) -> cmp::Ordering {
566 self.inner.cmp(&other.inner)
567 }
568}
569
570impl<VE: ValueEncoding> PartialEq<str> for MetadataValue<VE> {
571 #[inline]
572 fn eq(&self, other: &str) -> bool {
573 VE::equals(&self.inner, other.as_bytes())
574 }
575}
576
577impl<VE: ValueEncoding> PartialEq<[u8]> for MetadataValue<VE> {
578 #[inline]
579 fn eq(&self, other: &[u8]) -> bool {
580 VE::equals(&self.inner, other)
581 }
582}
583
584impl<VE: ValueEncoding> PartialOrd<str> for MetadataValue<VE> {
585 #[inline]
586 fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> {
587 self.inner.partial_cmp(other.as_bytes())
588 }
589}
590
591impl<VE: ValueEncoding> PartialOrd<[u8]> for MetadataValue<VE> {
592 #[inline]
593 fn partial_cmp(&self, other: &[u8]) -> Option<cmp::Ordering> {
594 self.inner.partial_cmp(other)
595 }
596}
597
598impl<VE: ValueEncoding> PartialEq<MetadataValue<VE>> for str {
599 #[inline]
600 fn eq(&self, other: &MetadataValue<VE>) -> bool {
601 *other == *self
602 }
603}
604
605impl<VE: ValueEncoding> PartialEq<MetadataValue<VE>> for [u8] {
606 #[inline]
607 fn eq(&self, other: &MetadataValue<VE>) -> bool {
608 *other == *self
609 }
610}
611
612impl<VE: ValueEncoding> PartialOrd<MetadataValue<VE>> for str {
613 #[inline]
614 fn partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering> {
615 self.as_bytes().partial_cmp(other.inner.as_bytes())
616 }
617}
618
619impl<VE: ValueEncoding> PartialOrd<MetadataValue<VE>> for [u8] {
620 #[inline]
621 fn partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering> {
622 self.partial_cmp(other.inner.as_bytes())
623 }
624}
625
626impl<VE: ValueEncoding> PartialEq<String> for MetadataValue<VE> {
627 #[inline]
628 fn eq(&self, other: &String) -> bool {
629 *self == &other[..]
630 }
631}
632
633impl<VE: ValueEncoding> PartialOrd<String> for MetadataValue<VE> {
634 #[inline]
635 fn partial_cmp(&self, other: &String) -> Option<cmp::Ordering> {
636 self.inner.partial_cmp(other.as_bytes())
637 }
638}
639
640impl<VE: ValueEncoding> PartialEq<MetadataValue<VE>> for String {
641 #[inline]
642 fn eq(&self, other: &MetadataValue<VE>) -> bool {
643 *other == *self
644 }
645}
646
647impl<VE: ValueEncoding> PartialOrd<MetadataValue<VE>> for String {
648 #[inline]
649 fn partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering> {
650 self.as_bytes().partial_cmp(other.inner.as_bytes())
651 }
652}
653
654impl<'a, VE: ValueEncoding> PartialEq<MetadataValue<VE>> for &'a MetadataValue<VE> {
655 #[inline]
656 fn eq(&self, other: &MetadataValue<VE>) -> bool {
657 **self == *other
658 }
659}
660
661impl<'a, VE: ValueEncoding> PartialOrd<MetadataValue<VE>> for &'a MetadataValue<VE> {
662 #[inline]
663 fn partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering> {
664 (**self).partial_cmp(other)
665 }
666}
667
668impl<'a, VE: ValueEncoding, T: ?Sized> PartialEq<&'a T> for MetadataValue<VE>
669where
670 MetadataValue<VE>: PartialEq<T>,
671{
672 #[inline]
673 fn eq(&self, other: &&'a T) -> bool {
674 *self == **other
675 }
676}
677
678impl<'a, VE: ValueEncoding, T: ?Sized> PartialOrd<&'a T> for MetadataValue<VE>
679where
680 MetadataValue<VE>: PartialOrd<T>,
681{
682 #[inline]
683 fn partial_cmp(&self, other: &&'a T) -> Option<cmp::Ordering> {
684 self.partial_cmp(*other)
685 }
686}
687
688impl<'a, VE: ValueEncoding> PartialEq<MetadataValue<VE>> for &'a str {
689 #[inline]
690 fn eq(&self, other: &MetadataValue<VE>) -> bool {
691 *other == *self
692 }
693}
694
695impl<'a, VE: ValueEncoding> PartialOrd<MetadataValue<VE>> for &'a str {
696 #[inline]
697 fn partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering> {
698 self.as_bytes().partial_cmp(other.inner.as_bytes())
699 }
700}
701
702#[test]
703fn test_debug() {
704 let cases = &[
705 ("hello", "\"hello\""),
706 ("hello \"world\"", "\"hello \\\"world\\\"\""),
707 ("\u{7FFF}hello", "\"\\xe7\\xbf\\xbfhello\""),
708 ];
709
710 for &(value, expected) in cases {
711 let val = AsciiMetadataValue::try_from_bytes(value.as_bytes()).unwrap();
712 let actual = format!("{:?}", val);
713 assert_eq!(expected, actual);
714 }
715
716 let mut sensitive = AsciiMetadataValue::from_static("password");
717 sensitive.set_sensitive(true);
718 assert_eq!("Sensitive", format!("{:?}", sensitive));
719}
720
721#[test]
722fn test_is_empty() {
723 fn from_str<VE: ValueEncoding>(s: &str) -> MetadataValue<VE> {
724 MetadataValue::<VE>::unchecked_from_header_value(s.parse().unwrap())
725 }
726
727 assert!(from_str::<Ascii>("").is_empty());
728 assert!(from_str::<Binary>("").is_empty());
729 assert!(!from_str::<Ascii>("a").is_empty());
730 assert!(!from_str::<Binary>("a").is_empty());
731 assert!(!from_str::<Ascii>("=").is_empty());
732 assert!(from_str::<Binary>("=").is_empty());
733 assert!(!from_str::<Ascii>("===").is_empty());
734 assert!(from_str::<Binary>("===").is_empty());
735 assert!(!from_str::<Ascii>("=====").is_empty());
736 assert!(from_str::<Binary>("=====").is_empty());
737}
738
739#[test]
740fn test_from_shared_base64_encodes() {
741 let value = BinaryMetadataValue::from_shared(Bytes::from_static(b"Hello")).unwrap();
742 assert_eq!(value.as_encoded_bytes(), b"SGVsbG8");
743}
744
745#[test]
746fn test_value_eq_value() {
747 type BMV = BinaryMetadataValue;
748 type AMV = AsciiMetadataValue;
749
750 assert_eq!(AMV::from_static("abc"), AMV::from_static("abc"));
751 assert!(AMV::from_static("abc") != AMV::from_static("ABC"));
752
753 assert_eq!(BMV::from_bytes(b"abc"), BMV::from_bytes(b"abc"));
754 assert!(BMV::from_bytes(b"abc") != BMV::from_bytes(b"ABC"));
755
756 assert_eq!(
758 BMV::from_static("SGVsbG8hIQ=="),
759 BMV::from_static("SGVsbG8hIQ")
760 );
761 unsafe {
763 assert_eq!(
764 BMV::from_shared_unchecked(Bytes::from_static(b"..{}")),
765 BMV::from_shared_unchecked(Bytes::from_static(b"{}.."))
766 );
767 }
768}
769
770#[test]
771fn test_value_eq_str() {
772 type BMV = BinaryMetadataValue;
773 type AMV = AsciiMetadataValue;
774
775 assert_eq!(AMV::from_static("abc"), "abc");
776 assert!(AMV::from_static("abc") != "ABC");
777 assert_eq!("abc", AMV::from_static("abc"));
778 assert!("ABC" != AMV::from_static("abc"));
779
780 assert_eq!(BMV::from_bytes(b"abc"), "abc");
781 assert!(BMV::from_bytes(b"abc") != "ABC");
782 assert_eq!("abc", BMV::from_bytes(b"abc"));
783 assert!("ABC" != BMV::from_bytes(b"abc"));
784
785 assert_eq!(BMV::from_static("SGVsbG8hIQ=="), "Hello!!");
787 assert_eq!("Hello!!", BMV::from_static("SGVsbG8hIQ=="));
788}
789
790#[test]
791fn test_value_eq_bytes() {
792 type BMV = BinaryMetadataValue;
793 type AMV = AsciiMetadataValue;
794
795 assert_eq!(AMV::from_static("abc"), "abc".as_bytes());
796 assert!(AMV::from_static("abc") != "ABC".as_bytes());
797 assert_eq!(*"abc".as_bytes(), AMV::from_static("abc"));
798 assert!(*"ABC".as_bytes() != AMV::from_static("abc"));
799
800 assert_eq!(*"abc".as_bytes(), BMV::from_bytes(b"abc"));
801 assert!(*"ABC".as_bytes() != BMV::from_bytes(b"abc"));
802
803 assert_eq!(BMV::from_static("SGVsbG8hIQ=="), "Hello!!".as_bytes());
805 assert_eq!(*"Hello!!".as_bytes(), BMV::from_static("SGVsbG8hIQ=="));
806}