simple_hyper_client/body/
shared.rs1use hyper::body::{Body, Buf, Frame, SizeHint};
8
9use std::cmp;
10use std::io;
11use std::pin::Pin;
12use std::sync::Arc;
13use std::task::{Context, Poll};
14
15#[derive(Clone)]
22pub struct SharedBody(Option<SharedBytes>);
23
24impl SharedBody {
25 #[inline]
27 pub fn empty() -> Self {
28 Self::default()
29 }
30
31 pub fn len(&self) -> usize {
33 self.0.as_ref().map(SharedBytes::len).unwrap_or_default()
34 }
35}
36
37impl Default for SharedBody {
38 fn default() -> Self {
39 Self(Some(SharedBytes::Static(&[])))
43 }
44}
45
46impl From<Arc<Vec<u8>>> for SharedBody {
47 fn from(arc: Arc<Vec<u8>>) -> Self {
48 Self(Some(SharedBytes::Arc(arc)))
49 }
50}
51
52impl From<Vec<u8>> for SharedBody {
53 fn from(vec: Vec<u8>) -> Self {
54 Self(Some(SharedBytes::Arc(Arc::new(vec))))
55 }
56}
57
58impl From<String> for SharedBody {
59 fn from(s: String) -> Self {
60 Self(Some(SharedBytes::Arc(Arc::new(s.into_bytes()))))
61 }
62}
63
64impl From<&'static [u8]> for SharedBody {
65 fn from(slice: &'static [u8]) -> Self {
66 Self(Some(SharedBytes::Static(slice)))
67 }
68}
69
70impl From<&'static str> for SharedBody {
71 fn from(s: &'static str) -> Self {
72 Self(Some(SharedBytes::Static(s.as_bytes())))
73 }
74}
75
76impl AsRef<[u8]> for SharedBody {
77 fn as_ref(&self) -> &[u8] {
78 self.0.as_ref().map(SharedBytes::as_ref).unwrap_or(&[])
79 }
80}
81
82impl Body for SharedBody {
83 type Data = SharedBuf;
84 type Error = io::Error;
85
86 fn poll_frame(
87 self: Pin<&mut Self>,
88 _cx: &mut Context<'_>,
89 ) -> Poll<Option<Result<Frame<Self::Data>, Self::Error>>> {
90 let opt = self
91 .get_mut()
92 .0
93 .take()
94 .map(|bytes| SharedBuf { bytes, pos: 0 })
95 .map(Frame::data)
96 .map(Ok);
97 Poll::Ready(opt)
98 }
99
100 fn is_end_stream(&self) -> bool {
101 self.0.is_none()
102 }
103
104 fn size_hint(&self) -> SizeHint {
105 let len = self.0.as_ref().map(SharedBytes::len).unwrap_or_default();
106 SizeHint::with_exact(len as u64)
107 }
108}
109
110pub struct SharedBuf {
111 bytes: SharedBytes,
112 pos: usize,
113}
114
115impl SharedBuf {
116 pub fn len(&self) -> usize {
117 self.bytes.len()
118 }
119}
120
121impl Buf for SharedBuf {
122 fn remaining(&self) -> usize {
123 self.len() - self.pos
124 }
125
126 fn chunk(&self) -> &[u8] {
127 match self.bytes {
128 SharedBytes::Arc(ref bytes) => &bytes[self.pos..],
129 SharedBytes::Static(ref bytes) => &bytes[self.pos..],
130 }
131 }
132
133 fn advance(&mut self, cnt: usize) {
134 self.pos = cmp::min(self.len(), self.pos + cnt);
135 }
136}
137
138#[derive(Clone)]
139enum SharedBytes {
140 Arc(Arc<Vec<u8>>),
141 Static(&'static [u8]),
142}
143
144impl SharedBytes {
145 fn len(&self) -> usize {
146 match self {
147 Self::Arc(ref bytes) => bytes.len(),
148 Self::Static(ref bytes) => bytes.len(),
149 }
150 }
151}
152
153impl AsRef<[u8]> for SharedBytes {
154 fn as_ref(&self) -> &[u8] {
155 match self {
156 Self::Arc(vec) => vec,
157 Self::Static(slice) => slice,
158 }
159 }
160}