From e8ce1df2ad6a715190bedf12b633649f4309aebd Mon Sep 17 00:00:00 2001 From: "a.chubar" Date: Tue, 18 Jun 2024 17:23:26 +0300 Subject: [PATCH] Fixing nested diffable POD structs being incorrectly marked as clean in GetDiff --- CHANGELOG.md | 2 +- tpl/macro.twig | 76 +++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 60 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c8c809c..465e267 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## v4.9.0 +## v4.9.1 - Fixing nested diffable POD structs being incorrectly marked as clean in GetDiff ## v4.8.2 diff --git a/tpl/macro.twig b/tpl/macro.twig index 7aff355..d1e65ce 100644 --- a/tpl/macro.twig +++ b/tpl/macro.twig @@ -459,7 +459,7 @@ public class {{o.name}} : IRpc } else if(old > item) { - item.SetDirtyMask(); + item.SetDirtyMaskDeep(); if(changed != null) changed.Add(item); i++; @@ -483,7 +483,7 @@ public class {{o.name}} : IRpc for(; i < items.Count; i++) { var item = items[i]; - item.SetDirtyMask(); + item.SetDirtyMaskDeep(); if(changed != null) changed.Add(item); has_diff = true; @@ -532,26 +532,54 @@ public class {{o.name}} : IRpc {{has_token(o, 'bitfields')?'CompareAndMarkFields':'IsEqual'}} {%- endmacro %} -{%- macro field_compare(o, f, field_idx) -%} +{% macro field_compare_array_bitfields_nested_diffable(o, f, field_idx) %} + { + int {{f.name}}_count_a = a.{{f.name}} == null ? 0 : a.{{f.name}}.Count; + int {{f.name}}_count_b = b.{{f.name}} == null ? 0 : b.{{f.name}}.Count; - {% if f.type is instanceof('\\mtgArrType') ~%} - {% if has_token(o, 'bitfields') ~%} + //For NESTED arrays of DIFFABLE structs: + //for DB compatibility we must add the WHOLE ARRAY to the diff if ANY ELEMENT of the array has changed. + //That means marking each element's fields_mask as dirty + + //Changed size means the array has changed, no furhter checks required. + bool {{f.name}}_equal = {{f.name}}_count_a == {{f.name}}_count_b; + + //For same size arrays - check contents for changes. + if({{f.name}}_equal) + { + for(int i=0;i<{{f.name}}_count_a && i<{{f.name}}_count_b;++i) + { + var tmp_{{f.name}} = a.{{f.name}}[i]; + if(!CompareAndMarkFields(ref tmp_{{f.name}}, b.{{f.name}}[i])) + { + {{f.name}}_equal = false; + break; + } + } + } + + //If change detected - mark top-level field as changed and add the whole array to the diff + if(!{{f.name}}_equal) + { + MetaIO.SetFieldDirty(ref a.fields_mask, {{field_idx}}); + for(int i=0; i<{{f.name}}_count_a;++i) + { + var tmp_{{f.name}} = a.{{f.name}}[i]; + tmp_{{f.name}}.SetDirtyMaskDeep(); + a.{{f.name}}[i] = tmp_{{f.name}}; + is_equal = false; + } + } + } +{%- endmacro %} + +{% macro field_compare_array_bitfields_nested_plain(o, f, field_idx) %} if(a.{{f.name}} == null || b.{{f.name}} == null || a.{{f.name}}.Count != b.{{f.name}}.Count) { MetaIO.SetFieldDirty(ref a.fields_mask, {{field_idx}}); is_equal = false; - - {% if has_token(f.type.value, 'bitfields') ~%} - //TODO: inefficient but reliable: marking the WHOLE collection as dirty when size changes - for(int i=0;i