Change the representation of Enums

Aperta
#717 12 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
5/5
Tempo stimato
Più di una settimana
Idoneità per principianti
25/100
Tipo di issue
Funzionalità
Chiarezza
Specificata chiaramente
Stato di attività
Ferma
Stack tecnologico
rust

Direzione di ricerca

Start with the Serde serialization code that handles enum variants; the issue does not name a file or test. Compare the requested XML representations with the existing enum handling and check how deserialization reads them. Done means unit, newtype, tuple, and struct variants serialize and round-trip as described.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

help wanted question serde

serde_json supports enums:

Kind Enum field
Unit "field": "Unit",
Newtype "field": { "Newtype": 42 },
Tuple "field": { "Tuple": [42, "answer"] },
Struct "field": { "Struct": {"q": 42, "a":"answer"} },
enum Kinds {             // Enum name as:
    Unit,                 // Value
    Newtype(i32),         // Key
    Tuple((i32, String)), // Key
    Struct(MyStruct),     // Key
}

https://docs.rs/quick-xml/latest/quick_xml/de/index.html#normal-enum-variant

so quick-xml should too:

Kind Enum field
Unit <field>Unit</field>
Newtype <field><Newtype>42</Newtype></field>
Tuple <field><Tuple>42</Tuple><Tuple>answer</Tuple></field>
Struct <field><Struct><q>42</q><a>answer</a></Struct></field>
enum Kinds {             // Enum name as:
    Unit,                 // Value
    Newtype(i32),         // Tag
    Tuple((i32, String)), // Tag
    Struct(MyStruct),     // Tag
}

Currently the above XML won't be generated (gives an error) while JSON would even parse back into Rust enum.
Unsupported operation: cannot serialize enum newtype variant

[Details] Ser/deserialization of enum - crate comparison:
// [package]
// name = "xml_vs_json"
// version = "0.1.0"
// edition = "2021"

// [dependencies]
// eyre = "0.6.12"
// quick-xml = { version = "0.31.0", features = ["serde", "serialize"] }
// rmp-serde = "1.1.2"
// serde = { version = "1.0.197", features = ["derive"] }
// serde_json = "1.0.114"
// serde_yaml = "0.9.32"
// toml = "0.8.10"

use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Eq, PartialEq, Debug)]
pub struct MyStruct {
    pub i8_value: i8,
    pub choice_value: MyChoice,
    pub choice_list: Vec<MyChoice>,
}

#[derive(Serialize, Deserialize, Eq, PartialEq, Debug)]
pub enum MyChoice {
    ChoiceA(MyChoiceA),
    ChoiceB(MyChoiceB),
}

#[derive(Serialize, Deserialize, Eq, PartialEq, Debug)]
pub struct MyChoiceA {
    pub choice_i32: i32,
}

#[derive(Serialize, Deserialize, Eq, PartialEq, Debug)]
pub struct MyChoiceB {
    pub choice_i64: i64,
    pub choice_text: String,
}

fn main() {
    let result = run();
    if let Err(err) = result {
        println!("err: {err}");
    }
}

fn run() -> eyre::Result<()> {
    let a = MyStruct {
        i8_value: 8,
        choice_value: MyChoice::ChoiceA(MyChoiceA { choice_i32: 32 }),

        choice_list: vec![
            MyChoice::ChoiceA(MyChoiceA { choice_i32: 32 }),
            MyChoice::ChoiceB(MyChoiceB {
                choice_i64: 64,
                choice_text: "my text".to_string(),
            }),
            MyChoice::ChoiceA(MyChoiceA { choice_i32: 32 }),
        ],
    };

    try_reencode_all(&a)?;

    Ok(())
}


fn try_reencode_all(a: &MyStruct) -> eyre::Result<()> {
    // pass
    let a_json = reencode_json(&a)?;
    assert_eq!(a, &a_json);

    // pass
    let a_toml = reencode_toml(&a)?;
    assert_eq!(a, &a_toml);

    // pass
    let a_yaml = reencode_yaml(&a)?;
    assert_eq!(a, &a_yaml);

    // pass
    let a_msgpack = reencode_msgpack(&a)?;
    assert_eq!(a, &a_msgpack);


    // fail: Unsupported operation: cannot serialize enum newtype variant `MyChoice::ChoiceA`
    let a_qxml = reencode_quick_xml(&a)?;
    assert_eq!(a, &a_qxml);
    Ok(())
}



fn reencode_json(input: &MyStruct) -> eyre::Result<MyStruct> {
    let json_str: String = serde_json::to_string(&input)?;
    println!("serde_json: {json_str}");
    let output = serde_json::from_str(&json_str)?;
    Ok(output)
}

fn reencode_toml(input: &MyStruct) -> eyre::Result<MyStruct> {
    let toml_str: String = toml::to_string(&input)?;
    println!("toml: {toml_str}");
    let output = toml::from_str(&toml_str)?;
    Ok(output)
}

fn reencode_yaml(input: &MyStruct) -> eyre::Result<MyStruct> {
    let yaml_str: String = serde_yaml::to_string(&input)?;
    println!("yaml: {yaml_str}");
    let output = serde_yaml::from_str(&yaml_str)?;
    Ok(output)
}

fn reencode_msgpack(input: &MyStruct) -> eyre::Result<MyStruct> {
    let msgpack_bytes: Vec<u8> = rmp_serde::to_vec(&input)?;
    println!("rmp_serde: {msgpack_bytes:?}");
    let output = rmp_serde::from_slice(&msgpack_bytes)?;
    Ok(output)
}



fn reencode_quick_xml(input: &MyStruct) -> eyre::Result<MyStruct> {
    // serialization does not work
    let qxml_str: String = quick_xml::se::to_string(&input)?;
    println!("quick_xml::se: {qxml_str}");
    let output = quick_xml::de::from_str(&qxml_str)?;
    Ok(output)
}
Lingua principale
Rust
Stelle
1.6k
Fork
299
Merge medio
2g 4h
PR unite (30g)
9

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di tafia/quick-xml

Tutte le issue di tafia/quick-xml

Issue simili

Altre issue su Rust

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.