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

feat(util): introduce a "fused" body combinator #145

Merged
merged 1 commit into from
Apr 8, 2025

Conversation

cratelyn
Copy link
Contributor

@cratelyn cratelyn commented Feb 3, 2025

this commit introduces a new Body combinator to the http-body-util library, http_body_util::combinators::Fuse<B>.

this combinator is roughly equivalent to the std::iter::Fuse<I> iterator, which returns None after the inner iterator returns it once.

while bodies should return Poll::Ready(None) indefinitely after reaching the end of the stream or returning an error, this combinator can help prevent further polling of an underlying body implementation, in the same manner that std::iter::Iterator::fuse() helps prevent an underlying iterator that might e.g. yield Some(value) after yielding None, or panic.

@cratelyn cratelyn force-pushed the fuse branch 2 times, most recently from 4c77dab to 02e11f5 Compare February 3, 2025 15:16
this commit introduces a new `Body` combinator to the `http-body-util`
library, `http_body_util::combinators::Fuse<B>`.

this combinator is roughly equivalent to the `std::iter::Fuse<I>`
iterator, which returns `None` after the inner iterator returns it once.

while bodies *should* return `Poll::Ready(None)` indefinitely after
reaching the end of the stream or returning an error, this combinator
can help prevent further polling of an underlying body implementation,
in the same manner that `std::iter::Iterator::fuse()` helps prevent an
underlying iterator that might e.g. yield `Some(value)` after yielding
`None`, or panic.

Signed-off-by: katelyn martin <[email protected]>
Comment on lines +70 to +79
fn is_end_stream(&self) -> bool {
self.inner.is_none()
}

fn size_hint(&self) -> SizeHint {
self.inner
.as_ref()
.map(B::size_hint)
.unwrap_or_else(|| SizeHint::with_exact(0))
}
Copy link
Contributor Author

@cratelyn cratelyn Apr 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i found myself wishing for this recently, since this pull request was opened.

besides the panic avoidance that this middleware can offer in certain situations, should the inner body not accept repeated polling after yielding a Ready(None) or Ready(Some(Err(_))), this middleware offers a nice additional benefit: it provides an accurate is_end_stream() for inner bodies that use the default implementation of this trait method, which always returns false.

Copy link
Member

@seanmonstar seanmonstar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks excellent to me! Thanks for the thorough docs and tests too! <3

@seanmonstar seanmonstar merged commit 4909098 into hyperium:master Apr 8, 2025
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants