-
Notifications
You must be signed in to change notification settings - Fork 136
Description
Consider the following types:
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(untagged)]
enum MyValue {
Int(i64),
String(String),
Enum(Enum),
List(Vec<MyValue>),
}
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
enum Enum {
First(String),
Second(i64),
}
Let's try serializing a MyValue::Enum
value like the following: MyValue::Enum(Enum::First("foo".to_string()))
. Its RON-serialized value is First("foo")
.
That First("foo")
value unfortunately deserializes to MyValue::List([MyValue::String("foo")])
instead of our original enum-based value. This is surprising to me, because the deserialization code decides to ignore the First
prefix entirely, and skip forward until the (
then deserialize a list with it. It's especially surprising because the MyValue::Enum
variant is before the MyValue::List
variant, and yet we still get a MyValue::List
back instead of MyValue::Enum
.
Here's a complete repro:
#[cfg(test)]
mod tests {
use serde::{Serialize, Deserialize};
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(untagged)]
enum MyValue {
Int(i64),
String(String),
Enum(Enum),
List(Vec<MyValue>),
}
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
enum Enum {
First(String),
Second(i64),
}
fn serialize_then_deserialize(value: &MyValue) -> MyValue {
ron::from_str(ron::to_string(value).unwrap().as_str()).unwrap()
}
#[test]
fn test() {
let value = MyValue::Enum(Enum::First("foo".to_string()));
let deserialized = serialize_then_deserialize(&value);
assert_eq!(value, deserialized, "Serialized as: {}", ron::to_string(&value).unwrap());
}
}
This fails with:
running 1 test
thread 'file::tests::test' panicked at 'assertion failed: `(left == right)`
left: `Enum(First("foo"))`,
right: `List([String("foo")])`: Serialized as: First("foo")', src/file.rs:X:9
Thanks to everyone that contributes to building and maintaining this awesome library! Any advice on avoiding this issue would be much appreciated.