枚举和整数

某些时候,我们可能需要根据某个值来匹配对应的枚举
如 输入2 得到 Num::Two

fn main() {
  enum Num {
    One = 1,
    Two = 2,
    Three = 3,
  }

  let a = 1;
  match a {
    // Num::One => println!("one"),
    // ^ 报错:因为a是i32类型,因此这里不能为Num枚举类型
    _ => ()
  }
}

使用第三方库 num_enum

Cargo.toml

[dependencies]
num_enum = "0.7.3"
use num_enum::TryFromPrimitive;

fn main() {
  // 使用第三方库 num_enum 来解决这个问题
  #[derive(TryFromPrimitive, Debug)]
  #[repr(i32)] // 控制底层类型的大小
  enum Num {
    One = 1,
    Two = 2,
    Three = 3
  }

  let b = 2;
  match Num::try_from(b) {
   /*
    Ok(Num::One) => println!("from num_enum_run: one"),
    Ok(Num::Two) => println!("from num_enum_run: two"),
    Ok(Num::Three) => println!("from num_enum_run: three"),
    */
    // 亦或:
    Ok(x) => {
      match x {
        v => println!("from num_enum_run: {:?}", v)
      }
    }
    _ => println!("from num_enum_run: other")
  }
}

使用as

fn main() {
  enum Num {
    One = 1,
    Two = 2,
    Three = 3,
  }

  let a = 1;

  // 思路:我们可以使用as将 Num枚举分支转为i32类型
  assert_eq!(a, Num::One as i32);

  // 因此:
  match a {
    x if x == Num::One as i32 => println!("one"),
    x if x == Num::Two as i32 => println!("two"),
    x if x == Num::Three as i32 => println!("two"),
    _ => println!("other")
  }
}

为枚举实现TryFrom 手动实现转换

use std::convert::TryFrom;
fn main() {
  #[derive(Debug, PartialEq)]
  enum Num {
    One = 1,
    Two = 2,
    Three = 3,
  }

  let a = 1;

  impl TryFrom<i32> for Num {
    type Error = ();

    fn try_from(v: i32) -> Result<Self, Self::Error> {
      match v {
        x if x == Num::One as i32 => Ok(Num::One),
        x if x == Num::Two as i32 => Ok(Num::Two),
        x if x == Num::Three as i32 => Ok(Num::Three),
        _ => Err(())
      }
    }
  }

  let b = Num::try_from(a);
  println!("{:?}", b);

  let c: Result<Num, ()> = a.try_into();
  println!("{:?}", c);

  assert_eq!(Ok(Num::Two), 2.try_into());


  // 同理
  impl From<Num> for i32 {
    fn from(value: Num) -> Self {
      value as i32
    }
  }

  let d: i32 = Num::Three.into();
  println!("{:?}", d);
}

使用 transmute 来实现转换

fn main() {
  #[derive(Debug, PartialEq)]
  #[repr(i32)]
  enum Num {
    One = 1,
    Two = 2,
    Three,
  }

  let a = 2;
  let b: Num = unsafe { std::mem::transmute(a) };
  println!("{:?}", b);
  assert_eq!(Num::Three, unsafe { std::mem::transmute(3) });

  let c: Num = unsafe { std::mem::transmute(100) };
  println!("c: {:?}", c);
  // assert_eq!(Num::Three, c); // 如果溢出,虽然也是Num::Three,但是却不相等
}