1use std::marker::PhantomData;
6use std::iter::ExactSizeIterator;
7use std::fmt::{self, Debug};
8use std::collections::HashSet;
9use std::cmp::PartialEq;
10use std::hash::{Hash, Hasher};
11
12use total_order_multi_map::{
13 self,
14 TotalOrderMultiMap,
15 EntryValues,
16 EntryValuesMut
17};
18
19use ::error::{
20 HeaderTypeError,
21 HeaderValidationError,
22 BuildInValidationError
23};
24
25use ::name::{
26 HeaderName, HasHeaderName
27};
28
29use ::header::{
30 Header, HeaderKind,
31 HeaderObj, HeaderObjTrait,
32 MaxOneMarker
33};
34
35mod into_iter;
36pub use self::into_iter::*;
37
38pub type HeaderMapValidator = fn(&HeaderMap) -> Result<(), ::error::HeaderValidationError>;
43
44#[derive(Clone)]
139pub struct HeaderMap {
140 inner_map: TotalOrderMultiMap<HeaderName, Box<HeaderObj>>,
141}
142
143pub type Iter<'a> = total_order_multi_map::Iter<'a, HeaderName, Box<HeaderObj>>;
144pub type IterMut<'a> = total_order_multi_map::IterMut<'a, HeaderName, Box<HeaderObj>>;
145pub type Values<'a> = total_order_multi_map::Values<'a, HeaderName, Box<HeaderObj>>;
146pub type ValuesMut<'a> = total_order_multi_map::ValuesMut<'a, HeaderName, Box<HeaderObj>>;
147
148impl Debug for HeaderMap {
149 fn fmt(&self, fter: &mut fmt::Formatter) -> fmt::Result {
150 write!(fter, "HeaderMap {{ ")?;
151 for (key, val_cont) in self.iter() {
152 write!(fter, "{}: {:?},", key.as_str(), val_cont)?;
153 }
154 write!(fter, " }}")
155 }
156}
157
158impl Default for HeaderMap {
159 fn default() -> Self {
160 HeaderMap {
161 inner_map: Default::default()
162 }
163 }
164}
165
166impl HeaderMap {
167
168 pub fn new() -> Self {
170 Default::default()
171 }
172
173 pub fn len(&self) -> usize {
175 self.inner_map.len()
176 }
177
178 pub fn clear(&mut self) {
182 self.inner_map.clear();
183 }
184
185 pub fn values(&self) -> Values {
187 self.inner_map.values()
188 }
189
190 pub fn values_mut(&mut self) -> ValuesMut {
192 self.inner_map.values_mut()
193 }
194
195 pub fn use_contextual_validators(&self) -> Result<(), HeaderValidationError> {
206 let mut seen_validators = HashSet::new();
207
208 let mut validate = |validator| -> Result<(), HeaderValidationError> {
209 if let Some(validator) = validator {
210 if seen_validators.insert(ValidatorHashWrapper(validator)) {
211 (validator)(self)?;
212 }
213 }
214 Ok(())
215 };
216
217 for mut group in self.inner_map.group_iter() {
218 let first = group.next().expect("[BUG] returned header without any headers inserted for it");
219 let max_one = first.is_max_one();
220 validate(first.validator())?;
221 let header_name = group.key().as_str();
222 for other in group {
223 if max_one != other.is_max_one() {
224 return Err(BuildInValidationError::MaxOneInconsistency { header_name }.into());
225 }
226 validate(other.validator())?;
227 }
228 }
229 Ok(())
230 }
231
232 pub fn contains<H: HasHeaderName>(&self, name: H) -> bool {
234 self.inner_map.contains_key(name.get_name())
235 }
236
237 #[inline]
263 pub fn get_single<'a, H>(&'a self, _type_hint: H)
264 -> Option<Result<&'a Header<H>, HeaderTypeError>>
265 where H: MaxOneMarker
266 {
267 self._get_single::<H>()
268 }
269
270 pub fn _get_single<'a, H>(&'a self)
275 -> Option<Result<&'a Header<H>, HeaderTypeError>>
276 where H: MaxOneMarker
277 {
278 let mut bodies = self.get_untyped(H::name());
279 if bodies.len() > 1 {
280 return Some(Err(HeaderTypeError::new(H::name())))
281 }
282
283 bodies.next().map(|untyped| {
284 untyped.downcast_ref::<H>()
285 .ok_or_else(|| HeaderTypeError::new(H::name()))
286 })
287 }
288
289 #[inline]
293 pub fn get_single_mut<H>(&mut self, _type_hint: H)
294 -> Option<Result<&mut Header<H>, HeaderTypeError>>
295 where H: MaxOneMarker
296 {
297 self._get_single_mut::<H>()
298 }
299
300 pub fn _get_single_mut<H>(&mut self)
304 -> Option<Result<&mut Header<H>, HeaderTypeError>>
305 where H: MaxOneMarker
306 {
307 let mut bodies = self.get_untyped_mut(H::name());
308 if bodies.len() > 1 {
309 return Some(Err(HeaderTypeError::new(H::name())))
310 }
311
312 bodies.next().map(|untyped| {
313 untyped.downcast_mut::<H>()
314 .ok_or_else(|| HeaderTypeError::new(H::name()))
315 })
316 }
317
318 #[inline]
323 pub fn get_untyped<H: HasHeaderName>(&self, name: H) -> UntypedBodies {
324 self.inner_map.get(name.get_name())
325 }
326
327 #[inline]
332 pub fn get_untyped_mut<H: HasHeaderName>(&mut self, name: H) -> UntypedBodiesMut {
333 self.inner_map.get_mut(name.get_name())
334 }
335
336 #[inline(always)]
338 pub fn get<H>(&self, _type_hint: H) -> TypedBodies<H>
339 where H: HeaderKind
340 {
341 self._get::<H>()
342 }
343
344 pub fn _get<H>(&self) -> TypedBodies<H>
346 where H: HeaderKind
347 {
348 self.get_untyped(H::name()).into()
349 }
350
351 #[inline(always)]
353 pub fn get_mut<H>(&mut self, _type_hint: H) -> TypedBodiesMut<H>
354 where H: HeaderKind
355 {
356 self._get_mut::<H>()
357 }
358
359 pub fn _get_mut<H>(&mut self) -> TypedBodiesMut<H>
361 where H: HeaderKind
362 {
363 self.get_untyped_mut(H::name()).into()
364 }
365
366 pub fn insert<H>(&mut self, header: Header<H>)
382 where H: HeaderKind
383 {
384 let name = header.name();
385 let obj: Box<HeaderObj> = Box::new(header);
386 self._insert(name, H::MAX_ONE, obj)
387 }
388
389 #[doc(hidden)]
391 pub fn insert_untyped(&mut self, obj: Box<HeaderObj>) {
392 self._insert(obj.name(), obj.is_max_one(), obj)
393 }
394
395 #[inline(always)]
396 fn _insert(&mut self, name: HeaderName, max_one: bool, obj: Box<HeaderObj>) {
397 if max_one {
398 self.inner_map.set(name, obj);
399 } else {
400 self.inner_map.add(name, obj);
401 }
402 }
403
404 pub fn insert_all(&mut self, other: HeaderMap) {
445 for (_name, header) in other.into_iter() {
446 self.insert_untyped(header);
447 }
448 }
449
450 pub fn remove<H: HasHeaderName>(&mut self, name: H) -> bool {
454 self.inner_map.remove_all(name.get_name())
455 }
456
457 pub fn iter(&self) -> Iter {
459 self.inner_map.iter()
460 }
461
462}
463
464pub type UntypedBodies<'a> = EntryValues<'a, HeaderObj>;
466pub type UntypedBodiesMut<'a> = EntryValuesMut<'a, HeaderObj>;
467
468
469pub struct TypedBodies<'a, H>
474 where H: HeaderKind
475{
476 inner: UntypedBodies<'a>,
477 _marker: PhantomData<H>
478}
479
480impl<'a, H> From<UntypedBodies<'a>> for TypedBodies<'a, H>
481 where H: HeaderKind
482{
483 fn from(untyped: UntypedBodies<'a>) -> Self {
484 Self::new(untyped)
485 }
486}
487
488impl<'a, H> TypedBodies<'a, H>
489 where H: HeaderKind,
490{
491 fn new(inner: UntypedBodies<'a>) -> Self {
492 TypedBodies {
493 inner,
494 _marker: PhantomData
495 }
496 }
497}
498
499impl<'a, H> Iterator for TypedBodies<'a, H>
500 where H: HeaderKind
501{
502 type Item = Result<&'a Header<H>, HeaderTypeError>;
503
504 fn next(&mut self) -> Option<Self::Item> {
505 self.inner.next()
506 .map( |tobj| {
507 tobj.downcast_ref::<H>()
508 .ok_or_else(|| HeaderTypeError::new(H::name()))
509 } )
510 }
511
512 fn size_hint(&self) -> (usize, Option<usize>) {
513 self.inner.size_hint()
514 }
515}
516
517impl<'a, H> ExactSizeIterator for TypedBodies<'a, H>
518 where H: HeaderKind
519{
520 fn len(&self) -> usize {
521 self.inner.len()
522 }
523}
524
525impl<'a, H> Clone for TypedBodies<'a, H>
526 where H: HeaderKind
527{
528 fn clone(&self) -> Self {
529 TypedBodies::new(self.inner.clone())
530 }
531}
532
533impl<'a, H> Debug for TypedBodies<'a, H>
534 where H: HeaderKind
535{
536 fn fmt(&self, fter: &mut fmt::Formatter) -> fmt::Result {
537 fter.debug_struct("TypedBodies")
538 .field("inner", &self.inner)
539 .finish()
540 }
541}
542
543pub struct TypedBodiesMut<'a, H>
548 where H: HeaderKind
549{
550 inner: UntypedBodiesMut<'a>,
551 _marker: PhantomData<H>
552}
553
554impl<'a, H> From<UntypedBodiesMut<'a>> for TypedBodiesMut<'a, H>
555 where H: HeaderKind
556{
557 fn from(untyped: UntypedBodiesMut<'a>) -> Self {
558 Self::new(untyped)
559 }
560}
561
562impl<'a, H> TypedBodiesMut<'a, H>
563 where H: HeaderKind
564{
565 fn new(inner: UntypedBodiesMut<'a>) -> Self {
566 TypedBodiesMut {
567 inner,
568 _marker: PhantomData
569 }
570 }
571}
572
573impl<'a, H> Iterator for TypedBodiesMut<'a, H>
574 where H: HeaderKind
575{
576 type Item = Result<&'a mut Header<H>, HeaderTypeError>;
577
578 fn next(&mut self) -> Option<Self::Item> {
579 self.inner.next()
580 .map(|tobj| {
581 tobj.downcast_mut::<H>()
582 .ok_or_else(|| HeaderTypeError::new(H::name()))
583 })
584 }
585
586 fn size_hint(&self) -> (usize, Option<usize>) {
587 self.inner.size_hint()
588 }
589}
590
591impl<'a, H> ExactSizeIterator for TypedBodiesMut<'a, H>
592 where H: HeaderKind
593{
594 fn len(&self) -> usize {
595 self.inner.len()
596 }
597}
598
599impl<'a, H> Debug for TypedBodiesMut<'a, H>
600 where H: HeaderKind
601{
602 fn fmt(&self, fter: &mut fmt::Formatter) -> fmt::Result {
603 fter.write_str("TypedBodiesMut { .. }")
604 }
605}
606
607#[macro_export]
624macro_rules! headers {
625 ($($header:ty : $val:expr),*) => ({
626 (|| -> ::std::result::Result<$crate::HeaderMap, $crate::error::ComponentCreationError> {
628 let mut map = $crate::HeaderMap::new();
629 $(
630 map.insert(<$header as $crate::HeaderKind>::auto_body($val)?);
631 )*
632 Ok(map)
633 })()
634 });
635}
636
637#[derive(Copy, Clone)]
644struct ValidatorHashWrapper(HeaderMapValidator);
645
646impl ValidatorHashWrapper {
647
648 fn identity_repr(&self) -> usize {
649 self.0 as usize
650 }
651}
652
653impl PartialEq<Self> for ValidatorHashWrapper {
654 fn eq(&self, other: &Self) -> bool {
655 self.identity_repr() == other.identity_repr()
656 }
657}
658
659impl Eq for ValidatorHashWrapper {}
660
661impl Debug for ValidatorHashWrapper {
662 fn fmt(&self, fter: &mut fmt::Formatter) -> fmt::Result {
663 write!(fter, "ValidatorHashWrapper(0x{:x})", self.identity_repr())
664 }
665}
666
667impl Hash for ValidatorHashWrapper {
668 fn hash<H: Hasher>(&self, state: &mut H) {
669 state.write_usize(self.identity_repr())
670 }
671}
672
673
674pub fn check_header_count_max_one(name: HeaderName, map: &HeaderMap)
675 -> Result<(), HeaderValidationError>
676{
677 let valid = map.get_untyped(name).len() <= 1;
678 if valid {
679 Ok(())
680 } else {
681 Err(HeaderValidationError::from(
682 BuildInValidationError::MoreThenOne {
683 header_name: name.as_str()
684 }
685 ))
686 }
687}
688
689#[cfg(test)]
690mod test {
691 use failure::Context;
692 use soft_ascii_string::SoftAsciiStr;
693
694 use internals::error::{EncodingError, EncodingErrorKind};
695 use internals::encoder::{EncodableInHeader, EncodingWriter};
696
697 use ::HeaderTryFrom;
698 use ::error::{ComponentCreationError, HeaderValidationError};
699 use ::header_components::RawUnstructured;
700
701 use super::*;
702
703 use self::good_headers::*;
704 use self::bad_headers::{
705 Subject as BadSubject,
706 Comments as BadComments
707 };
708 use self::bad_headers2::{
709 Comments2 as BadComments2
710 };
711
712 #[derive(Debug, Clone, Eq, PartialEq, Hash)]
713 pub struct OtherComponent;
714
715 impl HeaderTryFrom<()> for OtherComponent {
716 fn try_from(_: ()) -> Result<OtherComponent, ComponentCreationError> {
717 Ok(OtherComponent)
718 }
719 }
720 impl EncodableInHeader for OtherComponent {
721 fn encode(&self, _encoder: &mut EncodingWriter) -> Result<(), EncodingError> {
722 Err(EncodingError::from(
723 EncodingErrorKind::Other { kind: "encoding is not implemented" }))
724 }
725
726 fn boxed_clone(&self) -> Box<EncodableInHeader> {
727 Box::new(self.clone())
728 }
729 }
730
731
732 mod good_headers {
733 use ::header_components;
734 def_headers! {
735 test_name: validate_header_names,
736 scope: header_components,
737 Subject, unchecked { "Subject" }, RawUnstructured, maxOne, None,
738 Comments, unchecked { "Comments" }, RawUnstructured, multi, None
739 }
740 }
741
742 mod bad_headers {
743 def_headers! {
744 test_name: validate_header_names,
745 scope: super,
746 Subject, unchecked { "Subject" }, OtherComponent, maxOne, None,
747 Comments, unchecked { "Comments" }, OtherComponent, multi, None
748 }
749 }
750 mod bad_headers2 {
751 def_headers! {
752 test_name: validate_header_names2,
753 scope: super,
754 Comments2, unchecked { "Comments" }, OtherComponent, maxOne, None
755 }
756 }
757
758 const TEXT_1: &str = "Random stuff XD";
759 const TEXT_2: &str = "Having a log of fun, yes a log!";
760
761 test!(max_one_mixup {
762 let headers = headers! {
763 BadComments2: (),
764 BadComments: ()
765 }?;
766
767 let res = headers.use_contextual_validators();
768 if let Err(HeaderValidationError::BuildIn(berr)) = res {
769 if let BuildInValidationError::MaxOneInconsistency { ..} = berr.get_context() {
770 return Ok(());
771 }
772 panic!("unexpected error: {:?}", berr);
773 }
774 panic!("unexpected result: {:?}", res);
775 });
776
777 #[test]
778 fn headers_macro() {
779 let headers = headers! {
780 Comments: TEXT_1,
781 Subject: TEXT_2
782 }.unwrap();
783
784
785 let count = headers
786 .get(Comments)
789 .map(|h: Result<&Header<Comments>, HeaderTypeError>| {
790 let v = h.expect( "the trait object to be downcastable to Header<Comments>" );
791 assert_eq!(v.as_str(), TEXT_1);
792 })
793 .count();
794 assert_eq!(1, count);
795
796 let count = headers
797 .get(Subject)
798 .map(|h: Result<&Header<Subject>, HeaderTypeError>| {
799 let val = h.expect( "the trait object to be downcastable to Header<Subject>" );
800 assert_eq!(val.as_str(), TEXT_2);
801 })
802 .count();
803 assert_eq!(1, count);
804 }
805
806 #[test]
807 fn get_single() {
808 let headers = headers! {
809 Subject: "abc"
810 }.unwrap();
811
812 assert_eq!(
813 "abc",
814 headers.get_single(Subject)
815 .unwrap().unwrap().as_str()
818 );
819 }
820
821 #[test]
822 fn get_single_cast_error() {
823 let headers = headers! {
824 Subject: "abc"
825 }.unwrap();
826
827 let res = headers.get_single(BadSubject);
828 assert_err!( res.expect("where did the header go?") );
829 }
830
831 #[test]
832 fn get() {
833 let headers = headers! {
834 Subject: "abc",
835 Comments: "1st",
836 BadComments: ()
837 }.unwrap();
838
839
840 let mut res = headers.get(Comments);
841
842 assert_eq!(res.size_hint(), (2, Some(2)));
843
844 assert_eq!(
845 "1st",
846 assert_ok!(res.next().unwrap()).as_str()
847 );
848
849 assert_err!(res.next().unwrap());
850
851 assert!( res.next().is_none() )
852
853 }
854
855 #[test]
856 fn get_untyped() {
857 let headers = headers! {
858 Subject: "abc",
859 Comments: "1st",
860 BadComments: ()
861 }.unwrap();
862
863
864 let res = headers.get_untyped(Subject::name())
865 .map(|entry| entry.downcast_ref::<Subject>().unwrap().as_str() )
866 .collect::<Vec<_>>();
867
868 assert_eq!(
869 res.as_slice(),
870 &[ "abc" ]
871 );
872
873 let mut res = headers.get_untyped(Comments::name());
874
875 assert_eq!((2, Some(2)), res.size_hint());
876
877 assert_eq!(
878 res.next().unwrap().downcast_ref::<Comments>().unwrap().as_str(),
879 "1st"
880 );
881
882 assert_eq!((1, Some(1)), res.size_hint());
883
884 assert_eq!(
885 res.next().unwrap().downcast_ref::<BadComments>().unwrap().body(),
886 &OtherComponent
887 );
888
889 assert!(res.next().is_none());
890 }
891
892 #[test]
893 fn fmt_debug() {
894 let headers = headers! {
895 Subject: "hy there"
896 }.unwrap();
897
898 let res = format!("{:?}", headers);
899 assert_eq!(
900 "HeaderMap { Subject: RawUnstructured { text: Input(Owned(\"hy there\")) }, }",
901 res.as_str()
902 );
903 }
904
905 test!(combine_keeps_order {
906 let mut headers = headers! {
907 XComment: "ab@c"
908 }?;
909
910 headers.insert_all(headers! {
911 Subject: "hy there",
912 Comments: "magic+spell"
913 }?);
914
915 assert_eq!(
916 &[
917 "X-Comment",
918 "Subject",
919 "Comments"
920 ],
921 headers.into_iter()
922 .map(|(name, _val)| name.as_str())
923 .collect::<Vec<_>>()
924 .as_slice()
925 );
926 });
927
928
929 test!(remove_1 {
930 let mut headers = headers!{
931 Comments: "a",
932 Subject: "b",
933 Comments: "c",
934 Comments: "d"
935 }?;
936
937 assert_eq!( false, headers.remove(XComment::name()));
938 assert_eq!( true, headers.remove(Subject::name()));
939
940 assert_eq!( 3, headers.iter().count() );
941
942 let values = headers.get(Comments)
943 .map(|comp| comp.unwrap().as_str() )
944 .collect::<Vec<_>>();
945
946 assert_eq!(
947 &[ "a", "c", "d" ],
948 values.as_slice()
949 );
950 });
951
952 test!(remove_2 {
953 let mut headers = headers!{
954 Comments: "a",
955 Subject: "b",
956 Comments: "c",
957 Comments: "d"
958 }?;
959
960 assert_eq!(true, headers.remove(Comments::name()));
961 assert_eq!(false, headers.remove(Comments::name()));
962
963 assert_eq!(1, headers.iter().count());
964
965 let values = headers.get(Subject)
966 .map(|comp| comp.unwrap().as_str())
967 .collect::<Vec<_>>();
968
969 assert_eq!(
970 &[ "b" ],
971 values.as_slice()
972 );
973 });
974
975 #[derive(Default, Copy, Clone)]
976 struct XComment;
977 impl HeaderKind for XComment {
978 type Component = RawUnstructured;
979
980 fn name() -> HeaderName {
981 HeaderName::new(SoftAsciiStr::from_unchecked("X-Comment")).unwrap()
982 }
983
984 const VALIDATOR: Option<
985 fn(&HeaderMap)-> Result<(), HeaderValidationError>
986 > = Some(__validator);
987
988 const MAX_ONE: bool = false;
989 }
990
991 fn __validator(map: &HeaderMap) -> Result<(), HeaderValidationError> {
993 if map.get_untyped(Comments::name()).len() != 0 {
994 return Err(HeaderValidationError::Custom(
995 Context::new("can't have X-Comment and Comments in same mail")
996 .into()
997 ));
998 }
999 Ok(())
1000 }
1001
1002 test!(contains_works {
1003 let map = headers! {
1004 Subject: "soso"
1005 }?;
1006
1007 assert_eq!( true, map.contains( Subject::name() ));
1008 assert_eq!( true, map.contains( Subject ));
1009 assert_eq!( false, map.contains( Comments::name() ));
1010 assert_eq!( false, map.contains( Comments ));
1011 });
1012
1013 test!(use_validator_ok {
1014 let map = headers! {
1015 XComment: "yay",
1016 Subject: "soso"
1017 }?;
1018
1019 assert_ok!(map.use_contextual_validators());
1020 });
1021
1022 test!(use_validator_err {
1023 let map = headers! {
1024 XComment: "yay",
1025 Comments: "oh no",
1026 Subject: "soso"
1027 }?;
1028
1029 assert_err!(map.use_contextual_validators());
1030 });
1031
1032 test!(has_len {
1033 let map = headers! {
1034 XComment: "yay",
1035 Comments: "oh no",
1036 Subject: "soso"
1037 }?;
1038
1039 assert_eq!(3, map.len());
1040 });
1041
1042 test!(does_not_conflic_with_custom_result_type {
1043 #[allow(unused)]
1044 type Result<T> = ::std::result::Result<T, ()>;
1045
1046 let map = headers! {
1047 Subject: "yay"
1048 }?;
1049
1050 assert_eq!(1, map.len());
1051 });
1052}