From 8e0655637e80c5377c01da4dbca6fb627e6d4225 Mon Sep 17 00:00:00 2001 From: Jonathan Reem Date: Thu, 2 Apr 2015 22:33:55 -0700 Subject: [PATCH] fix(headers): Add CowStr as a temporary hack to build on beta. We can revert this PR when rust-lang/rust#23995 lands, but it won't land until after beta is cut. --- src/header/mod.rs | 61 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 50 insertions(+), 11 deletions(-) diff --git a/src/header/mod.rs b/src/header/mod.rs index 9ab2807818..b6463d5a13 100644 --- a/src/header/mod.rs +++ b/src/header/mod.rs @@ -9,6 +9,7 @@ use std::borrow::{Cow, ToOwned}; use std::collections::HashMap; use std::collections::hash_map::{Iter, Entry}; use std::iter::{FromIterator, IntoIterator}; +use std::ops::{Deref, DerefMut}; use std::{mem, fmt}; use {httparse, traitobject}; @@ -26,7 +27,7 @@ mod internals; mod shared; pub mod parsing; -type HeaderName = UniCase>; +type HeaderName = UniCase; /// A trait for any object that will represent a header field and value. /// @@ -117,7 +118,7 @@ impl Headers { let mut headers = Headers::new(); for header in raw { debug!("raw header: {:?}={:?}", header.name, &header.value[..]); - let name = UniCase(Cow::Owned(header.name.to_owned())); + let name = UniCase(CowStr(Cow::Owned(header.name.to_owned()))); let mut item = match headers.data.entry(name) { Entry::Vacant(entry) => entry.insert(Item::new_raw(vec![])), Entry::Occupied(entry) => entry.into_mut() @@ -133,7 +134,7 @@ impl Headers { /// /// The field is determined by the type of the value being set. pub fn set(&mut self, value: H) { - self.data.insert(UniCase(Cow::Borrowed(header_name::())), + self.data.insert(UniCase(CowStr(Cow::Borrowed(header_name::()))), Item::new_typed(Box::new(value))); } @@ -150,7 +151,7 @@ impl Headers { /// ``` pub fn get_raw(&self, name: &str) -> Option<&[Vec]> { self.data - .get(&UniCase(Cow::Borrowed(unsafe { mem::transmute::<&str, &str>(name) }))) + .get(&UniCase(CowStr(Cow::Borrowed(unsafe { mem::transmute::<&str, &str>(name) })))) .map(Item::raw) } @@ -164,22 +165,24 @@ impl Headers { /// headers.set_raw("content-length", vec![b"5".to_vec()]); /// ``` pub fn set_raw>>(&mut self, name: K, value: Vec>) { - self.data.insert(UniCase(name.into()), Item::new_raw(value)); + self.data.insert(UniCase(CowStr(name.into())), Item::new_raw(value)); } /// Remove a header set by set_raw pub fn remove_raw(&mut self, name: &str) { - self.data.remove(&UniCase(Cow::Borrowed(name))); + self.data.remove( + &UniCase(CowStr(Cow::Borrowed(unsafe { mem::transmute::<&str, &str>(name) }))) + ); } /// Get a reference to the header field's value, if it exists. pub fn get(&self) -> Option<&H> { - self.data.get(&UniCase(Cow::Borrowed(header_name::()))).and_then(Item::typed::) + self.data.get(&UniCase(CowStr(Cow::Borrowed(header_name::())))).and_then(Item::typed::) } /// Get a mutable reference to the header field's value, if it exists. pub fn get_mut(&mut self) -> Option<&mut H> { - self.data.get_mut(&UniCase(Cow::Borrowed(header_name::()))).and_then(Item::typed_mut::) + self.data.get_mut(&UniCase(CowStr(Cow::Borrowed(header_name::())))).and_then(Item::typed_mut::) } /// Returns a boolean of whether a certain header is in the map. @@ -193,13 +196,13 @@ impl Headers { /// let has_type = headers.has::(); /// ``` pub fn has(&self) -> bool { - self.data.contains_key(&UniCase(Cow::Borrowed(header_name::()))) + self.data.contains_key(&UniCase(CowStr(Cow::Borrowed(header_name::())))) } /// Removes a header from the map, if one existed. /// Returns true if a header has been removed. pub fn remove(&mut self) -> bool { - self.data.remove(&UniCase(Cow::Borrowed(header_name::()))).is_some() + self.data.remove(&UniCase(CowStr(Cow::Borrowed(header_name::())))).is_some() } /// Returns an iterator over the header fields. @@ -263,7 +266,7 @@ impl<'a> HeaderView<'a> { /// Check if a HeaderView is a certain Header. #[inline] pub fn is(&self) -> bool { - UniCase(Cow::Borrowed(header_name::())) == *self.0 + UniCase(CowStr(Cow::Borrowed(header_name::()))) == *self.0 } /// Get the Header name as a slice. @@ -341,6 +344,42 @@ impl<'a, H: HeaderFormat> fmt::Debug for HeaderFormatter<'a, H> { } } +#[derive(Clone, Hash, Eq, PartialEq, PartialOrd, Ord)] +struct CowStr(Cow<'static, str>); + +impl Deref for CowStr { + type Target = Cow<'static, str>; + + fn deref(&self) -> &Cow<'static, str> { + &self.0 + } +} + +impl fmt::Debug for CowStr { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&self.0, fmt) + } +} + +impl fmt::Display for CowStr { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&self.0, fmt) + } +} + +impl DerefMut for CowStr { + fn deref_mut(&mut self) -> &mut Cow<'static, str> { + &mut self.0 + } +} + +impl AsRef for CowStr { + fn as_ref(&self) -> &str { + self + } +} + + #[cfg(test)] mod tests { use std::fmt;