use super::{tag::Tag, Status, StorageClass};
use serde::{Deserialize, Serialize};
pub mod builder {
use crate::oss::entities::{Status, StorageClass};
use super::{
AbortMultipartUpload, Expiration, Filter, LifecycleConfiguration,
NoncurrentVersionExpiration, Rule, Transition,
};
#[derive(Default)]
pub struct FilterBuilder {}
impl FilterBuilder {
pub fn new() -> Self {
Self::default()
}
pub fn build() -> Filter {
Filter::default()
}
}
#[derive(Default)]
pub struct ExpirationBuilder {
days: Option<i32>,
created_before_date: Option<String>,
expired_object_delete_marker: Option<bool>,
}
impl ExpirationBuilder {
pub fn new() -> Self {
Self::default()
}
pub fn with_days(mut self, value: i32) -> Self {
self.days = Some(value);
self
}
pub fn with_created_before_date(mut self, value: String) -> Self {
self.created_before_date = Some(value);
self
}
pub fn with_expired_object_delete_marker(mut self, value: bool) -> Self {
self.expired_object_delete_marker = Some(value);
self
}
pub fn build(&self) -> Expiration {
Expiration {
days: self.days,
created_before_date: self.created_before_date.clone(),
expired_object_delete_marker: self.expired_object_delete_marker,
}
}
}
#[derive(Default, Debug, Clone)]
pub struct TransitionBuilder {
days: Option<i32>,
storage_class: StorageClass,
is_access_time: Option<bool>,
return_to_std_when_visit: Option<bool>,
allow_small_file: Option<bool>,
}
impl TransitionBuilder {
pub fn new() -> Self {
Self::default()
}
pub fn with_days(mut self, value: i32) -> Self {
self.days = Some(value);
self
}
pub fn with_torage_class(mut self, value: StorageClass) -> Self {
self.storage_class = value;
self
}
pub fn with_is_access_time(mut self, value: bool) -> Self {
self.is_access_time = Some(value);
self
}
pub fn with_return_to_std_when_visit(mut self, value: bool) -> Self {
self.return_to_std_when_visit = Some(value);
self
}
pub fn with_allow_small_file(mut self, value: bool) -> Self {
self.allow_small_file = Some(value);
self
}
pub fn build(&self) -> Transition {
Transition {
days: self.days,
storage_class: self.storage_class.clone(),
is_access_time: self.is_access_time,
return_to_std_when_visit: self.return_to_std_when_visit,
allow_small_file: self.allow_small_file,
}
}
}
#[derive(Default, Debug, Clone)]
pub struct RuleBuilder<'a> {
id: &'a str,
prefix: &'a str,
status: Status,
transition: Option<Vec<Transition>>,
filter: Option<Filter>,
expiration: Option<Expiration>,
noncurrent_version_expiration: Option<NoncurrentVersionExpiration>,
abort_multipart_upload: Option<AbortMultipartUpload>,
}
impl<'a> RuleBuilder<'a> {
pub fn new() -> Self {
Self::default()
}
pub fn with_id(mut self, value: &'a str) -> Self {
self.id = value;
self
}
pub fn with_prefix(mut self, value: &'a str) -> Self {
self.prefix = value;
self
}
pub fn with_status(mut self, value: Status) -> Self {
self.status = value;
self
}
pub fn with_transition(mut self, value: Transition) -> Self {
let transitions = if let Some(mut transitions) = self.transition {
transitions.push(value);
transitions
} else {
vec![value]
};
self.transition = Some(transitions);
self
}
pub fn with_filter(mut self, value: Filter) -> Self {
self.filter = Some(value);
self
}
pub fn with_expiration(mut self, value: Expiration) -> Self {
self.expiration = Some(value);
self
}
pub fn with_noncurrent_version_expiration(mut self, days: i32) -> Self {
self.noncurrent_version_expiration = Some(NoncurrentVersionExpiration {
noncurrent_days: days,
});
self
}
pub fn with_abort_multipart_upload(mut self, days: i32) -> Self {
self.abort_multipart_upload = Some(AbortMultipartUpload { days });
self
}
pub fn build(&self) -> Rule {
Rule {
id: self.id.into(),
prefix: self.prefix.into(),
status: self.status.clone(),
transition: self.transition.clone(),
filter: self.filter.clone(),
expiration: self.expiration.clone(),
noncurrent_version_expiration: self.noncurrent_version_expiration.clone(),
abort_multipart_upload: self.abort_multipart_upload.clone(),
}
}
}
#[derive(Default, Debug, Clone)]
pub struct LifecycleConfigurationBuilder {
rules: Vec<Rule>,
}
impl LifecycleConfigurationBuilder {
pub fn new() -> Self {
Self::default()
}
pub fn with_rule(mut self, value: Rule) -> Self {
self.rules.push(value);
self
}
pub fn build(&self) -> LifecycleConfiguration {
LifecycleConfiguration {
rule: self.rules.clone(),
}
}
}
}
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
pub struct Not {
#[serde(rename = "Prefix")]
pub prefix: String,
#[serde(rename = "Tag")]
pub tag: Tag,
}
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
pub struct Filter {
#[serde(rename = "Not", skip_serializing_if = "Option::is_none")]
pub not: Option<Not>,
#[serde(
rename = "ObjectSizeGreaterThan",
skip_serializing_if = "Option::is_none"
)]
pub object_size_greater_than: Option<i32>,
#[serde(rename = "ObjectSizeLessThan", skip_serializing_if = "Option::is_none")]
pub object_size_less_than: Option<i32>,
}
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
pub struct AbortMultipartUpload {
#[serde(rename = "Days")]
pub days: i32,
}
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
pub struct NoncurrentVersionTransition {
#[serde(rename = "NoncurrentDays", skip_serializing_if = "Option::is_none")]
pub noncurrent_days: Option<bool>,
#[serde(rename = "StorageClass")]
pub storage_class: StorageClass,
}
#[derive(Debug, Serialize, Deserialize, Default, Clone)]
pub struct Transition {
#[serde(rename = "Days")]
pub days: Option<i32>,
#[serde(rename = "StorageClass")]
pub storage_class: StorageClass,
#[serde(rename = "IsAccessTime", skip_serializing_if = "Option::is_none")]
pub is_access_time: Option<bool>,
#[serde(
rename = "ReturnToStdWhenVisit",
skip_serializing_if = "Option::is_none"
)]
pub return_to_std_when_visit: Option<bool>,
#[serde(rename = "AllowSmallFile", skip_serializing_if = "Option::is_none")]
pub allow_small_file: Option<bool>,
}
#[derive(Debug, Serialize, Deserialize, Default, Clone)]
pub struct Expiration {
#[serde(rename = "Days", skip_serializing_if = "Option::is_none")]
pub days: Option<i32>,
#[serde(rename = "CreatedBeforeDate", skip_serializing_if = "Option::is_none")]
pub created_before_date: Option<String>,
#[serde(
rename = "ExpiredObjectDeleteMarker",
skip_serializing_if = "Option::is_none"
)]
pub expired_object_delete_marker: Option<bool>,
}
#[derive(Debug, Serialize, Deserialize, Default, Clone)]
pub struct NoncurrentVersionExpiration {
#[serde(rename = "NoncurrentDays")]
pub noncurrent_days: i32,
}
#[derive(Debug, Serialize, Deserialize, Default, Clone)]
pub struct Rule {
#[serde(rename = "ID")]
pub id: String,
#[serde(rename = "Prefix")]
pub prefix: String,
#[serde(rename = "Status")]
pub status: Status,
#[serde(rename = "Transition", skip_serializing_if = "Option::is_none")]
pub transition: Option<Vec<Transition>>,
#[serde(rename = "Filter", skip_serializing_if = "Option::is_none")]
pub filter: Option<Filter>,
#[serde(rename = "Expiration", skip_serializing_if = "Option::is_none")]
pub expiration: Option<Expiration>,
#[serde(
rename = "NoncurrentVersionExpiration",
skip_serializing_if = "Option::is_none"
)]
pub noncurrent_version_expiration: Option<NoncurrentVersionExpiration>,
#[serde(
rename = "AbortMultipartUpload",
skip_serializing_if = "Option::is_none"
)]
pub abort_multipart_upload: Option<AbortMultipartUpload>,
}
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct LifecycleConfiguration {
#[serde(rename = "Rule")]
pub rule: Vec<Rule>,
}
#[cfg(test)]
mod tests {
use crate::oss::entities::Status;
use super::builder::*;
use super::*;
#[test]
fn lifecycle_configuration_return_parse_1() {
let xml_content = r#"<?xml version="1.0" encoding="UTF-8"?>
<LifecycleConfiguration>
<Rule>
<ID>delete after one day</ID>
<Prefix>logs1/</Prefix>
<Status>Enabled</Status>
<Expiration>
<Days>1</Days>
</Expiration>
</Rule>
<Rule>
<ID>mtime transition1</ID>
<Prefix>logs2/</Prefix>
<Status>Enabled</Status>
<Transition>
<Days>30</Days>
<StorageClass>IA</StorageClass>
</Transition>
</Rule>
<Rule>
<ID>mtime transition2</ID>
<Prefix>logs3/</Prefix>
<Status>Enabled</Status>
<Transition>
<Days>30</Days>
<StorageClass>IA</StorageClass>
<IsAccessTime>false</IsAccessTime>
</Transition>
</Rule>
</LifecycleConfiguration>"#;
let object: LifecycleConfiguration = quick_xml::de::from_str(xml_content).unwrap();
let left = "mtime transition1";
let right = &object.rule[1].id;
assert_eq!(left, right);
}
#[test]
fn lifecycle_configuration_return_parse_2() {
let xml_content = r#"<?xml version="1.0" encoding="UTF-8"?>
<LifecycleConfiguration>
<Rule>
<ID>atime transition1</ID>
<Prefix>logs1/</Prefix>
<Status>Enabled</Status>
<Transition>
<Days>30</Days>
<StorageClass>IA</StorageClass>
<IsAccessTime>true</IsAccessTime>
<ReturnToStdWhenVisit>false</ReturnToStdWhenVisit>
</Transition>
<AtimeBase>1631698332</AtimeBase>
</Rule>
<Rule>
<ID>atime transition2</ID>
<Prefix>logs2/</Prefix>
<Status>Enabled</Status>
<NoncurrentVersionTransition>
<NoncurrentDays>10</NoncurrentDays>
<StorageClass>IA</StorageClass>
<IsAccessTime>true</IsAccessTime>
<ReturnToStdWhenVisit>false</ReturnToStdWhenVisit>
</NoncurrentVersionTransition>
<AtimeBase>1631698332</AtimeBase>
</Rule>
</LifecycleConfiguration>"#;
let object: LifecycleConfiguration = quick_xml::de::from_str(xml_content).unwrap();
let left = "atime transition2";
let right = &object.rule[1].id;
assert_eq!(left, right);
}
#[test]
fn lifecycle_configuration_builder_1() {
let config = LifecycleConfigurationBuilder::new()
.with_rule(
RuleBuilder::new()
.with_id("rule")
.with_prefix("log")
.with_status(Status::Enabled)
.with_transition(
TransitionBuilder::new()
.with_days(30)
.with_torage_class(StorageClass::IA)
.build(),
)
.build(),
)
.build();
let left = "<LifecycleConfiguration><Rule><ID>rule</ID><Prefix>log</Prefix><Status>Enabled</Status><Transition><Days>30</Days><StorageClass>IA</StorageClass></Transition></Rule></LifecycleConfiguration>";
let right = quick_xml::se::to_string(&config).unwrap();
assert_eq!(left, right);
}
#[test]
fn lifecycle_configuration_builder_2() {
let config = LifecycleConfigurationBuilder::new()
.with_rule(
RuleBuilder::new()
.with_id("rule")
.with_prefix("log")
.with_status(Status::Enabled)
.with_expiration(ExpirationBuilder::new().with_days(90).build())
.build(),
)
.build();
let left = "<LifecycleConfiguration><Rule><ID>rule</ID><Prefix>log</Prefix><Status>Enabled</Status><Expiration><Days>90</Days></Expiration></Rule></LifecycleConfiguration>";
let right = quick_xml::se::to_string(&config).unwrap();
assert_eq!(left, right);
}
#[test]
fn lifecycle_configuration_builder_3() {
let config = LifecycleConfigurationBuilder::new()
.with_rule(
RuleBuilder::new()
.with_id("rule")
.with_prefix("log")
.with_status(Status::Enabled)
.with_transition(
TransitionBuilder::new()
.with_days(30)
.with_torage_class(StorageClass::IA)
.build(),
)
.with_transition(
TransitionBuilder::new()
.with_days(60)
.with_torage_class(StorageClass::Archive)
.build(),
)
.with_expiration(ExpirationBuilder::new().with_days(60).build())
.build(),
)
.build();
let left = "<LifecycleConfiguration><Rule><ID>rule</ID><Prefix>log</Prefix><Status>Enabled</Status><Transition><Days>30</Days><StorageClass>IA</StorageClass></Transition><Transition><Days>60</Days><StorageClass>Archive</StorageClass></Transition><Expiration><Days>60</Days></Expiration></Rule></LifecycleConfiguration>";
let right = quick_xml::se::to_string(&config).unwrap();
assert_eq!(left, right);
}
#[test]
fn lifecycle_configuration_builder_4() {
let config = LifecycleConfigurationBuilder::new()
.with_rule(
RuleBuilder::new()
.with_id("rule")
.with_prefix("")
.with_status(Status::Enabled)
.with_expiration(
ExpirationBuilder::new()
.with_expired_object_delete_marker(true)
.build(),
)
.with_noncurrent_version_expiration(5)
.build(),
)
.build();
let left = "<LifecycleConfiguration><Rule><ID>rule</ID><Prefix/><Status>Enabled</Status><Expiration><ExpiredObjectDeleteMarker>true</ExpiredObjectDeleteMarker></Expiration><NoncurrentVersionExpiration><NoncurrentDays>5</NoncurrentDays></NoncurrentVersionExpiration></Rule></LifecycleConfiguration>";
let right = quick_xml::se::to_string(&config).unwrap();
assert_eq!(left, right);
}
#[test]
fn lifecycle_configuration_builder_5() {
let config = LifecycleConfigurationBuilder::new()
.with_rule(
RuleBuilder::new()
.with_id("rule")
.with_prefix("log")
.with_status(Status::Enabled)
.with_transition(
TransitionBuilder::new()
.with_days(30)
.with_torage_class(StorageClass::IA)
.with_is_access_time(true)
.with_return_to_std_when_visit(true)
.build(),
)
.build(),
)
.build();
let left = "<LifecycleConfiguration><Rule><ID>rule</ID><Prefix>log</Prefix><Status>Enabled</Status><Transition><Days>30</Days><StorageClass>IA</StorageClass><IsAccessTime>true</IsAccessTime><ReturnToStdWhenVisit>true</ReturnToStdWhenVisit></Transition></Rule></LifecycleConfiguration>";
let right = quick_xml::se::to_string(&config).unwrap();
assert_eq!(left, right);
}
#[test]
fn lifecycle_configuration_builder_6() {
let config = LifecycleConfigurationBuilder::new()
.with_rule(
RuleBuilder::new()
.with_id("rule")
.with_prefix("/")
.with_status(Status::Enabled)
.with_abort_multipart_upload(30)
.build(),
)
.build();
let left = "<LifecycleConfiguration><Rule><ID>rule</ID><Prefix>/</Prefix><Status>Enabled</Status><AbortMultipartUpload><Days>30</Days></AbortMultipartUpload></Rule></LifecycleConfiguration>";
let right = quick_xml::se::to_string(&config).unwrap();
assert_eq!(left, right);
}
#[test]
fn lifecycle_configuration_builder_7() {
let config = LifecycleConfigurationBuilder::new()
.with_rule(
RuleBuilder::new()
.with_id("rule")
.with_prefix("/")
.with_status(Status::Enabled)
.with_abort_multipart_upload(30)
.build(),
)
.build();
let left = "<LifecycleConfiguration><Rule><ID>rule</ID><Prefix>/</Prefix><Status>Enabled</Status><AbortMultipartUpload><Days>30</Days></AbortMultipartUpload></Rule></LifecycleConfiguration>";
let right = quick_xml::se::to_string(&config).unwrap();
assert_eq!(left, right);
}
#[test]
fn lifecycle_configuration_builder_8() {
let config = LifecycleConfigurationBuilder::new()
.with_rule(
RuleBuilder::new()
.with_id("Rule1")
.with_prefix("dir1")
.with_expiration(ExpirationBuilder::new().with_days(180).build())
.build(),
)
.with_rule(
RuleBuilder::new()
.with_id("Rule2")
.with_prefix("dir1/dir2")
.with_status(Status::Enabled)
.with_expiration(ExpirationBuilder::new().with_days(30).build())
.build(),
)
.build();
let right = quick_xml::se::to_string(&config).unwrap();
let left = r#"<LifecycleConfiguration><Rule><ID>Rule1</ID><Prefix>dir1</Prefix><Status>Disabled</Status><Expiration><Days>180</Days></Expiration></Rule><Rule><ID>Rule2</ID><Prefix>dir1/dir2</Prefix><Status>Enabled</Status><Expiration><Days>30</Days></Expiration></Rule></LifecycleConfiguration>"#;
assert_eq!(left, right);
}
}