kube_client/client/
body.rs1use std::{
2 error::Error as StdError,
3 fmt,
4 pin::{pin, Pin},
5 task::{Context, Poll},
6};
7
8use bytes::Bytes;
9use http_body::{Body as HttpBody, Frame, SizeHint};
10use http_body_util::{combinators::UnsyncBoxBody, BodyExt};
11
12pub struct Body {
14 kind: Kind,
15}
16
17impl fmt::Debug for Body {
18 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
19 let mut builder = f.debug_struct("Body");
20 match self.kind {
21 Kind::Once(_) => builder.field("kind", &"Once"),
22 Kind::Wrap(_) => builder.field("kind", &"Wrap"),
23 };
24 builder.finish()
25 }
26}
27
28enum Kind {
29 Once(Option<Bytes>),
30 Wrap(UnsyncBoxBody<Bytes, Box<dyn StdError + Send + Sync>>),
31}
32
33impl Body {
34 fn new(kind: Kind) -> Self {
35 Body { kind }
36 }
37
38 pub fn empty() -> Self {
40 Self::new(Kind::Once(None))
41 }
42
43 pub(crate) fn wrap_body<B>(body: B) -> Self
45 where
46 B: HttpBody<Data = Bytes> + Send + 'static,
47 B::Error: Into<Box<dyn std::error::Error + Send + Sync>>,
48 {
49 Body::new(Kind::Wrap(body.map_err(Into::into).boxed_unsync()))
50 }
51
52 pub async fn collect_bytes(self) -> Result<Bytes, crate::Error> {
54 Ok(self.collect().await?.to_bytes())
55 }
56}
57
58impl From<Bytes> for Body {
59 fn from(bytes: Bytes) -> Self {
60 if bytes.is_empty() {
61 Self::empty()
62 } else {
63 Self::new(Kind::Once(Some(bytes)))
64 }
65 }
66}
67
68impl From<Vec<u8>> for Body {
69 fn from(vec: Vec<u8>) -> Self {
70 Self::from(Bytes::from(vec))
71 }
72}
73
74impl HttpBody for Body {
75 type Data = Bytes;
76 type Error = crate::Error;
77
78 fn poll_frame(
79 mut self: Pin<&mut Self>,
80 cx: &mut Context<'_>,
81 ) -> Poll<Option<Result<Frame<Self::Data>, Self::Error>>> {
82 match &mut self.kind {
83 Kind::Once(val) => Poll::Ready(val.take().map(|bytes| Ok(Frame::data(bytes)))),
84 Kind::Wrap(body) => pin!(body).poll_frame(cx).map_err(crate::Error::Service),
85 }
86 }
87
88 fn size_hint(&self) -> SizeHint {
89 match &self.kind {
90 Kind::Once(Some(bytes)) => SizeHint::with_exact(bytes.len() as u64),
91 Kind::Once(None) => SizeHint::with_exact(0),
92 Kind::Wrap(body) => body.size_hint(),
93 }
94 }
95
96 fn is_end_stream(&self) -> bool {
97 match &self.kind {
98 Kind::Once(Some(bytes)) => bytes.is_empty(),
99 Kind::Once(None) => true,
100 Kind::Wrap(body) => body.is_end_stream(),
101 }
102 }
103}