From ed491655dd0872016ee61788295df2c48525c34b Mon Sep 17 00:00:00 2001 From: Jonathan Reem Date: Tue, 9 Sep 2014 16:51:32 -0700 Subject: [PATCH] Use dynamic dispatch for client Request and Response through Box Also adds a convenience `abstract` method to NetworkStream for creating Box from a NetworkStream. --- src/client/request.rs | 16 ++++++++-------- src/client/response.rs | 10 +++++----- src/net.rs | 16 ++++++++++++++++ src/server/request.rs | 2 +- src/server/response.rs | 2 +- 5 files changed, 31 insertions(+), 15 deletions(-) diff --git a/src/client/request.rs b/src/client/request.rs index cc5e53f2..c48e5196 100644 --- a/src/client/request.rs +++ b/src/client/request.rs @@ -14,7 +14,7 @@ use super::{Response}; /// A client request to a remote server. -pub struct Request { +pub struct Request { /// The method of this request. pub method: method::Method, /// The headers that will be sent with this request. @@ -24,13 +24,13 @@ pub struct Request { /// The HTTP version of this request. pub version: version::HttpVersion, headers_written: bool, - body: BufferedWriter, + body: BufferedWriter>, } -impl Request { +impl Request { /// Create a new client request. - pub fn new(method: method::Method, url: Url) -> HttpResult> { + pub fn new(method: method::Method, url: Url) -> HttpResult { debug!("{} {}", method, url); let host = match url.serialize_host() { Some(host) => host, @@ -43,8 +43,8 @@ impl Request { }; debug!("port={}", port); - let stream = try_io!(NetworkStream::connect(host.as_slice(), port)); - let stream = BufferedWriter::new(stream); + let stream: HttpStream = try_io!(NetworkStream::connect(host.as_slice(), port)); + let stream = BufferedWriter::new(stream.abstract()); let mut headers = Headers::new(); headers.set(Host(host)); Ok(Request { @@ -82,7 +82,7 @@ impl Request { /// Completes writing the request, and returns a response to read from. /// /// Consumes the Request. - pub fn send(mut self) -> HttpResult> { + pub fn send(mut self) -> HttpResult { try_io!(self.flush()); let raw = self.body.unwrap(); Response::new(raw) @@ -90,7 +90,7 @@ impl Request { } -impl Writer for Request { +impl Writer for Request { fn write(&mut self, msg: &[u8]) -> IoResult<()> { if !self.headers_written { try!(self.write_head()); diff --git a/src/client/response.rs b/src/client/response.rs index 2e6f5eed..ef05cf40 100644 --- a/src/client/response.rs +++ b/src/client/response.rs @@ -18,14 +18,14 @@ pub struct Response { pub headers: header::Headers, /// The HTTP version of this response from the server. pub version: version::HttpVersion, - body: HttpReader>, + body: HttpReader>>, } -impl Response { +impl Response { /// Creates a new response from a server. - pub fn new(stream: S) -> HttpResult> { - let mut stream = BufferedReader::new(stream); + pub fn new(stream: Box) -> HttpResult { + let mut stream = BufferedReader::new(stream.abstract()); let (version, status) = try!(read_status_line(&mut stream)); let mut headers = try!(header::Headers::from_raw(&mut stream)); @@ -67,7 +67,7 @@ impl Response { } } -impl Reader for Response { +impl Reader for Response { #[inline] fn read(&mut self, buf: &mut [u8]) -> IoResult { self.body.read(buf) diff --git a/src/net.rs b/src/net.rs index 943ba0a6..2a3f5796 100644 --- a/src/net.rs +++ b/src/net.rs @@ -28,6 +28,22 @@ pub trait NetworkStream: Stream + Clone + Send { /// Connect to a remote address. fn connect(host: &str, port: Port) -> IoResult; + + /// Turn this into an appropriately typed trait object. + #[inline] + fn abstract(self) -> Box { + box self as Box + } + + #[doc(hidden)] + #[inline] + // Hack to work around lack of Clone impl for Box + fn clone_box(&self) -> Box { self.clone().abstract() } +} + +impl Clone for Box { + #[inline] + fn clone(&self) -> Box { self.clone_box() } } impl Reader for Box { diff --git a/src/server/request.rs b/src/server/request.rs index 81570d67..89071afb 100644 --- a/src/server/request.rs +++ b/src/server/request.rs @@ -37,7 +37,7 @@ impl Request { /// immediately useful. pub fn new(mut stream: S) -> HttpResult { let remote_addr = try_io!(stream.peer_name()); - let mut stream = BufferedReader::new(box stream as Box); + let mut stream = BufferedReader::new(stream.abstract()); let (method, uri, version) = try!(read_request_line(&mut stream)); let mut headers = try!(Headers::from_raw(&mut stream)); diff --git a/src/server/response.rs b/src/server/response.rs index 165979fb..155138eb 100644 --- a/src/server/response.rs +++ b/src/server/response.rs @@ -66,7 +66,7 @@ impl Response { status: status::Ok, version: version::Http11, headers: header::Headers::new(), - body: BufferedWriter::new(box stream as Box) + body: BufferedWriter::new(stream.abstract()) } }