hyperx/header/
mod.rs

1//! Headers container, and common header fields.
2//!
3//! ## Why Typed?
4//!
5//! Hyper <strike>has</strike> had the opinion that:
6//!
7//! > <em>
8//! >
9//! > Headers should be strongly-typed, because that's why we're using Rust in
10//! > the first place. Or, why not stringly-typed? Types give the following
11//! > advantages:
12//! > - More difficult to typo, since typos in types should be caught by the
13//! >   compiler
14//! > - Parsing to a proper type by default
15//! >
16//! > </em>
17//!
18//! However, it seems that for many applications, it is sufficient to use
19//! `http::header::HeaderMap` (byte values) and parse only the headers that
20//! are of interest.
21//!
22//! ## Parsing `http::header::HeaderValue`s
23//!
24//! `HeaderValue`(s) implement the `RawLike` trait which allows for parsing
25//! with less copying than going through `HeaderValue::to_str` or the `Raw`
26//! type. See example usage below:
27//!
28//! ```
29//! # extern crate hyperx;
30//! # extern crate http;
31//! # fn run() -> Result<(), Box<std::error::Error>> {
32//! use http::header::{HeaderMap, CONTENT_ENCODING};
33//! use hyperx::header::{ContentEncoding, Encoding, Header};
34//!
35//! // Given a HeaderMap with 2 Content-Encoding headers and 3 delimited values
36//! let mut hmap = HeaderMap::new();
37//! hmap.insert(CONTENT_ENCODING, "chunked, gzip".parse()?);
38//! hmap.append(CONTENT_ENCODING, "identity".parse()?);
39//!
40//! // Parse the first header value
41//! let first = hmap.get(CONTENT_ENCODING).unwrap();
42//! let ce = ContentEncoding::parse_header(&first)?;
43//! assert_eq!(ce, ContentEncoding(vec![Encoding::Chunked, Encoding::Gzip]));
44//!
45//! // Parse all header values to a single list
46//! let all = hmap.get_all(CONTENT_ENCODING);
47//! let ce = ContentEncoding::parse_header(&all)?;
48//! assert_eq!(ce, ContentEncoding(
49//!     vec![Encoding::Chunked, Encoding::Gzip, Encoding::Identity]
50//! ));
51//! # Ok(())
52//! # }
53//! # fn main() {
54//! #     run().unwrap();
55//! # }
56//! ```
57//!
58//! ## `TypedHeaders` extension to `http::HeaderMap`
59//!
60//! The [`TypedHeaders`](trait.TypedHeaders.html) extension trait provides more
61//! convenient `encode`/`decode` methods on `HeaderMap` generically for the
62//! standard header types named in the _http_ crate:
63//!
64//! ```
65//! # extern crate hyperx;
66//! # extern crate http;
67//! # fn run() -> Result<(), Box<std::error::Error>> {
68//! use http::header::HeaderMap;
69//! use hyperx::header::{ContentEncoding, Encoding, TypedHeaders};
70//!
71//! let mut hmap = http::HeaderMap::new();
72//! hmap.encode(
73//!     &ContentEncoding(vec![Encoding::Identity]));
74//! hmap.encode_append(
75//!     &ContentEncoding(vec![Encoding::Gzip, Encoding::Chunked]));
76//! let ce: ContentEncoding = hmap.decode()?;
77//! assert_eq!(
78//!     *ce,
79//!     vec![Encoding::Identity, Encoding::Gzip, Encoding::Chunked]
80//! );
81//! # Ok(())
82//! # }
83//! # fn main() {
84//! #     run().unwrap();
85//! # }
86//! ```
87//!
88//! ## Defining Custom Headers
89//!
90//! Hyper*x* provides all commonly used headers in HTTP. If you
91//! need to define a custom header, it's easy to do while still taking
92//! advantage of the type system. Hyper*x* includes a `header!` macro for
93//! defining many wrapper-style headers.
94//!
95//! ```
96//! # extern crate http;
97//! # #[macro_use] extern crate hyperx;
98//! header! { (XRequestGuid, "X-Request-Guid") => [String] }
99//!
100//! fn main () {
101//!     let mut headers = http::HeaderMap::new();
102//!
103//!     headers.insert(
104//!         "x-request-guid",
105//!         XRequestGuid("a proper guid".to_owned()).to_string().parse().unwrap()
106//!     );
107//! }
108//! ```
109//!
110//! This works well for simple "string" headers.  If you need more control,
111//! you can implement the trait directly.
112//!
113//! ## Implementing the `Header` trait
114//!
115//! Consider a Do Not Track header. It can be true or false, but it represents
116//! that via the numerals `1` and `0`.
117//!
118//! ```
119//! use std::fmt;
120//! use hyperx::header::{self, Header, RawLike};
121//!
122//! #[derive(Debug, Clone, Copy)]
123//! struct Dnt(bool);
124//!
125//! impl Header for Dnt {
126//!     fn header_name() -> &'static str {
127//!         "DNT"
128//!     }
129//!
130//!     fn parse_header<'a, T>(raw: &'a T) -> hyperx::Result<Dnt>
131//!         where T: RawLike<'a>
132//!     {
133//!         if let Some(line) = raw.one() {
134//!             if line.len() == 1 {
135//!                 let byte = line[0];
136//!                 match byte {
137//!                     b'0' => return Ok(Dnt(true)),
138//!                     b'1' => return Ok(Dnt(false)),
139//!                     _ => ()
140//!                 }
141//!             }
142//!         }
143//!         Err(hyperx::Error::Header)
144//!     }
145//!
146//!     fn fmt_header(&self, f: &mut header::Formatter) -> fmt::Result {
147//!         let value = if self.0 {
148//!             "1"
149//!         } else {
150//!             "0"
151//!         };
152//!         f.fmt_line(&value)
153//!     }
154//! }
155//! ```
156use 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
189/// A trait for any object that will represent a header field and value.
190///
191/// This trait represents the construction and identification of headers,
192/// and contains trait-object unsafe methods.
193pub trait Header: 'static + HeaderClone + Send + Sync {
194    /// Returns the name of the header field this belongs to.
195    ///
196    /// This will become an associated constant once available.
197    fn header_name() -> &'static str
198    where Self: Sized;
199
200    /// Parse a header from a raw stream of bytes.
201    ///
202    /// It's possible that a request can include a header field more than once,
203    /// and in that case, the slice will have a length greater than 1. However,
204    /// it's not necessarily the case that a Header is *allowed* to have more
205    /// than one field value. If that's the case, you **should** return `None`
206    /// if `raw.len() > 1`.
207    fn parse_header<'a, T>(raw: &'a T) -> ::Result<Self>
208    where T: RawLike<'a>, Self: Sized;
209
210    /// Format a header to outgoing stream.
211    ///
212    /// Most headers should be formatted on one line, and so a common pattern
213    /// would be to implement `std::fmt::Display` for this type as well, and
214    /// then just call `f.fmt_line(self)`.
215    ///
216    /// ## Note
217    ///
218    /// This has the ability to format a header over multiple lines.
219    ///
220    /// The main example here is `Set-Cookie`, which requires that every
221    /// cookie being set be specified in a separate line. Almost every other
222    /// case should only format as 1 single line.
223    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/// A formatter used to serialize headers to an output stream.
243#[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    /// Format one 'line' of a header.
256    ///
257    /// This writes the header name plus the `Display` value as a single line.
258    ///
259    /// ## Note
260    ///
261    /// This has the ability to format a header over multiple lines.
262    ///
263    /// The main example here is `Set-Cookie`, which requires that every
264    /// cookie being set be specified in a separate line. Almost every other
265    /// case should only format as 1 single line.
266    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    // A trait object looks like this:
366    //
367    // TraitObject { data: *mut (), vtable: *mut () }
368    //
369    // So, we transmute &Trait into a (*mut (), *mut ()). This depends on the
370    // order the compiler has chosen to represent a TraitObject.
371    //
372    // It has been assured that this order will be stable.
373    #[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/// A specialized map of typed headers.
406///
407/// This type is only available with the non-default _headers_ feature
408/// enabled. The type is preserved for compatibly, but its use is no longer
409/// required nor recommended. Consider replacing with `http::HeaderMap` and its
410/// [`TypedHeaders`](trait.TypedHeaders.html) extension.
411#[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    /// Creates a new, empty headers map.
475    #[inline]
476    pub fn new() -> Headers {
477        Headers::with_capacity(0)
478    }
479
480    /// Creates a new `Headers` struct with space reserved for `len` headers.
481    #[inline]
482    pub fn with_capacity(len: usize) -> Headers {
483        Headers {
484            data: VecMap::with_capacity(len)
485        }
486    }
487
488    /// Set a header field to the corresponding value.
489    ///
490    /// The field is determined by the type of the value being set.
491    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    /// Get a reference to the header field's value, if it exists.
497    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    /// Get a mutable reference to the header field's value, if it exists.
503    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    /// Returns a boolean of whether a certain header is in the map.
509    ///
510    /// Example:
511    ///
512    /// ```
513    /// # use hyperx::header::Headers;
514    /// # use hyperx::header::ContentType;
515    /// # let mut headers = Headers::new();
516    /// headers.set(ContentType::json());
517    /// assert!(headers.has::<ContentType>());
518    /// ```
519    pub fn has<H: Header>(&self) -> bool {
520        self.data.contains_key(&HeaderName(Ascii::new(Cow::Borrowed(header_name::<H>()))))
521    }
522
523    /// Removes a header from the map, if one existed.
524    /// Returns the header, if one has been removed and could be parsed.
525    ///
526    /// Note that this function may return `None` even though a header was removed. If you want to
527    /// know whether a header exists, rather rely on `has`.
528    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    /// Returns an iterator over the header fields.
534    pub fn iter(&self) -> HeadersItems {
535        HeadersItems {
536            inner: self.data.iter()
537        }
538    }
539
540    /// Returns the number of headers in the map.
541    pub fn len(&self) -> usize {
542        self.data.len()
543    }
544
545    /// Remove all headers from the map.
546    pub fn clear(&mut self) {
547        self.data.clear()
548    }
549
550    /// Access the raw value of a header.
551    ///
552    /// Prefer to use the typed getters instead.
553    ///
554    /// Example:
555    ///
556    /// ```
557    /// # use hyperx::header::Headers;
558    /// # let mut headers = Headers::new();
559    /// # headers.set_raw("content-type", "text/plain");
560    /// let raw = headers.get_raw("content-type").unwrap();
561    /// assert_eq!(raw, "text/plain");
562    /// ```
563    pub fn get_raw(&self, name: &str) -> Option<&Raw> {
564        self.data
565            .get(name)
566            .map(Item::raw)
567    }
568
569    /// Set the raw value of a header, bypassing any typed headers.
570    ///
571    /// Example:
572    ///
573    /// ```
574    /// # use hyperx::header::Headers;
575    /// # let mut headers = Headers::new();
576    /// headers.set_raw("content-length", b"1".as_ref());
577    /// headers.set_raw("content-length", "2");
578    /// headers.set_raw("content-length", "3".to_string());
579    /// headers.set_raw("content-length", vec![vec![b'4']]);
580    /// ```
581    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    /// Append a value to raw value of this header.
588    ///
589    /// If a header already contains a value, this will add another line to it.
590    ///
591    /// If a header does not exist for this name, a new one will be created with
592    /// the value.
593    ///
594    /// Example:
595    ///
596    /// ```
597    /// # use hyperx::header::Headers;
598    /// # let mut headers = Headers::new();
599    /// headers.append_raw("x-foo", b"bar".to_vec());
600    /// headers.append_raw("x-foo", b"quux".to_vec());
601    /// ```
602    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    /// Alternative to append_raw that avoids an allocation if name
614    /// already exists as a key.
615    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    /// Remove a header by name.
626    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/// An `Iterator` over the fields in a `Headers` map.
671#[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/// Returned with the `HeadersItems` iterator.
687#[cfg(feature = "headers")]
688pub struct HeaderView<'a>(&'a HeaderName, &'a Item);
689
690#[cfg(feature = "headers")]
691impl<'a> HeaderView<'a> {
692    /// Check if a HeaderView is a certain Header.
693    #[inline]
694    pub fn is<H: Header>(&self) -> bool {
695        HeaderName(Ascii::new(Cow::Borrowed(header_name::<H>()))) == *self.0
696    }
697
698    /// Get the Header name as a slice.
699    #[inline]
700    pub fn name(&self) -> &'a str {
701        self.0.as_ref()
702    }
703
704    /// Cast the value to a certain Header type.
705    #[inline]
706    pub fn value<H: Header>(&self) -> Option<&'a H> {
707        self.1.typed::<H>()
708    }
709
710    /// Get just the header value as a String.
711    ///
712    /// This will join multiple values of this header with a `, `.
713    ///
714    /// **Warning:** This may not be the format that should be used to send
715    /// a Request or Response.
716    #[inline]
717    pub fn value_string(&self) -> String {
718        ValueString(self.1).to_string()
719    }
720
721    /// Access the raw value of the header.
722    #[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            //let trim = header.value.iter().rev().take_while(|&&x| x == b' ').count();
759
760            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        // Redundant, should not increase count.
1002        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}