Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do I get an error when pattern matching a struct-like enum variant with fields?

I can't get rid of an error on this code:

#[derive(PartialEq, Copy, Clone)]
pub enum OperationMode {
    ECB,
    CBC { iv: [u8; 16] },
}

pub struct AES {
    key: Vec<u8>,
    nr: u8,
    mode: OperationMode,
}

impl AES {
    pub fn decrypt(&mut self, input: &Vec<u8>) {
        match self.mode {
            OperationMode::ECB => {},
            OperationMode::CBC(_) => {},
        };
    }
}

The pattern matching at the end of the decrypt function gives an error:

error[E0532]: expected tuple struct/variant, found struct variant `OperationMode::CBC`
  --> src/main.rs:17:13
   |
17 |             OperationMode::CBC(_) => {},
   |             ^^^^^^^^^^^^^^^^^^ did you mean `OperationMode::CBC { /* fields */ }`?

It tells me to look at the output of rustc --explain E0532 for help, which I did.

They show this example of wrong code:

enum State {
    Succeeded,
    Failed(String),
}

fn print_on_failure(state: &State) {
    match *state {
        // error: expected unit struct/variant or constant, found tuple
        //        variant `State::Failed`
        State::Failed => println!("Failed"),
        _ => ()
    }
}

In this example, the error occurs because State::Failed has a field which isn't matched. It should be State::Failed(ref msg).

In my case I'm matching the field of my enum because I'm doing OperationMode::CBC(_). Why does the error happen?

like image 417
Antoxyde Avatar asked Jun 09 '18 13:06

Antoxyde


People also ask

How do you match types in Rust?

Instead of matching on an element, call the method in the trait on it. TLDR: in Rust, to match over type, we create a trait, implement a function for each type and call it on the element to match. Surround it with backticks to mark it as code. Single backticks for inline code, triple backticks for code blocks.

Does Rust have pattern matching?

Patterns are a special syntax in Rust for matching against the structure of types, both complex and simple. Using patterns in conjunction with match expressions and other constructs gives you more control over a program's control flow.

What are structs and enums in Rust?

structs can be used to model cars and define state. methods and associated functions can be used to specify their behaviour. enums can be used to specify range of allowed values for a custom data type. traits can be used to describe shared behaviours across user-defined data types.

What is an enum in Rust?

An enum in Rust is a type that represents data that is one of several possible variants. Each variant in the enum can optionally have data associated with it: #![allow(unused_variables)] fn main() { enum Message { Quit, ChangeColor(i32, i32, i32), Move { x: i32, y: i32 }, Write(String), }


1 Answers

Enum variants have three possible syntaxes:

  • unit

    enum A { One }
    
  • tuple

    enum B { Two(u8, bool) }
    
  • struct

    enum C { Three { a: f64, b: String } }
    

You have to use the same syntax when pattern matching as the syntax the variant was defined as:

  • unit

    match something {
        A::One => { /* Do something */ }
    }
    
  • tuple

    match something {
        B::Two(x, y) => { /* Do something */ }
    }
    
  • struct

    match something {
        C::Three { a: another_name, b } => { /* Do something */ }
    }
    

Beyond that, you can use various patterns that allow ignoring a value, such as _ or ... In this case, you need curly braces and the .. catch-all:

OperationMode::CBC { .. } => { /* Do something */ }

See also:

  • Ignoring Values in a Pattern in The Rust Programming Language
  • Appendix B: Operators and Symbols in The Rust Programming Language
  • How to match struct fields in Rust?
like image 107
Shepmaster Avatar answered Sep 21 '22 19:09

Shepmaster