perf(headers): skip newline replacer for safe headers

This commit is contained in:
Sean McArthur
2017-07-03 14:43:37 -07:00
parent d7edc19af2
commit 9bb71b9bbf
4 changed files with 64 additions and 2 deletions

View File

@@ -66,7 +66,7 @@ impl Header for ContentLength {
#[inline]
fn fmt_header(&self, f: &mut ::header::Formatter) -> fmt::Result {
f.fmt_line(self)
f.danger_fmt_line_without_newline_replacer(self)
}
}

View File

@@ -45,7 +45,7 @@ header! {
/// ContentType(mime::TEXT_HTML)
/// );
/// ```
(ContentType, "Content-Type") => [Mime]
(ContentType, "Content-Type") => danger [Mime]
test_content_type {
test_header!(

View File

@@ -275,6 +275,34 @@ macro_rules! header {
}
}
};
// Single value header (internal)
($(#[$a:meta])*($id:ident, $n:expr) => danger [$value:ty]) => {
$(#[$a])*
#[derive(Clone, Debug, PartialEq)]
pub struct $id(pub $value);
__hyper__deref!($id => $value);
impl $crate::header::Header for $id {
#[inline]
fn header_name() -> &'static str {
static NAME: &'static str = $n;
NAME
}
#[inline]
fn parse_header(raw: &$crate::header::Raw) -> $crate::Result<Self> {
$crate::header::parsing::from_one_raw_str(raw).map($id)
}
#[inline]
fn fmt_header(&self, f: &mut $crate::header::Formatter) -> ::std::fmt::Result {
f.danger_fmt_line_without_newline_replacer(self)
}
}
impl ::std::fmt::Display for $id {
#[inline]
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
::std::fmt::Display::fmt(&self.0, f)
}
}
};
// Single value cow header
($(#[$a:meta])*($id:ident, $n:expr) => Cow[$value:ty]) => {
$(#[$a])*
@@ -383,6 +411,14 @@ macro_rules! header {
__hyper__tm! { $id, $tm { $($tf)* }}
};
($(#[$a:meta])*($id:ident, $n:expr) => danger [$item:ty] $tm:ident{$($tf:item)*}) => {
header! {
$(#[$a])*
($id, $n) => danger [$item]
}
__hyper__tm! { $id, $tm { $($tf)* }}
};
($(#[$a:meta])*($id:ident, $n:expr) => Cow[$item:ty] $tm:ident{$($tf:item)*}) => {
header! {
$(#[$a])*

View File

@@ -224,6 +224,32 @@ impl<'a, 'b> Formatter<'a, 'b> {
}
}
}
fn danger_fmt_line_without_newline_replacer<T: fmt::Display>(&mut self, line: &T) -> fmt::Result {
use std::fmt::Write;
match self.0 {
Multi::Line(name, ref mut f) => {
try!(f.write_str(name));
try!(f.write_str(": "));
try!(fmt::Display::fmt(line, f));
f.write_str("\r\n")
},
Multi::Join(ref mut first, ref mut f) => {
if !*first {
try!(f.write_str(", "));
} else {
*first = false;
}
fmt::Display::fmt(line, f)
}
Multi::Raw(ref mut raw) => {
let mut s = String::new();
try!(write!(s, "{}", line));
raw.push(s);
Ok(())
}
}
}
}
struct ValueString<'a>(&'a Item);