Ben Chuanlong Du's Blog

It is never too late to learn.

Enum in Rust

In [ ]:
:timing
:sccache 1

Tips

  1. It does NOT matter whether the last enum item is followed by a comma or not. It is suggested that you always have a comma after the last item so that it is easier to add new items later if needed.

  2. Use :: to access elements of an enum object.

  3. Integer enum variants (simple enum variants without associated data) can be casted into integer values using the keyword as. If no integer value is defined for enum items, they are casted into integer values starting from 0 (corresponding to their definition order). If a customized integer value v is assigned to an enum item $E_i$ and its following items $E_{i+1}$ is not assigned a customized integer value, then $E_{i+1}$ has the value v+1.

  4. It is suggested that you derive Copy and Clone (using #[derive(Copy, Clone)]) for your customized Enum so that you can cast an Enum item to integer (using the as keyword). Fore more discussion, please refer to How do I convert an enum reference to a number? .

  5. You can associate a const integer value with an Enum item, however, you cannot assoicate arbitrary constant value with an Enum item directly. If you do want to associate arbitrary constant value with an Enum item, you have to implement a customized method by yourself.

     :::Rust
     enum MyEnum {
         A,
         B,
     }
    
     impl MyEnum {
         fn value(&self) -> i32 {
             match *self {
                 MyEnum::A => 123,
                 MyEnum::B => 456,
             }
         }
     }
In [4]:
enum MyEnum {
            A,
            B,
        }

        impl MyEnum {
            fn value(&self) -> i32 {
                match *self {
                    MyEnum::A => 123,
                    MyEnum::B => 456,
                }
            }
        }
In [6]:
MyEnum::A.value()
Out[6]:
123

Simple Enum

Value of Enum Variants

Enum items can be casted into integer values. By default, casted integer values start from 0 (corresponding to the definition order of items).

In [2]:
enum Weekday {
    Monday,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday,
    Sunday,
}
In [3]:
Weekday::Monday as u8
Out[3]:
0
In [12]:
Weekday::Sunday as u8
Out[12]:
6
In [13]:
enum Weekday1 {
    Monday = 1,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday,
    Sunday,
}
In [14]:
Weekday1::Monday as u8
Out[14]:
1
In [15]:
Weekday1::Sunday as u8
Out[15]:
7
In [27]:
enum Weekday2 {
    Monday,
    Tuesday,
    Wednesday = 100,
    Thursday,
    Friday,
    Saturday,
    Sunday,
}
In [29]:
Weekday2::Monday as u8
Out[29]:
0
In [30]:
Weekday2::Tuesday as u8
Out[30]:
1
In [31]:
Weekday2::Wednesday as u8
Out[31]:
100
In [32]:
Weekday2::Sunday as u8
Out[32]:
104
In [20]:
enum WeekdayInt {
    Monday = 1,
    Tuesday = 2,
    Wednesday = 3,
    Thursday = 4,
    Friday = 5,
    Saturday = 6,
    Sunday = 0,
}
In [21]:
WeekdayInt::Monday as u8
Out[21]:
1
In [22]:
WeekdayInt::Saturday as u8
Out[22]:
6
In [23]:
WeekdayInt::Sunday as u8
Out[23]:
0

Construct Simple Enum Variants from Integers

There are 2 ways to do this. First, you can do a manual match statement. The second way is to use the crates num-traits and num-erive. Below is an example using those 2 crates to convert integers to simple enum variants.

In [26]:
:dep num-traits = "0.2.14"
:dep num-derive = "0.3.3"
In [ ]:
use num_derive::FromPrimitive;    
use num_traits::FromPrimitive;

#[derive(FromPrimitive)]
enum MyEnum {
    A = 1,
    B,
    C,
}
In [ ]:
let x = 2;

match FromPrimitive::from_i32(x) {
    Some(MyEnum::A) => println!("Got A"),
    Some(MyEnum::B) => println!("Got B"),
    Some(MyEnum::C) => println!("Got C"),
    None            => println!("Couldn't convert {}", x),
}

Complex Enum Variants

Enum in Rust is much more poweful than enum in other programming languages as you an associated any kind of data with an enum variant. For example, below is an Enum named IpAddr. It has 2 variants V4 and V6. The variant V4 has 4 integers of the type u8 associated with it while tthe variant V6 has a String associated with it.

In [29]:
#[derive(Debug)]
enum IpAddr {
    V4(u8, u8, u8, u8),
    V6(String),
}
In [31]:
let v4 = IpAddr::V4(1, 2, 3, 4);
v4
Out[31]:
V4(1, 2, 3, 4)
In [32]:
let v6 = IpAddr::V6("ab:d:ef".to_string());
v6
Out[32]:
V6("ab:d:ef")
In [33]:
match v4 {
    IpAddr::V4(x1, x2, x3, x4) => {
        println!("V4 values: {}, {}, {}, {}", x1, x2, x3, x4)
    },
    _ => println!("not matched"),
}
V4 values: 1, 2, 3, 4
Out[33]:
()

Comparing Enum Items

It is strongly suggested that you use match to compare Enum items especially when you have complex enum variants. Enums CANNOT be compared using == directly. For more discussions, please refer to How to compare enum without pattern matching .

Methods for Enum

  1. You can define methods for an Enum type using impl. The example below define 2 methods for the enum type Weekday. Notice that the method Weekday.val is an instance method while the method Weekday::greet is a static method.

  2. If &self (must use self unlike other programming languages, e.g., Python) is used as the first parameter, then the method is an instance method. Otherwise, the method is a static method.

In [3]:
impl Weekday {
    fn val(&self) -> i32 {
        1
    }
    fn greet() -> String {
        String::from("Hello")
    }
}
In [4]:
let m = Weekday::Monday;
m.nima()
Out[4]:
1
In [5]:
Weekday::greet()
Out[5]:
"Hello"

Pattern Matching

In [19]:
fn schedule(m: Weekday) {
    match m {
        Weekday::Monday | Weekday::Tuesday | Weekday::Wednesday | Weekday::Thursday | Weekday::Friday => println!("Work!"),
        Weekday::Saturday | Weekday::Sunday => println!("Have a rest!")
    }
}
In [20]:
schedule(Weekday::Monday)
Work!
Out[20]:
()
In [21]:
schedule(Weekday::Sunday)
Have a rest!
Out[21]:
()

Iterate Vairants of an Enum

  • strum is a set of macros and traits for working with enums and strings easier in Rust.

  • enum-iterator provides tools (see the IntoEnumIterator trait) to iterate over the variants of a field-less enum.

https://crates.io/crates/enum-map A library providing enum map providing type safe enum array. It is implemented using regular Rust arrays, so using them is as fast as using regular Rust arrays.

In [ ]:

Comments