Change trailers() to return Result<Option> instead of Option<Result>

This commit is contained in:
Sean McArthur
2019-08-20 16:20:49 -07:00
parent a1db5428db
commit b2af3d4b28
4 changed files with 18 additions and 39 deletions

View File

@@ -46,8 +46,8 @@ pub async fn main() -> Result<(), Box<dyn Error>> {
println!("GOT CHUNK = {:?}", chunk?); println!("GOT CHUNK = {:?}", chunk?);
} }
if let Some(trailers) = body.trailers().await { if let Some(trailers) = body.trailers().await? {
println!("GOT TRAILERS: {:?}", trailers?); println!("GOT TRAILERS: {:?}", trailers);
} }
Ok(()) Ok(())

View File

@@ -422,7 +422,7 @@ impl RecvStream {
} }
/// Get optional trailers for this stream. /// Get optional trailers for this stream.
pub async fn trailers(&mut self) -> Option<Result<HeaderMap, crate::Error>> { pub async fn trailers(&mut self) -> Result<Option<HeaderMap>, crate::Error> {
futures::future::poll_fn(move |cx| self.poll_trailers(cx)).await futures::future::poll_fn(move |cx| self.poll_trailers(cx)).await
} }
@@ -435,8 +435,12 @@ impl RecvStream {
pub fn poll_trailers( pub fn poll_trailers(
&mut self, &mut self,
cx: &mut Context, cx: &mut Context,
) -> Poll<Option<Result<HeaderMap, crate::Error>>> { ) -> Poll<Result<Option<HeaderMap>, crate::Error>> {
self.inner.inner.poll_trailers(cx).map_err_(Into::into) match ready!(self.inner.inner.poll_trailers(cx)) {
Some(Ok(map)) => Poll::Ready(Ok(Some(map))),
Some(Err(e)) => Poll::Ready(Err(e.into())),
None => Poll::Ready(Ok(None)),
}
} }
/// Returns the stream ID of this stream. /// Returns the stream ID of this stream.

View File

@@ -1,10 +1,7 @@
#![feature(async_await)] #![feature(async_await)]
use futures::{ready, FutureExt, StreamExt, TryFutureExt}; use futures::{FutureExt, StreamExt, TryFutureExt};
use h2_support::prelude::*; use h2_support::prelude::*;
use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};
use std::io; use std::io;
use std::{ use std::{
@@ -89,31 +86,6 @@ where
Ok(()) Ok(())
} }
struct Process {
body: RecvStream,
trailers: bool,
}
impl Future for Process {
type Output = Result<(), h2::Error>;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
loop {
if self.trailers {
ready!(self.body.poll_trailers(cx));
return Poll::Ready(Ok(()));
} else {
match ready!(Pin::new(&mut self.body).poll_next(cx)) {
None => {
self.trailers = true;
}
_ => {}
}
}
}
}
}
#[test] #[test]
fn hammer_client_concurrency() { fn hammer_client_concurrency() {
// This reproduces issue #326. // This reproduces issue #326.
@@ -150,11 +122,14 @@ fn hammer_client_concurrency() {
response response
.and_then(|response| { .and_then(|response| {
let (_, body) = response.into_parts(); let mut body = response.into_body();
Process { async move {
body, while let Some(res) = body.data().await {
trailers: false, res?;
}
body.trailers().await?;
Ok(())
} }
}) })
.map_err(|e| { .map_err(|e| {

View File

@@ -100,7 +100,7 @@ async fn send_trailers_immediately() {
let chunk = h2.run(body.next()).await; let chunk = h2.run(body.next()).await;
assert!(chunk.is_none()); assert!(chunk.is_none());
let trailers = h2.run(poll_fn(|cx| body.poll_trailers(cx))).await; let trailers = h2.run(poll_fn(|cx| body.poll_trailers(cx))).await.unwrap();
assert!(trailers.is_none()); assert!(trailers.is_none());
h2.await.unwrap(); h2.await.unwrap();