refactor all to async/await (#617)

Co-authored-by: Danny Browning <danny.browning@protectwise.com>
Co-authored-by: Daniel Eades <danieleades@hotmail.com>
This commit is contained in:
Sean McArthur
2019-09-06 17:22:56 -07:00
committed by GitHub
parent d7fcd8ac2e
commit ba7b2a754e
30 changed files with 1106 additions and 1430 deletions

View File

@@ -3,10 +3,11 @@ use std::fmt;
use std::marker::PhantomData;
use std::mem;
use std::net::SocketAddr;
use std::pin::Pin;
use std::task::{Context, Poll};
use encoding_rs::{Encoding, UTF_8};
use futures::stream::Concat2;
use futures::{try_ready, Async, Future, Poll, Stream};
use futures::{Future, FutureExt, TryStreamExt};
use http;
use hyper::client::connect::HttpInfo;
use hyper::header::CONTENT_LENGTH;
@@ -20,8 +21,12 @@ use url::Url;
use super::body::Body;
use super::Decoder;
use crate::async_impl::Chunk;
use crate::cookie;
/// https://github.com/rust-lang-nursery/futures-rs/issues/1812
type ConcatDecoder = Pin<Box<dyn Future<Output = Result<Chunk, crate::Error>> + Send>>;
/// A Response to a submitted `Request`.
pub struct Response {
status: StatusCode,
@@ -139,7 +144,7 @@ impl Response {
}
/// Get the response text
pub fn text(&mut self) -> impl Future<Item = String, Error = crate::Error> {
pub fn text(&mut self) -> impl Future<Output = Result<String, crate::Error>> {
self.text_with_charset("utf-8")
}
@@ -147,7 +152,7 @@ impl Response {
pub fn text_with_charset(
&mut self,
default_encoding: &str,
) -> impl Future<Item = String, Error = crate::Error> {
) -> impl Future<Output = Result<String, crate::Error>> {
let body = mem::replace(&mut self.body, Decoder::empty());
let content_type = self
.headers
@@ -160,18 +165,18 @@ impl Response {
.unwrap_or(default_encoding);
let encoding = Encoding::for_label(encoding_name.as_bytes()).unwrap_or(UTF_8);
Text {
concat: body.concat2(),
concat: body.try_concat().boxed(),
encoding,
}
}
/// Try to deserialize the response body as JSON using `serde`.
#[inline]
pub fn json<T: DeserializeOwned>(&mut self) -> impl Future<Item = T, Error = crate::Error> {
pub fn json<T: DeserializeOwned>(&mut self) -> impl Future<Output = Result<T, crate::Error>> {
let body = mem::replace(&mut self.body, Decoder::empty());
Json {
concat: body.concat2(),
concat: body.try_concat().boxed(),
_marker: PhantomData,
}
}
@@ -270,17 +275,27 @@ impl<T: Into<Body>> From<http::Response<T>> for Response {
/// A JSON object.
struct Json<T> {
concat: Concat2<Decoder>,
concat: ConcatDecoder,
_marker: PhantomData<T>,
}
impl<T> Json<T> {
fn concat(self: Pin<&mut Self>) -> Pin<&mut ConcatDecoder> {
unsafe { Pin::map_unchecked_mut(self, |x| &mut x.concat) }
}
}
impl<T: DeserializeOwned> Future for Json<T> {
type Item = T;
type Error = crate::Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
let bytes = try_ready!(self.concat.poll());
let t = try_!(serde_json::from_slice(&bytes));
Ok(Async::Ready(t))
type Output = Result<T, crate::Error>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
match futures::ready!(self.concat().as_mut().poll(cx)) {
Err(e) => Poll::Ready(Err(e)),
Ok(chunk) => {
let t = serde_json::from_slice(&chunk).map_err(crate::error::from);
Poll::Ready(t)
}
}
}
}
@@ -290,29 +305,36 @@ impl<T> fmt::Debug for Json<T> {
}
}
#[derive(Debug)]
//#[derive(Debug)]
struct Text {
concat: Concat2<Decoder>,
concat: ConcatDecoder,
encoding: &'static Encoding,
}
impl Text {
fn concat(self: Pin<&mut Self>) -> Pin<&mut ConcatDecoder> {
unsafe { Pin::map_unchecked_mut(self, |x| &mut x.concat) }
}
}
impl Future for Text {
type Item = String;
type Error = crate::Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
let bytes = try_ready!(self.concat.poll());
// a block because of borrow checker
{
let (text, _, _) = self.encoding.decode(&bytes);
if let Cow::Owned(s) = text {
return Ok(Async::Ready(s));
type Output = Result<String, crate::Error>;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
match futures::ready!(self.as_mut().concat().as_mut().poll(cx)) {
Err(e) => Poll::Ready(Err(e)),
Ok(chunk) => {
let (text, _, _) = self.as_mut().encoding.decode(&chunk);
if let Cow::Owned(s) = text {
return Poll::Ready(Ok(s));
}
unsafe {
// decoding returned Cow::Borrowed, meaning these bytes
// are already valid utf8
Poll::Ready(Ok(String::from_utf8_unchecked(chunk.to_vec())))
}
}
}
unsafe {
// decoding returned Cow::Borrowed, meaning these bytes
// are already valid utf8
Ok(Async::Ready(String::from_utf8_unchecked(bytes.to_vec())))
}
}
}