关于rust:如何将远程箱子的枚举序列化和反序列化为数字?

How do I serialize and deserialize a remote crate's enum as a number?

我一直在尝试使用serde在Rust中为serialport板条箱设置以下配置,因此我可以在data_bits的配置中直观地提供7,但是它将反序列化为serialport::DataBits::Seven 。不幸的是,当我希望它是一个数字(7)而不是一个字符串(seven)时,它似乎失败了。

测试用例

cargo.toml

1
2
3
4
5
6
7
8
9
10
[package]
name ="serde_error"
version ="0.1.0"
authors = ["Jason Miller"]
edition ="2018"

[dependencies]
serialport ="3.3.0"
serde = { version ="1.0", features = ["derive"] }
ron ="0.5.1"

以下导致错误:

1
6:16: Expected identifier

main.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Debug)]
#[serde(remote ="serialport::DataBits")]
pub enum DataBitsDef {
    #[serde(rename ="5")]
    Five,
    #[serde(rename ="6")]
    Six,
    #[serde(rename ="7")]
    Seven,
    #[serde(rename ="8")]
    Eight,
}

fn default_data_bits() -> serialport::DataBits {
    serialport::DataBits::Eight
}

#[derive(Debug, Serialize, Deserialize)]
pub struct TransceiverSettings {
    pub vid: u16,
    pub pid: u16,
    pub baud_rate: u32,

    #[serde(default ="default_data_bits", with ="DataBitsDef")]
    pub data_bits: serialport::DataBits,
}

impl Default for TransceiverSettings {
    fn default() -> Self {
        Self {
            vid: 0x2341,
            pid: 0x0043,
            baud_rate: 115_200,

            data_bits: serialport::DataBits::Eight,
        }
    }
}

const TRX_CONFIG: &str ="
(
    vid: 0x2341,
    pid: 0x0043,
    baud_rate: 9600,
    data_bits: 7,
)
";

fn main() {
    match ron::de::from_str::<TransceiverSettings>(&TRX_CONFIG) {
        Err(e) => eprintln!("{}", e),
        Ok(c) => println!("{:?}", c),
    }
}

奇怪的是,将7编写为seven成功并返回:

1
TransceiverSettings { vid: 9025, pid: 67, baud_rate: 9600, data_bits: Seven }

main.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Debug)]
#[serde(remote ="serialport::DataBits")]
pub enum DataBitsDef {
    #[serde(rename ="5")]
    Five,
    #[serde(rename ="6")]
    Six,
    #[serde(rename ="seven")]
    Seven,
    #[serde(rename ="8")]
    Eight,
}

fn default_data_bits() -> serialport::DataBits {
    serialport::DataBits::Eight
}

#[derive(Debug, Serialize, Deserialize)]
pub struct TransceiverSettings {
    pub vid: u16,
    pub pid: u16,
    pub baud_rate: u32,

    #[serde(default ="default_data_bits", with ="DataBitsDef")]
    pub data_bits: serialport::DataBits,
}

impl Default for TransceiverSettings {
    fn default() -> Self {
        Self {
            vid: 0x2341,
            pid: 0x0043,
            baud_rate: 115_200,

            data_bits: serialport::DataBits::Eight,
        }
    }
}

const TRX_CONFIG: &str ="
(
    vid: 0x2341,
    pid: 0x0043,
    baud_rate: 9600,
    data_bits: seven,
)
";

fn main() {
    match ron::de::from_str::<TransceiverSettings>(&TRX_CONFIG) {
        Err(e) => eprintln!("{}", e),
        Ok(c) => println!("{:?}", c),
    }
}

serde_repr

serde文档中的给定示例之一似乎与我的情况有关,但是我尚未设法使其与我的设置配合使用。

Serialize enum as number
The serde_repr crate provides alternative derive macros that derive the same Serialize and Deserialize traits but delegate to the underlying representation of a C-like enum. This allows C-like enums to be formatted as integers rather than strings in JSON

1
2
3
4
5
6
7
8
#[derive(Serialize_repr, Deserialize_repr, PartialEq, Debug)]
#[repr(u8)]
enum SmallPrime {
    Two = 2,
    Three = 3,
    Five = 5,
    Seven = 7,
}

#[serde(remote)]的支持在serde_repr 0.1.5中不存在。您将需要提交拉取请求或发出请求以添加对此的支持。

相反,请遵循"如何使用Serde在反序列化过程中转换字段"中的建议?和如何使用Serde在序列化期间转换字段?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
use serde::{Deserialize, Serialize};

mod shim {
    use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer};
    use serialport::DataBits;

    pub fn serialize(v: &DataBits, s: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        use DataBits::*;

        let v: u8 = match v {
            Five => 5,
            Six => 6,
            Seven => 7,
            Eight => 8,
        };

        v.serialize(s)
    }

    pub fn deserialize<'de, D>(d: D) -> Result<DataBits, D::Error>
    where
        D: Deserializer<'de>,
    {
        use DataBits::*;

        match u8::deserialize(d)? {
            5 => Ok(Five),
            6 => Ok(Six),
            7 => Ok(Seven),
            8 => Ok(Eight),
            o => Err(D::Error::custom(format_args!("Invalid value {}", o))),
        }
    }
}

#[derive(Debug, Serialize, Deserialize)]
pub struct TransceiverSettings {
    pub vid: u16,
    pub pid: u16,
    pub baud_rate: u32,

    #[serde(default ="default_data_bits", with ="shim")]
    pub data_bits: serialport::DataBits,
}