diff --git a/src/header/common/access_control_allow_credentials.rs b/src/header/common/access_control_allow_credentials.rs index 2ea66660..8b442ea2 100644 --- a/src/header/common/access_control_allow_credentials.rs +++ b/src/header/common/access_control_allow_credentials.rs @@ -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") } } diff --git a/src/header/common/access_control_allow_origin.rs b/src/header/common/access_control_allow_origin.rs index 9b1518ac..c5f2a4a7 100644 --- a/src/header/common/access_control_allow_origin.rs +++ b/src/header/common/access_control_allow_origin.rs @@ -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), + } } } diff --git a/src/header/common/authorization.rs b/src/header/common/authorization.rs index fa222f48..7568e317 100644 --- a/src/header/common/authorization.rs +++ b/src/header/common/authorization.rs @@ -100,8 +100,8 @@ impl Header for Authorization where ::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) } } diff --git a/src/header/common/cache_control.rs b/src/header/common/cache_control.rs index 66982656..f6ae4eb5 100644 --- a/src/header/common/cache_control.rs +++ b/src/header/common/cache_control.rs @@ -49,6 +49,7 @@ pub struct CacheControl(pub Vec); __hyper__deref!(CacheControl => Vec); +//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) } } diff --git a/src/header/common/content_disposition.rs b/src/header/common/content_disposition.rs index 3d0bde44..243308e4 100644 --- a/src/header/common/content_disposition.rs +++ b/src/header/common/content_disposition.rs @@ -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) } } diff --git a/src/header/common/content_length.rs b/src/header/common/content_length.rs index bc023b50..3ff82990 100644 --- a/src/header/common/content_length.rs +++ b/src/header/common/content_length.rs @@ -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) } } diff --git a/src/header/common/cookie.rs b/src/header/common/cookie.rs index 057fdf3b..c3752454 100644 --- a/src/header/common/cookie.rs +++ b/src/header/common/cookie.rs @@ -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) } } diff --git a/src/header/common/expect.rs b/src/header/common/expect.rs index 5324e115..0d918dd5 100644 --- a/src/header/common/expect.rs +++ b/src/header/common/expect.rs @@ -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) } } diff --git a/src/header/common/host.rs b/src/header/common/host.rs index 94f8ed10..3a32b667 100644 --- a/src/header/common/host.rs +++ b/src/header/common/host.rs @@ -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) + } } } diff --git a/src/header/common/if_range.rs b/src/header/common/if_range.rs index 29ce248d..5380a6e5 100644 --- a/src/header/common/if_range.rs +++ b/src/header/common/if_range.rs @@ -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), + } } } diff --git a/src/header/common/link.rs b/src/header/common/link.rs index f13ac3ae..3b0e8d53 100644 --- a/src/header/common/link.rs +++ b/src/header/common/link.rs @@ -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(), ", ", ("", "")) } } diff --git a/src/header/common/mod.rs b/src/header/common/mod.rs index a16a834c..3e8c26a7 100644 --- a/src/header/common/mod.rs +++ b/src/header/common/mod.rs @@ -204,14 +204,13 @@ macro_rules! header { fn parse_header(raw: &$crate::header::Raw) -> $crate::Result { $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 { $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 { $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 { $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 diff --git a/src/header/common/origin.rs b/src/header/common/origin.rs index 44d3638f..bbc5b5d2 100644 --- a/src/header/common/origin.rs +++ b/src/header/common/origin.rs @@ -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) } } diff --git a/src/header/common/pragma.rs b/src/header/common/pragma.rs index 9c4fc094..8b1c9801 100644 --- a/src/header/common/pragma.rs +++ b/src/header/common/pragma.rs @@ -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) } } diff --git a/src/header/common/prefer.rs b/src/header/common/prefer.rs index c9a7e5da..29931038 100644 --- a/src/header/common/prefer.rs +++ b/src/header/common/prefer.rs @@ -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) } } diff --git a/src/header/common/preference_applied.rs b/src/header/common/preference_applied.rs index 7c0196fe..b7467e5c 100644 --- a/src/header/common/preference_applied.rs +++ b/src/header/common/preference_applied.rs @@ -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) } } diff --git a/src/header/common/range.rs b/src/header/common/range.rs index 3ad6c100..b5ef34ad 100644 --- a/src/header/common/range.rs +++ b/src/header/common/range.rs @@ -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) } } diff --git a/src/header/common/referrer_policy.rs b/src/header/common/referrer_policy.rs index fb549047..9950e4e9 100644 --- a/src/header/common/referrer_policy.rs +++ b/src/header/common/referrer_policy.rs @@ -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) } } diff --git a/src/header/common/retry_after.rs b/src/header/common/retry_after.rs index 23c4bf6c..1a827596 100644 --- a/src/header/common/retry_after.rs +++ b/src/header/common/retry_after.rs @@ -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()) diff --git a/src/header/common/set_cookie.rs b/src/header/common/set_cookie.rs index fc6ceff1..9293454d 100644 --- a/src/header/common/set_cookie.rs +++ b/src/header/common/set_cookie.rs @@ -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)); } diff --git a/src/header/common/strict_transport_security.rs b/src/header/common/strict_transport_security.rs index 0ff52b13..388b6ee2 100644 --- a/src/header/common/strict_transport_security.rs +++ b/src/header/common/strict_transport_security.rs @@ -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) } } diff --git a/src/header/common/warning.rs b/src/header/common/warning.rs index 8e9c94d1..451cf97e 100644 --- a/src/header/common/warning.rs +++ b/src/header/common/warning.rs @@ -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) diff --git a/src/header/internals/item.rs b/src/header/internals/item.rs index 74935bfd..0ceb1119 100644 --- a/src/header/internals/item.rs +++ b/src/header/internals/item.rs @@ -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) } } } diff --git a/src/header/mod.rs b/src/header/mod.rs index 74fcc479..cfbf390a 100644 --- a/src/header/mod.rs +++ b/src/header/mod.rs @@ -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,56 +114,71 @@ 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 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; +} + +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::() + } + } + + impl GetType for T {} + + #[doc(hidden)] + pub trait HeaderClone { + fn clone_box(&self) -> Box
; + } + + impl HeaderClone for T { + #[inline] + fn clone_box(&self) -> Box
{ + 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::(), len.get_type()); + assert_eq!(TypeId::of::(), agent.get_type()); + + let len: Box
= Box::new(len); + let agent: Box
= Box::new(agent); + + assert_eq!(TypeId::of::(), (*len).get_type()); + assert_eq!(TypeId::of::(), (*agent).get_type()); } } -#[doc(hidden)] -pub trait GetType: Any { - #[inline(always)] - fn get_type(&self) -> TypeId { - TypeId::of::() - } -} -impl GetType for T {} - -#[test] -fn test_get_type() { - use ::header::{ContentLength, UserAgent}; - - let len = ContentLength(5); - let agent = UserAgent::new("hyper"); - - assert_eq!(TypeId::of::(), len.get_type()); - assert_eq!(TypeId::of::(), agent.get_type()); - - let len: Box
= Box::new(len); - let agent: Box
= Box::new(agent); - - assert_eq!(TypeId::of::(), (*len).get_type()); - assert_eq!(TypeId::of::(), (*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
; -} - -impl HeaderClone for T { - #[inline] - fn clone_box(&self) -> Box
{ - 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) }