aws_multipart_upload/types/
api.rs1use aws_sdk_s3::types as s3;
2
3use crate::{
4 aws_ops::{create, upload},
5 AwsError,
6};
7
8#[derive(Debug, Clone, PartialEq)]
10pub struct UploadId(String);
11
12impl From<String> for UploadId {
13 fn from(value: String) -> Self {
14 UploadId(value)
15 }
16}
17
18impl std::fmt::Display for UploadId {
19 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
20 write!(f, "{}", self.0)
21 }
22}
23
24impl TryFrom<create::CreateMultipartUploadOutput> for UploadId {
25 type Error = AwsError;
26
27 fn try_from(value: create::CreateMultipartUploadOutput) -> Result<Self, Self::Error> {
28 let id = value.upload_id().ok_or(AwsError::Missing("upload_id"))?;
29 Ok(Self(id.to_string()))
30 }
31}
32
33#[derive(Debug, Clone, PartialEq)]
35pub struct UploadAddress {
36 bucket: String,
37 key: String,
38}
39
40impl UploadAddress {
41 pub fn new(bucket: String, key: String) -> Self {
42 Self { bucket, key }
43 }
44
45 pub fn bucket(&self) -> &str {
46 &self.bucket
47 }
48
49 pub fn key(&self) -> &str {
50 &self.key
51 }
52}
53
54#[derive(Debug, Clone, PartialEq)]
56pub struct UploadRequestParams {
57 upload_id: UploadId,
58 addr: UploadAddress,
59}
60
61impl UploadRequestParams {
62 pub fn new(upload_id: UploadId, addr: UploadAddress) -> Self {
63 Self { upload_id, addr }
64 }
65
66 pub fn upload_id(&self) -> &str {
67 &self.upload_id.0
68 }
69
70 pub fn bucket(&self) -> &str {
71 self.addr.bucket()
72 }
73
74 pub fn key(&self) -> &str {
75 self.addr.key()
76 }
77}
78
79#[derive(Debug, Clone, PartialEq)]
81pub struct EntityTag(String);
82
83impl EntityTag {
84 pub fn new(etag: String) -> Self {
85 Self(etag)
86 }
87}
88
89impl std::fmt::Display for EntityTag {
90 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
91 write!(f, "{}", self.0)
92 }
93}
94
95impl From<String> for EntityTag {
96 fn from(value: String) -> Self {
97 EntityTag(value)
98 }
99}
100
101impl TryFrom<upload::UploadPartOutput> for EntityTag {
102 type Error = AwsError;
103
104 fn try_from(value: upload::UploadPartOutput) -> Result<Self, Self::Error> {
105 Ok(Self(value.e_tag.ok_or(AwsError::Missing("e_tag"))?))
106 }
107}
108
109#[derive(Clone, Debug, PartialEq, Default)]
113pub struct UploadedParts {
114 pub parts: Vec<(EntityTag, i32)>,
115}
116
117impl UploadedParts {
118 pub fn new() -> Self {
119 Self::default()
120 }
121
122 pub fn update(&mut self, etag: EntityTag) {
124 let part_number = self.parts.len() + 1;
125 self.parts.push((etag, part_number as i32));
126 }
127
128 pub fn last_completed(&self) -> i32 {
131 self.parts
132 .iter()
133 .fold(0, |acc, (_, p)| if acc >= *p { acc } else { *p })
134 }
135
136 pub fn current(&self) -> i32 {
139 self.last_completed() + 1
140 }
141
142 pub fn num_parts(&self) -> usize {
144 self.parts.len()
145 }
146}
147
148impl<'a> From<&'a UploadedParts> for s3::CompletedMultipartUpload {
149 fn from(val: &'a UploadedParts) -> s3::CompletedMultipartUpload {
150 let parts = val.parts.iter().fold(Vec::new(), |mut acc, (t, n)| {
151 acc.push(
152 s3::CompletedPart::builder()
153 .e_tag(t.to_string())
154 .part_number(*n)
155 .build(),
156 );
157
158 acc
159 });
160
161 s3::CompletedMultipartUpload::builder()
162 .set_parts(Some(parts))
163 .build()
164 }
165}
166
167impl Extend<(EntityTag, i32)> for UploadedParts {
168 fn extend<T: IntoIterator<Item = (EntityTag, i32)>>(&mut self, iter: T) {
169 self.parts.extend(iter)
170 }
171}