Unverified Commit 720578c2 authored by Copilot's avatar Copilot Committed by GitHub
Browse files

Optimize StrEnum XML deserialization to reduce allocations for known constants (#313)



* Initial plan

* Optimize StrEnum XML deserialization to reduce allocations for known constants

Co-authored-by: default avatarNugine <30099658+Nugine@users.noreply.github.com>

* fix

* fix

---------

Co-authored-by: default avatarcopilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: default avatarNugine <30099658+Nugine@users.noreply.github.com>
Co-authored-by: default avatarNugine <nugine@foxmail.com>
parent f3b921fa
Loading
Loading
Loading
Loading
+11 −1
Original line number Diff line number Diff line
@@ -277,7 +277,17 @@ fn codegen_xml_serde_content(ops: &Operations, rust_types: &RustTypes, field_typ
                {
                    g!("impl<'xml> DeserializeContent<'xml> for {} {{", ty.name);
                    g!("fn deserialize_content(d: &mut Deserializer<'xml>) -> DeResult<Self> {{");
                    g!("String::deserialize_content(d).map(Self::from)");

                    g!("d.text(|t| {{");
                    g!("    let b: &[u8] = &t;");
                    g!("    match b {{");
                    for variant in &ty.variants {
                        g!("b\"{}\" => Ok(Self::from_static({}::{})),", variant.value, ty.name, variant.name);
                    }
                    g!("        _ => Ok(Self::from(t.unescape().map_err(DeError::InvalidXml)?.into_owned())),");
                    g!("    }}");
                    g!("}})");

                    g!("}}");
                    g!("}}");
                }
+492 −52

File changed.

Preview size limit exceeded, changes collapsed.

+61 −0
Original line number Diff line number Diff line
@@ -441,3 +441,64 @@ fn xmlns_xsi() {
        Some("f30716ab7115dcb44a5ef76e9d74b8e20567f63TestAccountCanonicalUserID")
    );
}

#[test]
fn test_str_enum_optimization_functional() {
    use s3s::dto::BucketVersioningStatus;
    use s3s::xml::{DeserializeContent, Deserializer};

    // Test case 1: Known static value "Enabled"
    let xml_enabled = br"Enabled";
    let mut deserializer = Deserializer::new(xml_enabled);
    let status = BucketVersioningStatus::deserialize_content(&mut deserializer).unwrap();

    assert_eq!(status.as_str(), "Enabled");
    assert_eq!(status.as_str(), BucketVersioningStatus::ENABLED);

    // Test case 2: Another known static value "Suspended"
    let xml_suspended = br"Suspended";
    let mut deserializer2 = Deserializer::new(xml_suspended);
    let status2 = BucketVersioningStatus::deserialize_content(&mut deserializer2).unwrap();

    assert_eq!(status2.as_str(), "Suspended");
    assert_eq!(status2.as_str(), BucketVersioningStatus::SUSPENDED);

    // Test case 3: Unknown value should still work correctly
    let xml_unknown = br"Unknown";
    let mut deserializer3 = Deserializer::new(xml_unknown);
    let status3 = BucketVersioningStatus::deserialize_content(&mut deserializer3).unwrap();

    assert_eq!(status3.as_str(), "Unknown");
}

#[test]
fn test_static_vs_from_static() {
    use s3s::dto::BucketVersioningStatus;

    // Create values using different methods and verify they're equivalent
    let static_enabled = BucketVersioningStatus::from_static(BucketVersioningStatus::ENABLED);
    let from_string_enabled = BucketVersioningStatus::from("Enabled".to_owned());

    assert_eq!(static_enabled.as_str(), from_string_enabled.as_str());

    // Verify pointer equality for static values (indirect test for optimization)
    assert_eq!(static_enabled.as_str().as_ptr(), BucketVersioningStatus::ENABLED.as_ptr());
}

#[test]
fn test_xml_deserialization_with_various_enum_types() {
    use s3s::dto::{BucketAccelerateStatus, ChecksumAlgorithm};
    use s3s::xml::{DeserializeContent, Deserializer};

    // Test BucketAccelerateStatus optimization
    let xml_enabled = br"Enabled";
    let mut deserializer = Deserializer::new(xml_enabled);
    let accel_status = BucketAccelerateStatus::deserialize_content(&mut deserializer).unwrap();
    assert_eq!(accel_status.as_str(), BucketAccelerateStatus::ENABLED);

    // Test ChecksumAlgorithm optimization
    let xml_crc32 = br"CRC32";
    let mut deserializer2 = Deserializer::new(xml_crc32);
    let checksum_algo = ChecksumAlgorithm::deserialize_content(&mut deserializer2).unwrap();
    assert_eq!(checksum_algo.as_str(), ChecksumAlgorithm::CRC32);
}