about
05/04/2022
RustBites - Enumerations
Code Repository Code Examples Rust Bites Repo

Rust Bite - Enumerations

Option<T>, Result<T,E>, custom

1.0 - Introduction

Rust error handling is based on two things: enumerations and matching. Rust's enumerations are more powerful than those of C++ and C#. Each element of the enumeration may wrap some type, as shown below.
enum Option<T> { Some(T), None, }
Option is used when a value cannot be initialized at compile-time or a function that returns a value for some paths but may have nothing to return for another path, e.g. return the first occurence of ...
For cases where that indeterminacy is caused by possible errors, Rust provides the Result type:
enum Result<T, E> { Ok(T), Err(E), }
Result returns one of either of two types of values, a valid return value or a specific error value, perhaps a string or error code. Options and Returns are discussed in detail, with examples, in the two following Error Handling and Options Rust Bites.

2.0 - Custom Enumerations

Often in code we use enums defined in the standard libraries. However, it can be quite useful to develop custom enumerations like the one shown below. This example shows an Event<T> enumeration that represents different levels of events, and wraps information about the event inside the event item except for the NoEvent item. This example shows how to write code to wrap and unwrap values from enumeration items.
Custom Enumeration Example #![allow(unused_variables)] /*----------------------------------------------------- The generic parameter T represents some value associated with events, perhaps a name String or id number. */ #[derive(Debug, Clone)] enum Event<T> { Normal(T), Warning(T), Critical(T), NoEvent } impl<T> Event<T> { fn unwrap(&self) -> &T { if let Event::Normal(ev) = self{ ev } else if let Event::Warning(ev) = self{ev} else if let Event::Critical(ev) = self{ev} else { panic!() } } } use Event::*; fn main() { /*-- numbers are event ids --*/ let e1: Event<u8> = Event::<u8>::Normal(1); let e2 = Warning(2); let e3 = Critical(3); let e4: Event<u8> = NoEvent; /*-- match works like switch stmt on steriods --*/ match e3 { Normal(ev) => print!("\n event {} is Normal", ev), Warning(ev) => print!("\n event {} is Warning", ev), Critical(ev) => print!("\n event {} is Critical!", ev), NoEvent => print!("\n no events occurred"), } /*------------------------------------------------- without the clone() operation below e2 would move into e and become invalid for future operations. */ let e = e2.clone(); /*------------------------------------------------- if let statements use "=" as match operator */ if let Warning(ev) = e { print!("\n event {} is Warning", ev); } /*-- next stmt panics if event is NoEvent type --*/ let v = e3.unwrap(); print!("\n inner value of {:?} is {}", e3, v); /*-- will panic if you unwrap() e4 --*/ } Output event 3 is Critical! event 2 is Warning inner value of Critical(3) is 3 Comments Enumerations can have methods defined
in the same way we define methods for
structs. That let's us acess and use their
inner values.
Match statements require us to handle all of
the enum items.
Sometimes we don't need to do that.
Then, we can use the if let statement to
test for a single enum item type.
Here, the "=" operator is not assignment.
It is a matching operator that selects on a
single enum item type.
How cool is Rust? Very cool!
Example:
playground example

3.0 - Matching

Matching is Rust's model for alternates selection - more powerful than switch-case operations, as shown by the example, above. Matching works for more than just enum items. The example below shows matching on char ranges.
Matching Ordinary Data fn do_match(c: char) { match c { ('0'..='9') => print!("\n {} is a digit", c), ('a'..='z') => print!("\n {} is lower case ascii char", c), ('A'..='Z') => print!("\n {} is upper case ascii char", c), _ => print!("\n {} is some other char type", c) } } fn main() { let x = 'a'; do_match(x); do_match('Q'); do_match('7'); do_match('@'); } Output a is lower case ascii character Q is upper case ascii character 7 is a digit @ is some other char type Comments Lexer here we come!
playground example

4.0 - References


LinkDescription
the rust book Easy to use examples, illustrated with std::fs
rust-by-example Easy to use examples that have sufficient detail for project coding
  Next Prev Pages Sections About Keys