Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add default_with strum macro #254

Merged
merged 3 commits into from Jan 20, 2024
Merged

Conversation

ericmcbride
Copy link
Contributor

@ericmcbride ericmcbride commented Feb 26, 2023

let defaults =
::core::iter::repeat(quote!(Default::default())).take(fields.unnamed.len());
quote! { (#(#defaults),*) }
if let Some(ref value) = variant_properties.default_with {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn't sure if there was a new-type variant, if we wanted to be able to default each unnamed field. It'll be easy enough to add this feature/tests

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's not too difficult, let's try to match the conventions that serde uses according to this doc:

https://serde.rs/variant-attrs.html#deserialize_with

#[serde(deserialize_with = "path")]

Deserialize this variant using a function that is different from its implementation of Deserialize. The given function must be callable as fn<'de, D>(D) -> Result<FIELDS, D::Error> where D: Deserializer<'de>, although it may also be generic over the elements of FIELDS. Variants used with deserialize_with are not required be able to derive Deserialize.

FIELDS is a tuple of all fields of the variant. A unit variant will have () as its FIELDS type.

I'm not too worried about the generic bounds parts, however, if we can return a tuple, that's probably the clearest way to do it. Thoughts?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me see what I can do!

let mut defaults = vec![];
for field in &fields.named {
let meta = field.get_variant_inner_properties()?;
let field = field.ident.as_ref().unwrap();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wasn't sure about the unwrap here. I don't like unwraps in general, and I could return an ok_or_else Syn error here. I thought it'd just be weird if an ident on a field wasn't a thing. Thoughts here?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really mind unwrapping/expecting here. Maybe just use expect and tell people to file an issue against strum if they see this message

Copy link
Owner

@Peternator7 Peternator7 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally looks pretty good to me! Thanks for tackling this. I think it'll help a lot of use-cases

@@ -15,6 +15,15 @@ enum Color {
Purple,
#[strum(serialize = "blk", serialize = "Black", ascii_case_insensitive)]
Black,
Pink {
#[strum(default_with = "test_default")]
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add a test to make sure it works properly with a full module path

let defaults =
::core::iter::repeat(quote!(Default::default())).take(fields.unnamed.len());
quote! { (#(#defaults),*) }
if let Some(ref value) = variant_properties.default_with {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's not too difficult, let's try to match the conventions that serde uses according to this doc:

https://serde.rs/variant-attrs.html#deserialize_with

#[serde(deserialize_with = "path")]

Deserialize this variant using a function that is different from its implementation of Deserialize. The given function must be callable as fn<'de, D>(D) -> Result<FIELDS, D::Error> where D: Deserializer<'de>, although it may also be generic over the elements of FIELDS. Variants used with deserialize_with are not required be able to derive Deserialize.

FIELDS is a tuple of all fields of the variant. A unit variant will have () as its FIELDS type.

I'm not too worried about the generic bounds parts, however, if we can return a tuple, that's probably the clearest way to do it. Thoughts?

let mut defaults = vec![];
for field in &fields.named {
let meta = field.get_variant_inner_properties()?;
let field = field.ident.as_ref().unwrap();
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really mind unwrapping/expecting here. Maybe just use expect and tell people to file an issue against strum if they see this message

@Peternator7 Peternator7 merged commit c3021f7 into Peternator7:master Jan 20, 2024
@Peternator7
Copy link
Owner

Sorry for the long delay on this :( I don't have much time for this project anymore, but I'm trying to get through everything in the backlog. I think this is a cool addition to the project

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants