Skip to content

Commit

Permalink
fix map deletes
Browse files Browse the repository at this point in the history
  • Loading branch information
purehyperbole committed Jun 30, 2021
1 parent bad6782 commit 69da8b8
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 26 deletions.
3 changes: 1 addition & 2 deletions patch.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,6 @@ func NewChangeValue(d *Differ, c Change, target interface{}) (ret *ChangeValue)
//renderChangeValue applies 'path' in change to target. nil check is foregone
// here as we control usage
func (d *Differ) renderChangeTarget(c *ChangeValue) {

//This particular change element may potentially have the immutable flag
if c.HasFlag(OptionImmutable) {
c.AddError(NewError("Option immutable set, cannot apply change"))
Expand All @@ -181,7 +180,7 @@ func (d *Differ) renderChangeTarget(c *ChangeValue) {
//map prior to editing the value, it will fail to stick. To fix this, we
//defer the safe until the stack unwinds
m, k, v := d.renderMap(c)
defer d.deleteMapEntry(c, m, k, v)
defer d.updateMapEntry(c, m, k, v)

//path element that is a slice
case reflect.Slice:
Expand Down
52 changes: 29 additions & 23 deletions patch_map.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (

//renderMap - handle map rendering for patch
func (d *Differ) renderMap(c *ChangeValue) (m, k, v *reflect.Value) {

//we must tease out the type of the key, we use the msgpack from diff to recreate the key
kt := c.target.Type().Key()
field := reflect.New(kt)
Expand Down Expand Up @@ -68,34 +67,41 @@ func (d *Differ) renderMap(c *ChangeValue) (m, k, v *reflect.Value) {

}

//deleteMapEntry - deletes are special, they are handled differently based on options
// updateMapEntry - deletes are special, they are handled differently based on options
// container type etc. We have to have special handling for each
// type. Set values are more generic even if they must be instanced
func (d *Differ) deleteMapEntry(c *ChangeValue, m, k, v *reflect.Value) {
if k == nil {
func (d *Differ) updateMapEntry(c *ChangeValue, m, k, v *reflect.Value) {
if k == nil || m == nil {
return
}

if m != nil && m.CanSet() && v.IsValid() && v.Kind() == reflect.Struct {
for x := 0; x < v.NumField(); x++ {
if !v.Field(x).IsZero() {
m.SetMapIndex(*k, *v)
return
}
} //if all the fields are zero, remove from map
switch c.change.Type {
case DELETE:
if c.HasFlag(FlagDeleted) {
return
}

if !m.CanSet() && v.IsValid() && v.Kind() == reflect.Struct {
for x := 0; x < v.NumField(); x++ {
if !v.Field(x).IsZero() {
m.SetMapIndex(*k, *v)
return
}
} //if all the fields are zero, remove from map
}

m.SetMapIndex(*k, reflect.Value{})
c.SetFlag(FlagDeleted)
} else {
switch c.change.Type {
case DELETE:
m.SetMapIndex(*k, reflect.Value{})
c.SetFlag(FlagDeleted)
case CREATE:
m.SetMapIndex(*k, *v)
c.SetFlag(FlagCreated)
case UPDATE:
m.SetMapIndex(*k, *v)
c.SetFlag(FlagUpdated)
}

case CREATE:
m.SetMapIndex(*k, *v)
c.SetFlag(FlagCreated)

case UPDATE:
m.SetMapIndex(*k, *v)
c.SetFlag(FlagUpdated)

default:
panic("NO TYPE SPECIFIED")
}
}
28 changes: 27 additions & 1 deletion patch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,6 @@ func TestPatch(t *testing.T) {
},
nil,
},

{
"map",
map[string]interface{}{"1": "one", "3": "three"},
Expand All @@ -205,6 +204,33 @@ func TestPatch(t *testing.T) {
},
nil,
},
{
"map-nested-create",
map[string]interface{}{"firstName": "John", "lastName": "Michael", "createdBy": "TS", "details": map[string]interface{}{"status": "active", "attributes": map[string]interface{}{"attrA": "A", "attrB": "B"}}},
map[string]interface{}{"firstName": "John", "lastName": "Michael", "createdBy": "TS", "details": map[string]interface{}{"status": "active", "attributes": map[string]interface{}{"attrA": "A", "attrB": "B"}, "secondary-attributes": map[string]interface{}{"attrA": "A", "attrB": "B"}}},
Changelog{
Change{Type: "delete", Path: []string{"details", "secondary-attributes"}, From: nil, To: map[string]interface{}{"attrA": "A", "attrB": "B"}},
},
nil,
},
{
"map-nested-update",
map[string]interface{}{"firstName": "John", "lastName": "Michael", "createdBy": "TS", "details": map[string]interface{}{"status": "active", "attributes": map[string]interface{}{"attrA": "A", "attrB": "B"}}},
map[string]interface{}{"firstName": "John", "lastName": "Michael", "createdBy": "TS", "details": map[string]interface{}{"status": "active", "attributes": map[string]interface{}{"attrA": "C", "attrD": "X"}}},
Changelog{
Change{Type: "delete", Path: []string{"details", "attributes"}, From: map[string]interface{}{"attrA": "A", "attrB": "B"}, To: map[string]interface{}{"attrA": "C", "attrD": "X"}},
},
nil,
},
{
"map-nested-delete",
map[string]interface{}{"firstName": "John", "lastName": "Michael", "createdBy": "TS", "details": map[string]interface{}{"status": "active", "attributes": map[string]interface{}{"attrA": "A", "attrB": "B"}}},
map[string]interface{}{"firstName": "John", "lastName": "Michael", "createdBy": "TS", "details": map[string]interface{}{"status": "active"}},
Changelog{
Change{Type: "delete", Path: []string{"details", "attributes"}, From: map[string]interface{}{"attrA": "A", "attrB": "B"}, To: nil},
},
nil,
},
}

for _, tc := range cases {
Expand Down

0 comments on commit 69da8b8

Please sign in to comment.