I have the following code where every variant of the enum Message
has a Term
value associated with it:
type Term = usize;
pub enum Message {
AppendRequest(Term),
AppendResponse(Term),
VoteRequest(Term),
VoteResponse(Term),
}
impl Message {
pub fn term(&self) -> Term {
match *self {
Message::AppendRequest(term) => term,
Message::AppendResponse(term) => term,
Message::VoteRequest(term) => term,
Message::VoteResponse(term) =>term,
}
}
}
I want to, given a Message
be able to get its term without having to deconstruct the actual Message
value I have. The best I could come up with was creating a public function that unpacked the value for me, but this feels clunky. If I ever add a new enum value, I'm going to have to remember to update match statement in the term
function.
Is there a more succinct/ergonomic way to express the code above? Is there some way to say "hey, every value for this enum will have also have a Term
value associated with it.
By definition, the enumeration member values are unique. However, you can create different member names with the same values.
You can assign different values to enum member. A change in the default value of an enum member will automatically assign incremental values to the other members sequentially. You can even assign different values to each member.
You can't ; but you can create a static method in your enums, with a translation code. But you must have a clear idea of the rules you want to implement.
In theory, an ENUM column can have a maximum of 65,535 distinct values; in practice, the real maximum depends on many factors.
Is there some way to say "hey, every value for this enum will have also have a
Term
value associated with it.
No. This is usually handled by splitting the enum
into two parts, with a struct
containing all the common parts:
pub struct Message {
term: Term,
kind: MessageKind,
}
pub enum MessageKind {
AppendRequest,
AppendResponse,
VoteRequest,
VoteResponse,
}
One option is to implement the Deref
(and/or DerefMut
) trait to convert to the common part.
You still have to update that implementation each time you add to the Enum, but there is less boilerplate at the point of use.
E.g., an example below, note that main
accesses the field number
on the Enum.
use std::ops::Deref;
use std::string::String;
enum JudgedNumber {
GoodNumber(Number),
BadNumber(Number, String),
}
struct Number { number: i32 }
fn main() {
let nice = JudgedNumber::GoodNumber(Number{number: 42});
let naughty = JudgedNumber::BadNumber(
Number{number: 666}, "Damn you to hell".to_string());
println!("j1 = {}", j1.number);
println!("j2 = {}", j2.number);
}
impl Deref for JudgedNumber {
type Target = Number;
fn deref(&self) -> &Number {
match self {
JudgedNumber::GoodNumber(n) => n,
JudgedNumber::BadNumber(n, _) => n,
}
}
}
I learnt this from https://github.com/rust-embedded/svd/blob/master/src/svd/cluster.rs
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With