How to define a range of u8 that can exhaust in pattern match
This looks like a perfect use case for enum
. Note that enum
in Rust is not like it is in C. In C, enum
is a narrow wrapper around an integer. In Rust, it's a full-fledged sum-of-product algebraic data type, capable of describing basically whatever you want.
#[derive(Clone, Copy)]
pub enum SlidingRole { King, Queen }
fn adf(role: SlidingRole) -> u8 {
match role {
SlidingRole::King => 3,
SlidingRole::Queen => 2,
}
}
Now SlidingRole
is a new type with exactly two possible values. If you want, you can provide From
/ TryFrom
instances for conversion to / from u8
.
I also derive Clone
and Copy
so you don't have to worry about borrow semantics in the above example. For simple enums (where it's just a list of cases like yours is), this is fine. If your enum starts to contain something like a String
, you won't be able to get Copy
since it's no longer a plain memcpy to clone data. You'll probably want to add Eq
, PartialEq
, and potentially an ordering, depending on your specific use cases.
Finally, if you need the underlying representation to be u8
(for instance, if you're interfacing with a C library), you can use a repr
annotation to force this.
#[repr(u8)]
#[derive(Clone, Copy)]
pub enum SlidingRole { King, Queen }
Now SlidingRole
is genuinely still a new type, distinct from u8
. But it's guaranteed to use a memory layout equivalent to u8
, so you can pass it to C functions expecting a u8
, and you can transmute
it to/from a u8
safely. This is a niche and more advanced use case, so I don't recommend doing it unless you specifically need the data to be a u8
.
In particular, you shouldn't do this for the purposes of premature optimization; Rust's compiler is already really good at optimizing datatypes, so "I think this fits best in u8
" is not a good use case; the compiler is smarter than you or I when it comes to building assembly code. Stick with a plain enum
unless you have a very niche use case.