1use std::any::Any;
82use std::borrow::{Cow, ToOwned};
83use std::iter::{FromIterator, IntoIterator};
86use std::ops::{Deref, DerefMut};
87use std::{mem, fmt};
88
89use {httparse, traitobject};
90use typeable::Typeable;
91use unicase::UniCase;
92
93use self::internals::{Item, VecMap, Entry};
94use self::sealed::Sealed;
95
96pub use self::shared::*;
97pub use self::common::*;
98
99mod common;
100mod internals;
101mod shared;
102pub mod parsing;
103
104type HeaderName = UniCase<CowStr>;
105
106pub trait Header: Clone + Any + Send + Sync {
111 fn header_name() -> &'static str;
115 fn parse_header(raw: &[Vec<u8>]) -> crate::Result<Self>;
123
124}
125
126pub trait HeaderFormat: fmt::Debug + HeaderClone + Any + Typeable + Send + Sync {
130 fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result;
135
136 #[doc(hidden)]
145 #[inline]
146 fn fmt_multi_header(&self, f: &mut MultilineFormatter) -> fmt::Result {
147 f.fmt_line(&FmtHeader(self))
148 }
149}
150
151#[doc(hidden)]
152#[allow(missing_debug_implementations)]
153pub struct MultilineFormatter<'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}
159
160impl<'a, 'b> MultilineFormatter<'a, 'b> {
161 fn fmt_line(&mut self, line: &dyn fmt::Display) -> fmt::Result {
162 use std::fmt::Write;
163 match self.0 {
164 Multi::Line(ref name, ref mut f) => {
165 f.write_str(*name)?;
166 f.write_str(": ")?;
167 write!(NewlineReplacer(*f), "{}", line)?;
168 f.write_str("\r\n")
169 },
170 Multi::Join(ref mut first, ref mut f) => {
171 if !*first {
172 f.write_str(", ")?;
173 } else {
174 *first = false;
175 }
176 write!(NewlineReplacer(*f), "{}", line)
177 }
178 }
179 }
180}
181
182struct FmtHeader<'a, H: ?Sized + 'a>(&'a H);
184
185impl<'a, H: HeaderFormat + ?Sized + 'a> fmt::Display for FmtHeader<'a, H> {
186 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
187 self.0.fmt_header(f)
188 }
189}
190
191struct ValueString<'a>(&'a Item);
192
193impl<'a> fmt::Display for ValueString<'a> {
194 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
195 self.0.write_h1(&mut MultilineFormatter(Multi::Join(true, f)))
196 }
197}
198
199struct NewlineReplacer<'a, 'b: 'a>(&'a mut fmt::Formatter<'b>);
200
201impl<'a, 'b> fmt::Write for NewlineReplacer<'a, 'b> {
202 fn write_str(&mut self, s: &str) -> fmt::Result {
203 let mut since = 0;
204 for (i, &byte) in s.as_bytes().iter().enumerate() {
205 if byte == b'\r' || byte == b'\n' {
206 self.0.write_str(&s[since..i])?;
207 self.0.write_str(" ")?;
208 since = i + 1;
209 }
210 }
211 if since < s.len() {
212 self.0.write_str(&s[since..])
213 } else {
214 Ok(())
215 }
216 }
217}
218
219pub trait HeaderClone: Sealed {}
225impl<T: Sealed> HeaderClone for T {}
226
227mod sealed {
228 use super::HeaderFormat;
229
230 #[doc(hidden)]
231 pub trait Sealed {
232 #[doc(hidden)]
233 fn clone_box(&self) -> Box<dyn HeaderFormat + Send + Sync>;
234 }
235
236 #[doc(hidden)]
237 impl<T: HeaderFormat + Clone> Sealed for T {
238 #[inline]
239 fn clone_box(&self) -> Box<dyn HeaderFormat + Send + Sync> {
240 Box::new(self.clone())
241 }
242 }
243}
244
245impl dyn HeaderFormat + Send + Sync {
246 #[inline]
247 unsafe fn downcast_ref_unchecked<T: 'static>(&self) -> &T {
248 mem::transmute(traitobject::data(self))
249 }
250
251 #[inline]
252 unsafe fn downcast_mut_unchecked<T: 'static>(&mut self) -> &mut T {
253 mem::transmute(traitobject::data_mut(self))
254 }
255}
256
257impl Clone for Box<dyn HeaderFormat + Send + Sync> {
258 #[inline]
259 fn clone(&self) -> Box<dyn HeaderFormat + Send + Sync> {
260 self.clone_box()
261 }
262}
263
264#[inline]
265fn header_name<T: Header>() -> &'static str {
266 <T as Header>::header_name()
267}
268
269#[derive(Clone)]
271pub struct Headers {
272 data: VecMap<HeaderName, Item>,
274}
275
276impl Headers {
277
278 pub fn new() -> Headers {
280 Headers {
281 data: VecMap::new()
282 }
283 }
284
285 pub fn with_capacity(size:usize)-> Headers{
286 Headers {
287 data: VecMap::with_capacity(size)
288 }
289 }
290
291 #[doc(hidden)]
292 pub fn from_raw(raw: &[httparse::Header]) -> crate::Result<Headers> {
293 let mut headers = Headers::new();
294 for header in raw {
295 trace!("raw header: {:?}={:?}", header.name, &header.value[..]);
296 let name = UniCase(CowStr(Cow::Owned(header.name.to_owned())));
297 let item = match headers.data.entry(name) {
298 Entry::Vacant(entry) => entry.insert(Item::new_raw(vec![])),
299 Entry::Occupied(entry) => entry.into_mut()
300 };
301 let trim = header.value.iter().rev().take_while(|&&x| x == b' ').count();
302 let value = &header.value[.. header.value.len() - trim];
303 item.raw_mut().push(value.to_vec());
304 }
305 Ok(headers)
306 }
307
308 pub fn set<H: Header + HeaderFormat>(&mut self, value: H) {
312 trace!("Headers.set( {:?}, {:?} )", header_name::<H>(), value);
313 self.data.insert(UniCase(CowStr(Cow::Borrowed(header_name::<H>()))),
314 Item::new_typed(Box::new(value)));
315 }
316
317 pub fn get_raw(&self, name: &str) -> Option<&[Vec<u8>]> {
329 self.data
330 .get(&UniCase(CowStr(Cow::Borrowed(unsafe { mem::transmute::<&str, &str>(name) }))))
331 .map(Item::raw)
332 }
333
334 pub fn set_raw<K: Into<Cow<'static, str>>>(&mut self, name: K,
347 value: Vec<Vec<u8>>) {
348 let name = name.into();
349 trace!("Headers.set_raw( {:?}, {:?} )", name, value);
350 self.data.insert(UniCase(CowStr(name)), Item::new_raw(value));
351 }
352
353 pub fn append_raw<K: Into<Cow<'static, str>>>(&mut self, name: K, value: Vec<u8>) {
369 let name = name.into();
370 trace!("Headers.append_raw( {:?}, {:?} )", name, value);
371 let name = UniCase(CowStr(name));
372 if let Some(item) = self.data.get_mut(&name) {
373 item.raw_mut().push(value);
374 return;
375 }
376 self.data.insert(name, Item::new_raw(vec![value]));
377 }
378
379 pub fn remove_raw(&mut self, name: &str) {
381 trace!("Headers.remove_raw( {:?} )", name);
382 self.data.remove(
383 &UniCase(CowStr(Cow::Borrowed(unsafe { mem::transmute::<&str, &str>(name) })))
384 );
385 }
386
387 pub fn get<H: Header + HeaderFormat>(&self) -> Option<&H> {
389 self.data.get(&UniCase(CowStr(Cow::Borrowed(header_name::<H>()))))
390 .and_then(Item::typed::<H>)
391 }
392
393 pub fn get_mut<H: Header + HeaderFormat>(&mut self) -> Option<&mut H> {
395 self.data.get_mut(&UniCase(CowStr(Cow::Borrowed(header_name::<H>()))))
396 .and_then(Item::typed_mut::<H>)
397 }
398
399 pub fn has<H: Header + HeaderFormat>(&self) -> bool {
410 self.data.contains_key(&UniCase(CowStr(Cow::Borrowed(header_name::<H>()))))
411 }
412
413 pub fn remove<H: Header + HeaderFormat>(&mut self) -> bool {
416 trace!("Headers.remove( {:?} )", header_name::<H>());
417 self.data.remove(&UniCase(CowStr(Cow::Borrowed(header_name::<H>())))).is_some()
418 }
419
420 pub fn iter(&self) -> HeadersItems {
422 HeadersItems {
423 inner: self.data.iter()
424 }
425 }
426
427 pub fn len(&self) -> usize {
429 self.data.len()
430 }
431
432 pub fn clear(&mut self) {
434 self.data.clear()
435 }
436}
437
438impl PartialEq for Headers {
439 fn eq(&self, other: &Headers) -> bool {
440 if self.len() != other.len() {
441 return false;
442 }
443
444 for header in self.iter() {
445 match other.get_raw(header.name()) {
446 Some(val) if val == self.get_raw(header.name()).unwrap() => {},
447 _ => { return false; }
448 }
449 }
450 true
451 }
452}
453
454impl fmt::Display for Headers {
455 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
456 for header in self.iter() {
457 fmt::Display::fmt(&header, f)?;
458 }
459 Ok(())
460 }
461}
462
463impl fmt::Debug for Headers {
464 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
465 f.write_str("Headers { ")?;
466 for header in self.iter() {
467 write!(f, "{:?}, ", header)?;
468 }
469 f.write_str("}")?;
470 Ok(())
471 }
472}
473
474pub struct HeadersItems<'a> {
476 inner: ::std::slice::Iter<'a, (HeaderName, Item)>
477}
478
479impl<'a> Iterator for HeadersItems<'a> {
480 type Item = HeaderView<'a>;
481
482 fn next(&mut self) -> Option<HeaderView<'a>> {
483 self.inner.next().map(|&(ref k, ref v)| HeaderView(k, v))
484 }
485}
486
487pub struct HeaderView<'a>(&'a HeaderName, &'a Item);
489
490impl<'a> HeaderView<'a> {
491 #[inline]
493 pub fn is<H: Header>(&self) -> bool {
494 UniCase(CowStr(Cow::Borrowed(header_name::<H>()))) == *self.0
495 }
496
497 #[inline]
499 pub fn name(&self) -> &'a str {
500 self.0.as_ref()
501 }
502
503 #[inline]
505 pub fn value<H: Header + HeaderFormat>(&self) -> Option<&'a H> {
506 self.1.typed::<H>()
507 }
508
509 #[inline]
516 pub fn value_string(&self) -> String {
517 ValueString(self.1).to_string()
518 }
519}
520
521impl<'a> fmt::Display for HeaderView<'a> {
522 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
523 self.1.write_h1(&mut MultilineFormatter(Multi::Line(&self.0, f)))
524 }
525}
526
527impl<'a> fmt::Debug for HeaderView<'a> {
528 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
529 fmt::Display::fmt(self, f)
530 }
531}
532
533impl<'a> Extend<HeaderView<'a>> for Headers {
534 fn extend<I: IntoIterator<Item=HeaderView<'a>>>(&mut self, iter: I) {
535 for header in iter {
536 self.data.insert((*header.0).clone(), (*header.1).clone());
537 }
538 }
539}
540
541impl<'a> FromIterator<HeaderView<'a>> for Headers {
542 fn from_iter<I: IntoIterator<Item=HeaderView<'a>>>(iter: I) -> Headers {
543 let mut headers = Headers::new();
544 headers.extend(iter);
545 headers
546 }
547}
548
549impl<'a> fmt::Display for &'a (dyn HeaderFormat + Send + Sync) {
551 #[inline]
552 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
553 let mut multi = MultilineFormatter(Multi::Join(true, f));
554 self.fmt_multi_header(&mut multi)
555 }
556}
557
558#[deprecated(note="The semantics of formatting a HeaderFormat directly are not clear")]
566pub struct HeaderFormatter<'a, H: HeaderFormat>(pub &'a H);
567
568#[allow(deprecated)]
569impl<'a, H: HeaderFormat> fmt::Display for HeaderFormatter<'a, H> {
570 #[inline]
571 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
572 let mut multi = MultilineFormatter(Multi::Join(true, f));
573 self.0.fmt_multi_header(&mut multi)
574 }
575}
576
577#[allow(deprecated)]
578impl<'a, H: HeaderFormat> fmt::Debug for HeaderFormatter<'a, H> {
579 #[inline]
580 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
581 fmt::Display::fmt(self, f)
582 }
583}
584
585#[derive(Clone, Hash, Eq, PartialEq, PartialOrd, Ord)]
586struct CowStr(Cow<'static, str>);
587
588impl Deref for CowStr {
589 type Target = Cow<'static, str>;
590
591 fn deref(&self) -> &Cow<'static, str> {
592 &self.0
593 }
594}
595
596impl fmt::Debug for CowStr {
597 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
598 fmt::Debug::fmt(&self.0, f)
599 }
600}
601
602impl fmt::Display for CowStr {
603 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
604 fmt::Display::fmt(&self.0, f)
605 }
606}
607
608impl DerefMut for CowStr {
609 fn deref_mut(&mut self) -> &mut Cow<'static, str> {
610 &mut self.0
611 }
612}
613
614impl AsRef<str> for CowStr {
615 fn as_ref(&self) -> &str {
616 self
617 }
618}
619
620
621#[cfg(test)]
622mod tests {
623 use std::fmt;
624 use mime::Mime;
625 use mime::TopLevel::Text;
626 use mime::SubLevel::Plain;
627 use super::{Headers, Header, HeaderFormat, ContentLength, ContentType,
628 Accept, Host, qitem};
629 use httparse;
630
631 #[cfg(feature = "nightly")]
632 use test::Bencher;
633
634 fn index_of(slice: &[u8], byte: u8) -> Option<usize> {
636 for (index, &b) in slice.iter().enumerate() {
637 if b == byte {
638 return Some(index);
639 }
640 }
641 None
642 }
643
644 macro_rules! raw {
645 ($($line:expr),*) => ({
646 [$({
647 let line = $line;
648 let pos = index_of(line, b':').expect("raw splits on ':', not found");
649 httparse::Header {
650 name: ::std::str::from_utf8(&line[..pos]).unwrap(),
651 value: &line[pos + 2..]
652 }
653 }),*]
654 })
655 }
656
657 #[test]
658 fn test_from_raw() {
659 let headers = Headers::from_raw(&raw!(b"Content-Length: 10")).unwrap();
660 assert_eq!(headers.get(), Some(&ContentLength(10)));
661 }
662
663 #[test]
664 fn test_content_type() {
665 let content_type = Header::parse_header([b"text/plain".to_vec()].as_ref());
666 assert_eq!(content_type.ok(), Some(ContentType(Mime(Text, Plain, vec![]))));
667 }
668
669 #[test]
670 fn test_accept() {
671 let text_plain = qitem(Mime(Text, Plain, vec![]));
672 let application_vendor = "application/vnd.github.v3.full+json; q=0.5".parse().unwrap();
673
674 let accept = Header::parse_header([b"text/plain".to_vec()].as_ref());
675 assert_eq!(accept.ok(), Some(Accept(vec![text_plain.clone()])));
676
677 let bytevec = [b"application/vnd.github.v3.full+json; q=0.5, text/plain".to_vec()];
678 let accept = Header::parse_header(bytevec.as_ref());
679 assert_eq!(accept.ok(), Some(Accept(vec![application_vendor, text_plain])));
680 }
681
682 #[derive(Clone, PartialEq, Debug)]
683 struct CrazyLength(Option<bool>, usize);
684
685 impl Header for CrazyLength {
686 fn header_name() -> &'static str {
687 "content-length"
688 }
689 fn parse_header(raw: &[Vec<u8>]) -> crate::Result<CrazyLength> {
690 use std::str::from_utf8;
691 use std::str::FromStr;
692
693 if raw.len() != 1 {
694 return Err(crate::Error::Header);
695 }
696 match match from_utf8(unsafe { &raw.get_unchecked(0)[..] }) {
698 Ok(s) => FromStr::from_str(s).ok(),
699 Err(_) => None
700 }.map(|u| CrazyLength(Some(false), u)) {
701 Some(x) => Ok(x),
702 None => Err(crate::Error::Header),
703 }
704 }
705 }
706
707 impl HeaderFormat for CrazyLength {
708 fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result {
709 let CrazyLength(ref opt, ref value) = *self;
710 write!(f, "{:?}, {:?}", opt, value)
711 }
712 }
713
714 #[test]
715 fn test_different_structs_for_same_header() {
716 let headers = Headers::from_raw(&raw!(b"Content-Length: 10")).unwrap();
717 assert_eq!(headers.get::<ContentLength>(), Some(&ContentLength(10)));
718 assert_eq!(headers.get::<CrazyLength>(), Some(&CrazyLength(Some(false), 10)));
719 }
720
721 #[test]
722 fn test_trailing_whitespace() {
723 let headers = Headers::from_raw(&raw!(b"Content-Length: 10 ")).unwrap();
724 assert_eq!(headers.get::<ContentLength>(), Some(&ContentLength(10)));
725 }
726
727 #[test]
728 fn test_multiple_reads() {
729 let headers = Headers::from_raw(&raw!(b"Content-Length: 10")).unwrap();
730 let ContentLength(one) = *headers.get::<ContentLength>().unwrap();
731 let ContentLength(two) = *headers.get::<ContentLength>().unwrap();
732 assert_eq!(one, two);
733 }
734
735 #[test]
736 fn test_different_reads() {
737 let headers = Headers::from_raw(
738 &raw!(b"Content-Length: 10", b"Content-Type: text/plain")).unwrap();
739 let ContentLength(_) = *headers.get::<ContentLength>().unwrap();
740 let ContentType(_) = *headers.get::<ContentType>().unwrap();
741 }
742
743 #[test]
744 fn test_get_mutable() {
745 let mut headers = Headers::from_raw(&raw!(b"Content-Length: 10")).unwrap();
746 *headers.get_mut::<ContentLength>().unwrap() = ContentLength(20);
747 assert_eq!(headers.get_raw("content-length").unwrap(), &[b"20".to_vec()][..]);
748 assert_eq!(*headers.get::<ContentLength>().unwrap(), ContentLength(20));
749 }
750
751 #[test]
752 fn test_headers_fmt() {
753 let mut headers = Headers::new();
754 headers.set(ContentLength(15));
755 headers.set(Host { hostname: "foo.bar".to_owned(), port: None });
756
757 let s = headers.to_string();
758 assert!(s.contains("Host: foo.bar\r\n"));
759 assert!(s.contains("Content-Length: 15\r\n"));
760 }
761
762 #[test]
763 fn test_headers_fmt_raw() {
764 let mut headers = Headers::from_raw(&raw!(b"Content-Length: 10")).unwrap();
765 headers.set_raw("x-foo", vec![b"foo".to_vec(), b"bar".to_vec()]);
766 let s = headers.to_string();
767 assert_eq!(s, "Content-Length: 10\r\nx-foo: foo\r\nx-foo: bar\r\n");
768 }
769
770 #[test]
771 fn test_set_raw() {
772 let mut headers = Headers::new();
773 headers.set(ContentLength(10));
774 headers.set_raw("content-LENGTH", vec![b"20".to_vec()]);
775 assert_eq!(headers.get_raw("Content-length").unwrap(), &[b"20".to_vec()][..]);
776 assert_eq!(headers.get(), Some(&ContentLength(20)));
777 }
778
779 #[test]
780 fn test_append_raw() {
781 let mut headers = Headers::new();
782 headers.set(ContentLength(10));
783 headers.append_raw("content-LENGTH", b"20".to_vec());
784 assert_eq!(headers.get_raw("Content-length").unwrap(), &[b"10".to_vec(), b"20".to_vec()][..]);
785 headers.append_raw("x-foo", b"bar".to_vec());
786 assert_eq!(headers.get_raw("x-foo"), Some(&[b"bar".to_vec()][..]));
787 }
788
789 #[test]
790 fn test_remove_raw() {
791 let mut headers = Headers::new();
792 headers.set_raw("content-LENGTH", vec![b"20".to_vec()]);
793 headers.remove_raw("content-LENGTH");
794 assert_eq!(headers.get_raw("Content-length"), None);
795 }
796
797 #[test]
798 fn test_len() {
799 let mut headers = Headers::new();
800 headers.set(ContentLength(10));
801 assert_eq!(headers.len(), 1);
802 headers.set(ContentType(Mime(Text, Plain, vec![])));
803 assert_eq!(headers.len(), 2);
804 headers.set(ContentLength(20));
806 assert_eq!(headers.len(), 2);
807 }
808
809 #[test]
810 fn test_clear() {
811 let mut headers = Headers::new();
812 headers.set(ContentLength(10));
813 headers.set(ContentType(Mime(Text, Plain, vec![])));
814 assert_eq!(headers.len(), 2);
815 headers.clear();
816 assert_eq!(headers.len(), 0);
817 }
818
819 #[test]
820 fn test_iter() {
821 let mut headers = Headers::new();
822 headers.set(ContentLength(11));
823 for header in headers.iter() {
824 assert!(header.is::<ContentLength>());
825 assert_eq!(header.name(), <ContentLength as Header>::header_name());
826 assert_eq!(header.value(), Some(&ContentLength(11)));
827 assert_eq!(header.value_string(), "11".to_owned());
828 }
829 }
830
831 #[test]
832 fn test_header_view_value_string() {
833 let mut headers = Headers::new();
834 headers.set_raw("foo", vec![b"one".to_vec(), b"two".to_vec()]);
835 for header in headers.iter() {
836 assert_eq!(header.name(), "foo");
837 assert_eq!(header.value_string(), "one, two");
838 }
839 }
840
841 #[test]
842 fn test_eq() {
843 let mut headers1 = Headers::new();
844 let mut headers2 = Headers::new();
845
846 assert_eq!(headers1, headers2);
847
848 headers1.set(ContentLength(11));
849 headers2.set(Host {hostname: "foo.bar".to_owned(), port: None});
850 assert!(headers1 != headers2);
851
852 headers1 = Headers::new();
853 headers2 = Headers::new();
854
855 headers1.set(ContentLength(11));
856 headers2.set(ContentLength(11));
857 assert_eq!(headers1, headers2);
858
859 headers1.set(ContentLength(10));
860 assert!(headers1 != headers2);
861
862 headers1 = Headers::new();
863 headers2 = Headers::new();
864
865 headers1.set(Host { hostname: "foo.bar".to_owned(), port: None });
866 headers1.set(ContentLength(11));
867 headers2.set(ContentLength(11));
868 assert!(headers1 != headers2);
869 }
870
871 #[cfg(feature = "nightly")]
872 #[bench]
873 fn bench_headers_new(b: &mut Bencher) {
874 b.iter(|| {
875 let mut h = Headers::new();
876 h.set(ContentLength(11));
877 h
878 })
879 }
880
881 #[cfg(feature = "nightly")]
882 #[bench]
883 fn bench_headers_from_raw(b: &mut Bencher) {
884 let raw = raw!(b"Content-Length: 10");
885 b.iter(|| Headers::from_raw(&raw).unwrap())
886 }
887
888 #[cfg(feature = "nightly")]
889 #[bench]
890 fn bench_headers_get(b: &mut Bencher) {
891 let mut headers = Headers::new();
892 headers.set(ContentLength(11));
893 b.iter(|| assert_eq!(headers.get::<ContentLength>(), Some(&ContentLength(11))))
894 }
895
896 #[cfg(feature = "nightly")]
897 #[bench]
898 fn bench_headers_get_miss(b: &mut Bencher) {
899 let headers = Headers::new();
900 b.iter(|| assert!(headers.get::<ContentLength>().is_none()))
901 }
902
903 #[cfg(feature = "nightly")]
904 #[bench]
905 fn bench_headers_set(b: &mut Bencher) {
906 let mut headers = Headers::new();
907 b.iter(|| headers.set(ContentLength(12)))
908 }
909
910 #[cfg(feature = "nightly")]
911 #[bench]
912 fn bench_headers_has(b: &mut Bencher) {
913 let mut headers = Headers::new();
914 headers.set(ContentLength(11));
915 b.iter(|| assert!(headers.has::<ContentLength>()))
916 }
917
918 #[cfg(feature = "nightly")]
919 #[bench]
920 fn bench_headers_view_is(b: &mut Bencher) {
921 let mut headers = Headers::new();
922 headers.set(ContentLength(11));
923 let mut iter = headers.iter();
924 let view = iter.next().unwrap();
925 b.iter(|| assert!(view.is::<ContentLength>()))
926 }
927
928 #[cfg(feature = "nightly")]
929 #[bench]
930 fn bench_headers_fmt(b: &mut Bencher) {
931 let mut headers = Headers::new();
932 headers.set(ContentLength(11));
933 b.iter(|| headers.to_string())
934 }
935}