語境
在通過使用其 XML 描述讀取二進制檔案時嘗試找到一種更簡單的方式來處理轉換為 rust 型別時,建議使用帶有單元型別的列舉而不是反序列化字串或 &str,以獲得更多的編譯器保證和避免一生;但是,讓 XML 直接反序列化到列舉單元變體中會導致一些問題。
XML 檔案
<Records>
<Record>
<name>Single</name>
<number>1</number>
<location>0</location>
<data_type>IEEE754LSBSingle</data_type>
<length>4</length>
</Record>
<Record>
<name>Double</name>
<number>2</number>
<location>4</location>
<data_type>IEEE754LSBDouble</data_type>
<length>8</length>
</Record>
<Record>
<name>SingleArr</name>
<number>3</number>
<location>11</location>
<data_type>IEEE754LSBSingleArr</data_type>
<length>8</length>
</Record>
<Record>
<name>DoubleArr</name>
<number>4</number>
<location>18</location>
<data_type>IEEE754LSBDoubleArr</data_type>
<length>16</length>
</Record>
</Records>
編碼
use binary_type_cast::PrettyPrint;
use quick_xml::{de::from_reader, DeError};
use serde::{Deserialize};
use std::{fs::File, io::BufReader};
#[derive(Clone, Copy, Debug, Deserialize)]
//#[serde(tag="data_type")]
//#[serde(untagged)]
pub enum DataTypes {
// 4 bytes
IEEE754LSBSingle,
// 8 bytes
IEEE754LSBDouble,
// [4 bytes, 4 bytes]
IEEE754LSBSingleArr,
// [8 bytes, 8 bytes]
IEEE754LSBDoubleArr,
// Include ASCIIString just to make sure records are still gathered even if none of them use this
ASCIIString,
}
#[derive(Debug, Deserialize)]
pub struct Records {
#[serde(rename="Record")]
pub records: Vec<Record>,
}
#[derive(Debug, Deserialize)]
pub struct Record {
pub name: String,
pub number: u32,
pub location: u32,
//#[serde(flatten)]
pub data_type: DataTypes,
pub length: u32
}
pub fn get_xml_record(file: &File) -> Result<Records, DeError> {
let reader = BufReader::new(file);
let records: Records = from_reader(reader).unwrap();
Ok(records)
}
fn main() {
let description = "./data/desc.xml";
if let Ok(file) = File::open(description) {
if let Ok(records) = get_xml_record(&file) {
println!("{:#?}",records);
}
}
}
我試圖實作在呈現的代碼中看到的注釋掉的 serde 屬性的各種組合。似乎創建一個自定義反序列化器將匹配 XML 中的字串,然后輸出相關的 DataTypes 變體,這基本上會復制原始帖子在另一個問題中的行為,其中字串被手動匹配和轉換。
uj5u.com熱心網友回復:
這似乎是一個錯誤quick-xml
我不用大驚小怪地使用它來作業serde-xml-rs:
use serde_xml_rs::from_str;
use serde::Deserialize;
#[derive(Clone, Copy, Debug, Deserialize)]
pub enum DataTypes {
// 4 bytes
IEEE754LSBSingle,
// 8 bytes
IEEE754LSBDouble,
// [4 bytes, 4 bytes]
IEEE754LSBSingleArr,
// [8 bytes, 8 bytes]
IEEE754LSBDoubleArr,
// Include ASCIIString just to make sure records are still gathered even if none of them use this
ASCIIString,
}
#[derive(Debug, Deserialize)]
pub struct Records {
#[serde(rename = "$value")]
pub records: Vec<Record>,
}
#[derive(Debug, Deserialize)]
pub struct Record {
pub name: String,
pub number: u32,
pub location: u32,
pub data_type: DataTypes,
pub length: u32
}
fn main() {
let source = r##"
<Records>
<Record>
<name>Single</name>
<number>1</number>
<location>0</location>
<data_type>IEEE754LSBSingle</data_type>
<length>4</length>
</Record>
<Record>
<name>Double</name>
<number>2</number>
<location>4</location>
<data_type>IEEE754LSBDouble</data_type>
<length>8</length>
</Record>
<Record>
<name>SingleArr</name>
<number>3</number>
<location>11</location>
<data_type>IEEE754LSBSingleArr</data_type>
<length>8</length>
</Record>
<Record>
<name>DoubleArr</name>
<number>4</number>
<location>18</location>
<data_type>IEEE754LSBDoubleArr</data_type>
<length>16</length>
</Record>
</Records>
"##;
let records: Records = from_str(source).unwrap();
dbg!(records);
}
輸出:
[src\main.rs:71] records = Records {
records: [
Record {
name: "Single",
number: 1,
location: 0,
data_type: IEEE754LSBSingle,
length: 4,
},
Record {
name: "Double",
number: 2,
location: 4,
data_type: IEEE754LSBDouble,
length: 8,
},
Record {
name: "SingleArr",
number: 3,
location: 11,
data_type: IEEE754LSBSingleArr,
length: 8,
},
Record {
name: "DoubleArr",
number: 4,
location: 18,
data_type: IEEE754LSBDoubleArr,
length: 16,
},
],
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/527429.html
標籤:xml序列化锈枚举塞尔德
上一篇:處理無元素回傳
