Allow matching enums with their #[repr(T)] type

Given an enum with a primitive #[repr(T)] type, it would be nice to allow matching Ts against the respective enums.

Real-world example

I have this enum:

… in order to check for special control bytes in the protocol here:

As you can see, I need to have the verbose matching notation with the if condition, since I cannot match the u8 directly against an enum variant.

Alternatives considered

Previously I just had the control bytes as global constants, which I did not like due to possible match footgun when using plain variable names.

Another option would be to implement the values as constants on a tuple unit struct, but this feels just wrong to me and also looks weird imho.

Proposal

Allow the matching of enums against a T when the enum is #[repr(T)].

1 Like

Is there some kind of .as_repr() method available in such cases? How would method resolution work? Perhaps it needs to be a deriveable trait?

Why not try_into the byte into the enum first? Unfortunately it currently needs a custom impl with a boilerplate match, but it only has to do once, and there’s a crate that does it for you.

You should have a custom Error type, btw. Payload format/protocol errors are hardly I/O errors. Also, then you can do this:

match byte?.try_into()? {
    ControlByte::Cancel => ...
}

and you get exhaustiveness checking and don't need a wildcard case.

4 Likes

That’s another feasible alternative, but it requires an additional level of nesting matches, making the code more complex:

Patterns can be nested so the match statements doesn't actually have to be nested if you're okay with each pattern having Ok() or Err() around it. You won't have rightward indentation anymore

3 Likes

Also, I think let…else would work great here.

How? I’d need both, the content of Ok(control_byte_enum) and Err(non_control_byte_to_push).

I’d then need to store the result of byte? in a temporary variable to be able to access it in the error case.

Yes, I had a bit of a brain fart there, for a second I though of Option rather than Result. Of course one way is to write the early-return with a full match to avoid nesting the matches, but as long as there are only five or so variants in the enum, I might be inclined to just write a single match with Ok(ControlByte::Foo) => cases.