feat(lib): redesign API to use Futures and Tokio
There are many changes involved with this, but let's just talk about
user-facing changes.
- Creating a `Client` and `Server` now needs a Tokio `Core` event loop
to attach to.
- `Request` and `Response` both no longer implement the
`std::io::{Read,Write}` traits, but instead represent their bodies as a
`futures::Stream` of items, where each item is a `Chunk`.
- The `Client.request` method now takes a `Request`, instead of being
used as a builder, and returns a `Future` that resolves to `Response`.
- The `Handler` trait for servers is no more, and instead the Tokio
`Service` trait is used. This allows interoperability with generic
middleware.
BREAKING CHANGE: A big sweeping set of breaking changes.
			
			
This commit is contained in:
		
							
								
								
									
										65
									
								
								src/mock.rs
									
									
									
									
									
								
							
							
						
						
									
										65
									
								
								src/mock.rs
									
									
									
									
									
								
							| @@ -1,6 +1,9 @@ | ||||
| use std::cmp; | ||||
| use std::io::{self, Read, Write}; | ||||
|  | ||||
| use futures::Async; | ||||
| use tokio::io::Io; | ||||
|  | ||||
| #[derive(Debug)] | ||||
| pub struct Buf { | ||||
|     vec: Vec<u8> | ||||
| @@ -8,8 +11,12 @@ pub struct Buf { | ||||
|  | ||||
| impl Buf { | ||||
|     pub fn new() -> Buf { | ||||
|         Buf::wrap(vec![]) | ||||
|     } | ||||
|  | ||||
|     pub fn wrap(vec: Vec<u8>) -> Buf { | ||||
|         Buf { | ||||
|             vec: vec![] | ||||
|             vec: vec, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -58,27 +65,41 @@ impl ::vecio::Writev for Buf { | ||||
| } | ||||
|  | ||||
| #[derive(Debug)] | ||||
| pub struct Async<T> { | ||||
| pub struct AsyncIo<T> { | ||||
|     inner: T, | ||||
|     bytes_until_block: usize, | ||||
|     error: Option<io::Error>, | ||||
| } | ||||
|  | ||||
| impl<T> Async<T> { | ||||
|     pub fn new(inner: T, bytes: usize) -> Async<T> { | ||||
|         Async { | ||||
| impl<T> AsyncIo<T> { | ||||
|     pub fn new(inner: T, bytes: usize) -> AsyncIo<T> { | ||||
|         AsyncIo { | ||||
|             inner: inner, | ||||
|             bytes_until_block: bytes | ||||
|             bytes_until_block: bytes, | ||||
|             error: None, | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     pub fn block_in(&mut self, bytes: usize) { | ||||
|         self.bytes_until_block = bytes; | ||||
|     } | ||||
|  | ||||
|     pub fn error(&mut self, err: io::Error) { | ||||
|         self.error = Some(err); | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl<T: Read> Read for Async<T> { | ||||
| impl AsyncIo<Buf> { | ||||
|     pub fn new_buf<T: Into<Vec<u8>>>(buf: T, bytes: usize) -> AsyncIo<Buf> { | ||||
|         AsyncIo::new(Buf::wrap(buf.into()), bytes) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl<T: Read> Read for AsyncIo<T> { | ||||
|     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { | ||||
|         if self.bytes_until_block == 0 { | ||||
|         if let Some(err) = self.error.take() { | ||||
|             Err(err) | ||||
|         } else if self.bytes_until_block == 0 { | ||||
|             Err(io::Error::new(io::ErrorKind::WouldBlock, "mock block")) | ||||
|         } else { | ||||
|             let n = cmp::min(self.bytes_until_block, buf.len()); | ||||
| @@ -89,9 +110,11 @@ impl<T: Read> Read for Async<T> { | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl<T: Write> Write for Async<T> { | ||||
| impl<T: Write> Write for AsyncIo<T> { | ||||
|     fn write(&mut self, data: &[u8]) -> io::Result<usize> { | ||||
|         if self.bytes_until_block == 0 { | ||||
|         if let Some(err) = self.error.take() { | ||||
|             Err(err) | ||||
|         } else if self.bytes_until_block == 0 { | ||||
|             Err(io::Error::new(io::ErrorKind::WouldBlock, "mock block")) | ||||
|         } else { | ||||
|             let n = cmp::min(self.bytes_until_block, data.len()); | ||||
| @@ -106,7 +129,25 @@ impl<T: Write> Write for Async<T> { | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl<T: Write> ::vecio::Writev for Async<T> { | ||||
| impl<T: Read + Write> Io for AsyncIo<T> { | ||||
|     fn poll_read(&mut self) -> Async<()> { | ||||
|         if self.bytes_until_block == 0 { | ||||
|             Async::NotReady | ||||
|         } else { | ||||
|             Async::Ready(()) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fn poll_write(&mut self) -> Async<()> { | ||||
|         if self.bytes_until_block == 0 { | ||||
|             Async::NotReady | ||||
|         } else { | ||||
|             Async::Ready(()) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl<T: Write> ::vecio::Writev for AsyncIo<T> { | ||||
|     fn writev(&mut self, bufs: &[&[u8]]) -> io::Result<usize> { | ||||
|         let cap = bufs.iter().map(|buf| buf.len()).fold(0, |total, next| total + next); | ||||
|         let mut vec = Vec::with_capacity(cap); | ||||
| @@ -118,7 +159,7 @@ impl<T: Write> ::vecio::Writev for Async<T> { | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl ::std::ops::Deref for Async<Buf> { | ||||
| impl ::std::ops::Deref for AsyncIo<Buf> { | ||||
|     type Target = [u8]; | ||||
|  | ||||
|     fn deref(&self) -> &[u8] { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user