diff --git a/examples/hello.rs b/examples/hello.rs index c3a17173..221a9908 100644 --- a/examples/hello.rs +++ b/examples/hello.rs @@ -3,11 +3,8 @@ extern crate hyper; extern crate env_logger; extern crate num_cpus; -use std::io::Write; - -use hyper::{Decoder, Encoder, Next}; -use hyper::net::{HttpStream, HttpListener}; -use hyper::server::{Server, Handler, Request, Response}; +use hyper::{Decoder, Encoder, Next, HttpStream}; +use hyper::server::{Server, Handler, Request, Response, HttpListener}; static PHRASE: &'static [u8] = b"Hello World!"; diff --git a/examples/server.rs b/examples/server.rs index 7a0dd44f..e999b4dc 100644 --- a/examples/server.rs +++ b/examples/server.rs @@ -4,11 +4,8 @@ extern crate env_logger; #[macro_use] extern crate log; -use std::io::{self, Read, Write}; - -use hyper::{Get, Post, StatusCode, RequestUri, Decoder, Encoder, Next}; +use hyper::{Get, Post, StatusCode, RequestUri, Decoder, Encoder, HttpStream, Next}; use hyper::header::ContentLength; -use hyper::net::HttpStream; use hyper::server::{Server, Handler, Request, Response}; struct Echo { @@ -78,13 +75,13 @@ impl Handler for Echo { match self.route { Route::Echo(ref body) => { if self.read_pos < self.buf.len() { - match transport.read(&mut self.buf[self.read_pos..]) { - Ok(0) => { + match transport.try_read(&mut self.buf[self.read_pos..]) { + Ok(Some(0)) => { debug!("Read 0, eof"); self.eof = true; Next::write() }, - Ok(n) => { + Ok(Some(n)) => { self.read_pos += n; match *body { Body::Len(max) if max <= self.read_pos as u64 => { @@ -94,12 +91,10 @@ impl Handler for Echo { _ => Next::read_and_write() } } - Err(e) => match e.kind() { - io::ErrorKind::WouldBlock => Next::read_and_write(), - _ => { - println!("read error {:?}", e); - Next::end() - } + Ok(None) => Next::read_and_write(), + Err(e) => { + println!("read error {:?}", e); + Next::end() } } } else { @@ -137,18 +132,16 @@ impl Handler for Echo { } Route::Echo(..) => { if self.write_pos < self.read_pos { - match transport.write(&self.buf[self.write_pos..self.read_pos]) { - Ok(0) => panic!("write ZERO"), - Ok(n) => { + match transport.try_write(&self.buf[self.write_pos..self.read_pos]) { + Ok(Some(0)) => panic!("write ZERO"), + Ok(Some(n)) => { self.write_pos += n; Next::write() } - Err(e) => match e.kind() { - io::ErrorKind::WouldBlock => Next::write(), - _ => { - println!("write error {:?}", e); - Next::end() - } + Ok(None) => Next::write(), + Err(e) => { + println!("write error {:?}", e); + Next::end() } } } else if !self.eof { diff --git a/src/http/mod.rs b/src/http/mod.rs index 3d974e71..554833df 100644 --- a/src/http/mod.rs +++ b/src/http/mod.rs @@ -72,6 +72,31 @@ impl<'a, T: Read> Decoder<'a, T> { Decoder(DecoderImpl::H1(decoder, transport)) } + /// Read from the `Transport`. + #[inline] + pub fn read(&mut self, buf: &mut [u8]) -> io::Result { + match self.0 { + DecoderImpl::H1(ref mut decoder, ref mut transport) => { + decoder.decode(transport, buf) + } + } + } + + /// Try to read from the `Transport`. + /// + /// This method looks for the `WouldBlock` error. If the read did not block, + /// a return value would be `Ok(Some(x))`. If the read would block, + /// this method would return `Ok(None)`. + #[inline] + pub fn try_read(&mut self, buf: &mut [u8]) -> io::Result> { + match self.read(buf) { + Ok(n) => Ok(Some(n)), + Err(e) => match e.kind() { + io::ErrorKind::WouldBlock => Ok(None), + _ => Err(e) + } + } + } /// Get a reference to the transport. pub fn get_ref(&self) -> &T { @@ -86,9 +111,42 @@ impl<'a, T: Transport> Encoder<'a, T> { Encoder(EncoderImpl::H1(encoder, transport)) } + /// Write to the `Transport`. + #[inline] + pub fn write(&mut self, data: &[u8]) -> io::Result { + if data.is_empty() { + return Ok(0); + } + match self.0 { + EncoderImpl::H1(ref mut encoder, ref mut transport) => { + if encoder.is_closed() { + Ok(0) + } else { + encoder.encode(*transport, data) + } + } + } + } + + /// Try to write to the `Transport`. + /// + /// This method looks for the `WouldBlock` error. If the write did not block, + /// a return value would be `Ok(Some(x))`. If the write would block, + /// this method would return `Ok(None)`. + #[inline] + pub fn try_write(&mut self, data: &[u8]) -> io::Result> { + match self.write(data) { + Ok(n) => Ok(Some(n)), + Err(e) => match e.kind() { + io::ErrorKind::WouldBlock => Ok(None), + _ => Err(e) + } + } + } + /// Closes an encoder, signaling that no more writing will occur. /// - /// This is needed for encodings that don't know length of the content + /// This is needed for encodings that don't know the length of the content /// beforehand. Most common instance would be usage of /// `Transfer-Enciding: chunked`. You would call `close()` to signal /// the `Encoder` should write the end chunk, or `0\r\n\r\n`. @@ -109,29 +167,14 @@ impl<'a, T: Transport> Encoder<'a, T> { impl<'a, T: Read> Read for Decoder<'a, T> { #[inline] fn read(&mut self, buf: &mut [u8]) -> io::Result { - match self.0 { - DecoderImpl::H1(ref mut decoder, ref mut transport) => { - decoder.decode(transport, buf) - } - } + self.read(buf) } } impl<'a, T: Transport> Write for Encoder<'a, T> { #[inline] fn write(&mut self, data: &[u8]) -> io::Result { - if data.is_empty() { - return Ok(0); - } - match self.0 { - EncoderImpl::H1(ref mut encoder, ref mut transport) => { - if encoder.is_closed() { - Ok(0) - } else { - encoder.encode(*transport, data) - } - } - } + self.write(data) } #[inline]