func hashObj()

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
}