hyper_sync/header/
mod.rs

1//! Headers container, and common header fields.
2//!
3//! hyper_sync has the opinion that Headers should be strongly-typed, because that's
4//! why we're using Rust in the first place. To set or get any header, an object
5//! must implement the `Header` trait from this module. Several common headers
6//! are already provided, such as `Host`, `ContentType`, `UserAgent`, and others.
7//!
8//! # Why Typed?
9//!
10//! Or, why not stringly-typed? Types give the following advantages:
11//!
12//! - More difficult to typo, since typos in types should be caught by the compiler
13//! - Parsing to a proper type by default
14//!
15//! # Defining Custom Headers
16//!
17//! Hyper provides many of the most commonly used headers in HTTP. If
18//! you need to define a custom header, it's easy to do while still taking
19//! advantage of the type system. Hyper includes a `header!` macro for defining
20//! many wrapper-style headers.
21//!
22//! ```
23//! #[macro_use] extern crate hyper_sync;
24//! use hyper_sync::header::Headers;
25//! header! { (XRequestGuid, "X-Request-Guid") => [String] }
26//!
27//! fn main () {
28//!     let mut headers = Headers::new();
29//!
30//!     headers.set(XRequestGuid("a proper guid".to_owned()))
31//! }
32//! ```
33//!
34//! This works well for simple "string" headers.  If you need more control,
35//! you can implement the trait directly.
36//!
37//! ## Implementing the `Header` trait
38//!
39//! Consider a Do Not Track header. It can be true or false, but it represents
40//! that via the numerals `1` and `0`.
41//!
42//! ```
43//! use std::fmt;
44//! use hyper_sync::header::{self, Header, Raw};
45//!
46//! #[derive(Debug, Clone, Copy)]
47//! struct Dnt(bool);
48//!
49//! impl Header for Dnt {
50//!     fn header_name() -> &'static str {
51//!         "DNT"
52//!     }
53//!
54//!     fn parse_header(raw: &Raw) -> hyper_sync::Result<Dnt> {
55//!         if raw.len() == 1 {
56//!             let line = &raw[0];
57//!             if line.len() == 1 {
58//!                 let byte = line[0];
59//!                 match byte {
60//!                     b'0' => return Ok(Dnt(true)),
61//!                     b'1' => return Ok(Dnt(false)),
62//!                     _ => ()
63//!                 }
64//!             }
65//!         }
66//!         Err(hyper_sync::Error::Header)
67//!     }
68//!
69//!     fn fmt_header(&self, f: &mut header::Formatter) -> fmt::Result {
70//!         let value = if self.0 {
71//!             "1"
72//!         } else {
73//!             "0"
74//!         };
75//!         f.fmt_line(&value)
76//!     }
77//! }
78//! ```
79use 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
100/// A trait for any object that will represent a header field and value.
101///
102/// This trait represents the construction and identification of headers,
103/// and contains trait-object unsafe methods.
104pub trait Header: 'static + HeaderClone + Send + Sync {
105    /// Returns the name of the header field this belongs to.
106    ///
107    /// This will become an associated constant once available.
108    fn header_name() -> &'static str where Self: Sized;
109    /// Parse a header from a raw stream of bytes.
110    ///
111    /// It's possible that a request can include a header field more than once,
112    /// and in that case, the slice will have a length greater than 1. However,
113    /// it's not necessarily the case that a Header is *allowed* to have more
114    /// than one field value. If that's the case, you **should** return `None`
115    /// if `raw.len() > 1`.
116    fn parse_header(raw: &Raw) -> ::Result<Self> where Self: Sized;
117    /// Format a header to outgoing stream.
118    ///
119    /// Most headers should be formatted on one line, and so a common pattern
120    /// would be to implement `std::fmt::Display` for this type as well, and
121    /// then just call `f.fmt_line(self)`.
122    ///
123    /// ## Note
124    ///
125    /// This has the ability to format a header over multiple lines.
126    ///
127    /// The main example here is `Set-Cookie`, which requires that every
128    /// cookie being set be specified in a separate line. Almost every other
129    /// case should only format as 1 single line.
130    #[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/// A formatter used to serialize headers to an output stream.
152#[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    /// Format one 'line' of a header.
164    ///
165    /// This writes the header name plus the `Display` value as a single line.
166    ///
167    /// ## Note
168    ///
169    /// This has the ability to format a header over multiple lines.
170    ///
171    /// The main example here is `Set-Cookie`, which requires that every
172    /// cookie being set be specified in a separate line. Almost every other
173    /// case should only format as 1 single line.
174    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    // A trait object looks like this:
272    //
273    // TraitObject { data: *mut (), vtable: *mut () }
274    //
275    // So, we transmute &Trait into a (*mut (), *mut ()). This depends on the
276    // order the compiler has chosen to represent a TraitObject.
277    //
278    // It has been assured that this order will be stable.
279    #[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/// A map of header fields on requests and responses.
308#[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    /// Creates a new, empty headers map.
369    #[inline]
370    pub fn new() -> Headers {
371        Headers::with_capacity(0)
372    }
373
374    /// Creates a new `Headers` struct with space reserved for `len` headers.
375    #[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    /// Set a header field to the corresponding value.
395    ///
396    /// The field is determined by the type of the value being set.
397    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(crate) fn set_pos<H: Header>(&mut self, pos: usize, value: H) {
403    //     self.data.insert_pos(
404    //         HeaderName(Ascii::new(Cow::Borrowed(header_name::<H>()))),
405    //         Item::new_typed(value),
406    //         pos,
407    //     );
408    // }
409
410    /// Get a reference to the header field's value, if it exists.
411    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    /// Get a mutable reference to the header field's value, if it exists.
417    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    /// Returns a boolean of whether a certain header is in the map.
423    ///
424    /// Example:
425    ///
426    /// ```
427    /// # use hyper_sync::header::Headers;
428    /// # use hyper_sync::header::ContentType;
429    /// # let mut headers = Headers::new();
430    /// headers.set(ContentType::json());
431    /// assert!(headers.has::<ContentType>());
432    /// ```
433    pub fn has<H: Header>(&self) -> bool {
434        self.data.contains_key(&HeaderName(Ascii::new(Cow::Borrowed(header_name::<H>()))))
435    }
436
437    /// Removes a header from the map, if one existed.
438    /// Returns the header, if one has been removed and could be parsed.
439    ///
440    /// Note that this function may return `None` even though a header was removed. If you want to
441    /// know whether a header exists, rather rely on `has`.
442    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    /// Returns an iterator over the header fields.
448    pub fn iter(&self) -> HeadersItems {
449        HeadersItems {
450            inner: self.data.iter()
451        }
452    }
453
454    /// Returns the number of headers in the map.
455    pub fn len(&self) -> usize {
456        self.data.len()
457    }
458
459    /// Remove all headers from the map.
460    pub fn clear(&mut self) {
461        self.data.clear()
462    }
463
464    /// Access the raw value of a header.
465    ///
466    /// Prefer to use the typed getters instead.
467    ///
468    /// Example:
469    ///
470    /// ```
471    /// # use hyper_sync::header::Headers;
472    /// # let mut headers = Headers::new();
473    /// # headers.set_raw("content-type", "text/plain");
474    /// let raw = headers.get_raw("content-type").unwrap();
475    /// assert_eq!(raw, "text/plain");
476    /// ```
477    pub fn get_raw(&self, name: &str) -> Option<&Raw> {
478        self.data
479            .get(name)
480            .map(Item::raw)
481    }
482
483    /// Set the raw value of a header, bypassing any typed headers.
484    ///
485    /// Example:
486    ///
487    /// ```
488    /// # use hyper_sync::header::Headers;
489    /// # let mut headers = Headers::new();
490    /// headers.set_raw("content-length", b"1".as_ref());
491    /// headers.set_raw("content-length", "2");
492    /// headers.set_raw("content-length", "3".to_string());
493    /// headers.set_raw("content-length", vec![vec![b'4']]);
494    /// ```
495    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    /// Append a value to raw value of this header.
502    ///
503    /// If a header already contains a value, this will add another line to it.
504    ///
505    /// If a header does not exist for this name, a new one will be created with
506    /// the value.
507    ///
508    /// Example:
509    ///
510    /// ```
511    /// # use hyper_sync::header::Headers;
512    /// # let mut headers = Headers::new();
513    /// headers.append_raw("x-foo", b"bar".to_vec());
514    /// headers.append_raw("x-foo", b"quux".to_vec());
515    /// ```
516    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    /// Remove a header by name.
528    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/// An `Iterator` over the fields in a `Headers` map.
570#[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
583/// Returned with the `HeadersItems` iterator.
584pub struct HeaderView<'a>(&'a HeaderName, &'a Item);
585
586impl<'a> HeaderView<'a> {
587    /// Check if a HeaderView is a certain Header.
588    #[inline]
589    pub fn is<H: Header>(&self) -> bool {
590        HeaderName(Ascii::new(Cow::Borrowed(header_name::<H>()))) == *self.0
591    }
592
593    /// Get the Header name as a slice.
594    #[inline]
595    pub fn name(&self) -> &'a str {
596        self.0.as_ref()
597    }
598
599    /// Cast the value to a certain Header type.
600    #[inline]
601    pub fn value<H: Header>(&self) -> Option<&'a H> {
602        self.1.typed::<H>()
603    }
604
605    /// Get just the header value as a String.
606    ///
607    /// This will join multiple values of this header with a `, `.
608    ///
609    /// **Warning:** This may not be the format that should be used to send
610    /// a Request or Response.
611    #[inline]
612    pub fn value_string(&self) -> String {
613        ValueString(self.1).to_string()
614    }
615
616    /// Access the raw value of the header.
617    #[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            //let trim = header.value.iter().rev().take_while(|&&x| x == b' ').count();
650
651            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        // Redundant, should not increase count.
887        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}