Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make Full and Empty generic over the error type #85

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion http-body-util/src/collected.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ mod tests {

#[tokio::test]
async fn full_body() {
let body = Full::new(&b"hello"[..]);
let body = Full::<_, Infallible>::new(&b"hello"[..]);

let buffered = body.collect().await.unwrap();

Expand All @@ -121,6 +121,7 @@ mod tests {
}

#[tokio::test]
#[allow(unused_must_use)]
async fn delayed_segments() {
let one = stream::once(async { Ok::<_, Infallible>(Frame::data(&b"hello "[..])) });
let two = stream::once(async {
Expand Down
8 changes: 4 additions & 4 deletions http-body-util/src/combinators/box_body.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use crate::BodyExt as _;

use bytes::Buf;
use http_body::{Body, Frame, SizeHint};
use std::{
Expand Down Expand Up @@ -63,9 +61,10 @@ where
impl<D, E> Default for BoxBody<D, E>
where
D: Buf + 'static,
E: 'static,
{
fn default() -> Self {
BoxBody::new(crate::Empty::new().map_err(|err| match err {}))
BoxBody::new(crate::Empty::new())
}
}

Expand Down Expand Up @@ -115,8 +114,9 @@ where
impl<D, E> Default for UnsyncBoxBody<D, E>
where
D: Buf + 'static,
E: 'static,
{
fn default() -> Self {
UnsyncBoxBody::new(crate::Empty::new().map_err(|err| match err {}))
UnsyncBoxBody::new(crate::Empty::new())
}
}
10 changes: 6 additions & 4 deletions http-body-util/src/either.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,14 +144,16 @@ pub(crate) mod proj {

#[cfg(test)]
mod tests {
use std::convert::Infallible;

use super::*;
use crate::{BodyExt, Empty, Full};

#[tokio::test]
async fn data_left() {
let full = Full::new(&b"hello"[..]);
let full = Full::<_, Infallible>::new(&b"hello"[..]);

let mut value: Either<_, Empty<&[u8]>> = Either::Left(full);
let mut value: Either<_, Empty<&[u8], Infallible>> = Either::Left(full);

assert_eq!(value.size_hint().exact(), Some(b"hello".len() as u64));
assert_eq!(
Expand All @@ -163,9 +165,9 @@ mod tests {

#[tokio::test]
async fn data_right() {
let full = Full::new(&b"hello!"[..]);
let full = Full::<_, Infallible>::new(&b"hello!"[..]);

let mut value: Either<Empty<&[u8]>, _> = Either::Right(full);
let mut value: Either<Empty<&[u8], Infallible>, _> = Either::Right(full);

assert_eq!(value.size_hint().exact(), Some(b"hello!".len() as u64));
assert_eq!(
Expand Down
18 changes: 9 additions & 9 deletions http-body-util/src/empty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,20 @@ use std::{
};

/// A body that is always empty.
pub struct Empty<D> {
_marker: PhantomData<fn() -> D>,
pub struct Empty<D, E = Infallible> {
_marker: PhantomData<fn() -> (D, E)>,
}

impl<D> Empty<D> {
impl<D, E> Empty<D, E> {
/// Create a new `Empty`.
pub fn new() -> Self {
Self::default()
}
}

impl<D: Buf> Body for Empty<D> {
impl<D: Buf, E> Body for Empty<D, E> {
type Data = D;
type Error = Infallible;
type Error = E;

#[inline]
fn poll_frame(
Expand All @@ -41,26 +41,26 @@ impl<D: Buf> Body for Empty<D> {
}
}

impl<D> fmt::Debug for Empty<D> {
impl<D, E> fmt::Debug for Empty<D, E> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Empty").finish()
}
}

impl<D> Default for Empty<D> {
impl<D, E> Default for Empty<D, E> {
fn default() -> Self {
Self {
_marker: PhantomData,
}
}
}

impl<D> Clone for Empty<D> {
impl<D, E> Clone for Empty<D, E> {
fn clone(&self) -> Self {
Self {
_marker: PhantomData,
}
}
}

impl<D> Copy for Empty<D> {}
impl<D, E> Copy for Empty<D, E> {}
67 changes: 50 additions & 17 deletions http-body-util/src/full.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,20 @@ use http_body::{Body, Frame, SizeHint};
use pin_project_lite::pin_project;
use std::borrow::Cow;
use std::convert::{Infallible, TryFrom};
use std::fmt;
use std::marker::PhantomData;
use std::pin::Pin;
use std::task::{Context, Poll};

pin_project! {
/// A body that consists of a single chunk.
#[derive(Clone, Copy, Debug)]
pub struct Full<D> {
pub struct Full<D, E = Infallible> {
data: Option<D>,
_marker: PhantomData<fn() -> E>,
}
}

impl<D> Full<D>
impl<D, E> Full<D, E>
where
D: Buf,
{
Expand All @@ -25,16 +27,19 @@ where
} else {
None
};
Full { data }
Full {
data,
_marker: PhantomData,
}
}
}

impl<D> Body for Full<D>
impl<D, E> Body for Full<D, E>
where
D: Buf,
{
type Data = D;
type Error = Infallible;
type Error = E;

fn poll_frame(
mut self: Pin<&mut Self>,
Expand All @@ -55,17 +60,43 @@ where
}
}

impl<D> Default for Full<D>
impl<D, E> Clone for Full<D, E>
where
D: Clone,
{
fn clone(&self) -> Self {
Self {
data: self.data.clone(),
_marker: self._marker,
}
}
}

impl<D, E> Copy for Full<D, E> where D: Copy {}

impl<D, E> fmt::Debug for Full<D, E>
where
D: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Full").field("data", &self.data).finish()
}
}

impl<D, E> Default for Full<D, E>
where
D: Buf,
{
/// Create an empty `Full`.
fn default() -> Self {
Full { data: None }
Full {
data: None,
_marker: PhantomData,
}
}
}

impl<D> From<Bytes> for Full<D>
impl<D, E> From<Bytes> for Full<D, E>
where
D: Buf + From<Bytes>,
{
Expand All @@ -74,7 +105,7 @@ where
}
}

impl<D> From<Vec<u8>> for Full<D>
impl<D, E> From<Vec<u8>> for Full<D, E>
where
D: Buf + From<Vec<u8>>,
{
Expand All @@ -83,7 +114,7 @@ where
}
}

impl<D> From<&'static [u8]> for Full<D>
impl<D, E> From<&'static [u8]> for Full<D, E>
where
D: Buf + From<&'static [u8]>,
{
Expand All @@ -92,7 +123,7 @@ where
}
}

impl<D, B> From<Cow<'static, B>> for Full<D>
impl<D, E, B> From<Cow<'static, B>> for Full<D, E>
where
D: Buf + From<&'static B> + From<B::Owned>,
B: ToOwned + ?Sized,
Expand All @@ -105,7 +136,7 @@ where
}
}

impl<D> From<String> for Full<D>
impl<D, E> From<String> for Full<D, E>
where
D: Buf + From<String>,
{
Expand All @@ -114,7 +145,7 @@ where
}
}

impl<D> From<&'static str> for Full<D>
impl<D, E> From<&'static str> for Full<D, E>
where
D: Buf + From<&'static str>,
{
Expand All @@ -125,12 +156,14 @@ where

#[cfg(test)]
mod tests {
use std::convert::Infallible;

use super::*;
use crate::BodyExt;

#[tokio::test]
async fn full_returns_some() {
let mut full = Full::new(&b"hello"[..]);
let mut full = Full::<_, Infallible>::new(&b"hello"[..]);
assert_eq!(full.size_hint().exact(), Some(b"hello".len() as u64));
assert_eq!(
full.frame().await.unwrap().unwrap().into_data().unwrap(),
Expand All @@ -141,7 +174,7 @@ mod tests {

#[tokio::test]
async fn empty_full_returns_none() {
assert!(Full::<&[u8]>::default().frame().await.is_none());
assert!(Full::new(&b""[..]).frame().await.is_none());
assert!(Full::<&[u8], Infallible>::default().frame().await.is_none());
assert!(Full::<_, Infallible>::new(&b""[..]).frame().await.is_none());
}
}
4 changes: 2 additions & 2 deletions http-body-util/src/limited.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ mod tests {
#[tokio::test]
async fn read_for_body_under_limit_returns_data() {
const DATA: &[u8] = b"testing";
let inner = Full::new(Bytes::from(DATA));
let inner = Full::<_, Infallible>::new(Bytes::from(DATA));
let body = &mut Limited::new(inner, 8);

let mut hint = SizeHint::new();
Expand All @@ -128,7 +128,7 @@ mod tests {
#[tokio::test]
async fn read_for_body_over_limit_returns_error() {
const DATA: &[u8] = b"testing a string that is too long";
let inner = Full::new(Bytes::from(DATA));
let inner = Full::<_, Infallible>::new(Bytes::from(DATA));
let body = &mut Limited::new(inner, 8);

let mut hint = SizeHint::new();
Expand Down
1 change: 1 addition & 0 deletions http-body/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ pub trait Body {
type Error;

/// Attempt to pull out the next data buffer of this stream.
#[allow(clippy::type_complexity)]
fn poll_frame(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
Expand Down