我能得到这样一个枚举的整数值:
enum MyEnum {
A = 1,
B,
C,
}
let x = MyEnum::C as i32;
但我似乎无法做到这一点:
match x {
MyEnum::A => {}
MyEnum::B => {}
MyEnum::C => {}
_ => {}
}
我怎么能对枚举或值要么匹配尝试转换x
回MyEnum
?
我可以看到像这对于枚举有用的功能,但它可能不存在:
impl MyEnum {
fn from<T>(val: &T) -> Option<MyEnum>;
}
Answer 1:
您可以利用匹配警卫写的相当,但笨重,结构:
match x {
x if x == MyEnum::A as i32 => ...,
x if x == MyEnum::B as i32 => ...,
x if x == MyEnum::C as i32 => ...,
_ => ...
}
std::mem::transmute
也可用于:
let y: MyEnum = unsafe { transmute(x as i8) };
但是,这需要你知道枚举的大小,这样你就可以转换为一个合适的标量第一,同时也将产生不确定的行为,如果x
不是枚举的有效值。
Answer 2:
你可以得到FromPrimitive
。 使用除锈2018简化进口语法:
use num_derive::FromPrimitive;
use num_traits::FromPrimitive;
#[derive(FromPrimitive)]
enum MyEnum {
A = 1,
B,
C,
}
fn main() {
let x = 2;
match FromPrimitive::from_i32(x) {
Some(MyEnum::A) => println!("Got A"),
Some(MyEnum::B) => println!("Got B"),
Some(MyEnum::C) => println!("Got C"),
None => println!("Couldn't convert {}", x),
}
}
在您的Cargo.toml
:
[dependencies]
num-traits = "0.2"
num-derive = "0.2"
在更多细节NUM-派生箱 ,见电除尘器。 示例使用的测试 。
Answer 3:
std::num::FromPrimitive
被标记为不稳定的 ,并且将不会被包括在锈病1.0。 作为一种变通方法,我写的enum_primitive
箱 ,其中出口宏enum_from_primitive!
一个包装了enum
声明,并自动添加的实现num::FromPrimitive
(从num
箱 )。 例:
#[macro_use]
extern crate enum_primitive;
extern crate num;
use num::FromPrimitive;
enum_from_primitive! {
#[derive(Debug, PartialEq)]
enum FooBar {
Foo = 17,
Bar = 42,
Baz,
}
}
fn main() {
assert_eq!(FooBar::from_i32(17), Some(FooBar::Foo));
assert_eq!(FooBar::from_i32(42), Some(FooBar::Bar));
assert_eq!(FooBar::from_i32(43), Some(FooBar::Baz));
assert_eq!(FooBar::from_i32(91), None);
}
Answer 4:
如果你确定该整数的值包括在枚举,你可以使用std::mem::transmute
。
这应该与使用#[repr(..)]
来控制的基本类型。
完整的例子:
#[repr(i32)]
enum MyEnum {
A = 1, B, C
}
fn main() {
let x = MyEnum::C;
let y = x as i32;
let z: MyEnum = unsafe { ::std::mem::transmute(y) };
// match the enum that came from an int
match z {
MyEnum::A => { println!("Found A"); }
MyEnum::B => { println!("Found B"); }
MyEnum::C => { println!("Found C"); }
}
}
请注意,不像一些其他的答案,这个只需要锈病的标准库。
Answer 5:
我写了一个简单的宏,其将该数值回枚举:
macro_rules! num_to_enum {
($num:expr => $enm:ident<$tpe:ty>{ $($fld:ident),+ }; $err:expr) => ({
match $num {
$(_ if $num == $enm::$fld as $tpe => { $enm::$fld })+
_ => $err
}
});
}
您可以使用它像这样:
#[repr(u8)] #[derive(Debug, PartialEq)]
enum MyEnum {
Value1 = 1,
Value2 = 2
}
fn main() {
let num = 1u8;
let enm: MyEnum = num_to_enum!(
num => MyEnum<u8>{ Value1, Value2 };
panic!("Cannot convert number to `MyEnum`")
);
println!("`enm`: {:?}", enm);
}
Answer 6:
如果您对匹配的整数是基于枚举的变体的顺序 ,你可以用扫弦生成枚举的迭代器,并采取正确的:
#[macro_use]
extern crate strum_macros; // 0.9.0
extern crate strum; // 0.9.0
use strum::IntoEnumIterator;
#[derive(Debug, PartialEq, EnumIter)]
enum MyEnum {
A = 1,
B,
C,
}
fn main() {
let e = MyEnum::iter().nth(2);
assert_eq!(e, Some(MyEnum::C));
}
文章来源: How do I match enum values with an integer?