tower_hyper_http_body_compat/
body.rs1use std::{
2 pin::Pin,
3 task::{Context, Poll},
4};
5
6use http::HeaderMap;
7use http_body_1::Frame;
8use pin_project_lite::pin_project;
9
10pin_project! {
13 #[derive(Debug, Clone, Copy)]
18 pub struct HttpBody04ToHttpBody1<B> {
19 #[pin]
20 body: B,
21 }
22}
23
24impl<B> HttpBody04ToHttpBody1<B> {
25 #[inline]
27 pub fn new(body: B) -> Self {
28 Self { body }
29 }
30}
31
32impl<B> http_body_1::Body for HttpBody04ToHttpBody1<B>
33where
34 B: http_body_04::Body,
35{
36 type Data = B::Data;
37 type Error = B::Error;
38
39 fn poll_frame(
40 mut self: Pin<&mut Self>,
41 cx: &mut Context<'_>,
42 ) -> Poll<Option<Result<Frame<Self::Data>, Self::Error>>> {
43 match self.as_mut().project().body.poll_data(cx) {
44 Poll::Ready(Some(Ok(buf))) => return Poll::Ready(Some(Ok(Frame::data(buf)))),
45 Poll::Ready(Some(Err(err))) => return Poll::Ready(Some(Err(err))),
46 Poll::Ready(None) => {}
47 Poll::Pending => return Poll::Pending,
48 }
49
50 match self.as_mut().project().body.poll_trailers(cx) {
51 Poll::Ready(Ok(Some(trailers))) => Poll::Ready(Some(Ok(Frame::trailers(trailers)))),
52 Poll::Ready(Ok(None)) => Poll::Ready(None),
53 Poll::Ready(Err(err)) => Poll::Ready(Some(Err(err))),
54 Poll::Pending => Poll::Pending,
55 }
56 }
57
58 fn size_hint(&self) -> http_body_1::SizeHint {
59 let size_hint = self.body.size_hint();
60 let mut out = http_body_1::SizeHint::new();
61 out.set_lower(size_hint.lower());
62 if let Some(upper) = size_hint.upper() {
63 out.set_upper(upper);
64 }
65 out
66 }
67
68 #[inline]
69 fn is_end_stream(&self) -> bool {
70 self.body.is_end_stream()
71 }
72}
73
74pin_project! {
77 #[derive(Debug, Clone, Default)]
82 pub struct HttpBody1ToHttpBody04<B> {
83 #[pin]
84 body: B,
85 trailers: Option<HeaderMap>,
86 }
87}
88
89impl<B> HttpBody1ToHttpBody04<B> {
90 #[inline]
92 pub fn new(body: B) -> Self {
93 Self {
94 body,
95 trailers: None,
96 }
97 }
98}
99
100impl<B> http_body_04::Body for HttpBody1ToHttpBody04<B>
101where
102 B: http_body_1::Body,
103{
104 type Data = B::Data;
105 type Error = B::Error;
106
107 fn poll_data(
108 self: Pin<&mut Self>,
109 cx: &mut Context<'_>,
110 ) -> Poll<Option<Result<Self::Data, Self::Error>>> {
111 let this = self.project();
112 match ready!(this.body.poll_frame(cx)) {
113 Some(Ok(frame)) => {
114 let frame = match frame.into_data() {
115 Ok(data) => return Poll::Ready(Some(Ok(data))),
116 Err(frame) => frame,
117 };
118
119 match frame.into_trailers() {
120 Ok(trailers) => {
121 *this.trailers = Some(trailers);
122 }
123 Err(_frame) => {}
124 }
125
126 Poll::Ready(None)
127 }
128 Some(Err(err)) => Poll::Ready(Some(Err(err))),
129 None => Poll::Ready(None),
130 }
131 }
132
133 fn poll_trailers(
134 mut self: Pin<&mut Self>,
135 cx: &mut Context<'_>,
136 ) -> Poll<Result<Option<http::HeaderMap>, Self::Error>> {
137 loop {
138 let this = self.as_mut().project();
139
140 if let Some(trailers) = this.trailers.take() {
141 break Poll::Ready(Ok(Some(trailers)));
142 }
143
144 match ready!(this.body.poll_frame(cx)) {
145 Some(Ok(frame)) => match frame.into_trailers() {
146 Ok(trailers) => break Poll::Ready(Ok(Some(trailers))),
147 Err(_frame) => {}
150 },
151 Some(Err(err)) => break Poll::Ready(Err(err)),
152 None => break Poll::Ready(Ok(None)),
153 }
154 }
155 }
156
157 fn size_hint(&self) -> http_body_04::SizeHint {
158 let size_hint = self.body.size_hint();
159 let mut out = http_body_04::SizeHint::new();
160 out.set_lower(size_hint.lower());
161 if let Some(upper) = size_hint.upper() {
162 out.set_upper(upper);
163 }
164 out
165 }
166
167 #[inline]
168 fn is_end_stream(&self) -> bool {
169 self.body.is_end_stream()
170 }
171}