add + 'static bounds to Header trait

This commit is contained in:
Sean McArthur
2014-09-03 11:12:04 -07:00
parent 592438b630
commit e2e93c5d5f

View File

@@ -27,8 +27,11 @@ use rfc7230::read_header;
use {HttpResult}; use {HttpResult};
/// A trait for any object that will represent a header field and value. /// A trait for any object that will represent a header field and value.
pub trait Header: Any { pub trait Header: Any + 'static {
/// Returns the name of the header field this belongs to. /// Returns the name of the header field this belongs to.
///
/// The market `Option` is to hint to the type system which implementation
/// to call. This can be done away with once UFCS arrives.
fn header_name(marker: Option<Self>) -> &'static str; fn header_name(marker: Option<Self>) -> &'static str;
/// Parse a header from a raw stream of bytes. /// Parse a header from a raw stream of bytes.
/// ///
@@ -106,7 +109,7 @@ impl Headers {
/// Set a header field to the corresponding value. /// Set a header field to the corresponding value.
/// ///
/// The field is determined by the type of the value being set. /// The field is determined by the type of the value being set.
pub fn set<H: Header + 'static>(&mut self, value: H) { pub fn set<H: Header>(&mut self, value: H) {
self.data.insert(header_name::<H>(), Typed(box value)); self.data.insert(header_name::<H>(), Typed(box value));
} }
@@ -119,12 +122,12 @@ impl Headers {
/// # let mut headers = Headers::new(); /// # let mut headers = Headers::new();
/// let content_type = headers.get::<ContentType>(); /// let content_type = headers.get::<ContentType>();
/// ``` /// ```
pub fn get<H: Header + Clone + 'static>(&mut self) -> Option<H> { pub fn get<H: Header + Clone>(&mut self) -> Option<H> {
self.get_ref().map(|v: &H| v.clone()) self.get_ref().map(|v: &H| v.clone())
} }
/// Get a reference to the header field's value, if it exists. /// Get a reference to the header field's value, if it exists.
pub fn get_ref<H: Header + 'static>(&mut self) -> Option<&H> { pub fn get_ref<H: Header>(&mut self) -> Option<&H> {
self.data.find_mut(&header_name::<H>()).and_then(|item| { self.data.find_mut(&header_name::<H>()).and_then(|item| {
debug!("get_ref, name={}, val={}", header_name::<H>(), item); debug!("get_ref, name={}, val={}", header_name::<H>(), item);
let header = match *item { let header = match *item {
@@ -136,7 +139,7 @@ impl Headers {
}, },
Typed(..) => return Some(item) Typed(..) => return Some(item)
}; };
*item = Typed(box header as Box<Header + 'static>); *item = Typed(box header as Box<Header>);
Some(item) Some(item)
}).and_then(|item| { }).and_then(|item| {
debug!("downcasting {}", item); debug!("downcasting {}", item);
@@ -162,7 +165,7 @@ impl Headers {
/// # let mut headers = Headers::new(); /// # let mut headers = Headers::new();
/// let has_type = headers.has::<ContentType>(); /// let has_type = headers.has::<ContentType>();
/// ``` /// ```
pub fn has<H: Header + 'static>(&self) -> bool { pub fn has<H: Header>(&self) -> bool {
self.data.contains_key(&header_name::<H>()) self.data.contains_key(&header_name::<H>())
} }
@@ -227,7 +230,7 @@ impl Mutable for Headers {
enum Item { enum Item {
Raw(Vec<Vec<u8>>), Raw(Vec<Vec<u8>>),
Typed(Box<Header + 'static>) Typed(Box<Header>)
} }
impl fmt::Show for Item { impl fmt::Show for Item {
@@ -498,6 +501,27 @@ impl Header for UserAgent {
} }
} }
/// The `Server` header field.
///
/// They can contain any value, so it just wraps a `String`.
#[deriving(Clone, PartialEq, Show)]
pub struct Server(pub String);
impl Header for Server {
fn header_name(_: Option<Server>) -> &'static str {
"server"
}
fn parse_header(raw: &[Vec<u8>]) -> Option<Server> {
from_one_raw_str(raw).map(|s| Server(s))
}
fn fmt_header(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
let Server(ref value) = *self;
value.fmt(fmt)
}
}
fn from_one_raw_str<T: FromStr>(raw: &[Vec<u8>]) -> Option<T> { fn from_one_raw_str<T: FromStr>(raw: &[Vec<u8>]) -> Option<T> {
if raw.len() != 1 { if raw.len() != 1 {
return None; return None;