in wstl1/mapping_engine/util/jsonutil/jsonutil.go [855:920]
func hashObj(obj JSONToken, h hash.Hash, arrayWithoutOrder bool) error {
switch t := obj.(type) {
case JSONStr:
return hashBytes("str", []byte(t), h)
case JSONNum:
var b [8]byte
binary.BigEndian.PutUint64(b[:], math.Float64bits(float64(t)))
return hashBytes("num", b[:], h)
case JSONBool:
b := []byte{1}
if t {
b = []byte{2}
}
return hashBytes("bool", b, h)
case JSONArr:
if arrayWithoutOrder {
hc := make([]byte, 16)
for _, a := range t {
ah := fnv.New128()
if err := hashObj(a, ah, arrayWithoutOrder); err != nil {
return err
}
if err := xor128(hc, ah.Sum(nil)); err != nil {
return err
}
}
return hashBytes("arr", hc, h)
}
for _, a := range t {
if err := hashObj(a, h, arrayWithoutOrder); err != nil {
return err
}
}
case JSONContainer:
var kv []struct {
k string
v JSONToken
}
for k, v := range t {
kv = append(kv, struct {
k string
v JSONToken
}{k, *v})
}
// Stable sort not needed because container can't have multiple occurrences of the same key.
sort.Slice(kv, func(i, j int) bool {
return kv[i].k < kv[j].k
})
for _, a := range kv {
if err := hashBytes("key", []byte(a.k), h); err != nil {
return err
}
if err := hashObj(a.v, h, arrayWithoutOrder); err != nil {
return err
}
}
case nil:
return hashBytes("nil", []byte{}, h)
default:
return fmt.Errorf("this is an internal bug: unknown JSON type %T", obj)
}
return nil
}