illicitonion / num_enum

Apache License 2.0
264 stars 34 forks source link

Support custom error type for TryFromPrimitive #121

Closed qwandor closed 1 year ago

qwandor commented 1 year ago

It would be useful for the TryFromPrimitive derive macro to have an option to specify a custom error type to use when the conversion fails, rather than the supplied TryFromPrimitiveError. I'd like to use TryFromPrimitive on some types which are part of my library's public API, and exposing TryFromPrimitiveError as part of this isn't great. It could look something like:

#[derive(TryFromPrimitive)]
#[from_primitive_error(MyError, error_constructor)]
#[repr(u8)]
pub enum MyEnum {
    VariantOne,
    VariantTwo,
}

Where MyError is the error type to use for the TryFrom implementation, and error_constructor is a function of type (u8) -> MyError which the generated TryFrom implementation would call with the invalid input value to make an instance of the error type.

illicitonion commented 1 year ago

I really like this idea, and in particular I think it will also help solve https://github.com/illicitonion/num_enum/issues/82 (which ideally would be solved by use of something like https://crates.io/crates/transitive rather than with num_enum-specific support)...

I'll have a play with what the API could look like for this - the place I'm not 100% sure of is on how to take the error_constructor, but in general I like the proposed API :)

illicitonion commented 1 year ago

I put together a draft in https://github.com/illicitonion/num_enum/pull/123 - can you give it a go and see how it works for you?

You can see an example of the syntax in the newly added tests in num_enum/tests/try_from_primitive.rs:

#[derive(TryFromPrimitive)]
#[num_enum(error_type(name = CustomError, constructor = CustomError::new))]
#[repr(u8)]
enum FirstNumber {
    Zero,
    One,
    Two,
}
qwandor commented 1 year ago

I just had a go with this in my code and it works well, thanks! Looking forward to seeing a release with this in it.

illicitonion commented 1 year ago

Fabulous! I've just published 0.7.0 with this feature :) Thanks again for the feature request, and testing it out!