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