-
Notifications
You must be signed in to change notification settings - Fork 174
Expand file tree
/
Copy pathgeneric_diff.go
More file actions
59 lines (50 loc) · 1.51 KB
/
generic_diff.go
File metadata and controls
59 lines (50 loc) · 1.51 KB
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
package maputil
import (
"reflect"
"github.com/stackrox/rox/pkg/reflectutils"
"github.com/stackrox/rox/pkg/set"
)
// DiffLeaf contains the information for a diff found within untyped maps.
type DiffLeaf struct {
A interface{} // This is the value in the `a` resource.
B interface{} // This is the value in the `b` resource.
}
// DiffGenericMap computes a diff in the form of a generic map for two generic maps.
// The values in the result map are either of type `map[string]interface{}` or `DiffLeaf`.
func DiffGenericMap(a map[string]interface{}, b map[string]interface{}) map[string]interface{} {
keys := set.NewStringSet()
diffMap := make(map[string]interface{})
// collect all keys first
for k := range a {
keys.Add(k)
}
for k := range b {
keys.Add(k)
}
// Compute any diffs for the given objets by traversing the union of the keys.
for _, k := range keys.AsSortedSlice(func(a, b string) bool { return a < b }) {
aVal := a[k]
bVal := b[k]
aMap, aOk := aVal.(map[string]interface{})
bMap, bOk := bVal.(map[string]interface{})
if aOk && bOk {
// Compute diffs for the nested maps.
subDiff := DiffGenericMap(aMap, bMap)
if subDiff != nil {
diffMap[k] = subDiff
}
} else if reflectutils.IsNil(aVal) && reflectutils.IsNil(bVal) {
continue
} else if reflect.TypeOf(aVal) != reflect.TypeOf(bVal) || !reflect.DeepEqual(aVal, bVal) {
// Type or value mismatch.
diffMap[k] = &DiffLeaf{
A: aVal,
B: bVal,
}
}
}
if len(diffMap) == 0 {
return nil
}
return diffMap
}