liveBook · Manning

Enum

As explained in Rust in Action: Systems programming concepts and techniques

An enum is a type whose value is one of a finite set of named variants, optionally carrying associated data.

An enum is a Rust type with a fixed set of named variants. Use it when a value must be one of several known possibilities: a playing-card suit, an event code, or a file state. Unlike a string or an unrestricted number, the choice is visible to the compiler. section 3.5 section 3.5.1

Name the possibilities

`enum Suit { Clubs, Spades, Diamonds, Hearts }` defines four variants. A value such as `Suit::Hearts` names one of them. Variants can also carry data: `Card::King(Suit)` holds a suit, while `Card::Pip(Suit, usize)` holds a suit and a number. section 3.5

For an event log, `Event` can distinguish `Update`, `Delete`, and `Unknown` instead of passing event names around as strings. Matching on those variants makes the cases explicit and lets the compiler help catch a forgotten case. Like a struct, an enum can have methods through an `impl` block. section 3.5 section 3.9

Listing 3.11 An enum that represents a File being open or closed
 #[derive(Debug,PartialEq)]
 enum FileState {
   Open,
   Closed,
 }
 
 #[derive(Debug)]
 struct File {
   name: String,
   data: Vec<u8>,
   state: FileState,
 }
 
 impl File {
   fn new(name: &str) -> File {
     File {
       name: String::from(name),
       data: Vec::new(),
       state: FileState::Closed,
     }
   }
 
   fn read(
     self: &File,
     save_to: &mut Vec<u8>,
   ) -> Result<usize, String> {
     if self.state != FileState::Open {
       return Err(String::from("File must be open for reading"));
     }
     let mut tmp = self.data.clone();
     let read_length = tmp.len();
     save_to.reserve(read_length);
     save_to.append(&mut tmp);
     Ok(read_length)
   }
 }
 
 fn open(mut f: File) -> Result<File, String> {
   f.state = FileState::Open;
   Ok(f)
 }
 
 fn close(mut f: File) -> Result<File, String> {
   f.state = FileState::Closed;
   Ok(f)
 }
 
 fn main() {
   let mut f5 = File::new("5.txt");
 
   let mut buffer: Vec<u8> = vec![];
 
   if f5.read(&mut buffer).is_err() {
     println!("Error checking is working");
   }
 
   f5 = open(f5).unwrap();
   let f5_length = f5.read(&mut buffer).unwrap();
   f5 = close(f5).unwrap();
 
   let text = String::from_utf8_lossy(&buffer);
 
   println!("{:?}", f5);
   println!("{} is {} bytes long", &f5.name, f5_length);
   println!("{}", text);
 }

Follow the file example from `FileState::Closed` at creation to `FileState::Open` after opening. The `read` method checks the state and returns an error if the file is closed. section 3.5.1

An enum can also keep different errors under one return type without discarding their origins. An error wrapper has variants carrying I/O and address-parsing errors; `map_err` converts each upstream error into its corresponding variant. Implementing `From` can remove those explicit conversions. section 8.5.2

The same idea extends to changing network states and hardware constants. A loop can match a connection state and assign the next one. For VGA text colors, an enum with `#[repr(u8)]` groups named numeric values and makes an illegal color harder to use than a bare `u8`. section 8.7 section 11.5.1 section 11.5.3

How Rust in Action: Systems programming concepts and techniques covers it

How deep it goes
Works through enum syntax, data-carrying variants, matching, state checks, and error conversion; defers advanced state-machine methods.
Examples
Uses card suits, parsed event logs, mock files, wrapped errors, network states, and VGA colors.
What it assumes
Starts enum syntax with simple named choices and builds on the introduction to compound types and structs.
What you can do after
Build it from scratch to represent named alternatives, carry variant-specific data, and check file state before reading.
How it connects
Connects enums to structs, pattern matching, Result, finite state machines, and error conversion.

Also explained in

Compare how 23 books explain enum →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Rust in Action: Systems programming concepts and techniques. The section links point to the parts of the book it draws on.