Merge pull request #329 from hyperium/324

Rustup
This commit is contained in:
Sean McArthur
2015-02-21 18:12:49 -05:00
32 changed files with 129 additions and 113 deletions

View File

@@ -1,4 +1,4 @@
#![feature(core, io, test)]
#![feature(core, old_io, test)]
extern crate hyper;
extern crate test;

View File

@@ -1,4 +1,4 @@
#![feature(collections, io, test)]
#![feature(collections, old_io, test)]
extern crate hyper;
extern crate test;

View File

@@ -1,4 +1,4 @@
#![feature(io, test)]
#![feature(old_io, test)]
extern crate hyper;
extern crate test;

View File

@@ -1,4 +1,4 @@
#![feature(env, io)]
#![feature(env, old_io)]
extern crate hyper;
use std::env;

View File

@@ -1,4 +1,4 @@
#![feature(io)]
#![feature(old_io)]
extern crate hyper;
use std::old_io::net::ip::Ipv4Addr;

View File

@@ -1,4 +1,4 @@
#![feature(io)]
#![feature(old_io)]
extern crate hyper;
#[macro_use] extern crate log;
@@ -21,7 +21,7 @@ macro_rules! try_return(
fn echo(mut req: Request, mut res: Response) {
match req.uri {
AbsolutePath(ref path) => match (&req.method, &path[]) {
AbsolutePath(ref path) => match (&req.method, &path[..]) {
(&Get, "/") | (&Get, "/echo") => {
let out = b"Try POST /echo";

View File

@@ -197,7 +197,7 @@ impl<'a, U: IntoUrl, C: NetworkConnector> RequestBuilder<'a, U, C> {
// punching borrowck here
let loc = match res.headers.get::<Location>() {
Some(&Location(ref loc)) => {
Some(UrlParser::new().base_url(&url).parse(&loc[]))
Some(UrlParser::new().base_url(&url).parse(&loc[..]))
}
None => {
debug!("no Location header");
@@ -394,7 +394,7 @@ mod tests {
#[test]
fn test_redirect_followif() {
fn follow_if(url: &Url) -> bool {
!url.serialize()[].contains("127.0.0.3")
!url.serialize().contains("127.0.0.3")
}
let mut client = Client::with_connector(MockRedirectPolicy);
client.set_redirect_policy(RedirectPolicy::FollowIf(follow_if));

View File

@@ -1,5 +1,6 @@
//! Client Requests
use std::old_io::{BufferedWriter, IoResult};
use std::marker::PhantomData;
use url::Url;
@@ -25,8 +26,13 @@ pub struct Request<W> {
body: HttpWriter<BufferedWriter<Box<NetworkStream + Send>>>,
headers: Headers,
method: method::Method,
_marker: PhantomData<W>,
}
//FIXME: remove once https://github.com/rust-lang/issues/22629 is fixed
unsafe impl<W> Send for Request<W> {}
impl<W> Request<W> {
/// Read the Request headers.
#[inline]
@@ -66,7 +72,8 @@ impl Request<Fresh> {
headers: headers,
url: url,
version: version::HttpVersion::Http11,
body: stream
body: stream,
_marker: PhantomData,
})
}
@@ -77,7 +84,7 @@ impl Request<Fresh> {
//TODO: this needs a test
if let Some(ref q) = self.url.query {
uri.push('?');
uri.push_str(&q[]);
uri.push_str(&q[..]);
}
debug!("writing head: {:?} {:?} {:?}", self.method, uri, self.version);
@@ -136,7 +143,8 @@ impl Request<Fresh> {
headers: self.headers,
url: self.url,
version: self.version,
body: stream
body: stream,
_marker: PhantomData,
})
}
@@ -185,7 +193,7 @@ mod tests {
let stream = *req.body.end().unwrap()
.into_inner().downcast::<MockStream>().ok().unwrap();
let bytes = stream.write.into_inner();
let s = from_utf8(&bytes[]).unwrap();
let s = from_utf8(&bytes[..]).unwrap();
assert!(!s.contains("Content-Length:"));
assert!(!s.contains("Transfer-Encoding:"));
}
@@ -199,7 +207,7 @@ mod tests {
let stream = *req.body.end().unwrap()
.into_inner().downcast::<MockStream>().ok().unwrap();
let bytes = stream.write.into_inner();
let s = from_utf8(&bytes[]).unwrap();
let s = from_utf8(&bytes[..]).unwrap();
assert!(!s.contains("Content-Length:"));
assert!(!s.contains("Transfer-Encoding:"));
}

View File

@@ -1,6 +1,7 @@
//! Client Responses
use std::num::FromPrimitive;
use std::old_io::{BufferedReader, IoResult};
use std::marker::PhantomData;
use header;
use header::{ContentLength, TransferEncoding};
@@ -23,8 +24,13 @@ pub struct Response<S = HttpStream> {
pub version: version::HttpVersion,
status_raw: RawStatus,
body: HttpReader<BufferedReader<Box<NetworkStream + Send>>>,
_marker: PhantomData<S>,
}
//FIXME: remove once https://github.com/rust-lang/issues/22629 is fixed
unsafe impl<S: Send> Send for Response<S> {}
impl Response {
/// Creates a new response from a server.
@@ -72,6 +78,7 @@ impl Response {
headers: headers,
body: body,
status_raw: raw_status,
_marker: PhantomData,
})
}
@@ -98,6 +105,7 @@ mod tests {
use std::borrow::Cow::Borrowed;
use std::boxed::BoxAny;
use std::old_io::BufferedReader;
use std::marker::PhantomData;
use header::Headers;
use header::TransferEncoding;
@@ -119,7 +127,8 @@ mod tests {
headers: Headers::new(),
version: version::HttpVersion::Http11,
body: EofReader(BufferedReader::new(box MockStream::new() as Box<NetworkStream + Send>)),
status_raw: RawStatus(200, Borrowed("OK"))
status_raw: RawStatus(200, Borrowed("OK")),
_marker: PhantomData,
};
let b = res.into_inner().downcast::<MockStream>().ok().unwrap();

View File

@@ -29,7 +29,7 @@ impl header::Header for AccessControlAllowOrigin {
fn parse_header(raw: &[Vec<u8>]) -> Option<AccessControlAllowOrigin> {
if raw.len() == 1 {
match str::from_utf8(unsafe { &raw[].get_unchecked(0)[] }) {
match str::from_utf8(unsafe { &raw.get_unchecked(0)[..] }) {
Ok(s) => {
if s == "*" {
Some(AccessControlAllowOrigin::AllowStar)

View File

@@ -22,14 +22,14 @@ impl<S: Scheme> DerefMut for Authorization<S> {
}
}
impl<S: Scheme> Header for Authorization<S> {
impl<S: Scheme + 'static> Header for Authorization<S> where <S as FromStr>::Err: 'static {
fn header_name() -> &'static str {
"Authorization"
}
fn parse_header(raw: &[Vec<u8>]) -> Option<Authorization<S>> {
if raw.len() == 1 {
match (from_utf8(unsafe { &raw[].get_unchecked(0)[] }), Scheme::scheme(None::<S>)) {
match (from_utf8(unsafe { &raw.get_unchecked(0)[..] }), Scheme::scheme(None::<S>)) {
(Ok(header), Some(scheme))
if header.starts_with(scheme) && header.len() > scheme.len() + 1 => {
header[scheme.len() + 1..].parse::<S>().map(|s| Authorization(s)).ok()
@@ -43,7 +43,7 @@ impl<S: Scheme> Header for Authorization<S> {
}
}
impl<S: Scheme> HeaderFormat for Authorization<S> {
impl<S: Scheme + 'static> HeaderFormat for Authorization<S> where <S as FromStr>::Err: 'static {
fn fmt_header(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match Scheme::scheme(None::<S>) {
Some(scheme) => try!(write!(fmt, "{} ", scheme)),
@@ -96,7 +96,7 @@ impl Scheme for Basic {
let mut text = self.username.clone();
text.push(':');
if let Some(ref pass) = self.password {
text.push_str(&pass[]);
text.push_str(&pass[..]);
}
write!(f, "{}", text.as_bytes().to_base64(Config {
char_set: Standard,
@@ -113,7 +113,7 @@ impl FromStr for Basic {
match s.from_base64() {
Ok(decoded) => match String::from_utf8(decoded) {
Ok(text) => {
let mut parts = &mut text[].split(':');
let mut parts = &mut text.split(':');
let user = match parts.next() {
Some(part) => part.to_string(),
None => return Err(())
@@ -160,7 +160,7 @@ mod tests {
#[test]
fn test_raw_auth_parse() {
let headers = Headers::from_raw(&mut mem("Authorization: foo bar baz\r\n\r\n")).unwrap();
assert_eq!(&headers.get::<Authorization<String>>().unwrap().0[], "foo bar baz");
assert_eq!(&headers.get::<Authorization<String>>().unwrap().0[..], "foo bar baz");
}
#[test]
@@ -181,7 +181,7 @@ mod tests {
fn test_basic_auth_parse() {
let headers = Headers::from_raw(&mut mem("Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==\r\n\r\n")).unwrap();
let auth = headers.get::<Authorization<Basic>>().unwrap();
assert_eq!(&auth.0.username[], "Aladdin");
assert_eq!(&auth.0.username[..], "Aladdin");
assert_eq!(auth.0.password, Some("open sesame".to_string()));
}

View File

@@ -16,7 +16,7 @@ impl Header for CacheControl {
fn parse_header(raw: &[Vec<u8>]) -> Option<CacheControl> {
let directives = raw.iter()
.filter_map(|line| from_one_comma_delimited(&line[]))
.filter_map(|line| from_one_comma_delimited(&line[..]))
.collect::<Vec<Vec<CacheDirective>>>()
.concat();
if directives.len() > 0 {
@@ -29,7 +29,7 @@ impl Header for CacheControl {
impl HeaderFormat for CacheControl {
fn fmt_header(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt_comma_delimited(fmt, &self[])
fmt_comma_delimited(fmt, &self[..])
}
}
@@ -88,7 +88,7 @@ impl fmt::Display for CacheDirective {
ProxyRevalidate => "proxy-revalidate",
SMaxAge(secs) => return write!(f, "s-maxage={}", secs),
Extension(ref name, None) => &name[],
Extension(ref name, None) => &name[..],
Extension(ref name, Some(ref arg)) => return write!(f, "{}={}", name, arg),
}, f)

View File

@@ -64,7 +64,7 @@ impl Header for Connection {
impl HeaderFormat for Connection {
fn fmt_header(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
let Connection(ref parts) = *self;
fmt_comma_delimited(fmt, &parts[])
fmt_comma_delimited(fmt, &parts[..])
}
}

View File

@@ -26,7 +26,7 @@ impl Header for Cookie {
fn parse_header(raw: &[Vec<u8>]) -> Option<Cookie> {
let mut cookies = Vec::with_capacity(raw.len());
for cookies_raw in raw.iter() {
match from_utf8(&cookies_raw[]) {
match from_utf8(&cookies_raw[..]) {
Ok(cookies_str) => {
for cookie_str in cookies_str.split(';') {
match cookie_str.trim().parse() {
@@ -82,7 +82,7 @@ impl Cookie {
#[test]
fn test_parse() {
let h = Header::parse_header(&[b"foo=bar; baz=quux".to_vec()][]);
let h = Header::parse_header(&[b"foo=bar; baz=quux".to_vec()][..]);
let c1 = CookiePair::new("foo".to_string(), "bar".to_string());
let c2 = CookiePair::new("baz".to_string(), "quux".to_string());
assert_eq!(h, Some(Cookie(vec![c1, c2])));
@@ -99,7 +99,7 @@ fn test_fmt() {
let mut headers = Headers::new();
headers.set(cookie_header);
assert_eq!(&headers.to_string()[], "Cookie: foo=bar; baz=quux\r\n");
assert_eq!(&headers.to_string()[..], "Cookie: foo=bar; baz=quux\r\n");
}
#[test]

View File

@@ -28,7 +28,7 @@ impl Header for Host {
// FIXME: use rust-url to parse this
// https://github.com/servo/rust-url/issues/42
let idx = {
let slice = &s[];
let slice = &s[..];
if slice.char_at(1) == '[' {
match slice.rfind(']') {
Some(idx) => {

View File

@@ -25,7 +25,7 @@ impl Header for IfMatch {
fn parse_header(raw: &[Vec<u8>]) -> Option<IfMatch> {
from_one_raw_str(raw).and_then(|s: String| {
let slice = &s[];
let slice = &s[..];
match slice {
"" => None,
"*" => Some(IfMatch::Any),
@@ -39,7 +39,7 @@ impl HeaderFormat for IfMatch {
fn fmt_header(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match *self {
IfMatch::Any => write!(fmt, "*"),
IfMatch::EntityTags(ref fields) => fmt_comma_delimited(fmt, &fields[])
IfMatch::EntityTags(ref fields) => fmt_comma_delimited(fmt, &fields[..])
}
}
}

View File

@@ -33,7 +33,7 @@ impl Header for IfNoneMatch {
fn parse_header(raw: &[Vec<u8>]) -> Option<IfNoneMatch> {
from_one_raw_str(raw).and_then(|s: String| {
let slice = &s[];
let slice = &s[..];
match slice {
"" => None,
"*" => Some(IfNoneMatch::Any),
@@ -47,7 +47,7 @@ impl HeaderFormat for IfNoneMatch {
fn fmt_header(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match *self {
IfNoneMatch::Any => { write!(fmt, "*") }
IfNoneMatch::EntityTags(ref fields) => { fmt_comma_delimited(fmt, &fields[]) }
IfNoneMatch::EntityTags(ref fields) => { fmt_comma_delimited(fmt, &fields[..]) }
}
}
}

View File

@@ -50,13 +50,13 @@ macro_rules! bench_header(
fn bench_parse(b: &mut Bencher) {
let val = $value;
b.iter(|| {
let _: $ty = Header::parse_header(&val[]).unwrap();
let _: $ty = Header::parse_header(&val[..]).unwrap();
});
}
#[bench]
fn bench_format(b: &mut Bencher) {
let val: $ty = Header::parse_header(&$value[]).unwrap();
let val: $ty = Header::parse_header(&$value[..]).unwrap();
let fmt = HeaderFormatter(&val);
b.iter(|| {
format!("{}", fmt);
@@ -102,7 +102,7 @@ macro_rules! impl_list_header(
impl $crate::header::HeaderFormat for $from {
fn fmt_header(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
$crate::header::parsing::fmt_comma_delimited(fmt, &self[])
$crate::header::parsing::fmt_comma_delimited(fmt, &self[..])
}
}

View File

@@ -31,7 +31,7 @@ impl Header for Pragma {
fn parse_header(raw: &[Vec<u8>]) -> Option<Pragma> {
parsing::from_one_raw_str(raw).and_then(|s: String| {
let slice = &s.to_ascii_lowercase()[];
let slice = &s.to_ascii_lowercase()[..];
match slice {
"" => None,
"no-cache" => Some(Pragma::NoCache),

View File

@@ -23,7 +23,7 @@ impl Header for SetCookie {
fn parse_header(raw: &[Vec<u8>]) -> Option<SetCookie> {
let mut set_cookies = Vec::with_capacity(raw.len());
for set_cookies_raw in raw.iter() {
match from_utf8(&set_cookies_raw[]) {
match from_utf8(&set_cookies_raw[..]) {
Ok(s) if !s.is_empty() => {
match s.parse() {
Ok(cookie) => set_cookies.push(cookie),
@@ -76,7 +76,7 @@ impl SetCookie {
#[test]
fn test_parse() {
let h = Header::parse_header(&[b"foo=bar; HttpOnly".to_vec()][]);
let h = Header::parse_header(&[b"foo=bar; HttpOnly".to_vec()][..]);
let mut c1 = Cookie::new("foo".to_string(), "bar".to_string());
c1.httponly = true;
@@ -94,7 +94,7 @@ fn test_fmt() {
let mut headers = Headers::new();
headers.set(cookies);
assert_eq!(&headers.to_string()[], "Set-Cookie: foo=bar; HttpOnly; Path=/p\r\nSet-Cookie: baz=quux; Path=/\r\n");
assert_eq!(&headers.to_string()[..], "Set-Cookie: foo=bar; HttpOnly; Path=/p\r\nSet-Cookie: baz=quux; Path=/\r\n");
}
#[test]

View File

@@ -55,7 +55,7 @@ impl Header for Upgrade {
impl HeaderFormat for Upgrade {
fn fmt_header(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
let Upgrade(ref parts) = *self;
fmt_comma_delimited(fmt, &parts[])
fmt_comma_delimited(fmt, &parts[..])
}
}

View File

@@ -21,7 +21,7 @@ impl Header for Vary {
fn parse_header(raw: &[Vec<u8>]) -> Option<Vary> {
from_one_raw_str(raw).and_then(|s: String| {
let slice = &s[];
let slice = &s[..];
match slice {
"" => None,
"*" => Some(Vary::Any),
@@ -35,7 +35,7 @@ impl HeaderFormat for Vary {
fn fmt_header(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match *self {
Vary::Any => { write!(fmt, "*") }
Vary::Headers(ref fields) => { fmt_comma_delimited(fmt, &fields[]) }
Vary::Headers(ref fields) => { fmt_comma_delimited(fmt, &fields[..]) }
}
}
}

View File

@@ -9,11 +9,10 @@ use std::borrow::Cow::{Borrowed, Owned};
use std::fmt;
use std::raw::TraitObject;
use std::str::from_utf8;
use std::string::CowString;
use std::collections::HashMap;
use std::collections::hash_map::{Iter, Entry};
use std::iter::FromIterator;
use std::borrow::IntoCow;
use std::iter::{FromIterator, IntoIterator};
use std::borrow::{Cow, IntoCow};
use std::{mem, raw};
use uany::{UnsafeAnyExt};
@@ -30,7 +29,7 @@ mod common;
mod shared;
pub mod parsing;
type HeaderName = UniCase<CowString<'static>>;
type HeaderName = UniCase<Cow<'static, str>>;
/// A trait for any object that will represent a header field and value.
///
@@ -139,7 +138,7 @@ impl Headers {
loop {
match try!(http::read_header(rdr)) {
Some((name, value)) => {
debug!("raw header: {:?}={:?}", name, &value[]);
debug!("raw header: {:?}={:?}", name, &value[..]);
count += (name.len() + value.len()) as u32;
if count > MAX_HEADERS_LENGTH {
debug!("Max header size reached, aborting");
@@ -183,14 +182,14 @@ impl Headers {
.get(&UniCase(Borrowed(unsafe { mem::transmute::<&str, &str>(name) })))
.and_then(|item| {
if let Some(ref raw) = *item.raw {
return Some(&raw[]);
return Some(&raw[..]);
}
let raw = vec![item.typed.as_ref().unwrap().to_string().into_bytes()];
item.raw.set(raw);
let raw = item.raw.as_ref().unwrap();
Some(&raw[])
Some(&raw[..])
})
}
@@ -203,7 +202,7 @@ impl Headers {
/// # let mut headers = Headers::new();
/// headers.set_raw("content-length", vec![b"5".to_vec()]);
/// ```
pub fn set_raw<K: IntoCow<'static, String, str>>(&mut self, name: K, value: Vec<Vec<u8>>) {
pub fn set_raw<K: IntoCow<'static, str>>(&mut self, name: K, value: Vec<Vec<u8>>) {
self.data.insert(UniCase(name.into_cow()), Item::new_raw(value));
}
@@ -351,7 +350,7 @@ impl<'a> fmt::Debug for HeaderView<'a> {
}
impl<'a> Extend<HeaderView<'a>> for Headers {
fn extend<I: Iterator<Item=HeaderView<'a>>>(&mut self, iter: I) {
fn extend<I: IntoIterator<Item=HeaderView<'a>>>(&mut self, iter: I) {
for header in iter {
self.data.insert((*header.0).clone(), (*header.1).clone());
}
@@ -359,7 +358,7 @@ impl<'a> Extend<HeaderView<'a>> for Headers {
}
impl<'a> FromIterator<HeaderView<'a>> for Headers {
fn from_iter<I: Iterator<Item=HeaderView<'a>>>(iter: I) -> Headers {
fn from_iter<I: IntoIterator<Item=HeaderView<'a>>>(iter: I) -> Headers {
let mut headers = Headers::new();
headers.extend(iter);
headers
@@ -451,7 +450,7 @@ fn get_or_parse_mut<H: Header + HeaderFormat>(item: &mut Item) -> Option<&mut It
fn parse<H: Header + HeaderFormat>(item: &Item) {
match *item.raw {
Some(ref raw) => match Header::parse_header(&raw[]) {
Some(ref raw) => match Header::parse_header(&raw[..]) {
Some::<H>(h) => item.typed.set(box h as Box<HeaderFormat + Send + Sync>),
None => ()
},
@@ -476,7 +475,7 @@ impl fmt::Display for Item {
None => match *self.raw {
Some(ref raw) => {
for part in raw.iter() {
match from_utf8(&part[]) {
match from_utf8(&part[..]) {
Ok(s) => try!(fmt.write_str(s)),
Err(e) => {
error!("raw header value is not utf8. header={:?}, error={:?}", part, e);
@@ -532,12 +531,9 @@ impl<'a, H: HeaderFormat> fmt::Debug for HeaderFormatter<'a, H> {
mod tests {
use std::old_io::MemReader;
use std::fmt;
use std::borrow::Cow::Borrowed;
use std::hash::{SipHasher, hash};
use mime::Mime;
use mime::TopLevel::Text;
use mime::SubLevel::Plain;
use unicase::UniCase;
use super::{Headers, Header, HeaderFormat, ContentLength, ContentType,
Accept, Host, QualityItem};
@@ -547,15 +543,6 @@ mod tests {
MemReader::new(s.as_bytes().to_vec())
}
#[test]
fn test_case_insensitive() {
let a = UniCase(Borrowed("foobar"));
let b = UniCase(Borrowed("FOOBAR"));
assert_eq!(a, b);
assert_eq!(hash::<_, SipHasher>(&a), hash::<_, SipHasher>(&b));
}
#[test]
fn test_from_raw() {
let headers = Headers::from_raw(&mut mem("Content-Length: 10\r\n\r\n")).unwrap();
@@ -595,7 +582,7 @@ mod tests {
return None;
}
// we JUST checked that raw.len() == 1, so raw[0] WILL exist.
match from_utf8(unsafe { &raw[].get_unchecked(0)[] }) {
match from_utf8(unsafe { &raw.get_unchecked(0)[..] }) {
Ok(s) => FromStr::from_str(s).ok(),
Err(_) => None
}.map(|u| CrazyLength(Some(false), u))
@@ -671,7 +658,7 @@ mod tests {
let mut headers = Headers::new();
headers.set(ContentLength(10));
headers.set_raw("content-LENGTH", vec![b"20".to_vec()]);
assert_eq!(headers.get_raw("Content-length").unwrap(), &[b"20".to_vec()][]);
assert_eq!(headers.get_raw("Content-length").unwrap(), &[b"20".to_vec()][..]);
assert_eq!(headers.get(), Some(&ContentLength(20)));
}

View File

@@ -11,7 +11,7 @@ pub fn from_one_raw_str<T: str::FromStr>(raw: &[Vec<u8>]) -> Option<T> {
return None;
}
// we JUST checked that raw.len() == 1, so raw[0] WILL exist.
match str::from_utf8(&raw[0][]) {
match str::from_utf8(&raw[0][..]) {
Ok(s) => str::FromStr::from_str(s).ok(),
Err(_) => None
}
@@ -24,7 +24,7 @@ pub fn from_comma_delimited<T: str::FromStr>(raw: &[Vec<u8>]) -> Option<Vec<T>>
return None;
}
// we JUST checked that raw.len() == 1, so raw[0] WILL exist.
from_one_comma_delimited(&raw[0][])
from_one_comma_delimited(&raw[0][..])
}
/// Reads a comma-delimited raw string into a Vec.

View File

@@ -42,7 +42,7 @@ impl FromStr for EntityTag {
type Err = ();
fn from_str(s: &str) -> Result<EntityTag, ()> {
let length: usize = s.len();
let slice = &s[];
let slice = &s[..];
// Early exits:
// 1. The string is empty, or,

View File

@@ -39,7 +39,7 @@ impl<T: fmt::Display> fmt::Display for QualityItem<T> {
write!(f, "{}", self.item)
} else {
write!(f, "{}; q={}", self.item,
format!("{:.3}", self.quality).trim_right_matches(&['0', '.'][]))
format!("{:.3}", self.quality).trim_right_matches(&['0', '.'][..]))
}
}
}

View File

@@ -1,11 +1,10 @@
//! Pieces pertaining to the HTTP message protocol.
use std::borrow::Cow::{Borrowed, Owned};
use std::borrow::Cow::{self, Borrowed, Owned};
use std::borrow::IntoCow;
use std::cmp::min;
use std::old_io::{self, Reader, IoResult, BufWriter};
use std::num::from_u16;
use std::str;
use std::string::CowString;
use url::Url;
use url::ParseError as UrlError;
@@ -395,7 +394,7 @@ pub fn read_method<R: Reader>(stream: &mut R) -> HttpResult<method::Method> {
debug!("maybe_method = {:?}", maybe_method);
match (maybe_method, &buf[]) {
match (maybe_method, &buf[..]) {
(Some(method), _) => Ok(method),
(None, ext) => {
// We already checked that the buffer is ASCII
@@ -587,7 +586,7 @@ pub type StatusLine = (HttpVersion, RawStatus);
/// The raw status code and reason-phrase.
#[derive(PartialEq, Debug)]
pub struct RawStatus(pub u16, pub CowString<'static>);
pub struct RawStatus(pub u16, pub Cow<'static, str>);
impl Clone for RawStatus {
fn clone(&self) -> RawStatus {
@@ -664,7 +663,7 @@ pub fn read_status<R: Reader>(stream: &mut R) -> HttpResult<RawStatus> {
}
}
let reason = match str::from_utf8(&buf[]) {
let reason = match str::from_utf8(&buf[..]) {
Ok(s) => s.trim(),
Err(_) => return Err(HttpStatusError)
};

View File

@@ -1,5 +1,5 @@
#![feature(core, collections, hash, io, os, path, std_misc,
slicing_syntax, box_syntax, unsafe_destructor)]
#![feature(core, collections, io, old_io, os, old_path,
std_misc, box_syntax, unsafe_destructor)]
#![deny(missing_docs)]
#![cfg_attr(test, deny(warnings))]
#![cfg_attr(test, feature(alloc, test))]

View File

@@ -58,7 +58,7 @@ pub trait NetworkAcceptor: Clone + Send {
}
/// An iterator wrapper over a NetworkAcceptor.
pub struct NetworkConnections<'a, N: NetworkAcceptor>(&'a mut N);
pub struct NetworkConnections<'a, N: NetworkAcceptor + 'a>(&'a mut N);
impl<'a, N: NetworkAcceptor> Iterator for NetworkConnections<'a, N> {
type Item = IoResult<N::Stream>;

View File

@@ -1,13 +1,13 @@
use std::thread::{Thread, JoinGuard};
use std::sync::Arc;
use std::thread::{self, JoinGuard};
use std::sync::mpsc;
use std::collections::VecMap;
use net::NetworkAcceptor;
pub struct AcceptorPool<A: NetworkAcceptor> {
acceptor: A
}
impl<A: NetworkAcceptor> AcceptorPool<A> {
impl<'a, A: NetworkAcceptor + 'a> AcceptorPool<A> {
/// Create a thread pool to manage the acceptor.
pub fn new(acceptor: A) -> AcceptorPool<A> {
AcceptorPool { acceptor: acceptor }
@@ -18,34 +18,39 @@ impl<A: NetworkAcceptor> AcceptorPool<A> {
/// ## Panics
///
/// Panics if threads == 0.
pub fn accept<F: Fn(A::Stream) + Send + Sync>(self,
work: F,
threads: usize) -> JoinGuard<'static, ()> {
pub fn accept<F>(self, work: F, threads: usize)
where F: Fn(A::Stream) + Send + Sync + 'a {
assert!(threads != 0, "Can't accept on 0 threads.");
// Replace with &F when Send changes land.
let work = Arc::new(work);
let (super_tx, supervisor_rx) = mpsc::channel();
let spawn =
move || spawn_with(super_tx.clone(), work.clone(), self.acceptor.clone());
let counter = &mut 0;
let work = &work;
let mut spawn = move || {
let id = *counter;
let guard = spawn_with(super_tx.clone(), work, self.acceptor.clone(), id);
*counter += 1;
(id, guard)
};
// Go
for _ in 0..threads { spawn() }
let mut guards: VecMap<_> = (0..threads).map(|_| spawn()).collect();
// Spawn the supervisor
Thread::scoped(move || for () in supervisor_rx.iter() { spawn() })
for id in supervisor_rx.iter() {
guards.remove(&id);
let (id, guard) = spawn();
guards.insert(id, guard);
}
}
}
fn spawn_with<A, F>(supervisor: mpsc::Sender<()>, work: Arc<F>, mut acceptor: A)
where A: NetworkAcceptor,
F: Fn(<A as NetworkAcceptor>::Stream) + Send + Sync {
fn spawn_with<'a, A, F>(supervisor: mpsc::Sender<usize>, work: &'a F, mut acceptor: A, id: usize) -> JoinGuard<'a, ()>
where A: NetworkAcceptor + 'a,
F: Fn(<A as NetworkAcceptor>::Stream) + Send + Sync + 'a {
use std::old_io::EndOfFile;
Thread::spawn(move || {
let sentinel = Sentinel::new(supervisor, ());
thread::scoped(move || {
let sentinel = Sentinel::new(supervisor, id);
loop {
match acceptor.accept() {
@@ -61,7 +66,7 @@ where A: NetworkAcceptor,
}
}
}
});
})
}
struct Sentinel<T: Send> {
@@ -83,7 +88,7 @@ impl<T: Send> Sentinel<T> {
}
#[unsafe_destructor]
impl<T: Send> Drop for Sentinel<T> {
impl<T: Send + 'static> Drop for Sentinel<T> {
fn drop(&mut self) {
// If we were cancelled, get out of here.
if !self.active { return; }

View File

@@ -2,7 +2,7 @@
use std::old_io::{Listener, BufferedReader, BufferedWriter};
use std::old_io::net::ip::{IpAddr, Port, SocketAddr};
use std::os;
use std::thread::JoinGuard;
use std::thread::{self, JoinGuard};
pub use self::request::Request;
pub use self::response::Response;
@@ -56,7 +56,7 @@ impl Server<HttpListener> {
impl<
L: NetworkListener<Acceptor=A> + Send,
A: NetworkAcceptor<Stream=S> + Send,
A: NetworkAcceptor<Stream=S> + Send + 'static,
S: NetworkStream + Clone + Send> Server<L> {
/// Creates a new server that will handle `HttpStream`s.
pub fn with_listener(ip: IpAddr, port: Port, listener: L) -> Server<L> {
@@ -68,7 +68,7 @@ S: NetworkStream + Clone + Send> Server<L> {
}
/// Binds to a socket, and starts handling connections using a task pool.
pub fn listen_threads<H: Handler>(mut self, handler: H, threads: usize) -> HttpResult<Listening<L::Acceptor>> {
pub fn listen_threads<H: Handler + 'static>(mut self, handler: H, threads: usize) -> HttpResult<Listening<L::Acceptor>> {
debug!("binding to {:?}:{:?}", self.ip, self.port);
let acceptor = try!(self.listener.listen((self.ip, self.port)));
let socket = try!(acceptor.socket_name());
@@ -77,15 +77,17 @@ S: NetworkStream + Clone + Send> Server<L> {
let pool = AcceptorPool::new(acceptor.clone());
let work = move |stream| handle_connection(stream, &handler);
let guard = thread::scoped(move || pool.accept(work, threads));
Ok(Listening {
_guard: pool.accept(work, threads),
_guard: guard,
socket: socket,
acceptor: acceptor
})
}
/// Binds to a socket and starts handling connections.
pub fn listen<H: Handler>(self, handler: H) -> HttpResult<Listening<L::Acceptor>> {
pub fn listen<H: Handler + 'static>(self, handler: H) -> HttpResult<Listening<L::Acceptor>> {
self.listen_threads(handler, os::num_cpus() * 5 / 4)
}

View File

@@ -3,6 +3,7 @@
//! These are responses sent by a `hyper::Server` to clients, after
//! receiving a request.
use std::old_io::IoResult;
use std::marker::PhantomData;
use time::now_utc;
@@ -22,7 +23,9 @@ pub struct Response<'a, W = Fresh> {
// The status code for the request.
status: status::StatusCode,
// The outgoing headers on this response.
headers: header::Headers
headers: header::Headers,
_marker: PhantomData<W>
}
impl<'a, W> Response<'a, W> {
@@ -42,7 +45,8 @@ impl<'a, W> Response<'a, W> {
status: status,
version: version,
body: body,
headers: headers
headers: headers,
_marker: PhantomData,
}
}
@@ -60,7 +64,8 @@ impl<'a> Response<'a, Fresh> {
status: status::StatusCode::Ok,
version: version::HttpVersion::Http11,
headers: header::Headers::new(),
body: ThroughWriter(stream)
body: ThroughWriter(stream),
_marker: PhantomData,
}
}
@@ -119,7 +124,8 @@ impl<'a> Response<'a, Fresh> {
version: self.version,
body: stream,
status: self.status,
headers: self.headers
headers: self.headers,
_marker: PhantomData,
})
}