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:
Sean McArthur
2016-11-17 17:31:42 -08:00
parent e23689122a
commit 2d2d5574a6
43 changed files with 2775 additions and 5033 deletions

77
src/http/chunk.rs Normal file
View File

@@ -0,0 +1,77 @@
use std::borrow::Borrow;
use std::fmt;
use std::sync::Arc;
/// A piece of a message body.
pub struct Chunk(Inner);
enum Inner {
Owned(Vec<u8>),
Referenced(Arc<Vec<u8>>),
Static(&'static [u8]),
}
impl From<Vec<u8>> for Chunk {
#[inline]
fn from(v: Vec<u8>) -> Chunk {
Chunk(Inner::Owned(v))
}
}
impl From<Arc<Vec<u8>>> for Chunk {
#[inline]
fn from(v: Arc<Vec<u8>>) -> Chunk {
Chunk(Inner::Referenced(v))
}
}
impl From<&'static [u8]> for Chunk {
#[inline]
fn from(slice: &'static [u8]) -> Chunk {
Chunk(Inner::Static(slice))
}
}
impl From<String> for Chunk {
#[inline]
fn from(s: String) -> Chunk {
s.into_bytes().into()
}
}
impl From<&'static str> for Chunk {
#[inline]
fn from(slice: &'static str) -> Chunk {
slice.as_bytes().into()
}
}
impl ::std::ops::Deref for Chunk {
type Target = [u8];
#[inline]
fn deref(&self) -> &Self::Target {
self.as_ref()
}
}
impl AsRef<[u8]> for Chunk {
#[inline]
fn as_ref(&self) -> &[u8] {
match self.0 {
Inner::Owned(ref vec) => vec,
Inner::Referenced(ref vec) => {
let v: &Vec<u8> = vec.borrow();
v.as_slice()
}
Inner::Static(slice) => slice,
}
}
}
impl fmt::Debug for Chunk {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(self.as_ref(), f)
}
}