refactor(header): change Header::fmt_header to take a header::Formatter
				
					
				
			The `header::Formatter` ensures that a formatted header is written to a line, and allows for headers that require multiple lines. The only header to specifically require this is `Set-Cookie`. BREAKING CHANGE: The `fmt_header` method has changed to take a different formatter. In most cases, if your header also implements `fmt::Display`, you can just call `f.fmt_line(self)`.
This commit is contained in:
		| @@ -63,14 +63,14 @@ impl Header for AccessControlAllowCredentials { | ||||
|         Err(::Error::Header) | ||||
|     } | ||||
|  | ||||
|     fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||
|         f.write_str("true") | ||||
|     fn fmt_header(&self, f: &mut ::header::Formatter) -> fmt::Result { | ||||
|         f.fmt_line(self) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl Display for AccessControlAllowCredentials { | ||||
|     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { | ||||
|         self.fmt_header(f) | ||||
|         f.write_str("true") | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -72,18 +72,18 @@ impl Header for AccessControlAllowOrigin { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||
|         match *self { | ||||
|             AccessControlAllowOrigin::Any => f.write_str("*"), | ||||
|             AccessControlAllowOrigin::Null => f.write_str("null"), | ||||
|             AccessControlAllowOrigin::Value(ref url) => Display::fmt(url, f), | ||||
|         } | ||||
|     fn fmt_header(&self, f: &mut ::header::Formatter) -> fmt::Result { | ||||
|         f.fmt_line(self) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl Display for AccessControlAllowOrigin { | ||||
|     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { | ||||
|         self.fmt_header(f) | ||||
|         match *self { | ||||
|             AccessControlAllowOrigin::Any => f.write_str("*"), | ||||
|             AccessControlAllowOrigin::Null => f.write_str("null"), | ||||
|             AccessControlAllowOrigin::Value(ref url) => Display::fmt(url, f), | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -100,8 +100,8 @@ impl<S: Scheme + Any> Header for Authorization<S> where <S as FromStr>::Err: 'st | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||
|         fmt::Display::fmt(self, f) | ||||
|     fn fmt_header(&self, f: &mut ::header::Formatter) -> fmt::Result { | ||||
|         f.fmt_line(self) | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -49,6 +49,7 @@ pub struct CacheControl(pub Vec<CacheDirective>); | ||||
|  | ||||
| __hyper__deref!(CacheControl => Vec<CacheDirective>); | ||||
|  | ||||
| //TODO: this could just be the header! macro | ||||
| impl Header for CacheControl { | ||||
|     fn header_name() -> &'static str { | ||||
|         static NAME: &'static str = "Cache-Control"; | ||||
| @@ -64,8 +65,8 @@ impl Header for CacheControl { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||
|         fmt::Display::fmt(self, f) | ||||
|     fn fmt_header(&self, f: &mut ::header::Formatter) -> fmt::Result { | ||||
|         f.fmt_line(self) | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -146,8 +146,8 @@ impl Header for ContentDisposition { | ||||
|     } | ||||
|  | ||||
|     #[inline] | ||||
|     fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||
|         fmt::Display::fmt(&self, f) | ||||
|     fn fmt_header(&self, f: &mut ::header::Formatter) -> fmt::Result { | ||||
|         f.fmt_line(self) | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -60,8 +60,8 @@ impl Header for ContentLength { | ||||
|     } | ||||
|  | ||||
|     #[inline] | ||||
|     fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||
|         fmt::Display::fmt(&self.0, f) | ||||
|     fn fmt_header(&self, f: &mut ::header::Formatter) -> fmt::Result { | ||||
|         f.fmt_line(self) | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -54,8 +54,8 @@ impl Header for Cookie { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||
|         fmt::Display::fmt(self, f) | ||||
|     fn fmt_header(&self, f: &mut ::header::Formatter) -> fmt::Result { | ||||
|         f.fmt_line(self) | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -54,8 +54,8 @@ impl Header for Expect { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||
|         fmt::Display::fmt(self, f) | ||||
|     fn fmt_header(&self, f: &mut ::header::Formatter) -> fmt::Result { | ||||
|         f.fmt_line(self) | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -68,17 +68,17 @@ impl Header for Host { | ||||
|        from_one_raw_str(raw) | ||||
|     } | ||||
|  | ||||
|     fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||
|         match self.port { | ||||
|             None | Some(80) | Some(443) => f.write_str(&self.hostname[..]), | ||||
|             Some(port) => write!(f, "{}:{}", self.hostname, port) | ||||
|         } | ||||
|     fn fmt_header(&self, f: &mut ::header::Formatter) -> fmt::Result { | ||||
|         f.fmt_line(self) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl fmt::Display for Host { | ||||
|     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||
|         self.fmt_header(f) | ||||
|         match self.port { | ||||
|             None | Some(80) | Some(443) => f.write_str(&self.hostname[..]), | ||||
|             Some(port) => write!(f, "{}:{}", self.hostname, port) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -70,17 +70,17 @@ impl Header for IfRange { | ||||
|         Err(::Error::Header) | ||||
|     } | ||||
|  | ||||
|     fn fmt_header(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { | ||||
|         match *self { | ||||
|             IfRange::EntityTag(ref x) => Display::fmt(x, f), | ||||
|             IfRange::Date(ref x) => Display::fmt(x, f), | ||||
|         } | ||||
|     fn fmt_header(&self, f: &mut ::header::Formatter) -> ::std::fmt::Result { | ||||
|         f.fmt_line(self) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl Display for IfRange { | ||||
|     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||
|         self.fmt_header(f) | ||||
|         match *self { | ||||
|             IfRange::EntityTag(ref x) => Display::fmt(x, f), | ||||
|             IfRange::Date(ref x) => Display::fmt(x, f), | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -423,14 +423,14 @@ impl Header for Link { | ||||
|             .unwrap_or(Err(::Error::Header)) | ||||
|     } | ||||
|  | ||||
|     fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||
|         fmt_delimited(f, self.values.as_slice(), ", ", ("", "")) | ||||
|     fn fmt_header(&self, f: &mut ::header::Formatter) -> fmt::Result { | ||||
|         f.fmt_line(self) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl fmt::Display for Link { | ||||
|     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||
|         self.fmt_header(f) | ||||
|         fmt_delimited(f, self.values.as_slice(), ", ", ("", "")) | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -204,14 +204,13 @@ macro_rules! header { | ||||
|             fn parse_header(raw: &$crate::header::Raw) -> $crate::Result<Self> { | ||||
|                 $crate::header::parsing::from_comma_delimited(raw).map($id) | ||||
|             } | ||||
|             fn fmt_header(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { | ||||
|                 $crate::header::parsing::fmt_comma_delimited(f, &self.0[..]) | ||||
|             fn fmt_header(&self, f: &mut $crate::header::Formatter) -> ::std::fmt::Result { | ||||
|                 f.fmt_line(self) | ||||
|             } | ||||
|         } | ||||
|         impl ::std::fmt::Display for $id { | ||||
|             fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { | ||||
|                 use $crate::header::Header; | ||||
|                 self.fmt_header(f) | ||||
|                 $crate::header::parsing::fmt_comma_delimited(f, &self.0[..]) | ||||
|             } | ||||
|         } | ||||
|     }; | ||||
| @@ -229,14 +228,13 @@ macro_rules! header { | ||||
|             fn parse_header(raw: &$crate::header::Raw) -> $crate::Result<Self> { | ||||
|                 $crate::header::parsing::from_comma_delimited(raw).map($id) | ||||
|             } | ||||
|             fn fmt_header(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { | ||||
|                 $crate::header::parsing::fmt_comma_delimited(f, &self.0[..]) | ||||
|             fn fmt_header(&self, f: &mut $crate::header::Formatter) -> ::std::fmt::Result { | ||||
|                 f.fmt_line(self) | ||||
|             } | ||||
|         } | ||||
|         impl ::std::fmt::Display for $id { | ||||
|             fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { | ||||
|                 use $crate::header::Header; | ||||
|                 self.fmt_header(f) | ||||
|                 $crate::header::parsing::fmt_comma_delimited(f, &self.0[..]) | ||||
|             } | ||||
|         } | ||||
|     }; | ||||
| @@ -254,8 +252,8 @@ macro_rules! header { | ||||
|             fn parse_header(raw: &$crate::header::Raw) -> $crate::Result<Self> { | ||||
|                 $crate::header::parsing::from_one_raw_str(raw).map($id) | ||||
|             } | ||||
|             fn fmt_header(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { | ||||
|                 ::std::fmt::Display::fmt(&**self, f) | ||||
|             fn fmt_header(&self, f: &mut $crate::header::Formatter) -> ::std::fmt::Result { | ||||
|                 f.fmt_line(self) | ||||
|             } | ||||
|         } | ||||
|         impl ::std::fmt::Display for $id { | ||||
| @@ -289,8 +287,8 @@ macro_rules! header { | ||||
|             fn parse_header(raw: &$crate::header::Raw) -> $crate::Result<Self> { | ||||
|                 $crate::header::parsing::from_one_raw_str::<<$value as ::std::borrow::ToOwned>::Owned>(raw).map($id::new) | ||||
|             } | ||||
|             fn fmt_header(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { | ||||
|                 ::std::fmt::Display::fmt(&**self, f) | ||||
|             fn fmt_header(&self, f: &mut $crate::header::Formatter) -> ::std::fmt::Result { | ||||
|                 f.fmt_line(self) | ||||
|             } | ||||
|         } | ||||
|         impl ::std::fmt::Display for $id { | ||||
| @@ -323,7 +321,12 @@ macro_rules! header { | ||||
|                 } | ||||
|                 $crate::header::parsing::from_comma_delimited(raw).map($id::Items) | ||||
|             } | ||||
|             fn fmt_header(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { | ||||
|             fn fmt_header(&self, f: &mut $crate::header::Formatter) -> ::std::fmt::Result { | ||||
|                 f.fmt_line(self) | ||||
|             } | ||||
|         } | ||||
|         impl ::std::fmt::Display for $id { | ||||
|             fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { | ||||
|                 match *self { | ||||
|                     $id::Any => f.write_str("*"), | ||||
|                     $id::Items(ref fields) => $crate::header::parsing::fmt_comma_delimited( | ||||
| @@ -331,12 +334,6 @@ macro_rules! header { | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         impl ::std::fmt::Display for $id { | ||||
|             fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { | ||||
|                 use $crate::header::Header; | ||||
|                 self.fmt_header(f) | ||||
|             } | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     // optional test module | ||||
|   | ||||
| @@ -104,8 +104,8 @@ impl Header for Origin { | ||||
|         from_one_raw_str(raw) | ||||
|     } | ||||
|  | ||||
|     fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||
|         fmt::Display::fmt(self, f) | ||||
|     fn fmt_header(&self, f: &mut ::header::Formatter) -> fmt::Result { | ||||
|         f.fmt_line(self) | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -54,8 +54,8 @@ impl Header for Pragma { | ||||
|         }) | ||||
|     } | ||||
|  | ||||
|     fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||
|         fmt::Display::fmt(self, f) | ||||
|     fn fmt_header(&self, f: &mut ::header::Formatter) -> fmt::Result { | ||||
|         f.fmt_line(self) | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -65,8 +65,8 @@ impl Header for Prefer { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||
|         fmt::Display::fmt(self, f) | ||||
|     fn fmt_header(&self, f: &mut ::header::Formatter) -> fmt::Result { | ||||
|         f.fmt_line(self) | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -63,8 +63,8 @@ impl Header for PreferenceApplied { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||
|         fmt::Display::fmt(self, f) | ||||
|     fn fmt_header(&self, f: &mut ::header::Formatter) -> fmt::Result { | ||||
|         f.fmt_line(self) | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -190,8 +190,8 @@ impl Header for Range { | ||||
|         from_one_raw_str(raw) | ||||
|     } | ||||
|  | ||||
|     fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||
|         Display::fmt(self, f) | ||||
|     fn fmt_header(&self, f: &mut ::header::Formatter) -> fmt::Result { | ||||
|         f.fmt_line(self) | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -79,8 +79,8 @@ impl Header for ReferrerPolicy { | ||||
|         Err(::Error::Header) | ||||
|     } | ||||
|  | ||||
|     fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||
|         fmt::Display::fmt(self, f) | ||||
|     fn fmt_header(&self, f: &mut ::header::Formatter) -> fmt::Result { | ||||
|         f.fmt_line(self) | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -121,7 +121,13 @@ impl Header for RetryAfter { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||
|     fn fmt_header(&self, f: &mut ::header::Formatter) -> ::std::fmt::Result { | ||||
|         f.fmt_line(self) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl fmt::Display for RetryAfter { | ||||
|     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||
|         match *self { | ||||
|             RetryAfter::Delay(ref duration) => { | ||||
|                 write!(f, "{}", duration.num_seconds()) | ||||
|   | ||||
| @@ -91,16 +91,7 @@ impl Header for SetCookie { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||
|         if self.0.len() == 1 { | ||||
|             write!(f, "{}", &self.0[0]) | ||||
|         } else { | ||||
|             panic!("SetCookie with multiple cookies cannot be used with fmt_header, must use fmt_multi_header"); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|  | ||||
|     fn fmt_multi_header(&self, f: &mut ::header::MultilineFormatter) -> fmt::Result { | ||||
|     fn fmt_header(&self, f: &mut ::header::Formatter) -> fmt::Result { | ||||
|         for cookie in &self.0 { | ||||
|             try!(f.fmt_line(cookie)); | ||||
|         } | ||||
|   | ||||
| @@ -129,8 +129,8 @@ impl Header for StrictTransportSecurity { | ||||
|         parsing::from_one_raw_str(raw) | ||||
|     } | ||||
|  | ||||
|     fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||
|         fmt::Display::fmt(self, f) | ||||
|     fn fmt_header(&self, f: &mut ::header::Formatter) -> fmt::Result { | ||||
|         f.fmt_line(self) | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -96,7 +96,13 @@ impl Header for Warning { | ||||
|         from_one_raw_str(raw) | ||||
|     } | ||||
|  | ||||
|     fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||
|     fn fmt_header(&self, f: &mut ::header::Formatter) -> fmt::Result { | ||||
|         f.fmt_line(self) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl fmt::Display for Warning { | ||||
|     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||
|         match self.date { | ||||
|             Some(date) => write!(f, "{:03} {} \"{}\" \"{}\"", self.code, self.agent, self.text, date), | ||||
|             None => write!(f, "{:03} {} \"{}\"", self.code, self.agent, self.text) | ||||
|   | ||||
| @@ -4,7 +4,7 @@ use std::fmt; | ||||
| use std::str::from_utf8; | ||||
|  | ||||
| use super::cell::{OptCell, PtrMapCell}; | ||||
| use header::{Header, MultilineFormatter, Multi, raw, Raw}; | ||||
| use header::{Header, Formatter, Multi, raw, Raw}; | ||||
|  | ||||
|  | ||||
| #[derive(Clone)] | ||||
| @@ -47,7 +47,7 @@ impl Item { | ||||
|         } | ||||
|  | ||||
|         let mut raw = raw::new(); | ||||
|         self.write_h1(&mut MultilineFormatter(Multi::Raw(&mut raw))).expect("fmt failed"); | ||||
|         self.write_h1(&mut Formatter(Multi::Raw(&mut raw))).expect("fmt failed"); | ||||
|         self.raw.set(raw); | ||||
|  | ||||
|         self.raw.as_ref().unwrap() | ||||
| @@ -93,7 +93,7 @@ impl Item { | ||||
|         }.map(|typed| unsafe { typed.downcast_unchecked() }) | ||||
|     } | ||||
|  | ||||
|     pub fn write_h1(&self, f: &mut MultilineFormatter) -> fmt::Result { | ||||
|     pub fn write_h1(&self, f: &mut Formatter) -> fmt::Result { | ||||
|         match *self.raw { | ||||
|             Some(ref raw) => { | ||||
|                 for part in raw.iter() { | ||||
| @@ -111,7 +111,7 @@ impl Item { | ||||
|             }, | ||||
|             None => { | ||||
|                 let typed = unsafe { self.typed.one() }; | ||||
|                 typed.fmt_multi_header(f) | ||||
|                 typed.fmt_header(f) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|   | ||||
| @@ -41,7 +41,7 @@ | ||||
| //! | ||||
| //! ``` | ||||
| //! use std::fmt; | ||||
| //! use hyper::header::{Header, Raw}; | ||||
| //! use hyper::header::{self, Header, Raw}; | ||||
| //! | ||||
| //! #[derive(Debug, Clone, Copy)] | ||||
| //! struct Dnt(bool); | ||||
| @@ -66,16 +66,16 @@ | ||||
| //!         Err(hyper::Error::Header) | ||||
| //!     } | ||||
| //! | ||||
| //!     fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||
| //!         if self.0 { | ||||
| //!             f.write_str("1") | ||||
| //!     fn fmt_header(&self, f: &mut header::Formatter) -> fmt::Result { | ||||
| //!         let value = if self.0 { | ||||
| //!             "1" | ||||
| //!         } else { | ||||
| //!             f.write_str("0") | ||||
| //!         } | ||||
| //!             "0" | ||||
| //!         }; | ||||
| //!         f.fmt_line(&value) | ||||
| //!     } | ||||
| //! } | ||||
| //! ``` | ||||
| use std::any::{Any, TypeId}; | ||||
| use std::borrow::{Cow, ToOwned}; | ||||
| use std::iter::{FromIterator, IntoIterator}; | ||||
| use std::{mem, fmt}; | ||||
| @@ -83,6 +83,7 @@ use std::{mem, fmt}; | ||||
| use unicase::UniCase; | ||||
|  | ||||
| use self::internals::{Item, VecMap, Entry}; | ||||
| use self::sealed::{GetType, HeaderClone}; | ||||
|  | ||||
| pub use self::shared::*; | ||||
| pub use self::common::*; | ||||
| @@ -100,7 +101,7 @@ pub mod parsing; | ||||
| /// | ||||
| /// This trait represents the construction and identification of headers, | ||||
| /// and contains trait-object unsafe methods. | ||||
| pub trait Header: HeaderClone + Any + GetType + Send + Sync { | ||||
| pub trait Header: HeaderClone + GetType + Send + Sync { | ||||
|     /// Returns the name of the header field this belongs to. | ||||
|     /// | ||||
|     /// This will become an associated constant once available. | ||||
| @@ -113,38 +114,51 @@ pub trait Header: HeaderClone + Any + GetType + Send + Sync { | ||||
|     /// than one field value. If that's the case, you **should** return `None` | ||||
|     /// if `raw.len() > 1`. | ||||
|     fn parse_header(raw: &Raw) -> ::Result<Self> where Self: Sized; | ||||
|     /// Format a header to be output into a TcpStream. | ||||
|     /// Format a header to outgoing stream. | ||||
|     /// | ||||
|     /// This method is not allowed to introduce an Err not produced | ||||
|     /// by the passed-in Formatter. | ||||
|     fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result; | ||||
|     /// Formats a header over multiple lines. | ||||
|     /// Most headers should be formatted on one line, and so a common pattern | ||||
|     /// would be to implement `std::fmt::Display` for this type as well, and | ||||
|     /// then just call `f.fmt_line(self)`. | ||||
|     /// | ||||
|     /// ## Note | ||||
|     /// | ||||
|     /// This has the ability to format a header over multiple lines. | ||||
|     /// | ||||
|     /// The main example here is `Set-Cookie`, which requires that every | ||||
|     /// cookie being set be specified in a separate line. | ||||
|     /// | ||||
|     /// The API here is still being explored, so this is hidden by default. | ||||
|     /// The passed in formatter doesn't have any public methods, so it would | ||||
|     /// be quite difficult to depend on this externally. | ||||
|     #[doc(hidden)] | ||||
|     /// cookie being set be specified in a separate line. Almost every other | ||||
|     /// case should only format as 1 single line. | ||||
|     #[inline] | ||||
|     fn fmt_multi_header(&self, f: &mut MultilineFormatter) -> fmt::Result { | ||||
|         f.fmt_line(&FmtHeader(self)) | ||||
|     } | ||||
|     fn fmt_header(&self, f: &mut Formatter) -> fmt::Result; | ||||
| } | ||||
|  | ||||
| #[doc(hidden)] | ||||
| pub trait GetType: Any { | ||||
| mod sealed { | ||||
|     use std::any::{Any, TypeId}; | ||||
|     use super::Header; | ||||
|  | ||||
|     #[doc(hidden)] | ||||
|     pub trait GetType: Any { | ||||
|         #[inline(always)] | ||||
|         fn get_type(&self) -> TypeId { | ||||
|             TypeId::of::<Self>() | ||||
|         } | ||||
| } | ||||
|     } | ||||
|  | ||||
| impl<T: Any> GetType for T {} | ||||
|     impl<T: Any> GetType for T {} | ||||
|  | ||||
| #[test] | ||||
| fn test_get_type() { | ||||
|     #[doc(hidden)] | ||||
|     pub trait HeaderClone { | ||||
|         fn clone_box(&self) -> Box<Header + Send + Sync>; | ||||
|     } | ||||
|  | ||||
|     impl<T: Header + Clone> HeaderClone for T { | ||||
|         #[inline] | ||||
|         fn clone_box(&self) -> Box<Header + Send + Sync> { | ||||
|             Box::new(self.clone()) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     #[test] | ||||
|     fn test_get_type() { | ||||
|         use ::header::{ContentLength, UserAgent}; | ||||
|  | ||||
|         let len = ContentLength(5); | ||||
| @@ -158,11 +172,13 @@ fn test_get_type() { | ||||
|  | ||||
|         assert_eq!(TypeId::of::<ContentLength>(), (*len).get_type()); | ||||
|         assert_eq!(TypeId::of::<UserAgent>(), (*agent).get_type()); | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[doc(hidden)] | ||||
|  | ||||
| /// A formatter used to serialize headers to an output stream. | ||||
| #[allow(missing_debug_implementations)] | ||||
| pub struct MultilineFormatter<'a, 'b: 'a>(Multi<'a, 'b>); | ||||
| pub struct Formatter<'a, 'b: 'a>(Multi<'a, 'b>); | ||||
|  | ||||
| enum Multi<'a, 'b: 'a> { | ||||
|     Line(&'a str, &'a mut fmt::Formatter<'b>), | ||||
| @@ -170,8 +186,20 @@ enum Multi<'a, 'b: 'a> { | ||||
|     Raw(&'a mut Raw), | ||||
| } | ||||
|  | ||||
| impl<'a, 'b> MultilineFormatter<'a, 'b> { | ||||
|     fn fmt_line(&mut self, line: &fmt::Display) -> fmt::Result { | ||||
| impl<'a, 'b> Formatter<'a, 'b> { | ||||
|  | ||||
|     /// Format one 'line' of a header. | ||||
|     /// | ||||
|     /// This writes the header name plus the `Display` value as a single line. | ||||
|     /// | ||||
|     /// ## Note | ||||
|     /// | ||||
|     /// This has the ability to format a header over multiple lines. | ||||
|     /// | ||||
|     /// The main example here is `Set-Cookie`, which requires that every | ||||
|     /// cookie being set be specified in a separate line. Almost every other | ||||
|     /// case should only format as 1 single line. | ||||
|     pub fn fmt_line(&mut self, line: &fmt::Display) -> fmt::Result { | ||||
|         use std::fmt::Write; | ||||
|         match self.0 { | ||||
|             Multi::Line(ref name, ref mut f) => { | ||||
| @@ -198,28 +226,19 @@ impl<'a, 'b> MultilineFormatter<'a, 'b> { | ||||
|     } | ||||
| } | ||||
|  | ||||
| // Internal helper to wrap fmt_header into a fmt::Display | ||||
| struct FmtHeader<'a, H: ?Sized + 'a>(&'a H); | ||||
|  | ||||
| impl<'a, H: Header + ?Sized + 'a> fmt::Display for FmtHeader<'a, H> { | ||||
|     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||
|         self.0.fmt_header(f) | ||||
|     } | ||||
| } | ||||
|  | ||||
| struct ValueString<'a>(&'a Item); | ||||
|  | ||||
| impl<'a> fmt::Debug for ValueString<'a> { | ||||
|     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||
|         try!(f.write_str("\"")); | ||||
|         try!(self.0.write_h1(&mut MultilineFormatter(Multi::Join(true, f)))); | ||||
|         try!(self.0.write_h1(&mut Formatter(Multi::Join(true, f)))); | ||||
|         f.write_str("\"") | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl<'a> fmt::Display for ValueString<'a> { | ||||
|     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||
|         self.0.write_h1(&mut MultilineFormatter(Multi::Join(true, f))) | ||||
|         self.0.write_h1(&mut Formatter(Multi::Join(true, f))) | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -229,7 +248,7 @@ impl<'a, H: Header> fmt::Debug for HeaderValueString<'a, H> { | ||||
|     #[inline] | ||||
|     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||
|         try!(f.write_str("\"")); | ||||
|         try!(self.0.fmt_multi_header(&mut MultilineFormatter(Multi::Join(true, f)))); | ||||
|         try!(self.0.fmt_header(&mut Formatter(Multi::Join(true, f)))); | ||||
|         f.write_str("\"") | ||||
|     } | ||||
| } | ||||
| @@ -254,17 +273,6 @@ impl<'a, F: fmt::Write + 'a> fmt::Write for NewlineReplacer<'a, F> { | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[doc(hidden)] | ||||
| pub trait HeaderClone { | ||||
|     fn clone_box(&self) -> Box<Header + Send + Sync>; | ||||
| } | ||||
|  | ||||
| impl<T: Header + Clone> HeaderClone for T { | ||||
|     #[inline] | ||||
|     fn clone_box(&self) -> Box<Header + Send + Sync> { | ||||
|         Box::new(self.clone()) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl Header + Send + Sync { | ||||
|     // A trait object looks like this: | ||||
| @@ -606,7 +614,7 @@ impl<'a> HeaderView<'a> { | ||||
|  | ||||
| impl<'a> fmt::Display for HeaderView<'a> { | ||||
|     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||
|         self.1.write_h1(&mut MultilineFormatter(Multi::Line(self.0.as_ref(), f))) | ||||
|         self.1.write_h1(&mut Formatter(Multi::Line(self.0.as_ref(), f))) | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -746,7 +754,13 @@ mod tests { | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||
|         fn fmt_header(&self, f: &mut super::Formatter) -> fmt::Result { | ||||
|             f.fmt_line(self) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     impl fmt::Display for CrazyLength { | ||||
|         fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||
|             let CrazyLength(ref opt, ref value) = *self; | ||||
|             write!(f, "{:?}, {:?}", opt, value) | ||||
|         } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user