forked from r3labs/diff
-
Notifications
You must be signed in to change notification settings - Fork 0
/
patch_map.go
62 lines (54 loc) · 1.87 KB
/
patch_map.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package diff
import (
"reflect"
"github.com/vmihailenco/msgpack"
)
//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)
if err := msgpack.Unmarshal([]byte(c.change.Path[c.pos]), field.Interface()); err != nil {
c.SetFlag(FlagIgnored)
c.AddError(NewError("Unable to unmarshal path element to target type for key in map", err))
return
}
c.key = field.Elem()
if c.target.IsNil() && c.target.IsValid() {
c.target.Set(reflect.MakeMap(c.target.Type()))
}
x := c.target.MapIndex(c.key)
if !x.IsValid() && c.change.Type != DELETE && !c.HasFlag(OptionNoCreate) {
x = c.NewElement()
}
if x.IsValid() { //Map elements come out as read only so we must convert
nv := reflect.New(x.Type()).Elem()
nv.Set(x)
x = nv
}
if x.IsValid() && !reflect.DeepEqual(c.change.From, x.Interface()) &&
c.HasFlag(OptionOmitUnequal) {
c.SetFlag(FlagIgnored)
c.AddError(NewError("target change doesn't match original"))
return
}
mp := *c.target //these may change out from underneath us as we recurse
key := c.key //so we make copies and pass back pointers to them
c.swap(&x)
return &mp, &key, &x
}
//deleteMapEntry - 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 m != nil && m.CanSet() && v.IsValid() {
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)
}
}