使用Rust的枚举作为双向查找表

时间:2016-12-21 04:11:12

标签: enums rust lookup-tables

我正在编写通过D-Bus与NetworkManager交互的代码,我希望使用enum作为键值,如方案。

例如,我希望一次使用值0作为数字零,并在不同的上下文中使用此Unknown的字符串enum

pub enum NetworkManagerState {
    Unknown = 0,
    Asleep = 10,
    Disconnected = 20,
    Disconnecting = 30,
    Connecting = 40,
    ConnectedLocal = 50,
    ConnectedSite = 60,
    ConnectedGlobal = 70,
}

最干净,最惯用的方法是什么?有没有办法定义基于元组的枚举,每个条目看起来像(ConnectedSite, 60u32, "Connected")并在上下文中使用每个元组属性。

1 个答案:

答案 0 :(得分:5)

  1. 要将枚举转换为int,您可以使用as i32
  2. 要将i32演示到您的枚举,您可以使用enum_primitive crate:
  3. cargo.toml:

    [dependencies]
    enum_primitive = "*"
    

    main.rs:

    #[macro_use]
    extern crate enum_primitive;
    use enum_primitive::FromPrimitive;
    
    enum_from_primitive! {
    #[derive(Debug, PartialEq)]
    pub enum NetworkManagerState {
        Unknown = 0,
        Asleep = 10,
        Disconnected = 20,
        Disconnecting = 30,
        Connecting = 40,
        ConnectedLocal = 50,
        ConnectedSite = 60,
        ConnectedGlobal = 70,
    }
    }
    
    impl From<i32> for NetworkManagerState {
        fn from(val: i32) -> NetworkManagerState {
            NetworkManagerState::from_i32(val).expect("passed Value does not match an enum value!")
        }
    }
    impl From<NetworkManagerState> for i32 {
        fn from(val: NetworkManagerState) -> i32 {
            val as i32
        }
    }
    
    
    fn main() {
        let value_i32 = 40;
        let value_enum = NetworkManagerState::Connecting;
    
        // enum to i32
        println!("{:?}", value_enum as i32);
    
        // i32 to enum
        println!("{:?}", NetworkManagerState::from_i32(value_i32).unwrap());
    
        // using from trait
        let y: i32 = NetworkManagerState::Connecting.into();
        println!("{:?}", y);
    
        // using from trait
        let x: NetworkManagerState = 40.into();
        println!("{:?}", x);
    }
    

    使用from trait,您可以让您的函数接受可以转换为枚举的所有内容:

    fn fancy_function<T: Into<NetworkManagerState>>(value: T) {
        let internal: NetworkManagerState = value.into();
        println!("{:?}", internal);
    }
    
    ...
    
    fancy_function(60);
    fancy_function(NetworkManagerState::Asleep);