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

Enhancement: Better ParseError #221

Open
JRAndreassen opened this issue Apr 16, 2022 · 4 comments
Open

Enhancement: Better ParseError #221

JRAndreassen opened this issue Apr 16, 2022 · 4 comments

Comments

@JRAndreassen
Copy link

JRAndreassen commented Apr 16, 2022

Hi...

Love the crate...
I'd love it even more if the from_str() gave better error messages.

When I parse a file with serde I often get:

Failed: "Custom { field: \"Matching variant not found\" }"

It would be ooohhh so much better if it said:

Failed: Custom { field: \"Matching variant not found: [EnumName:'Value']\" }"

Perhaps change:

pub enum ParseError {
    VariantNotFound(String),
}

...
    fn from_str( s: &str,    ) ...
{
...
        _ => ::core::result::Result::Err(::strum::ParseError::VariantNotFound(format!("StructName[{}]", s))),
}

I know it's extra overhead, but ohhh so useful.
Could make it optional and/or only in Test/Debug
Since serde does not always give a good error, even with serde_path_to_error...

Thanks
JR

@Peternator7
Copy link
Owner

Hello @JRAndreassen, glad to hear you like the crate! What does your Deserialize impl look like? I wasn't aware that serde would use a type's FromStr impl when deriving Deserialize

@JRAndreassen
Copy link
Author

JRAndreassen commented Apr 17, 2022

Hi @Peternator7 ,

Thanks for getting back to me...

It does not use it directly...
But the handy crate "serde_with" makes it possible.
It eliminates the redundant serde attributes and code, by telling serde to use "from_str"[DeserializeFromStr] and "Display"[SerializeDisplay]

serde = { version = "^1.0", features = ["derive","rc"] }
serde_derive = "^1.0"
serde_json = "^1.0"
serde_path_to_error = "*"
serde_with = "*"

strum = "*"
strum_macros = "*"
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, DisplayMore)]
#[derive(AsRefStr, IntoStaticStr, EnumString, EnumMessage, EnumIter, FromRepr)]
#[strum(ascii_case_insensitive)]
#[serde_as]
#[derive(SerializeDisplay, DeserializeFromStr)]
#[repr(u8)]
pub enum Units {
   #[strum(to_string = "BytesBandwidth", serialize = "Bandwidth", serialize = "OctetsBandwidth"")]
   BytesBandwidth = 0,
   #[strum(to_string = "BytesMemory", serialize = "Memory", serialize = "Mem")]
   BytesMemory = 1,
   #[strum(to_string = "BytesDisk", serialize = "Bytes", serialize = "Disk")]
   BytesDisk = 2,
   #[strum(to_string = "Temperature", serialize = "Temprature", serialize = "Temp")]
   Temperature = 3,
   #[strum(to_string = "Percent", serialize = "Pct", serialize = "%",)]
   Percent = 4,
   #[strum(to_string = "TimeResponse", serialize = "ResponseTime", serialize = "ms")]
   TimeResponse = 5,
   #[strum(to_string = "TimeSeconds", serialize = "Seconds", serialize = "sec")]
   TimeSeconds = 6,
   #[strum(to_string = "Custom", serialize = "Other")]
   Custom = 7,
...
   #[strum(to_string = "TimeHours", serialize = "Hours", serialize = "hrs")]
   TimeHours = 13,
   Invalid = 99,
 }

Which makes quite a difference, since I generate code from API(OpenApi) definitions, which
has some rather large structures.

Also... is there a particular reason why the "to_string" value gets evaluated last ?
Just asking for efficiency...
It would make sense to order the most likely choices first in the list...

    fn from_str(s: &str,  ) -
> ::core::result::Result<ChannelUnits, <Self as ::core::str::FromStr>::Err> {
...
            s if s.eq_ignore_ascii_case("Hours") => {
                ::core::result::Result::Ok(ChannelUnits::TimeHours)
            }
            s if s.eq_ignore_ascii_case("hrs") => {
                ::core::result::Result::Ok(ChannelUnits::TimeHours)
            }
            s if s.eq_ignore_ascii_case("TimeHours") => {
                ::core::result::Result::Ok(ChannelUnits::TimeHours)
            }
...
}
...
    fn get_serializations(&self) -> &'static [&'static str] {
...
     static ARR: [&'static str; 3usize] = ["Hours", "hrs", "TimeHours"];
...
   }

Thanks
JR

@FaveroFerreira
Copy link

FaveroFerreira commented Sep 6, 2023

I support this, it would be nice to know what value I am trying to parse into an Enum in the error message. @Peternator7 , if you think this is valid maybe I can takkle this issue in a PR.

@ju6ge
Copy link

ju6ge commented Dec 11, 2023

I support this as well 👍

Just as a note when I deserialize an enum with serde I get the following useful error message:

unknown variant `bla`, expected one of `Red`, `Green`, `Yellow`, `Blue`

Would be awesome if strum had a similar message.

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

No branches or pull requests

4 participants