From 521d91c35e41b5c346fd69668fae4ce2016b516f Mon Sep 17 00:00:00 2001 From: SylvKT Date: Tue, 2 Jan 2024 22:41:23 -0500 Subject: [PATCH 01/25] prepare adding `explicit_struct_names` extension --- src/extensions.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/extensions.rs b/src/extensions.rs index 454db7931..6c0c53356 100644 --- a/src/extensions.rs +++ b/src/extensions.rs @@ -7,6 +7,8 @@ bitflags::bitflags! { const UNWRAP_NEWTYPES = 0x1; const IMPLICIT_SOME = 0x2; const UNWRAP_VARIANT_NEWTYPES = 0x4; + /// During deserialization, this extension requires that structs' names are stated explicitly. + const EXPLICIT_STRUCT_NAMES = 0x8; } } // GRCOV_EXCL_STOP @@ -19,6 +21,7 @@ impl Extensions { "unwrap_newtypes" => Some(Extensions::UNWRAP_NEWTYPES), "implicit_some" => Some(Extensions::IMPLICIT_SOME), "unwrap_variant_newtypes" => Some(Extensions::UNWRAP_VARIANT_NEWTYPES), + "explicit_struct_names" => Some(Extensions::EXPLICIT_STRUCT_NAMES), _ => None, } } @@ -40,19 +43,25 @@ mod tests { assert_eq!(ext, ext2); } + // todo: maybe make a macro for this? #[test] fn test_extension_serde() { roundtrip_extensions(Extensions::default()); roundtrip_extensions(Extensions::UNWRAP_NEWTYPES); roundtrip_extensions(Extensions::IMPLICIT_SOME); roundtrip_extensions(Extensions::UNWRAP_VARIANT_NEWTYPES); + roundtrip_extensions(Extensions::EXPLICIT_STRUCT_NAMES); roundtrip_extensions(Extensions::UNWRAP_NEWTYPES | Extensions::IMPLICIT_SOME); roundtrip_extensions(Extensions::UNWRAP_NEWTYPES | Extensions::UNWRAP_VARIANT_NEWTYPES); + roundtrip_extensions(Extensions::UNWRAP_NEWTYPES | Extensions::EXPLICIT_STRUCT_NAMES); roundtrip_extensions(Extensions::IMPLICIT_SOME | Extensions::UNWRAP_VARIANT_NEWTYPES); + roundtrip_extensions(Extensions::IMPLICIT_SOME | Extensions::EXPLICIT_STRUCT_NAMES); + roundtrip_extensions(Extensions::UNWRAP_VARIANT_NEWTYPES | Extensions::EXPLICIT_STRUCT_NAMES); roundtrip_extensions( Extensions::UNWRAP_NEWTYPES | Extensions::IMPLICIT_SOME - | Extensions::UNWRAP_VARIANT_NEWTYPES, + | Extensions::UNWRAP_VARIANT_NEWTYPES + | Extensions::EXPLICIT_STRUCT_NAMES, ); } } From 35b973e673ccc1093c7769ab9653d59541c488af Mon Sep 17 00:00:00 2001 From: SylvKT Date: Tue, 2 Jan 2024 23:04:51 -0500 Subject: [PATCH 02/25] add error handling, prepare to implement it, prepare to add test --- src/de/mod.rs | 4 ++++ src/error.rs | 2 ++ tests/522_explicit_struct_names.rs | 1 + 3 files changed, 7 insertions(+) create mode 100644 tests/522_explicit_struct_names.rs diff --git a/src/de/mod.rs b/src/de/mod.rs index 9707a7a1e..0edd6ab10 100644 --- a/src/de/mod.rs +++ b/src/de/mod.rs @@ -723,6 +723,10 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> { self.parser.skip_ws()?; + if self.parser.exts.contains(Extensions::EXPLICIT_STRUCT_NAMES) && name.len() == 0 { + return Err(Error::ExpectedStructName) + } + self.handle_struct_after_name(name, visitor) } diff --git a/src/error.rs b/src/error.rs index 74b65b297..17bae4dca 100644 --- a/src/error.rs +++ b/src/error.rs @@ -110,6 +110,7 @@ pub enum Error { SuggestRawIdentifier(String), ExpectedRawValue, ExceededRecursionLimit, + ExpectedStructName, } impl fmt::Display for SpannedError { @@ -281,6 +282,7 @@ impl fmt::Display for Error { "Exceeded recursion limit, try increasing `ron::Options::recursion_limit` \ and using `serde_stacker` to protect against a stack overflow", ), + Error::ExpectedStructName => f.write_str("Expected a struct name") } } } diff --git a/tests/522_explicit_struct_names.rs b/tests/522_explicit_struct_names.rs new file mode 100644 index 000000000..fdc5ab1d7 --- /dev/null +++ b/tests/522_explicit_struct_names.rs @@ -0,0 +1 @@ +fn explicit_struct_names() {} From f3722983d0de3a0b03308c7ef3fbb8f6bcab8261 Mon Sep 17 00:00:00 2001 From: SylvKT Date: Wed, 3 Jan 2024 22:08:01 -0500 Subject: [PATCH 03/25] implement extension, add test --- src/de/mod.rs | 4 --- src/error.rs | 4 +-- src/parse.rs | 6 +++- tests/522_explicit_struct_names.rs | 44 +++++++++++++++++++++++++++++- 4 files changed, 50 insertions(+), 8 deletions(-) diff --git a/src/de/mod.rs b/src/de/mod.rs index 0edd6ab10..9707a7a1e 100644 --- a/src/de/mod.rs +++ b/src/de/mod.rs @@ -723,10 +723,6 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> { self.parser.skip_ws()?; - if self.parser.exts.contains(Extensions::EXPLICIT_STRUCT_NAMES) && name.len() == 0 { - return Err(Error::ExpectedStructName) - } - self.handle_struct_after_name(name, visitor) } diff --git a/src/error.rs b/src/error.rs index 17bae4dca..9ce3dc072 100644 --- a/src/error.rs +++ b/src/error.rs @@ -110,7 +110,7 @@ pub enum Error { SuggestRawIdentifier(String), ExpectedRawValue, ExceededRecursionLimit, - ExpectedStructName, + ExpectedStructName(String), } impl fmt::Display for SpannedError { @@ -282,7 +282,7 @@ impl fmt::Display for Error { "Exceeded recursion limit, try increasing `ron::Options::recursion_limit` \ and using `serde_stacker` to protect against a stack overflow", ), - Error::ExpectedStructName => f.write_str("Expected a struct name") + Error::ExpectedStructName(ref name) => write!(f, "Expected a struct name `{}`, but none was found", name), } } } diff --git a/src/parse.rs b/src/parse.rs index fdc1b1073..47c69db37 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -666,7 +666,11 @@ impl<'a> Parser<'a> { pub fn consume_struct_name(&mut self, ident: &'static str) -> Result { if self.check_ident("") { - return Ok(false); + if self.exts.contains(Extensions::EXPLICIT_STRUCT_NAMES) { + return Err(Error::ExpectedStructName(ident.to_string())) + } else { + return Ok(false); + } } let found_ident = match self.identifier() { diff --git a/tests/522_explicit_struct_names.rs b/tests/522_explicit_struct_names.rs index fdc5ab1d7..f0b94730e 100644 --- a/tests/522_explicit_struct_names.rs +++ b/tests/522_explicit_struct_names.rs @@ -1 +1,43 @@ -fn explicit_struct_names() {} +use ron::{Options, extensions::Extensions, Error, from_str}; +use serde_derive::Deserialize; + +#[derive(Debug, Deserialize)] +struct Id(u32); + +#[derive(Debug, Deserialize)] +struct Foo { + #[allow(unused)] + pub id: Id, +} + +const EXPECT_ERROR_MESSAGE: &'static str = "expected `Err(Error::ExpectedStructName)`, deserializer returned `Ok`"; +const INCORRECT_ERROR_MESSAGE: &'static str = "expected error ExpectedStructName, found"; + +#[test] +fn explicit_struct_names() { + let options = Options::default() + .with_default_extension(Extensions::EXPLICIT_STRUCT_NAMES); + + // phase 1 + let content = r#"( + id: Id(3), + )"#; + let foo = options.from_str::(content); + match foo.expect_err(EXPECT_ERROR_MESSAGE).code { + Error::ExpectedStructName(_) => {}, + err => panic!("{INCORRECT_ERROR_MESSAGE} \"{err}\""), + } + + // phase 2 + let content = r#"Foo( + id: (3), + )"#; + let foo = options.from_str::(content); + match foo.expect_err(EXPECT_ERROR_MESSAGE).code { + Error::ExpectedStructName(_) => {}, + err => panic!("{INCORRECT_ERROR_MESSAGE} \"{err}\""), + } + + // phase 3 (use content from phase 2) + let _foo = from_str::(content).unwrap(); +} From cf7710ee2f98a10d9481c1320fc1a56a641c0348 Mon Sep 17 00:00:00 2001 From: SylvKT Date: Wed, 3 Jan 2024 22:14:16 -0500 Subject: [PATCH 04/25] update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index da3095450..4afeb39c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Allow `ron::value::RawValue` to capture any whitespace to the left and right of a ron value ([#487](https://github.com/ron-rs/ron/pull/487)) - Breaking: Enforce that ron always writes valid UTF-8 ([#488](https://github.com/ron-rs/ron/pull/488)) - Add convenient `Value::from` impls ([#498](https://github.com/ron-rs/ron/pull/498)) +- Add new extension `explicit_struct_names` which requires that struct names are included during deserialization ([#522](https://github.com/ron-rs/ron/pull/522)) ### Format Changes From 8605b975dba5eaac004bfc39946a254f311938b9 Mon Sep 17 00:00:00 2001 From: SylvKT Date: Wed, 3 Jan 2024 22:41:58 -0500 Subject: [PATCH 05/25] add documentation, improve comments --- docs/extensions.md | 24 ++++++++++++++++++++++++ tests/522_explicit_struct_names.rs | 6 +++--- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/docs/extensions.md b/docs/extensions.md index a84922022..9d07ca620 100644 --- a/docs/extensions.md +++ b/docs/extensions.md @@ -114,3 +114,27 @@ With the `unwrap_variant_newtypes` extension, the first structural layer inside ``` Note that when the `unwrap_variant_newtypes` extension is enabled, the first layer inside a newtype variant will **always** be unwrapped, i.e. it is no longer possible to write `A(Inner(a: 4, b: true))` or `A((a: 4, b: true))`. + +# explicit_struct_names +This extension requires that all structs have names attached to them. For example, the following deserializes perfectly fine: +```ron +Foo( + bar: Bar(42), +) +``` + +However, with the `explicit_struct_names` extension enabled, the following will throw an `ExpectedStructName` error: +```ron +( + bar: Bar(42), +) +``` + +Similarly, the following will throw the same error: +```ron +Foo( + bar: (42), +) +``` + +Note that if what you are parsing is spread across many files, you would likely use `Options::with_default_extension` to enable `Extensions::EXPLICIT_STRUCT_NAMES` before the parsing stage. This is because prepending `#![enable(explicit_struct_names)]` to the contents of every file you parse would violate DRY (Don't Repeat Yourself). diff --git a/tests/522_explicit_struct_names.rs b/tests/522_explicit_struct_names.rs index f0b94730e..e8c4eba0d 100644 --- a/tests/522_explicit_struct_names.rs +++ b/tests/522_explicit_struct_names.rs @@ -18,7 +18,7 @@ fn explicit_struct_names() { let options = Options::default() .with_default_extension(Extensions::EXPLICIT_STRUCT_NAMES); - // phase 1 + // phase 1 (regular structs) let content = r#"( id: Id(3), )"#; @@ -28,7 +28,7 @@ fn explicit_struct_names() { err => panic!("{INCORRECT_ERROR_MESSAGE} \"{err}\""), } - // phase 2 + // phase 2 (newtype structs) let content = r#"Foo( id: (3), )"#; @@ -38,6 +38,6 @@ fn explicit_struct_names() { err => panic!("{INCORRECT_ERROR_MESSAGE} \"{err}\""), } - // phase 3 (use content from phase 2) + // phase 3 (test without this extension) let _foo = from_str::(content).unwrap(); } From 5f29b8c5afdd82d4d36c1597188759548a4ac079 Mon Sep 17 00:00:00 2001 From: SylvKT Date: Wed, 3 Jan 2024 22:47:28 -0500 Subject: [PATCH 06/25] add example using the Options method --- docs/extensions.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/docs/extensions.md b/docs/extensions.md index 9d07ca620..36fd58c87 100644 --- a/docs/extensions.md +++ b/docs/extensions.md @@ -138,3 +138,16 @@ Foo( ``` Note that if what you are parsing is spread across many files, you would likely use `Options::with_default_extension` to enable `Extensions::EXPLICIT_STRUCT_NAMES` before the parsing stage. This is because prepending `#![enable(explicit_struct_names)]` to the contents of every file you parse would violate DRY (Don't Repeat Yourself). + +Here is an example of how to enable `explicit_struct_names` using this method: +```rust +use ron::extensions::Extensions; +use ron::options::Options; + +// Setup the options +let options = Options::default().with_default_extension(Extensions::EXPLICIT_STRUCT_NAMES); +// Retrieve the contents of the file +let file_contents: &str = /* ... */; +// Parse the file's contents +let foo: Foo = options.from_str(file_contents)?; +``` From c2fdc0a6113d99e955dae2bc94d5f1c3ae680b13 Mon Sep 17 00:00:00 2001 From: Sylv Date: Thu, 4 Jan 2024 10:28:25 -0500 Subject: [PATCH 07/25] fix wording in ExpectedStructName error message Co-authored-by: Juniper Tyree <50025784+juntyr@users.noreply.github.com> --- src/error.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/error.rs b/src/error.rs index 9ce3dc072..2bf9064e3 100644 --- a/src/error.rs +++ b/src/error.rs @@ -282,7 +282,7 @@ impl fmt::Display for Error { "Exceeded recursion limit, try increasing `ron::Options::recursion_limit` \ and using `serde_stacker` to protect against a stack overflow", ), - Error::ExpectedStructName(ref name) => write!(f, "Expected a struct name `{}`, but none was found", name), + Error::ExpectedStructName(ref name) => write!(f, "Expected the explicit struct name `{}`, but none was found", name), } } } From c7c4a8a229c321e7ecf4e2916d7051d154aa2d3c Mon Sep 17 00:00:00 2001 From: SylvKT Date: Thu, 4 Jan 2024 11:52:04 -0500 Subject: [PATCH 08/25] add tuple struct test, use all codepaths --- tests/522_explicit_struct_names.rs | 42 ++++++++++++++++++------------ 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/tests/522_explicit_struct_names.rs b/tests/522_explicit_struct_names.rs index e8c4eba0d..fbbcd60ba 100644 --- a/tests/522_explicit_struct_names.rs +++ b/tests/522_explicit_struct_names.rs @@ -4,14 +4,18 @@ use serde_derive::Deserialize; #[derive(Debug, Deserialize)] struct Id(u32); +#[derive(Debug, Deserialize)] +struct Position(f32, f32); + #[derive(Debug, Deserialize)] struct Foo { #[allow(unused)] pub id: Id, + #[allow(unused)] + pub position: Position, } const EXPECT_ERROR_MESSAGE: &'static str = "expected `Err(Error::ExpectedStructName)`, deserializer returned `Ok`"; -const INCORRECT_ERROR_MESSAGE: &'static str = "expected error ExpectedStructName, found"; #[test] fn explicit_struct_names() { @@ -19,25 +23,31 @@ fn explicit_struct_names() { .with_default_extension(Extensions::EXPLICIT_STRUCT_NAMES); // phase 1 (regular structs) - let content = r#"( + let content_regular = r#"( id: Id(3), + position: Position(0.0, 8.72), )"#; - let foo = options.from_str::(content); - match foo.expect_err(EXPECT_ERROR_MESSAGE).code { - Error::ExpectedStructName(_) => {}, - err => panic!("{INCORRECT_ERROR_MESSAGE} \"{err}\""), - } + let foo = options.from_str::(content_regular); + assert_eq!(foo.expect_err(EXPECT_ERROR_MESSAGE).code, Error::ExpectedStructName("Foo".to_string())); // phase 2 (newtype structs) - let content = r#"Foo( + let content_newtype = r#"Foo( id: (3), + position: Position(0.0, 8.72), )"#; - let foo = options.from_str::(content); - match foo.expect_err(EXPECT_ERROR_MESSAGE).code { - Error::ExpectedStructName(_) => {}, - err => panic!("{INCORRECT_ERROR_MESSAGE} \"{err}\""), - } - - // phase 3 (test without this extension) - let _foo = from_str::(content).unwrap(); + let foo = options.from_str::(content_newtype); + assert_eq!(foo.expect_err(EXPECT_ERROR_MESSAGE).code, Error::ExpectedStructName("Id".to_string())); + + // phase 3 (tuple structs) + let content_tuple = r#"Foo( + id: Id(3), + position: (0.0, 8.72), + )"#; + let foo = options.from_str::(content_tuple); + assert_eq!(foo.expect_err(EXPECT_ERROR_MESSAGE).code, Error::ExpectedStructName("Position".to_string())); + + // phase 4 (test without this extension) + let _foo = from_str::(content_regular).unwrap(); + let _foo = from_str::(content_newtype).unwrap(); + let _foo = from_str::(content_tuple).unwrap(); } From 6dabe55c5c65f6032749b62dcee63a751e428196 Mon Sep 17 00:00:00 2001 From: SylvKT Date: Thu, 4 Jan 2024 11:58:26 -0500 Subject: [PATCH 09/25] in test: rename each foo variable to correspond with their phase (formatting) --- tests/522_explicit_struct_names.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/522_explicit_struct_names.rs b/tests/522_explicit_struct_names.rs index fbbcd60ba..b1e815195 100644 --- a/tests/522_explicit_struct_names.rs +++ b/tests/522_explicit_struct_names.rs @@ -47,7 +47,7 @@ fn explicit_struct_names() { assert_eq!(foo.expect_err(EXPECT_ERROR_MESSAGE).code, Error::ExpectedStructName("Position".to_string())); // phase 4 (test without this extension) - let _foo = from_str::(content_regular).unwrap(); - let _foo = from_str::(content_newtype).unwrap(); - let _foo = from_str::(content_tuple).unwrap(); + let _foo1 = from_str::(content_regular).unwrap(); + let _foo2 = from_str::(content_newtype).unwrap(); + let _foo3 = from_str::(content_tuple).unwrap(); } From d59f6727520a9871eacccbe05789114b07fa0e64 Mon Sep 17 00:00:00 2001 From: SylvKT Date: Thu, 4 Jan 2024 12:23:33 -0500 Subject: [PATCH 10/25] fix extensions test --- src/extensions.rs | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/src/extensions.rs b/src/extensions.rs index 6c0c53356..66df9a64c 100644 --- a/src/extensions.rs +++ b/src/extensions.rs @@ -43,25 +43,12 @@ mod tests { assert_eq!(ext, ext2); } - // todo: maybe make a macro for this? #[test] fn test_extension_serde() { - roundtrip_extensions(Extensions::default()); - roundtrip_extensions(Extensions::UNWRAP_NEWTYPES); - roundtrip_extensions(Extensions::IMPLICIT_SOME); - roundtrip_extensions(Extensions::UNWRAP_VARIANT_NEWTYPES); - roundtrip_extensions(Extensions::EXPLICIT_STRUCT_NAMES); - roundtrip_extensions(Extensions::UNWRAP_NEWTYPES | Extensions::IMPLICIT_SOME); - roundtrip_extensions(Extensions::UNWRAP_NEWTYPES | Extensions::UNWRAP_VARIANT_NEWTYPES); - roundtrip_extensions(Extensions::UNWRAP_NEWTYPES | Extensions::EXPLICIT_STRUCT_NAMES); - roundtrip_extensions(Extensions::IMPLICIT_SOME | Extensions::UNWRAP_VARIANT_NEWTYPES); - roundtrip_extensions(Extensions::IMPLICIT_SOME | Extensions::EXPLICIT_STRUCT_NAMES); - roundtrip_extensions(Extensions::UNWRAP_VARIANT_NEWTYPES | Extensions::EXPLICIT_STRUCT_NAMES); - roundtrip_extensions( - Extensions::UNWRAP_NEWTYPES - | Extensions::IMPLICIT_SOME - | Extensions::UNWRAP_VARIANT_NEWTYPES - | Extensions::EXPLICIT_STRUCT_NAMES, - ); + // iterate over the powerset of all extensions (i.e. every possible combination of extensions) + for bits in Extensions::empty().bits()..=Extensions::all().bits() { + let extensions = Extensions::from_bits_retain(bits); + roundtrip_extensions(extensions); + } } } From b620b3f03430508e75422414999ff579f2feb78e Mon Sep 17 00:00:00 2001 From: SylvKT Date: Thu, 4 Jan 2024 12:28:37 -0500 Subject: [PATCH 11/25] add check for Error::ExpectedStructName message, suppress unnecessary compiler warning --- src/error.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/error.rs b/src/error.rs index 2bf9064e3..b495ff7b8 100644 --- a/src/error.rs +++ b/src/error.rs @@ -570,6 +570,7 @@ mod tests { "Unexpected leading underscore in a number", ); check_error_message(&Error::UnexpectedChar('🦀'), "Unexpected char \'🦀\'"); + #[allow(invalid_from_utf8)] check_error_message( &Error::Utf8Error(std::str::from_utf8(b"error: \xff\xff\xff\xff").unwrap_err()), "invalid utf-8 sequence of 1 bytes from index 7", @@ -668,6 +669,10 @@ mod tests { "Exceeded recursion limit, try increasing `ron::Options::recursion_limit` \ and using `serde_stacker` to protect against a stack overflow", ); + check_error_message( + &Error::ExpectedStructName(String::from("Struct")), + "Expected the explicit struct name `Struct`, but none was found", + ) } fn check_error_message(err: &T, msg: &str) { From ec5f527c1dd218285df2b1a6e505619926927603 Mon Sep 17 00:00:00 2001 From: SylvKT Date: Thu, 4 Jan 2024 12:55:22 -0500 Subject: [PATCH 12/25] resolve redundant else block --- src/parse.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/parse.rs b/src/parse.rs index 47c69db37..0374f3ffc 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -668,9 +668,9 @@ impl<'a> Parser<'a> { if self.check_ident("") { if self.exts.contains(Extensions::EXPLICIT_STRUCT_NAMES) { return Err(Error::ExpectedStructName(ident.to_string())) - } else { - return Ok(false); } + + return Ok(false); } let found_ident = match self.identifier() { From 3f584af9c2806d59cc766bf56b00ec8fdaef8ab6 Mon Sep 17 00:00:00 2001 From: SylvKT Date: Thu, 4 Jan 2024 13:05:22 -0500 Subject: [PATCH 13/25] add "see also" blurbs, OR the `explicit_struct_names` value in `PrettyConfig::struct_names` --- docs/extensions.md | 9 ++++++++- src/extensions.rs | 2 ++ src/ser/mod.rs | 4 +++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/docs/extensions.md b/docs/extensions.md index 36fd58c87..af5401f6f 100644 --- a/docs/extensions.md +++ b/docs/extensions.md @@ -116,7 +116,14 @@ With the `unwrap_variant_newtypes` extension, the first structural layer inside Note that when the `unwrap_variant_newtypes` extension is enabled, the first layer inside a newtype variant will **always** be unwrapped, i.e. it is no longer possible to write `A(Inner(a: 4, b: true))` or `A((a: 4, b: true))`. # explicit_struct_names -This extension requires that all structs have names attached to them. For example, the following deserializes perfectly fine: +During serialization, this extension emits struct names. For instance, this would be emitted: +```ron +Foo( + bar: Bar(42), +) +``` + +During deserialization, this extension requires that all structs have names attached to them. For example, the following deserializes perfectly fine: ```ron Foo( bar: Bar(42), diff --git a/src/extensions.rs b/src/extensions.rs index 66df9a64c..2ea4a7446 100644 --- a/src/extensions.rs +++ b/src/extensions.rs @@ -7,6 +7,8 @@ bitflags::bitflags! { const UNWRAP_NEWTYPES = 0x1; const IMPLICIT_SOME = 0x2; const UNWRAP_VARIANT_NEWTYPES = 0x4; + /// During serialization, this extension emits struct names. See also [`PrettyConfig::struct_names`](crate::ser::PrettyConfig::struct_names) for the [`PrettyConfig`](crate::ser::PrettyConfig) equivalent. + /// /// During deserialization, this extension requires that structs' names are stated explicitly. const EXPLICIT_STRUCT_NAMES = 0x8; } diff --git a/src/ser/mod.rs b/src/ser/mod.rs index cfc30c430..ec0de57bd 100644 --- a/src/ser/mod.rs +++ b/src/ser/mod.rs @@ -162,11 +162,13 @@ impl PrettyConfig { } /// Configures whether to emit struct names. + /// + /// Note that when using the `explicit_struct_names` extension, this method will use an OR operation on the extension and the [`PrettyConfig`] option. See also [`Extensions::EXPLICIT_STRUCT_NAMES`] for the extension equivalent. /// /// Default: `false` #[must_use] pub fn struct_names(mut self, struct_names: bool) -> Self { - self.struct_names = struct_names; + self.struct_names = struct_names | self.extensions.contains(Extensions::EXPLICIT_STRUCT_NAMES); self } From 1057138266f823b532dcc634274b1dbc877ee5f9 Mon Sep 17 00:00:00 2001 From: SylvKT Date: Thu, 4 Jan 2024 13:13:10 -0500 Subject: [PATCH 14/25] fix formatting --- src/error.rs | 8 ++++++-- src/extensions.rs | 2 +- src/parse.rs | 2 +- src/ser/mod.rs | 5 +++-- tests/522_explicit_struct_names.rs | 25 +++++++++++++++++-------- 5 files changed, 28 insertions(+), 14 deletions(-) diff --git a/src/error.rs b/src/error.rs index b495ff7b8..4dc6b83ba 100644 --- a/src/error.rs +++ b/src/error.rs @@ -282,7 +282,11 @@ impl fmt::Display for Error { "Exceeded recursion limit, try increasing `ron::Options::recursion_limit` \ and using `serde_stacker` to protect against a stack overflow", ), - Error::ExpectedStructName(ref name) => write!(f, "Expected the explicit struct name `{}`, but none was found", name), + Error::ExpectedStructName(ref name) => write!( + f, + "Expected the explicit struct name `{}`, but none was found", + name + ), } } } @@ -672,7 +676,7 @@ mod tests { check_error_message( &Error::ExpectedStructName(String::from("Struct")), "Expected the explicit struct name `Struct`, but none was found", - ) + ); } fn check_error_message(err: &T, msg: &str) { diff --git a/src/extensions.rs b/src/extensions.rs index 2ea4a7446..997dcb991 100644 --- a/src/extensions.rs +++ b/src/extensions.rs @@ -8,7 +8,7 @@ bitflags::bitflags! { const IMPLICIT_SOME = 0x2; const UNWRAP_VARIANT_NEWTYPES = 0x4; /// During serialization, this extension emits struct names. See also [`PrettyConfig::struct_names`](crate::ser::PrettyConfig::struct_names) for the [`PrettyConfig`](crate::ser::PrettyConfig) equivalent. - /// + /// /// During deserialization, this extension requires that structs' names are stated explicitly. const EXPLICIT_STRUCT_NAMES = 0x8; } diff --git a/src/parse.rs b/src/parse.rs index 0374f3ffc..0144d0ade 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -667,7 +667,7 @@ impl<'a> Parser<'a> { pub fn consume_struct_name(&mut self, ident: &'static str) -> Result { if self.check_ident("") { if self.exts.contains(Extensions::EXPLICIT_STRUCT_NAMES) { - return Err(Error::ExpectedStructName(ident.to_string())) + return Err(Error::ExpectedStructName(ident.to_string())); } return Ok(false); diff --git a/src/ser/mod.rs b/src/ser/mod.rs index ec0de57bd..0ef5eca3f 100644 --- a/src/ser/mod.rs +++ b/src/ser/mod.rs @@ -162,13 +162,14 @@ impl PrettyConfig { } /// Configures whether to emit struct names. - /// + /// /// Note that when using the `explicit_struct_names` extension, this method will use an OR operation on the extension and the [`PrettyConfig`] option. See also [`Extensions::EXPLICIT_STRUCT_NAMES`] for the extension equivalent. /// /// Default: `false` #[must_use] pub fn struct_names(mut self, struct_names: bool) -> Self { - self.struct_names = struct_names | self.extensions.contains(Extensions::EXPLICIT_STRUCT_NAMES); + self.struct_names = + struct_names | self.extensions.contains(Extensions::EXPLICIT_STRUCT_NAMES); self } diff --git a/tests/522_explicit_struct_names.rs b/tests/522_explicit_struct_names.rs index b1e815195..f9ac3ffaf 100644 --- a/tests/522_explicit_struct_names.rs +++ b/tests/522_explicit_struct_names.rs @@ -1,4 +1,4 @@ -use ron::{Options, extensions::Extensions, Error, from_str}; +use ron::{extensions::Extensions, from_str, Error, Options}; use serde_derive::Deserialize; #[derive(Debug, Deserialize)] @@ -15,12 +15,12 @@ struct Foo { pub position: Position, } -const EXPECT_ERROR_MESSAGE: &'static str = "expected `Err(Error::ExpectedStructName)`, deserializer returned `Ok`"; +const EXPECT_ERROR_MESSAGE: &'static str = + "expected `Err(Error::ExpectedStructName)`, deserializer returned `Ok`"; #[test] fn explicit_struct_names() { - let options = Options::default() - .with_default_extension(Extensions::EXPLICIT_STRUCT_NAMES); + let options = Options::default().with_default_extension(Extensions::EXPLICIT_STRUCT_NAMES); // phase 1 (regular structs) let content_regular = r#"( @@ -28,7 +28,10 @@ fn explicit_struct_names() { position: Position(0.0, 8.72), )"#; let foo = options.from_str::(content_regular); - assert_eq!(foo.expect_err(EXPECT_ERROR_MESSAGE).code, Error::ExpectedStructName("Foo".to_string())); + assert_eq!( + foo.expect_err(EXPECT_ERROR_MESSAGE).code, + Error::ExpectedStructName("Foo".to_string()) + ); // phase 2 (newtype structs) let content_newtype = r#"Foo( @@ -36,15 +39,21 @@ fn explicit_struct_names() { position: Position(0.0, 8.72), )"#; let foo = options.from_str::(content_newtype); - assert_eq!(foo.expect_err(EXPECT_ERROR_MESSAGE).code, Error::ExpectedStructName("Id".to_string())); - + assert_eq!( + foo.expect_err(EXPECT_ERROR_MESSAGE).code, + Error::ExpectedStructName("Id".to_string()) + ); + // phase 3 (tuple structs) let content_tuple = r#"Foo( id: Id(3), position: (0.0, 8.72), )"#; let foo = options.from_str::(content_tuple); - assert_eq!(foo.expect_err(EXPECT_ERROR_MESSAGE).code, Error::ExpectedStructName("Position".to_string())); + assert_eq!( + foo.expect_err(EXPECT_ERROR_MESSAGE).code, + Error::ExpectedStructName("Position".to_string()) + ); // phase 4 (test without this extension) let _foo1 = from_str::(content_regular).unwrap(); From 00a65cdd9e01cfc54066387069f5218b09a74378 Mon Sep 17 00:00:00 2001 From: SylvKT Date: Thu, 4 Jan 2024 13:18:13 -0500 Subject: [PATCH 15/25] fix coverage --- src/extensions.rs | 2 ++ tests/non_string_tag.rs | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/extensions.rs b/src/extensions.rs index 997dcb991..c319b948c 100644 --- a/src/extensions.rs +++ b/src/extensions.rs @@ -29,11 +29,13 @@ impl Extensions { } } +// GRCOV_EXCL_START impl Default for Extensions { fn default() -> Self { Extensions::empty() } } +// GRCOV_EXCL_STOP #[cfg(test)] mod tests { diff --git a/tests/non_string_tag.rs b/tests/non_string_tag.rs index 4f896a220..d9ef40902 100644 --- a/tests/non_string_tag.rs +++ b/tests/non_string_tag.rs @@ -26,7 +26,7 @@ macro_rules! test_non_tag { } } - #[derive(Debug)] + #[derive(Debug)] // GRCOV_EXCL_LINE struct InternallyTagged; impl<'de> Deserialize<'de> for InternallyTagged { From 966675a4cf624ffa2da77f61dd8b047881705089 Mon Sep 17 00:00:00 2001 From: SylvKT Date: Thu, 4 Jan 2024 19:43:05 -0500 Subject: [PATCH 16/25] move OR operation to Serializer::struct_names --- src/ser/mod.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/ser/mod.rs b/src/ser/mod.rs index 0ef5eca3f..b1ed2f41d 100644 --- a/src/ser/mod.rs +++ b/src/ser/mod.rs @@ -163,13 +163,12 @@ impl PrettyConfig { /// Configures whether to emit struct names. /// - /// Note that when using the `explicit_struct_names` extension, this method will use an OR operation on the extension and the [`PrettyConfig`] option. See also [`Extensions::EXPLICIT_STRUCT_NAMES`] for the extension equivalent. + /// See also [`Extensions::EXPLICIT_STRUCT_NAMES`] for the extension equivalent. /// /// Default: `false` #[must_use] pub fn struct_names(mut self, struct_names: bool) -> Self { - self.struct_names = - struct_names | self.extensions.contains(Extensions::EXPLICIT_STRUCT_NAMES); + self.struct_names = struct_names; self } @@ -639,10 +638,15 @@ impl Serializer { Ok(()) } + /// Checks if struct names should be emitted + /// + /// Note that when using the `explicit_struct_names` extension, this method will use an OR operation on the extension and the [`PrettyConfig::struct_names`] option. See also [`Extensions::EXPLICIT_STRUCT_NAMES`] for the extension equivalent. fn struct_names(&self) -> bool { self.pretty .as_ref() - .map_or(false, |(pc, _)| pc.struct_names) + .map_or(false, |(pc, _)| { + pc.struct_names | pc.extensions.contains(Extensions::EXPLICIT_STRUCT_NAMES) + }) } } From 08ebb5d850177053f09854d6c6769561c44e3078 Mon Sep 17 00:00:00 2001 From: SylvKT Date: Thu, 4 Jan 2024 19:50:22 -0500 Subject: [PATCH 17/25] fix pretty print in Error::ExpectedStructName message --- src/error.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/error.rs b/src/error.rs index 4dc6b83ba..46be80dd6 100644 --- a/src/error.rs +++ b/src/error.rs @@ -284,8 +284,8 @@ impl fmt::Display for Error { ), Error::ExpectedStructName(ref name) => write!( f, - "Expected the explicit struct name `{}`, but none was found", - name + "Expected the explicit struct name {}, but none was found", + Identifier(name) ), } } From 8add0cc0463c2409394c707a98c989400f95406f Mon Sep 17 00:00:00 2001 From: SylvKT Date: Thu, 4 Jan 2024 21:23:28 -0500 Subject: [PATCH 18/25] fix Serializer::struct_names --- src/ser/mod.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/ser/mod.rs b/src/ser/mod.rs index b1ed2f41d..d5b3f6843 100644 --- a/src/ser/mod.rs +++ b/src/ser/mod.rs @@ -642,11 +642,12 @@ impl Serializer { /// /// Note that when using the `explicit_struct_names` extension, this method will use an OR operation on the extension and the [`PrettyConfig::struct_names`] option. See also [`Extensions::EXPLICIT_STRUCT_NAMES`] for the extension equivalent. fn struct_names(&self) -> bool { - self.pretty - .as_ref() - .map_or(false, |(pc, _)| { - pc.struct_names | pc.extensions.contains(Extensions::EXPLICIT_STRUCT_NAMES) - }) + self.extensions() + .contains(Extensions::EXPLICIT_STRUCT_NAMES) + || self + .pretty + .as_ref() + .map_or(false, |(pc, _)| pc.struct_names) } } From 17cb912a0a5bc5a08d845e33228dcc2e755ef804 Mon Sep 17 00:00:00 2001 From: SylvKT Date: Sat, 6 Jan 2024 11:32:13 -0500 Subject: [PATCH 19/25] add trunk config files to .gitignore (for those who use it) --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 621062929..4e715885c 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,6 @@ # Generated by Cargo /target/ /Cargo.lock + +# VSCode Extensions +/.trunk From 2d99d9e50f2691c88c137261c2815c44fdc83181 Mon Sep 17 00:00:00 2001 From: SylvKT Date: Sat, 6 Jan 2024 12:02:23 -0500 Subject: [PATCH 20/25] add .DS_Store to the .gitignore (you'll thank me later) --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 4e715885c..ae37927d9 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,6 @@ # VSCode Extensions /.trunk + +# MacOS Shenanigans +.DS_Store From 90de04f84947f35322f41cf138f93dc3230518c3 Mon Sep 17 00:00:00 2001 From: SylvKT Date: Sat, 6 Jan 2024 15:01:03 -0500 Subject: [PATCH 21/25] add test for enum variants, clean up `Extensions::from_ident` code --- src/extensions.rs | 14 +++++----- src/ser/mod.rs | 16 ++--------- tests/522_explicit_struct_names.rs | 45 ++++++++++++++++++++++++++---- tests/non_string_tag.rs | 2 +- 4 files changed, 51 insertions(+), 26 deletions(-) diff --git a/src/extensions.rs b/src/extensions.rs index c319b948c..9ed804dbf 100644 --- a/src/extensions.rs +++ b/src/extensions.rs @@ -16,16 +16,16 @@ bitflags::bitflags! { // GRCOV_EXCL_STOP impl Extensions { - /// Creates an extension flag from an ident. + /// Creates an extension flag from an idents. #[must_use] pub fn from_ident(ident: &str) -> Option { - match ident { - "unwrap_newtypes" => Some(Extensions::UNWRAP_NEWTYPES), - "implicit_some" => Some(Extensions::IMPLICIT_SOME), - "unwrap_variant_newtypes" => Some(Extensions::UNWRAP_VARIANT_NEWTYPES), - "explicit_struct_names" => Some(Extensions::EXPLICIT_STRUCT_NAMES), - _ => None, + for (name, extension) in Extensions::all().iter_names() { + if ident == name.to_lowercase() { + return Some(extension); + } } + + None } } diff --git a/src/ser/mod.rs b/src/ser/mod.rs index d5b3f6843..fc040937f 100644 --- a/src/ser/mod.rs +++ b/src/ser/mod.rs @@ -415,20 +415,10 @@ impl Serializer { let non_default_extensions = !options.default_extensions; - if (non_default_extensions & conf.extensions).contains(Extensions::IMPLICIT_SOME) { - writer.write_str("#![enable(implicit_some)]")?; + for (extension_name, _) in (non_default_extensions & conf.extensions).iter_names() { + write!(writer, "#![enable({})]", extension_name.to_lowercase())?; writer.write_str(&conf.new_line)?; - }; - if (non_default_extensions & conf.extensions).contains(Extensions::UNWRAP_NEWTYPES) { - writer.write_str("#![enable(unwrap_newtypes)]")?; - writer.write_str(&conf.new_line)?; - }; - if (non_default_extensions & conf.extensions) - .contains(Extensions::UNWRAP_VARIANT_NEWTYPES) - { - writer.write_str("#![enable(unwrap_variant_newtypes)]")?; - writer.write_str(&conf.new_line)?; - }; + } }; Ok(Serializer { output: writer, diff --git a/tests/522_explicit_struct_names.rs b/tests/522_explicit_struct_names.rs index f9ac3ffaf..ea12979c5 100644 --- a/tests/522_explicit_struct_names.rs +++ b/tests/522_explicit_struct_names.rs @@ -1,18 +1,32 @@ -use ron::{extensions::Extensions, from_str, Error, Options}; -use serde_derive::Deserialize; +use ron::{ + extensions::Extensions, + from_str, + ser::{to_string_pretty, PrettyConfig}, + Error, Options, +}; +use serde_derive::{Deserialize, Serialize}; -#[derive(Debug, Deserialize)] +#[derive(Debug, Serialize, Deserialize)] struct Id(u32); -#[derive(Debug, Deserialize)] +#[derive(Debug, Serialize, Deserialize)] struct Position(f32, f32); -#[derive(Debug, Deserialize)] +#[derive(Debug, Serialize, Deserialize)] +enum Query { + None, + Creature(Id), + Location(Position), +} + +#[derive(Debug, Serialize, Deserialize)] struct Foo { #[allow(unused)] pub id: Id, #[allow(unused)] pub position: Position, + #[allow(unused)] + pub query: Query, } const EXPECT_ERROR_MESSAGE: &'static str = @@ -21,11 +35,17 @@ const EXPECT_ERROR_MESSAGE: &'static str = #[test] fn explicit_struct_names() { let options = Options::default().with_default_extension(Extensions::EXPLICIT_STRUCT_NAMES); + let foo_ser = Foo { + id: Id(3), + position: Position(0.0, 8.72), + query: Query::Creature(Id(4)), + }; // phase 1 (regular structs) let content_regular = r#"( id: Id(3), position: Position(0.0, 8.72), + query: None, )"#; let foo = options.from_str::(content_regular); assert_eq!( @@ -37,6 +57,7 @@ fn explicit_struct_names() { let content_newtype = r#"Foo( id: (3), position: Position(0.0, 8.72), + query: None, )"#; let foo = options.from_str::(content_newtype); assert_eq!( @@ -48,6 +69,7 @@ fn explicit_struct_names() { let content_tuple = r#"Foo( id: Id(3), position: (0.0, 8.72), + query: None, )"#; let foo = options.from_str::(content_tuple); assert_eq!( @@ -59,4 +81,17 @@ fn explicit_struct_names() { let _foo1 = from_str::(content_regular).unwrap(); let _foo2 = from_str::(content_newtype).unwrap(); let _foo3 = from_str::(content_tuple).unwrap(); + + // phase 5 (test serialization) + let pretty_config = PrettyConfig::new().extensions(Extensions::EXPLICIT_STRUCT_NAMES); + let content = to_string_pretty(&foo_ser, pretty_config).unwrap(); + assert_eq!( + content, + r#"#![enable(explicit_struct_names)] +Foo( + id: Id(3), + position: Position(0.0, 8.72), + query: Creature(Id(4)), +)"# + ); } diff --git a/tests/non_string_tag.rs b/tests/non_string_tag.rs index d9ef40902..6c6c206e5 100644 --- a/tests/non_string_tag.rs +++ b/tests/non_string_tag.rs @@ -112,7 +112,7 @@ macro_rules! test_tag { } } - #[derive(Debug)] + #[derive(Debug)] // GRCOV_EXCL_LINE struct InternallyTagged; impl<'de> Deserialize<'de> for InternallyTagged { From 7283d7b1d848e2fc9f7cc857eb1faa18c6e5189a Mon Sep 17 00:00:00 2001 From: Sylv Date: Sat, 6 Jan 2024 15:37:49 -0500 Subject: [PATCH 22/25] Fix grammar error in extensions.rs Co-authored-by: Juniper Tyree <50025784+juntyr@users.noreply.github.com> --- src/extensions.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/extensions.rs b/src/extensions.rs index 9ed804dbf..c4862b791 100644 --- a/src/extensions.rs +++ b/src/extensions.rs @@ -16,7 +16,7 @@ bitflags::bitflags! { // GRCOV_EXCL_STOP impl Extensions { - /// Creates an extension flag from an idents. + /// Creates an extension flag from an ident. #[must_use] pub fn from_ident(ident: &str) -> Option { for (name, extension) in Extensions::all().iter_names() { From 313b30f88d0db5e5973281f99923309b9b1cb1af Mon Sep 17 00:00:00 2001 From: SylvKT Date: Sat, 6 Jan 2024 16:25:17 -0500 Subject: [PATCH 23/25] add `unwrap_variant_newtypes` to test --- tests/522_explicit_struct_names.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/522_explicit_struct_names.rs b/tests/522_explicit_struct_names.rs index ea12979c5..b790a6740 100644 --- a/tests/522_explicit_struct_names.rs +++ b/tests/522_explicit_struct_names.rs @@ -83,15 +83,16 @@ fn explicit_struct_names() { let _foo3 = from_str::(content_tuple).unwrap(); // phase 5 (test serialization) - let pretty_config = PrettyConfig::new().extensions(Extensions::EXPLICIT_STRUCT_NAMES); + let pretty_config = PrettyConfig::new().extensions(Extensions::EXPLICIT_STRUCT_NAMES | Extensions::UNWRAP_VARIANT_NEWTYPES); let content = to_string_pretty(&foo_ser, pretty_config).unwrap(); assert_eq!( content, - r#"#![enable(explicit_struct_names)] + r#"#![enable(unwrap_variant_newtypes)] +#![enable(explicit_struct_names)] Foo( id: Id(3), position: Position(0.0, 8.72), - query: Creature(Id(4)), + query: Creature(4), )"# ); } From 94fabf3a011020cb7d0dfa26475c5188e809b949 Mon Sep 17 00:00:00 2001 From: SylvKT Date: Sat, 6 Jan 2024 16:30:08 -0500 Subject: [PATCH 24/25] add to phase 5 a deserialize test --- tests/522_explicit_struct_names.rs | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/tests/522_explicit_struct_names.rs b/tests/522_explicit_struct_names.rs index b790a6740..a686ccc1c 100644 --- a/tests/522_explicit_struct_names.rs +++ b/tests/522_explicit_struct_names.rs @@ -6,20 +6,20 @@ use ron::{ }; use serde_derive::{Deserialize, Serialize}; -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, PartialEq, Serialize, Deserialize)] struct Id(u32); -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, PartialEq, Serialize, Deserialize)] struct Position(f32, f32); -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, PartialEq, Serialize, Deserialize)] enum Query { None, Creature(Id), Location(Position), } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, PartialEq, Serialize, Deserialize)] struct Foo { #[allow(unused)] pub id: Id, @@ -83,7 +83,8 @@ fn explicit_struct_names() { let _foo3 = from_str::(content_tuple).unwrap(); // phase 5 (test serialization) - let pretty_config = PrettyConfig::new().extensions(Extensions::EXPLICIT_STRUCT_NAMES | Extensions::UNWRAP_VARIANT_NEWTYPES); + let pretty_config = PrettyConfig::new() + .extensions(Extensions::EXPLICIT_STRUCT_NAMES | Extensions::UNWRAP_VARIANT_NEWTYPES); let content = to_string_pretty(&foo_ser, pretty_config).unwrap(); assert_eq!( content, @@ -95,4 +96,12 @@ Foo( query: Creature(4), )"# ); + let foo_de = from_str::(&content); + match foo_de { + Err(err) => panic!( + "failed to deserialize with `explicit_struct_names` and `unwrap_variant_newtypes`: {}", + err + ), + Ok(foo_de) => assert_eq!(foo_de, foo_ser), + } } From 4bf6ef754e49fc4c7e0b4d4e18614a2902017db0 Mon Sep 17 00:00:00 2001 From: SylvKT Date: Sat, 6 Jan 2024 16:31:41 -0500 Subject: [PATCH 25/25] add GRCOV_EXCL --- tests/522_explicit_struct_names.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/522_explicit_struct_names.rs b/tests/522_explicit_struct_names.rs index a686ccc1c..7a9a7d463 100644 --- a/tests/522_explicit_struct_names.rs +++ b/tests/522_explicit_struct_names.rs @@ -98,10 +98,12 @@ Foo( ); let foo_de = from_str::(&content); match foo_de { + // GRCOV_EXCL_START Err(err) => panic!( "failed to deserialize with `explicit_struct_names` and `unwrap_variant_newtypes`: {}", err ), + // GRCOV_EXCL_STOP Ok(foo_de) => assert_eq!(foo_de, foo_ser), } }