From b3467878617886af7f96e3d5f5b597ed5ace9fe7 Mon Sep 17 00:00:00 2001 From: Diggory Blake Date: Thu, 17 Feb 2022 15:56:34 +0000 Subject: [PATCH] Fix struct-in-map diffing --- Cargo.toml | 10 ++++-- examples/nested_map.rs | 79 ++++++++++++++++++++++++++++++++++++++++++ src/implementation.rs | 1 + 3 files changed, 87 insertions(+), 3 deletions(-) create mode 100644 examples/nested_map.rs diff --git a/Cargo.toml b/Cargo.toml index 46b2c86..63c5638 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,10 @@ [package] name = "serde-diff" version = "0.4.1" -authors = ["Karl Bergström ", "Philip Degarmo "] +authors = [ + "Karl Bergström ", + "Philip Degarmo ", +] readme = "README.md" exclude = ["examples/*"] license = "Apache-2.0 OR MIT" @@ -17,10 +20,11 @@ maintenance = { status = "experimental" } [dependencies] serde-diff-derive = { version = "0.4.0", path = "serde-diff-derive" } -serde = { version = "1", features = [ "derive" ] } -serde_derive = { version = "1", features = ["deserialize_in_place"]} +serde = { version = "1", features = ["derive"] } +serde_derive = { version = "1", features = ["deserialize_in_place"] } [dev-dependencies] serde_json = "1.0" bincode = "1.2" rmp-serde = "0.15.0" +maplit = "1.0.2" diff --git a/examples/nested_map.rs b/examples/nested_map.rs new file mode 100644 index 0000000..b77f2fa --- /dev/null +++ b/examples/nested_map.rs @@ -0,0 +1,79 @@ +use maplit::hashmap; +use serde::{Deserialize, Serialize}; +use serde_diff::{Apply, Diff, SerdeDiff}; +use std::collections::HashMap; + +#[derive(SerdeDiff, Serialize, Deserialize, Debug, Default, PartialEq, Clone)] +struct TestValue { + v: String, +} + +#[derive(SerdeDiff, Serialize, Deserialize, Debug, Default, PartialEq, Clone)] +struct TestStruct { + test: bool, + map: HashMap>, +} + +fn main() -> Result<(), Box> { + let mut empty = TestStruct::default(); + empty.test = true; + + let mut hello_world = TestStruct::default(); + hello_world.map.insert( + "hello".to_string(), + hashmap![0 => TestValue { v: "world".to_string()}], + ); + + let mut hi_world = TestStruct::default(); + hi_world.map.insert( + "hi".to_string(), + hashmap![0 => TestValue { v: "world".to_string()}], + ); + + let mut hi_world_and_planet = TestStruct::default(); + hi_world_and_planet.map.insert( + "hi".to_string(), + hashmap![0 => TestValue { v: "world".to_string()}, 1 => TestValue { v: "planet".to_string()}], + ); + + let mut hi_planet = TestStruct::default(); + hi_planet.map.insert( + "hi".to_string(), + hashmap![0 => TestValue { v: "planet".to_string()}], + ); + + let mut hi_planet_hello_world = TestStruct::default(); + hi_planet_hello_world.map.insert( + "hi".to_string(), + hashmap![0 => TestValue { v: "planet".to_string()}], + ); + hi_planet_hello_world.map.insert( + "hello".to_string(), + hashmap![0 => TestValue { v: "world".to_string()}], + ); + + let add_hello = serde_json::to_string(&Diff::serializable(&empty, &hello_world))?; + let hello_to_hi = serde_json::to_string(&Diff::serializable(&hello_world, &hi_world))?; + let add_planet = serde_json::to_string(&Diff::serializable(&hi_world, &hi_world_and_planet))?; + let del_world = serde_json::to_string(&Diff::serializable(&hi_world_and_planet, &hi_planet))?; + let no_change = serde_json::to_string(&Diff::serializable(&hi_planet, &hi_planet))?; + let add_world = serde_json::to_string(&Diff::serializable(&hi_planet, &hi_planet_hello_world))?; + + let mut built = TestStruct::default(); + for (diff, after) in &[ + (add_hello, hello_world), + (hello_to_hi, hi_world), + (add_planet, hi_world_and_planet), + (del_world, hi_planet.clone()), + (no_change, hi_planet), + (add_world, hi_planet_hello_world), + ] { + println!("{}", diff); + + let mut deserializer = serde_json::Deserializer::from_str(&diff); + Apply::apply(&mut deserializer, &mut built)?; + + assert_eq!(after, &built); + } + Ok(()) +} diff --git a/src/implementation.rs b/src/implementation.rs index d83a1cc..7a975ca 100644 --- a/src/implementation.rs +++ b/src/implementation.rs @@ -172,6 +172,7 @@ macro_rules! map_serde_diff { if ::diff(self_value, &mut subctx, other_value)? { changed = true; } + subctx.pop_path_element()?; }, None => { ctx.save_command(&DiffCommandRef::RemoveKey(key), true, true)?;