chore(stability): remove into_cow feature gate

This commit is contained in:
Sean McArthur
2015-03-30 11:03:11 -07:00
parent 1b28515b6e
commit ccd4814e69
4 changed files with 29 additions and 108 deletions

View File

@@ -5,14 +5,12 @@
//! must implement the `Header` trait from this module. Several common headers //! must implement the `Header` trait from this module. Several common headers
//! are already provided, such as `Host`, `ContentType`, `UserAgent`, and others. //! are already provided, such as `Host`, `ContentType`, `UserAgent`, and others.
use std::any::Any; use std::any::Any;
use std::borrow::Cow::{Borrowed}; use std::borrow::{Cow, ToOwned};
use std::borrow::ToOwned;
use std::fmt; use std::fmt;
use std::raw::TraitObject;
use std::collections::HashMap; use std::collections::HashMap;
use std::collections::hash_map::{Iter, Entry}; use std::collections::hash_map::{Iter, Entry};
use std::iter::{FromIterator, IntoIterator}; use std::iter::{FromIterator, IntoIterator};
use std::borrow::{Cow, IntoCow}; use std::raw::TraitObject;
use std::{mem, raw}; use std::{mem, raw};
use httparse; use httparse;
@@ -120,7 +118,7 @@ impl Headers {
let mut headers = Headers::new(); let mut headers = Headers::new();
for header in raw { for header in raw {
debug!("raw header: {:?}={:?}", header.name, &header.value[..]); debug!("raw header: {:?}={:?}", header.name, &header.value[..]);
let name = UniCase(header.name.to_owned().into_cow()); let name = UniCase(Cow::Owned(header.name.to_owned()));
let mut item = match headers.data.entry(name) { let mut item = match headers.data.entry(name) {
Entry::Vacant(entry) => entry.insert(Item::new_raw(vec![])), Entry::Vacant(entry) => entry.insert(Item::new_raw(vec![])),
Entry::Occupied(entry) => entry.into_mut() Entry::Occupied(entry) => entry.into_mut()
@@ -136,7 +134,7 @@ impl Headers {
/// ///
/// 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 + HeaderFormat>(&mut self, value: H) { pub fn set<H: Header + HeaderFormat>(&mut self, value: H) {
self.data.insert(UniCase(Borrowed(header_name::<H>())), self.data.insert(UniCase(Cow::Borrowed(header_name::<H>())),
Item::new_typed(Box::new(value))); Item::new_typed(Box::new(value)));
} }
@@ -153,7 +151,7 @@ impl Headers {
/// ``` /// ```
pub fn get_raw(&self, name: &str) -> Option<&[Vec<u8>]> { pub fn get_raw(&self, name: &str) -> Option<&[Vec<u8>]> {
self.data self.data
.get(&UniCase(Borrowed(unsafe { mem::transmute::<&str, &str>(name) }))) .get(&UniCase(Cow::Borrowed(unsafe { mem::transmute::<&str, &str>(name) })))
.map(Item::raw) .map(Item::raw)
} }
@@ -166,23 +164,23 @@ impl Headers {
/// # let mut headers = Headers::new(); /// # let mut headers = Headers::new();
/// headers.set_raw("content-length", vec![b"5".to_vec()]); /// headers.set_raw("content-length", vec![b"5".to_vec()]);
/// ``` /// ```
pub fn set_raw<K: IntoCow<'static, str>>(&mut self, name: K, value: Vec<Vec<u8>>) { pub fn set_raw<K: Into<Cow<'static, str>>>(&mut self, name: K, value: Vec<Vec<u8>>) {
self.data.insert(UniCase(name.into_cow()), Item::new_raw(value)); self.data.insert(UniCase(name.into()), Item::new_raw(value));
} }
/// Remove a header set by set_raw /// Remove a header set by set_raw
pub fn remove_raw(&mut self, name: &str) { pub fn remove_raw(&mut self, name: &str) {
self.data.remove(&UniCase(name.into_cow())); self.data.remove(&UniCase(Cow::Borrowed(name)));
} }
/// 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<H: Header + HeaderFormat>(&self) -> Option<&H> { pub fn get<H: Header + HeaderFormat>(&self) -> Option<&H> {
self.data.get(&UniCase(Borrowed(header_name::<H>()))).and_then(Item::typed::<H>) self.data.get(&UniCase(Cow::Borrowed(header_name::<H>()))).and_then(Item::typed::<H>)
} }
/// Get a mutable reference to the header field's value, if it exists. /// Get a mutable reference to the header field's value, if it exists.
pub fn get_mut<H: Header + HeaderFormat>(&mut self) -> Option<&mut H> { pub fn get_mut<H: Header + HeaderFormat>(&mut self) -> Option<&mut H> {
self.data.get_mut(&UniCase(Borrowed(header_name::<H>()))).and_then(Item::typed_mut::<H>) self.data.get_mut(&UniCase(Cow::Borrowed(header_name::<H>()))).and_then(Item::typed_mut::<H>)
} }
/// Returns a boolean of whether a certain header is in the map. /// Returns a boolean of whether a certain header is in the map.
@@ -196,13 +194,13 @@ impl Headers {
/// let has_type = headers.has::<ContentType>(); /// let has_type = headers.has::<ContentType>();
/// ``` /// ```
pub fn has<H: Header + HeaderFormat>(&self) -> bool { pub fn has<H: Header + HeaderFormat>(&self) -> bool {
self.data.contains_key(&UniCase(Borrowed(header_name::<H>()))) self.data.contains_key(&UniCase(Cow::Borrowed(header_name::<H>())))
} }
/// Removes a header from the map, if one existed. /// Removes a header from the map, if one existed.
/// Returns true if a header has been removed. /// Returns true if a header has been removed.
pub fn remove<H: Header + HeaderFormat>(&mut self) -> bool { pub fn remove<H: Header + HeaderFormat>(&mut self) -> bool {
self.data.remove(&UniCase(Borrowed(header_name::<H>()))).is_some() self.data.remove(&UniCase(Cow::Borrowed(header_name::<H>()))).is_some()
} }
/// Returns an iterator over the header fields. /// Returns an iterator over the header fields.
@@ -266,7 +264,7 @@ impl<'a> HeaderView<'a> {
/// Check if a HeaderView is a certain Header. /// Check if a HeaderView is a certain Header.
#[inline] #[inline]
pub fn is<H: Header>(&self) -> bool { pub fn is<H: Header>(&self) -> bool {
UniCase(header_name::<H>().into_cow()) == *self.0 UniCase(Cow::Borrowed(header_name::<H>())) == *self.0
} }
/// Get the Header name as a slice. /// Get the Header name as a slice.

View File

@@ -1,13 +1,15 @@
//! Pieces pertaining to the HTTP message protocol. //! Pieces pertaining to the HTTP message protocol.
use std::borrow::{Cow, IntoCow, ToOwned}; use std::borrow::{Cow, ToOwned};
use std::cmp::min; use std::cmp::min;
use std::io::{self, Read, Write, BufRead}; use std::io::{self, Read, Write, BufRead};
use std::num::FromPrimitive;
use httparse; use httparse;
use buffer::BufReader; use buffer::BufReader;
use header::Headers; use header::Headers;
use method::Method; use method::Method;
use status::StatusCode;
use uri::RequestUri; use uri::RequestUri;
use version::HttpVersion::{self, Http10, Http11}; use version::HttpVersion::{self, Http10, Http11};
use HttpError:: HttpTooLargeError; use HttpError:: HttpTooLargeError;
@@ -375,11 +377,17 @@ impl<'a> TryParse for httparse::Response<'a> {
let mut res = httparse::Response::new(headers); let mut res = httparse::Response::new(headers);
Ok(match try!(res.parse(buf)) { Ok(match try!(res.parse(buf)) {
httparse::Status::Complete(len) => { httparse::Status::Complete(len) => {
let code = res.code.unwrap();
let reason = match <StatusCode as FromPrimitive>::from_u16(code) {
Some(status) => match status.canonical_reason() {
Some(reason) => Cow::Borrowed(reason),
None => Cow::Owned(res.reason.unwrap().to_owned())
},
None => Cow::Owned(res.reason.unwrap().to_owned())
};
httparse::Status::Complete((Incoming { httparse::Status::Complete((Incoming {
version: if res.version.unwrap() == 1 { Http11 } else { Http10 }, version: if res.version.unwrap() == 1 { Http11 } else { Http10 },
subject: RawStatus( subject: RawStatus(code, reason),
res.code.unwrap(), res.reason.unwrap().to_owned().into_cow()
),
headers: try!(Headers::from_raw(res.headers)) headers: try!(Headers::from_raw(res.headers))
}, len)) }, len))
}, },
@@ -405,15 +413,9 @@ pub const STAR: u8 = b'*';
pub const LINE_ENDING: &'static str = "\r\n"; pub const LINE_ENDING: &'static str = "\r\n";
/// The raw status code and reason-phrase. /// The raw status code and reason-phrase.
#[derive(PartialEq, Debug)] #[derive(Clone, PartialEq, Debug)]
pub struct RawStatus(pub u16, pub Cow<'static, str>); pub struct RawStatus(pub u16, pub Cow<'static, str>);
impl Clone for RawStatus {
fn clone(&self) -> RawStatus {
RawStatus(self.0, self.1.clone().into_cow())
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::io::{self, Write}; use std::io::{self, Write};

View File

@@ -1,5 +1,5 @@
#![doc(html_root_url = "https://hyperium.github.io/hyper/hyper/index.html")] #![doc(html_root_url = "https://hyperium.github.io/hyper/hyper/index.html")]
#![feature(core, into_cow)] #![feature(core)]
#![deny(missing_docs)] #![deny(missing_docs)]
#![cfg_attr(test, deny(warnings))] #![cfg_attr(test, deny(warnings))]
#![cfg_attr(test, feature(test))] #![cfg_attr(test, feature(test))]

View File

@@ -31,6 +31,7 @@ use std::cmp::Ordering;
/// Registry](http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml) which is /// Registry](http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml) which is
/// the source for this enum (with one exception, 418 I'm a teapot, which is /// the source for this enum (with one exception, 418 I'm a teapot, which is
/// inexplicably not in the register). /// inexplicably not in the register).
#[derive(Debug)]
pub enum StatusCode { pub enum StatusCode {
/// 100 Continue /// 100 Continue
/// [[RFC7231, Section 6.2.1](https://tools.ietf.org/html/rfc7231#section-6.2.1)] /// [[RFC7231, Section 6.2.1](https://tools.ietf.org/html/rfc7231#section-6.2.1)]
@@ -305,7 +306,7 @@ impl StatusCode {
StatusCode::NotExtended => Some("Not Extended"), StatusCode::NotExtended => Some("Not Extended"),
StatusCode::NetworkAuthenticationRequired => Some("Network Authentication Required"), StatusCode::NetworkAuthenticationRequired => Some("Network Authentication Required"),
_ => None StatusCode::Unregistered(..) => None
} }
} }
@@ -379,86 +380,6 @@ impl fmt::Display for StatusCode {
} }
} }
impl fmt::Debug for StatusCode {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let s = match *self {
StatusCode::Continue => "Continue",
StatusCode::SwitchingProtocols => "SwitchingProtocols",
StatusCode::Processing => "Processing",
StatusCode::Ok => "Ok",
StatusCode::Created => "Created",
StatusCode::Accepted => "Accepted",
StatusCode::NonAuthoritativeInformation => "NonAuthoritativeInformation",
StatusCode::NoContent => "NoContent",
StatusCode::ResetContent => "ResetContent",
StatusCode::PartialContent => "PartialContent",
StatusCode::MultiStatus => "MultiStatus",
StatusCode::AlreadyReported => "AlreadyReported",
StatusCode::ImUsed => "ImUsed",
StatusCode::MultipleChoices => "MultipleChoices",
StatusCode::MovedPermanently => "MovedPermanently",
StatusCode::Found => "Found",
StatusCode::SeeOther => "SeeOther",
StatusCode::NotModified => "NotModified",
StatusCode::UseProxy => "UseProxy",
StatusCode::TemporaryRedirect => "TemporaryRedirect",
StatusCode::PermanentRedirect => "PermanentRedirect",
StatusCode::BadRequest => "BadRequest",
StatusCode::Unauthorized => "Unauthorized",
StatusCode::PaymentRequired => "PaymentRequired",
StatusCode::Forbidden => "Forbidden",
StatusCode::NotFound => "NotFound",
StatusCode::MethodNotAllowed => "MethodNotAllowed",
StatusCode::NotAcceptable => "NotAcceptable",
StatusCode::ProxyAuthenticationRequired => "ProxyAuthenticationRequired",
StatusCode::RequestTimeout => "RequestTimeout",
StatusCode::Conflict => "Conflict",
StatusCode::Gone => "Gone",
StatusCode::LengthRequired => "LengthRequired",
StatusCode::PreconditionFailed => "PreconditionFailed",
StatusCode::PayloadTooLarge => "PayloadTooLarge",
StatusCode::UriTooLong => "UriTooLong",
StatusCode::UnsupportedMediaType => "UnsupportedMediaType",
StatusCode::RangeNotSatisfiable => "RangeNotSatisfiable",
StatusCode::ExpectationFailed => "ExpectationFailed",
StatusCode::ImATeapot => "ImATeapot",
StatusCode::UnprocessableEntity => "UnprocessableEntity",
StatusCode::Locked => "Locked",
StatusCode::FailedDependency => "FailedDependency",
StatusCode::UpgradeRequired => "UpgradeRequired",
StatusCode::PreconditionRequired => "PreconditionRequired",
StatusCode::TooManyRequests => "TooManyRequests",
StatusCode::RequestHeaderFieldsTooLarge => "RequestHeaderFieldsTooLarge",
StatusCode::InternalServerError => "InternalServerError",
StatusCode::NotImplemented => "NotImplemented",
StatusCode::BadGateway => "BadGateway",
StatusCode::ServiceUnavailable => "ServiceUnavailable",
StatusCode::GatewayTimeout => "GatewayTimeout",
StatusCode::HttpVersionNotSupported => "HttpVersionNotSupported",
StatusCode::VariantAlsoNegotiates => "VariantAlsoNegotiates",
StatusCode::InsufficientStorage => "InsufficientStorage",
StatusCode::LoopDetected => "LoopDetected",
StatusCode::NotExtended => "NotExtended",
StatusCode::NetworkAuthenticationRequired => "NetworkAuthenticationRequired",
StatusCode::Unregistered(ref code) => {
return write!(f, "Unregistered({})", code);
}
};
f.write_str(s)
}
}
impl PartialEq for StatusCode { impl PartialEq for StatusCode {
#[inline] #[inline]
fn eq(&self, other: &StatusCode) -> bool { fn eq(&self, other: &StatusCode) -> bool {