nutype icon indicating copy to clipboard operation
nutype copied to clipboard

Support custom errors

Open greyblake opened this issue 1 year ago β€’ 5 comments

Context

Some orgs and people are not quite happy with auto-generated error types, e.g. it's not possible to customize them, inject extra details, etc.

Requirement

Provide a way for users to:

  • Define and provide error type they want to use
  • Inject their custom validation function that would return Result<(), CustomError>, where CustomError is a user defined error.

Technically it's possible, but the syntax for this needs to be decided.

Consideration

Having this may clash with "unified error": https://github.com/greyblake/nutype/issues/75, so requires careful thinking.

greyblake avatar Jul 17 '24 10:07 greyblake

I would love to see this - is one of the main reasons I'm unable to use nutype

boyswan avatar Jul 17 '24 14:07 boyswan

@AlisCode @gobanos @boyswan What do you guys think of the following syntax?

#[nutype(
    sanitize(trim),
    validate(with = validate_name, error = NameError),
    derive(Debug, AsRef, PartialEq, Deref),
)]
struct Name(String);

where

fn validate_name(name: &str) -> Result<(), NameError> {
    if name.len() < 3 {
        Err(NameError::TooShort)
    } else if name.len() > 20 {
        Err(NameError::TooLong)
    } else {
        Ok(())
    }
}

// This actually probably will need to implement fully std::error::Error
#[derive(Debug)]
enum NameError {
    TooShort,
    TooLong,
}

Do you have any alternative proposal to consider?

greyblake avatar Aug 09 '24 06:08 greyblake

Looks great!

boyswan avatar Aug 09 '24 08:08 boyswan

Looks cool!

Although I have to say this breaks a lot with the current nutype philosophy.

Right now, nutype supports e.g. the following attribute :

validate(not_empty, len_char_max = 20), which produces an error enum with 2 variants (NotEmptyViolated, LenCharMaxViolated)

I think it's a good feat of nutype that you're able to provide a multi-step validation, and this proposal attemps to do exactly the reverse which is that you would provide one custom validation function which would contain all your logic in one place. It would probably mean having a lot of code dedicated to the special case.

What if instead, nutype still produced an enum which contains one variant for each step of the validation ?

For example :

struct TooLongError;
fn max_len(input: &str) -> Result<(), TooLongError> {
    if name.len() > 20 {
        Err(TooLongError)
    } else {
        Ok(())
    }
}

struct TooShortError;
fn min_len(input: &str) -> Result<(), TooShortError> {
    if name.len() < 3 {
        Err(TooShortError)
    } else {
        Ok(())
    }
}

#[nutype(
    sanitize(trim),
    validate(
        with(max_len, variant = TooLong),
        with(min_len, variant = TooShort),
    )
    derive(Debug, AsRef, PartialEq, Deref),
)]
struct Name(String);

Produced code :

enum NameError { 
    TooLong(TooLongError),
    TooShort(TooShortError),
    // And here you can support other potential validation steps ...
}

Also right now nutype supports passing in arguments to validators such as for len_char_max = 20. What if the customized validation function needs to be reused between different newtypes, and you wanted to pass in an argument just like for len_char_max ? How do you see that working ?

AlisCode avatar Aug 09 '24 12:08 AlisCode

@AlisCode Thank you for your valuable input! I had a similar thing to what you suggest in mind, though I see it as an orthogonal to this story (support of custom errors VS custom error variants). Ideally I'd like to have both in some or other form implement, because they serve different needs.

greyblake avatar Aug 10 '24 11:08 greyblake

What if instead, nutype still produced an enum which contains one variant for each step of the validation ?

This would "pollute" (even more than it currently does) the public API of libraries that want to use nutype. Maybe a different approach, more centered towards fixing #75, fits better?

DJDuque avatar Aug 21 '24 17:08 DJDuque

Maybe good inspiration on how to handle "let users customize errors" can be taken from parser combinator libraries? Feels like nutype validation errors can take inspiration on how they handle parsing errors (?) I don't know, just throwing ideas out there.

Maybe there is something to copy from the work that @epage has done in winnow? Again, I don't know, just throwing random ideas around.

DJDuque avatar Aug 21 '24 17:08 DJDuque

@DJDuque Could you explain how winnow error idea would fit here?

greyblake avatar Aug 21 '24 18:08 greyblake

@boyswan @AlisCode @DJDuque I just released 0.5.0-beta.2, with the support of custom validation and errors.

I'd appreciate if you find a bit of time to try it out and give me feedback before I release 0.5.0 (planning in ~1 week).

See the docs in the Custom validation with a custom error type section.

greyblake avatar Aug 24 '24 15:08 greyblake

I don't recall being involved in this issue, maybe you meant to tag someone else, @greyblake?

memark avatar Aug 24 '24 15:08 memark

@memark Sorry my bad.

greyblake avatar Aug 24 '24 15:08 greyblake