/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package diff import ( "fmt" "reflect" "github.com/vmihailenco/msgpack/v5" ) func (d *Differ) diffMap(path []string, a, b reflect.Value, parent interface{}) error { if a.Kind() == reflect.Invalid { return d.mapValues(CREATE, path, b) } if b.Kind() == reflect.Invalid { return d.mapValues(DELETE, path, a) } c := NewComparativeList() for _, k := range a.MapKeys() { ae := a.MapIndex(k) c.addA(exportInterface(k), &ae) } for _, k := range b.MapKeys() { be := b.MapIndex(k) c.addB(exportInterface(k), &be) } return d.diffComparative(path, c, exportInterface(a)) } func (d *Differ) mapValues(t string, path []string, a reflect.Value) error { if t != CREATE && t != DELETE { return ErrInvalidChangeType } if a.Kind() == reflect.Ptr { a = reflect.Indirect(a) } if a.Kind() != reflect.Map { return ErrTypeMismatch } x := reflect.New(a.Type()).Elem() for _, k := range a.MapKeys() { ae := a.MapIndex(k) xe := x.MapIndex(k) var err error if d.StructMapKeys { //it's not enough to turn k to a string, we need to able to marshal a type when //we apply it in patch so... we'll marshal it to JSON var b []byte if b, err = msgpack.Marshal(k.Interface()); err == nil { err = d.diff(append(path, string(b)), xe, ae, a.Interface()) } } else { err = d.diff(append(path, fmt.Sprint(k.Interface())), xe, ae, a.Interface()) } if err != nil { return err } } for i := 0; i < len(d.cl); i++ { // only swap changes on the relevant map if pathmatch(path, d.cl[i].Path) { d.cl[i] = swapChange(t, d.cl[i]) } } return nil }