1use std::{collections::HashMap, fmt::Display};
3
4use quick_xml::events::Event;
5
6use crate::error::Error;
7use crate::Result;
8
9pub const VERSION: &str = "0.2.5";
10
11pub const MIME_TYPE_XML: &str = "application/xml";
12pub const DELETE_MULTIPLE_OBJECTS_LIMIT: usize = 1000;
13pub const SIGNATURE_VERSION: &str = "OSS4-HMAC-SHA256";
14pub const UNSIGNED_PAYLOAD: &str = "UNSIGNED-PAYLOAD";
15pub const MIN_BUCKET_NAME_LENGTH: usize = 3;
16pub const MAX_BUCKET_NAME_LENGTH: usize = 63;
17pub const MAX_LIST_OBJECTS_LIMIT: u32 = 1000;
18
19#[derive(Debug, Clone, Default)]
20#[cfg_attr(feature = "serde-support", derive(serde::Serialize, serde::Deserialize))]
21#[cfg_attr(feature = "serde-camelcase", serde(rename_all = "camelCase"))]
22pub struct Owner {
23 pub id: String,
24 pub display_name: String,
25}
26
27impl Owner {
28 pub(crate) fn from_xml_reader(reader: &mut quick_xml::Reader<&[u8]>) -> Result<Self> {
29 let mut current_tag = "".to_string();
30 let mut owner = Self::default();
31
32 loop {
33 match reader.read_event()? {
34 Event::Eof => break,
35
36 Event::Start(e) => {
37 current_tag = String::from_utf8_lossy(e.local_name().as_ref()).into_owned();
38 }
39
40 Event::Text(e) => match current_tag.as_str() {
41 "ID" => owner.id = e.unescape()?.trim().to_string(),
42 "DisplayName" => owner.display_name = e.unescape()?.trim().to_string(),
43 _ => {}
44 },
45
46 Event::End(e) => {
47 current_tag.clear();
48 if e.local_name().as_ref() == b"Owner" {
49 break;
50 }
51 }
52
53 _ => {}
54 }
55 }
56
57 Ok(owner)
58 }
59}
60
61#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
63#[cfg_attr(feature = "serde-support", derive(serde::Serialize, serde::Deserialize))]
64pub enum StorageClass {
65 #[default]
67 #[cfg_attr(feature = "serde-support", serde(rename = "Standard"))]
68 Standard,
69
70 #[cfg_attr(feature = "serde-support", serde(rename = "IA"))]
72 IA,
73
74 #[cfg_attr(feature = "serde-support", serde(rename = "Archive"))]
76 Archive,
77
78 #[cfg_attr(feature = "serde-support", serde(rename = "ColdArchive"))]
80 ColdArchive,
81
82 #[cfg_attr(feature = "serde-support", serde(rename = "DeepColdArchive"))]
84 DeepColdArchive,
85}
86
87impl StorageClass {
88 pub fn as_str(&self) -> &str {
89 match self {
90 StorageClass::Standard => "Standard",
91 StorageClass::IA => "IA",
92 StorageClass::Archive => "Archive",
93 StorageClass::ColdArchive => "ColdArchive",
94 StorageClass::DeepColdArchive => "DeepColdArchive",
95 }
96 }
97}
98
99impl Display for StorageClass {
100 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
101 match self {
102 StorageClass::Standard => write!(f, "Standard"),
103 StorageClass::IA => write!(f, "IA"),
104 StorageClass::Archive => write!(f, "Archive"),
105 StorageClass::ColdArchive => write!(f, "ColdArchive"),
106 StorageClass::DeepColdArchive => write!(f, "DeepColdArchive"),
107 }
108 }
109}
110
111impl AsRef<str> for StorageClass {
112 fn as_ref(&self) -> &str {
113 self.as_str()
114 }
115}
116
117impl TryFrom<&str> for StorageClass {
118 type Error = crate::error::Error;
119
120 fn try_from(s: &str) -> std::result::Result<Self, Self::Error> {
121 match s {
122 "Standard" => Ok(StorageClass::Standard),
123 "IA" => Ok(StorageClass::IA),
124 "Archive" => Ok(StorageClass::Archive),
125 "ColdArchive" => Ok(StorageClass::ColdArchive),
126 "DeepColdArchive" => Ok(StorageClass::DeepColdArchive),
127 _ => Err(Error::Other(format!("Invalid StorageClass value: {}", s))),
128 }
129 }
130}
131
132impl TryFrom<String> for StorageClass {
133 type Error = crate::error::Error;
134
135 fn try_from(s: String) -> std::result::Result<Self, Self::Error> {
136 Self::try_from(s.as_str())
137 }
138}
139
140impl TryFrom<&String> for StorageClass {
141 type Error = crate::error::Error;
142
143 fn try_from(s: &String) -> std::result::Result<Self, Self::Error> {
144 Self::try_from(s.as_str())
145 }
146}
147
148#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
149#[cfg_attr(feature = "serde-support", derive(serde::Serialize, serde::Deserialize))]
150pub enum DataRedundancyType {
151 #[default]
152 #[cfg_attr(feature = "serde-support", serde(rename = "LRS"))]
153 LRS,
154
155 #[cfg_attr(feature = "serde-support", serde(rename = "ZRS"))]
156 ZRS,
157}
158
159impl DataRedundancyType {
160 pub fn as_str(&self) -> &str {
161 match self {
162 DataRedundancyType::LRS => "LRS",
163 DataRedundancyType::ZRS => "ZRS",
164 }
165 }
166}
167
168impl Display for DataRedundancyType {
169 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
170 match self {
171 DataRedundancyType::LRS => write!(f, "LRS"),
172 DataRedundancyType::ZRS => write!(f, "ZRS"),
173 }
174 }
175}
176
177impl AsRef<str> for DataRedundancyType {
178 fn as_ref(&self) -> &str {
179 self.as_str()
180 }
181}
182
183impl TryFrom<&str> for DataRedundancyType {
184 type Error = crate::error::Error;
185
186 fn try_from(value: &str) -> std::result::Result<Self, Self::Error> {
187 match value {
188 "LRS" => Ok(DataRedundancyType::LRS),
189 "ZRS" => Ok(DataRedundancyType::ZRS),
190 _ => Err(Error::Other(format!("Invalid DataRedundancyType value: {}", value))),
191 }
192 }
193}
194
195impl TryFrom<String> for DataRedundancyType {
196 type Error = crate::error::Error;
197
198 fn try_from(value: String) -> std::result::Result<Self, Self::Error> {
199 Self::try_from(value.as_str())
200 }
201}
202
203impl TryFrom<&String> for DataRedundancyType {
204 type Error = crate::error::Error;
205
206 fn try_from(value: &String) -> std::result::Result<Self, Self::Error> {
207 Self::try_from(value.as_str())
208 }
209}
210
211pub struct KvPair {
212 pub key: String,
213 pub value: String,
214}
215
216#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
223#[cfg_attr(feature = "serde-support", derive(serde::Serialize, serde::Deserialize))]
224pub enum OnOff {
225 #[cfg_attr(feature = "serde-support", serde(rename = "Enabled"))]
226 Enabled,
227
228 #[default]
229 #[cfg_attr(feature = "serde-support", serde(rename = "Disabled"))]
230 Disabled,
231}
232
233impl OnOff {
234 pub fn as_str(&self) -> &str {
235 match self {
236 OnOff::Enabled => "Enabled",
237 OnOff::Disabled => "Disabled",
238 }
239 }
240}
241
242impl AsRef<str> for OnOff {
243 fn as_ref(&self) -> &str {
244 self.as_str()
245 }
246}
247
248impl Display for OnOff {
249 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
250 write!(f, "{}", self.as_str())
251 }
252}
253
254impl TryFrom<&str> for OnOff {
255 type Error = crate::error::Error;
256
257 fn try_from(value: &str) -> std::result::Result<Self, Self::Error> {
258 match value {
259 "Enabled" => Ok(OnOff::Enabled),
260 "Disabled" => Ok(OnOff::Disabled),
261 _ => Err(Error::Other(format!("Invalid CrossRegionReplication value: {}", value))),
262 }
263 }
264}
265
266impl TryFrom<String> for OnOff {
267 type Error = crate::error::Error;
268
269 fn try_from(value: String) -> std::result::Result<Self, Self::Error> {
270 Self::try_from(value.as_str())
271 }
272}
273
274impl TryFrom<&String> for OnOff {
275 type Error = crate::error::Error;
276
277 fn try_from(value: &String) -> std::result::Result<Self, Self::Error> {
278 Self::try_from(value.as_str())
279 }
280}
281
282pub type CrossRegionReplication = OnOff;
284pub type TransferAcceleration = OnOff;
285pub type AccessMonitor = OnOff;
286
287#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
291#[cfg_attr(feature = "serde-support", derive(serde::Serialize, serde::Deserialize))]
292pub enum Versioning {
293 #[cfg_attr(feature = "serde-support", serde(rename = "Enabled"))]
294 Enabled,
295
296 #[default]
297 #[cfg_attr(feature = "serde-support", serde(rename = "Suspended"))]
298 Suspended,
299}
300
301impl Versioning {
302 pub fn as_str(&self) -> &str {
303 match self {
304 Versioning::Enabled => "Enabled",
305 Versioning::Suspended => "Disabled",
306 }
307 }
308}
309
310impl AsRef<str> for Versioning {
311 fn as_ref(&self) -> &str {
312 self.as_str()
313 }
314}
315
316impl Display for Versioning {
317 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
318 write!(f, "{}", self.as_str())
319 }
320}
321
322impl TryFrom<&str> for Versioning {
323 type Error = crate::error::Error;
324
325 fn try_from(value: &str) -> std::result::Result<Self, Self::Error> {
326 match value {
327 "Enabled" => Ok(Versioning::Enabled),
328 "Disabled" => Ok(Versioning::Suspended),
329 _ => Err(Error::Other(format!("Invalid Versioning value: {}", value))),
330 }
331 }
332}
333
334impl TryFrom<String> for Versioning {
335 type Error = crate::error::Error;
336
337 fn try_from(value: String) -> std::result::Result<Self, Self::Error> {
338 Self::try_from(value.as_str())
339 }
340}
341
342impl TryFrom<&String> for Versioning {
343 type Error = crate::error::Error;
344
345 fn try_from(value: &String) -> std::result::Result<Self, Self::Error> {
346 Self::try_from(value.as_str())
347 }
348}
349
350#[derive(Debug, Clone, PartialEq, Eq, Default)]
351#[cfg_attr(feature = "serde-support", derive(serde::Serialize, serde::Deserialize))]
352pub enum ServerSideEncryptionAlgorithm {
353 #[default]
354 #[cfg_attr(feature = "serde-support", serde(rename = "KMS"))]
355 KMS,
356
357 #[cfg_attr(feature = "serde-support", serde(rename = "AES256"))]
358 AES256,
359
360 #[cfg_attr(feature = "serde-support", serde(rename = "SM4"))]
361 SM4,
362}
363
364impl ServerSideEncryptionAlgorithm {
365 pub fn as_str(&self) -> &str {
366 match self {
367 ServerSideEncryptionAlgorithm::KMS => "KMS",
368 ServerSideEncryptionAlgorithm::AES256 => "AES256",
369 ServerSideEncryptionAlgorithm::SM4 => "SM4",
370 }
371 }
372}
373
374impl AsRef<str> for ServerSideEncryptionAlgorithm {
375 fn as_ref(&self) -> &str {
376 self.as_str()
377 }
378}
379
380impl Display for ServerSideEncryptionAlgorithm {
381 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
382 write!(f, "{}", self.as_str())
383 }
384}
385
386impl TryFrom<&str> for ServerSideEncryptionAlgorithm {
387 type Error = crate::error::Error;
388
389 fn try_from(value: &str) -> std::result::Result<Self, Self::Error> {
390 match value {
391 "KMS" => Ok(ServerSideEncryptionAlgorithm::KMS),
392 "AES256" => Ok(ServerSideEncryptionAlgorithm::AES256),
393 "SM4" => Ok(ServerSideEncryptionAlgorithm::SM4),
394 _ => Err(Error::Other(format!("Invalid ServerSideEncryptionAlgorithm value: {}", value))),
395 }
396 }
397}
398
399impl TryFrom<String> for ServerSideEncryptionAlgorithm {
400 type Error = crate::error::Error;
401
402 fn try_from(value: String) -> std::result::Result<Self, Self::Error> {
403 Self::try_from(value.as_str())
404 }
405}
406
407impl TryFrom<&String> for ServerSideEncryptionAlgorithm {
408 type Error = crate::error::Error;
409
410 fn try_from(value: &String) -> std::result::Result<Self, Self::Error> {
411 Self::try_from(value.as_str())
412 }
413}
414
415#[derive(Debug, Clone, Default, Eq, PartialEq)]
416#[cfg_attr(feature = "serde-support", derive(serde::Serialize, serde::Deserialize))]
417#[cfg_attr(feature = "serde-camelcase", serde(rename_all = "camelCase"))]
418pub struct ServerSideEncryptionRule {
419 pub sse_algorithm: ServerSideEncryptionAlgorithm,
420
421 pub kms_master_key_id: Option<String>,
423 pub kms_data_encryption: Option<String>,
424}
425
426#[derive(Debug, Clone, Default, Eq, PartialEq)]
428#[cfg_attr(feature = "serde-support", derive(serde::Serialize, serde::Deserialize))]
429pub enum ObjectType {
430 #[default]
432 #[cfg_attr(feature = "serde-support", serde(rename = "Normal"))]
433 Normal,
434
435 #[cfg_attr(feature = "serde-support", serde(rename = "Multipart"))]
437 Multipart,
438
439 #[cfg_attr(feature = "serde-support", serde(rename = "Appendable"))]
441 Appendable,
442
443 #[cfg_attr(feature = "serde-support", serde(rename = "Symlink"))]
445 Symlink,
446}
447
448impl ObjectType {
449 pub fn as_str(&self) -> &str {
450 match self {
451 ObjectType::Normal => "Normal",
452 ObjectType::Multipart => "Multipart",
453 ObjectType::Appendable => "Appendable",
454 ObjectType::Symlink => "Symlink",
455 }
456 }
457}
458
459impl AsRef<str> for ObjectType {
460 fn as_ref(&self) -> &str {
461 self.as_str()
462 }
463}
464
465impl TryFrom<&str> for ObjectType {
466 type Error = crate::error::Error;
467
468 fn try_from(value: &str) -> std::result::Result<Self, Self::Error> {
469 match value {
470 "Normal" => Ok(ObjectType::Normal),
471 "Multipart" => Ok(ObjectType::Multipart),
472 "Appendable" => Ok(ObjectType::Appendable),
473 "Symlink" => Ok(ObjectType::Symlink),
474 _ => Err(Error::Other(format!("Invalid ObjectType value: {}", value))),
475 }
476 }
477}
478
479impl TryFrom<String> for ObjectType {
480 type Error = crate::error::Error;
481
482 fn try_from(value: String) -> std::result::Result<Self, Self::Error> {
483 Self::try_from(value.as_str())
484 }
485}
486
487impl TryFrom<&String> for ObjectType {
488 type Error = crate::error::Error;
489
490 fn try_from(value: &String) -> std::result::Result<Self, Self::Error> {
491 Self::try_from(value.as_str())
492 }
493}
494
495#[derive(Debug, Clone, Copy, Default, Eq, PartialEq)]
497#[cfg_attr(feature = "serde-support", derive(serde::Serialize, serde::Deserialize))]
498pub enum MetadataDirective {
499 #[default]
503 #[cfg_attr(feature = "serde-support", serde(rename = "COPY"))]
504 Copy,
505
506 #[cfg_attr(feature = "serde-support", serde(rename = "REPLACE"))]
508 Replace,
509}
510
511impl MetadataDirective {
512 pub fn as_str(&self) -> &str {
513 match self {
514 MetadataDirective::Copy => "COPY",
515 MetadataDirective::Replace => "REPLACE",
516 }
517 }
518}
519
520impl AsRef<str> for MetadataDirective {
521 fn as_ref(&self) -> &str {
522 self.as_str()
523 }
524}
525
526impl Display for MetadataDirective {
527 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
528 match self {
529 MetadataDirective::Copy => write!(f, "COPY"),
530 MetadataDirective::Replace => write!(f, "REPLACE"),
531 }
532 }
533}
534
535impl TryFrom<&str> for MetadataDirective {
536 type Error = crate::error::Error;
537
538 fn try_from(value: &str) -> std::result::Result<Self, Self::Error> {
539 match value {
540 "COPY" => Ok(MetadataDirective::Copy),
541 "REPLACE" => Ok(MetadataDirective::Replace),
542 _ => Err(Error::Other(format!("Invalid MetadataDirective value: {}", value))),
543 }
544 }
545}
546
547impl TryFrom<String> for MetadataDirective {
548 type Error = crate::error::Error;
549
550 fn try_from(value: String) -> std::result::Result<Self, Self::Error> {
551 Self::try_from(value.as_str())
552 }
553}
554
555impl TryFrom<&String> for MetadataDirective {
556 type Error = crate::error::Error;
557
558 fn try_from(value: &String) -> std::result::Result<Self, Self::Error> {
559 Self::try_from(value.as_str())
560 }
561}
562
563#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
565#[cfg_attr(feature = "serde-support", derive(serde::Serialize, serde::Deserialize))]
566pub enum TagDirective {
567 #[default]
569 #[cfg_attr(feature = "serde-support", serde(rename = "Copy"))]
570 Copy,
571
572 #[cfg_attr(feature = "serde-support", serde(rename = "Replace"))]
574 Replace,
575}
576
577impl TagDirective {
578 pub fn as_str(&self) -> &str {
579 match self {
580 TagDirective::Copy => "Copy",
581 TagDirective::Replace => "Replace",
582 }
583 }
584}
585
586impl AsRef<str> for TagDirective {
587 fn as_ref(&self) -> &str {
588 self.as_str()
589 }
590}
591
592impl Display for TagDirective {
593 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
594 match self {
595 TagDirective::Copy => write!(f, "Copy"),
596 TagDirective::Replace => write!(f, "Replace"),
597 }
598 }
599}
600
601impl TryFrom<&str> for TagDirective {
602 type Error = crate::error::Error;
603
604 fn try_from(value: &str) -> std::result::Result<Self, Self::Error> {
605 match value {
606 "Copy" => Ok(TagDirective::Copy),
607 "Replace" => Ok(TagDirective::Replace),
608 _ => Err(Error::Other(format!("Invalid MetadataDirective value: {}", value))),
609 }
610 }
611}
612
613impl TryFrom<String> for TagDirective {
614 type Error = crate::error::Error;
615
616 fn try_from(value: String) -> std::result::Result<Self, Self::Error> {
617 Self::try_from(value.as_str())
618 }
619}
620
621impl TryFrom<&String> for TagDirective {
622 type Error = crate::error::Error;
623
624 fn try_from(value: &String) -> std::result::Result<Self, Self::Error> {
625 Self::try_from(value.as_str())
626 }
627}
628
629#[derive(Debug, Clone, Default)]
630#[cfg_attr(feature = "serde-support", derive(serde::Serialize, serde::Deserialize))]
631#[cfg_attr(feature = "serde-camelcase", serde(rename_all = "camelCase"))]
632pub struct VersionIdOnlyOptions {
633 pub version_id: Option<String>,
634}
635
636pub(crate) fn build_tag_string(tags: &HashMap<String, String>) -> String {
638 tags.iter()
639 .map(|(k, v)| {
640 if v.is_empty() {
641 urlencoding::encode(k).to_string()
642 } else {
643 format!("{}={}", urlencoding::encode(k), urlencoding::encode(v))
644 }
645 })
646 .collect::<Vec<_>>()
647 .join("&")
648}