|
It's really nice when doing networking protocols and other binary formats. Lots of things are defined as "This byte signifies X : 0 == Undefined, 1 == A, 2 == B, 3 == C, 4-127 == reserved for future use, 128-255 vendor specific options". This allows you to do something like: #[derive(Clone, Copy)]
#[repr(u8)]
#[non_exhaustive]
pub enum Foo {
A = 1,
B,
C,
}
impl Foo {
pub fn from_byte(val: u8) -> Self {
unsafe { std::mem::transmute(val) }
}
pub fn from_byte_ref(val: &u8) -> &Self {
unsafe { std::mem::transmute(val) }
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn conversion_copy() {
let n: u8 = 1;
let y = Foo::from_byte(n);
assert!(matches!(y, Foo::A));
let n: u8 = 4;
let y = Foo::from_byte(n);
assert!(!matches!(y, Foo::A) && !matches!(y, Foo::B) && !matches!(y, Foo::C));
let n2 = y as u8;
assert_eq!(n2, 4);
}
#[test]
fn conversion_ref() {
let n: u8 = 1;
let y = Foo::from_byte_ref(&n);
assert!(matches!(*y, Foo::A));
let n: u8 = 4;
let y = Foo::from_byte_ref(&n);
assert!(!matches!(*y, Foo::A) && !matches!(*y, Foo::B) && !matches!(*y, Foo::C));
let n2 = (*y) as u8;
assert_eq!(n2, 4);
}
}
This lets you have a simple fast parsing of types without needing a bunch of logic - particularly in the ref example. Someone else sent you data over the wire and is using a vendor defined value, or a newer version of the protocol that defines Foo::D? No big deal, you can igore it or error, or whatever else is appropriate for your case.If you want to define Reserved and Vendor as enum attributes, now you have to have logic that runs all the time - and if you want to preserve the original value for error messages, logs, etc - you can't Repr(u8) and take up more memory, have to do copies, etc. #[non_exhaustive]
pub enum Foo {
Undefined =0,
A = 1,
B,
C,
Reserved(u8),
Vendor(u8),
}
impl Foo {
pub fn from_byte(val: u8) -> Self {
match val {
0 => Foo::Undefined,
1 => Foo::A,
2 => Foo::B,
3 => Foo::C,
4..=127 => Foo::Reserved(val)
128.. => Foo::Vendor(val)
}
}
}
You also need logic to convert back to a u8 now too.It's not strictly necessary, but it certainly makes some things far more ergonomic. |
Apologies for my pre-coffee brainfarts.