Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add test to track #508 #509

Merged
merged 2 commits into from
Sep 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
59 changes: 59 additions & 0 deletions tests/508_value_adjacently_tagged_bug.rs
Original file line number Diff line number Diff line change
@@ -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::<TheEnum>(&ron).unwrap();
assert_eq!(de, value);

let ron_value = ron::from_str::<ron::Value>(&ron).unwrap();

// Known bug: ron::Value only stores a unit, cannot find a variant
let err = ron_value.into_rust::<TheEnum>().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::<TheEnum>(&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::<ron::Value>(&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::<TheEnum>().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::<ron::Value>("(\"Variant\",(0.1,0.1,0.1))").unwrap();
let de: TheEnum = ron_value.into_rust::<TheEnum>().unwrap();
assert_eq!(de, value);
}