Coverage Report

Created: 2026-01-30 06:08

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/http-body-util-0.1.3/src/lib.rs
Line
Count
Source
1
#![deny(missing_debug_implementations, missing_docs, unreachable_pub)]
2
#![cfg_attr(test, deny(warnings))]
3
4
//! Utilities for [`http_body::Body`].
5
//!
6
//! [`BodyExt`] adds extensions to the common trait.
7
//!
8
//! [`Empty`] and [`Full`] provide simple implementations.
9
10
mod collected;
11
pub mod combinators;
12
mod either;
13
mod empty;
14
mod full;
15
mod limited;
16
mod stream;
17
18
#[cfg(feature = "channel")]
19
pub mod channel;
20
21
mod util;
22
23
use self::combinators::{BoxBody, MapErr, MapFrame, UnsyncBoxBody};
24
25
pub use self::collected::Collected;
26
pub use self::either::Either;
27
pub use self::empty::Empty;
28
pub use self::full::Full;
29
pub use self::limited::{LengthLimitError, Limited};
30
pub use self::stream::{BodyDataStream, BodyStream, StreamBody};
31
32
#[cfg(feature = "channel")]
33
pub use self::channel::Channel;
34
35
/// An extension trait for [`http_body::Body`] adding various combinators and adapters
36
pub trait BodyExt: http_body::Body {
37
    /// Returns a future that resolves to the next [`Frame`], if any.
38
    ///
39
    /// [`Frame`]: combinators::Frame
40
    fn frame(&mut self) -> combinators::Frame<'_, Self>
41
    where
42
        Self: Unpin,
43
    {
44
        combinators::Frame(self)
45
    }
46
47
    /// Maps this body's frame to a different kind.
48
    fn map_frame<F, B>(self, f: F) -> MapFrame<Self, F>
49
    where
50
        Self: Sized,
51
        F: FnMut(http_body::Frame<Self::Data>) -> http_body::Frame<B>,
52
        B: bytes::Buf,
53
    {
54
        MapFrame::new(self, f)
55
    }
56
57
    /// Maps this body's error value to a different value.
58
0
    fn map_err<F, E>(self, f: F) -> MapErr<Self, F>
59
0
    where
60
0
        Self: Sized,
61
0
        F: FnMut(Self::Error) -> E,
62
    {
63
0
        MapErr::new(self, f)
64
0
    }
Unexecuted instantiation: <reqwest::async_impl::body::IntoBytesBody<opendal_core::raw::http_util::client::HttpBufferBody> as http_body_util::BodyExt>::map_err::<<core::convert::Infallible as core::convert::Into<alloc::boxed::Box<dyn core::error::Error + core::marker::Sync + core::marker::Send>>>::into, alloc::boxed::Box<dyn core::error::Error + core::marker::Sync + core::marker::Send>>
Unexecuted instantiation: <http_body_util::combinators::box_body::BoxBody<bytes::bytes::Bytes, alloc::boxed::Box<dyn core::error::Error + core::marker::Sync + core::marker::Send>> as http_body_util::BodyExt>::map_err::<reqwest::async_impl::body::box_err<alloc::boxed::Box<dyn core::error::Error + core::marker::Sync + core::marker::Send>>, alloc::boxed::Box<dyn core::error::Error + core::marker::Sync + core::marker::Send>>
Unexecuted instantiation: <hyper::body::incoming::Incoming as http_body_util::BodyExt>::map_err::<reqwest::async_impl::body::box_err<hyper::error::Error>, alloc::boxed::Box<dyn core::error::Error + core::marker::Sync + core::marker::Send>>
Unexecuted instantiation: <reqwest::async_impl::body::IntoBytesBody<reqwest::async_impl::decoder::Decoder> as http_body_util::BodyExt>::map_err::<<reqwest::error::Error as core::convert::Into<alloc::boxed::Box<dyn core::error::Error + core::marker::Sync + core::marker::Send>>>::into, alloc::boxed::Box<dyn core::error::Error + core::marker::Sync + core::marker::Send>>
Unexecuted instantiation: <reqwest::async_impl::body::ReadTimeoutBody<http_body_util::combinators::box_body::BoxBody<bytes::bytes::Bytes, alloc::boxed::Box<dyn core::error::Error + core::marker::Sync + core::marker::Send>>> as http_body_util::BodyExt>::map_err::<reqwest::async_impl::body::box_err<reqwest::error::Error>, alloc::boxed::Box<dyn core::error::Error + core::marker::Sync + core::marker::Send>>
Unexecuted instantiation: <reqwest::async_impl::body::TotalTimeoutBody<http_body_util::combinators::map_err::MapErr<reqwest::async_impl::body::ReadTimeoutBody<http_body_util::combinators::box_body::BoxBody<bytes::bytes::Bytes, alloc::boxed::Box<dyn core::error::Error + core::marker::Sync + core::marker::Send>>>, reqwest::async_impl::body::box_err<reqwest::error::Error>>> as http_body_util::BodyExt>::map_err::<reqwest::async_impl::body::box_err<reqwest::error::Error>, alloc::boxed::Box<dyn core::error::Error + core::marker::Sync + core::marker::Send>>
Unexecuted instantiation: <reqwest::async_impl::body::TotalTimeoutBody<http_body_util::combinators::box_body::BoxBody<bytes::bytes::Bytes, alloc::boxed::Box<dyn core::error::Error + core::marker::Sync + core::marker::Send>>> as http_body_util::BodyExt>::map_err::<reqwest::async_impl::body::box_err<reqwest::error::Error>, alloc::boxed::Box<dyn core::error::Error + core::marker::Sync + core::marker::Send>>
65
66
    /// Turn this body into a boxed trait object.
67
0
    fn boxed(self) -> BoxBody<Self::Data, Self::Error>
68
0
    where
69
0
        Self: Sized + Send + Sync + 'static,
70
    {
71
0
        BoxBody::new(self)
72
0
    }
Unexecuted instantiation: <http_body_util::combinators::map_err::MapErr<reqwest::async_impl::body::IntoBytesBody<opendal_core::raw::http_util::client::HttpBufferBody>, <core::convert::Infallible as core::convert::Into<alloc::boxed::Box<dyn core::error::Error + core::marker::Sync + core::marker::Send>>>::into> as http_body_util::BodyExt>::boxed
Unexecuted instantiation: <http_body_util::combinators::map_err::MapErr<http_body_util::combinators::box_body::BoxBody<bytes::bytes::Bytes, alloc::boxed::Box<dyn core::error::Error + core::marker::Sync + core::marker::Send>>, reqwest::async_impl::body::box_err<alloc::boxed::Box<dyn core::error::Error + core::marker::Sync + core::marker::Send>>> as http_body_util::BodyExt>::boxed
Unexecuted instantiation: <http_body_util::combinators::map_err::MapErr<reqwest::async_impl::body::IntoBytesBody<reqwest::async_impl::decoder::Decoder>, <reqwest::error::Error as core::convert::Into<alloc::boxed::Box<dyn core::error::Error + core::marker::Sync + core::marker::Send>>>::into> as http_body_util::BodyExt>::boxed
Unexecuted instantiation: <http_body_util::combinators::map_err::MapErr<reqwest::async_impl::body::ReadTimeoutBody<http_body_util::combinators::box_body::BoxBody<bytes::bytes::Bytes, alloc::boxed::Box<dyn core::error::Error + core::marker::Sync + core::marker::Send>>>, reqwest::async_impl::body::box_err<reqwest::error::Error>> as http_body_util::BodyExt>::boxed
Unexecuted instantiation: <http_body_util::combinators::map_err::MapErr<reqwest::async_impl::body::TotalTimeoutBody<http_body_util::combinators::map_err::MapErr<reqwest::async_impl::body::ReadTimeoutBody<http_body_util::combinators::box_body::BoxBody<bytes::bytes::Bytes, alloc::boxed::Box<dyn core::error::Error + core::marker::Sync + core::marker::Send>>>, reqwest::async_impl::body::box_err<reqwest::error::Error>>>, reqwest::async_impl::body::box_err<reqwest::error::Error>> as http_body_util::BodyExt>::boxed
Unexecuted instantiation: <http_body_util::combinators::map_err::MapErr<reqwest::async_impl::body::TotalTimeoutBody<http_body_util::combinators::box_body::BoxBody<bytes::bytes::Bytes, alloc::boxed::Box<dyn core::error::Error + core::marker::Sync + core::marker::Send>>>, reqwest::async_impl::body::box_err<reqwest::error::Error>> as http_body_util::BodyExt>::boxed
Unexecuted instantiation: <http_body_util::combinators::map_err::MapErr<hyper::body::incoming::Incoming, reqwest::async_impl::body::box_err<hyper::error::Error>> as http_body_util::BodyExt>::boxed
73
74
    /// Turn this body into a boxed trait object that is !Sync.
75
    fn boxed_unsync(self) -> UnsyncBoxBody<Self::Data, Self::Error>
76
    where
77
        Self: Sized + Send + 'static,
78
    {
79
        UnsyncBoxBody::new(self)
80
    }
81
82
    /// Turn this body into [`Collected`] body which will collect all the DATA frames
83
    /// and trailers.
84
    fn collect(self) -> combinators::Collect<Self>
85
    where
86
        Self: Sized,
87
    {
88
        combinators::Collect {
89
            body: self,
90
            collected: Some(crate::Collected::default()),
91
        }
92
    }
93
94
    /// Add trailers to the body.
95
    ///
96
    /// The trailers will be sent when all previous frames have been sent and the `trailers` future
97
    /// resolves.
98
    ///
99
    /// # Example
100
    ///
101
    /// ```
102
    /// use http::HeaderMap;
103
    /// use http_body_util::{Full, BodyExt};
104
    /// use bytes::Bytes;
105
    ///
106
    /// # #[tokio::main]
107
    /// async fn main() {
108
    /// let (tx, rx) = tokio::sync::oneshot::channel::<HeaderMap>();
109
    ///
110
    /// let body = Full::<Bytes>::from("Hello, World!")
111
    ///     // add trailers via a future
112
    ///     .with_trailers(async move {
113
    ///         match rx.await {
114
    ///             Ok(trailers) => Some(Ok(trailers)),
115
    ///             Err(_err) => None,
116
    ///         }
117
    ///     });
118
    ///
119
    /// // compute the trailers in the background
120
    /// tokio::spawn(async move {
121
    ///     let _ = tx.send(compute_trailers().await);
122
    /// });
123
    ///
124
    /// async fn compute_trailers() -> HeaderMap {
125
    ///     // ...
126
    ///     # unimplemented!()
127
    /// }
128
    /// # }
129
    /// ```
130
    fn with_trailers<F>(self, trailers: F) -> combinators::WithTrailers<Self, F>
131
    where
132
        Self: Sized,
133
        F: std::future::Future<Output = Option<Result<http::HeaderMap, Self::Error>>>,
134
    {
135
        combinators::WithTrailers::new(self, trailers)
136
    }
137
138
    /// Turn this body into [`BodyDataStream`].
139
    fn into_data_stream(self) -> BodyDataStream<Self>
140
    where
141
        Self: Sized,
142
    {
143
        BodyDataStream::new(self)
144
    }
145
}
146
147
impl<T: ?Sized> BodyExt for T where T: http_body::Body {}