我可以得到这样的枚举的整数值:
enum MyEnum {
A = 1,
B,
C,
}
let x = MyEnum::C as i32;
Run Code Online (Sandbox Code Playgroud)
但我似乎无法做到这一点:
match x {
MyEnum::A => {}
MyEnum::B => {}
MyEnum::C => {}
_ => {}
}
Run Code Online (Sandbox Code Playgroud)
我怎样才能匹配枚举值或尝试转换x回MyEnum?
我可以看到这样的函数对枚举很有用,但它可能不存在:
impl MyEnum {
fn from<T>(val: &T) -> Option<MyEnum>;
}
Run Code Online (Sandbox Code Playgroud)
Ren*_*non 25
你可以派生出来FromPrimitive.使用Rust 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),
}
}
Run Code Online (Sandbox Code Playgroud)
在你的Cargo.toml:
[dependencies]
num-traits = "0.2"
num-derive = "0.2"
Run Code Online (Sandbox Code Playgroud)
num-derive crate中的更多细节,请参见esp.样本用于测试.
win*_*ner 14
您可以利用比赛防护来编写一个等效但更笨重的结构:
match x {
x if x == MyEnum::A as i32 => ...,
x if x == MyEnum::B as i32 => ...,
x if x == MyEnum::C as i32 => ...,
_ => ...
}
Run Code Online (Sandbox Code Playgroud)
std::mem::transmute 也可以用:
let y: MyEnum = unsafe { transmute(x as i8) };
Run Code Online (Sandbox Code Playgroud)
但是这需要您知道枚举的大小,因此您可以首先转换为适当的标量,如果x不是枚举的有效值,也会产生未定义的行为.
And*_*org 12
std::num::FromPrimitive被标记为不稳定,不会包含在Rust 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);
}
Run Code Online (Sandbox Code Playgroud)
如果您匹配的整数基于枚举变体的顺序,则可以使用strum生成枚举变体的迭代器并获取正确的迭代器:
#[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));
}
Run Code Online (Sandbox Code Playgroud)
如果您确定整数的值包含在枚举中,则可以使用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"); }
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,与其他一些答案不同,这只需要Rust的标准库.
从Rust 1.34开始,我建议实现TryFrom:
use std::convert::TryFrom;
impl TryFrom<i32> for MyEnum {
type Error = ();
fn try_from(v: i32) -> Result<Self, Self::Error> {
match v {
x if x == MyEnum::A as i32 => Ok(MyEnum::A),
x if x == MyEnum::B as i32 => Ok(MyEnum::B),
x if x == MyEnum::C as i32 => Ok(MyEnum::C),
_ => Err(()),
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后,您可以使用TryInto并处理可能的错误:
use std::convert::TryInto;
fn main() {
let x = MyEnum::C as i32;
match x.try_into() {
Ok(MyEnum::A) => println!("a"),
Ok(MyEnum::B) => println!("b"),
Ok(MyEnum::C) => println!("c"),
Err(_) => eprintln!("unknown number"),
}
}
Run Code Online (Sandbox Code Playgroud)
也可以看看:
| 归档时间: |
|
| 查看次数: |
20951 次 |
| 最近记录: |