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.
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
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.