diff --git a/src/client/response.rs b/src/client/response.rs index 830e49bf..2aaae0e9 100644 --- a/src/client/response.rs +++ b/src/client/response.rs @@ -95,9 +95,9 @@ impl Reader for Response { #[cfg(test)] mod tests { + use std::borrow::Borrowed; use std::boxed::BoxAny; use std::io::BufferedReader; - use std::str::Slice; use header::Headers; use http::HttpReader::EofReader; @@ -117,7 +117,7 @@ mod tests { headers: Headers::new(), version: version::HttpVersion::Http11, body: EofReader(BufferedReader::new(box MockStream::new() as Box)), - status_raw: RawStatus(200, Slice("OK")) + status_raw: RawStatus(200, Borrowed("OK")) }; let b = res.into_inner().downcast::().unwrap(); diff --git a/src/header/mod.rs b/src/header/mod.rs index 2ea88b2e..a42ec1cc 100644 --- a/src/header/mod.rs +++ b/src/header/mod.rs @@ -6,10 +6,11 @@ //! are already provided, such as `Host`, `ContentType`, `UserAgent`, and others. use std::any::Any; use std::ascii::{AsciiExt, AsciiCast}; +use std::borrow::{Borrowed, Owned}; use std::fmt::{mod, Show}; use std::intrinsics::TypeId; use std::raw::TraitObject; -use std::str::{SendStr, Slice, Owned}; +use std::str::SendStr; use std::collections::HashMap; use std::collections::hash_map::{Entries, Occupied, Vacant}; use std::sync::RWLock; @@ -95,7 +96,7 @@ fn header_name() -> &'static str { /// A map of header fields on requests and responses. #[deriving(Clone)] pub struct Headers { - data: HashMap, RWLock> + data: HashMap> } impl Headers { @@ -136,7 +137,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(CaseInsensitive(Slice(header_name::())), + self.data.insert(CaseInsensitive(Borrowed(header_name::())), RWLock::new(Item::typed(box value as Box))); } @@ -154,7 +155,7 @@ impl Headers { pub fn get_raw(&self, name: &str) -> Option<&[Vec]> { self.data // FIXME(reem): Find a better way to do this lookup without find_equiv. - .get(&CaseInsensitive(Slice(unsafe { mem::transmute::<&str, &str>(name) }))) + .get(&CaseInsensitive(Borrowed(unsafe { mem::transmute::<&str, &str>(name) }))) .and_then(|item| { let lock = item.read(); if let Some(ref raw) = lock.raw { @@ -177,8 +178,8 @@ impl Headers { /// # let mut headers = Headers::new(); /// headers.set_raw("content-length", vec!["5".as_bytes().to_vec()]); /// ``` - pub fn set_raw>(&mut self, name: K, value: Vec>) { - self.data.insert(CaseInsensitive(name.into_maybe_owned()), RWLock::new(Item::raw(value))); + pub fn set_raw>(&mut self, name: K, value: Vec>) { + self.data.insert(CaseInsensitive(name.into_cow()), RWLock::new(Item::raw(value))); } /// Get a reference to the header field's value, if it exists. @@ -200,7 +201,7 @@ impl Headers { } fn get_or_parse(&self) -> Option<&RWLock> { - self.data.get(&CaseInsensitive(Slice(header_name::()))).and_then(|item| get_or_parse::(item)) + self.data.get(&CaseInsensitive(Borrowed(header_name::()))).and_then(|item| get_or_parse::(item)) } /// Returns a boolean of whether a certain header is in the map. @@ -214,13 +215,13 @@ impl Headers { /// let has_type = headers.has::(); /// ``` pub fn has(&self) -> bool { - self.data.contains_key(&CaseInsensitive(Slice(header_name::()))) + self.data.contains_key(&CaseInsensitive(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(&CaseInsensitive(Slice(Header::header_name(None::)))).is_some() + self.data.remove(&CaseInsensitive(Borrowed(Header::header_name(None::)))).is_some() } /// Returns an iterator over the header fields. @@ -252,7 +253,7 @@ impl fmt::Show for Headers { /// An `Iterator` over the fields in a `Headers` map. pub struct HeadersItems<'a> { - inner: Entries<'a, CaseInsensitive, RWLock> + inner: Entries<'a, CaseInsensitive, RWLock> } impl<'a> Iterator> for HeadersItems<'a> { @@ -265,13 +266,13 @@ impl<'a> Iterator> for HeadersItems<'a> { } /// Returned with the `HeadersItems` iterator. -pub struct HeaderView<'a>(&'a CaseInsensitive, &'a RWLock); +pub struct HeaderView<'a>(&'a CaseInsensitive, &'a RWLock); impl<'a> HeaderView<'a> { /// Check if a HeaderView is a certain Header. #[inline] pub fn is(&self) -> bool { - CaseInsensitive(header_name::().into_maybe_owned()) == *self.0 + CaseInsensitive(header_name::().into_cow()) == *self.0 } /// Get the Header name as a slice. @@ -432,10 +433,16 @@ impl fmt::Show for Box { } } -#[deriving(Clone)] -struct CaseInsensitive(S); +//#[deriving(Clone)] +struct CaseInsensitive(SendStr); -impl Str for CaseInsensitive { +impl Clone for CaseInsensitive { + fn clone(&self) -> CaseInsensitive { + CaseInsensitive((*self.0).clone().into_cow()) + } +} + +impl Str for CaseInsensitive { fn as_slice(&self) -> &str { let CaseInsensitive(ref s) = *self; s.as_slice() @@ -443,29 +450,27 @@ impl Str for CaseInsensitive { } -impl fmt::Show for CaseInsensitive { +impl fmt::Show for CaseInsensitive { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { self.as_slice().fmt(fmt) } } -impl PartialEq for CaseInsensitive { - fn eq(&self, other: &CaseInsensitive) -> bool { +impl PartialEq for CaseInsensitive { + fn eq(&self, other: &CaseInsensitive) -> bool { self.as_slice().eq_ignore_ascii_case(other.as_slice()) } } -impl Eq for CaseInsensitive {} +impl Eq for CaseInsensitive {} -impl Equiv> for CaseInsensitive { - fn equiv(&self, other: &CaseInsensitive) -> bool { - let left = CaseInsensitive(self.as_slice()); - let right = CaseInsensitive(other.as_slice()); - left == right +impl Equiv for CaseInsensitive { + fn equiv(&self, other: &CaseInsensitive) -> bool { + self == other } } -impl hash::Hash for CaseInsensitive { +impl hash::Hash for CaseInsensitive { #[inline] fn hash(&self, hasher: &mut H) { for b in self.as_slice().bytes() { @@ -491,7 +496,7 @@ impl Show for HeaderFormatter { mod tests { use std::io::MemReader; use std::fmt; - use std::str::Slice; + use std::borrow::Borrowed; use std::hash::sip::hash; use mime::{Mime, Text, Plain}; use super::CaseInsensitive; @@ -506,8 +511,8 @@ mod tests { #[test] fn test_case_insensitive() { - let a = CaseInsensitive(Slice("foobar")); - let b = CaseInsensitive(Slice("FOOBAR")); + let a = CaseInsensitive(Borrowed("foobar")); + let b = CaseInsensitive(Borrowed("FOOBAR")); assert_eq!(a, b); assert_eq!(hash(&a), hash(&b)); diff --git a/src/http.rs b/src/http.rs index bfc22a5d..30313b40 100644 --- a/src/http.rs +++ b/src/http.rs @@ -1,9 +1,10 @@ //! Pieces pertaining to the HTTP message protocol. +use std::borrow::{Borrowed, Owned}; use std::cmp::min; use std::fmt; use std::io::{mod, Reader, IoResult, BufWriter}; use std::num::from_u16; -use std::str::{mod, SendStr, Slice, Owned}; +use std::str::{mod, SendStr}; use url::Url; @@ -559,9 +560,15 @@ pub fn read_request_line(stream: &mut R) -> HttpResult { pub type StatusLine = (HttpVersion, RawStatus); /// The raw status code and reason-phrase. -#[deriving(PartialEq, Show, Clone)] +#[deriving(PartialEq, Show)] pub struct RawStatus(pub u16, pub SendStr); +impl Clone for RawStatus { + fn clone(&self) -> RawStatus { + RawStatus(self.0, (*self.1).clone().into_cow()) + } +} + /// Read the StatusLine, such as `HTTP/1.1 200 OK`. /// /// > The first line of a response message is the status-line, consisting @@ -632,7 +639,7 @@ pub fn read_status(stream: &mut R) -> HttpResult { Some(status) => match status.canonical_reason() { Some(phrase) => { if phrase == reason { - Slice(phrase) + Borrowed(phrase) } else { Owned(reason.into_string()) } @@ -657,7 +664,7 @@ fn expect(r: IoResult, expected: u8) -> HttpResult<()> { #[cfg(test)] mod tests { use std::io::{mod, MemReader, MemWriter}; - use std::str::{Slice, Owned}; + use std::borrow::{Borrowed, Owned}; use test::Bencher; use uri::RequestUri; use uri::RequestUri::{Star, AbsoluteUri, AbsolutePath, Authority}; @@ -727,8 +734,8 @@ mod tests { assert_eq!(read_status(&mut mem(s)), result); } - read("200 OK\r\n", Ok(RawStatus(200, Slice("OK")))); - read("404 Not Found\r\n", Ok(RawStatus(404, Slice("Not Found")))); + read("200 OK\r\n", Ok(RawStatus(200, Borrowed("OK")))); + read("404 Not Found\r\n", Ok(RawStatus(404, Borrowed("Not Found")))); read("200 crazy pants\r\n", Ok(RawStatus(200, Owned("crazy pants".to_string())))); } @@ -774,7 +781,7 @@ mod tests { #[bench] fn bench_read_status(b: &mut Bencher) { b.bytes = b"404 Not Found\r\n".len() as u64; - b.iter(|| assert_eq!(read_status(&mut mem("404 Not Found\r\n")), Ok(RawStatus(404, Slice("Not Found"))))); + b.iter(|| assert_eq!(read_status(&mut mem("404 Not Found\r\n")), Ok(RawStatus(404, Borrowed("Not Found"))))); } }