msgpack-rust icon indicating copy to clipboard operation
msgpack-rust copied to clipboard

Enum encoding discrepancy between `rmp-serde` and `rmpv` serde implementations

Open wuggen opened this issue 1 year ago • 0 comments

The serde implementation in rmp-serde encodes enum variants as a single-element mapping with the variant's name as a key; in contrast, rmpv's serde implementation encodes enum variants as a two-element array with the variant index as the first element.

Example:

use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize)]
pub enum Foo {
    Bar(String),
}

fn main() {
    let bar = Foo::Bar(String::from("Heya lol"));
    let encoded_bin = rmp_serde::encode::to_vec(&bar).unwrap();
    for b in &encoded_bin {
        print!("{b:02x}");
    }
    println!();

    let decoded_val = rmpv::decode::read_value::<&[u8]>(&mut encoded_bin.as_ref()).unwrap();
    println!("{decoded_val:?}");

    let encoded_val = rmpv::ext::to_value(&bar).unwrap();
    println!("{encoded_val:?}");
}

The above code outputs the following:

81a3426172a848657961206c6f6c
Map([(String(Utf8String { s: Ok("Bar") }), String(Utf8String { s: Ok("Heya lol") }))])
Array([Integer(PosInt(0)), Array([String(Utf8String { s: Ok("Heya lol") })])])

Either of these encodings is reasonable on its own, but it would seem that the two implementations should agree by default.

Relatedly, as noted in #323, the documentation incorrectly states that the default configuration in rmp-serde serializes enum variants as integer indices.

wuggen avatar Mar 28 '23 14:03 wuggen