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,26 +114,27 @@ 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)]
|
#[doc(hidden)]
|
||||||
pub trait GetType: Any {
|
pub trait GetType: Any {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@@ -143,6 +145,18 @@ pub trait GetType: Any {
|
|||||||
|
|
||||||
impl<T: Any> GetType for T {}
|
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]
|
#[test]
|
||||||
fn test_get_type() {
|
fn test_get_type() {
|
||||||
use ::header::{ContentLength, UserAgent};
|
use ::header::{ContentLength, UserAgent};
|
||||||
@@ -159,10 +173,12 @@ fn test_get_type() {
|
|||||||
assert_eq!(TypeId::of::<ContentLength>(), (*len).get_type());
|
assert_eq!(TypeId::of::<ContentLength>(), (*len).get_type());
|
||||||
assert_eq!(TypeId::of::<UserAgent>(), (*agent).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)]
|
#[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