spire_core/request/
body.rs1use std::any::Any;
7use std::fmt;
8use std::pin::Pin;
9use std::task::{Context, Poll};
10
11use bytes::Bytes;
12use http_body::{Body as HttpBody, Frame, SizeHint};
13use http_body_util::combinators::BoxBody;
14use http_body_util::{BodyExt, Empty, Full};
15
16use crate::BoxError;
17
18fn try_downcast<T, K>(k: K) -> Result<T, K>
24where
25 T: 'static,
26 K: Send + 'static,
27{
28 let mut k = Some(k);
29 match <dyn Any>::downcast_mut::<Option<T>>(&mut k) {
30 Some(x) => Ok(x.take().unwrap()),
31 _ => Err(k.unwrap()),
32 }
33}
34
35pub struct Body(BoxBody<Bytes, BoxError>);
41
42impl Body {
43 pub fn new<B>(body: B) -> Self
45 where
46 B: HttpBody<Data = Bytes> + Send + Sync + 'static,
47 B::Error: Into<BoxError> + Send + Sync + 'static,
48 {
49 try_downcast(body).unwrap_or_else(|x| {
50 let boxed = x.map_err(Into::into).boxed();
51 Self(boxed)
52 })
53 }
54}
55
56impl Default for Body {
57 #[inline]
58 fn default() -> Self {
59 Self::new(Empty::new())
60 }
61}
62
63impl From<()> for Body {
64 #[inline]
65 fn from((): ()) -> Self {
66 Self::default()
67 }
68}
69
70impl From<Bytes> for Body {
71 #[inline]
72 fn from(bytes: Bytes) -> Self {
73 Self::new(Full::new(bytes))
74 }
75}
76
77impl From<Vec<u8>> for Body {
78 #[inline]
79 fn from(vec: Vec<u8>) -> Self {
80 Bytes::from(vec).into()
81 }
82}
83
84impl From<&'static [u8]> for Body {
85 #[inline]
86 fn from(slice: &'static [u8]) -> Self {
87 Bytes::from(slice).into()
88 }
89}
90
91impl From<String> for Body {
92 #[inline]
93 fn from(string: String) -> Self {
94 string.into_bytes().into()
95 }
96}
97
98impl From<&'static str> for Body {
99 #[inline]
100 fn from(slice: &'static str) -> Self {
101 slice.as_bytes().into()
102 }
103}
104
105impl fmt::Debug for Body {
106 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
107 f.debug_struct("Body").finish_non_exhaustive()
108 }
109}
110
111impl HttpBody for Body {
112 type Data = Bytes;
113 type Error = BoxError;
114
115 #[inline]
116 fn poll_frame(
117 mut self: Pin<&mut Self>,
118 cx: &mut Context<'_>,
119 ) -> Poll<Option<Result<Frame<Self::Data>, Self::Error>>> {
120 Pin::new(&mut self.0).poll_frame(cx)
121 }
122
123 #[inline]
124 fn is_end_stream(&self) -> bool {
125 self.0.is_end_stream()
126 }
127
128 #[inline]
129 fn size_hint(&self) -> SizeHint {
130 self.0.size_hint()
131 }
132}
133
134#[cfg(test)]
138mod test {
139 use bytes::Bytes;
140 use http_body_util::{Empty, Full};
141
142 use super::Body;
143
144 #[test]
145 pub fn empty() {
146 let _ = Body::default();
147 let _ = Body::new(Empty::new());
148 }
149
150 #[test]
151 pub fn full() {
152 let body = Full::new(Bytes::new());
153 let _ = Body::new(body);
154 }
155}