1use std::borrow::{Cow, ToOwned};
80use std::iter::{FromIterator, IntoIterator};
81use std::{mem, fmt};
82
83use bytes::Bytes;
84use httparse;
85use unicase::Ascii;
86
87use self::internals::{Item, VecMap, Entry};
88use self::sealed::HeaderClone;
89
90pub use self::shared::*;
91pub use self::common::*;
92pub use self::raw::Raw;
93
94mod common;
95mod internals;
96mod raw;
97mod shared;
98pub mod parsing;
99
100pub trait Header: 'static + HeaderClone + Send + Sync {
105 fn header_name() -> &'static str where Self: Sized;
109 fn parse_header(raw: &Raw) -> ::Result<Self> where Self: Sized;
117 #[inline]
131 fn fmt_header(&self, f: &mut Formatter) -> fmt::Result;
132}
133
134mod sealed {
135 use super::Header;
136
137 #[doc(hidden)]
138 pub trait HeaderClone {
139 fn clone_box(&self) -> Box<Header + Send + Sync>;
140 }
141
142 impl<T: Header + Clone> HeaderClone for T {
143 #[inline]
144 fn clone_box(&self) -> Box<Header + Send + Sync> {
145 Box::new(self.clone())
146 }
147 }
148}
149
150
151#[allow(missing_debug_implementations)]
153pub struct Formatter<'a, 'b: 'a>(Multi<'a, 'b>);
154
155enum Multi<'a, 'b: 'a> {
156 Line(&'a str, &'a mut fmt::Formatter<'b>),
157 Join(bool, &'a mut fmt::Formatter<'b>),
158 Raw(&'a mut Raw),
159}
160
161impl<'a, 'b> Formatter<'a, 'b> {
162
163 pub fn fmt_line(&mut self, line: &fmt::Display) -> fmt::Result {
175 use std::fmt::Write;
176 match self.0 {
177 Multi::Line(name, ref mut f) => {
178 try!(f.write_str(name));
179 try!(f.write_str(": "));
180 try!(write!(NewlineReplacer(*f), "{}", line));
181 f.write_str("\r\n")
182 },
183 Multi::Join(ref mut first, ref mut f) => {
184 if !*first {
185 try!(f.write_str(", "));
186 } else {
187 *first = false;
188 }
189 write!(NewlineReplacer(*f), "{}", line)
190 }
191 Multi::Raw(ref mut raw) => {
192 let mut s = String::new();
193 try!(write!(NewlineReplacer(&mut s), "{}", line));
194 raw.push(s);
195 Ok(())
196 }
197 }
198 }
199
200 fn danger_fmt_line_without_newline_replacer<T: fmt::Display>(&mut self, line: &T) -> fmt::Result {
201 use std::fmt::Write;
202 match self.0 {
203 Multi::Line(name, ref mut f) => {
204 try!(f.write_str(name));
205 try!(f.write_str(": "));
206 try!(fmt::Display::fmt(line, f));
207 f.write_str("\r\n")
208 },
209 Multi::Join(ref mut first, ref mut f) => {
210 if !*first {
211 try!(f.write_str(", "));
212 } else {
213 *first = false;
214 }
215 fmt::Display::fmt(line, f)
216 }
217 Multi::Raw(ref mut raw) => {
218 let mut s = String::new();
219 try!(write!(s, "{}", line));
220 raw.push(s);
221 Ok(())
222 }
223 }
224 }
225}
226
227struct ValueString<'a>(&'a Item);
228
229impl<'a> fmt::Debug for ValueString<'a> {
230 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
231 try!(f.write_str("\""));
232 try!(self.0.write_h1(&mut Formatter(Multi::Join(true, f))));
233 f.write_str("\"")
234 }
235}
236
237impl<'a> fmt::Display for ValueString<'a> {
238 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
239 self.0.write_h1(&mut Formatter(Multi::Join(true, f)))
240 }
241}
242
243struct NewlineReplacer<'a, F: fmt::Write + 'a>(&'a mut F);
244
245impl<'a, F: fmt::Write + 'a> fmt::Write for NewlineReplacer<'a, F> {
246 #[inline]
247 fn write_str(&mut self, s: &str) -> fmt::Result {
248 let mut since = 0;
249 for (i, &byte) in s.as_bytes().iter().enumerate() {
250 if byte == b'\r' || byte == b'\n' {
251 try!(self.0.write_str(&s[since..i]));
252 try!(self.0.write_str(" "));
253 since = i + 1;
254 }
255 }
256 if since < s.len() {
257 self.0.write_str(&s[since..])
258 } else {
259 Ok(())
260 }
261 }
262
263 #[inline]
264 fn write_fmt(&mut self, args: fmt::Arguments) -> fmt::Result {
265 fmt::write(self, args)
266 }
267}
268
269
270impl Header + Send + Sync {
271 #[inline]
280 unsafe fn downcast_ref_unchecked<T: 'static>(&self) -> &T {
281 &*(mem::transmute::<*const _, (*const (), *const ())>(self).0 as *const T)
282 }
283
284 #[inline]
285 unsafe fn downcast_mut_unchecked<T: 'static>(&mut self) -> &mut T {
286 &mut *(mem::transmute::<*mut _, (*mut (), *mut ())>(self).0 as *mut T)
287 }
288
289 #[inline]
290 unsafe fn downcast_unchecked<T: 'static>(self: Box<Self>) -> T {
291 *Box::from_raw(mem::transmute::<*mut _, (*mut (), *mut ())>(Box::into_raw(self)).0 as *mut T)
292 }
293}
294
295impl Clone for Box<Header + Send + Sync> {
296 #[inline]
297 fn clone(&self) -> Box<Header + Send + Sync> {
298 self.clone_box()
299 }
300}
301
302#[inline]
303fn header_name<T: Header>() -> &'static str {
304 <T as Header>::header_name()
305}
306
307#[derive(Clone)]
309pub struct Headers {
310 data: VecMap<HeaderName, Item>,
311}
312
313impl Default for Headers {
314 fn default() -> Headers {
315 Headers::new()
316 }
317}
318
319macro_rules! literals {
320 ($($len:expr => $($header:path),+;)+) => (
321 fn maybe_literal(s: &str) -> Cow<'static, str> {
322 match s.len() {
323 $($len => {
324 $(
325 if Ascii::new(<$header>::header_name()) == Ascii::new(s) {
326 return Cow::Borrowed(<$header>::header_name());
327 }
328 )+
329 })+
330
331 _ => ()
332 }
333
334 trace!("maybe_literal not found, copying {:?}", s);
335 Cow::Owned(s.to_owned())
336 }
337
338 #[test]
339 fn test_literal_lens() {
340 $(
341 $({
342 let s = <$header>::header_name();
343 assert!(s.len() == $len, "{:?} has len of {}, listed as {}", s, s.len(), $len);
344 })+
345 )+
346 }
347 );
348}
349
350literals! {
351 4 => Host, Date, ETag;
352 5 => Allow, Range;
353 6 => Accept, Cookie, Server, Expect;
354 7 => Upgrade, Referer, Expires;
355 8 => Location, IfMatch, IfRange;
356 10 => UserAgent, Connection, SetCookie;
357 12 => ContentType;
358 13 => Authorization<String>, CacheControl, LastModified, IfNoneMatch, AcceptRanges, ContentRange;
359 14 => ContentLength, AcceptCharset;
360 15 => AcceptEncoding, AcceptLanguage;
361 17 => TransferEncoding;
362 25 => StrictTransportSecurity;
363 27 => AccessControlAllowOrigin;
364}
365
366impl Headers {
367
368 #[inline]
370 pub fn new() -> Headers {
371 Headers::with_capacity(0)
372 }
373
374 #[inline]
376 pub fn with_capacity(len: usize) -> Headers {
377 Headers {
378 data: VecMap::with_capacity(len)
379 }
380 }
381
382 #[doc(hidden)]
383 pub fn from_raw(raw: &[httparse::Header]) -> ::Result<Headers> {
384 let mut headers = Headers::new();
385 for header in raw {
386 trace!("raw header: {:?}={:?}", header.name, &header.value[..]);
387 let trim = header.value.iter().rev().take_while(|&&x| x == b' ').count();
388 let value = &header.value[.. header.value.len() - trim];
389 headers.append_raw(header.name.to_owned(), value.to_vec());
390 }
391 Ok(headers)
392 }
393
394 pub fn set<H: Header>(&mut self, value: H) {
398 self.data.insert(HeaderName(Ascii::new(Cow::Borrowed(header_name::<H>()))),
399 Item::new_typed(value));
400 }
401
402 pub fn get<H: Header>(&self) -> Option<&H> {
412 self.data.get(&HeaderName(Ascii::new(Cow::Borrowed(header_name::<H>()))))
413 .and_then(Item::typed::<H>)
414 }
415
416 pub fn get_mut<H: Header>(&mut self) -> Option<&mut H> {
418 self.data.get_mut(&HeaderName(Ascii::new(Cow::Borrowed(header_name::<H>()))))
419 .and_then(Item::typed_mut::<H>)
420 }
421
422 pub fn has<H: Header>(&self) -> bool {
434 self.data.contains_key(&HeaderName(Ascii::new(Cow::Borrowed(header_name::<H>()))))
435 }
436
437 pub fn remove<H: Header>(&mut self) -> Option<H> {
443 self.data.remove(&HeaderName(Ascii::new(Cow::Borrowed(header_name::<H>()))))
444 .and_then(Item::into_typed::<H>)
445 }
446
447 pub fn iter(&self) -> HeadersItems {
449 HeadersItems {
450 inner: self.data.iter()
451 }
452 }
453
454 pub fn len(&self) -> usize {
456 self.data.len()
457 }
458
459 pub fn clear(&mut self) {
461 self.data.clear()
462 }
463
464 pub fn get_raw(&self, name: &str) -> Option<&Raw> {
478 self.data
479 .get(name)
480 .map(Item::raw)
481 }
482
483 pub fn set_raw<K: Into<Cow<'static, str>>, V: Into<Raw>>(&mut self, name: K, value: V) {
496 let name = name.into();
497 let value = value.into();
498 self.data.insert(HeaderName(Ascii::new(name)), Item::new_raw(value));
499 }
500
501 pub fn append_raw<K: Into<Cow<'static, str>>, V: Into<Raw>>(&mut self, name: K, value: V) {
517 let name = name.into();
518 let value = value.into();
519 let name = HeaderName(Ascii::new(name));
520 if let Some(item) = self.data.get_mut(&name) {
521 item.raw_mut().push(value);
522 return;
523 }
524 self.data.insert(name, Item::new_raw(value));
525 }
526
527 pub fn remove_raw(&mut self, name: &str) {
529 self.data.remove(name);
530 }
531
532}
533
534impl PartialEq for Headers {
535 fn eq(&self, other: &Headers) -> bool {
536 if self.len() != other.len() {
537 return false;
538 }
539
540 for header in self.iter() {
541 match other.get_raw(header.name()) {
542 Some(val) if val == self.get_raw(header.name()).unwrap() => {},
543 _ => { return false; }
544 }
545 }
546 true
547 }
548}
549
550impl fmt::Display for Headers {
551 #[inline]
552 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
553 for header in self.iter() {
554 try!(fmt::Display::fmt(&header, f));
555 }
556 Ok(())
557 }
558}
559
560impl fmt::Debug for Headers {
561 #[inline]
562 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
563 f.debug_map()
564 .entries(self.iter().map(|view| (view.0.as_ref(), ValueString(view.1))))
565 .finish()
566 }
567}
568
569#[allow(missing_debug_implementations)]
571pub struct HeadersItems<'a> {
572 inner: ::std::slice::Iter<'a, (HeaderName, Item)>
573}
574
575impl<'a> Iterator for HeadersItems<'a> {
576 type Item = HeaderView<'a>;
577
578 fn next(&mut self) -> Option<HeaderView<'a>> {
579 self.inner.next().map(|&(ref k, ref v)| HeaderView(k, v))
580 }
581}
582
583pub struct HeaderView<'a>(&'a HeaderName, &'a Item);
585
586impl<'a> HeaderView<'a> {
587 #[inline]
589 pub fn is<H: Header>(&self) -> bool {
590 HeaderName(Ascii::new(Cow::Borrowed(header_name::<H>()))) == *self.0
591 }
592
593 #[inline]
595 pub fn name(&self) -> &'a str {
596 self.0.as_ref()
597 }
598
599 #[inline]
601 pub fn value<H: Header>(&self) -> Option<&'a H> {
602 self.1.typed::<H>()
603 }
604
605 #[inline]
612 pub fn value_string(&self) -> String {
613 ValueString(self.1).to_string()
614 }
615
616 #[inline]
618 pub fn raw(&self) -> &Raw {
619 self.1.raw()
620 }
621}
622
623impl<'a> fmt::Display for HeaderView<'a> {
624 #[inline]
625 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
626 self.1.write_h1(&mut Formatter(Multi::Line(self.0.as_ref(), f)))
627 }
628}
629
630impl<'a> fmt::Debug for HeaderView<'a> {
631 #[inline]
632 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
633 fmt::Display::fmt(self, f)
634 }
635}
636
637impl<'a> Extend<HeaderView<'a>> for Headers {
638 fn extend<I: IntoIterator<Item=HeaderView<'a>>>(&mut self, iter: I) {
639 for header in iter {
640 self.data.insert((*header.0).clone(), (*header.1).clone());
641 }
642 }
643}
644
645impl<'a> Extend<(&'a str, Bytes)> for Headers {
646 fn extend<I: IntoIterator<Item=(&'a str, Bytes)>>(&mut self, iter: I) {
647 for (name, value) in iter {
648 let name = HeaderName(Ascii::new(maybe_literal(name)));
649 match self.data.entry(name) {
652 Entry::Vacant(entry) => {
653 entry.insert(Item::new_raw(self::raw::parsed(value)));
654 }
655 Entry::Occupied(entry) => {
656 self::raw::push(entry.into_mut().raw_mut(), value);
657 }
658 };
659 }
660 }
661}
662
663impl<'a> FromIterator<HeaderView<'a>> for Headers {
664 fn from_iter<I: IntoIterator<Item=HeaderView<'a>>>(iter: I) -> Headers {
665 let mut headers = Headers::new();
666 headers.extend(iter);
667 headers
668 }
669}
670
671#[derive(Clone, Debug)]
672struct HeaderName(Ascii<Cow<'static, str>>);
673
674impl fmt::Display for HeaderName {
675 #[inline]
676 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
677 fmt::Display::fmt(self.0.as_ref(), f)
678 }
679}
680
681impl AsRef<str> for HeaderName {
682 fn as_ref(&self) -> &str {
683 self.0.as_ref()
684 }
685}
686
687impl PartialEq for HeaderName {
688 #[inline]
689 fn eq(&self, other: &HeaderName) -> bool {
690 let s = self.as_ref();
691 let k = other.as_ref();
692 if s.as_ptr() == k.as_ptr() && s.len() == k.len() {
693 true
694 } else {
695 self.0 == other.0
696 }
697 }
698}
699
700impl PartialEq<HeaderName> for str {
701 fn eq(&self, other: &HeaderName) -> bool {
702 let k = other.as_ref();
703 if self.as_ptr() == k.as_ptr() && self.len() == k.len() {
704 true
705 } else {
706 other.0 == self
707 }
708 }
709}
710
711#[cfg(test)]
712mod tests {
713 use std::fmt;
714 use super::{Headers, Header, Raw, ContentLength, ContentType, Host, SetCookie};
715
716 #[cfg(feature = "nightly")]
717 use test::Bencher;
718
719 macro_rules! make_header {
720 ($name:expr, $value:expr) => ({
721 let mut headers = Headers::new();
722 headers.set_raw(String::from_utf8($name.to_vec()).unwrap(), $value.to_vec());
723 headers
724 });
725 ($text:expr) => ({
726 let bytes = $text;
727 let colon = bytes.iter().position(|&x| x == b':').unwrap();
728 make_header!(&bytes[..colon], &bytes[colon + 2..])
729 })
730 }
731 #[test]
732 fn test_from_raw() {
733 let headers = make_header!(b"Content-Length", b"10");
734 assert_eq!(headers.get(), Some(&ContentLength(10)));
735 }
736
737 #[derive(Clone, PartialEq, Debug)]
738 struct CrazyLength(Option<bool>, usize);
739
740 impl Header for CrazyLength {
741 fn header_name() -> &'static str {
742 "content-length"
743 }
744
745 fn parse_header(raw: &Raw) -> ::Result<CrazyLength> {
746 use std::str::from_utf8;
747 use std::str::FromStr;
748
749 if let Some(line) = raw.one() {
750 let s = try!(from_utf8(line).map(|s| FromStr::from_str(s).map_err(|_| ::Error::Header)));
751 s.map(|u| CrazyLength(Some(false), u))
752 } else {
753 Err(::Error::Header)
754 }
755 }
756
757 fn fmt_header(&self, f: &mut super::Formatter) -> fmt::Result {
758 f.fmt_line(self)
759 }
760 }
761
762 impl fmt::Display for CrazyLength {
763 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
764 let CrazyLength(ref opt, ref value) = *self;
765 write!(f, "{:?}, {:?}", opt, value)
766 }
767 }
768
769 #[test]
770 fn test_different_structs_for_same_header() {
771 let headers = make_header!(b"Content-Length: 10");
772 assert_eq!(headers.get::<ContentLength>(), Some(&ContentLength(10)));
773 assert_eq!(headers.get::<CrazyLength>(), Some(&CrazyLength(Some(false), 10)));
774 }
775
776 #[test]
777 fn test_trailing_whitespace() {
778 let headers = make_header!(b"Content-Length: 10 ");
779 assert_eq!(headers.get::<ContentLength>(), Some(&ContentLength(10)));
780 }
781
782 #[test]
783 fn test_multiple_reads() {
784 let headers = make_header!(b"Content-Length: 10");
785 let ContentLength(one) = *headers.get::<ContentLength>().unwrap();
786 let ContentLength(two) = *headers.get::<ContentLength>().unwrap();
787 assert_eq!(one, two);
788 }
789
790 #[test]
791 fn test_different_reads() {
792 let mut headers = Headers::new();
793 headers.set_raw("Content-Length", "10");
794 headers.set_raw("Content-Type", "text/plain");
795 let ContentLength(_) = *headers.get::<ContentLength>().unwrap();
796 let ContentType(_) = *headers.get::<ContentType>().unwrap();
797 }
798
799 #[test]
800 fn test_typed_get_raw() {
801 let mut headers = Headers::new();
802 headers.set(ContentLength(15));
803 assert_eq!(headers.get_raw("content-length").unwrap(), "15");
804
805 headers.set(SetCookie(vec![
806 "foo=bar".to_string(),
807 "baz=quux; Path=/path".to_string()
808 ]));
809 assert_eq!(headers.get_raw("set-cookie").unwrap(), &["foo=bar", "baz=quux; Path=/path"][..]);
810 }
811
812 #[test]
813 fn test_get_mutable() {
814 let mut headers = make_header!(b"Content-Length: 10");
815 *headers.get_mut::<ContentLength>().unwrap() = ContentLength(20);
816 assert_eq!(headers.get_raw("content-length").unwrap(), &[b"20".to_vec()][..]);
817 assert_eq!(*headers.get::<ContentLength>().unwrap(), ContentLength(20));
818 }
819
820 #[test]
821 fn test_headers_to_string() {
822 let mut headers = Headers::new();
823 headers.set(ContentLength(15));
824 headers.set(Host::new("foo.bar", None));
825
826 let s = headers.to_string();
827 assert!(s.contains("Host: foo.bar\r\n"));
828 assert!(s.contains("Content-Length: 15\r\n"));
829 }
830
831 #[test]
832 fn test_headers_to_string_raw() {
833 let mut headers = make_header!(b"Content-Length: 10");
834 headers.set_raw("x-foo", vec![b"foo".to_vec(), b"bar".to_vec()]);
835 let s = headers.to_string();
836 assert_eq!(s, "Content-Length: 10\r\nx-foo: foo\r\nx-foo: bar\r\n");
837 }
838
839 #[test]
840 fn test_set_raw() {
841 let mut headers = Headers::new();
842 headers.set(ContentLength(10));
843 headers.set_raw("content-LENGTH", vec![b"20".to_vec()]);
844 assert_eq!(headers.get_raw("Content-length").unwrap(), &[b"20".to_vec()][..]);
845 assert_eq!(headers.get(), Some(&ContentLength(20)));
846 }
847
848 #[test]
849 fn test_append_raw() {
850 let mut headers = Headers::new();
851 headers.set(ContentLength(10));
852 headers.append_raw("content-LENGTH", b"20".to_vec());
853 assert_eq!(headers.get_raw("Content-length").unwrap(), &[b"10".to_vec(), b"20".to_vec()][..]);
854 headers.append_raw("x-foo", "bar");
855 assert_eq!(headers.get_raw("x-foo").unwrap(), &[b"bar".to_vec()][..]);
856 }
857
858 #[test]
859 fn test_remove_raw() {
860 let mut headers = Headers::new();
861 headers.set_raw("content-LENGTH", vec![b"20".to_vec()]);
862 headers.remove_raw("content-LENGTH");
863 assert_eq!(headers.get_raw("Content-length"), None);
864 }
865
866 #[test]
867 fn test_remove() {
868 let mut headers = Headers::new();
869 headers.set(ContentLength(10));
870 assert_eq!(headers.remove(), Some(ContentLength(10)));
871 assert_eq!(headers.len(), 0);
872
873 headers.set(ContentLength(9));
874 assert_eq!(headers.len(), 1);
875 assert!(headers.remove::<CrazyLength>().is_none());
876 assert_eq!(headers.len(), 0);
877 }
878
879 #[test]
880 fn test_len() {
881 let mut headers = Headers::new();
882 headers.set(ContentLength(10));
883 assert_eq!(headers.len(), 1);
884 headers.set(ContentType::json());
885 assert_eq!(headers.len(), 2);
886 headers.set(ContentLength(20));
888 assert_eq!(headers.len(), 2);
889 }
890
891 #[test]
892 fn test_clear() {
893 let mut headers = Headers::new();
894 headers.set(ContentLength(10));
895 headers.set(ContentType::json());
896 assert_eq!(headers.len(), 2);
897 headers.clear();
898 assert_eq!(headers.len(), 0);
899 }
900
901 #[test]
902 fn test_iter() {
903 let mut headers = Headers::new();
904 headers.set(ContentLength(11));
905 for header in headers.iter() {
906 assert!(header.is::<ContentLength>());
907 assert_eq!(header.name(), <ContentLength as Header>::header_name());
908 assert_eq!(header.value(), Some(&ContentLength(11)));
909 assert_eq!(header.value_string(), "11".to_owned());
910 }
911 }
912
913 #[test]
914 fn test_header_view_value_string() {
915 let mut headers = Headers::new();
916 headers.set_raw("foo", vec![b"one".to_vec(), b"two".to_vec()]);
917 for header in headers.iter() {
918 assert_eq!(header.name(), "foo");
919 assert_eq!(header.value_string(), "one, two");
920 }
921 }
922
923 #[test]
924 fn test_header_view_raw() {
925 let mut headers = Headers::new();
926 headers.set_raw("foo", vec![b"one".to_vec(), b"two".to_vec()]);
927 for header in headers.iter() {
928 assert_eq!(header.name(), "foo");
929 let values: Vec<&[u8]> = header.raw().iter().collect();
930 assert_eq!(values, vec![b"one", b"two"]);
931 }
932 }
933
934 #[test]
935 fn test_eq() {
936 let mut headers1 = Headers::new();
937 let mut headers2 = Headers::new();
938
939 assert_eq!(headers1, headers2);
940
941 headers1.set(ContentLength(11));
942 headers2.set(Host::new("foo.bar", None));
943 assert_ne!(headers1, headers2);
944
945 headers1 = Headers::new();
946 headers2 = Headers::new();
947
948 headers1.set(ContentLength(11));
949 headers2.set(ContentLength(11));
950 assert_eq!(headers1, headers2);
951
952 headers1.set(ContentLength(10));
953 assert_ne!(headers1, headers2);
954
955 headers1 = Headers::new();
956 headers2 = Headers::new();
957
958 headers1.set(Host::new("foo.bar", None));
959 headers1.set(ContentLength(11));
960 headers2.set(ContentLength(11));
961 assert_ne!(headers1, headers2);
962 }
963
964 #[cfg(feature = "nightly")]
965 #[bench]
966 fn bench_headers_new(b: &mut Bencher) {
967 b.iter(|| {
968 let mut h = Headers::new();
969 h.set(ContentLength(11));
970 h
971 })
972 }
973
974 #[cfg(feature = "nightly")]
975 #[bench]
976 fn bench_headers_get(b: &mut Bencher) {
977 let mut headers = Headers::new();
978 headers.set(ContentLength(11));
979 b.iter(|| assert_eq!(headers.get::<ContentLength>(), Some(&ContentLength(11))))
980 }
981
982 #[cfg(feature = "nightly")]
983 #[bench]
984 fn bench_headers_get_miss(b: &mut Bencher) {
985 let headers = Headers::new();
986 b.iter(|| assert!(headers.get::<ContentLength>().is_none()))
987 }
988
989 #[cfg(feature = "nightly")]
990 #[bench]
991 fn bench_headers_get_miss_previous_10(b: &mut Bencher) {
992 let mut headers = Headers::new();
993 for i in 0..10 {
994 headers.set_raw(format!("non-standard-{}", i), "hi");
995 }
996 b.iter(|| assert!(headers.get::<ContentLength>().is_none()))
997 }
998
999 #[cfg(feature = "nightly")]
1000 #[bench]
1001 fn bench_headers_set(b: &mut Bencher) {
1002 let mut headers = Headers::new();
1003 b.iter(|| headers.set(ContentLength(12)))
1004 }
1005
1006 #[cfg(feature = "nightly")]
1007 #[bench]
1008 fn bench_headers_set_previous_10(b: &mut Bencher) {
1009 let mut headers = Headers::new();
1010 for i in 0..10 {
1011 headers.set_raw(format!("non-standard-{}", i), "hi");
1012 }
1013 b.iter(|| headers.set(ContentLength(12)))
1014 }
1015
1016 #[cfg(feature = "nightly")]
1017 #[bench]
1018 fn bench_headers_set_raw(b: &mut Bencher) {
1019 let mut headers = Headers::new();
1020 b.iter(|| headers.set_raw("non-standard", "hello"))
1021 }
1022
1023 #[cfg(feature = "nightly")]
1024 #[bench]
1025 fn bench_headers_set_raw_previous_10(b: &mut Bencher) {
1026 let mut headers = Headers::new();
1027 for i in 0..10 {
1028 headers.set_raw(format!("non-standard-{}", i), "hi");
1029 }
1030 b.iter(|| headers.set_raw("non-standard", "hello"))
1031 }
1032
1033 #[cfg(feature = "nightly")]
1034 #[bench]
1035 fn bench_headers_has(b: &mut Bencher) {
1036 let mut headers = Headers::new();
1037 headers.set(ContentLength(11));
1038 b.iter(|| assert!(headers.has::<ContentLength>()))
1039 }
1040
1041 #[cfg(feature = "nightly")]
1042 #[bench]
1043 fn bench_headers_view_is(b: &mut Bencher) {
1044 let mut headers = Headers::new();
1045 headers.set(ContentLength(11));
1046 let mut iter = headers.iter();
1047 let view = iter.next().unwrap();
1048 b.iter(|| assert!(view.is::<ContentLength>()))
1049 }
1050
1051 #[cfg(feature = "nightly")]
1052 #[bench]
1053 fn bench_headers_fmt(b: &mut Bencher) {
1054 use std::fmt::Write;
1055 let mut buf = String::with_capacity(64);
1056 let mut headers = Headers::new();
1057 headers.set(ContentLength(11));
1058 headers.set(ContentType::json());
1059 b.bytes = headers.to_string().len() as u64;
1060 b.iter(|| {
1061 let _ = write!(buf, "{}", headers);
1062 ::test::black_box(&buf);
1063 unsafe { buf.as_mut_vec().set_len(0); }
1064 })
1065 }
1066}