rama_http_types/body/
mod.rs1use crate::body::util::BodyExt;
6use pin_project_lite::pin_project;
7use rama_core::bytes::Bytes;
8use rama_core::error::BoxError;
9use rama_core::futures::TryStream;
10use rama_core::futures::stream::Stream;
11use rama_core::stream::json;
12use rama_utils::str::arcstr::ArcStr;
13use serde::de::DeserializeOwned;
14use sse::{EventDataRead, EventStream};
15use std::pin::Pin;
16use std::task::{Context, Poll};
17use sync_wrapper::SyncWrapper;
18
19pub mod http_body;
22mod http_body_util;
23
24pub use http_body::Body as StreamingBody;
25pub use http_body::Frame;
26pub use http_body::SizeHint;
27
28pub mod util {
30 pub use super::http_body_util::*;
31}
32
33mod limit;
34pub use limit::BodyLimit;
35
36mod ext;
37pub use ext::BodyExtractExt;
38
39#[doc(inline)]
40pub use util::{CollectError, CollectErrorKind, CollectOptions};
41
42pub mod sse;
43
44mod infinite;
45pub use infinite::InfiniteReader;
46
47mod on_drop;
48pub use on_drop::OnDropBody;
49
50mod guarded;
51pub use guarded::GuardedBody;
52
53mod optional;
54pub use optional::OptionalBody;
55
56impl<B: StreamingBody> StreamingBody for crate::Request<B> {
59 type Data = B::Data;
60 type Error = B::Error;
61
62 fn poll_frame(
63 self: Pin<&mut Self>,
64 cx: &mut Context<'_>,
65 ) -> Poll<Option<Result<Frame<Self::Data>, Self::Error>>> {
66 unsafe { self.map_unchecked_mut(Self::body_mut).poll_frame(cx) }
69 }
70
71 fn is_end_stream(&self) -> bool {
72 self.body().is_end_stream()
73 }
74
75 fn size_hint(&self) -> SizeHint {
76 self.body().size_hint()
77 }
78}
79
80impl<B: StreamingBody> StreamingBody for crate::Response<B> {
81 type Data = B::Data;
82 type Error = B::Error;
83
84 fn poll_frame(
85 self: Pin<&mut Self>,
86 cx: &mut Context<'_>,
87 ) -> Poll<Option<Result<Frame<Self::Data>, Self::Error>>> {
88 unsafe { self.map_unchecked_mut(Self::body_mut).poll_frame(cx) }
91 }
92
93 fn is_end_stream(&self) -> bool {
94 self.body().is_end_stream()
95 }
96
97 fn size_hint(&self) -> SizeHint {
98 self.body().size_hint()
99 }
100}
101
102type BoxBody = util::combinators::BoxBody<Bytes, BoxError>;
105
106fn boxed<B>(body: B) -> BoxBody
107where
108 B: StreamingBody<Data = Bytes, Error: Into<BoxError>> + Send + Sync + 'static,
109{
110 try_downcast(body).unwrap_or_else(|body| body.map_err(Into::into).boxed())
111}
112
113#[expect(clippy::unwrap_used)]
114pub(crate) fn try_downcast<T, K>(k: K) -> Result<T, K>
115where
116 T: 'static,
117 K: Send + 'static,
118{
119 let mut k = Some(k);
120 if let Some(k) = <dyn std::any::Any>::downcast_mut::<Option<T>>(&mut k) {
121 Ok(k.take().unwrap())
122 } else {
123 Err(k.unwrap())
124 }
125}
126
127#[must_use]
129#[derive(Debug)]
130pub struct Body(BoxBody);
131
132impl Body {
133 pub fn new<B>(body: B) -> Self
135 where
136 B: StreamingBody<Data = Bytes, Error: Into<BoxError>> + Send + Sync + 'static,
137 {
138 try_downcast(body).unwrap_or_else(|body| Self(boxed(body)))
139 }
140
141 pub fn with_limit<B>(body: B, limit: usize) -> Self
143 where
144 B: StreamingBody<Data = Bytes, Error: Into<BoxError>> + Send + Sync + 'static,
145 {
146 Self::new(util::Limited::new(body, limit))
147 }
148
149 pub fn empty() -> Self {
151 Self::new(util::Empty::new())
152 }
153
154 pub fn from_stream<S>(stream: S) -> Self
158 where
159 S: TryStream<Ok: Into<Bytes>, Error: Into<BoxError>> + Send + 'static,
160 {
161 Self::new(StreamBody {
162 stream: SyncWrapper::new(stream),
163 })
164 }
165
166 pub fn limited(self, limit: usize) -> Self {
168 Self::new(util::Limited::new(self.0, limit))
169 }
170
171 pub fn on_drop<F>(self, on_drop: F) -> Self
177 where
178 F: FnOnce() + Send + Sync + 'static,
179 {
180 Self::new(OnDropBody::new(self.0, on_drop))
181 }
182
183 pub fn with_trailer_headers(self, headers: crate::HeaderMap) -> Self {
190 Self::new(self.0.with_trailers(std::future::ready(Some(Ok(headers)))))
191 }
192
193 pub fn into_data_stream(self) -> BodyDataStream {
200 BodyDataStream { inner: self }
201 }
202
203 #[must_use]
207 pub fn into_event_stream<T: EventDataRead>(self) -> EventStream<BodyDataStream, T> {
208 EventStream::new(self.into_data_stream())
209 }
210
211 #[must_use]
215 pub fn into_json_stream<T: DeserializeOwned>(self) -> json::JsonReadStream<T, BodyDataStream> {
216 let stream = self.into_data_stream();
217 json::JsonReadStream::new(stream)
218 }
219
220 #[must_use]
224 pub fn into_json_stream_with_config<T: DeserializeOwned>(
225 self,
226 cfg: json::ParseConfig,
227 ) -> json::JsonReadStream<T, BodyDataStream> {
228 let stream = self.into_data_stream();
229 json::JsonReadStream::new_with_config(stream, cfg)
230 }
231
232 #[must_use]
236 pub fn into_string_data_event_stream(self) -> EventStream<BodyDataStream> {
237 EventStream::new(self.into_data_stream())
238 }
239
240 pub async fn chunk(&mut self) -> Result<Option<Bytes>, BoxError> {
244 loop {
246 if let Some(res) = self.frame().await {
247 let frame = res?;
248 if let Ok(buf) = frame.into_data() {
249 return Ok(Some(buf));
250 }
251 } else {
253 return Ok(None);
254 }
255 }
256 }
257}
258
259impl Default for Body {
260 fn default() -> Self {
261 Self::empty()
262 }
263}
264
265impl From<()> for Body {
266 fn from(_: ()) -> Self {
267 Self::empty()
268 }
269}
270
271macro_rules! body_from_impl {
272 ($ty:ty) => {
273 impl From<$ty> for Body {
274 fn from(buf: $ty) -> Self {
275 Self::new(crate::body::util::Full::from(buf))
276 }
277 }
278 };
279}
280
281body_from_impl!(&'static [u8]);
282body_from_impl!(std::borrow::Cow<'static, [u8]>);
283body_from_impl!(Vec<u8>);
284
285body_from_impl!(&'static str);
286body_from_impl!(std::borrow::Cow<'static, str>);
287body_from_impl!(String);
288
289impl From<&ArcStr> for Body {
290 fn from(buf: &ArcStr) -> Self {
291 Self::new(if let Some(s) = ArcStr::as_static(buf) {
292 crate::body::util::Full::from(s)
293 } else {
294 crate::body::util::Full::from(buf.to_string())
295 })
296 }
297}
298
299impl From<ArcStr> for Body {
300 #[inline(always)]
301 fn from(buf: ArcStr) -> Self {
302 Self::from(&buf)
303 }
304}
305
306body_from_impl!(Bytes);
307
308impl StreamingBody for Body {
309 type Data = Bytes;
310 type Error = BoxError;
311
312 #[inline]
313 fn poll_frame(
314 mut self: Pin<&mut Self>,
315 cx: &mut Context<'_>,
316 ) -> Poll<Option<Result<Frame<Self::Data>, Self::Error>>> {
317 Pin::new(&mut self.0).poll_frame(cx)
318 }
319
320 #[inline]
321 fn size_hint(&self) -> SizeHint {
322 self.0.size_hint()
323 }
324
325 #[inline]
326 fn is_end_stream(&self) -> bool {
327 self.0.is_end_stream()
328 }
329}
330
331#[derive(Debug)]
335#[must_use]
336pub struct BodyDataStream {
337 inner: Body,
338}
339
340impl Stream for BodyDataStream {
341 type Item = Result<Bytes, BoxError>;
342
343 #[inline]
344 fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
345 loop {
346 match rama_core::futures::ready!(Pin::new(&mut self.inner).poll_frame(cx)?) {
347 Some(frame) => match frame.into_data() {
348 Ok(data) => return Poll::Ready(Some(Ok(data))),
349 Err(_frame) => {}
350 },
351 None => return Poll::Ready(None),
352 }
353 }
354 }
355}
356
357impl StreamingBody for BodyDataStream {
358 type Data = Bytes;
359 type Error = BoxError;
360
361 #[inline]
362 fn poll_frame(
363 mut self: Pin<&mut Self>,
364 cx: &mut Context<'_>,
365 ) -> Poll<Option<Result<Frame<Self::Data>, Self::Error>>> {
366 Pin::new(&mut self.inner).poll_frame(cx)
367 }
368
369 #[inline]
370 fn is_end_stream(&self) -> bool {
371 self.inner.is_end_stream()
372 }
373
374 #[inline]
375 fn size_hint(&self) -> SizeHint {
376 self.inner.size_hint()
377 }
378}
379
380pin_project! {
381 struct StreamBody<S> {
382 #[pin]
383 stream: SyncWrapper<S>,
384 }
385}
386
387impl<S> StreamingBody for StreamBody<S>
388where
389 S: TryStream<Ok: Into<Bytes>, Error: Into<BoxError>>,
390{
391 type Data = Bytes;
392 type Error = BoxError;
393
394 fn poll_frame(
395 self: Pin<&mut Self>,
396 cx: &mut Context<'_>,
397 ) -> Poll<Option<Result<Frame<Self::Data>, Self::Error>>> {
398 let stream = self.project().stream.get_pin_mut();
399 match rama_core::futures::ready!(stream.try_poll_next(cx)) {
400 Some(Ok(chunk)) => Poll::Ready(Some(Ok(Frame::data(chunk.into())))),
401 Some(Err(err)) => Poll::Ready(Some(Err(err.into()))),
402 None => Poll::Ready(None),
403 }
404 }
405}
406
407#[test]
408fn test_try_downcast() {
409 assert_eq!(try_downcast::<i32, _>(5_u32), Err(5_u32));
410 assert_eq!(try_downcast::<i32, _>(5_i32), Ok(5_i32));
411}