首页 > 解决方案 > 在 Rust 中没有双重匹配语句的情况下将整数与枚举情况匹配

问题描述

所以在 Rust 中,我试图迭代 的向量u8,并将它们与枚举的情况相匹配。为此,我设置了以下代码。

use std::io::prelude::*;

enum Byte {
    A = 0,
    B = 1,
    C = 2,
    D = 3
}

fn main() {
    let mut buf = Vec::<u8>::new();
    write!(buf, "\x01\x03\x02\x00");
    match buf[1] {
        Byte::A => println!("got A"),
        Byte::B => println!("got B"),
        Byte::C => println!("got C"),
        Byte::D => println!("got D")
    }
}

假设println!语句可以是任何形式的行为,例如确定字节 vec 中的下一个类型等。

然而,这导致

error[E0308]: mismatched types
  --> src/main.rs:16:9
   |
6  |     A = 0,
   |     ----- unit variant defined here
...
15 |     match buf[1] {
   |           ------ this expression has type `u8`
16 |         Byte::A => println!("got A"),
   |         ^^^^^^^ expected `u8`, found enum `Byte`

然后,如果我尝试将枚举转换为 u8, with Byte::A as u8,则会出现语法错误。我知道可以将 a 转换u8为 a Byte,然后匹配已转换的Byte,但这需要两个匹配语句,一个用于转换,一个用于比较。我正在寻找一种类似于 C/C++ 的方法,将枚举大小写直接视为 Rust 中的整数。这样我的原始代码就可以运行。

如果没有办法做到这一点,那么在 match 语句中匹配命名常量的方法就足够了。

标签: rustenums

解决方案


简而言之:您想将1u8值转换为Byte的变体。

问题是存在u8不对应于Byte枚举的任何变体的值,例如,任何u8高于3没有变体Byte支持它的值(即任何u8匹配的值4..=255)。

如果您(尝试)转换7u8为 aByte的变体,这种转换应该如何表现?将u8值转换为enum的变体属于易错转换的类别。


但是,您可以为这种易错转换实现TryFrom<u8>特征Byte

use std::convert::TryFrom;

impl TryFrom<u8> for Byte {
    type Error = ();

    fn try_from(val: u8) -> Result<Byte, ()> {
        match val {
            0 => Ok(Byte::A),
            1 => Ok(Byte::B),
            2 => Ok(Byte::C),
            3 => Ok(Byte::D),
            _ => Err(()),
        }
    }
}

它的关联函数try_from()返回 aResult<Byte, ()>而不是仅仅Byte因为转换可能失败。然后,您只需Byte要从返回的中提取(如果有的话)Result

match Byte::try_from(buf[1]).unwrap() {
    Byte::A => println!("got A"),
    Byte::B => println!("got B"),
    Byte::C => println!("got C"),
    Byte::D => println!("got D")
}

或者更简洁,已经Byte实现Display,那么你可以取消match上面的:

println!("got {}", Byte::try_from(buf[1]).unwrap());

1请注意,在另一个方向上执行转换,即从 aByte的变体到一个u8值,可以使用as运算符轻松完成,例如Byte::A as u8.


推荐阅读