http_body_alt/
body_ext.rs1use core::{
2 pin::Pin,
3 task::{Context, Poll, ready},
4};
5
6use pin_project_lite::pin_project;
7
8use super::{body::Body, frame::Frame};
9
10pub trait BodyExt: Body {
11 fn frame(&mut self) -> FrameFuture<'_, Self>
12 where
13 Self: Unpin,
14 {
15 FrameFuture { body: self }
16 }
17
18 fn data(&mut self) -> DataFuture<'_, Self>
19 where
20 Self: Unpin,
21 {
22 DataFuture { body: self }
23 }
24
25 fn chain<B>(self, other: B) -> ChainBody<Self, B>
26 where
27 B: Body<Data = Self::Data>,
28 Self: Sized,
29 Self::Error: From<B::Error>,
30 {
31 ChainBody {
32 first: self,
33 second: other,
34 }
35 }
36}
37
38pub struct FrameFuture<'a, B: ?Sized> {
39 body: &'a mut B,
40}
41
42impl<B> Future for FrameFuture<'_, B>
43where
44 B: Body + Unpin,
45{
46 type Output = Option<Result<Frame<B::Data>, B::Error>>;
47
48 #[inline]
49 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
50 Body::poll_frame(Pin::new(self.get_mut().body), cx)
51 }
52}
53
54pub struct DataFuture<'a, B: ?Sized> {
55 body: &'a mut B,
56}
57
58impl<B> Future for DataFuture<'_, B>
59where
60 B: Body + Unpin,
61{
62 type Output = Option<Result<B::Data, B::Error>>;
63
64 #[inline]
65 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
66 let opt = match ready!(Body::poll_frame(Pin::new(self.get_mut().body), cx)) {
67 Some(Ok(Frame::Data(data))) => Some(Ok(data)),
68 Some(Err(e)) => Some(Err(e)),
69 Some(_) | None => None,
70 };
71
72 Poll::Ready(opt)
73 }
74}
75
76pin_project! {
77 pub struct ChainBody<A, B> {
78 #[pin]
79 first: A,
80 #[pin]
81 second: B
82 }
83}
84
85impl<A, B> Body for ChainBody<A, B>
86where
87 A: Body,
88 B: Body<Data = A::Data>,
89 A::Error: From<B::Error>,
90{
91 type Data = A::Data;
92 type Error = A::Error;
93
94 fn poll_frame(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Result<Frame<Self::Data>, Self::Error>>> {
95 let this = self.project();
96
97 match ready!(this.first.poll_frame(cx)) {
98 Some(frame) => Poll::Ready(Some(frame)),
99 None => this.second.poll_frame(cx).map_err(Into::into),
100 }
101 }
102
103 #[inline]
104 fn is_end_stream(&self) -> bool {
105 self.first.is_end_stream() && self.second.is_end_stream()
106 }
107
108 fn size_hint(&self) -> crate::SizeHint {
109 self.first.size_hint() + self.second.size_hint()
110 }
111}
112
113impl<B> BodyExt for B where B: Body {}