diff --git a/crates/stackable-versioned-macros/src/attrs/item/field.rs b/crates/stackable-versioned-macros/src/attrs/item/field.rs index 47811b5b9..8c45c4471 100644 --- a/crates/stackable-versioned-macros/src/attrs/item/field.rs +++ b/crates/stackable-versioned-macros/src/attrs/item/field.rs @@ -92,4 +92,5 @@ impl FieldAttributes { pub enum Hint { Option, Vec, + Map, } diff --git a/crates/stackable-versioned-macros/src/codegen/item/field.rs b/crates/stackable-versioned-macros/src/codegen/item/field.rs index 96774a78d..ea074aeea 100644 --- a/crates/stackable-versioned-macros/src/codegen/item/field.rs +++ b/crates/stackable-versioned-macros/src/codegen/item/field.rs @@ -442,6 +442,9 @@ impl VersionedField { Hint::Vec => { quote! { into_iter().map(|v| v.tracking_into(status, &#json_path_ident)).collect() } } + Hint::Map => { + quote! { into_iter().map(|(k, v)| (k, v.tracking_into(status, &#json_path_ident))).collect() } + } } } else { quote! { tracking_into(status, &#json_path_ident) } @@ -454,6 +457,7 @@ impl VersionedField { match hint { Hint::Option => quote! { map(Into::into) }, Hint::Vec => quote! { into_iter().map(Into::into).collect() }, + Hint::Map => quote! { into_iter().map(|(k, v)| (k, v.into())).collect() }, } } else { quote! { into() } diff --git a/crates/stackable-versioned-macros/tests/inputs/pass/hint_map.rs b/crates/stackable-versioned-macros/tests/inputs/pass/hint_map.rs new file mode 100644 index 000000000..9e9784615 --- /dev/null +++ b/crates/stackable-versioned-macros/tests/inputs/pass/hint_map.rs @@ -0,0 +1,31 @@ +use std::collections::HashMap; + +use stackable_versioned::versioned; +// --- +#[versioned(version(name = "v1alpha1"), version(name = "v1alpha2"))] +// --- +pub(crate) mod versioned { + pub(crate) struct Foo { + #[versioned( + changed(since = "v1alpha2", from_type = "HashMap"), + hint(map) + )] + bar: HashMap, + } +} +// --- +struct Bar(u8); + +impl From for Bar { + fn from(value: u8) -> Self { + Self(value) + } +} + +impl From for u8 { + fn from(value: Bar) -> Self { + value.0 + } +} + +fn main() {} diff --git a/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshots__pass@hint_map.rs.snap b/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshots__pass@hint_map.rs.snap new file mode 100644 index 000000000..0a4eb3c23 --- /dev/null +++ b/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshots__pass@hint_map.rs.snap @@ -0,0 +1,35 @@ +--- +source: crates/stackable-versioned-macros/src/lib.rs +expression: formatted +input_file: crates/stackable-versioned-macros/tests/inputs/pass/hint_map.rs +--- +#[automatically_derived] +pub(crate) mod v1alpha1 { + use super::*; + pub struct Foo { + pub bar: HashMap, + } +} +#[automatically_derived] +impl ::core::convert::From for v1alpha2::Foo { + fn from(__sv_foo: v1alpha1::Foo) -> Self { + Self { + bar: __sv_foo.bar.into_iter().map(|(k, v)| (k, v.into())).collect(), + } + } +} +#[automatically_derived] +impl ::core::convert::From for v1alpha1::Foo { + fn from(__sv_foo: v1alpha2::Foo) -> Self { + Self { + bar: __sv_foo.bar.into_iter().map(|(k, v)| (k, v.into())).collect(), + } + } +} +#[automatically_derived] +pub(crate) mod v1alpha2 { + use super::*; + pub struct Foo { + pub bar: HashMap, + } +} diff --git a/crates/stackable-versioned-macros/tests/trybuild.rs b/crates/stackable-versioned-macros/tests/trybuild.rs index c252bb572..25e9e9b4e 100644 --- a/crates/stackable-versioned-macros/tests/trybuild.rs +++ b/crates/stackable-versioned-macros/tests/trybuild.rs @@ -29,6 +29,7 @@ mod inputs { // mod downgrade_with; // mod enum_fields; // mod generics; + // mod hint_map; // mod module; // mod module_preserve; // mod renamed_field;