Files
dependabot[bot] 51805e710d build(deps): bump github.com/open-policy-agent/opa from 1.4.2 to 1.5.0
Bumps [github.com/open-policy-agent/opa](https://github.com/open-policy-agent/opa) from 1.4.2 to 1.5.0.
- [Release notes](https://github.com/open-policy-agent/opa/releases)
- [Changelog](https://github.com/open-policy-agent/opa/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-policy-agent/opa/compare/v1.4.2...v1.5.0)

---
updated-dependencies:
- dependency-name: github.com/open-policy-agent/opa
  dependency-version: 1.5.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-02 15:18:43 +00:00

170 lines
3.1 KiB
Go

// Copyright 2016 The OPA Authors. All rights reserved.
// Use of this source code is governed by an Apache2
// license that can be found in the LICENSE file.
package util
import (
"encoding/json"
"fmt"
"math/big"
)
// Compare returns 0 if a equals b, -1 if a is less than b, and 1 if b is than a.
//
// For comparison between values of different types, the following ordering is used:
// nil < bool < int, float64 < string < []any < map[string]any. Slices and maps
// are compared recursively. If one slice or map is a subset of the other slice or map
// it is considered "less than". Nil is always equal to nil.
func Compare(a, b any) int {
aSortOrder := sortOrder(a)
bSortOrder := sortOrder(b)
if aSortOrder < bSortOrder {
return -1
} else if bSortOrder < aSortOrder {
return 1
}
switch a := a.(type) {
case nil:
return 0
case bool:
switch b := b.(type) {
case bool:
if a == b {
return 0
}
if !a {
return -1
}
return 1
}
case json.Number:
switch b := b.(type) {
case json.Number:
return compareJSONNumber(a, b)
}
case int:
switch b := b.(type) {
case int:
if a == b {
return 0
} else if a < b {
return -1
}
return 1
}
case float64:
switch b := b.(type) {
case float64:
if a == b {
return 0
} else if a < b {
return -1
}
return 1
}
case string:
switch b := b.(type) {
case string:
if a == b {
return 0
} else if a < b {
return -1
}
return 1
}
case []any:
switch b := b.(type) {
case []any:
bLen := len(b)
aLen := len(a)
minLen := min(bLen, aLen)
for i := range minLen {
cmp := Compare(a[i], b[i])
if cmp != 0 {
return cmp
}
}
if aLen == bLen {
return 0
} else if aLen < bLen {
return -1
}
return 1
}
case map[string]any:
switch b := b.(type) {
case map[string]any:
aKeys := KeysSorted(a)
bKeys := KeysSorted(b)
aLen := len(aKeys)
bLen := len(bKeys)
minLen := min(bLen, aLen)
for i := range minLen {
if aKeys[i] < bKeys[i] {
return -1
} else if bKeys[i] < aKeys[i] {
return 1
}
aVal := a[aKeys[i]]
bVal := b[bKeys[i]]
cmp := Compare(aVal, bVal)
if cmp != 0 {
return cmp
}
}
if aLen == bLen {
return 0
} else if aLen < bLen {
return -1
}
return 1
}
}
panic(fmt.Sprintf("illegal arguments of type %T and type %T", a, b))
}
const (
nilSort = iota
boolSort = iota
numberSort = iota
stringSort = iota
arraySort = iota
objectSort = iota
)
func compareJSONNumber(a, b json.Number) int {
bigA, ok := new(big.Float).SetString(string(a))
if !ok {
panic("illegal value")
}
bigB, ok := new(big.Float).SetString(string(b))
if !ok {
panic("illegal value")
}
return bigA.Cmp(bigB)
}
func sortOrder(v any) int {
switch v.(type) {
case nil:
return nilSort
case bool:
return boolSort
case json.Number:
return numberSort
case int:
return numberSort
case float64:
return numberSort
case string:
return stringSort
case []any:
return arraySort
case map[string]any:
return objectSort
}
panic(fmt.Sprintf("illegal argument of type %T", v))
}