aws_multipart_upload/client/
part.rs1use super::UploadId;
2use crate::complete_upload::CompleteMultipartUploadOutput as CompleteResponse;
3use crate::error::{ErrorRepr, Result};
4use crate::part_upload::UploadPartOutput as UploadResponse;
5
6use aws_sdk_s3::primitives::ByteStream;
7use bytes::{BufMut as _, BytesMut};
8use std::borrow::Cow;
9use std::fmt::{self, Display, Formatter};
10use std::io::{Result as IoResult, Write};
11use std::ops::{Deref, DerefMut};
12
13#[derive(Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
23pub struct PartBody(BytesMut);
24
25impl PartBody {
26 pub fn new(bytes: BytesMut) -> Self {
28 Self(bytes)
29 }
30
31 pub fn with_capacity(capacity: usize) -> Self {
33 let bytes = BytesMut::with_capacity(capacity);
34 Self(bytes)
35 }
36
37 pub fn size(&self) -> usize {
39 self.0.len()
40 }
41
42 pub fn as_sdk_body(&mut self) -> ByteStream {
48 let buf = self.split();
49 let bytes = buf.freeze();
50 bytes.into()
51 }
52}
53
54impl Write for PartBody {
55 fn write(&mut self, buf: &[u8]) -> IoResult<usize> {
56 let bytes = buf.len();
57 self.reserve(bytes);
58 self.put(buf);
59 Ok(bytes)
60 }
61
62 fn flush(&mut self) -> IoResult<()> {
63 Ok(())
64 }
65}
66
67impl From<BytesMut> for PartBody {
68 fn from(value: BytesMut) -> Self {
69 Self(value)
70 }
71}
72
73impl Deref for PartBody {
74 type Target = BytesMut;
75
76 fn deref(&self) -> &Self::Target {
77 &self.0
78 }
79}
80
81impl DerefMut for PartBody {
82 fn deref_mut(&mut self) -> &mut Self::Target {
83 &mut self.0
84 }
85}
86
87impl AsRef<[u8]> for PartBody {
88 fn as_ref(&self) -> &[u8] {
89 self.deref().as_ref()
90 }
91}
92
93#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
99pub struct PartNumber(i32);
100
101impl Default for PartNumber {
102 fn default() -> Self {
103 Self(1)
104 }
105}
106
107impl PartNumber {
108 pub fn new(n: i32) -> Self {
119 Self(n)
120 }
121
122 pub fn increment(&mut self) -> PartNumber {
124 self.0 += 1;
125 PartNumber(self.0 - 1)
126 }
127}
128
129impl Deref for PartNumber {
130 type Target = i32;
131
132 fn deref(&self) -> &Self::Target {
133 &self.0
134 }
135}
136
137impl DerefMut for PartNumber {
138 fn deref_mut(&mut self) -> &mut Self::Target {
139 &mut self.0
140 }
141}
142
143impl Display for PartNumber {
144 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
145 write!(f, "part_{}", self.0)
146 }
147}
148
149#[derive(Debug, Clone, Default)]
157pub struct EntityTag(Cow<'static, str>);
158
159impl EntityTag {
160 fn new<T: Into<Cow<'static, str>>>(etag: T) -> Self {
161 Self(etag.into())
162 }
163
164 pub(crate) fn try_from_upload_resp(value: &UploadResponse) -> Result<Self, ErrorRepr> {
165 value
166 .e_tag
167 .as_deref()
168 .map(Self::from)
169 .ok_or_else(|| ErrorRepr::Missing("UploadResponse", "e_tag"))
170 }
171
172 pub(crate) fn try_from_complete_resp(value: &CompleteResponse) -> Result<Self, ErrorRepr> {
173 value
174 .e_tag
175 .as_deref()
176 .map(Self::from)
177 .ok_or_else(|| ErrorRepr::Missing("CompleteResponse", "e_tag"))
178 }
179}
180
181impl Deref for EntityTag {
182 type Target = str;
183
184 fn deref(&self) -> &str {
185 &self.0
186 }
187}
188
189impl AsRef<str> for EntityTag {
190 fn as_ref(&self) -> &str {
191 self
192 }
193}
194
195impl Display for EntityTag {
196 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
197 self.0.fmt(f)
198 }
199}
200
201impl From<&str> for EntityTag {
202 fn from(value: &str) -> Self {
203 Self::new(value.to_string())
204 }
205}
206
207impl From<String> for EntityTag {
208 fn from(value: String) -> Self {
209 Self(Cow::Owned(value))
210 }
211}
212
213#[derive(Debug, Clone)]
218pub struct CompletedPart {
219 pub id: UploadId,
221 pub etag: EntityTag,
224 pub part_number: PartNumber,
227 pub part_size: usize,
229}
230
231impl CompletedPart {
232 pub fn new(id: UploadId, etag: EntityTag, part_number: PartNumber, part_size: usize) -> Self {
234 Self {
235 id,
236 etag,
237 part_number,
238 part_size,
239 }
240 }
241}
242
243#[derive(Debug, Clone, Default)]
245pub struct CompletedParts(Vec<CompletedPart>);
246
247impl CompletedParts {
248 pub fn push(&mut self, part: CompletedPart) {
250 self.0.push(part);
251 }
252
253 pub fn extend(&mut self, other: CompletedParts) {
255 self.0.extend(other.0);
256 self.sort_ascending();
257 }
258
259 pub fn count(&self) -> usize {
261 self.0.len()
262 }
263
264 pub fn size(&self) -> usize {
266 self.0.iter().map(|p| p.part_size).sum()
267 }
268
269 pub fn max_part_number(&self) -> PartNumber {
272 match self.0.iter().max_by_key(|p| p.part_number) {
273 Some(part) => part.part_number,
274 _ => PartNumber::default(),
275 }
276 }
277
278 pub fn sort_ascending(&mut self) {
283 self.sort_by_key(|part| part.part_number);
284 }
285}
286
287impl Deref for CompletedParts {
288 type Target = [CompletedPart];
289
290 fn deref(&self) -> &Self::Target {
291 &self.0
292 }
293}
294
295impl DerefMut for CompletedParts {
296 fn deref_mut(&mut self) -> &mut Self::Target {
297 &mut self.0
298 }
299}
300
301impl From<&CompletedParts> for aws_sdk_s3::types::CompletedMultipartUpload {
302 fn from(value: &CompletedParts) -> Self {
303 let completed_parts = value.0.iter().fold(Vec::new(), |mut acc, v| {
304 acc.push(
305 aws_sdk_s3::types::CompletedPart::builder()
306 .e_tag(v.etag.to_string())
307 .part_number(*v.part_number)
308 .build(),
309 );
310
311 acc
312 });
313
314 aws_sdk_s3::types::CompletedMultipartUpload::builder()
315 .set_parts(Some(completed_parts))
316 .build()
317 }
318}