From 9726e1c3fae083cdc1081d864cbd36e7d5793ada Mon Sep 17 00:00:00 2001 From: Nugine Date: Sat, 14 Dec 2024 14:18:10 +0800 Subject: [PATCH 1/2] feat(codegen/dto): patch `Tag` --- codegen/src/v1/aws_conv.rs | 1 + codegen/src/v1/dto.rs | 15 +++++++++++++++ crates/s3s-aws/src/conv/builtin.rs | 20 ++++++++++++++++++++ crates/s3s-aws/src/conv/generated.rs | 19 ------------------- crates/s3s/src/dto/generated.rs | 16 ++++++++++------ crates/s3s/src/xml/generated.rs | 13 +++++++------ crates/s3s/tests/xml.rs | 4 ++-- 7 files changed, 55 insertions(+), 33 deletions(-) diff --git a/codegen/src/v1/aws_conv.rs b/codegen/src/v1/aws_conv.rs index a4fa3a0d..37f00ada 100644 --- a/codegen/src/v1/aws_conv.rs +++ b/codegen/src/v1/aws_conv.rs @@ -27,6 +27,7 @@ pub fn codegen(ops: &Operations, rust_types: &RustTypes) { "SelectObjectContentRequest" => continue, "SelectObjectContentInput" => continue, "AssumeRoleOutput" => continue, + "Tag" => continue, _ if super::sts::NAMES.iter().any(|n| n.eq_ignore_ascii_case(name)) => continue, _ => {} } diff --git a/codegen/src/v1/dto.rs b/codegen/src/v1/dto.rs index e0c97a82..d03e8216 100644 --- a/codegen/src/v1/dto.rs +++ b/codegen/src/v1/dto.rs @@ -246,6 +246,21 @@ pub fn collect_rust_types(model: &smithy::Model, ops: &Operations) -> RustTypes } fn patch_types(space: &mut RustTypes) { + // patch Tag + { + let Some(rust::Type::Struct(ty)) = space.get_mut("Tag") else { panic!() }; + for field in &mut ty.fields { + if field.name == "key" { + field.is_required = false; + field.option_type = true; + } + if field.name == "value" { + field.is_required = false; + field.option_type = true; + } + } + } + // patch LifecycleExpiration { let Some(rust::Type::Struct(ty)) = space.get_mut("LifecycleExpiration") else { panic!() }; diff --git a/crates/s3s-aws/src/conv/builtin.rs b/crates/s3s-aws/src/conv/builtin.rs index 4b982611..f3147614 100644 --- a/crates/s3s-aws/src/conv/builtin.rs +++ b/crates/s3s-aws/src/conv/builtin.rs @@ -191,3 +191,23 @@ impl AwsConversion for s3s::dto::SelectObjectContentInput { .map_err(S3Error::internal_error) } } + +impl AwsConversion for s3s::dto::Tag { + type Target = aws_sdk_s3::types::Tag; + + type Error = S3Error; + + fn try_from_aws(x: Self::Target) -> S3Result { + Ok(Self { + key: Some(try_from_aws(x.key)?), + value: Some(try_from_aws(x.value)?), + }) + } + + fn try_into_aws(x: Self) -> S3Result { + let mut y = Self::Target::builder(); + y = y.set_key(try_into_aws(x.key)?); + y = y.set_value(try_into_aws(x.value)?); + y.build().map_err(S3Error::internal_error) + } +} diff --git a/crates/s3s-aws/src/conv/generated.rs b/crates/s3s-aws/src/conv/generated.rs index 4fd00c4f..f3812cd3 100644 --- a/crates/s3s-aws/src/conv/generated.rs +++ b/crates/s3s-aws/src/conv/generated.rs @@ -8236,25 +8236,6 @@ impl AwsConversion for s3s::dto::StorageClassAnalysisSchemaVersion { } } -impl AwsConversion for s3s::dto::Tag { - type Target = aws_sdk_s3::types::Tag; - type Error = S3Error; - - fn try_from_aws(x: Self::Target) -> S3Result { - Ok(Self { - key: try_from_aws(x.key)?, - value: try_from_aws(x.value)?, - }) - } - - fn try_into_aws(x: Self) -> S3Result { - let mut y = Self::Target::builder(); - y = y.set_key(Some(try_into_aws(x.key)?)); - y = y.set_value(Some(try_into_aws(x.value)?)); - y.build().map_err(S3Error::internal_error) - } -} - impl AwsConversion for s3s::dto::Tagging { type Target = aws_sdk_s3::types::Tagging; type Error = S3Error; diff --git a/crates/s3s/src/dto/generated.rs b/crates/s3s/src/dto/generated.rs index 6eff7826..4c858cfa 100644 --- a/crates/s3s/src/dto/generated.rs +++ b/crates/s3s/src/dto/generated.rs @@ -1,4 +1,4 @@ -//! Auto generated by `codegen/src/v1/dto.rs:354` +//! Auto generated by `codegen/src/v1/dto.rs:369` #![allow(clippy::empty_structs_with_brackets)] #![allow(clippy::too_many_lines)] @@ -18349,19 +18349,23 @@ impl FromStr for StorageClassAnalysisSchemaVersion { pub type Suffix = String; ///

A container of a key value name pair.

-#[derive(Clone, PartialEq)] +#[derive(Clone, Default, PartialEq)] pub struct Tag { ///

Name of the object key.

- pub key: ObjectKey, + pub key: Option, ///

Value of the tag.

- pub value: Value, + pub value: Option, } impl fmt::Debug for Tag { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut d = f.debug_struct("Tag"); - d.field("key", &self.key); - d.field("value", &self.value); + if let Some(ref val) = self.key { + d.field("key", val); + } + if let Some(ref val) = self.value { + d.field("value", val); + } d.finish_non_exhaustive() } } diff --git a/crates/s3s/src/xml/generated.rs b/crates/s3s/src/xml/generated.rs index a793d482..01c61a18 100644 --- a/crates/s3s/src/xml/generated.rs +++ b/crates/s3s/src/xml/generated.rs @@ -8665,8 +8665,12 @@ impl<'xml> DeserializeContent<'xml> for StorageClassAnalysisSchemaVersion { } impl SerializeContent for Tag { fn serialize_content(&self, s: &mut Serializer) -> SerResult { - s.content("Key", &self.key)?; - s.content("Value", &self.value)?; + if let Some(ref val) = self.key { + s.content("Key", val)?; + } + if let Some(ref val) = self.value { + s.content("Value", val)?; + } Ok(()) } } @@ -8692,10 +8696,7 @@ impl<'xml> DeserializeContent<'xml> for Tag { } _ => Err(DeError::UnexpectedTagName), })?; - Ok(Self { - key: key.ok_or(DeError::MissingField)?, - value: value.ok_or(DeError::MissingField)?, - }) + Ok(Self { key, value }) } } impl SerializeContent for Tagging { diff --git a/crates/s3s/tests/xml.rs b/crates/s3s/tests/xml.rs index a6a57a04..e3a48a31 100644 --- a/crates/s3s/tests/xml.rs +++ b/crates/s3s/tests/xml.rs @@ -181,8 +181,8 @@ fn tagging() { assert_eq!(ans.tag_set.len(), 1); let tag = &ans.tag_set[0]; - assert_eq!(tag.key, "Key4"); - assert_eq!(tag.value, "Value4"); + assert_eq!(tag.key.as_deref(), Some("Key4")); + assert_eq!(tag.value.as_deref(), Some("Value4")); test_serde(&ans); } From 787319c5a6c6df905dc8d1b4a140635fef75d42d Mon Sep 17 00:00:00 2001 From: Nugine Date: Sat, 14 Dec 2024 13:22:12 +0800 Subject: [PATCH 2/2] feat(codegen/minio): `DeleteReplication` --- codegen/src/v1/aws_conv.rs | 6 ++- codegen/src/v1/dto.rs | 1 + codegen/src/v1/rust.rs | 2 + codegen/src/v1/xml.rs | 1 + crates/s3s/src/dto/generated.rs | 2 +- crates/s3s/tests/xml.rs | 96 +++++++++++++++++++++++++++------ justfile | 2 +- model/minio-patches.json | 45 ++++++++++++++++ 8 files changed, 135 insertions(+), 20 deletions(-) diff --git a/codegen/src/v1/aws_conv.rs b/codegen/src/v1/aws_conv.rs index 37f00ada..e715402f 100644 --- a/codegen/src/v1/aws_conv.rs +++ b/codegen/src/v1/aws_conv.rs @@ -38,7 +38,11 @@ pub fn codegen(ops: &Operations, rust_types: &RustTypes) { rust::Type::Timestamp(_) => continue, rust::Type::List(_) => continue, rust::Type::Map(_) => continue, - rust::Type::StrEnum(_) => {} + rust::Type::StrEnum(ty) => { + if ty.is_custom_extension { + continue; + } + } rust::Type::Struct(ty) => { if ty.is_custom_extension { continue; diff --git a/codegen/src/v1/dto.rs b/codegen/src/v1/dto.rs index d03e8216..d6e0a920 100644 --- a/codegen/src/v1/dto.rs +++ b/codegen/src/v1/dto.rs @@ -125,6 +125,7 @@ pub fn collect_rust_types(model: &smithy::Model, ops: &Operations) -> RustTypes name: rs_shape_name.clone(), variants, doc: shape.traits.doc().map(o), + is_custom_extension: shape.traits.minio(), }); insert(rs_shape_name, ty); } diff --git a/codegen/src/v1/rust.rs b/codegen/src/v1/rust.rs index 06826543..621cac33 100644 --- a/codegen/src/v1/rust.rs +++ b/codegen/src/v1/rust.rs @@ -54,6 +54,8 @@ pub struct StrEnum { pub name: String, pub variants: Vec, pub doc: Option, + + pub is_custom_extension: bool, } #[derive(Debug, Clone)] diff --git a/codegen/src/v1/xml.rs b/codegen/src/v1/xml.rs index 4797c1c6..0589b803 100644 --- a/codegen/src/v1/xml.rs +++ b/codegen/src/v1/xml.rs @@ -427,6 +427,7 @@ fn codegen_xml_serde_content_struct(_ops: &Operations, rust_types: &RustTypes, t if field.option_type { g!("{},", field.name); } else { + // g!("{0}: {0}.ok_or_else(||dbg!(DeError::MissingField))?,", field.name); g!("{0}: {0}.ok_or(DeError::MissingField)?,", field.name); } } diff --git a/crates/s3s/src/dto/generated.rs b/crates/s3s/src/dto/generated.rs index 4c858cfa..eaa922f5 100644 --- a/crates/s3s/src/dto/generated.rs +++ b/crates/s3s/src/dto/generated.rs @@ -1,4 +1,4 @@ -//! Auto generated by `codegen/src/v1/dto.rs:369` +//! Auto generated by `codegen/src/v1/dto.rs:370` #![allow(clippy::empty_structs_with_brackets)] #![allow(clippy::too_many_lines)] diff --git a/crates/s3s/tests/xml.rs b/crates/s3s/tests/xml.rs index e3a48a31..d176bca6 100644 --- a/crates/s3s/tests/xml.rs +++ b/crates/s3s/tests/xml.rs @@ -1,6 +1,8 @@ use s3s::xml; use std::fmt; +use std::ops::Not; +use std::sync::LazyLock; use stdx::default::default; @@ -276,20 +278,80 @@ fn assume_role_output() { test_serde(&val); } -// #[test] -// fn minio_versioning_configuration() { -// let xml = r#" -// -// Enabled -// -// a -// -// -// b -// -// true -// -// "#; -// let val = deserialize::(xml.as_bytes()).unwrap(); -// test_serde(&val); -// } +fn git_branch() -> String { + let output = std::process::Command::new("git") + .args(["rev-parse", "--abbrev-ref", "HEAD"]) + .output() + .unwrap(); + let stdout = core::str::from_utf8(&output.stdout).unwrap(); + stdout.trim().to_owned() +} + +static IS_MINIO_BRANCH: LazyLock = LazyLock::new(|| { + matches!(git_branch().as_str(), "minio" | "feat/minio") // +}); + +#[test] +fn minio_versioning_configuration() { + if IS_MINIO_BRANCH.not() { + return; + } + + let xml = r#" + + Enabled + + a + + + b + + true + + "#; + let val = deserialize::(xml.as_bytes()).unwrap(); + test_serde(&val); +} + +#[test] +fn minio_delete_replication() { + if IS_MINIO_BRANCH.not() { + return; + } + + let xml = r#" + + + cte4oalu3vqltovlh28g + Enabled + 0 + + Enabled + + + Enabled + + + arn:minio:replication:us-east-1:e02ce029-7459-4be2-8267-064712b0ead4:buc2 + + + + + + + + + Enabled + + + + Enabled + + + + + + "#; + let val = deserialize::(xml.as_bytes()).unwrap(); + test_serde(&val); +} diff --git a/justfile b/justfile index 138b08b8..738eb725 100644 --- a/justfile +++ b/justfile @@ -26,7 +26,7 @@ model: uv run model/main.py update codegen: - cargo run -p s3s-codegen -- model/s3.json + cargo run -p s3s-codegen cargo fmt cargo check diff --git a/model/minio-patches.json b/model/minio-patches.json index 71e0014c..de8372aa 100644 --- a/model/minio-patches.json +++ b/model/minio-patches.json @@ -54,6 +54,51 @@ } } } + }, + "com.amazonaws.s3#ReplicationRule": { + "type": "structure", + "members": { + "DeleteReplication": { + "target": "com.amazonaws.s3#DeleteReplication", + "traits": { + "s3s#minio": "" + } + } + } + }, + "com.amazonaws.s3#DeleteReplication": { + "type": "structure", + "members": { + "Status": { + "target": "com.amazonaws.s3#DeleteReplicationStatus", + "traits": { + "smithy.api#required": {} + } + } + }, + "traits": { + "s3s#minio": "" + } + }, + "com.amazonaws.s3#DeleteReplicationStatus": { + "type": "enum", + "members": { + "Enabled": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#enumValue": "Enabled" + } + }, + "Disabled": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#enumValue": "Disabled" + } + } + }, + "traits": { + "s3s#minio": "" + } } } } \ No newline at end of file