如何将远程板条箱的枚举序列化和反序列化为数字?

Jas*_*son 2 rust serde

我一直在试图建立以下配置的serialport拉斯特箱用serde,这样我就可以直观地提供7在我的配置了data_bits,但它会被反序列化serialport::DataBits::Seven。不幸的是,当我希望它是数字 ( 7) 而不是字符串 ( seven) 时,它似乎失败了。

测试用例

货物.toml

[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"
Run Code Online (Sandbox Code Playgroud)

以下结果导致错误:

[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"
Run Code Online (Sandbox Code Playgroud)

主文件

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),
    }
}
Run Code Online (Sandbox Code Playgroud)

奇怪的是,写作7的seven成功和回报:

6:16: Expected identifier
Run Code Online (Sandbox Code Playgroud)

主文件

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),
    }
}
Run Code Online (Sandbox Code Playgroud)

serde_repr

serde 文档中给定的示例之一似乎与我的案例相关,但我还没有设法让它与我的设置一起工作。

序列化枚举作为数
的serde_repr板条箱提供了导出相同的序列化和反序列化性状但委托给一个类C的枚举的基本表示替代派生宏。这允许类似 C 的枚举被格式化为整数而不是 JSON 中的字符串

#[derive(Serialize_repr, Deserialize_repr, PartialEq, Debug)]
#[repr(u8)]
enum SmallPrime {
    Two = 2,
    Three = 3,
    Five = 5,
    Seven = 7,
}
Run Code Online (Sandbox Code Playgroud)

She*_*ter 5

支持#[serde(remote)]是不存在的serde_repr 0.1.5。您需要提交拉取请求或问题以添加对它的支持。

相反,请遵循如何在使用 Serde 进行反序列化期间转换字段中的建议?以及如何使用 Serde 在序列化期间转换字段?:

use serde::{Deserialize, Serialize};

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

    pub fn serialize<S>(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,
}
Run Code Online (Sandbox Code Playgroud)