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

Syntax for expressing enums with mixed variants #249

Closed
LonerDan opened this issue Jul 27, 2023 · 9 comments · Fixed by #276
Closed

Syntax for expressing enums with mixed variants #249

LonerDan opened this issue Jul 27, 2023 · 9 comments · Fixed by #276
Labels

Comments

@LonerDan
Copy link

LonerDan commented Jul 27, 2023

Let's say I have the following:

#[derive(Debug, FromField)]
#[darling(attributes(my_attribute))]
struct StructFieldReceiver {
    ident: Option<syn::Ident>,
    vis: syn::Visibility,
    ty: syn::Type,
    name: String,
    sql_type: SqlType,
}

#[derive(Debug, FromMeta)]
#[darling(rename_all = "lowercase")]
enum SqlType {
// omitted variants
    BigInt, Int, SmallInt, TinyInt, Bit,
    Float(Option<u8>),
    Decimal{
        p: Option<u8>,
        s: Option<u8>
    },
// omitted variants
}

I can use the variants without type with #[my_attribute(name = "name", sql_type = "int")], but I don't know the correct syntax for specifying the Float or Decimal variants. Could you please point me in the right direction?

@TedDriggs
Copy link
Owner

Try #[my_attribute(name = "name", sql_type(float = 3.5)]

@LonerDan
Copy link
Author

Thank you, that works. Is there a way to also allow using it without the value, so that it defaults to None? Neither sql_type(float), sql_type = float nor sql_type = "float" seem to accomplish that.

@TedDriggs
Copy link
Owner

I think for that you'll need to do a custom implementation of FromMeta, or use the #[darling(with = "...")] attribute on the field in question to override the parsing function.

@LonerDan
Copy link
Author

LonerDan commented Aug 3, 2023

Could this be done in addition to the derived FromMeta implementation (i.e. only add implementation for those cases)?

@TedDriggs
Copy link
Owner

Sort of - you can create a private mirror of the enum that derives FromMeta and has a conversion into the public enum, and then have your custom impl of FromMeta on the public enum delegate to the derived impl for all cases except the ones that need special handling.

I’d be willing to look at a PR or issue for adding with = “…” support to variants, which would be another way to do this.

@LonerDan
Copy link
Author

LonerDan commented Aug 3, 2023

Would it be possible or desired to add handling of this to the code generated for #[derive(FromMeta)]? Darling already handles correctly Option<..> fields (i.e. absence of attribute field means None), so it could behave similarly in enums.

@TedDriggs
Copy link
Owner

I don't think the way that darling handles absent fields would work for enum variants; that uses the FromMeta::from_none method on the field-type level, and we don't have a good way of expressing that for variant type.

I think the place that would need work would be here, where we'd want to check if all the fields of the variant were optional and then do something special. However, I'm not sure if that would compose well with newtype variants, and I think any solution we pursue here would need to do that.

@LonerDan
Copy link
Author

I looked at the way the variant parsing is done from string values, and we could alter the matching a bit for the variants which are newtype or struct by using the default value or trying the from_none fallback (in a very similar way it is done in the from_list implementation).
Here is a proof of concept: LonerDan/darling@3e06e62

@TedDriggs
Copy link
Owner

I'd suggest trying this again, as a bunch of changes in enum variant handling just merged.

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

Successfully merging a pull request may close this issue.

2 participants