1pub(crate) mod foreign_impls;
4pub mod message_body;
5pub(crate) mod none;
6pub(crate) mod size;
7
8use crate::body::message_body::{MessageBody, MessageBodyMapErr};
9use crate::body::size::BodySize;
10use bytes::Bytes;
11use std::error::Error;
12use std::fmt::Debug;
13use std::pin::Pin;
14use std::task::{Context, Poll};
15
16#[derive(Debug, Clone)]
17pub struct BoxBody(BoxBodyInner);
19
20enum BoxBodyInner {
21 None(none::None),
22 Bytes(Bytes),
23 Stream(Pin<Box<dyn MessageBody<Error = Box<dyn Error>>>>),
24}
25
26impl Clone for BoxBodyInner {
27 fn clone(&self) -> Self {
28 match self {
29 BoxBodyInner::None(none) => BoxBodyInner::None(*none),
30 BoxBodyInner::Bytes(b) => BoxBodyInner::Bytes(b.clone()),
31 BoxBodyInner::Stream(_) => BoxBodyInner::None(none::None::new()),
32 }
33 }
34}
35
36impl Debug for BoxBodyInner {
37 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
38 match self {
39 BoxBodyInner::None(none) => f.debug_tuple("Empty").field(none).finish(),
40 BoxBodyInner::Bytes(b) => f.debug_tuple("Bytes").field(b).finish(),
41 BoxBodyInner::Stream(_) => f.debug_tuple("Stream").finish(),
42 }
43 }
44}
45
46impl BoxBody {
47 #[inline]
52 pub fn new<B>(body: B) -> Self
53 where
54 B: MessageBody + Clone + 'static,
55 {
56 match body.size() {
57 BodySize::None => Self(BoxBodyInner::None(none::None::new())),
58 _ => match body.try_into_bytes() {
59 Ok(bytes) => Self(BoxBodyInner::Bytes(bytes)),
60 Err(body) => {
61 let body = MessageBodyMapErr::new(body, Into::into);
62 Self(BoxBodyInner::Stream(Box::pin(body)))
63 }
64 },
65 }
66 }
67
68 #[inline]
70 pub fn as_pin_mut(&mut self) -> Pin<&mut Self> {
71 Pin::new(self)
72 }
73}
74
75impl MessageBody for BoxBody {
76 type Error = Box<dyn Error>;
77
78 #[inline]
79 fn size(&self) -> BodySize {
80 match &self.0 {
81 BoxBodyInner::None(none) => none.size(),
82 BoxBodyInner::Bytes(bytes) => bytes.size(),
83 BoxBodyInner::Stream(stream) => stream.size(),
84 }
85 }
86
87 #[inline]
88 fn poll_next(
89 mut self: Pin<&mut Self>,
90 cx: &mut Context<'_>,
91 ) -> Poll<Option<Result<Bytes, Self::Error>>> {
92 match &mut self.0 {
93 BoxBodyInner::None(body) => Pin::new(body).poll_next(cx).map_err(|err| match err {}),
94 BoxBodyInner::Bytes(body) => Pin::new(body).poll_next(cx).map_err(|err| match err {}),
95 BoxBodyInner::Stream(body) => Pin::new(body).poll_next(cx),
96 }
97 }
98
99 #[inline]
100 fn try_into_bytes(self) -> Result<Bytes, Self> {
101 match self.0 {
102 BoxBodyInner::None(body) => Ok(body.try_into_bytes().unwrap()),
103 BoxBodyInner::Bytes(body) => Ok(body.try_into_bytes().unwrap()),
104 _ => Err(self),
105 }
106 }
107
108 #[inline]
109 fn boxed(self) -> BoxBody {
110 self
111 }
112}