我最接近用char区分枚举的是什么? [英] What's the closest I can get to discriminating an enum by a char?

查看:62
本文介绍了我最接近用char区分枚举的是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经写了很多遍这个问题,终于意识到我最大的问题是我不知道如何表示这些数据,这使得很难推理其余的代码。

I've written this question out many times, and have finally realized that my biggest problem is that I don't know how I want to represent this data, and that's making it really hard to reason about the rest of the code.

在Python中表示数据的方式:

The way the data is represented in Python:

class LSP():
    C_MASK_MAP={
        "A":"Ch A",
        "B":"Ch B",
        "C":"Ch C",
        "D":"Ch D",
        "T":"Tmpr",
        "Y":"Batt",
        "L":"Acc"
    }

    ADC_CHANS= (
        "Ch A",
        "Ch B",
        "Ch C",
        "Ch D",
        "Tmpr",
        "Batt"
    )

    ADC_MAJORS = (
        "Ch A",
        "Ch B",
        "Ch C",
    )

我的虚构的Rust代码(我知道名称需要更新,但是为了清楚起见,在这里是相同的):

My imaginary Rust code (I realize the names will need updating but are the same here for clarity):

enum C_MASK_MAP {
    Ch_A = 'A',
    Ch_B = 'B',
    Ch_C = 'C',
    Ch_D = 'D',
    Tmpr = 'T',
    Batt = 'Y',
    Acc  = 'L'
}
//...
let ADC_CHANS = [
    C_MASK_MAP::Ch_A,
    C_MASK_MAP::Ch_B,
    C_MASK_MAP::Ch_C,
    C_MASK_MAP::Ch_D,
    C_MASK_MAP::Tmpr,
    C_MASK_MAP::Batt
];

ADC_MAJORS = [
    C_MASK_MAP::Ch_A,
    C_MASK_MAP::Ch_B,
    C_MASK_MAP::Ch_C,
];

我考虑过制作 C_MASK_MAP a HashMap< char,&'static str> ,但是后来我陷入混乱,试图不制作一百万个 str s无处不在,并处理生命周期,同时避免使用 String s,以及避免引用静态 str &''static str 之类的东西)。

I've considered making C_MASK_MAP a HashMap<char, &'static str>, but then I ran into a huge mess trying not to make a million copies of the strs everywhere and dealing with lifetimes while avoiding making Strings, and the syntactic mess that is a reference to a static str (&&'static str or something).

我认为使用枚举(或类似枚举)的真正好处是,值不会那么大,并且更容易互换 C_MASK_MAP.get(key).expect( invalid key)

I think there'd be a real benefit to being able to use an enum (or similar) because the values wouldn't be as big and are more easily interchanged C_MASK_MAP.get(key).expect("invalid key") vs just casting.

推荐答案

您的字符串是前哨值;这是Python中的一种常见模式,但是在Rust中却不是这样:枚举就是这样:您正在类型系统中编码合法值。

Your strings are sentinel values; this is a common pattern in Python, but is not how things should be done in Rust: enums are what such things should be: you’re encoding the legal values in the type system.

您最终可能会遇到这样的情况:

You could end up with something like this:

#[derive(Clone, Copy)]
#[repr(u8)]
pub enum Mask {
    ChA = b'A',
    ChB = b'B',
    ChC = b'C',
    ChD = b'D',
    Tmpr = b'T',
    Batt = b'Y',
    Acc  = b'L',
}

// e.g. Mask::ChA.into() == 'A'
impl Into<char> for Mask {
    fn into(self) -> char {
        self as u8 as char
    }
}

impl Mask {
    // e.g. Mask::from('A') == Ok(Mask::ChA)
    pub fn from(c: char) -> Result<Mask, ()> {
        match c {
            'A' => Ok(Mask::ChA),
            'B' => Ok(Mask::ChB),
            'C' => Ok(Mask::ChC),
            'D' => Ok(Mask::ChD),
            'T' => Ok(Mask::Tmpr),
            'Y' => Ok(Mask::Batt),
            'L' => Ok(Mask::Acc),
            _ => Err(()),
        }
    }

    // e.g. Mask::ChA.is_chan() == true
    pub fn is_chan(&self) -> bool {
        match *self {
            Mask::ChA | Mask::ChB | Mask::ChC | Mask::ChD | Mask::Tmpr | Mask::Batt => true,
            Mask::Acc => false,
        }
    }

    // e.g. Mask::ChD.is_major() == false
    pub fn is_major(&self) -> bool {
        match *self {
            Mask::ChA | Mask::ChB | Mask::ChC => true,
            Mask::ChD | Mask::Tmpr | Mask::Batt | Mask::Acc => false,
        }
    }
}

如果需要也可以为 Mask 实现 std :: str :: FromStr ,这将允许 A .parse()== Ok(Mask :: ChA)

If you wanted you could implement std::str::FromStr for Mask as well, which would allow "A".parse() == Ok(Mask::ChA):

impl FromStr for Mask {
    type Err = ();

    fn from_str(s: &str) -> Result<Mask, ()> {
        match s {
            "A" => Ok(Mask::ChA),
            "B" => Ok(Mask::ChB),
            "C" => Ok(Mask::ChC),
            "D" => Ok(Mask::ChD),
            "T" => Ok(Mask::Tmpr),
            "Y" => Ok(Mask::Batt),
            "L" => Ok(Mask::Acc),
            _ => Err(()),
        }
    }
}

我怀疑 is_chan 等。也许比 ADC_CHANS 等更合适,但是如果您确实需要它们,它们可以很好地工作(您可以执行 [Mask; 6] ,但是如果您需要添加新元素,则会更改类型,如果公开的话,这是API兼容性中断):

I suspect that is_chan et al. may be more suitable than ADC_CHANS et al., but if you do actually need them, they work fine (you could do [Mask; 6] too, but if you need to add new elements it’d change the type which is an API compatibility break if public):

pub static ADC_CHANS: &'static [Mask] = &[
    Mask::ChA,
    Mask::ChB,
    Mask::ChC,
    Mask::ChD,
    Mask::Tmpr,
    Mask::Batt,
];

pub static ADC_MAJORS: &'static [Mask] = &[
    Mask::ChA,
    Mask::ChB,
    Mask::ChC,
];

这篇关于我最接近用char区分枚举的是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆