1use std::borrow::Cow;
157use std::fmt;
158
159use unicase::Ascii;
160
161use self::sealed::HeaderClone;
162
163pub use self::shared::*;
164pub use self::common::*;
165pub use self::raw::{Raw, RawLike};
166
167#[cfg(feature = "headers")]
168use std::{
169 borrow::ToOwned,
170 iter::{FromIterator, IntoIterator},
171 mem,
172};
173
174#[cfg(feature = "headers")]
175use self::internals::{Item, VecMap, Entry};
176
177#[cfg(feature = "headers")]
178use bytes::Bytes;
179
180pub use self::compat::{TypedHeaders, StandardHeader, ValueMapIter};
181
182mod common;
183mod internals;
184mod raw;
185mod shared;
186pub mod parsing;
187mod compat;
188
189pub trait Header: 'static + HeaderClone + Send + Sync {
194 fn header_name() -> &'static str
198 where Self: Sized;
199
200 fn parse_header<'a, T>(raw: &'a T) -> ::Result<Self>
208 where T: RawLike<'a>, Self: Sized;
209
210 fn fmt_header(&self, f: &mut Formatter) -> fmt::Result;
224}
225
226mod sealed {
227 use super::Header;
228
229 #[doc(hidden)]
230 pub trait HeaderClone {
231 fn clone_box(&self) -> Box<dyn Header + Send + Sync>;
232 }
233
234 impl<T: Header + Clone> HeaderClone for T {
235 #[inline]
236 fn clone_box(&self) -> Box<dyn Header + Send + Sync> {
237 Box::new(self.clone())
238 }
239 }
240}
241
242#[allow(missing_debug_implementations)]
244pub struct Formatter<'a, 'b: 'a>(Multi<'a, 'b>);
245
246#[allow(unused)]
247enum Multi<'a, 'b: 'a> {
248 Line(&'a str, &'a mut fmt::Formatter<'b>),
249 Join(bool, &'a mut fmt::Formatter<'b>),
250 Raw(&'a mut Raw),
251}
252
253impl<'a, 'b> Formatter<'a, 'b> {
254
255 pub fn fmt_line(&mut self, line: &dyn fmt::Display) -> fmt::Result {
267 use std::fmt::Write;
268 match self.0 {
269 Multi::Line(name, ref mut f) => {
270 f.write_str(name)?;
271 f.write_str(": ")?;
272 write!(NewlineReplacer(*f), "{}", line)?;
273 f.write_str("\r\n")
274 },
275 Multi::Join(ref mut first, ref mut f) => {
276 if !*first {
277 f.write_str(", ")?;
278 } else {
279 *first = false;
280 }
281 write!(NewlineReplacer(*f), "{}", line)
282 }
283 Multi::Raw(ref mut raw) => {
284 let mut s = String::new();
285 write!(NewlineReplacer(&mut s), "{}", line)?;
286 raw.push(s);
287 Ok(())
288 }
289 }
290 }
291
292 fn danger_fmt_line_without_newline_replacer<T: fmt::Display>(&mut self, line: &T) -> fmt::Result {
293 use std::fmt::Write;
294 match self.0 {
295 Multi::Line(name, ref mut f) => {
296 f.write_str(name)?;
297 f.write_str(": ")?;
298 fmt::Display::fmt(line, f)?;
299 f.write_str("\r\n")
300 },
301 Multi::Join(ref mut first, ref mut f) => {
302 if !*first {
303 f.write_str(", ")?;
304 } else {
305 *first = false;
306 }
307 fmt::Display::fmt(line, f)
308 }
309 Multi::Raw(ref mut raw) => {
310 let mut s = String::new();
311 write!(s, "{}", line)?;
312 raw.push(s);
313 Ok(())
314 }
315 }
316 }
317}
318
319#[cfg(feature = "headers")]
320struct ValueString<'a>(&'a Item);
321
322#[cfg(feature = "headers")]
323impl<'a> fmt::Debug for ValueString<'a> {
324 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
325 f.write_str("\"")?;
326 self.0.write_h1(&mut Formatter(Multi::Join(true, f)))?;
327 f.write_str("\"")
328 }
329}
330
331#[cfg(feature = "headers")]
332impl<'a> fmt::Display for ValueString<'a> {
333 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
334 self.0.write_h1(&mut Formatter(Multi::Join(true, f)))
335 }
336}
337
338struct NewlineReplacer<'a, F: fmt::Write + 'a>(&'a mut F);
339
340impl<'a, F: fmt::Write + 'a> fmt::Write for NewlineReplacer<'a, F> {
341 #[inline]
342 fn write_str(&mut self, s: &str) -> fmt::Result {
343 let mut since = 0;
344 for (i, &byte) in s.as_bytes().iter().enumerate() {
345 if byte == b'\r' || byte == b'\n' {
346 self.0.write_str(&s[since..i])?;
347 self.0.write_str(" ")?;
348 since = i + 1;
349 }
350 }
351 if since < s.len() {
352 self.0.write_str(&s[since..])
353 } else {
354 Ok(())
355 }
356 }
357
358 #[inline]
359 fn write_fmt(&mut self, args: fmt::Arguments) -> fmt::Result {
360 fmt::write(self, args)
361 }
362}
363
364impl dyn Header + Send + Sync {
365 #[cfg(feature = "headers")]
374 #[inline]
375 unsafe fn downcast_ref_unchecked<T: 'static>(&self) -> &T {
376 &*(mem::transmute::<*const _, (*const (), *const ())>(self).0 as *const T)
377 }
378
379 #[cfg(feature = "headers")]
380 #[inline]
381 unsafe fn downcast_mut_unchecked<T: 'static>(&mut self) -> &mut T {
382 &mut *(mem::transmute::<*mut _, (*mut (), *mut ())>(self).0 as *mut T)
383 }
384
385 #[cfg(feature = "headers")]
386 #[inline]
387 unsafe fn downcast_unchecked<T: 'static>(self: Box<Self>) -> T {
388 *Box::from_raw(mem::transmute::<*mut _, (*mut (), *mut ())>(Box::into_raw(self)).0 as *mut T)
389 }
390}
391
392impl Clone for Box<dyn Header + Send + Sync> {
393 #[inline]
394 fn clone(&self) -> Box<dyn Header + Send + Sync> {
395 self.clone_box()
396 }
397}
398
399#[cfg(feature = "headers")]
400#[inline]
401fn header_name<T: Header>() -> &'static str {
402 <T as Header>::header_name()
403}
404
405#[cfg(feature = "headers")]
412#[derive(Clone)]
413pub struct Headers {
414 data: VecMap<HeaderName, Item>,
415}
416
417#[cfg(feature = "headers")]
418impl Default for Headers {
419 fn default() -> Headers {
420 Headers::new()
421 }
422}
423
424macro_rules! literals {
425 ($($len:expr => $($header:path),+;)+) => (
426 #[cfg(feature = "headers")]
427 fn maybe_literal(s: &str) -> Cow<'static, str> {
428 match s.len() {
429 $($len => {
430 $(
431 if Ascii::new(<$header>::header_name()) == Ascii::new(s) {
432 return Cow::Borrowed(<$header>::header_name());
433 }
434 )+
435 })+
436
437 _ => ()
438 }
439
440 Cow::Owned(s.to_owned())
441 }
442
443 #[test]
444 fn test_literal_lens() {
445 $(
446 $({
447 let s = <$header>::header_name();
448 assert!(s.len() == $len, "{:?} has len of {}, listed as {}", s, s.len(), $len);
449 })+
450 )+
451 }
452 );
453}
454
455literals! {
456 4 => Host, Date, ETag;
457 5 => Allow, Range;
458 6 => Accept, Cookie, Server, Expect;
459 7 => Upgrade, Referer, Expires;
460 8 => Location, IfMatch, IfRange;
461 10 => UserAgent, Connection, SetCookie;
462 12 => ContentType;
463 13 => Authorization<String>, CacheControl, LastModified, IfNoneMatch, AcceptRanges, ContentRange;
464 14 => ContentLength, AcceptCharset;
465 15 => AcceptEncoding, AcceptLanguage;
466 17 => TransferEncoding;
467 25 => StrictTransportSecurity;
468 27 => AccessControlAllowOrigin;
469}
470
471#[cfg(feature = "headers")]
472impl Headers {
473
474 #[inline]
476 pub fn new() -> Headers {
477 Headers::with_capacity(0)
478 }
479
480 #[inline]
482 pub fn with_capacity(len: usize) -> Headers {
483 Headers {
484 data: VecMap::with_capacity(len)
485 }
486 }
487
488 pub fn set<H: Header>(&mut self, value: H) {
492 self.data.insert(HeaderName(Ascii::new(Cow::Borrowed(header_name::<H>()))),
493 Item::new_typed(value));
494 }
495
496 pub fn get<H: Header>(&self) -> Option<&H> {
498 self.data.get(&HeaderName(Ascii::new(Cow::Borrowed(header_name::<H>()))))
499 .and_then(Item::typed::<H>)
500 }
501
502 pub fn get_mut<H: Header>(&mut self) -> Option<&mut H> {
504 self.data.get_mut(&HeaderName(Ascii::new(Cow::Borrowed(header_name::<H>()))))
505 .and_then(Item::typed_mut::<H>)
506 }
507
508 pub fn has<H: Header>(&self) -> bool {
520 self.data.contains_key(&HeaderName(Ascii::new(Cow::Borrowed(header_name::<H>()))))
521 }
522
523 pub fn remove<H: Header>(&mut self) -> Option<H> {
529 self.data.remove(&HeaderName(Ascii::new(Cow::Borrowed(header_name::<H>()))))
530 .and_then(Item::into_typed::<H>)
531 }
532
533 pub fn iter(&self) -> HeadersItems {
535 HeadersItems {
536 inner: self.data.iter()
537 }
538 }
539
540 pub fn len(&self) -> usize {
542 self.data.len()
543 }
544
545 pub fn clear(&mut self) {
547 self.data.clear()
548 }
549
550 pub fn get_raw(&self, name: &str) -> Option<&Raw> {
564 self.data
565 .get(name)
566 .map(Item::raw)
567 }
568
569 pub fn set_raw<K: Into<Cow<'static, str>>, V: Into<Raw>>(&mut self, name: K, value: V) {
582 let name = name.into();
583 let value = value.into();
584 self.data.insert(HeaderName(Ascii::new(name)), Item::new_raw(value));
585 }
586
587 pub fn append_raw<K: Into<Cow<'static, str>>, V: Into<Raw>>(&mut self, name: K, value: V) {
603 let name = name.into();
604 let value = value.into();
605 let name = HeaderName(Ascii::new(name));
606 if let Some(item) = self.data.get_mut(&name) {
607 item.raw_mut().push(value);
608 return;
609 }
610 self.data.insert(name, Item::new_raw(value));
611 }
612
613 pub fn append_raw_str<V: Into<Raw>>(&mut self, name: &str, value: V) {
616 let value = value.into();
617 if let Some(item) = self.data.get_mut(name) {
618 item.raw_mut().push(value);
619 return;
620 }
621 let name = HeaderName(Ascii::new(name.to_owned().into()));
622 self.data.insert(name, Item::new_raw(value));
623 }
624
625 pub fn remove_raw(&mut self, name: &str) {
627 self.data.remove(name);
628 }
629
630}
631
632#[cfg(feature = "headers")]
633impl PartialEq for Headers {
634 fn eq(&self, other: &Headers) -> bool {
635 if self.len() != other.len() {
636 return false;
637 }
638
639 for header in self.iter() {
640 match other.get_raw(header.name()) {
641 Some(val) if val == self.get_raw(header.name()).unwrap() => {},
642 _ => { return false; }
643 }
644 }
645 true
646 }
647}
648
649#[cfg(feature = "headers")]
650impl fmt::Display for Headers {
651 #[inline]
652 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
653 for header in self.iter() {
654 fmt::Display::fmt(&header, f)?;
655 }
656 Ok(())
657 }
658}
659
660#[cfg(feature = "headers")]
661impl fmt::Debug for Headers {
662 #[inline]
663 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
664 f.debug_map()
665 .entries(self.iter().map(|view| (view.0.as_ref(), ValueString(view.1))))
666 .finish()
667 }
668}
669
670#[cfg(feature = "headers")]
672#[allow(missing_debug_implementations)]
673pub struct HeadersItems<'a> {
674 inner: ::std::slice::Iter<'a, (HeaderName, Item)>
675}
676
677#[cfg(feature = "headers")]
678impl<'a> Iterator for HeadersItems<'a> {
679 type Item = HeaderView<'a>;
680
681 fn next(&mut self) -> Option<HeaderView<'a>> {
682 self.inner.next().map(|&(ref k, ref v)| HeaderView(k, v))
683 }
684}
685
686#[cfg(feature = "headers")]
688pub struct HeaderView<'a>(&'a HeaderName, &'a Item);
689
690#[cfg(feature = "headers")]
691impl<'a> HeaderView<'a> {
692 #[inline]
694 pub fn is<H: Header>(&self) -> bool {
695 HeaderName(Ascii::new(Cow::Borrowed(header_name::<H>()))) == *self.0
696 }
697
698 #[inline]
700 pub fn name(&self) -> &'a str {
701 self.0.as_ref()
702 }
703
704 #[inline]
706 pub fn value<H: Header>(&self) -> Option<&'a H> {
707 self.1.typed::<H>()
708 }
709
710 #[inline]
717 pub fn value_string(&self) -> String {
718 ValueString(self.1).to_string()
719 }
720
721 #[inline]
723 pub fn raw(&self) -> &Raw {
724 self.1.raw()
725 }
726}
727
728#[cfg(feature = "headers")]
729impl<'a> fmt::Display for HeaderView<'a> {
730 #[inline]
731 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
732 self.1.write_h1(&mut Formatter(Multi::Line(self.0.as_ref(), f)))
733 }
734}
735
736#[cfg(feature = "headers")]
737impl<'a> fmt::Debug for HeaderView<'a> {
738 #[inline]
739 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
740 fmt::Display::fmt(self, f)
741 }
742}
743
744#[cfg(feature = "headers")]
745impl<'a> Extend<HeaderView<'a>> for Headers {
746 fn extend<I: IntoIterator<Item=HeaderView<'a>>>(&mut self, iter: I) {
747 for header in iter {
748 self.data.insert((*header.0).clone(), (*header.1).clone());
749 }
750 }
751}
752
753#[cfg(feature = "headers")]
754impl<'a> Extend<(&'a str, Bytes)> for Headers {
755 fn extend<I: IntoIterator<Item=(&'a str, Bytes)>>(&mut self, iter: I) {
756 for (name, value) in iter {
757 let name = HeaderName(Ascii::new(maybe_literal(name)));
758 match self.data.entry(name) {
761 Entry::Vacant(entry) => {
762 entry.insert(Item::new_raw(self::raw::parsed(value)));
763 }
764 Entry::Occupied(entry) => {
765 self::raw::push(entry.into_mut().raw_mut(), value);
766 }
767 };
768 }
769 }
770}
771
772#[cfg(feature = "headers")]
773impl<'a> FromIterator<HeaderView<'a>> for Headers {
774 fn from_iter<I: IntoIterator<Item=HeaderView<'a>>>(iter: I) -> Headers {
775 let mut headers = Headers::new();
776 headers.extend(iter);
777 headers
778 }
779}
780
781#[derive(Clone, Debug)]
782struct HeaderName(Ascii<Cow<'static, str>>);
783
784impl fmt::Display for HeaderName {
785 #[inline]
786 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
787 fmt::Display::fmt(self.0.as_ref(), f)
788 }
789}
790
791impl AsRef<str> for HeaderName {
792 fn as_ref(&self) -> &str {
793 self.0.as_ref()
794 }
795}
796
797impl PartialEq for HeaderName {
798 #[inline]
799 fn eq(&self, other: &HeaderName) -> bool {
800 let s = self.as_ref();
801 let k = other.as_ref();
802 if s.as_ptr() == k.as_ptr() && s.len() == k.len() {
803 true
804 } else {
805 self.0 == other.0
806 }
807 }
808}
809
810impl PartialEq<HeaderName> for str {
811 fn eq(&self, other: &HeaderName) -> bool {
812 let k = other.as_ref();
813 if self.as_ptr() == k.as_ptr() && self.len() == k.len() {
814 true
815 } else {
816 other.0 == self
817 }
818 }
819}
820
821#[cfg(all(test, feature = "headers"))]
822mod tests {
823 use std::fmt;
824
825 use super::{
826 Header, Headers, ContentLength, ContentType, Host, RawLike, SetCookie
827 };
828
829 #[cfg(feature = "nightly")]
830 use test::Bencher;
831
832 macro_rules! make_header {
833 ($name:expr, $value:expr) => ({
834 let mut headers = Headers::new();
835 headers.set_raw(String::from_utf8($name.to_vec()).unwrap(), $value.to_vec());
836 headers
837 });
838 ($text:expr) => ({
839 let bytes = $text;
840 let colon = bytes.iter().position(|&x| x == b':').unwrap();
841 make_header!(&bytes[..colon], &bytes[colon + 2..])
842 })
843 }
844
845 #[test]
846 fn test_from_raw() {
847 let headers = make_header!(b"Content-Length", b"10");
848 assert_eq!(headers.get(), Some(&ContentLength(10)));
849 }
850
851 #[derive(Clone, PartialEq, Debug)]
852 struct CrazyLength(Option<bool>, usize);
853
854 impl Header for CrazyLength {
855 fn header_name() -> &'static str {
856 "content-length"
857 }
858 fn parse_header<'a, T>(raw: &'a T) -> ::Result<CrazyLength>
859 where T: RawLike<'a>
860 {
861 use std::str::from_utf8;
862 use std::str::FromStr;
863
864 if let Some(line) = raw.one() {
865 let s = from_utf8(line).map(|s| FromStr::from_str(s).map_err(|_| ::Error::Header))?;
866 s.map(|u| CrazyLength(Some(false), u))
867 } else {
868 Err(::Error::Header)
869 }
870 }
871
872 fn fmt_header(&self, f: &mut super::Formatter) -> fmt::Result {
873 f.fmt_line(self)
874 }
875 }
876
877 impl fmt::Display for CrazyLength {
878 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
879 let CrazyLength(ref opt, ref value) = *self;
880 write!(f, "{:?}, {:?}", opt, value)
881 }
882 }
883
884 #[test]
885 fn test_different_structs_for_same_header() {
886 let headers = make_header!(b"Content-Length: 10");
887 assert_eq!(headers.get::<ContentLength>(), Some(&ContentLength(10)));
888 assert_eq!(headers.get::<CrazyLength>(), Some(&CrazyLength(Some(false), 10)));
889 }
890
891 #[test]
892 fn test_trailing_whitespace() {
893 let headers = make_header!(b"Content-Length: 10 ");
894 assert_eq!(headers.get::<ContentLength>(), Some(&ContentLength(10)));
895 }
896
897 #[test]
898 fn test_multiple_reads() {
899 let headers = make_header!(b"Content-Length: 10");
900 let ContentLength(one) = *headers.get::<ContentLength>().unwrap();
901 let ContentLength(two) = *headers.get::<ContentLength>().unwrap();
902 assert_eq!(one, two);
903 }
904
905 #[test]
906 fn test_different_reads() {
907 let mut headers = Headers::new();
908 headers.set_raw("Content-Length", "10");
909 headers.set_raw("Content-Type", "text/plain");
910 let ContentLength(_) = *headers.get::<ContentLength>().unwrap();
911 let ContentType(_) = *headers.get::<ContentType>().unwrap();
912 }
913
914 #[test]
915 fn test_typed_get_raw() {
916 let mut headers = Headers::new();
917 headers.set(ContentLength(15));
918 assert_eq!(headers.get_raw("content-length").unwrap(), "15");
919
920 headers.set(SetCookie(vec![
921 "foo=bar".to_string(),
922 "baz=quux; Path=/path".to_string()
923 ]));
924 assert_eq!(headers.get_raw("set-cookie").unwrap(), &["foo=bar", "baz=quux; Path=/path"][..]);
925 }
926
927 #[test]
928 fn test_get_mutable() {
929 let mut headers = make_header!(b"Content-Length: 10");
930 *headers.get_mut::<ContentLength>().unwrap() = ContentLength(20);
931 assert_eq!(headers.get_raw("content-length").unwrap(), &[b"20".to_vec()][..]);
932 assert_eq!(*headers.get::<ContentLength>().unwrap(), ContentLength(20));
933 }
934
935 #[test]
936 fn test_headers_to_string() {
937 let mut headers = Headers::new();
938 headers.set(ContentLength(15));
939 headers.set(Host::new("foo.bar", None));
940
941 let s = headers.to_string();
942 assert!(s.contains("Host: foo.bar\r\n"));
943 assert!(s.contains("Content-Length: 15\r\n"));
944 }
945
946 #[test]
947 fn test_headers_to_string_raw() {
948 let mut headers = make_header!(b"Content-Length: 10");
949 headers.set_raw("x-foo", vec![b"foo".to_vec(), b"bar".to_vec()]);
950 let s = headers.to_string();
951 assert_eq!(s, "Content-Length: 10\r\nx-foo: foo\r\nx-foo: bar\r\n");
952 }
953
954 #[test]
955 fn test_set_raw() {
956 let mut headers = Headers::new();
957 headers.set(ContentLength(10));
958 headers.set_raw("content-LENGTH", vec![b"20".to_vec()]);
959 assert_eq!(headers.get_raw("Content-length").unwrap(), &[b"20".to_vec()][..]);
960 assert_eq!(headers.get(), Some(&ContentLength(20)));
961 }
962
963 #[test]
964 fn test_append_raw() {
965 let mut headers = Headers::new();
966 headers.set(ContentLength(10));
967 headers.append_raw("content-LENGTH", b"20".to_vec());
968 assert_eq!(headers.get_raw("Content-length").unwrap(), &[b"10".to_vec(), b"20".to_vec()][..]);
969 headers.append_raw("x-foo", "bar");
970 assert_eq!(headers.get_raw("x-foo").unwrap(), &[b"bar".to_vec()][..]);
971 }
972
973 #[test]
974 fn test_remove_raw() {
975 let mut headers = Headers::new();
976 headers.set_raw("content-LENGTH", vec![b"20".to_vec()]);
977 headers.remove_raw("content-LENGTH");
978 assert_eq!(headers.get_raw("Content-length"), None);
979 }
980
981 #[test]
982 fn test_remove() {
983 let mut headers = Headers::new();
984 headers.set(ContentLength(10));
985 assert_eq!(headers.remove(), Some(ContentLength(10)));
986 assert_eq!(headers.len(), 0);
987
988 headers.set(ContentLength(9));
989 assert_eq!(headers.len(), 1);
990 assert!(headers.remove::<CrazyLength>().is_none());
991 assert_eq!(headers.len(), 0);
992 }
993
994 #[test]
995 fn test_len() {
996 let mut headers = Headers::new();
997 headers.set(ContentLength(10));
998 assert_eq!(headers.len(), 1);
999 headers.set(ContentType::json());
1000 assert_eq!(headers.len(), 2);
1001 headers.set(ContentLength(20));
1003 assert_eq!(headers.len(), 2);
1004 }
1005
1006 #[test]
1007 fn test_clear() {
1008 let mut headers = Headers::new();
1009 headers.set(ContentLength(10));
1010 headers.set(ContentType::json());
1011 assert_eq!(headers.len(), 2);
1012 headers.clear();
1013 assert_eq!(headers.len(), 0);
1014 }
1015
1016 #[test]
1017 fn test_iter() {
1018 let mut headers = Headers::new();
1019 headers.set(ContentLength(11));
1020 for header in headers.iter() {
1021 assert!(header.is::<ContentLength>());
1022 assert_eq!(header.name(), <ContentLength as Header>::header_name());
1023 assert_eq!(header.value(), Some(&ContentLength(11)));
1024 assert_eq!(header.value_string(), "11".to_owned());
1025 }
1026 }
1027
1028 #[test]
1029 fn test_header_view_value_string() {
1030 let mut headers = Headers::new();
1031 headers.set_raw("foo", vec![b"one".to_vec(), b"two".to_vec()]);
1032 for header in headers.iter() {
1033 assert_eq!(header.name(), "foo");
1034 assert_eq!(header.value_string(), "one, two");
1035 }
1036 }
1037
1038 #[test]
1039 fn test_header_view_raw() {
1040 let mut headers = Headers::new();
1041 headers.set_raw("foo", vec![b"one".to_vec(), b"two".to_vec()]);
1042 for header in headers.iter() {
1043 assert_eq!(header.name(), "foo");
1044 let values: Vec<&[u8]> = header.raw().iter().collect();
1045 assert_eq!(values, vec![b"one", b"two"]);
1046 }
1047 }
1048
1049 #[test]
1050 fn test_eq() {
1051 let mut headers1 = Headers::new();
1052 let mut headers2 = Headers::new();
1053
1054 assert_eq!(headers1, headers2);
1055
1056 headers1.set(ContentLength(11));
1057 headers2.set(Host::new("foo.bar", None));
1058 assert_ne!(headers1, headers2);
1059
1060 headers1 = Headers::new();
1061 headers2 = Headers::new();
1062
1063 headers1.set(ContentLength(11));
1064 headers2.set(ContentLength(11));
1065 assert_eq!(headers1, headers2);
1066
1067 headers1.set(ContentLength(10));
1068 assert_ne!(headers1, headers2);
1069
1070 headers1 = Headers::new();
1071 headers2 = Headers::new();
1072
1073 headers1.set(Host::new("foo.bar", None));
1074 headers1.set(ContentLength(11));
1075 headers2.set(ContentLength(11));
1076 assert_ne!(headers1, headers2);
1077 }
1078
1079 #[cfg(feature = "nightly")]
1080 #[bench]
1081 fn bench_headers_new(b: &mut Bencher) {
1082 b.iter(|| {
1083 let mut h = Headers::new();
1084 h.set(ContentLength(11));
1085 h
1086 })
1087 }
1088
1089 #[cfg(feature = "nightly")]
1090 #[bench]
1091 fn bench_headers_get(b: &mut Bencher) {
1092 let mut headers = Headers::new();
1093 headers.set(ContentLength(11));
1094 b.iter(|| assert_eq!(headers.get::<ContentLength>(), Some(&ContentLength(11))))
1095 }
1096
1097 #[cfg(feature = "nightly")]
1098 #[bench]
1099 fn bench_headers_get_miss(b: &mut Bencher) {
1100 let headers = Headers::new();
1101 b.iter(|| assert!(headers.get::<ContentLength>().is_none()))
1102 }
1103
1104 #[cfg(feature = "nightly")]
1105 #[bench]
1106 fn bench_headers_get_miss_previous_10(b: &mut Bencher) {
1107 let mut headers = Headers::new();
1108 for i in 0..10 {
1109 headers.set_raw(format!("non-standard-{}", i), "hi");
1110 }
1111 b.iter(|| assert!(headers.get::<ContentLength>().is_none()))
1112 }
1113
1114 #[cfg(feature = "nightly")]
1115 #[bench]
1116 fn bench_headers_set(b: &mut Bencher) {
1117 let mut headers = Headers::new();
1118 b.iter(|| headers.set(ContentLength(12)))
1119 }
1120
1121 #[cfg(feature = "nightly")]
1122 #[bench]
1123 fn bench_headers_set_previous_10(b: &mut Bencher) {
1124 let mut headers = Headers::new();
1125 for i in 0..10 {
1126 headers.set_raw(format!("non-standard-{}", i), "hi");
1127 }
1128 b.iter(|| headers.set(ContentLength(12)))
1129 }
1130
1131 #[cfg(feature = "nightly")]
1132 #[bench]
1133 fn bench_headers_set_raw(b: &mut Bencher) {
1134 let mut headers = Headers::new();
1135 b.iter(|| headers.set_raw("non-standard", "hello"))
1136 }
1137
1138 #[cfg(feature = "nightly")]
1139 #[bench]
1140 fn bench_headers_set_raw_previous_10(b: &mut Bencher) {
1141 let mut headers = Headers::new();
1142 for i in 0..10 {
1143 headers.set_raw(format!("non-standard-{}", i), "hi");
1144 }
1145 b.iter(|| headers.set_raw("non-standard", "hello"))
1146 }
1147
1148 #[cfg(feature = "nightly")]
1149 #[bench]
1150 fn bench_headers_has(b: &mut Bencher) {
1151 let mut headers = Headers::new();
1152 headers.set(ContentLength(11));
1153 b.iter(|| assert!(headers.has::<ContentLength>()))
1154 }
1155
1156 #[cfg(feature = "nightly")]
1157 #[bench]
1158 fn bench_headers_view_is(b: &mut Bencher) {
1159 let mut headers = Headers::new();
1160 headers.set(ContentLength(11));
1161 let mut iter = headers.iter();
1162 let view = iter.next().unwrap();
1163 b.iter(|| assert!(view.is::<ContentLength>()))
1164 }
1165
1166 #[cfg(feature = "nightly")]
1167 #[bench]
1168 fn bench_headers_fmt(b: &mut Bencher) {
1169 use std::fmt::Write;
1170 let mut buf = String::with_capacity(64);
1171 let mut headers = Headers::new();
1172 headers.set(ContentLength(11));
1173 headers.set(ContentType::json());
1174 b.bytes = headers.to_string().len() as u64;
1175 b.iter(|| {
1176 let _ = write!(buf, "{}", headers);
1177 ::test::black_box(&buf);
1178 unsafe { buf.as_mut_vec().set_len(0); }
1179 })
1180 }
1181}