1use bytes::Bytes;
19use std::sync::Arc;
20
21#[derive(Debug, Clone)]
31pub struct PutPayload(Arc<[Bytes]>);
32
33impl Default for PutPayload {
34 fn default() -> Self {
35 Self(Arc::new([]))
36 }
37}
38
39impl PutPayload {
40 pub fn new() -> Self {
42 Self::default()
43 }
44
45 pub fn from_static(s: &'static [u8]) -> Self {
47 s.into()
48 }
49
50 pub fn from_bytes(s: Bytes) -> Self {
52 s.into()
53 }
54
55 pub fn content_length(&self) -> usize {
57 self.0.iter().map(|b| b.len()).sum()
58 }
59
60 pub fn iter(&self) -> PutPayloadIter<'_> {
62 PutPayloadIter(self.0.iter())
63 }
64}
65
66impl AsRef<[Bytes]> for PutPayload {
67 fn as_ref(&self) -> &[Bytes] {
68 self.0.as_ref()
69 }
70}
71
72impl<'a> IntoIterator for &'a PutPayload {
73 type Item = &'a Bytes;
74 type IntoIter = PutPayloadIter<'a>;
75
76 fn into_iter(self) -> Self::IntoIter {
77 self.iter()
78 }
79}
80
81impl IntoIterator for PutPayload {
82 type Item = Bytes;
83 type IntoIter = PutPayloadIntoIter;
84
85 fn into_iter(self) -> Self::IntoIter {
86 PutPayloadIntoIter {
87 payload: self,
88 idx: 0,
89 }
90 }
91}
92
93#[derive(Debug)]
95pub struct PutPayloadIter<'a>(std::slice::Iter<'a, Bytes>);
96
97impl<'a> Iterator for PutPayloadIter<'a> {
98 type Item = &'a Bytes;
99
100 fn next(&mut self) -> Option<Self::Item> {
101 self.0.next()
102 }
103
104 fn size_hint(&self) -> (usize, Option<usize>) {
105 self.0.size_hint()
106 }
107}
108
109#[derive(Debug)]
111pub struct PutPayloadIntoIter {
112 payload: PutPayload,
113 idx: usize,
114}
115
116impl Iterator for PutPayloadIntoIter {
117 type Item = Bytes;
118
119 fn next(&mut self) -> Option<Self::Item> {
120 let p = self.payload.0.get(self.idx)?.clone();
121 self.idx += 1;
122 Some(p)
123 }
124
125 fn size_hint(&self) -> (usize, Option<usize>) {
126 let l = self.payload.0.len() - self.idx;
127 (l, Some(l))
128 }
129}
130
131impl From<Bytes> for PutPayload {
132 fn from(value: Bytes) -> Self {
133 Self(Arc::new([value]))
134 }
135}
136
137impl From<Vec<u8>> for PutPayload {
138 fn from(value: Vec<u8>) -> Self {
139 Self(Arc::new([value.into()]))
140 }
141}
142
143impl From<&'static str> for PutPayload {
144 fn from(value: &'static str) -> Self {
145 Bytes::from(value).into()
146 }
147}
148
149impl From<&'static [u8]> for PutPayload {
150 fn from(value: &'static [u8]) -> Self {
151 Bytes::from(value).into()
152 }
153}
154
155impl From<String> for PutPayload {
156 fn from(value: String) -> Self {
157 Bytes::from(value).into()
158 }
159}
160
161impl FromIterator<u8> for PutPayload {
162 fn from_iter<T: IntoIterator<Item = u8>>(iter: T) -> Self {
163 Bytes::from_iter(iter).into()
164 }
165}
166
167impl FromIterator<Bytes> for PutPayload {
168 fn from_iter<T: IntoIterator<Item = Bytes>>(iter: T) -> Self {
169 Self(iter.into_iter().collect())
170 }
171}
172
173impl From<PutPayload> for Bytes {
174 fn from(value: PutPayload) -> Self {
175 match value.0.len() {
176 0 => Self::new(),
177 1 => value.0[0].clone(),
178 _ => {
179 let mut buf = Vec::with_capacity(value.content_length());
180 value.iter().for_each(|x| buf.extend_from_slice(x));
181 buf.into()
182 }
183 }
184 }
185}
186
187#[derive(Debug)]
194pub struct PutPayloadMut {
195 len: usize,
196 completed: Vec<Bytes>,
197 in_progress: Vec<u8>,
198 block_size: usize,
199}
200
201impl Default for PutPayloadMut {
202 fn default() -> Self {
203 Self {
204 len: 0,
205 completed: vec![],
206 in_progress: vec![],
207
208 block_size: 8 * 1024,
209 }
210 }
211}
212
213impl PutPayloadMut {
214 pub fn new() -> Self {
216 Self::default()
217 }
218
219 pub fn with_block_size(self, block_size: usize) -> Self {
223 Self { block_size, ..self }
224 }
225
226 pub fn extend_from_slice(&mut self, slice: &[u8]) {
232 let remaining = self.in_progress.capacity() - self.in_progress.len();
233 let to_copy = remaining.min(slice.len());
234
235 self.in_progress.extend_from_slice(&slice[..to_copy]);
236 if self.in_progress.capacity() == self.in_progress.len() {
237 let new_cap = self.block_size.max(slice.len() - to_copy);
238 let completed = std::mem::replace(&mut self.in_progress, Vec::with_capacity(new_cap));
239 if !completed.is_empty() {
240 self.completed.push(completed.into())
241 }
242 self.in_progress.extend_from_slice(&slice[to_copy..])
243 }
244 self.len += slice.len();
245 }
246
247 pub fn push(&mut self, bytes: Bytes) {
252 if !self.in_progress.is_empty() {
253 let completed = std::mem::take(&mut self.in_progress);
254 self.completed.push(completed.into())
255 }
256 self.len += bytes.len();
257 self.completed.push(bytes);
258 }
259
260 #[inline]
262 pub fn is_empty(&self) -> bool {
263 self.len == 0
264 }
265
266 #[inline]
268 pub fn content_length(&self) -> usize {
269 self.len
270 }
271
272 pub fn freeze(mut self) -> PutPayload {
274 if !self.in_progress.is_empty() {
275 let completed = std::mem::take(&mut self.in_progress).into();
276 self.completed.push(completed);
277 }
278 PutPayload(self.completed.into())
279 }
280}
281
282impl From<PutPayloadMut> for PutPayload {
283 fn from(value: PutPayloadMut) -> Self {
284 value.freeze()
285 }
286}
287
288#[cfg(test)]
289mod test {
290 use crate::PutPayloadMut;
291
292 #[test]
293 fn test_put_payload() {
294 let mut chunk = PutPayloadMut::new().with_block_size(23);
295 chunk.extend_from_slice(&[1; 16]);
296 chunk.extend_from_slice(&[2; 32]);
297 chunk.extend_from_slice(&[2; 5]);
298 chunk.extend_from_slice(&[2; 21]);
299 chunk.extend_from_slice(&[2; 40]);
300 chunk.extend_from_slice(&[0; 0]);
301 chunk.push("foobar".into());
302
303 let payload = chunk.freeze();
304 assert_eq!(payload.content_length(), 120);
305
306 let chunks = payload.as_ref();
307 assert_eq!(chunks.len(), 6);
308
309 assert_eq!(chunks[0].len(), 23);
310 assert_eq!(chunks[1].len(), 25); assert_eq!(chunks[2].len(), 23);
312 assert_eq!(chunks[3].len(), 23);
313 assert_eq!(chunks[4].len(), 20);
314 assert_eq!(chunks[5].len(), 6);
315 }
316
317 #[test]
318 fn test_content_length() {
319 let mut chunk = PutPayloadMut::new();
320 chunk.push(vec![0; 23].into());
321 assert_eq!(chunk.content_length(), 23);
322 chunk.extend_from_slice(&[0; 4]);
323 assert_eq!(chunk.content_length(), 27);
324 chunk.push(vec![0; 121].into());
325 assert_eq!(chunk.content_length(), 148);
326 let payload = chunk.freeze();
327 assert_eq!(payload.content_length(), 148);
328 }
329}