Skip to content

Commit 789c223

Browse files
committed
refactor(body): separate body, payload, and chunk into their own internal mods
1 parent 52e1700 commit 789c223

File tree

5 files changed

+149
-139
lines changed

5 files changed

+149
-139
lines changed

src/body.rs renamed to src/body/body.rs

Lines changed: 3 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -1,127 +1,19 @@
1-
//! Streaming bodies for Requests and Responses
2-
//!
3-
//! For both [Clients](::client) and [Servers](::server), requests and
4-
//! responses use streaming bodies, instead of complete buffering. This
5-
//! allows applications to not use memory they don't need, and allows exerting
6-
//! back-pressure on connections by only reading when asked.
7-
//!
8-
//! There are two pieces to this in hyper:
9-
//!
10-
//! - The [`Payload`](Payload) trait the describes all possible bodies. hyper
11-
//! allows any body type that implements `Payload`, allowing applications to
12-
//! have fine-grained control over their streaming.
13-
//! - The [`Body`](Body) concrete type, which is an implementation of `Payload`,
14-
//! and returned by hyper as a "receive stream" (so, for server requests and
15-
//! client responses). It is also a decent default implementation if you don't
16-
//! have very custom needs of your send streams.
171
use std::borrow::Cow;
182
use std::fmt;
193

20-
use bytes::{Buf, Bytes};
4+
use bytes::Bytes;
215
use futures::{Async, Future, Poll, Stream};
226
use futures::sync::{mpsc, oneshot};
237
use h2;
248
use http::HeaderMap;
259

2610
use common::Never;
27-
pub use chunk::Chunk;
11+
use super::{Chunk, Payload};
12+
use super::internal::{FullDataArg, FullDataRet};
2813

29-
use self::internal::{FullDataArg, FullDataRet};
3014

3115
type BodySender = mpsc::Sender<Result<Chunk, ::Error>>;
3216

33-
34-
/// This trait represents a streaming body of a `Request` or `Response`.
35-
///
36-
/// The built-in implementation of this trait is [`Body`](Body), in case you
37-
/// don't need to customize a send stream for your own application.
38-
pub trait Payload: Send + 'static {
39-
/// A buffer of bytes representing a single chunk of a body.
40-
type Data: Buf + Send;
41-
42-
/// The error type of this stream.
43-
type Error: Into<Box<::std::error::Error + Send + Sync>>;
44-
45-
/// Poll for a `Data` buffer.
46-
///
47-
/// Similar to `Stream::poll_next`, this yields `Some(Data)` until
48-
/// the body ends, when it yields `None`.
49-
fn poll_data(&mut self) -> Poll<Option<Self::Data>, Self::Error>;
50-
51-
/// Poll for an optional **single** `HeaderMap` of trailers.
52-
///
53-
/// This should **only** be called after `poll_data` has ended.
54-
///
55-
/// Note: Trailers aren't currently used for HTTP/1, only for HTTP/2.
56-
fn poll_trailers(&mut self) -> Poll<Option<HeaderMap>, Self::Error> {
57-
Ok(Async::Ready(None))
58-
}
59-
60-
/// A hint that the `Body` is complete, and doesn't need to be polled more.
61-
///
62-
/// This can be useful to determine if the there is any body or trailers
63-
/// without having to poll. An empty `Body` could return `true` and hyper
64-
/// would be able to know that only the headers need to be sent. Or, it can
65-
/// also be checked after each `poll_data` call, to allow hyper to try to
66-
/// end the underlying stream with the last chunk, instead of needing to
67-
/// send an extra `DATA` frame just to mark the stream as finished.
68-
///
69-
/// As a hint, it is used to try to optimize, and thus is OK for a default
70-
/// implementation to return `false`.
71-
fn is_end_stream(&self) -> bool {
72-
false
73-
}
74-
75-
/// Return a length of the total bytes that will be streamed, if known.
76-
///
77-
/// If an exact size of bytes is known, this would allow hyper to send a
78-
/// `Content-Length` header automatically, not needing to fall back to
79-
/// `Transfer-Encoding: chunked`.
80-
///
81-
/// This does not need to be kept updated after polls, it will only be
82-
/// called once to create the headers.
83-
fn content_length(&self) -> Option<u64> {
84-
None
85-
}
86-
87-
// This API is unstable, and is impossible to use outside of hyper. Some
88-
// form of it may become stable in a later version.
89-
//
90-
// The only thing a user *could* do is reference the method, but DON'T
91-
// DO THAT! :)
92-
#[doc(hidden)]
93-
fn __hyper_full_data(&mut self, FullDataArg) -> FullDataRet<Self::Data> {
94-
FullDataRet(None)
95-
}
96-
}
97-
98-
impl<E: Payload> Payload for Box<E> {
99-
type Data = E::Data;
100-
type Error = E::Error;
101-
102-
fn poll_data(&mut self) -> Poll<Option<Self::Data>, Self::Error> {
103-
(**self).poll_data()
104-
}
105-
106-
fn poll_trailers(&mut self) -> Poll<Option<HeaderMap>, Self::Error> {
107-
(**self).poll_trailers()
108-
}
109-
110-
fn is_end_stream(&self) -> bool {
111-
(**self).is_end_stream()
112-
}
113-
114-
fn content_length(&self) -> Option<u64> {
115-
(**self).content_length()
116-
}
117-
118-
#[doc(hidden)]
119-
fn __hyper_full_data(&mut self, arg: FullDataArg) -> FullDataRet<Self::Data> {
120-
(**self).__hyper_full_data(arg)
121-
}
122-
}
123-
124-
12517
/// A stream of `Chunk`s, used when receiving bodies.
12618
///
12719
/// A good default `Payload` to use in many applications.
@@ -496,35 +388,8 @@ impl From<Cow<'static, str>> for Body {
496388
}
497389
}
498390

499-
// The full_data API is not stable, so these types are to try to prevent
500-
// users from being able to:
501-
//
502-
// - Implment `__hyper_full_data` on their own Payloads.
503-
// - Call `__hyper_full_data` on any Payload.
504-
//
505-
// That's because to implement it, they need to name these types, and
506-
// they can't because they aren't exported. And to call it, they would
507-
// need to create one of these values, which they also can't.
508-
pub(crate) mod internal {
509-
#[allow(missing_debug_implementations)]
510-
pub struct FullDataArg(pub(crate) ());
511-
#[allow(missing_debug_implementations)]
512-
pub struct FullDataRet<B>(pub(crate) Option<B>);
513-
}
514-
515-
fn _assert_send_sync() {
516-
fn _assert_send<T: Send>() {}
517-
fn _assert_sync<T: Sync>() {}
518-
519-
_assert_send::<Body>();
520-
_assert_send::<Chunk>();
521-
_assert_sync::<Chunk>();
522-
}
523-
524391
#[test]
525392
fn test_body_stream_concat() {
526-
use futures::{Stream, Future};
527-
528393
let body = Body::from("hello world");
529394

530395
let total = body
File renamed without changes.

src/body/mod.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
//! Streaming bodies for Requests and Responses
2+
//!
3+
//! For both [Clients](::client) and [Servers](::server), requests and
4+
//! responses use streaming bodies, instead of complete buffering. This
5+
//! allows applications to not use memory they don't need, and allows exerting
6+
//! back-pressure on connections by only reading when asked.
7+
//!
8+
//! There are two pieces to this in hyper:
9+
//!
10+
//! - The [`Payload`](Payload) trait the describes all possible bodies. hyper
11+
//! allows any body type that implements `Payload`, allowing applications to
12+
//! have fine-grained control over their streaming.
13+
//! - The [`Body`](Body) concrete type, which is an implementation of `Payload`,
14+
//! and returned by hyper as a "receive stream" (so, for server requests and
15+
//! client responses). It is also a decent default implementation if you don't
16+
//! have very custom needs of your send streams.
17+
pub use self::body::{Body, Sender};
18+
pub use self::chunk::Chunk;
19+
pub use self::payload::Payload;
20+
21+
mod body;
22+
mod chunk;
23+
mod payload;
24+
25+
// The full_data API is not stable, so these types are to try to prevent
26+
// users from being able to:
27+
//
28+
// - Implment `__hyper_full_data` on their own Payloads.
29+
// - Call `__hyper_full_data` on any Payload.
30+
//
31+
// That's because to implement it, they need to name these types, and
32+
// they can't because they aren't exported. And to call it, they would
33+
// need to create one of these values, which they also can't.
34+
pub(crate) mod internal {
35+
#[allow(missing_debug_implementations)]
36+
pub struct FullDataArg(pub(crate) ());
37+
#[allow(missing_debug_implementations)]
38+
pub struct FullDataRet<B>(pub(crate) Option<B>);
39+
}
40+
41+
fn _assert_send_sync() {
42+
fn _assert_send<T: Send>() {}
43+
fn _assert_sync<T: Sync>() {}
44+
45+
_assert_send::<Body>();
46+
_assert_send::<Chunk>();
47+
_assert_sync::<Chunk>();
48+
}
49+

src/body/payload.rs

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
use bytes::Buf;
2+
use futures::{Async, Poll};
3+
use http::HeaderMap;
4+
5+
use super::internal::{FullDataArg, FullDataRet};
6+
7+
/// This trait represents a streaming body of a `Request` or `Response`.
8+
///
9+
/// The built-in implementation of this trait is [`Body`](Body), in case you
10+
/// don't need to customize a send stream for your own application.
11+
pub trait Payload: Send + 'static {
12+
/// A buffer of bytes representing a single chunk of a body.
13+
type Data: Buf + Send;
14+
15+
/// The error type of this stream.
16+
type Error: Into<Box<::std::error::Error + Send + Sync>>;
17+
18+
/// Poll for a `Data` buffer.
19+
///
20+
/// Similar to `Stream::poll_next`, this yields `Some(Data)` until
21+
/// the body ends, when it yields `None`.
22+
fn poll_data(&mut self) -> Poll<Option<Self::Data>, Self::Error>;
23+
24+
/// Poll for an optional **single** `HeaderMap` of trailers.
25+
///
26+
/// This should **only** be called after `poll_data` has ended.
27+
///
28+
/// Note: Trailers aren't currently used for HTTP/1, only for HTTP/2.
29+
fn poll_trailers(&mut self) -> Poll<Option<HeaderMap>, Self::Error> {
30+
Ok(Async::Ready(None))
31+
}
32+
33+
/// A hint that the `Body` is complete, and doesn't need to be polled more.
34+
///
35+
/// This can be useful to determine if the there is any body or trailers
36+
/// without having to poll. An empty `Body` could return `true` and hyper
37+
/// would be able to know that only the headers need to be sent. Or, it can
38+
/// also be checked after each `poll_data` call, to allow hyper to try to
39+
/// end the underlying stream with the last chunk, instead of needing to
40+
/// send an extra `DATA` frame just to mark the stream as finished.
41+
///
42+
/// As a hint, it is used to try to optimize, and thus is OK for a default
43+
/// implementation to return `false`.
44+
fn is_end_stream(&self) -> bool {
45+
false
46+
}
47+
48+
/// Return a length of the total bytes that will be streamed, if known.
49+
///
50+
/// If an exact size of bytes is known, this would allow hyper to send a
51+
/// `Content-Length` header automatically, not needing to fall back to
52+
/// `Transfer-Encoding: chunked`.
53+
///
54+
/// This does not need to be kept updated after polls, it will only be
55+
/// called once to create the headers.
56+
fn content_length(&self) -> Option<u64> {
57+
None
58+
}
59+
60+
// This API is unstable, and is impossible to use outside of hyper. Some
61+
// form of it may become stable in a later version.
62+
//
63+
// The only thing a user *could* do is reference the method, but DON'T
64+
// DO THAT! :)
65+
#[doc(hidden)]
66+
fn __hyper_full_data(&mut self, FullDataArg) -> FullDataRet<Self::Data> {
67+
FullDataRet(None)
68+
}
69+
}
70+
71+
impl<E: Payload> Payload for Box<E> {
72+
type Data = E::Data;
73+
type Error = E::Error;
74+
75+
fn poll_data(&mut self) -> Poll<Option<Self::Data>, Self::Error> {
76+
(**self).poll_data()
77+
}
78+
79+
fn poll_trailers(&mut self) -> Poll<Option<HeaderMap>, Self::Error> {
80+
(**self).poll_trailers()
81+
}
82+
83+
fn is_end_stream(&self) -> bool {
84+
(**self).is_end_stream()
85+
}
86+
87+
fn content_length(&self) -> Option<u64> {
88+
(**self).content_length()
89+
}
90+
91+
#[doc(hidden)]
92+
fn __hyper_full_data(&mut self, arg: FullDataArg) -> FullDataRet<Self::Data> {
93+
(**self).__hyper_full_data(arg)
94+
}
95+
}
96+
97+

src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ mod common;
5757
#[cfg(test)]
5858
mod mock;
5959
pub mod body;
60-
mod chunk;
6160
pub mod client;
6261
pub mod error;
6362
mod headers;

0 commit comments

Comments
 (0)