diff --git a/CHANGELOG.md b/CHANGELOG.md index 240b614f..fc2a753a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Bump MSRV to 1.46.0 ([#361](https://github.com/ron-rs/ron/pull/361)) - Fix issue [#337](https://github.com/ron-rs/ron/issues/337) by removing `decimal_floats` PrettyConfig option and unconditional decimals in floats ([#363](https://github.com/ron-rs/ron/pull/363)) - Fix issue [#203](https://github.com/ron-rs/ron/issues/203) with full de error positioning ([#356](https://github.com/ron-rs/ron/pull/356)) +- Fix issue [#367](https://github.com/ron-rs/ron/issues/367) with eager implicit some ([#368](https://github.com/ron-rs/ron/pull/368)) ## [0.7.0] - 2021-10-22 diff --git a/docs/extensions.md b/docs/extensions.md index 4069472a..b44fb02e 100644 --- a/docs/extensions.md +++ b/docs/extensions.md @@ -42,7 +42,7 @@ You can add this extension by adding the following attribute at the top of your `#![enable(implicit_some)]` -This feature enables RON to automatically convert any value to `Some(value)` if the deserialized struct requires it. +This feature enables RON to automatically convert any value to `Some(value)` if the deserialized type requires it. ```rust struct Object { @@ -66,6 +66,15 @@ Enabling the feature would automatically infer `Some(x)` if `x` is given. In thi ) ``` +With this extension enabled, explicitly given `None` and `Some(..)` will be matched eagerly on `Option>>`, i.e. +* `5` -> `Some(Some(Some(5)))` +* `None` -> `None` +* `Some(5)` -> `Some(Some(Some(5)))` +* `Some(None)` -> `Some(None)` +* `Some(Some(5))` -> `Some(Some(Some(5)))` +* `Some(Some(None))` -> `Some(Some(None))` +* `Some(Some(Some(5)))` -> `Some(Some(Some(5)))` + # unwrap_variant_newtypes You can add this extension by adding the following attribute at the top of your RON document: diff --git a/src/de/mod.rs b/src/de/mod.rs index e0d09f46..6f4afbdd 100644 --- a/src/de/mod.rs +++ b/src/de/mod.rs @@ -349,8 +349,6 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> { { if self.bytes.consume("None") { visitor.visit_none() - } else if self.bytes.exts.contains(Extensions::IMPLICIT_SOME) { - visitor.visit_some(&mut *self) } else if self.bytes.consume("Some") && { self.bytes.skip_ws()?; self.bytes.consume("(") @@ -366,6 +364,8 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> { } else { Err(Error::ExpectedOptionEnd) } + } else if self.bytes.exts.contains(Extensions::IMPLICIT_SOME) { + visitor.visit_some(&mut *self) } else { Err(Error::ExpectedOption) } diff --git a/tests/367_implicit_some.rs b/tests/367_implicit_some.rs new file mode 100644 index 00000000..4eeac4df --- /dev/null +++ b/tests/367_implicit_some.rs @@ -0,0 +1,108 @@ +#[derive(Debug, PartialEq, serde::Deserialize, serde::Serialize)] +struct MaybeFields { + f1: i64, + f2: Option, + f3: Option>, +} + +#[test] +fn test_recursive_implicit_some() { + // Test case provided by d86leader in + // https://github.com/ron-rs/ron/issues/367#issue-1147920589 + + let x1: std::result::Result = + ron::from_str("#![enable(implicit_some)]\n(f1: 1)"); + let x2: std::result::Result = + ron::from_str("#![enable(implicit_some)]\n(f1: 1, f2: None, f3: None)"); + let x3: std::result::Result = + ron::from_str("#![enable(implicit_some)]\n(f1: 1, f2: 2, f3: 3)"); + let x4: std::result::Result = + ron::from_str("#![enable(implicit_some)]\n(f1: 1, f2: 2, f3: Some(3))"); + let x5: std::result::Result = + ron::from_str("#![enable(implicit_some)]\n(f1: 1, f2: 2, f3: Some(Some(3)))"); + let x6: std::result::Result = + ron::from_str("#![enable(implicit_some)]\n(f1: 1, f2: 2, f3: Some(None))"); + + assert_eq!( + x1, + Ok(MaybeFields { + f1: 1, + f2: None, + f3: None + }) + ); + assert_eq!( + x2, + Ok(MaybeFields { + f1: 1, + f2: None, + f3: None + }) + ); + assert_eq!( + x3, + Ok(MaybeFields { + f1: 1, + f2: Some(2), + f3: Some(Some(3)) + }) + ); + assert_eq!( + x4, + Ok(MaybeFields { + f1: 1, + f2: Some(2), + f3: Some(Some(3)) + }) + ); + assert_eq!( + x5, + Ok(MaybeFields { + f1: 1, + f2: Some(2), + f3: Some(Some(3)) + }) + ); + assert_eq!( + x6, + Ok(MaybeFields { + f1: 1, + f2: Some(2), + f3: Some(None) + }) + ); +} + +#[test] +fn test_nested_implicit_some() { + assert_eq!( + ron::from_str::>>>("#![enable(implicit_some)]\n5"), + Ok(Some(Some(Some(5)))) + ); + assert_eq!( + ron::from_str::>>>("#![enable(implicit_some)]\nNone"), + Ok(None) + ); + assert_eq!( + ron::from_str::>>>("#![enable(implicit_some)]\nSome(5)"), + Ok(Some(Some(Some(5)))) + ); + assert_eq!( + ron::from_str::>>>("#![enable(implicit_some)]\nSome(None)"), + Ok(Some(None)) + ); + assert_eq!( + ron::from_str::>>>("#![enable(implicit_some)]\nSome(Some(5))"), + Ok(Some(Some(Some(5)))) + ); + assert_eq!( + ron::from_str::>>>("#![enable(implicit_some)]\nSome(Some(None))"), + Ok(Some(Some(None))) + ); + assert_eq!( + ron::from_str::>>>( + "#![enable(implicit_some)]\nSome(Some(Some(5)))" + ), + Ok(Some(Some(Some(5)))) + ); +}