1use serde::{Deserialize, Serialize};
2
3#[derive(Deserialize, Debug)]
4pub struct InitiateMultipartUploadResponse {
5 #[serde(rename = "Bucket")]
6 _bucket: String,
7 #[serde(rename = "Key")]
8 pub key: String,
9 #[serde(rename = "UploadId")]
10 pub upload_id: String,
11}
12
13#[derive(Deserialize, Debug, Clone)]
15pub struct Owner {
16 #[serde(rename = "DisplayName")]
17 pub display_name: Option<String>,
19 #[serde(rename = "ID")]
20 pub id: String,
22}
23
24pub type DateTime = chrono::DateTime<chrono::Utc>;
25
26#[derive(Deserialize, Debug, Clone)]
28pub struct Object {
29 #[serde(rename = "LastModified")]
30 pub last_modified: DateTime,
32 #[serde(rename = "ETag")]
33 pub e_tag: Option<String>,
36 #[serde(rename = "StorageClass")]
37 pub storage_class: Option<String>,
39 #[serde(rename = "Key")]
40 pub key: String,
42 #[serde(rename = "Owner")]
43 pub owner: Option<Owner>,
45 #[serde(rename = "Size")]
46 pub size: u64,
48}
49
50#[derive(Deserialize, Debug, Clone)]
52pub struct MultipartUpload {
53 #[serde(rename = "Initiated")]
54 pub initiated: DateTime,
56 #[serde(rename = "StorageClass")]
57 pub storage_class: String,
59 #[serde(rename = "Key")]
60 pub key: String,
62 #[serde(rename = "Owner")]
63 pub owner: Option<Owner>,
65 #[serde(rename = "UploadId")]
66 pub id: String,
68}
69
70use std::fmt;
71
72impl fmt::Display for CompleteMultipartUploadData {
73 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
74 let mut parts = String::new();
75 for part in self.parts.clone() {
76 parts.push_str(&part.to_string())
77 }
78 write!(
79 f,
80 "<CompleteMultipartUpload>{}</CompleteMultipartUpload>",
81 parts
82 )
83 }
84}
85
86impl CompleteMultipartUploadData {
87 pub fn len(&self) -> usize {
88 self.to_string().as_bytes().len()
89 }
90
91 pub fn is_empty(&self) -> bool {
92 self.to_string().as_bytes().len() == 0
93 }
94}
95
96#[derive(Debug, Clone)]
97pub struct CompleteMultipartUploadData {
98 pub parts: Vec<Part>,
99}
100
101#[derive(Debug, Clone, Serialize)]
102pub struct Part {
103 #[serde(rename = "PartNumber")]
104 pub part_number: u32,
105 #[serde(rename = "ETag")]
106 pub etag: String,
107}
108
109impl fmt::Display for Part {
110 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
111 write!(f, "<Part>").expect("Can't fail");
112 write!(f, "<PartNumber>{}</PartNumber>", self.part_number).expect("Can't fail");
113 write!(f, "<ETag>{}</ETag>", self.etag).expect("Can't fail");
114 write!(f, "</Part>")
115 }
116}
117
118#[derive(Deserialize, Debug, Clone)]
119pub struct BucketLocationResult {
120 #[serde(rename = "$value")]
121 pub region: String,
122}
123
124#[derive(Deserialize, Debug, Clone)]
128pub struct ListBucketResult {
129 #[serde(rename = "Name")]
130 pub name: String,
132 #[serde(rename = "Delimiter")]
133 pub delimiter: Option<String>,
135 #[serde(rename = "MaxKeys")]
136 pub max_keys: Option<i32>,
138 #[serde(rename = "Prefix")]
139 pub prefix: Option<String>,
141 #[serde(rename = "ContinuationToken")] #[serde(alias = "Marker")] pub continuation_token: Option<String>,
146 #[serde(rename = "EncodingType")]
147 pub encoding_type: Option<String>,
149 #[serde(
150 default,
151 rename = "IsTruncated",
152 deserialize_with = "super::deserializer::bool_deserializer"
153 )]
154 pub is_truncated: bool,
163 #[serde(rename = "NextContinuationToken", default)] #[serde(alias = "NextMarker")] pub next_continuation_token: Option<String>,
166 #[serde(rename = "Contents", default)]
167 pub contents: Vec<Object>,
169 #[serde(rename = "CommonPrefixes", default)]
170 pub common_prefixes: Option<Vec<CommonPrefix>>,
173}
174
175#[derive(Deserialize, Debug, Clone)]
177pub struct ListMultipartUploadsResult {
178 #[serde(rename = "Bucket")]
179 pub name: String,
181 #[serde(rename = "NextKeyMarker")]
182 pub next_marker: Option<String>,
187 #[serde(rename = "Prefix")]
188 pub prefix: Option<String>,
191 #[serde(rename = "KeyMarker")]
192 pub marker: Option<String>,
194 #[serde(rename = "EncodingType")]
195 pub encoding_type: Option<String>,
197 #[serde(
198 rename = "IsTruncated",
199 deserialize_with = "super::deserializer::bool_deserializer"
200 )]
201 pub is_truncated: bool,
205 #[serde(rename = "Upload", default)]
206 pub uploads: Vec<MultipartUpload>,
208 #[serde(rename = "CommonPrefixes", default)]
209 pub common_prefixes: Option<Vec<CommonPrefix>>,
212}
213
214#[derive(Deserialize, Debug, Clone)]
216pub struct CommonPrefix {
217 #[serde(rename = "Prefix")]
218 pub prefix: String,
220}
221
222#[derive(Deserialize, Debug, Default, Clone)]
224pub struct HeadObjectResult {
225 #[serde(rename = "AcceptRanges")]
226 pub accept_ranges: Option<String>,
228 #[serde(rename = "CacheControl")]
229 pub cache_control: Option<String>,
231 #[serde(rename = "ContentDisposition")]
232 pub content_disposition: Option<String>,
234 #[serde(rename = "ContentEncoding")]
235 pub content_encoding: Option<String>,
237 #[serde(rename = "ContentLanguage")]
238 pub content_language: Option<String>,
240 #[serde(rename = "ContentLength")]
241 pub content_length: Option<i64>,
243 #[serde(rename = "ContentType")]
244 pub content_type: Option<String>,
246 #[serde(rename = "DeleteMarker")]
247 pub delete_marker: Option<bool>,
249 #[serde(rename = "ETag")]
250 pub e_tag: Option<String>,
252 #[serde(rename = "Expiration")]
253 pub expiration: Option<String>,
256 #[serde(rename = "Expires")]
257 pub expires: Option<DateTime>,
259 #[serde(rename = "LastModified")]
260 pub last_modified: Option<DateTime>,
262 #[serde(rename = "Metadata", default)]
263 pub metadata: Option<::std::collections::HashMap<String, String>>,
265 #[serde(rename = "MissingMeta")]
266 pub missing_meta: Option<i64>,
269 #[serde(rename = "ObjectLockLegalHoldStatus")]
270 pub object_lock_legal_hold_status: Option<String>,
273 #[serde(rename = "ObjectLockMode")]
274 pub object_lock_mode: Option<String>,
276 #[serde(rename = "ObjectLockRetainUntilDate")]
277 pub object_lock_retain_until_date: Option<String>,
280 #[serde(rename = "PartsCount")]
281 pub parts_count: Option<i64>,
283 #[serde(rename = "ReplicationStatus")]
284 pub replication_status: Option<String>,
286 #[serde(rename = "RequestCharged")]
287 pub request_charged: Option<String>,
288 #[serde(rename = "Restore")]
289 pub restore: Option<String>,
292 #[serde(rename = "SseCustomerAlgorithm")]
293 pub sse_customer_algorithm: Option<String>,
295 #[serde(rename = "SseCustomerKeyMd5")]
296 pub sse_customer_key_md5: Option<String>,
298 #[serde(rename = "SsekmsKeyId")]
299 pub ssekms_key_id: Option<String>,
301 #[serde(rename = "ServerSideEncryption")]
302 pub server_side_encryption: Option<String>,
305 #[serde(rename = "StorageClass")]
306 pub storage_class: Option<String>,
308 #[serde(rename = "VersionId")]
309 pub version_id: Option<String>,
311 #[serde(rename = "WebsiteRedirectLocation")]
312 pub website_redirect_location: Option<String>,
314}
315
316#[derive(Deserialize, Debug)]
317pub struct AwsError {
318 #[serde(rename = "Code")]
319 pub code: String,
320 #[serde(rename = "Message")]
321 pub message: String,
322 #[serde(rename = "RequestId")]
323 pub request_id: String,
324}
325
326#[derive(Clone, Debug, Serialize, Deserialize)]
327#[serde(rename = "CORSConfiguration")]
328pub struct CorsConfiguration {
329 #[serde(rename = "CORSRule")]
330 rules: Vec<CorsRule>,
331}
332
333impl CorsConfiguration {
334 pub fn new(rules: Vec<CorsRule>) -> Self {
335 CorsConfiguration { rules }
336 }
337}
338
339#[derive(Clone, Debug, Serialize, Deserialize)]
340pub struct CorsRule {
341 #[serde(rename = "AllowedHeader")]
342 #[serde(skip_serializing_if = "Option::is_none")]
343 allowed_headers: Option<Vec<String>>,
344 #[serde(rename = "AllowedMethod")]
345 allowed_methods: Vec<String>,
346 #[serde(rename = "AllowedOrigin")]
347 allowed_origins: Vec<String>,
348 #[serde(rename = "ExposeHeader")]
349 #[serde(skip_serializing_if = "Option::is_none")]
350 expose_headers: Option<Vec<String>>,
351 #[serde(rename = "ID")]
352 id: Option<String>,
353 #[serde(rename = "MaxAgeSeconds")]
354 #[serde(skip_serializing_if = "Option::is_none")]
355 max_age_seconds: Option<u32>,
356}
357
358impl CorsRule {
359 pub fn new(
360 allowed_headers: Option<Vec<String>>,
361 allowed_methods: Vec<String>,
362 allowed_origins: Vec<String>,
363 expose_headers: Option<Vec<String>>,
364 id: Option<String>,
365 max_age_seconds: Option<u32>,
366 ) -> Self {
367 Self {
368 allowed_headers,
369 allowed_methods,
370 allowed_origins,
371 expose_headers,
372 id,
373 max_age_seconds,
374 }
375 }
376}
377
378#[cfg(test)]
379mod test {
380 use super::{CorsConfiguration, CorsRule};
381
382 #[test]
383 fn cors_config_serde() {
384 let rule = CorsRule {
385 allowed_headers: Some(vec!["Authorization".to_string(), "Header2".to_string()]),
386 allowed_methods: vec!["GET".to_string(), "DELETE".to_string()],
387 allowed_origins: vec!["*".to_string()],
388 expose_headers: None,
389 id: Some("lala".to_string()),
390 max_age_seconds: None,
391 };
392
393 let config = CorsConfiguration {
394 rules: vec![rule.clone(), rule],
395 };
396
397 let se = quick_xml::se::to_string(&config).unwrap();
398 assert_eq!(
399 se,
400 r#"<CORSConfiguration><CORSRule><AllowedHeader>Authorization</AllowedHeader><AllowedHeader>Header2</AllowedHeader><AllowedMethod>GET</AllowedMethod><AllowedMethod>DELETE</AllowedMethod><AllowedOrigin>*</AllowedOrigin><ID>lala</ID></CORSRule><CORSRule><AllowedHeader>Authorization</AllowedHeader><AllowedHeader>Header2</AllowedHeader><AllowedMethod>GET</AllowedMethod><AllowedMethod>DELETE</AllowedMethod><AllowedOrigin>*</AllowedOrigin><ID>lala</ID></CORSRule></CORSConfiguration>"#
401 )
402 }
403}