http_pool/
body.rs

1use hyper::body::{Body, Buf, Frame};
2use std::error::Error;
3use std::pin::Pin;
4use std::task::{Context, Poll};
5
6/// 擦除掉具体的body和error
7trait ErasedBody: Send + Sync {
8    fn poll_frame(
9        self: Pin<&mut Self>,
10        cx: &mut Context<'_>,
11    ) -> Poll<Option<Result<Frame<Box<dyn Buf + Send>>, Box<dyn Error + Send + Sync>>>>;
12}
13
14/// 为所有满足条件的 Body 实现 ErasedBody
15impl<B> ErasedBody for B
16where
17    B: Body + Send + Sync + 'static,
18    B::Data: Buf + Send + 'static,
19    B::Error: Error + Send + Sync + 'static,
20{
21    fn poll_frame(
22        self: Pin<&mut Self>,
23        cx: &mut Context<'_>,
24    ) -> Poll<Option<Result<Frame<Box<dyn Buf + Send>>, Box<dyn Error + Send + Sync>>>> {
25        match <Self as Body>::poll_frame(self, cx) {
26            Poll::Pending => Poll::Pending,
27            Poll::Ready(None) => Poll::Ready(None),
28            Poll::Ready(Some(Err(e))) => Poll::Ready(Some(Err(Box::new(e)))),
29            Poll::Ready(Some(Ok(frame))) => {
30                let mapped = frame.map_data(|d| Box::new(d) as Box<dyn Buf + Send>);
31                Poll::Ready(Some(Ok(mapped)))
32            }
33        }
34    }
35}
36
37/// 通用型http body
38pub struct VariantBody {
39    inner: Pin<Box<dyn ErasedBody + 'static>>,
40}
41
42impl VariantBody {
43    pub fn new<B>(body: B) -> Self
44    where
45        B: Body + Send + Sync + 'static,
46        B::Data: Buf + Send + 'static,
47        B::Error: Error + Send + Sync + 'static,
48    {
49        Self {
50            inner: Box::pin(body),
51        }
52    }
53}
54
55/// 为VariantBody实现body trait
56impl Body for VariantBody {
57    type Data = Box<dyn Buf + Send>;
58    type Error = Box<dyn Error + Send + Sync>;
59
60    fn poll_frame(
61        self: Pin<&mut Self>,
62        cx: &mut Context<'_>,
63    ) -> Poll<Option<Result<Frame<Self::Data>, Self::Error>>> {
64        self.get_mut().inner.as_mut().poll_frame(cx)
65    }
66}
67
68pub type Empty = http_body_util::Empty<hyper::body::Bytes>;
69
70pub type Full = http_body_util::Full<hyper::body::Bytes>;
71
72pub fn empty() -> VariantBody {
73    VariantBody::new(Empty::new())
74}
75
76pub fn variant_body<B>(body: B) -> VariantBody
77where
78    B: Body + Send + Sync + 'static,
79    B::Data: Buf + Send + 'static,
80    B::Error: Error + Send + Sync + 'static,
81{
82    VariantBody::new(body)
83}