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,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<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;
|
||||
}
|
||||
|
||||
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 {}
|
||||
|
||||
#[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)]
|
||||
/// 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