From 416b13277549b77e0814a1735ea0e59a3c33b7f8 Mon Sep 17 00:00:00 2001 From: Juniper Tyree <50025784+juntyr@users.noreply.github.com> Date: Tue, 19 Sep 2023 10:14:29 +0300 Subject: [PATCH] Add test to track #508 (#509) * Add a test to track known bugs for #508 * Document ron::Value restriction --- README.md | 2 + tests/508_value_adjacently_tagged_bug.rs | 59 ++++++++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 tests/508_value_adjacently_tagged_bug.rs diff --git a/README.md b/README.md index d3f9eadd8..5a70578f4 100644 --- a/README.md +++ b/README.md @@ -197,6 +197,8 @@ While data structures with any of these attributes should generally roundtrip th Please file a [new issue](https://github.com/ron-rs/ron/issues/new) if you come across a use case which is not listed among the above restrictions but still breaks. +While RON guarantees roundtrips like Rust -> RON -> Rust for Rust types using non-`deserialize_any`-based implementations, RON does not yet make any guarantees about roundtrips through `ron::Value`. For instance, even when RON -> Rust works, RON -> `ron::Value` -> Rust, or RON -> `ron::Value` -> RON -> Rust may not work. We plan on improving `ron::Value` in an upcoming version of RON, though this work is partially blocked on [serde#1183](https://github.com/serde-rs/serde/issues/1183). + [^serde-enum-hack]: Deserialising an internally, adjacently, or un-tagged enum requires detecting `serde`'s internal `serde::__private::de::content::Content` content type so that RON can describe the deserialised data structure in serde's internal JSON-like format. This detection only works for the automatically-derived [`Deserialize`](https://docs.rs/serde/latest/serde/de/trait.Deserialize.html) impls on enums. See [#451](https://github.com/ron-rs/ron/pull/451) for more details. [^serde-flatten-hack]: Deserialising a flattened struct from a map requires that the struct's [`Visitor::expecting`](https://docs.rs/serde/latest/serde/de/trait.Visitor.html#tymethod.expecting) implementation formats a string starting with `"struct "`. This is the case for automatically-derived [`Deserialize`](https://docs.rs/serde/latest/serde/de/trait.Deserialize.html) impls on structs. See [#455](https://github.com/ron-rs/ron/pull/455) for more details. diff --git a/tests/508_value_adjacently_tagged_bug.rs b/tests/508_value_adjacently_tagged_bug.rs new file mode 100644 index 000000000..c237c2ca0 --- /dev/null +++ b/tests/508_value_adjacently_tagged_bug.rs @@ -0,0 +1,59 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +#[serde(tag = "type", content = "value")] +enum TheEnum { + Variant([f32; 3]), +} + +#[test] +fn roundtrip_through_value() { + let value = TheEnum::Variant([0.1, 0.1, 0.1]); + + let ron = ron::to_string(&value).unwrap(); + assert_eq!(ron, "(type:Variant,value:(0.1,0.1,0.1))"); + + let de = ron::from_str::(&ron).unwrap(); + assert_eq!(de, value); + + let ron_value = ron::from_str::(&ron).unwrap(); + + // Known bug: ron::Value only stores a unit, cannot find a variant + let err = ron_value.into_rust::().unwrap_err(); + assert_eq!( + err, + ron::Error::InvalidValueForType { + expected: String::from("variant of enum TheEnum"), + found: String::from("a unit value") + } + ); + + let old_serde_ron: &str = "(type:\"Variant\",value:(0.1,0.1,0.1))"; + + // Known bug: serde no longer uses strings in > v1.0.180 to deserialize the variant + let err = ron::from_str::(&old_serde_ron).unwrap_err(); + assert_eq!( + err, + ron::error::SpannedError { + code: ron::Error::ExpectedIdentifier, + position: ron::error::Position { line: 1, col: 7 }, + } + ); + + let ron_value = ron::from_str::(&old_serde_ron).unwrap(); + + // Known bug: ron::Value is asked for an enum but has no special handling for it (yet) + let err = ron_value.into_rust::().unwrap_err(); + assert_eq!( + err, + ron::Error::InvalidValueForType { + expected: String::from("variant of enum TheEnum"), + found: String::from("the string \"Variant\"") + } + ); + + // This still works, but is a bug as well + let ron_value = ron::from_str::("(\"Variant\",(0.1,0.1,0.1))").unwrap(); + let de: TheEnum = ron_value.into_rust::().unwrap(); + assert_eq!(de, value); +}