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:
@@ -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())))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user