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) |         Err(::Error::Header) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result { |     fn fmt_header(&self, f: &mut ::header::Formatter) -> fmt::Result { | ||||||
|         f.write_str("true") |         f.fmt_line(self) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| impl Display for AccessControlAllowCredentials { | impl Display for AccessControlAllowCredentials { | ||||||
|     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { |     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 { |     fn fmt_header(&self, f: &mut ::header::Formatter) -> fmt::Result { | ||||||
|         match *self { |         f.fmt_line(self) | ||||||
|             AccessControlAllowOrigin::Any => f.write_str("*"), |  | ||||||
|             AccessControlAllowOrigin::Null => f.write_str("null"), |  | ||||||
|             AccessControlAllowOrigin::Value(ref url) => Display::fmt(url, f), |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| impl Display for AccessControlAllowOrigin { | impl Display for AccessControlAllowOrigin { | ||||||
|     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { |     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 { |     fn fmt_header(&self, f: &mut ::header::Formatter) -> fmt::Result { | ||||||
|         fmt::Display::fmt(self, f) |         f.fmt_line(self) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -49,6 +49,7 @@ pub struct CacheControl(pub Vec<CacheDirective>); | |||||||
|  |  | ||||||
| __hyper__deref!(CacheControl => Vec<CacheDirective>); | __hyper__deref!(CacheControl => Vec<CacheDirective>); | ||||||
|  |  | ||||||
|  | //TODO: this could just be the header! macro | ||||||
| impl Header for CacheControl { | impl Header for CacheControl { | ||||||
|     fn header_name() -> &'static str { |     fn header_name() -> &'static str { | ||||||
|         static NAME: &'static str = "Cache-Control"; |         static NAME: &'static str = "Cache-Control"; | ||||||
| @@ -64,8 +65,8 @@ impl Header for CacheControl { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result { |     fn fmt_header(&self, f: &mut ::header::Formatter) -> fmt::Result { | ||||||
|         fmt::Display::fmt(self, f) |         f.fmt_line(self) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -146,8 +146,8 @@ impl Header for ContentDisposition { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     #[inline] |     #[inline] | ||||||
|     fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result { |     fn fmt_header(&self, f: &mut ::header::Formatter) -> fmt::Result { | ||||||
|         fmt::Display::fmt(&self, f) |         f.fmt_line(self) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -60,8 +60,8 @@ impl Header for ContentLength { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     #[inline] |     #[inline] | ||||||
|     fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result { |     fn fmt_header(&self, f: &mut ::header::Formatter) -> fmt::Result { | ||||||
|         fmt::Display::fmt(&self.0, f) |         f.fmt_line(self) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -54,8 +54,8 @@ impl Header for Cookie { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result { |     fn fmt_header(&self, f: &mut ::header::Formatter) -> fmt::Result { | ||||||
|         fmt::Display::fmt(self, f) |         f.fmt_line(self) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -54,8 +54,8 @@ impl Header for Expect { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result { |     fn fmt_header(&self, f: &mut ::header::Formatter) -> fmt::Result { | ||||||
|         fmt::Display::fmt(self, f) |         f.fmt_line(self) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -68,17 +68,17 @@ impl Header for Host { | |||||||
|        from_one_raw_str(raw) |        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 { | ||||||
|         match self.port { |         f.fmt_line(self) | ||||||
|             None | Some(80) | Some(443) => f.write_str(&self.hostname[..]), |  | ||||||
|             Some(port) => write!(f, "{}:{}", self.hostname, port) |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| impl fmt::Display for Host { | impl fmt::Display for Host { | ||||||
|     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |     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) |         Err(::Error::Header) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn fmt_header(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { |     fn fmt_header(&self, f: &mut ::header::Formatter) -> ::std::fmt::Result { | ||||||
|         match *self { |         f.fmt_line(self) | ||||||
|             IfRange::EntityTag(ref x) => Display::fmt(x, f), |  | ||||||
|             IfRange::Date(ref x) => Display::fmt(x, f), |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| impl Display for IfRange { | impl Display for IfRange { | ||||||
|     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |     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)) |             .unwrap_or(Err(::Error::Header)) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result { |     fn fmt_header(&self, f: &mut ::header::Formatter) -> fmt::Result { | ||||||
|         fmt_delimited(f, self.values.as_slice(), ", ", ("", "")) |         f.fmt_line(self) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| impl fmt::Display for Link { | impl fmt::Display for Link { | ||||||
|     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |     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> { |             fn parse_header(raw: &$crate::header::Raw) -> $crate::Result<Self> { | ||||||
|                 $crate::header::parsing::from_comma_delimited(raw).map($id) |                 $crate::header::parsing::from_comma_delimited(raw).map($id) | ||||||
|             } |             } | ||||||
|             fn fmt_header(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { |             fn fmt_header(&self, f: &mut $crate::header::Formatter) -> ::std::fmt::Result { | ||||||
|                 $crate::header::parsing::fmt_comma_delimited(f, &self.0[..]) |                 f.fmt_line(self) | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         impl ::std::fmt::Display for $id { |         impl ::std::fmt::Display for $id { | ||||||
|             fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { |             fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { | ||||||
|                 use $crate::header::Header; |                 $crate::header::parsing::fmt_comma_delimited(f, &self.0[..]) | ||||||
|                 self.fmt_header(f) |  | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     }; |     }; | ||||||
| @@ -229,14 +228,13 @@ macro_rules! header { | |||||||
|             fn parse_header(raw: &$crate::header::Raw) -> $crate::Result<Self> { |             fn parse_header(raw: &$crate::header::Raw) -> $crate::Result<Self> { | ||||||
|                 $crate::header::parsing::from_comma_delimited(raw).map($id) |                 $crate::header::parsing::from_comma_delimited(raw).map($id) | ||||||
|             } |             } | ||||||
|             fn fmt_header(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { |             fn fmt_header(&self, f: &mut $crate::header::Formatter) -> ::std::fmt::Result { | ||||||
|                 $crate::header::parsing::fmt_comma_delimited(f, &self.0[..]) |                 f.fmt_line(self) | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         impl ::std::fmt::Display for $id { |         impl ::std::fmt::Display for $id { | ||||||
|             fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { |             fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { | ||||||
|                 use $crate::header::Header; |                 $crate::header::parsing::fmt_comma_delimited(f, &self.0[..]) | ||||||
|                 self.fmt_header(f) |  | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     }; |     }; | ||||||
| @@ -254,8 +252,8 @@ macro_rules! header { | |||||||
|             fn parse_header(raw: &$crate::header::Raw) -> $crate::Result<Self> { |             fn parse_header(raw: &$crate::header::Raw) -> $crate::Result<Self> { | ||||||
|                 $crate::header::parsing::from_one_raw_str(raw).map($id) |                 $crate::header::parsing::from_one_raw_str(raw).map($id) | ||||||
|             } |             } | ||||||
|             fn fmt_header(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { |             fn fmt_header(&self, f: &mut $crate::header::Formatter) -> ::std::fmt::Result { | ||||||
|                 ::std::fmt::Display::fmt(&**self, f) |                 f.fmt_line(self) | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         impl ::std::fmt::Display for $id { |         impl ::std::fmt::Display for $id { | ||||||
| @@ -289,8 +287,8 @@ macro_rules! header { | |||||||
|             fn parse_header(raw: &$crate::header::Raw) -> $crate::Result<Self> { |             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) |                 $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 { |             fn fmt_header(&self, f: &mut $crate::header::Formatter) -> ::std::fmt::Result { | ||||||
|                 ::std::fmt::Display::fmt(&**self, f) |                 f.fmt_line(self) | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         impl ::std::fmt::Display for $id { |         impl ::std::fmt::Display for $id { | ||||||
| @@ -323,7 +321,12 @@ macro_rules! header { | |||||||
|                 } |                 } | ||||||
|                 $crate::header::parsing::from_comma_delimited(raw).map($id::Items) |                 $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 { |                 match *self { | ||||||
|                     $id::Any => f.write_str("*"), |                     $id::Any => f.write_str("*"), | ||||||
|                     $id::Items(ref fields) => $crate::header::parsing::fmt_comma_delimited( |                     $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 |     // optional test module | ||||||
|   | |||||||
| @@ -104,8 +104,8 @@ impl Header for Origin { | |||||||
|         from_one_raw_str(raw) |         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 { | ||||||
|         fmt::Display::fmt(self, f) |         f.fmt_line(self) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -54,8 +54,8 @@ impl Header for Pragma { | |||||||
|         }) |         }) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result { |     fn fmt_header(&self, f: &mut ::header::Formatter) -> fmt::Result { | ||||||
|         fmt::Display::fmt(self, f) |         f.fmt_line(self) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -65,8 +65,8 @@ impl Header for Prefer { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result { |     fn fmt_header(&self, f: &mut ::header::Formatter) -> fmt::Result { | ||||||
|         fmt::Display::fmt(self, f) |         f.fmt_line(self) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -63,8 +63,8 @@ impl Header for PreferenceApplied { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result { |     fn fmt_header(&self, f: &mut ::header::Formatter) -> fmt::Result { | ||||||
|         fmt::Display::fmt(self, f) |         f.fmt_line(self) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -190,8 +190,8 @@ impl Header for Range { | |||||||
|         from_one_raw_str(raw) |         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 { | ||||||
|         Display::fmt(self, f) |         f.fmt_line(self) | ||||||
|     } |     } | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -79,8 +79,8 @@ impl Header for ReferrerPolicy { | |||||||
|         Err(::Error::Header) |         Err(::Error::Header) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result { |     fn fmt_header(&self, f: &mut ::header::Formatter) -> fmt::Result { | ||||||
|         fmt::Display::fmt(self, f) |         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 { |         match *self { | ||||||
|             RetryAfter::Delay(ref duration) => { |             RetryAfter::Delay(ref duration) => { | ||||||
|                 write!(f, "{}", duration.num_seconds()) |                 write!(f, "{}", duration.num_seconds()) | ||||||
|   | |||||||
| @@ -91,16 +91,7 @@ impl Header for SetCookie { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result { |     fn fmt_header(&self, f: &mut ::header::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 { |  | ||||||
|         for cookie in &self.0 { |         for cookie in &self.0 { | ||||||
|             try!(f.fmt_line(cookie)); |             try!(f.fmt_line(cookie)); | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -129,8 +129,8 @@ impl Header for StrictTransportSecurity { | |||||||
|         parsing::from_one_raw_str(raw) |         parsing::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 { | ||||||
|         fmt::Display::fmt(self, f) |         f.fmt_line(self) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -96,7 +96,13 @@ impl Header for Warning { | |||||||
|         from_one_raw_str(raw) |         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 { |         match self.date { | ||||||
|             Some(date) => write!(f, "{:03} {} \"{}\" \"{}\"", self.code, self.agent, self.text, date), |             Some(date) => write!(f, "{:03} {} \"{}\" \"{}\"", self.code, self.agent, self.text, date), | ||||||
|             None => write!(f, "{:03} {} \"{}\"", self.code, self.agent, self.text) |             None => write!(f, "{:03} {} \"{}\"", self.code, self.agent, self.text) | ||||||
|   | |||||||
| @@ -4,7 +4,7 @@ use std::fmt; | |||||||
| use std::str::from_utf8; | use std::str::from_utf8; | ||||||
|  |  | ||||||
| use super::cell::{OptCell, PtrMapCell}; | use super::cell::{OptCell, PtrMapCell}; | ||||||
| use header::{Header, MultilineFormatter, Multi, raw, Raw}; | use header::{Header, Formatter, Multi, raw, Raw}; | ||||||
|  |  | ||||||
|  |  | ||||||
| #[derive(Clone)] | #[derive(Clone)] | ||||||
| @@ -47,7 +47,7 @@ impl Item { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         let mut raw = raw::new(); |         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.set(raw); | ||||||
|  |  | ||||||
|         self.raw.as_ref().unwrap() |         self.raw.as_ref().unwrap() | ||||||
| @@ -93,7 +93,7 @@ impl Item { | |||||||
|         }.map(|typed| unsafe { typed.downcast_unchecked() }) |         }.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 { |         match *self.raw { | ||||||
|             Some(ref raw) => { |             Some(ref raw) => { | ||||||
|                 for part in raw.iter() { |                 for part in raw.iter() { | ||||||
| @@ -111,7 +111,7 @@ impl Item { | |||||||
|             }, |             }, | ||||||
|             None => { |             None => { | ||||||
|                 let typed = unsafe { self.typed.one() }; |                 let typed = unsafe { self.typed.one() }; | ||||||
|                 typed.fmt_multi_header(f) |                 typed.fmt_header(f) | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -41,7 +41,7 @@ | |||||||
| //! | //! | ||||||
| //! ``` | //! ``` | ||||||
| //! use std::fmt; | //! use std::fmt; | ||||||
| //! use hyper::header::{Header, Raw}; | //! use hyper::header::{self, Header, Raw}; | ||||||
| //! | //! | ||||||
| //! #[derive(Debug, Clone, Copy)] | //! #[derive(Debug, Clone, Copy)] | ||||||
| //! struct Dnt(bool); | //! struct Dnt(bool); | ||||||
| @@ -66,16 +66,16 @@ | |||||||
| //!         Err(hyper::Error::Header) | //!         Err(hyper::Error::Header) | ||||||
| //!     } | //!     } | ||||||
| //! | //! | ||||||
| //!     fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result { | //!     fn fmt_header(&self, f: &mut header::Formatter) -> fmt::Result { | ||||||
| //!         if self.0 { | //!         let value = if self.0 { | ||||||
| //!             f.write_str("1") | //!             "1" | ||||||
| //!         } else { | //!         } else { | ||||||
| //!             f.write_str("0") | //!             "0" | ||||||
| //!         } | //!         }; | ||||||
|  | //!         f.fmt_line(&value) | ||||||
| //!     } | //!     } | ||||||
| //! } | //! } | ||||||
| //! ``` | //! ``` | ||||||
| use std::any::{Any, TypeId}; |  | ||||||
| use std::borrow::{Cow, ToOwned}; | use std::borrow::{Cow, ToOwned}; | ||||||
| use std::iter::{FromIterator, IntoIterator}; | use std::iter::{FromIterator, IntoIterator}; | ||||||
| use std::{mem, fmt}; | use std::{mem, fmt}; | ||||||
| @@ -83,6 +83,7 @@ use std::{mem, fmt}; | |||||||
| use unicase::UniCase; | use unicase::UniCase; | ||||||
|  |  | ||||||
| use self::internals::{Item, VecMap, Entry}; | use self::internals::{Item, VecMap, Entry}; | ||||||
|  | use self::sealed::{GetType, HeaderClone}; | ||||||
|  |  | ||||||
| pub use self::shared::*; | pub use self::shared::*; | ||||||
| pub use self::common::*; | pub use self::common::*; | ||||||
| @@ -100,7 +101,7 @@ pub mod parsing; | |||||||
| /// | /// | ||||||
| /// This trait represents the construction and identification of headers, | /// This trait represents the construction and identification of headers, | ||||||
| /// and contains trait-object unsafe methods. | /// 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. |     /// Returns the name of the header field this belongs to. | ||||||
|     /// |     /// | ||||||
|     /// This will become an associated constant once available. |     /// This will become an associated constant once available. | ||||||
| @@ -113,56 +114,71 @@ pub trait Header: HeaderClone + Any + GetType + Send + Sync { | |||||||
|     /// than one field value. If that's the case, you **should** return `None` |     /// than one field value. If that's the case, you **should** return `None` | ||||||
|     /// if `raw.len() > 1`. |     /// if `raw.len() > 1`. | ||||||
|     fn parse_header(raw: &Raw) -> ::Result<Self> where Self: Sized; |     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 |     /// Most headers should be formatted on one line, and so a common pattern | ||||||
|     /// by the passed-in Formatter. |     /// would be to implement `std::fmt::Display` for this type as well, and | ||||||
|     fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result; |     /// then just call `f.fmt_line(self)`. | ||||||
|     /// Formats a header over multiple lines. |     /// | ||||||
|  |     /// ## Note | ||||||
|  |     /// | ||||||
|  |     /// This has the ability to format a header over multiple lines. | ||||||
|     /// |     /// | ||||||
|     /// The main example here is `Set-Cookie`, which requires that every |     /// The main example here is `Set-Cookie`, which requires that every | ||||||
|     /// cookie being set be specified in a separate line. |     /// cookie being set be specified in a separate line. Almost every other | ||||||
|     /// |     /// case should only format as 1 single 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)] |  | ||||||
|     #[inline] |     #[inline] | ||||||
|     fn fmt_multi_header(&self, f: &mut MultilineFormatter) -> fmt::Result { |     fn fmt_header(&self, f: &mut Formatter) -> fmt::Result; | ||||||
|         f.fmt_line(&FmtHeader(self)) | } | ||||||
|  |  | ||||||
|  | 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 {} | ||||||
|  |  | ||||||
|  |     #[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); | ||||||
|  |         let agent = UserAgent::new("hyper"); | ||||||
|  |  | ||||||
|  |         assert_eq!(TypeId::of::<ContentLength>(), len.get_type()); | ||||||
|  |         assert_eq!(TypeId::of::<UserAgent>(), agent.get_type()); | ||||||
|  |  | ||||||
|  |         let len: Box<Header + Send + Sync> = Box::new(len); | ||||||
|  |         let agent: Box<Header + Send + Sync> = Box::new(agent); | ||||||
|  |  | ||||||
|  |         assert_eq!(TypeId::of::<ContentLength>(), (*len).get_type()); | ||||||
|  |         assert_eq!(TypeId::of::<UserAgent>(), (*agent).get_type()); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| #[doc(hidden)] |  | ||||||
| pub trait GetType: Any { |  | ||||||
|     #[inline(always)] |  | ||||||
|     fn get_type(&self) -> TypeId { |  | ||||||
|         TypeId::of::<Self>() |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| impl<T: Any> GetType for T {} | /// A formatter used to serialize headers to an output stream. | ||||||
|  |  | ||||||
| #[test] |  | ||||||
| fn test_get_type() { |  | ||||||
|     use ::header::{ContentLength, UserAgent}; |  | ||||||
|  |  | ||||||
|     let len = ContentLength(5); |  | ||||||
|     let agent = UserAgent::new("hyper"); |  | ||||||
|  |  | ||||||
|     assert_eq!(TypeId::of::<ContentLength>(), len.get_type()); |  | ||||||
|     assert_eq!(TypeId::of::<UserAgent>(), agent.get_type()); |  | ||||||
|  |  | ||||||
|     let len: Box<Header + Send + Sync> = Box::new(len); |  | ||||||
|     let agent: Box<Header + Send + Sync> = Box::new(agent); |  | ||||||
|  |  | ||||||
|     assert_eq!(TypeId::of::<ContentLength>(), (*len).get_type()); |  | ||||||
|     assert_eq!(TypeId::of::<UserAgent>(), (*agent).get_type()); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| #[doc(hidden)] |  | ||||||
| #[allow(missing_debug_implementations)] | #[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> { | enum Multi<'a, 'b: 'a> { | ||||||
|     Line(&'a str, &'a mut fmt::Formatter<'b>), |     Line(&'a str, &'a mut fmt::Formatter<'b>), | ||||||
| @@ -170,8 +186,20 @@ enum Multi<'a, 'b: 'a> { | |||||||
|     Raw(&'a mut Raw), |     Raw(&'a mut Raw), | ||||||
| } | } | ||||||
|  |  | ||||||
| impl<'a, 'b> MultilineFormatter<'a, 'b> { | impl<'a, 'b> Formatter<'a, 'b> { | ||||||
|     fn fmt_line(&mut self, line: &fmt::Display) -> fmt::Result { |  | ||||||
|  |     /// 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; |         use std::fmt::Write; | ||||||
|         match self.0 { |         match self.0 { | ||||||
|             Multi::Line(ref name, ref mut f) => { |             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); | struct ValueString<'a>(&'a Item); | ||||||
|  |  | ||||||
| impl<'a> fmt::Debug for ValueString<'a> { | impl<'a> fmt::Debug for ValueString<'a> { | ||||||
|     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||||
|         try!(f.write_str("\"")); |         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("\"") |         f.write_str("\"") | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| impl<'a> fmt::Display for ValueString<'a> { | impl<'a> fmt::Display for ValueString<'a> { | ||||||
|     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |     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] |     #[inline] | ||||||
|     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||||
|         try!(f.write_str("\"")); |         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("\"") |         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 { | impl Header + Send + Sync { | ||||||
|     // A trait object looks like this: |     // A trait object looks like this: | ||||||
| @@ -606,7 +614,7 @@ impl<'a> HeaderView<'a> { | |||||||
|  |  | ||||||
| impl<'a> fmt::Display for HeaderView<'a> { | impl<'a> fmt::Display for HeaderView<'a> { | ||||||
|     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |     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; |             let CrazyLength(ref opt, ref value) = *self; | ||||||
|             write!(f, "{:?}, {:?}", opt, value) |             write!(f, "{:?}, {:?}", opt, value) | ||||||
|         } |         } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user