build(deps): bump github.com/open-policy-agent/opa from 1.5.1 to 1.6.0

Bumps [github.com/open-policy-agent/opa](https://github.com/open-policy-agent/opa) from 1.5.1 to 1.6.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.5.1...v1.6.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
dependabot[bot]
2025-06-30 17:04:07 +00:00
committed by GitHub
parent 7d6bc2a485
commit 77c5c75436
56 changed files with 6072 additions and 759 deletions
+2 -2
View File
@@ -62,7 +62,7 @@ require (
github.com/onsi/ginkgo v1.16.5
github.com/onsi/ginkgo/v2 v2.23.4
github.com/onsi/gomega v1.37.0
github.com/open-policy-agent/opa v1.5.1
github.com/open-policy-agent/opa v1.6.0
github.com/opencloud-eu/libre-graph-api-go v1.0.8-0.20250603072916-fa601fb14450
github.com/opencloud-eu/reva/v2 v2.34.0
github.com/orcaman/concurrent-map v1.0.0
@@ -308,7 +308,7 @@ require (
github.com/tinylib/msgp v1.3.0 // indirect
github.com/toorop/go-dkim v0.0.0-20201103131630-e1cd1a0a5208 // indirect
github.com/trustelem/zxcvbn v1.0.1 // indirect
github.com/vektah/gqlparser/v2 v2.5.26 // indirect
github.com/vektah/gqlparser/v2 v2.5.28 // indirect
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
github.com/wk8/go-ordered-map v1.0.0 // indirect
github.com/xanzy/ssh-agent v0.3.3 // indirect
+6 -8
View File
@@ -200,8 +200,6 @@ github.com/c-bata/go-prompt v0.2.5/go.mod h1:vFnjEGDIIA/Lib7giyE4E9c50Lvl8j0S+7F
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
github.com/cenkalti/backoff/v4 v4.1.0/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/cenkalti/backoff/v5 v5.0.2 h1:rIfFVxEf1QsI7E1ZHfp/B4DF/6QBAUhmgkxc0H7Zss8=
github.com/cenkalti/backoff/v5 v5.0.2/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=
github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
@@ -864,8 +862,8 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.37.0 h1:CdEG8g0S133B4OswTDC/5XPSzE1OeP29QOioj2PID2Y=
github.com/onsi/gomega v1.37.0/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0=
github.com/open-policy-agent/opa v1.5.1 h1:LTxxBJusMVjfs67W4FoRcnMfXADIGFMzpqnfk6D08Cg=
github.com/open-policy-agent/opa v1.5.1/go.mod h1:bYbS7u+uhTI+cxHQIpzvr5hxX0hV7urWtY+38ZtjMgk=
github.com/open-policy-agent/opa v1.6.0 h1:/S/cnNQJ2MUMNzizHPbisTWBHowmLkPrugY5jjkPlRQ=
github.com/open-policy-agent/opa v1.6.0/go.mod h1:zFmw4P+W62+CWGYRDDswfVYSCnPo6oYaktQnfIaRFC4=
github.com/opencloud-eu/go-micro-plugins/v4/store/nats-js-kv v0.0.0-20250512152754-23325793059a h1:Sakl76blJAaM6NxylVkgSzktjo2dS504iDotEFJsh3M=
github.com/opencloud-eu/go-micro-plugins/v4/store/nats-js-kv v0.0.0-20250512152754-23325793059a/go.mod h1:pjcozWijkNPbEtX5SIQaxEW/h8VAVZYTLx+70bmB3LY=
github.com/opencloud-eu/libre-graph-api-go v1.0.8-0.20250603072916-fa601fb14450 h1:QWn9G2f1R/EbyZSbkjtd9jqNq9X0NIphmmD4KYLNZtA=
@@ -1116,8 +1114,8 @@ github.com/urfave/cli/v2 v2.27.7/go.mod h1:CyNAG/xg+iAOg0N4MPGZqVmv2rCoP267496AO
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
github.com/valyala/fasttemplate v1.1.0/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
github.com/vektah/gqlparser/v2 v2.5.26 h1:REqqFkO8+SOEgZHR/eHScjjVjGS8Nk3RMO/juiTobN4=
github.com/vektah/gqlparser/v2 v2.5.26/go.mod h1:D1/VCZtV3LPnQrcPBeR/q5jkSQIPti0uYCP/RI0gIeo=
github.com/vektah/gqlparser/v2 v2.5.28 h1:bIulcl3LF69ba6EiZVGD88y4MkM+Jxrf3P2MX8xLRkY=
github.com/vektah/gqlparser/v2 v2.5.28/go.mod h1:D1/VCZtV3LPnQrcPBeR/q5jkSQIPti0uYCP/RI0gIeo=
github.com/vinyldns/go-vinyldns v0.0.0-20200917153823-148a5f6b8f14/go.mod h1:RWc47jtnVuQv6+lY3c768WtXCas/Xi+U5UFc5xULmYg=
github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8=
github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok=
@@ -1191,8 +1189,8 @@ go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0 h1:Ahq7pZmv87yiyn3jeFz
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0/go.mod h1:MJTqhM0im3mRLw1i8uGHnCvUEeS7VwRyxlLC78PA18M=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.37.0 h1:EtFWSnwW9hGObjkIdmlnWSydO+Qs8OwzfzXLUPg4xOc=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.37.0/go.mod h1:QjUEoiGCPkvFZ/MjK6ZZfNOS6mfVEVKYE99dFhuN2LI=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 h1:xJ2qHD0C1BeYVTLLR9sX12+Qb95kfeD/byKj6Ky1pXg=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0/go.mod h1:u5BF1xyjstDowA1R5QAO9JHzqK+ublenEW/dyqTjBVk=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.36.0 h1:nRVXXvf78e00EwY6Wp0YII8ww2JVWshZ20HfTlE11AM=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.36.0/go.mod h1:r49hO7CgrxY9Voaj3Xe8pANWtr0Oq916d0XAmOoCZAQ=
go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE=
go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E=
go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI=
+2 -2
View File
@@ -9,14 +9,14 @@ import (
)
func InternedBooleanTerm(b bool) *Term {
return v1.InternedBooleanTerm(b)
return v1.InternedTerm(b)
}
// InternedIntNumberTerm returns a term with the given integer value. The term is
// cached between -1 to 512, and for values outside of that range, this function
// is equivalent to ast.IntNumberTerm.
func InternedIntNumberTerm(i int) *Term {
return v1.InternedIntNumberTerm(i)
return v1.InternedTerm(i)
}
func HasInternedIntNumberTerm(i int) bool {
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -723,7 +723,7 @@ func (e *EditTree) Unfold(path ast.Ref) (*EditTree, error) {
return child.Unfold(path[1:])
}
idxt := ast.InternedIntNumberTerm(idx)
idxt := ast.InternedTerm(idx)
// Fall back to looking up the key in e.value.
// Extend the tree if key is present. Error otherwise.
@@ -1028,7 +1028,7 @@ func (e *EditTree) Exists(path ast.Ref) bool {
}
// Fallback if child lookup failed.
// We have to ensure that the lookup term is a number here, or Find will fail.
_, err = x.Find(ast.Ref{ast.InternedIntNumberTerm(idx)}.Concat(path[1:]))
_, err = x.Find(ast.Ref{ast.InternedTerm(idx)}.Concat(path[1:]))
return err == nil
default:
// Catch all primitive types.
+3 -3
View File
@@ -24,7 +24,7 @@ func IsAllFutureKeywords(imp *ast.Import) bool {
path := imp.Path.Value.(ast.Ref)
return len(path) == 2 &&
ast.FutureRootDocument.Equal(path[0]) &&
path[1].Equal(ast.InternedStringTerm("keywords"))
path[1].Equal(ast.InternedTerm("keywords"))
}
// IsFutureKeyword returns true if the passed *ast.Import is `future.keywords.{kw}`
@@ -32,7 +32,7 @@ func IsFutureKeyword(imp *ast.Import, kw string) bool {
path := imp.Path.Value.(ast.Ref)
return len(path) == 3 &&
ast.FutureRootDocument.Equal(path[0]) &&
path[1].Equal(ast.InternedStringTerm("keywords")) &&
path[1].Equal(ast.InternedTerm("keywords")) &&
path[2].Equal(ast.StringTerm(kw))
}
@@ -40,7 +40,7 @@ func WhichFutureKeyword(imp *ast.Import) (string, bool) {
path := imp.Path.Value.(ast.Ref)
if len(path) == 3 &&
ast.FutureRootDocument.Equal(path[0]) &&
path[1].Equal(ast.InternedStringTerm("keywords")) {
path[1].Equal(ast.InternedTerm("keywords")) {
if str, ok := path[2].Value.(ast.String); ok {
return string(str), true
}
+20 -20
View File
@@ -423,28 +423,28 @@ func (a *Annotations) toObject() (*Object, *Error) {
if len(a.Scope) > 0 {
switch a.Scope {
case annotationScopeDocument:
obj.Insert(InternedStringTerm("scope"), InternedStringTerm("document"))
obj.Insert(InternedTerm("scope"), InternedTerm("document"))
case annotationScopePackage:
obj.Insert(InternedStringTerm("scope"), InternedStringTerm("package"))
obj.Insert(InternedTerm("scope"), InternedTerm("package"))
case annotationScopeRule:
obj.Insert(InternedStringTerm("scope"), InternedStringTerm("rule"))
obj.Insert(InternedTerm("scope"), InternedTerm("rule"))
case annotationScopeSubpackages:
obj.Insert(InternedStringTerm("scope"), InternedStringTerm("subpackages"))
obj.Insert(InternedTerm("scope"), InternedTerm("subpackages"))
default:
obj.Insert(InternedStringTerm("scope"), StringTerm(a.Scope))
obj.Insert(InternedTerm("scope"), StringTerm(a.Scope))
}
}
if len(a.Title) > 0 {
obj.Insert(InternedStringTerm("title"), StringTerm(a.Title))
obj.Insert(InternedTerm("title"), StringTerm(a.Title))
}
if a.Entrypoint {
obj.Insert(InternedStringTerm("entrypoint"), InternedBooleanTerm(true))
obj.Insert(InternedTerm("entrypoint"), InternedTerm(true))
}
if len(a.Description) > 0 {
obj.Insert(InternedStringTerm("description"), StringTerm(a.Description))
obj.Insert(InternedTerm("description"), StringTerm(a.Description))
}
if len(a.Organizations) > 0 {
@@ -452,19 +452,19 @@ func (a *Annotations) toObject() (*Object, *Error) {
for _, org := range a.Organizations {
orgs = append(orgs, StringTerm(org))
}
obj.Insert(InternedStringTerm("organizations"), ArrayTerm(orgs...))
obj.Insert(InternedTerm("organizations"), ArrayTerm(orgs...))
}
if len(a.RelatedResources) > 0 {
rrs := make([]*Term, 0, len(a.RelatedResources))
for _, rr := range a.RelatedResources {
rrObj := NewObject(Item(InternedStringTerm("ref"), StringTerm(rr.Ref.String())))
rrObj := NewObject(Item(InternedTerm("ref"), StringTerm(rr.Ref.String())))
if len(rr.Description) > 0 {
rrObj.Insert(InternedStringTerm("description"), StringTerm(rr.Description))
rrObj.Insert(InternedTerm("description"), StringTerm(rr.Description))
}
rrs = append(rrs, NewTerm(rrObj))
}
obj.Insert(InternedStringTerm("related_resources"), ArrayTerm(rrs...))
obj.Insert(InternedTerm("related_resources"), ArrayTerm(rrs...))
}
if len(a.Authors) > 0 {
@@ -472,14 +472,14 @@ func (a *Annotations) toObject() (*Object, *Error) {
for _, author := range a.Authors {
aObj := NewObject()
if len(author.Name) > 0 {
aObj.Insert(InternedStringTerm("name"), StringTerm(author.Name))
aObj.Insert(InternedTerm("name"), StringTerm(author.Name))
}
if len(author.Email) > 0 {
aObj.Insert(InternedStringTerm("email"), StringTerm(author.Email))
aObj.Insert(InternedTerm("email"), StringTerm(author.Email))
}
as = append(as, NewTerm(aObj))
}
obj.Insert(InternedStringTerm("authors"), ArrayTerm(as...))
obj.Insert(InternedTerm("authors"), ArrayTerm(as...))
}
if len(a.Schemas) > 0 {
@@ -487,21 +487,21 @@ func (a *Annotations) toObject() (*Object, *Error) {
for _, s := range a.Schemas {
sObj := NewObject()
if len(s.Path) > 0 {
sObj.Insert(InternedStringTerm("path"), NewTerm(s.Path.toArray()))
sObj.Insert(InternedTerm("path"), NewTerm(s.Path.toArray()))
}
if len(s.Schema) > 0 {
sObj.Insert(InternedStringTerm("schema"), NewTerm(s.Schema.toArray()))
sObj.Insert(InternedTerm("schema"), NewTerm(s.Schema.toArray()))
}
if s.Definition != nil {
def, err := InterfaceToValue(s.Definition)
if err != nil {
return nil, NewError(CompileErr, a.Location, "invalid definition in schema annotation: %s", err.Error())
}
sObj.Insert(InternedStringTerm("definition"), NewTerm(def))
sObj.Insert(InternedTerm("definition"), NewTerm(def))
}
ss = append(ss, NewTerm(sObj))
}
obj.Insert(InternedStringTerm("schemas"), ArrayTerm(ss...))
obj.Insert(InternedTerm("schemas"), ArrayTerm(ss...))
}
if len(a.Custom) > 0 {
@@ -509,7 +509,7 @@ func (a *Annotations) toObject() (*Object, *Error) {
if err != nil {
return nil, NewError(CompileErr, a.Location, "invalid custom annotation %s", err.Error())
}
obj.Insert(InternedStringTerm("custom"), NewTerm(c))
obj.Insert(InternedTerm("custom"), NewTerm(c))
}
return &obj, nil
File diff suppressed because it is too large Load Diff
+3
View File
@@ -55,6 +55,7 @@ const FeatureRefHeadStringPrefixes = "rule_head_ref_string_prefixes"
const FeatureRefHeads = "rule_head_refs"
const FeatureRegoV1 = "rego_v1"
const FeatureRegoV1Import = "rego_v1_import"
const FeatureKeywordsInRefs = "keywords_in_refs"
// Capabilities defines a structure containing data that describes the capabilities
// or features supported by a particular version of OPA.
@@ -133,6 +134,7 @@ func CapabilitiesForThisVersion(opts ...CapabilitiesOption) *Capabilities {
FeatureRefHeads,
FeatureRegoV1Import,
FeatureRegoV1, // Included in v0 capabilities to allow v1 bundles in --v0-compatible mode
FeatureKeywordsInRefs,
}
default:
for kw := range futureKeywords {
@@ -141,6 +143,7 @@ func CapabilitiesForThisVersion(opts ...CapabilitiesOption) *Capabilities {
f.Features = []string{
FeatureRegoV1,
FeatureKeywordsInRefs,
}
}
+9 -3
View File
@@ -211,8 +211,10 @@ func (tc *typeChecker) getSchemaType(schemaAnnot *SchemaAnnotation, rule *Rule)
tc.schemaTypes = make(map[string]types.Type)
}
if refType, exists := tc.schemaTypes[schemaAnnot.Schema.String()]; exists {
return refType, nil
if len(schemaAnnot.Schema) > 0 {
if refType, exists := tc.schemaTypes[schemaAnnot.Schema.String()]; exists {
return refType, nil
}
}
refType, err := processAnnotation(tc.ss, schemaAnnot, rule, tc.allowNet)
@@ -224,7 +226,11 @@ func (tc *typeChecker) getSchemaType(schemaAnnot *SchemaAnnotation, rule *Rule)
return nil, nil
}
tc.schemaTypes[schemaAnnot.Schema.String()] = refType
// Only add to cache if schema is read from file
if len(schemaAnnot.Schema) > 0 {
tc.schemaTypes[schemaAnnot.Schema.String()] = refType
}
return refType, nil
}
+3 -3
View File
@@ -964,7 +964,7 @@ func (c *Compiler) buildComprehensionIndices() {
}
}
var futureKeywordsPrefix = Ref{FutureRootDocument, InternedStringTerm("keywords")}
var futureKeywordsPrefix = Ref{FutureRootDocument, InternedTerm("keywords")}
// buildRequiredCapabilities updates the required capabilities on the compiler
// to include any keyword and feature dependencies present in the modules. The
@@ -2531,13 +2531,13 @@ func createMetadataChain(chain []*AnnotationsRef) (*Term, *Error) {
for _, link := range chain {
// Dropping leading 'data' element of path
p := link.Path[1:].toArray()
obj := NewObject(Item(InternedStringTerm("path"), NewTerm(p)))
obj := NewObject(Item(InternedTerm("path"), NewTerm(p)))
if link.Annotations != nil {
annotObj, err := link.Annotations.toObject()
if err != nil {
return nil, err
}
obj.Insert(InternedStringTerm("annotations"), NewTerm(*annotObj))
obj.Insert(InternedTerm("annotations"), NewTerm(*annotObj))
}
metaArray = metaArray.Append(NewTerm(obj))
}
+2 -2
View File
@@ -402,7 +402,7 @@ func (i *refindices) updateGlobMatch(rule *Rule, expr *Expr) {
if ref == nil {
for j, arg := range args {
if arg.Equal(match) {
ref = Ref{FunctionArgRootDocument, InternedIntNumberTerm(j)}
ref = Ref{FunctionArgRootDocument, InternedTerm(j)}
}
}
}
@@ -822,7 +822,7 @@ func eqOperandsToRefAndValue(isVirtual func(Ref) bool, args []*Term, a, b *Term)
for i, arg := range args {
if arg.Value.Compare(a.Value) == 0 {
if bval, ok := indexValue(b); ok {
return &refindex{Ref: Ref{FunctionArgRootDocument, InternedIntNumberTerm(i)}, Value: bval}, true
return &refindex{Ref: Ref{FunctionArgRootDocument, InternedTerm(i)}, Value: bval}, true
}
}
}
@@ -116,6 +116,11 @@ func (s *Scanner) HasKeyword(keywords map[string]tokens.Token) bool {
return false
}
func (s *Scanner) IsKeyword(str string) bool {
_, ok := s.keywords[str]
return ok
}
func (s *Scanner) SetRegoV1Compatible() {
s.regoV1Compatible = true
}
+100 -220
View File
@@ -8,18 +8,16 @@ import (
"strconv"
)
type internable interface {
bool | string | int | int8 | int16 | int32 | int64 | uint | uint8 | uint16 | uint32 | uint64
}
// NOTE! Great care must be taken **not** to modify the terms returned
// from these functions, as they are shared across all callers.
// This package is currently considered experimental, and may change
// at any time without notice.
var (
booleanTrueTerm = &Term{Value: Boolean(true)}
booleanFalseTerm = &Term{Value: Boolean(false)}
// since this is by far the most common negative number
minusOneTerm = &Term{Value: Number("-1")}
InternedNullTerm = &Term{Value: Null{}}
InternedEmptyString = StringTerm("")
@@ -28,6 +26,16 @@ var (
InternedEmptySet = SetTerm()
InternedEmptyArrayValue = NewArray()
booleanTrueTerm = &Term{Value: Boolean(true)}
booleanFalseTerm = &Term{Value: Boolean(false)}
// since this is by far the most common negative number
minusOneTerm = &Term{Value: Number("-1")}
internedStringTerms = map[string]*Term{
"": InternedEmptyString,
}
)
// InternStringTerm interns the given strings as terms. Note that Interning is
@@ -44,28 +52,37 @@ func InternStringTerm(str ...string) {
}
}
// InternedBooleanTerm returns an interned term with the given boolean value.
func InternedBooleanTerm(b bool) *Term {
if b {
return booleanTrueTerm
// Interned returns a possibly interned term for the given scalar value.
// If the value is not interned, a new term is created for that value.
func InternedTerm[T internable](v T) *Term {
switch value := any(v).(type) {
case bool:
return internedBooleanTerm(value)
case string:
return internedStringTerm(value)
case int:
return internedIntNumberTerm(value)
case int8:
return internedIntNumberTerm(int(value))
case int16:
return internedIntNumberTerm(int(value))
case int32:
return internedIntNumberTerm(int(value))
case int64:
return internedIntNumberTerm(int(value))
case uint:
return internedIntNumberTerm(int(value))
case uint8:
return internedIntNumberTerm(int(value))
case uint16:
return internedIntNumberTerm(int(value))
case uint32:
return internedIntNumberTerm(int(value))
case uint64:
return internedIntNumberTerm(int(value))
default:
panic("unreachable")
}
return booleanFalseTerm
}
// InternedIntNumberTerm returns a term with the given integer value. The term is
// cached between -1 to 512, and for values outside of that range, this function
// is equivalent to ast.IntNumberTerm.
func InternedIntNumberTerm(i int) *Term {
if i >= 0 && i < len(intNumberTerms) {
return intNumberTerms[i]
}
if i == -1 {
return minusOneTerm
}
return &Term{Value: Number(strconv.Itoa(i))}
}
// InternedIntFromString returns a term with the given integer value if the string
@@ -85,17 +102,6 @@ func HasInternedIntNumberTerm(i int) bool {
return i >= -1 && i < len(intNumberTerms)
}
// InternedStringTerm returns an interned term with the given string value. If the
// provided string is not interned, a new term is created for that value. It does *not*
// modify the global interned terms map.
func InternedStringTerm(s string) *Term {
if term, ok := internedStringTerms[s]; ok {
return term
}
return StringTerm(s)
}
// Returns an interned string term representing the integer value i, if
// interned. If not, creates a new StringTerm for the integer value.
func InternedIntegerString(i int) *Term {
@@ -117,195 +123,69 @@ func InternedIntegerString(i int) *Term {
return StringTerm(s)
}
var internedStringTerms = map[string]*Term{
"": InternedEmptyString,
"0": StringTerm("0"),
"1": StringTerm("1"),
"2": StringTerm("2"),
"3": StringTerm("3"),
"4": StringTerm("4"),
"5": StringTerm("5"),
"6": StringTerm("6"),
"7": StringTerm("7"),
"8": StringTerm("8"),
"9": StringTerm("9"),
"10": StringTerm("10"),
"11": StringTerm("11"),
"12": StringTerm("12"),
"13": StringTerm("13"),
"14": StringTerm("14"),
"15": StringTerm("15"),
"16": StringTerm("16"),
"17": StringTerm("17"),
"18": StringTerm("18"),
"19": StringTerm("19"),
"20": StringTerm("20"),
"21": StringTerm("21"),
"22": StringTerm("22"),
"23": StringTerm("23"),
"24": StringTerm("24"),
"25": StringTerm("25"),
"26": StringTerm("26"),
"27": StringTerm("27"),
"28": StringTerm("28"),
"29": StringTerm("29"),
"30": StringTerm("30"),
"31": StringTerm("31"),
"32": StringTerm("32"),
"33": StringTerm("33"),
"34": StringTerm("34"),
"35": StringTerm("35"),
"36": StringTerm("36"),
"37": StringTerm("37"),
"38": StringTerm("38"),
"39": StringTerm("39"),
"40": StringTerm("40"),
"41": StringTerm("41"),
"42": StringTerm("42"),
"43": StringTerm("43"),
"44": StringTerm("44"),
"45": StringTerm("45"),
"46": StringTerm("46"),
"47": StringTerm("47"),
"48": StringTerm("48"),
"49": StringTerm("49"),
"50": StringTerm("50"),
"51": StringTerm("51"),
"52": StringTerm("52"),
"53": StringTerm("53"),
"54": StringTerm("54"),
"55": StringTerm("55"),
"56": StringTerm("56"),
"57": StringTerm("57"),
"58": StringTerm("58"),
"59": StringTerm("59"),
"60": StringTerm("60"),
"61": StringTerm("61"),
"62": StringTerm("62"),
"63": StringTerm("63"),
"64": StringTerm("64"),
"65": StringTerm("65"),
"66": StringTerm("66"),
"67": StringTerm("67"),
"68": StringTerm("68"),
"69": StringTerm("69"),
"70": StringTerm("70"),
"71": StringTerm("71"),
"72": StringTerm("72"),
"73": StringTerm("73"),
"74": StringTerm("74"),
"75": StringTerm("75"),
"76": StringTerm("76"),
"77": StringTerm("77"),
"78": StringTerm("78"),
"79": StringTerm("79"),
"80": StringTerm("80"),
"81": StringTerm("81"),
"82": StringTerm("82"),
"83": StringTerm("83"),
"84": StringTerm("84"),
"85": StringTerm("85"),
"86": StringTerm("86"),
"87": StringTerm("87"),
"88": StringTerm("88"),
"89": StringTerm("89"),
"90": StringTerm("90"),
"91": StringTerm("91"),
"92": StringTerm("92"),
"93": StringTerm("93"),
"94": StringTerm("94"),
"95": StringTerm("95"),
"96": StringTerm("96"),
"97": StringTerm("97"),
"98": StringTerm("98"),
"99": StringTerm("99"),
"100": StringTerm("100"),
// InternedBooleanTerm returns an interned term with the given boolean value.
func internedBooleanTerm(b bool) *Term {
if b {
return booleanTrueTerm
}
// Types
"null": StringTerm("null"),
"boolean": StringTerm("boolean"),
"number": StringTerm("number"),
"string": StringTerm("string"),
"array": StringTerm("array"),
"object": StringTerm("object"),
"set": StringTerm("set"),
return booleanFalseTerm
}
// Runtime
"config": StringTerm("config"),
"env": StringTerm("env"),
"version": StringTerm("version"),
"commit": StringTerm("commit"),
"authorization_enabled": StringTerm("authorization_enabled"),
"skip_known_schema_check": StringTerm("skip_known_schema_check"),
// InternedIntNumberTerm returns a term with the given integer value. The term is
// cached between -1 to 512, and for values outside of that range, this function
// is equivalent to IntNumberTerm.
func internedIntNumberTerm(i int) *Term {
if i >= 0 && i < len(intNumberTerms) {
return intNumberTerms[i]
}
// Annotations
"annotations": StringTerm("annotations"),
"scope": StringTerm("scope"),
"title": StringTerm("title"),
"entrypoint": StringTerm("entrypoint"),
"description": StringTerm("description"),
"organizations": StringTerm("organizations"),
"authors": StringTerm("authors"),
"related_resources": StringTerm("related_resources"),
"schemas": StringTerm("schemas"),
"custom": StringTerm("custom"),
"ref": StringTerm("ref"),
"name": StringTerm("name"),
"email": StringTerm("email"),
"schema": StringTerm("schema"),
"definition": StringTerm("definition"),
"document": StringTerm("document"),
"package": StringTerm("package"),
"rule": StringTerm("rule"),
"subpackages": StringTerm("subpackages"),
if i == -1 {
return minusOneTerm
}
// Debug
"text": StringTerm("text"),
"value": StringTerm("value"),
"bindings": StringTerm("bindings"),
"expressions": StringTerm("expressions"),
return &Term{Value: Number(strconv.Itoa(i))}
}
// Various
"data": StringTerm("data"),
"input": StringTerm("input"),
"result": StringTerm("result"),
"keywords": StringTerm("keywords"),
"path": StringTerm("path"),
"v1": StringTerm("v1"),
"error": StringTerm("error"),
"partial": StringTerm("partial"),
// InternedStringTerm returns an interned term with the given string value. If the
// provided string is not interned, a new term is created for that value. It does *not*
// modify the global interned terms map.
func internedStringTerm(s string) *Term {
if term, ok := internedStringTerms[s]; ok {
return term
}
// HTTP
"code": StringTerm("code"),
"message": StringTerm("message"),
"status_code": StringTerm("status_code"),
"method": StringTerm("method"),
"url": StringTerm("url"),
return StringTerm(s)
}
// JWT
"enc": StringTerm("enc"),
"cty": StringTerm("cty"),
"iss": StringTerm("iss"),
"exp": StringTerm("exp"),
"nbf": StringTerm("nbf"),
"aud": StringTerm("aud"),
"secret": StringTerm("secret"),
"cert": StringTerm("cert"),
// Decisions
"revision": StringTerm("revision"),
"labels": StringTerm("labels"),
"decision_id": StringTerm("decision_id"),
"bundles": StringTerm("bundles"),
"query": StringTerm("query"),
"mapped_result": StringTerm("mapped_result"),
"nd_builtin_cache": StringTerm("nd_builtin_cache"),
"erased": StringTerm("erased"),
"masked": StringTerm("masked"),
"requested_by": StringTerm("requested_by"),
"timestamp": StringTerm("timestamp"),
"metrics": StringTerm("metrics"),
"req_id": StringTerm("req_id"),
func init() {
InternStringTerm(
// Numbers
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "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", "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "70", "71", "72", "73", "74",
"75", "76", "77", "78", "79", "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "90", "91", "92",
"93", "94", "95", "96", "97", "98", "99", "100",
// Types
"null", "boolean", "number", "string", "array", "object", "set", "var", "ref", "true", "false",
// Runtime
"config", "env", "version", "commit", "authorization_enabled", "skip_known_schema_check",
// Annotations
"annotations", "scope", "title", "entrypoint", "description", "organizations", "authors", "related_resources",
"schemas", "custom", "name", "email", "schema", "definition", "document", "package", "rule", "subpackages",
// Debug
"text", "value", "bindings", "expressions",
// Various
"data", "input", "result", "keywords", "path", "v1", "error", "partial",
// HTTP
"code", "message", "status_code", "method", "url", "uri",
// JWT
"enc", "cty", "iss", "exp", "nbf", "aud", "secret", "cert",
// Decisions
"revision", "labels", "decision_id", "bundles", "query", "mapped_result", "nd_builtin_cache",
"erased", "masked", "requested_by", "timestamp", "metrics", "req_id",
)
}
var stringToIntNumberTermMap = map[string]*Term{
+193 -52
View File
@@ -36,7 +36,7 @@ const DefaultMaxParsingRecursionDepth = 100000
// recursion exceeds the maximum allowed depth
var ErrMaxParsingRecursionDepthExceeded = errors.New("max parsing recursion depth exceeded")
var RegoV1CompatibleRef = Ref{VarTerm("rego"), InternedStringTerm("v1")}
var RegoV1CompatibleRef = Ref{VarTerm("rego"), InternedTerm("v1")}
// RegoVersion defines the Rego syntax requirements for a module.
type RegoVersion int
@@ -572,8 +572,19 @@ func (p *Parser) parsePackage() *Package {
return nil
}
p.scan()
if p.s.tok != tokens.Ident {
p.scanWS()
// Make sure we allow the first term of refs to be the 'package' keyword.
if p.s.tok == tokens.Dot || p.s.tok == tokens.LBrack {
// This is a ref, not a package declaration.
return nil
}
if p.s.tok == tokens.Whitespace {
p.scan()
}
if !isIdentOrAllowedRefKeyword(p) {
p.illegalToken()
return nil
}
@@ -630,11 +641,23 @@ func (p *Parser) parseImport() *Import {
return nil
}
p.scan()
if p.s.tok != tokens.Ident {
p.error(p.s.Loc(), "expected ident")
p.scanWS()
// Make sure we allow the first term of refs to be the 'import' keyword.
if p.s.tok == tokens.Dot || p.s.tok == tokens.LBrack {
// This is a ref, not an import declaration.
return nil
}
if p.s.tok == tokens.Whitespace {
p.scan()
}
if !isIdentOrAllowedRefKeyword(p) {
p.illegalToken()
return nil
}
q, prev := p.presentParser()
term := q.parseTerm()
if term != nil {
@@ -693,17 +716,81 @@ func (p *Parser) parseImport() *Import {
return nil
}
if imp.Alias != "" {
// Unreachable: parsing the alias var should already have generated an error.
name := imp.Alias.String()
if IsKeywordInRegoVersion(name, p.po.EffectiveRegoVersion()) {
p.errorf(imp.Location, "unexpected import alias, must not be a keyword, got: %s", name)
}
return &imp
}
r := imp.Path.Value.(Ref)
// Don't allow keywords in the tail path term unless it's a future import
if len(r) == 1 {
t := r[0]
name := string(t.Value.(Var))
if IsKeywordInRegoVersion(name, p.po.EffectiveRegoVersion()) {
p.errorf(t.Location, "unexpected import path, must not end with a keyword, got: %s", name)
p.hint("import a different path or use an alias")
}
} else if !FutureRootDocument.Equal(r[0]) {
t := r[len(r)-1]
name := string(t.Value.(String))
if IsKeywordInRegoVersion(name, p.po.EffectiveRegoVersion()) {
p.errorf(t.Location, "unexpected import path, must not end with a keyword, got: %s", name)
p.hint("import a different path or use an alias")
}
}
return &imp
}
// isIdentOrAllowedRefKeyword checks if the current token is an Ident or a keyword in the active rego-version.
// If a keyword, sets p.s.token to token.Ident
func isIdentOrAllowedRefKeyword(p *Parser) bool {
if p.s.tok == tokens.Ident {
return true
}
if p.isAllowedRefKeyword(p.s.tok) {
p.s.tok = tokens.Ident
return true
}
return false
}
func scanAheadRef(p *Parser) bool {
if p.isAllowedRefKeyword(p.s.tok) {
// scan ahead to check if we're parsing a ref
s := p.save()
p.scanWS()
tok := p.s.tok
p.restore(s)
if tok == tokens.Dot || tok == tokens.LBrack {
p.s.tok = tokens.Ident
return true
}
}
return false
}
func (p *Parser) parseRules() []*Rule {
var rule Rule
rule.SetLoc(p.s.Loc())
// This allows keywords in the first var term of the ref
_ = scanAheadRef(p)
if p.s.tok == tokens.Default {
p.scan()
rule.Default = true
_ = scanAheadRef(p)
}
if p.s.tok != tokens.Ident {
@@ -817,17 +904,20 @@ func (p *Parser) parseRules() []*Rule {
}
if p.s.tok == tokens.Else {
if r := rule.Head.Ref(); len(r) > 1 && !r.IsGround() {
p.error(p.s.Loc(), "else keyword cannot be used on rules with variables in head")
return nil
}
if rule.Head.Key != nil {
p.error(p.s.Loc(), "else keyword cannot be used on multi-value rules")
return nil
}
// This might just be a refhead rule with a leading 'else' term.
if !scanAheadRef(p) {
if r := rule.Head.Ref(); len(r) > 1 && !r.IsGround() {
p.error(p.s.Loc(), "else keyword cannot be used on rules with variables in head")
return nil
}
if rule.Head.Key != nil {
p.error(p.s.Loc(), "else keyword cannot be used on multi-value rules")
return nil
}
if rule.Else = p.parseElse(rule.Head); rule.Else == nil {
return nil
if rule.Else = p.parseElse(rule.Head); rule.Else == nil {
return nil
}
}
}
@@ -1102,10 +1192,31 @@ func (p *Parser) parseLiteral() (expr *Expr) {
}
}()
// Check that we're not parsing a ref
if p.isAllowedRefKeyword(p.s.tok) {
// Scan ahead
s := p.save()
p.scanWS()
tok := p.s.tok
p.restore(s)
if tok == tokens.Dot || tok == tokens.LBrack {
p.s.tok = tokens.Ident
return p.parseLiteralExpr(false)
}
}
var negated bool
if p.s.tok == tokens.Not {
p.scan()
negated = true
s := p.save()
p.scanWS()
tok := p.s.tok
p.restore(s)
if tok != tokens.Dot && tok != tokens.LBrack {
p.scan()
negated = true
}
}
switch p.s.tok {
@@ -1122,35 +1233,51 @@ func (p *Parser) parseLiteral() (expr *Expr) {
}
return p.parseEvery()
default:
s := p.save()
expr := p.parseExpr()
if expr != nil {
expr.Negated = negated
if p.s.tok == tokens.With {
if expr.With = p.parseWith(); expr.With == nil {
return nil
}
}
// If we find a plain `every` identifier, attempt to parse an every expression,
// add hint if it succeeds.
if term, ok := expr.Terms.(*Term); ok && Var("every").Equal(term.Value) {
var hint bool
t := p.save()
p.restore(s)
if expr := p.futureParser().parseEvery(); expr != nil {
_, hint = expr.Terms.(*Every)
}
p.restore(t)
if hint {
p.hint("`import future.keywords.every` for `every x in xs { ... }` expressions")
}
}
return expr
}
return nil
return p.parseLiteralExpr(negated)
}
}
func (p *Parser) isAllowedRefKeyword(t tokens.Token) bool {
return p.isAllowedRefKeywordStr(t.String())
}
func (p *Parser) isAllowedRefKeywordStr(s string) bool {
if p.po.Capabilities.ContainsFeature(FeatureKeywordsInRefs) {
return IsKeywordInRegoVersion(s, p.po.EffectiveRegoVersion()) || p.s.s.IsKeyword(s)
}
return false
}
func (p *Parser) parseLiteralExpr(negated bool) *Expr {
s := p.save()
expr := p.parseExpr()
if expr != nil {
expr.Negated = negated
if p.s.tok == tokens.With {
if expr.With = p.parseWith(); expr.With == nil {
return nil
}
}
// If we find a plain `every` identifier, attempt to parse an every expression,
// add hint if it succeeds.
if term, ok := expr.Terms.(*Term); ok && Var("every").Equal(term.Value) {
var hint bool
t := p.save()
p.restore(s)
if expr := p.futureParser().parseEvery(); expr != nil {
_, hint = expr.Terms.(*Every)
}
p.restore(t)
if hint {
p.hint("`import future.keywords.every` for `every x in xs { ... }` expressions")
}
}
return expr
}
return nil
}
func (p *Parser) parseWith() []*With {
withs := []*With{}
@@ -1431,6 +1558,9 @@ func (p *Parser) parseTermIn(lhs *Term, keyVal bool, offset int) *Term {
}
p.restore(s)
}
_ = scanAheadRef(p)
if op := p.parseTermOpName(memberRef, tokens.In); op != nil {
if rhs := p.parseTermRelation(nil, p.s.loc.Offset); rhs != nil {
call := p.setLoc(CallTerm(op, lhs, rhs), lhs.Location, offset, p.s.lastEnd)
@@ -1647,6 +1777,8 @@ func (p *Parser) parseTermFinish(head *Term, skipws bool) *Term {
func (p *Parser) parseNumber() *Term {
var prefix string
loc := p.s.Loc()
// Handle negative sign
if p.s.tok == tokens.Sub {
prefix = "-"
p.scan()
@@ -1658,6 +1790,8 @@ func (p *Parser) parseNumber() *Term {
return nil
}
}
// Handle decimal point
if p.s.tok == tokens.Dot {
prefix += "."
p.scan()
@@ -1667,12 +1801,19 @@ func (p *Parser) parseNumber() *Term {
}
}
// Check for multiple leading 0's, parsed by math/big.Float.Parse as decimal 0:
// https://golang.org/pkg/math/big/#Float.Parse
if ((len(prefix) != 0 && prefix[0] == '-') || len(prefix) == 0) &&
len(p.s.lit) > 1 && p.s.lit[0] == '0' && p.s.lit[1] == '0' {
p.illegal("expected number")
return nil
// Validate leading zeros: reject numbers like "01", "007", etc.
// Skip validation if prefix ends with '.' (like ".123")
hasDecimalPrefix := len(prefix) > 0 && prefix[len(prefix)-1] == '.'
if !hasDecimalPrefix && len(p.s.lit) > 1 && p.s.lit[0] == '0' {
// These are the only valid cases starting with '0':
isDecimal := p.s.lit[1] == '.' // "0.123"
isScientific := len(p.s.lit) > 2 && (p.s.lit[1] == 'e' || p.s.lit[1] == 'E') // "0e5", "0E-3"
if !isDecimal && !isScientific {
p.illegal("expected number without leading zero")
return nil
}
}
// Ensure that the number is valid
@@ -1789,7 +1930,7 @@ func (p *Parser) parseRef(head *Term, offset int) (term *Term) {
switch p.s.tok {
case tokens.Dot:
p.scanWS()
if p.s.tok != tokens.Ident {
if p.s.tok != tokens.Ident && !p.isAllowedRefKeyword(p.s.tok) {
p.illegal("expected %v", tokens.Ident)
return nil
}
@@ -2778,7 +2919,7 @@ func IsFutureKeywordForRegoVersion(s string, v RegoVersion) bool {
func (p *Parser) futureImport(imp *Import, allowedFutureKeywords map[string]tokens.Token) {
path := imp.Path.Value.(Ref)
if len(path) == 1 || !path[1].Equal(InternedStringTerm("keywords")) {
if len(path) == 1 || !path[1].Equal(InternedTerm("keywords")) {
p.errorf(imp.Path.Location, "invalid import, must be `future.keywords`")
return
}
+1 -1
View File
@@ -191,7 +191,7 @@ func checkRegoV1Rule(rule *Rule, opts RegoCheckOptions) Errors {
var errs Errors
if opts.NoKeywordsAsRuleNames && IsKeywordInRegoVersion(rule.Head.Name.String(), RegoV1) {
if opts.NoKeywordsAsRuleNames && len(rule.Head.Reference) < 2 && IsKeywordInRegoVersion(rule.Head.Name.String(), RegoV1) {
errs = append(errs, NewError(ParseErr, rule.Location, "%s keyword cannot be used for rule name", rule.Head.Name.String()))
}
if opts.RequireRuleBodyOrValue && rule.generatedBody && rule.Head.generatedValue {
+7 -7
View File
@@ -61,7 +61,7 @@ func InterfaceToValue(x any) (Value, error) {
case nil:
return NullValue, nil
case bool:
return InternedBooleanTerm(x).Value, nil
return InternedTerm(x).Value, nil
case json.Number:
if interned := InternedIntNumberTermFromString(string(x)); interned != nil {
return interned.Value, nil
@@ -587,9 +587,9 @@ type Boolean bool
// BooleanTerm creates a new Term with a Boolean value.
func BooleanTerm(b bool) *Term {
if b {
return &Term{Value: InternedBooleanTerm(true).Value}
return &Term{Value: InternedTerm(true).Value}
}
return &Term{Value: InternedBooleanTerm(false).Value}
return &Term{Value: InternedTerm(false).Value}
}
// Equal returns true if the other Value is a Boolean and is equal.
@@ -624,7 +624,7 @@ func (bol Boolean) Compare(other Value) int {
// Find returns the current value or a not found error.
func (bol Boolean) Find(path Ref) (Value, error) {
if len(path) == 0 {
return InternedBooleanTerm(bool(bol)).Value, nil
return InternedTerm(bool(bol)).Value, nil
}
return nil, errFindNotFound
}
@@ -676,8 +676,8 @@ func (num Number) Equal(other Value) bool {
case Number:
if n1, ok1 := num.Int64(); ok1 {
n2, ok2 := other.Int64()
if ok1 && ok2 && n1 == n2 {
return true
if ok1 && ok2 {
return n1 == n2
}
}
@@ -1237,7 +1237,7 @@ func (ref Ref) toArray() *Array {
if _, ok := term.Value.(String); ok {
terms = append(terms, term)
} else {
terms = append(terms, InternedStringTerm(term.Value.String()))
terms = append(terms, InternedTerm(term.Value.String()))
}
}
return NewArray(terms...)
+7
View File
@@ -1402,6 +1402,13 @@
}
},
"features": {
"keywords_in_refs": {
"Major": 1,
"Minor": 6,
"Patch": 0,
"PreRelease": "",
"Metadata": ""
},
"rego_v1": {
"Major": 1,
"Minor": 0,
+36 -12
View File
@@ -1092,31 +1092,55 @@ func (b *Bundle) FormatModules(useModulePath bool) error {
// FormatModulesForRegoVersion formats Rego modules to comply with a given Rego version
func (b *Bundle) FormatModulesForRegoVersion(version ast.RegoVersion, preserveModuleRegoVersion bool, useModulePath bool) error {
return b.FormatModulesWithOptions(BundleFormatOptions{
RegoVersion: version,
PreserveModuleRegoVersion: preserveModuleRegoVersion,
UseModulePath: useModulePath,
})
}
type BundleFormatOptions struct {
RegoVersion ast.RegoVersion
Capabilities *ast.Capabilities
PreserveModuleRegoVersion bool
UseModulePath bool
}
// FormatModulesWithOptions formats Rego modules with the given options.
func (b *Bundle) FormatModulesWithOptions(opts BundleFormatOptions) error {
var err error
for i, module := range b.Modules {
opts := format.Opts{}
if preserveModuleRegoVersion {
opts.RegoVersion = module.Parsed.RegoVersion()
opts.ParserOptions = &ast.ParserOptions{
RegoVersion: opts.RegoVersion,
fmtOpts := format.Opts{
RegoVersion: opts.RegoVersion,
Capabilities: opts.Capabilities,
}
if module.Parsed != nil {
fmtOpts.ParserOptions = &ast.ParserOptions{
RegoVersion: module.Parsed.RegoVersion(),
}
} else {
opts.RegoVersion = version
if opts.PreserveModuleRegoVersion {
fmtOpts.RegoVersion = module.Parsed.RegoVersion()
}
}
if fmtOpts.Capabilities == nil {
fmtOpts.Capabilities = ast.CapabilitiesForThisVersion(ast.CapabilitiesRegoVersion(fmtOpts.RegoVersion))
}
if module.Raw == nil {
module.Raw, err = format.AstWithOpts(module.Parsed, opts)
module.Raw, err = format.AstWithOpts(module.Parsed, fmtOpts)
if err != nil {
return err
}
} else {
path := module.URL
if useModulePath {
path = module.Path
p := module.URL
if opts.UseModulePath {
p = module.Path
}
module.Raw, err = format.SourceWithOpts(path, module.Raw, opts)
module.Raw, err = format.SourceWithOpts(p, module.Raw, fmtOpts)
if err != nil {
return err
}
+48 -10
View File
@@ -37,6 +37,8 @@ type Opts struct {
// DropV0Imports instructs the formatter to drop all v0 imports from the module; i.e. 'rego.v1' and 'future.keywords' imports.
// Imports are only removed if [Opts.RegoVersion] makes them redundant.
DropV0Imports bool
Capabilities *ast.Capabilities
}
func (o Opts) effectiveRegoVersion() ast.RegoVersion {
@@ -146,6 +148,10 @@ type fmtOpts struct {
regoV1 bool
regoV1Imported bool
futureKeywords []string
// If true, the formatter will retain keywords in refs, e.g. `p.not ` instead of `p["not"]`.
// The format of the original ref is preserved, so `p["not"]` will still be formatted as `p["not"]`.
allowKeywordsInRefs bool
}
func (o fmtOpts) keywords() []string {
@@ -179,6 +185,12 @@ func AstWithOpts(x any, opts Opts) ([]byte, error) {
o.contains = true
}
capabilities := opts.Capabilities
if capabilities == nil {
capabilities = ast.CapabilitiesForThisVersion(ast.CapabilitiesRegoVersion(opts.effectiveRegoVersion()))
}
o.allowKeywordsInRefs = capabilities.ContainsFeature(ast.FeatureKeywordsInRefs)
memberRef := ast.Member.Ref()
memberWithKeyRef := ast.MemberWithKey.Ref()
@@ -533,7 +545,7 @@ func (w *writer) writeRules(rules []*ast.Rule, comments []*ast.Comment) ([]*ast.
return comments, nil
}
var expandedConst = ast.NewBody(ast.NewExpr(ast.InternedBooleanTerm(true)))
var expandedConst = ast.NewBody(ast.NewExpr(ast.InternedTerm(true)))
func (w *writer) groupableOneLiner(rule *ast.Rule) bool {
// Location required to determine if two rules are adjacent in the policy.
@@ -790,7 +802,7 @@ func (w *writer) writeHead(head *ast.Head, isDefault bool, isExpandedConst bool,
}
if head.Value != nil &&
(head.Key != nil || !ast.InternedBooleanTerm(true).Equal(head.Value) || isExpandedConst || isDefault) {
(head.Key != nil || !ast.InternedTerm(true).Equal(head.Value) || isExpandedConst || isDefault) {
// in rego v1, explicitly print value for ref-head constants that aren't partial set assignments, e.g.:
// * a -> parser error, won't reach here
@@ -801,7 +813,7 @@ func (w *writer) writeHead(head *ast.Head, isDefault bool, isExpandedConst bool,
if head.Location == head.Value.Location &&
head.Name != "else" &&
ast.InternedBooleanTerm(true).Equal(head.Value) &&
ast.InternedTerm(true).Equal(head.Value) &&
!isRegoV1RefConst {
// If the value location is the same as the location of the head,
// we know that the value is generated, i.e. f(1)
@@ -1070,8 +1082,16 @@ func (w *writer) writeFunctionCall(expr *ast.Expr, comments []*ast.Comment) ([]*
}
func (w *writer) writeFunctionCallPlain(terms []*ast.Term, comments []*ast.Comment) ([]*ast.Comment, error) {
w.write(terms[0].String() + "(")
if r, ok := terms[0].Value.(ast.Ref); ok {
if c, err := w.writeRef(r, comments); err != nil {
return c, err
}
} else {
w.write(terms[0].String())
}
w.write("(")
defer w.write(")")
args := make([]any, len(terms)-1)
for i, t := range terms[1:] {
args[i] = t
@@ -1264,7 +1284,7 @@ func (w *writer) writeRef(x ast.Ref, comments []*ast.Comment) ([]*ast.Comment, e
for _, t := range path {
switch p := t.Value.(type) {
case ast.String:
w.writeRefStringPath(p)
w.writeRefStringPath(p, t.Location)
case ast.Var:
w.writeBracketed(w.formatVar(p))
default:
@@ -1292,15 +1312,33 @@ func (w *writer) writeBracketed(str string) {
var varRegexp = regexp.MustCompile("^[[:alpha:]_][[:alpha:][:digit:]_]*$")
func (w *writer) writeRefStringPath(s ast.String) {
func (w *writer) writeRefStringPath(s ast.String, l *ast.Location) {
str := string(s)
if varRegexp.MatchString(str) && !ast.IsInKeywords(str, w.fmtOpts.keywords()) {
w.write("." + str)
} else {
if w.shouldBracketRefTerm(str, l) {
w.writeBracketed(s.String())
} else {
w.write("." + str)
}
}
func (w *writer) shouldBracketRefTerm(s string, l *ast.Location) bool {
if !varRegexp.MatchString(s) {
return true
}
if ast.IsInKeywords(s, w.fmtOpts.keywords()) {
if !w.fmtOpts.allowKeywordsInRefs {
return true
}
if l != nil && l.Text[0] == 34 { // If the original term text starts with '"', we preserve the brackets and quotes
return true
}
}
return false
}
func (*writer) formatVar(v ast.Var) string {
if v.IsWildcard() {
return ast.Wildcard.String()
@@ -2211,5 +2249,5 @@ func isRegoV1Compatible(imp *ast.Import) bool {
path := imp.Path.Value.(ast.Ref)
return len(path) == 2 &&
ast.RegoRootDocument.Equal(path[0]) &&
path[1].Equal(ast.InternedStringTerm("v1"))
path[1].Equal(ast.InternedTerm("v1"))
}
+1 -1
View File
@@ -462,7 +462,7 @@ func getSchemaSetByPathKey(path string) ast.Ref {
key := make(ast.Ref, 1+len(parts))
key[0] = ast.SchemaRootDocument
for i := range parts {
key[i+1] = ast.StringTerm(parts[i])
key[i+1] = ast.InternedTerm(parts[i])
}
return key
+62 -10
View File
@@ -66,9 +66,17 @@ type metrics struct {
// New returns a new Metrics object.
func New() Metrics {
m := &metrics{}
m.Clear()
return m
return &metrics{
timers: map[string]Timer{},
histograms: map[string]Histogram{},
counters: map[string]Counter{},
}
}
// NoOp returns a Metrics implementation that does nothing and costs nothing.
// Used when metrics are expected, but not of interest.
func NoOp() Metrics {
return noOpMetricsInstance
}
type metric struct {
@@ -83,7 +91,6 @@ func (*metrics) Info() Info {
}
func (m *metrics) String() string {
all := m.All()
sorted := make([]metric, 0, len(all))
@@ -147,7 +154,7 @@ func (m *metrics) Counter(name string) Counter {
func (m *metrics) All() map[string]any {
m.mtx.Lock()
defer m.mtx.Unlock()
result := map[string]any{}
result := make(map[string]any, len(m.timers)+len(m.histograms)+len(m.counters))
for name, timer := range m.timers {
result[m.formatKey(name, timer)] = timer.Value()
}
@@ -163,7 +170,7 @@ func (m *metrics) All() map[string]any {
func (m *metrics) Timers() map[string]any {
m.mtx.Lock()
defer m.mtx.Unlock()
ts := map[string]any{}
ts := make(map[string]any, len(m.timers))
for n, t := range m.timers {
ts[m.formatKey(n, t)] = t.Value()
}
@@ -196,7 +203,10 @@ func (*metrics) formatKey(name string, metrics any) string {
type Timer interface {
Value() any
Int64() int64
// Start or resume a timer's time tracking.
Start()
// Stop a timer, and accumulate the delta (in nanoseconds) since it was last
// started.
Stop() int64
}
@@ -208,15 +218,22 @@ type timer struct {
func (t *timer) Start() {
t.mtx.Lock()
defer t.mtx.Unlock()
t.start = time.Now()
t.mtx.Unlock()
}
func (t *timer) Stop() int64 {
t.mtx.Lock()
defer t.mtx.Unlock()
delta := time.Since(t.start).Nanoseconds()
t.value += delta
var delta int64
if !t.start.IsZero() {
// Add the delta to the accumulated time value so far.
delta = time.Since(t.start).Nanoseconds()
t.value += delta
t.start = time.Time{} // Reset the start time to zero.
}
return delta
}
@@ -254,7 +271,7 @@ func (h *histogram) Update(v int64) {
}
func (h *histogram) Value() any {
values := map[string]any{}
values := make(map[string]any, 12)
snap := h.hist.Snapshot()
percentiles := snap.Percentiles([]float64{
0.5,
@@ -310,3 +327,38 @@ func Statistics(num ...int64) any {
}
return t.Value()
}
type noOpMetrics struct{}
type noOpTimer struct{}
type noOpHistogram struct{}
type noOpCounter struct{}
var (
noOpMetricsInstance = &noOpMetrics{}
noOpTimerInstance = &noOpTimer{}
noOpHistogramInstance = &noOpHistogram{}
noOpCounterInstance = &noOpCounter{}
)
func (*noOpMetrics) Info() Info { return Info{Name: "<built-in no-op>"} }
func (*noOpMetrics) Timer(name string) Timer { return noOpTimerInstance }
func (*noOpMetrics) Histogram(name string) Histogram { return noOpHistogramInstance }
func (*noOpMetrics) Counter(name string) Counter { return noOpCounterInstance }
func (*noOpMetrics) All() map[string]any { return nil }
func (*noOpMetrics) Clear() {}
func (*noOpMetrics) MarshalJSON() ([]byte, error) {
return []byte(`{"name": "<built-in no-op>"}`), nil
}
func (*noOpTimer) Start() {}
func (*noOpTimer) Stop() int64 { return 0 }
func (*noOpTimer) Value() any { return 0 }
func (*noOpTimer) Int64() int64 { return 0 }
func (*noOpHistogram) Update(v int64) {}
func (*noOpHistogram) Value() any { return nil }
func (*noOpCounter) Incr() {}
func (*noOpCounter) Add(_ uint64) {}
func (*noOpCounter) Value() any { return 0 }
func (*noOpCounter) Int64() int64 { return 0 }
+4 -5
View File
@@ -11,6 +11,7 @@ import (
"fmt"
"maps"
mr "math/rand"
"net/http"
"sync"
"time"
@@ -18,8 +19,6 @@ import (
"github.com/prometheus/client_golang/prometheus"
"go.opentelemetry.io/otel/sdk/trace"
"github.com/gorilla/mux"
bundleUtils "github.com/open-policy-agent/opa/internal/bundle"
cfg "github.com/open-policy-agent/opa/internal/config"
initload "github.com/open-policy-agent/opa/internal/runtime/init"
@@ -207,7 +206,7 @@ type Manager struct {
serverInitializedOnce sync.Once
printHook print.Hook
enablePrintStatements bool
router *mux.Router
router *http.ServeMux
prometheusRegister prometheus.Registerer
tracerProvider *trace.TracerProvider
distributedTacingOpts tracing.Options
@@ -370,7 +369,7 @@ func PrintHook(h print.Hook) func(*Manager) {
}
}
func WithRouter(r *mux.Router) func(*Manager) {
func WithRouter(r *http.ServeMux) func(*Manager) {
return func(m *Manager) {
m.router = r
}
@@ -655,7 +654,7 @@ func (m *Manager) setCompiler(compiler *ast.Compiler) {
}
// GetRouter returns the managers router if set
func (m *Manager) GetRouter() *mux.Router {
func (m *Manager) GetRouter() *http.ServeMux {
m.mtx.Lock()
defer m.mtx.Unlock()
return m.router
+3 -3
View File
@@ -637,7 +637,7 @@ type Rego struct {
generateJSON func(*ast.Term, *EvalContext) (any, error)
printHook print.Hook
enablePrintStatements bool
distributedTacingOpts tracing.Options
distributedTracingOpts tracing.Options
strict bool
pluginMgr *plugins.Manager
plugins []TargetPlugin
@@ -1251,7 +1251,7 @@ func PrintHook(h print.Hook) func(r *Rego) {
// DistributedTracingOpts sets the options to be used by distributed tracing.
func DistributedTracingOpts(tr tracing.Options) func(r *Rego) {
return func(r *Rego) {
r.distributedTacingOpts = tr
r.distributedTracingOpts = tr
}
}
@@ -2185,7 +2185,7 @@ func (r *Rego) eval(ctx context.Context, ectx *EvalContext) (ResultSet, error) {
WithBuiltinErrorList(r.builtinErrorList).
WithSeed(ectx.seed).
WithPrintHook(ectx.printHook).
WithDistributedTracingOpts(r.distributedTacingOpts).
WithDistributedTracingOpts(r.distributedTracingOpts).
WithVirtualCache(ectx.virtualCache).
WithBaseCache(ectx.baseCache)
+1 -1
View File
@@ -168,7 +168,7 @@ func getResult(evalResult *opa.Result) (ast.Value, error) {
return nil, err
}
result := obj.Get(ast.InternedStringTerm("result"))
result := obj.Get(ast.InternedTerm("result"))
return result.Value, nil
}
+3 -3
View File
@@ -154,7 +154,7 @@ func newUpdateArrayAST(data *ast.Array, op storage.PatchOp, path storage.Path, i
}
func newUpdateObjectAST(data ast.Object, op storage.PatchOp, path storage.Path, idx int, value ast.Value) (*updateAST, error) {
key := ast.InternedStringTerm(path[idx])
key := ast.InternedTerm(path[idx])
val := data.Get(key)
if idx == len(path)-1 {
@@ -200,7 +200,7 @@ func setInAst(data ast.Value, path storage.Path, value ast.Value) (ast.Value, er
}
func setInAstObject(obj ast.Object, path storage.Path, value ast.Value) (ast.Value, error) {
key := ast.InternedStringTerm(path[0])
key := ast.InternedTerm(path[0])
if len(path) == 1 {
obj.Insert(key, ast.NewTerm(value))
@@ -256,7 +256,7 @@ func removeInAst(value ast.Value, path storage.Path) (ast.Value, error) {
}
func removeInAstObject(obj ast.Object, path storage.Path) (ast.Value, error) {
key := ast.InternedStringTerm(path[0])
key := ast.InternedTerm(path[0])
if len(path) == 1 {
var items [][2]*ast.Term
+21 -21
View File
@@ -14,13 +14,13 @@ import (
func builtinCount(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
switch a := operands[0].Value.(type) {
case *ast.Array:
return iter(ast.InternedIntNumberTerm(a.Len()))
return iter(ast.InternedTerm(a.Len()))
case ast.Object:
return iter(ast.InternedIntNumberTerm(a.Len()))
return iter(ast.InternedTerm(a.Len()))
case ast.Set:
return iter(ast.InternedIntNumberTerm(a.Len()))
return iter(ast.InternedTerm(a.Len()))
case ast.String:
return iter(ast.InternedIntNumberTerm(len([]rune(a))))
return iter(ast.InternedTerm(len([]rune(a))))
}
return builtins.NewOperandTypeErr(1, operands[0].Value, "array", "object", "set", "string")
}
@@ -40,7 +40,7 @@ func builtinSum(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) err
return true
})
if !nonInts {
return iter(ast.InternedIntNumberTerm(is))
return iter(ast.InternedTerm(is))
}
// Non-integer values found, so we need to sum as floats.
@@ -70,7 +70,7 @@ func builtinSum(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) err
return true
})
if !nonInts {
return iter(ast.InternedIntNumberTerm(is))
return iter(ast.InternedTerm(is))
}
sum := big.NewFloat(0)
@@ -209,7 +209,7 @@ func builtinAll(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) err
switch val := operands[0].Value.(type) {
case ast.Set:
res := true
match := ast.InternedBooleanTerm(true)
match := ast.InternedTerm(true)
val.Until(func(term *ast.Term) bool {
if !match.Equal(term) {
res = false
@@ -217,10 +217,10 @@ func builtinAll(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) err
}
return false
})
return iter(ast.InternedBooleanTerm(res))
return iter(ast.InternedTerm(res))
case *ast.Array:
res := true
match := ast.InternedBooleanTerm(true)
match := ast.InternedTerm(true)
val.Until(func(term *ast.Term) bool {
if !match.Equal(term) {
res = false
@@ -228,7 +228,7 @@ func builtinAll(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) err
}
return false
})
return iter(ast.InternedBooleanTerm(res))
return iter(ast.InternedTerm(res))
default:
return builtins.NewOperandTypeErr(1, operands[0].Value, "array", "set")
}
@@ -237,11 +237,11 @@ func builtinAll(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) err
func builtinAny(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
switch val := operands[0].Value.(type) {
case ast.Set:
res := val.Len() > 0 && val.Contains(ast.InternedBooleanTerm(true))
return iter(ast.InternedBooleanTerm(res))
res := val.Len() > 0 && val.Contains(ast.InternedTerm(true))
return iter(ast.InternedTerm(res))
case *ast.Array:
res := false
match := ast.InternedBooleanTerm(true)
match := ast.InternedTerm(true)
val.Until(func(term *ast.Term) bool {
if match.Equal(term) {
res = true
@@ -249,7 +249,7 @@ func builtinAny(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) err
}
return false
})
return iter(ast.InternedBooleanTerm(res))
return iter(ast.InternedTerm(res))
default:
return builtins.NewOperandTypeErr(1, operands[0].Value, "array", "set")
}
@@ -259,20 +259,20 @@ func builtinMember(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term)
containee := operands[0]
switch c := operands[1].Value.(type) {
case ast.Set:
return iter(ast.InternedBooleanTerm(c.Contains(containee)))
return iter(ast.InternedTerm(c.Contains(containee)))
case *ast.Array:
for i := range c.Len() {
if c.Elem(i).Value.Compare(containee.Value) == 0 {
return iter(ast.InternedBooleanTerm(true))
return iter(ast.InternedTerm(true))
}
}
return iter(ast.InternedBooleanTerm(false))
return iter(ast.InternedTerm(false))
case ast.Object:
return iter(ast.InternedBooleanTerm(c.Until(func(_, v *ast.Term) bool {
return iter(ast.InternedTerm(c.Until(func(_, v *ast.Term) bool {
return v.Value.Compare(containee.Value) == 0
})))
}
return iter(ast.InternedBooleanTerm(false))
return iter(ast.InternedTerm(false))
}
func builtinMemberWithKey(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
@@ -283,9 +283,9 @@ func builtinMemberWithKey(_ BuiltinContext, operands []*ast.Term, iter func(*ast
if act := c.Get(key); act != nil {
ret = act.Value.Compare(val.Value) == 0
}
return iter(ast.InternedBooleanTerm(ret))
return iter(ast.InternedTerm(ret))
}
return iter(ast.InternedBooleanTerm(false))
return iter(ast.InternedTerm(false))
}
func init() {
+4 -4
View File
@@ -67,7 +67,7 @@ func builtinPlus(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) er
y, ok2 := n2.Int()
if ok1 && ok2 && inSmallIntRange(x) && inSmallIntRange(y) {
return iter(ast.InternedIntNumberTerm(x + y))
return iter(ast.InternedTerm(x + y))
}
f := new(big.Float).Add(builtins.NumberToFloat(n1), builtins.NumberToFloat(n2))
@@ -89,7 +89,7 @@ func builtinMultiply(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term
y, ok2 := n2.Int()
if ok1 && ok2 && inSmallIntRange(x) && inSmallIntRange(y) {
return iter(ast.InternedIntNumberTerm(x * y))
return iter(ast.InternedTerm(x * y))
}
f := new(big.Float).Mul(builtins.NumberToFloat(n1), builtins.NumberToFloat(n2))
@@ -155,7 +155,7 @@ func builtinMinus(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) e
y, oky := n2.Int()
if okx && oky && inSmallIntRange(x) && inSmallIntRange(y) {
return iter(ast.InternedIntNumberTerm(x - y))
return iter(ast.InternedTerm(x - y))
}
f := new(big.Float).Sub(builtins.NumberToFloat(n1), builtins.NumberToFloat(n2))
@@ -199,7 +199,7 @@ func builtinRem(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) err
return errors.New("modulo by zero")
}
return iter(ast.InternedIntNumberTerm(x % y))
return iter(ast.InternedTerm(x % y))
}
op1, err1 := builtins.NumberToInt(n1)
+1 -1
View File
@@ -39,7 +39,7 @@ type NDBCache map[string]ast.Object
func (c NDBCache) AsValue() ast.Value {
out := ast.NewObject()
for bname, obj := range c {
out.Insert(ast.InternedStringTerm(bname), ast.NewTerm(obj))
out.Insert(ast.InternedTerm(bname), ast.NewTerm(obj))
}
return out
}
+3 -3
View File
@@ -15,12 +15,12 @@ import (
func builtinToNumber(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
switch a := operands[0].Value.(type) {
case ast.Null:
return iter(ast.InternedIntNumberTerm(0))
return iter(ast.InternedTerm(0))
case ast.Boolean:
if a {
return iter(ast.InternedIntNumberTerm(1))
return iter(ast.InternedTerm(1))
}
return iter(ast.InternedIntNumberTerm(0))
return iter(ast.InternedTerm(0))
case ast.Number:
return iter(operands[0])
case ast.String:
+7 -7
View File
@@ -76,7 +76,7 @@ func builtinNetCIDRIntersects(_ BuiltinContext, operands []*ast.Term, iter func(
// If either net contains the others starting IP they are overlapping
cidrsOverlap := cidrnetA.Contains(cidrnetB.IP) || cidrnetB.Contains(cidrnetA.IP)
return iter(ast.InternedBooleanTerm(cidrsOverlap))
return iter(ast.InternedTerm(cidrsOverlap))
}
func builtinNetCIDRContains(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
@@ -93,7 +93,7 @@ func builtinNetCIDRContains(_ BuiltinContext, operands []*ast.Term, iter func(*a
ip := net.ParseIP(string(bStr))
if ip != nil {
return iter(ast.InternedBooleanTerm(cidrnetA.Contains(ip)))
return iter(ast.InternedTerm(cidrnetA.Contains(ip)))
}
// It wasn't an IP, try and parse it as a CIDR
@@ -114,7 +114,7 @@ func builtinNetCIDRContains(_ BuiltinContext, operands []*ast.Term, iter func(*a
cidrContained = cidrnetA.Contains(lastIP)
}
return iter(ast.InternedBooleanTerm(cidrContained))
return iter(ast.InternedTerm(cidrContained))
}
var errNetCIDRContainsMatchElementType = errors.New("element must be string or non-empty array")
@@ -143,7 +143,7 @@ func evalNetCIDRContainsMatchesOperand(operand int, a *ast.Term, iter func(cidr,
if err != nil {
return fmt.Errorf("operand %v: %v", operand, err)
}
if err := iter(cidr, ast.InternedIntNumberTerm(i)); err != nil {
if err := iter(cidr, ast.InternedTerm(i)); err != nil {
return err
}
}
@@ -220,13 +220,13 @@ func builtinNetCIDRExpand(bctx BuiltinContext, operands []*ast.Term, iter func(*
func builtinNetCIDRIsValid(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
cidr, err := builtins.StringOperand(operands[0].Value, 1)
if err != nil {
return iter(ast.InternedBooleanTerm(false))
return iter(ast.InternedTerm(false))
}
if _, _, err := net.ParseCIDR(string(cidr)); err != nil {
return iter(ast.InternedBooleanTerm(false))
return iter(ast.InternedTerm(false))
}
return iter(ast.InternedBooleanTerm(true))
return iter(ast.InternedTerm(true))
}
type cidrBlockRange struct {
+1 -1
View File
@@ -34,7 +34,7 @@ func compareEq(a, b ast.Value) bool {
func builtinCompare(cmp compareFunc) BuiltinFunc {
return func(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
return iter(ast.InternedBooleanTerm(cmp(operands[0].Value, operands[1].Value)))
return iter(ast.InternedTerm(cmp(operands[0].Value, operands[1].Value)))
}
}
+7 -7
View File
@@ -99,12 +99,12 @@ func builtinCryptoX509ParseAndVerifyCertificates(_ BuiltinContext, operands []*a
certs, err := getX509CertsFromString(string(input))
if err != nil {
return iter(ast.ArrayTerm(ast.InternedBooleanTerm(false), ast.InternedEmptyArray))
return iter(ast.ArrayTerm(ast.InternedTerm(false), ast.InternedEmptyArray))
}
verified, err := verifyX509CertificateChain(certs, x509.VerifyOptions{})
if err != nil {
return iter(ast.ArrayTerm(ast.InternedBooleanTerm(false), ast.InternedEmptyArray))
return iter(ast.ArrayTerm(ast.InternedTerm(false), ast.InternedEmptyArray))
}
value, err := ast.InterfaceToValue(extendCertificates(verified))
@@ -112,7 +112,7 @@ func builtinCryptoX509ParseAndVerifyCertificates(_ BuiltinContext, operands []*a
return err
}
valid := ast.ArrayTerm(ast.InternedBooleanTerm(true), ast.NewTerm(value))
valid := ast.ArrayTerm(ast.InternedTerm(true), ast.NewTerm(value))
return iter(valid)
}
@@ -148,7 +148,7 @@ func builtinCryptoX509ParseAndVerifyCertificatesWithOptions(_ BuiltinContext, op
certs, err := getX509CertsFromString(string(input))
if err != nil {
return iter(ast.ArrayTerm(ast.InternedBooleanTerm(false), ast.InternedEmptyArray))
return iter(ast.ArrayTerm(ast.InternedTerm(false), ast.InternedEmptyArray))
}
// Collect the cert verification options
@@ -159,7 +159,7 @@ func builtinCryptoX509ParseAndVerifyCertificatesWithOptions(_ BuiltinContext, op
verified, err := verifyX509CertificateChain(certs, verifyOpt)
if err != nil {
return iter(ast.ArrayTerm(ast.InternedBooleanTerm(false), ast.InternedEmptyArray))
return iter(ast.ArrayTerm(ast.InternedTerm(false), ast.InternedEmptyArray))
}
value, err := ast.InterfaceToValue(verified)
@@ -167,7 +167,7 @@ func builtinCryptoX509ParseAndVerifyCertificatesWithOptions(_ BuiltinContext, op
return err
}
return iter(ast.ArrayTerm(ast.InternedBooleanTerm(true), ast.NewTerm(value)))
return iter(ast.ArrayTerm(ast.InternedTerm(true), ast.NewTerm(value)))
}
func extractVerifyOpts(options ast.Object) (verifyOpt x509.VerifyOptions, err error) {
@@ -513,7 +513,7 @@ func builtinCryptoHmacEqual(_ BuiltinContext, operands []*ast.Term, iter func(*a
res := hmac.Equal([]byte(mac1), []byte(mac2))
return iter(ast.InternedBooleanTerm(res))
return iter(ast.InternedTerm(res))
}
func init() {
+8 -8
View File
@@ -144,10 +144,10 @@ func builtinJSONIsValid(_ BuiltinContext, operands []*ast.Term, iter func(*ast.T
str, err := builtins.StringOperand(operands[0].Value, 1)
if err != nil {
return iter(ast.InternedBooleanTerm(false))
return iter(ast.InternedTerm(false))
}
return iter(ast.InternedBooleanTerm(json.Valid([]byte(str))))
return iter(ast.InternedTerm(json.Valid([]byte(str))))
}
func builtinBase64Encode(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
@@ -169,17 +169,17 @@ func builtinBase64Decode(_ BuiltinContext, operands []*ast.Term, iter func(*ast.
if err != nil {
return err
}
return iter(ast.StringTerm(string(result)))
return iter(ast.InternedTerm(string(result)))
}
func builtinBase64IsValid(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
str, err := builtins.StringOperand(operands[0].Value, 1)
if err != nil {
return iter(ast.InternedBooleanTerm(false))
return iter(ast.InternedTerm(false))
}
_, err = base64.StdEncoding.DecodeString(string(str))
return iter(ast.InternedBooleanTerm(err == nil))
return iter(ast.InternedTerm(err == nil))
}
func builtinBase64UrlEncode(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
@@ -224,7 +224,7 @@ func builtinBase64UrlDecode(_ BuiltinContext, operands []*ast.Term, iter func(*a
if err != nil {
return err
}
return iter(ast.StringTerm(string(result)))
return iter(ast.InternedTerm(string(result)))
}
func builtinURLQueryEncode(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
@@ -355,12 +355,12 @@ func builtinYAMLUnmarshal(_ BuiltinContext, operands []*ast.Term, iter func(*ast
func builtinYAMLIsValid(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
str, err := builtins.StringOperand(operands[0].Value, 1)
if err != nil {
return iter(ast.InternedBooleanTerm(false))
return iter(ast.InternedTerm(false))
}
var x any
err = yaml.Unmarshal([]byte(str), &x)
return iter(ast.InternedBooleanTerm(err == nil))
return iter(ast.InternedTerm(err == nil))
}
func builtinHexEncode(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
+64 -41
View File
@@ -229,6 +229,11 @@ func (e *eval) unknown(x any, b *bindings) bool {
return saveRequired(e.compiler, e.inliningControl, true, e.saveSet, b, x, false)
}
// exactly like `unknown` above` but without the cost of `any` boxing when arg is known to be a ref
func (e *eval) unknownRef(ref ast.Ref, b *bindings) bool {
return e.partial() && saveRequired(e.compiler, e.inliningControl, true, e.saveSet, b, ast.NewTerm(ref), false)
}
func (e *eval) traceEnter(x ast.Node) {
e.traceEvent(EnterOp, x, "", nil)
}
@@ -458,7 +463,7 @@ func (e *eval) evalStep(iter evalIterator) error {
return iter(e)
})
}
if !e.bindings.Plug(rterm).Equal(ast.InternedBooleanTerm(false)) {
if !e.bindings.Plug(rterm).Equal(ast.InternedTerm(false)) {
defined = true
err := iter(e)
e.traceRedo(expr)
@@ -519,7 +524,7 @@ func (e *eval) evalStep(iter evalIterator) error {
return iter(e)
})
}
if !e.bindings.Plug(rterm).Equal(ast.InternedBooleanTerm(false)) {
if !e.bindings.Plug(rterm).Equal(ast.InternedTerm(false)) {
return iter(e)
}
return nil
@@ -917,6 +922,7 @@ func (e *eval) evalCall(terms []*ast.Term, iter unifyIterator) error {
} else {
ir, err = e.getRules(ref, terms[1:])
}
defer ast.IndexResultPool.Put(ir)
if err != nil {
return err
}
@@ -943,36 +949,41 @@ func (e *eval) evalCall(terms []*ast.Term, iter unifyIterator) error {
return e.saveCall(bi.Decl.Arity(), terms, iter)
}
var parentID uint64
if e.parent != nil {
parentID = e.parent.queryID
}
var bctx *BuiltinContext
var capabilities *ast.Capabilities
if e.compiler != nil {
capabilities = e.compiler.Capabilities()
}
// Creating a BuiltinContext is expensive, so only do it if the builtin depends on it.
if bi.NeedsBuiltInContext() {
var parentID uint64
if e.parent != nil {
parentID = e.parent.queryID
}
bctx := BuiltinContext{
Context: e.ctx,
Metrics: e.metrics,
Seed: e.seed,
Time: e.time,
Cancel: e.cancel,
Runtime: e.runtime,
Cache: e.builtinCache,
InterQueryBuiltinCache: e.interQueryBuiltinCache,
InterQueryBuiltinValueCache: e.interQueryBuiltinValueCache,
NDBuiltinCache: e.ndBuiltinCache,
Location: e.query[e.index].Location,
QueryTracers: e.tracers,
TraceEnabled: e.traceEnabled,
QueryID: e.queryID,
ParentID: parentID,
PrintHook: e.printHook,
DistributedTracingOpts: e.tracingOpts,
Capabilities: capabilities,
RoundTripper: e.roundTripper,
var capabilities *ast.Capabilities
if e.compiler != nil {
capabilities = e.compiler.Capabilities()
}
bctx = &BuiltinContext{
Context: e.ctx,
Metrics: e.metrics,
Seed: e.seed,
Time: e.time,
Cancel: e.cancel,
Runtime: e.runtime,
Cache: e.builtinCache,
InterQueryBuiltinCache: e.interQueryBuiltinCache,
InterQueryBuiltinValueCache: e.interQueryBuiltinValueCache,
NDBuiltinCache: e.ndBuiltinCache,
Location: e.query[e.index].Location,
QueryTracers: e.tracers,
TraceEnabled: e.traceEnabled,
QueryID: e.queryID,
ParentID: parentID,
PrintHook: e.printHook,
DistributedTracingOpts: e.tracingOpts,
Capabilities: capabilities,
RoundTripper: e.roundTripper,
}
}
eval := evalBuiltin{
@@ -1895,6 +1906,7 @@ func (e *eval) getDeclArgsLen(x *ast.Expr) (int, error) {
}
ir, err := e.getRules(operator, nil)
defer ast.IndexResultPool.Put(ir)
if err != nil {
return -1, err
} else if ir == nil || ir.Empty() {
@@ -1916,14 +1928,14 @@ func (e *eval) updateFromQuery(expr *ast.Expr) {
type evalBuiltin struct {
e *eval
bi *ast.Builtin
bctx BuiltinContext
bctx *BuiltinContext
f BuiltinFunc
terms []*ast.Term
}
// Is this builtin non-deterministic, and did the caller provide an NDBCache?
func (e *evalBuiltin) canUseNDBCache(bi *ast.Builtin) bool {
return bi.Nondeterministic && e.bctx.NDBuiltinCache != nil
return bi.Nondeterministic && e.bctx != nil && e.bctx.NDBuiltinCache != nil
}
func (e *evalBuiltin) eval(iter unifyIterator) error {
@@ -1971,8 +1983,18 @@ func (e *evalBuiltin) eval(iter unifyIterator) error {
e.e.instr.startTimer(evalOpBuiltinCall)
}
var bctx BuiltinContext
if e.bctx == nil {
bctx = BuiltinContext{
// Location potentially needed for error reporting.
Location: e.e.query[e.e.index].Location,
}
} else {
bctx = *e.bctx
}
// Normal unification flow for builtins:
err := e.f(e.bctx, operands, func(output *ast.Term) error {
err := e.f(bctx, operands, func(output *ast.Term) error {
e.e.instr.stopTimer(evalOpBuiltinCall)
@@ -2053,7 +2075,7 @@ func (e evalFunc) eval(iter unifyIterator) error {
if len(defRule.Head.Args) == len(e.terms)-1 {
// The function is called without collecting the result in an output term,
// therefore any successful evaluation of the function is of interest, including the default value ...
if ret := defRule.Head.Value; ret == nil || !ret.Equal(ast.InternedBooleanTerm(false)) {
if ret := defRule.Head.Value; ret == nil || !ret.Equal(ast.InternedTerm(false)) {
// ... unless the default value is false,
mustGenerateSupport = true
}
@@ -2070,7 +2092,7 @@ func (e evalFunc) eval(iter unifyIterator) error {
if mustGenerateSupport || e.e.inliningControl.shallow || e.e.inliningControl.Disabled(ref, false) {
// check if the function definitions, or any of the arguments
// contain something unknown
unknown := e.e.unknown(ref, e.e.bindings)
unknown := e.e.unknownRef(ref, e.e.bindings)
for i := 1; !unknown && i <= argCount; i++ {
unknown = e.e.unknown(e.terms[i], e.e.bindings)
}
@@ -2406,7 +2428,7 @@ func (e evalTree) finish(iter unifyIterator) error {
// In some cases, it may not be possible to PE the ref. If the path refers
// to virtual docs that PE does not support or base documents where inlining
// has been disabled, then we have to save.
if e.e.partial() && e.e.unknown(e.plugged, e.e.bindings) {
if e.e.partial() && e.e.unknownRef(e.plugged, e.e.bindings) {
return e.e.saveUnify(ast.NewTerm(e.plugged), e.rterm, e.bindings, e.rbindings, iter)
}
@@ -2468,7 +2490,7 @@ func (e evalTree) enumerate(iter unifyIterator) error {
switch doc := doc.(type) {
case *ast.Array:
for i := range doc.Len() {
k := ast.InternedIntNumberTerm(i)
k := ast.InternedTerm(i)
err := e.e.biunify(k, e.ref[e.pos], e.bindings, e.bindings, func() error {
return e.next(iter, k)
})
@@ -2609,13 +2631,14 @@ type evalVirtual struct {
func (e evalVirtual) eval(iter unifyIterator) error {
ir, err := e.e.getRules(e.plugged[:e.pos+1], nil)
defer ast.IndexResultPool.Put(ir)
if err != nil {
return err
}
// Partial evaluation of ordered rules is not supported currently. Save the
// expression and continue. This could be revisited in the future.
if len(ir.Else) > 0 && e.e.unknown(e.ref, e.bindings) {
if len(ir.Else) > 0 && e.e.unknownRef(e.ref, e.bindings) {
return e.e.saveUnify(ast.NewTerm(e.ref), e.rterm, e.bindings, e.rbindings, iter)
}
@@ -3425,7 +3448,7 @@ func (e evalVirtualComplete) eval(iter unifyIterator) error {
return nil
}
if !e.e.unknown(e.ref, e.bindings) {
if !e.e.unknownRef(e.ref, e.bindings) {
return e.evalValue(iter, e.ir.EarlyExit)
}
@@ -3434,7 +3457,7 @@ func (e evalVirtualComplete) eval(iter unifyIterator) error {
if e.ir.Default != nil {
// If inlining has been disabled for the rterm, and the default rule has a 'false' result value,
// the default value is inconsequential, and support does not need to be generated.
if !(e.ir.Default.Head.Value.Equal(ast.InternedBooleanTerm(false)) && e.e.inliningControl.Disabled(e.rterm.Value, false)) {
if !(e.ir.Default.Head.Value.Equal(ast.InternedTerm(false)) && e.e.inliningControl.Disabled(e.rterm.Value, false)) {
// If the other term is not constant OR it's equal to the default value, then
// a support rule must be produced as the default value _may_ be required. On
// the other hand, if the other term is constant (i.e., it does not require
@@ -3752,7 +3775,7 @@ func (e evalTerm) enumerate(iter unifyIterator) error {
// win across most policies. Those cases are however much more complex, as we need to deal with
// any type on either side, not just int/var as is the case here.
for i := range v.Len() {
a := ast.InternedIntNumberTerm(i)
a := ast.InternedTerm(i)
b := e.ref[e.pos]
if _, ok := b.Value.(ast.Var); ok {
+1 -1
View File
@@ -57,7 +57,7 @@ func builtinGlobMatch(bctx BuiltinContext, operands []*ast.Term, iter func(*ast.
if err != nil {
return err
}
return iter(ast.InternedBooleanTerm(m))
return iter(ast.InternedTerm(m))
}
func globCompileAndMatch(bctx BuiltinContext, id, pattern, match string, delimiters []rune) (bool, error) {
+12 -12
View File
@@ -331,7 +331,7 @@ func builtinGraphQLParseAndVerify(bctx BuiltinContext, operands []*ast.Term, ite
var err error
unverified := ast.ArrayTerm(
ast.InternedBooleanTerm(false),
ast.InternedTerm(false),
ast.NewTerm(ast.NewObject()),
ast.NewTerm(ast.NewObject()),
)
@@ -404,7 +404,7 @@ func builtinGraphQLParseAndVerify(bctx BuiltinContext, operands []*ast.Term, ite
// Construct return value.
verified := ast.ArrayTerm(
ast.InternedBooleanTerm(true),
ast.InternedTerm(true),
ast.NewTerm(queryResult),
ast.NewTerm(querySchema),
)
@@ -482,10 +482,10 @@ func builtinGraphQLIsValid(bctx BuiltinContext, operands []*ast.Term, iter func(
queryDoc, err = objectToQueryDocument(x)
default:
// Error if wrong type.
return iter(ast.InternedBooleanTerm(false))
return iter(ast.InternedTerm(false))
}
if err != nil {
return iter(ast.InternedBooleanTerm(false))
return iter(ast.InternedTerm(false))
}
schemaCacheKey, schema := cacheGetSchema(bctx, operands[1])
@@ -497,26 +497,26 @@ func builtinGraphQLIsValid(bctx BuiltinContext, operands []*ast.Term, iter func(
schemaDoc, err = objectToSchemaDocument(x)
default:
// Error if wrong type.
return iter(ast.InternedBooleanTerm(false))
return iter(ast.InternedTerm(false))
}
if err != nil {
return iter(ast.InternedBooleanTerm(false))
return iter(ast.InternedTerm(false))
}
// Validate the query against the schema, erroring if there's an issue.
schema, err = convertSchema(schemaDoc)
if err != nil {
return iter(ast.InternedBooleanTerm(false))
return iter(ast.InternedTerm(false))
}
cacheInsertSchema(bctx, schemaCacheKey, schema)
}
if err := validateQuery(schema, queryDoc); err != nil {
return iter(ast.InternedBooleanTerm(false))
return iter(ast.InternedTerm(false))
}
// If we got this far, the GraphQL query passed validation.
return iter(ast.InternedBooleanTerm(true))
return iter(ast.InternedTerm(true))
}
func builtinGraphQLSchemaIsValid(bctx BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
@@ -535,10 +535,10 @@ func builtinGraphQLSchemaIsValid(bctx BuiltinContext, operands []*ast.Term, iter
schemaDoc, err = objectToSchemaDocument(x)
default:
// Error if wrong type.
return iter(ast.InternedBooleanTerm(false))
return iter(ast.InternedTerm(false))
}
if err != nil {
return iter(ast.InternedBooleanTerm(false))
return iter(ast.InternedTerm(false))
}
// Validate the schema, this determines the result
// and whether there is a schema to cache
@@ -548,7 +548,7 @@ func builtinGraphQLSchemaIsValid(bctx BuiltinContext, operands []*ast.Term, iter
}
}
return iter(ast.InternedBooleanTerm(err == nil))
return iter(ast.InternedTerm(err == nil))
}
// Insert Schema into cache
+32 -11
View File
@@ -14,6 +14,7 @@ import (
"fmt"
"io"
"math"
"mime"
"net"
"net/http"
"net/url"
@@ -95,7 +96,7 @@ var (
allowedKeys = ast.NewSet()
keyCache = make(map[string]*ast.Term, len(allowedKeyNames))
cacheableCodes = ast.NewSet()
requiredKeys = ast.NewSet(ast.InternedStringTerm("method"), ast.InternedStringTerm("url"))
requiredKeys = ast.NewSet(ast.InternedTerm("method"), ast.InternedTerm("url"))
httpSendLatencyMetricKey = "rego_builtin_http_send"
httpSendInterQueryCacheHits = httpSendLatencyMetricKey + "_interquery_cache_hits"
)
@@ -161,19 +162,19 @@ func generateRaiseErrorResult(err error) *ast.Term {
switch err.(type) {
case *url.Error:
errObj = ast.NewObject(
ast.Item(ast.InternedStringTerm("code"), httpSendNetworkErrTerm),
ast.Item(ast.InternedStringTerm("message"), ast.StringTerm(err.Error())),
ast.Item(ast.InternedTerm("code"), httpSendNetworkErrTerm),
ast.Item(ast.InternedTerm("message"), ast.StringTerm(err.Error())),
)
default:
errObj = ast.NewObject(
ast.Item(ast.InternedStringTerm("code"), httpSendInternalErrTerm),
ast.Item(ast.InternedStringTerm("message"), ast.StringTerm(err.Error())),
ast.Item(ast.InternedTerm("code"), httpSendInternalErrTerm),
ast.Item(ast.InternedTerm("message"), ast.StringTerm(err.Error())),
)
}
return ast.ObjectTerm(
ast.Item(ast.InternedStringTerm("status_code"), ast.InternedIntNumberTerm(0)),
ast.Item(ast.InternedStringTerm("error"), ast.NewTerm(errObj)),
ast.Item(ast.InternedTerm("status_code"), ast.InternedTerm(0)),
ast.Item(ast.InternedTerm("error"), ast.NewTerm(errObj)),
)
}
@@ -755,6 +756,26 @@ func executeHTTPRequest(req *http.Request, client *http.Client, inputReqObj ast.
return nil, err
}
func isJSONType(header http.Header) bool {
t, _, err := mime.ParseMediaType(header.Get("Content-Type"))
if err != nil {
return false
}
mediaType := strings.Split(t, "/")
if len(mediaType) != 2 {
return false
}
if mediaType[0] == "application" {
if mediaType[1] == "json" || strings.HasSuffix(mediaType[1], "+json") {
return true
}
}
return false
}
func isContentType(header http.Header, typ ...string) bool {
for _, t := range typ {
if strings.Contains(header.Get("Content-Type"), t) {
@@ -962,7 +983,7 @@ func (c *interQueryCache) checkHTTPSendInterQueryCache() (ast.Value, error) {
// insertIntoHTTPSendInterQueryCache inserts given key and value in the inter-query cache
func insertIntoHTTPSendInterQueryCache(bctx BuiltinContext, key ast.Value, resp *http.Response, respBody []byte, cacheParams *forceCacheParams) error {
if resp == nil || (!forceCaching(cacheParams) && !canStore(resp.Header)) || !cacheableCodes.Contains(ast.InternedIntNumberTerm(resp.StatusCode)) {
if resp == nil || (!forceCaching(cacheParams) && !canStore(resp.Header)) || !cacheableCodes.Contains(ast.InternedTerm(resp.StatusCode)) {
return nil
}
@@ -1006,7 +1027,7 @@ func createKeys() {
func createCacheableHTTPStatusCodes() {
for _, element := range cacheableHTTPStatusCodes {
cacheableCodes.Add(ast.InternedIntNumberTerm(element))
cacheableCodes.Add(ast.InternedTerm(element))
}
}
@@ -1383,7 +1404,7 @@ func prepareASTResult(headers http.Header, forceJSONDecode, forceYAMLDecode bool
// an error will not be returned. Instead, the "body" field
// in the result will be null.
switch {
case forceJSONDecode || isContentType(headers, "application/json"):
case forceJSONDecode || isJSONType(headers):
_ = util.UnmarshalJSON(body, &resultBody)
case forceYAMLDecode || isContentType(headers, "application/yaml", "application/x-yaml"):
_ = util.Unmarshal(body, &resultBody)
@@ -1548,7 +1569,7 @@ func (c *intraQueryCache) InsertIntoCache(value *http.Response) (ast.Value, erro
return nil, handleHTTPSendErr(c.bctx, err)
}
if cacheableCodes.Contains(ast.InternedIntNumberTerm(value.StatusCode)) {
if cacheableCodes.Contains(ast.InternedTerm(value.StatusCode)) {
insertIntoHTTPSendCache(c.bctx, c.key, result)
}
+1 -1
View File
@@ -44,7 +44,7 @@ func astValueToJSONSchemaLoader(value ast.Value) (gojsonschema.JSONLoader, error
}
func newResultTerm(valid bool, data *ast.Term) *ast.Term {
return ast.ArrayTerm(ast.InternedBooleanTerm(valid), data)
return ast.ArrayTerm(ast.InternedTerm(valid), data)
}
// builtinJSONSchemaVerify accepts 1 argument which can be string or object and checks if it is valid JSON schema.
+24 -20
View File
@@ -20,7 +20,7 @@ var one = big.NewInt(1)
func builtinNumbersRange(bctx BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
if canGenerateCheapRange(operands) {
return generateCheapRange(operands, iter)
return generateCheapRange(operands, 1, iter)
}
x, err := builtins.BigIntOperand(operands[0].Value, 1)
@@ -42,6 +42,13 @@ func builtinNumbersRange(bctx BuiltinContext, operands []*ast.Term, iter func(*a
}
func builtinNumbersRangeStep(bctx BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
if canGenerateCheapRangeStep(operands) {
step, _ := builtins.IntOperand(operands[2].Value, 3)
if step <= 0 {
return errors.New("numbers.range_step: step must be a positive number above zero")
}
return generateCheapRange(operands, step, iter)
}
x, err := builtins.BigIntOperand(operands[0].Value, 1)
if err != nil {
@@ -84,7 +91,18 @@ func canGenerateCheapRange(operands []*ast.Term) bool {
return true
}
func generateCheapRange(operands []*ast.Term, iter func(*ast.Term) error) error {
func canGenerateCheapRangeStep(operands []*ast.Term) bool {
if canGenerateCheapRange(operands) {
step, err := builtins.IntOperand(operands[1].Value, 3)
if err == nil && ast.HasInternedIntNumberTerm(step) {
return true
}
}
return false
}
func generateCheapRange(operands []*ast.Term, step int, iter func(*ast.Term) error) error {
x, err := builtins.IntOperand(operands[0].Value, 1)
if err != nil {
return err
@@ -95,28 +113,15 @@ func generateCheapRange(operands []*ast.Term, iter func(*ast.Term) error) error
return err
}
step := 1
if len(operands) > 2 {
stepOp, err := builtins.IntOperand(operands[2].Value, 3)
if err == nil {
step = stepOp
}
}
if step <= 0 {
return errors.New("numbers.range_step: step must be a positive number above zero")
}
terms := make([]*ast.Term, 0, y+1)
if x <= y {
for i := x; i <= y; i += step {
terms = append(terms, ast.InternedIntNumberTerm(i))
terms = append(terms, ast.InternedTerm(i))
}
} else {
for i := x; i >= y; i -= step {
terms = append(terms, ast.InternedIntNumberTerm(i))
terms = append(terms, ast.InternedTerm(i))
}
}
@@ -124,7 +129,6 @@ func generateCheapRange(operands []*ast.Term, iter func(*ast.Term) error) error
}
func generateRange(bctx BuiltinContext, x *big.Int, y *big.Int, step *big.Int, funcName string) (*ast.Term, error) {
cmp := x.Cmp(y)
comp := func(i *big.Int, y *big.Int) bool { return i.Cmp(y) <= 0 }
@@ -167,7 +171,7 @@ func builtinRandIntn(bctx BuiltinContext, operands []*ast.Term, iter func(*ast.T
}
if n == 0 {
return iter(ast.InternedIntNumberTerm(0))
return iter(ast.InternedTerm(0))
}
if n < 0 {
@@ -184,7 +188,7 @@ func builtinRandIntn(bctx BuiltinContext, operands []*ast.Term, iter func(*ast.T
if err != nil {
return err
}
result := ast.InternedIntNumberTerm(r.Intn(n))
result := ast.InternedTerm(r.Intn(n))
bctx.Cache.Put(key, result)
return iter(result)
+1 -1
View File
@@ -400,7 +400,7 @@ func (q *Query) PartialRun(ctx context.Context) (partials []ast.Body, support []
saveSet: newSaveSet(q.unknowns, b, q.instr),
saveStack: newSaveStack(),
saveSupport: newSaveSupport(),
saveNamespace: ast.InternedStringTerm(q.partialNamespace),
saveNamespace: ast.InternedTerm(q.partialNamespace),
skipSaveNamespace: q.skipSaveNamespace,
inliningControl: &inliningControl{
shallow: q.shallowInlining,
+7 -7
View File
@@ -25,15 +25,15 @@ func builtinRegexIsValid(_ BuiltinContext, operands []*ast.Term, iter func(*ast.
s, err := builtins.StringOperand(operands[0].Value, 1)
if err != nil {
return iter(ast.InternedBooleanTerm(false))
return iter(ast.InternedTerm(false))
}
_, err = regexp.Compile(string(s))
if err != nil {
return iter(ast.InternedBooleanTerm(false))
return iter(ast.InternedTerm(false))
}
return iter(ast.InternedBooleanTerm(true))
return iter(ast.InternedTerm(true))
}
func builtinRegexMatch(bctx BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
@@ -49,7 +49,7 @@ func builtinRegexMatch(bctx BuiltinContext, operands []*ast.Term, iter func(*ast
if err != nil {
return err
}
return iter(ast.InternedBooleanTerm(re.MatchString(string(s2))))
return iter(ast.InternedTerm(re.MatchString(string(s2))))
}
func builtinRegexMatchTemplate(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
@@ -79,7 +79,7 @@ func builtinRegexMatchTemplate(_ BuiltinContext, operands []*ast.Term, iter func
if err != nil {
return err
}
return iter(ast.InternedBooleanTerm(re.MatchString(string(match))))
return iter(ast.InternedTerm(re.MatchString(string(match))))
}
func builtinRegexSplit(bctx BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
@@ -177,7 +177,7 @@ func builtinGlobsMatch(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Te
if err != nil {
return err
}
return iter(ast.InternedBooleanTerm(ne))
return iter(ast.InternedTerm(ne))
}
func builtinRegexFind(bctx BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
@@ -264,7 +264,7 @@ func builtinRegexReplace(bctx BuiltinContext, operands []*ast.Term, iter func(*a
return iter(operands[0])
}
return iter(ast.InternedStringTerm(res))
return iter(ast.InternedTerm(res))
}
func init() {
+1 -1
View File
@@ -19,7 +19,7 @@ func builtinOPARuntime(bctx BuiltinContext, _ []*ast.Term, iter func(*ast.Term)
return iter(ast.InternedEmptyObject)
}
if bctx.Runtime.Get(ast.InternedStringTerm("config")) != nil {
if bctx.Runtime.Get(ast.InternedTerm("config")) != nil {
iface, err := ast.ValueToInterface(bctx.Runtime.Value, nothingResolver)
if err != nil {
return err
+3 -3
View File
@@ -34,13 +34,13 @@ func builtinSemVerCompare(_ BuiltinContext, operands []*ast.Term, iter func(*ast
result := versionA.Compare(*versionB)
return iter(ast.InternedIntNumberTerm(result))
return iter(ast.InternedTerm(result))
}
func builtinSemVerIsValid(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
versionString, err := builtins.StringOperand(operands[0].Value, 1)
if err != nil {
return iter(ast.InternedBooleanTerm(false))
return iter(ast.InternedTerm(false))
}
result := true
@@ -50,7 +50,7 @@ func builtinSemVerIsValid(_ BuiltinContext, operands []*ast.Term, iter func(*ast
result = false
}
return iter(ast.InternedBooleanTerm(result))
return iter(ast.InternedTerm(result))
}
func init() {
+121 -74
View File
@@ -51,7 +51,7 @@ func builtinAnyPrefixMatch(_ BuiltinContext, operands []*ast.Term, iter func(*as
return builtins.NewOperandTypeErr(2, b, "string", "set", "array")
}
return iter(ast.InternedBooleanTerm(anyStartsWithAny(strs, prefixes)))
return iter(ast.InternedTerm(anyStartsWithAny(strs, prefixes)))
}
func builtinAnySuffixMatch(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
@@ -91,7 +91,7 @@ func builtinAnySuffixMatch(_ BuiltinContext, operands []*ast.Term, iter func(*as
return builtins.NewOperandTypeErr(2, b, "string", "set", "array")
}
return iter(ast.InternedBooleanTerm(anyStartsWithAny(strsReversed, suffixesReversed)))
return iter(ast.InternedTerm(anyStartsWithAny(strsReversed, suffixesReversed)))
}
func anyStartsWithAny(strs []string, prefixes []string) bool {
@@ -148,63 +148,110 @@ func builtinFormatInt(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Ter
f := builtins.NumberToFloat(input)
i, _ := f.Int(nil)
return iter(ast.InternedStringTerm(fmt.Sprintf(format, i)))
return iter(ast.InternedTerm(fmt.Sprintf(format, i)))
}
func builtinConcat(b BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
func builtinConcat(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
join, err := builtins.StringOperand(operands[0].Value, 1)
if err != nil {
return err
}
var strs []string
switch b := operands[1].Value.(type) {
case *ast.Array:
var l int
for i := range b.Len() {
s, ok := b.Elem(i).Value.(ast.String)
if !ok {
return builtins.NewOperandElementErr(2, operands[1].Value, b.Elem(i).Value, "string")
}
l += len(string(s))
}
if b.Len() == 1 {
return iter(b.Elem(0))
}
strs = make([]string, 0, l)
for i := range b.Len() {
strs = append(strs, string(b.Elem(i).Value.(ast.String)))
}
case ast.Set:
var l int
terms := b.Slice()
for i := range terms {
s, ok := terms[i].Value.(ast.String)
if !ok {
return builtins.NewOperandElementErr(2, operands[1].Value, terms[i].Value, "string")
}
l += len(string(s))
}
if b.Len() == 1 {
return iter(b.Slice()[0])
}
strs = make([]string, 0, l)
for i := range b.Len() {
strs = append(strs, string(terms[i].Value.(ast.String)))
}
default:
return builtins.NewOperandTypeErr(2, operands[1].Value, "set", "array")
// fast path for empty or single string array/set, allocates no memory
if term, ok := zeroOrOneStringTerm(operands[1].Value); ok {
return iter(term)
}
return iter(ast.InternedStringTerm(strings.Join(strs, string(join))))
// NOTE(anderseknert):
// More or less Go's strings.Join implementation, but where we avoid
// creating an intermediate []string slice to pass to that function,
// as that's expensive (3.5x more space allocated). Instead we build
// the string directly using a strings.Builder to concatenate the string
// values from the array/set with the separator.
n := 0
switch b := operands[1].Value.(type) {
case *ast.Array:
l := b.Len()
for i := range l {
s, ok := b.Elem(i).Value.(ast.String)
if !ok {
return builtins.NewOperandElementErr(2, b, b.Elem(i).Value, "string")
}
n += len(s)
}
sep := string(join)
n += len(sep) * (l - 1)
var sb strings.Builder
sb.Grow(n)
sb.WriteString(string(b.Elem(0).Value.(ast.String)))
if sep == "" {
for i := 1; i < l; i++ {
sb.WriteString(string(b.Elem(i).Value.(ast.String)))
}
} else if len(sep) == 1 {
// when the separator is a single byte, sb.WriteByte is substantially faster
bsep := sep[0]
for i := 1; i < l; i++ {
sb.WriteByte(bsep)
sb.WriteString(string(b.Elem(i).Value.(ast.String)))
}
} else {
// for longer separators, there is no such difference between WriteString and Write
for i := 1; i < l; i++ {
sb.WriteString(sep)
sb.WriteString(string(b.Elem(i).Value.(ast.String)))
}
}
return iter(ast.InternedTerm(sb.String()))
case ast.Set:
for _, v := range b.Slice() {
s, ok := v.Value.(ast.String)
if !ok {
return builtins.NewOperandElementErr(2, b, v.Value, "string")
}
n += len(s)
}
sep := string(join)
l := b.Len()
n += len(sep) * (l - 1)
var sb strings.Builder
sb.Grow(n)
for i, v := range b.Slice() {
sb.WriteString(string(v.Value.(ast.String)))
if i < l-1 {
sb.WriteString(sep)
}
}
return iter(ast.InternedTerm(sb.String()))
}
return builtins.NewOperandTypeErr(2, operands[1].Value, "set", "array")
}
func zeroOrOneStringTerm(a ast.Value) (*ast.Term, bool) {
switch b := a.(type) {
case *ast.Array:
if b.Len() == 0 {
return ast.InternedEmptyString, true
}
if b.Len() == 1 {
e := b.Elem(0)
if _, ok := e.Value.(ast.String); ok {
return e, true
}
}
case ast.Set:
if b.Len() == 0 {
return ast.InternedEmptyString, true
}
if b.Len() == 1 {
e := b.Slice()[0]
if _, ok := e.Value.(ast.String); ok {
return e, true
}
}
}
return nil, false
}
func runesEqual(a, b []rune) bool {
@@ -237,7 +284,7 @@ func builtinIndexOf(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term)
// this is a false positive in the indexAlloc rule that thinks
// we're converting byte arrays to strings
//nolint:gocritic
return iter(ast.InternedIntNumberTerm(strings.Index(string(base), string(search))))
return iter(ast.InternedTerm(strings.Index(string(base), string(search))))
}
baseRunes := []rune(string(base))
@@ -247,14 +294,14 @@ func builtinIndexOf(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term)
for i, r := range baseRunes {
if len(baseRunes) >= i+searchLen {
if r == searchRunes[0] && runesEqual(baseRunes[i:i+searchLen], searchRunes) {
return iter(ast.InternedIntNumberTerm(i))
return iter(ast.InternedTerm(i))
}
} else {
break
}
}
return iter(ast.InternedIntNumberTerm(-1))
return iter(ast.InternedTerm(-1))
}
func builtinIndexOfN(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
@@ -279,7 +326,7 @@ func builtinIndexOfN(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term
for i, r := range baseRunes {
if len(baseRunes) >= i+searchLen {
if r == searchRunes[0] && runesEqual(baseRunes[i:i+searchLen], searchRunes) {
arr = append(arr, ast.InternedIntNumberTerm(i))
arr = append(arr, ast.InternedTerm(i))
}
} else {
break
@@ -323,7 +370,7 @@ func builtinSubstring(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Ter
}
if length < 0 {
return iter(ast.InternedStringTerm(sbase[startIndex:]))
return iter(ast.InternedTerm(sbase[startIndex:]))
}
if startIndex == 0 && length >= len(sbase) {
@@ -331,7 +378,7 @@ func builtinSubstring(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Ter
}
upto := min(len(sbase), startIndex+length)
return iter(ast.InternedStringTerm(sbase[startIndex:upto]))
return iter(ast.InternedTerm(sbase[startIndex:upto]))
}
if startIndex == 0 && length >= utf8.RuneCountInString(sbase) {
@@ -352,7 +399,7 @@ func builtinSubstring(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Ter
s = string(runes[startIndex:upto])
}
return iter(ast.InternedStringTerm(s))
return iter(ast.InternedTerm(s))
}
func isASCII(s string) bool {
@@ -375,7 +422,7 @@ func builtinContains(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term
return err
}
return iter(ast.InternedBooleanTerm(strings.Contains(string(s), string(substr))))
return iter(ast.InternedTerm(strings.Contains(string(s), string(substr))))
}
func builtinStringCount(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
@@ -393,7 +440,7 @@ func builtinStringCount(_ BuiltinContext, operands []*ast.Term, iter func(*ast.T
searchTerm := string(substr)
count := strings.Count(baseTerm, searchTerm)
return iter(ast.InternedIntNumberTerm(count))
return iter(ast.InternedTerm(count))
}
func builtinStartsWith(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
@@ -407,7 +454,7 @@ func builtinStartsWith(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Te
return err
}
return iter(ast.InternedBooleanTerm(strings.HasPrefix(string(s), string(prefix))))
return iter(ast.InternedTerm(strings.HasPrefix(string(s), string(prefix))))
}
func builtinEndsWith(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
@@ -421,7 +468,7 @@ func builtinEndsWith(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term
return err
}
return iter(ast.InternedBooleanTerm(strings.HasSuffix(string(s), string(suffix))))
return iter(ast.InternedTerm(strings.HasSuffix(string(s), string(suffix))))
}
func builtinLower(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
@@ -437,7 +484,7 @@ func builtinLower(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) e
return iter(operands[0])
}
return iter(ast.InternedStringTerm(low))
return iter(ast.InternedTerm(low))
}
func builtinUpper(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
@@ -453,7 +500,7 @@ func builtinUpper(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) e
return iter(operands[0])
}
return iter(ast.InternedStringTerm(upp))
return iter(ast.InternedTerm(upp))
}
func builtinSplit(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
@@ -475,7 +522,7 @@ func builtinSplit(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) e
arr := make([]*ast.Term, len(elems))
for i := range elems {
arr[i] = ast.InternedStringTerm(elems[i])
arr[i] = ast.InternedTerm(elems[i])
}
return iter(ast.ArrayTerm(arr...))
@@ -502,7 +549,7 @@ func builtinReplace(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term)
return iter(operands[0])
}
return iter(ast.InternedStringTerm(replaced))
return iter(ast.InternedTerm(replaced))
}
func builtinReplaceN(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
@@ -532,7 +579,7 @@ func builtinReplaceN(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term
oldnewArr = append(oldnewArr, string(keyVal), string(strVal))
}
return iter(ast.InternedStringTerm(strings.NewReplacer(oldnewArr...).Replace(string(s))))
return iter(ast.InternedTerm(strings.NewReplacer(oldnewArr...).Replace(string(s))))
}
func builtinTrim(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
@@ -551,7 +598,7 @@ func builtinTrim(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) er
return iter(operands[0])
}
return iter(ast.InternedStringTerm(strings.Trim(string(s), string(c))))
return iter(ast.InternedTerm(strings.Trim(string(s), string(c))))
}
func builtinTrimLeft(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
@@ -570,7 +617,7 @@ func builtinTrimLeft(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term
return iter(operands[0])
}
return iter(ast.InternedStringTerm(trimmed))
return iter(ast.InternedTerm(trimmed))
}
func builtinTrimPrefix(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
@@ -589,7 +636,7 @@ func builtinTrimPrefix(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Te
return iter(operands[0])
}
return iter(ast.InternedStringTerm(trimmed))
return iter(ast.InternedTerm(trimmed))
}
func builtinTrimRight(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
@@ -608,7 +655,7 @@ func builtinTrimRight(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Ter
return iter(operands[0])
}
return iter(ast.InternedStringTerm(trimmed))
return iter(ast.InternedTerm(trimmed))
}
func builtinTrimSuffix(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
@@ -627,7 +674,7 @@ func builtinTrimSuffix(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Te
return iter(operands[0])
}
return iter(ast.InternedStringTerm(trimmed))
return iter(ast.InternedTerm(trimmed))
}
func builtinTrimSpace(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
@@ -641,7 +688,7 @@ func builtinTrimSpace(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Ter
return iter(operands[0])
}
return iter(ast.InternedStringTerm(trimmed))
return iter(ast.InternedTerm(trimmed))
}
func builtinSprintf(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
@@ -689,7 +736,7 @@ func builtinSprintf(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term)
}
}
return iter(ast.InternedStringTerm(fmt.Sprintf(string(s), args...)))
return iter(ast.InternedTerm(fmt.Sprintf(string(s), args...)))
}
func builtinReverse(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
@@ -698,7 +745,7 @@ func builtinReverse(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term)
return err
}
return iter(ast.InternedStringTerm(reverseString(string(s))))
return iter(ast.InternedTerm(reverseString(string(s))))
}
func reverseString(str string) string {
+4 -4
View File
@@ -216,22 +216,22 @@ func builtinObjectSubset(_ BuiltinContext, operands []*ast.Term, iter func(*ast.
if ok, superObj, subObj := bothObjects(superTerm, subTerm); ok {
// Both operands are objects.
return iter(ast.InternedBooleanTerm(objectSubset(superObj, subObj)))
return iter(ast.InternedTerm(objectSubset(superObj, subObj)))
}
if ok, superSet, subSet := bothSets(superTerm, subTerm); ok {
// Both operands are sets.
return iter(ast.InternedBooleanTerm(setSubset(superSet, subSet)))
return iter(ast.InternedTerm(setSubset(superSet, subSet)))
}
if ok, superArray, subArray := bothArrays(superTerm, subTerm); ok {
// Both operands are sets.
return iter(ast.InternedBooleanTerm(arraySubset(superArray, subArray)))
return iter(ast.InternedTerm(arraySubset(superArray, subArray)))
}
if ok, superArray, subSet := arraySet(superTerm, subTerm); ok {
// Super operand is array and sub operand is set
return iter(ast.InternedBooleanTerm(arraySetSubset(superArray, subSet)))
return iter(ast.InternedTerm(arraySetSubset(superArray, subSet)))
}
return builtins.ErrOperand("both arguments object.subset must be of the same type or array and set")
+4 -4
View File
@@ -128,7 +128,7 @@ func builtinDate(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) er
}
year, month, day := t.Date()
return iter(ast.ArrayTerm(ast.InternedIntNumberTerm(year), ast.InternedIntNumberTerm(int(month)), ast.InternedIntNumberTerm(day)))
return iter(ast.ArrayTerm(ast.InternedTerm(year), ast.InternedTerm(int(month)), ast.InternedTerm(day)))
}
func builtinClock(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
@@ -137,7 +137,7 @@ func builtinClock(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) e
return err
}
hour, minute, second := t.Clock()
result := ast.NewArray(ast.InternedIntNumberTerm(hour), ast.InternedIntNumberTerm(minute), ast.InternedIntNumberTerm(second))
result := ast.NewArray(ast.InternedTerm(hour), ast.InternedTerm(minute), ast.InternedTerm(second))
return iter(ast.NewTerm(result))
}
@@ -238,8 +238,8 @@ func builtinDiff(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) er
}
// END REDISTRIBUTION FROM APACHE 2.0 LICENSED PROJECT
return iter(ast.ArrayTerm(ast.InternedIntNumberTerm(year), ast.InternedIntNumberTerm(month), ast.InternedIntNumberTerm(day),
ast.InternedIntNumberTerm(hour), ast.InternedIntNumberTerm(min), ast.InternedIntNumberTerm(sec)))
return iter(ast.ArrayTerm(ast.InternedTerm(year), ast.InternedTerm(month), ast.InternedTerm(day),
ast.InternedTerm(hour), ast.InternedTerm(min), ast.InternedTerm(sec)))
}
func tzTime(a ast.Value) (t time.Time, lay string, err error) {
+21 -21
View File
@@ -75,7 +75,7 @@ func builtinJWTDecode(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Ter
return fmt.Errorf("JWT payload had invalid encoding: %v", err)
}
if cty := token.decodedHeader.Get(ast.InternedStringTerm("cty")); cty != nil {
if cty := token.decodedHeader.Get(ast.InternedTerm("cty")); cty != nil {
ctyVal := string(cty.Value.(ast.String))
// It is possible for the contents of a token to be another
// token as a result of nested signing or encryption. To handle
@@ -128,7 +128,7 @@ func builtinJWTVerifyRS256(bctx BuiltinContext, operands []*ast.Term, iter func(
signature)
})
if err == nil {
return iter(ast.InternedBooleanTerm(result))
return iter(ast.InternedTerm(result))
}
return err
}
@@ -143,7 +143,7 @@ func builtinJWTVerifyRS384(bctx BuiltinContext, operands []*ast.Term, iter func(
signature)
})
if err == nil {
return iter(ast.InternedBooleanTerm(result))
return iter(ast.InternedTerm(result))
}
return err
}
@@ -158,7 +158,7 @@ func builtinJWTVerifyRS512(bctx BuiltinContext, operands []*ast.Term, iter func(
signature)
})
if err == nil {
return iter(ast.InternedBooleanTerm(result))
return iter(ast.InternedTerm(result))
}
return err
}
@@ -174,7 +174,7 @@ func builtinJWTVerifyPS256(bctx BuiltinContext, operands []*ast.Term, iter func(
nil)
})
if err == nil {
return iter(ast.InternedBooleanTerm(result))
return iter(ast.InternedTerm(result))
}
return err
}
@@ -190,7 +190,7 @@ func builtinJWTVerifyPS384(bctx BuiltinContext, operands []*ast.Term, iter func(
nil)
})
if err == nil {
return iter(ast.InternedBooleanTerm(result))
return iter(ast.InternedTerm(result))
}
return err
}
@@ -206,7 +206,7 @@ func builtinJWTVerifyPS512(bctx BuiltinContext, operands []*ast.Term, iter func(
nil)
})
if err == nil {
return iter(ast.InternedBooleanTerm(result))
return iter(ast.InternedTerm(result))
}
return err
}
@@ -226,7 +226,7 @@ func builtinJWTVerifyRSA(bctx BuiltinContext, jwt ast.Value, keyStr ast.Value, h
func builtinJWTVerifyES256(bctx BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
result, err := builtinJWTVerify(bctx, operands[0].Value, operands[1].Value, sha256.New, verifyES)
if err == nil {
return iter(ast.InternedBooleanTerm(result))
return iter(ast.InternedTerm(result))
}
return err
}
@@ -235,7 +235,7 @@ func builtinJWTVerifyES256(bctx BuiltinContext, operands []*ast.Term, iter func(
func builtinJWTVerifyES384(bctx BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
result, err := builtinJWTVerify(bctx, operands[0].Value, operands[1].Value, sha512.New384, verifyES)
if err == nil {
return iter(ast.InternedBooleanTerm(result))
return iter(ast.InternedTerm(result))
}
return err
}
@@ -244,7 +244,7 @@ func builtinJWTVerifyES384(bctx BuiltinContext, operands []*ast.Term, iter func(
func builtinJWTVerifyES512(bctx BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
result, err := builtinJWTVerify(bctx, operands[0].Value, operands[1].Value, sha512.New, verifyES)
if err == nil {
return iter(ast.InternedBooleanTerm(result))
return iter(ast.InternedTerm(result))
}
return err
}
@@ -439,7 +439,7 @@ func builtinJWTVerifyHS(bctx BuiltinContext, operands []*ast.Term, hashF func()
}
if found, _, _, valid := getTokenFromCache(bctx, jwt, astSecret); found {
return iter(ast.InternedBooleanTerm(valid))
return iter(ast.InternedTerm(valid))
}
// Decode the JSON Web Token
@@ -465,7 +465,7 @@ func builtinJWTVerifyHS(bctx BuiltinContext, operands []*ast.Term, hashF func()
putTokenInCache(bctx, jwt, astSecret, nil, nil, valid)
return iter(ast.InternedBooleanTerm(valid))
return iter(ast.InternedTerm(valid))
}
// -- Full JWT verification and decoding --
@@ -993,7 +993,7 @@ func builtinJWTDecodeVerify(bctx BuiltinContext, operands []*ast.Term, iter func
}
unverified := ast.ArrayTerm(
ast.InternedBooleanTerm(false),
ast.InternedTerm(false),
ast.InternedEmptyObject,
ast.InternedEmptyObject,
)
@@ -1010,8 +1010,8 @@ func builtinJWTDecodeVerify(bctx BuiltinContext, operands []*ast.Term, iter func
// FIXME: optimize
k, _ := b.Filter(ast.NewObject(
ast.Item(ast.InternedStringTerm("secret"), ast.InternedEmptyObject),
ast.Item(ast.InternedStringTerm("cert"), ast.InternedEmptyObject),
ast.Item(ast.InternedTerm("secret"), ast.InternedEmptyObject),
ast.Item(ast.InternedTerm("cert"), ast.InternedEmptyObject),
))
if found, th, tp, validSignature := getTokenFromCache(bctx, a, k); found {
@@ -1117,7 +1117,7 @@ func builtinJWTDecodeVerify(bctx BuiltinContext, operands []*ast.Term, iter func
// Check registered claim names against constraints or environment
// RFC7159 4.1.1 iss
if constraints.iss != "" {
if iss := payload.Get(ast.InternedStringTerm("iss")); iss != nil {
if iss := payload.Get(ast.InternedTerm("iss")); iss != nil {
issVal := string(iss.Value.(ast.String))
if constraints.iss != issVal {
return iter(unverified)
@@ -1127,7 +1127,7 @@ func builtinJWTDecodeVerify(bctx BuiltinContext, operands []*ast.Term, iter func
}
}
// RFC7159 4.1.3 aud
if aud := payload.Get(ast.InternedStringTerm("aud")); aud != nil {
if aud := payload.Get(ast.InternedTerm("aud")); aud != nil {
if !constraints.validAudience(aud.Value) {
return iter(unverified)
}
@@ -1137,7 +1137,7 @@ func builtinJWTDecodeVerify(bctx BuiltinContext, operands []*ast.Term, iter func
}
}
// RFC7159 4.1.4 exp
if exp := payload.Get(ast.InternedStringTerm("exp")); exp != nil {
if exp := payload.Get(ast.InternedTerm("exp")); exp != nil {
switch v := exp.Value.(type) {
case ast.Number:
// constraints.time is in nanoseconds but exp Value is in seconds
@@ -1150,7 +1150,7 @@ func builtinJWTDecodeVerify(bctx BuiltinContext, operands []*ast.Term, iter func
}
}
// RFC7159 4.1.5 nbf
if nbf := payload.Get(ast.InternedStringTerm("nbf")); nbf != nil {
if nbf := payload.Get(ast.InternedTerm("nbf")); nbf != nil {
switch v := nbf.Value.(type) {
case ast.Number:
// constraints.time is in nanoseconds but nbf Value is in seconds
@@ -1164,7 +1164,7 @@ func builtinJWTDecodeVerify(bctx BuiltinContext, operands []*ast.Term, iter func
}
verified := ast.ArrayTerm(
ast.InternedBooleanTerm(true),
ast.InternedTerm(true),
ast.NewTerm(header),
ast.NewTerm(payload),
)
@@ -1218,7 +1218,7 @@ func validateJWTHeader(h string) (ast.Object, error) {
// won't support it for now.
// This code checks which kind of JWT we are dealing with according to
// RFC 7516 Section 9: https://tools.ietf.org/html/rfc7516#section-9
if header.Get(ast.InternedStringTerm("enc")) != nil {
if header.Get(ast.InternedTerm("enc")) != nil {
return nil, errors.New("JWT is a JWE object, which is not supported")
}
+2 -2
View File
@@ -533,7 +533,7 @@ func builtinTrace(bctx BuiltinContext, operands []*ast.Term, iter func(*ast.Term
}
if !bctx.TraceEnabled {
return iter(ast.InternedBooleanTerm(true))
return iter(ast.InternedTerm(true))
}
evt := Event{
@@ -548,7 +548,7 @@ func builtinTrace(bctx BuiltinContext, operands []*ast.Term, iter func(*ast.Term
bctx.QueryTracers[i].TraceEvent(evt)
}
return iter(ast.InternedBooleanTerm(true))
return iter(ast.InternedTerm(true))
}
func rewrite(event *Event) *Event {
+14 -14
View File
@@ -11,63 +11,63 @@ import (
func builtinIsNumber(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
switch operands[0].Value.(type) {
case ast.Number:
return iter(ast.InternedBooleanTerm(true))
return iter(ast.InternedTerm(true))
default:
return iter(ast.InternedBooleanTerm(false))
return iter(ast.InternedTerm(false))
}
}
func builtinIsString(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
switch operands[0].Value.(type) {
case ast.String:
return iter(ast.InternedBooleanTerm(true))
return iter(ast.InternedTerm(true))
default:
return iter(ast.InternedBooleanTerm(false))
return iter(ast.InternedTerm(false))
}
}
func builtinIsBoolean(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
switch operands[0].Value.(type) {
case ast.Boolean:
return iter(ast.InternedBooleanTerm(true))
return iter(ast.InternedTerm(true))
default:
return iter(ast.InternedBooleanTerm(false))
return iter(ast.InternedTerm(false))
}
}
func builtinIsArray(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
switch operands[0].Value.(type) {
case *ast.Array:
return iter(ast.InternedBooleanTerm(true))
return iter(ast.InternedTerm(true))
default:
return iter(ast.InternedBooleanTerm(false))
return iter(ast.InternedTerm(false))
}
}
func builtinIsSet(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
switch operands[0].Value.(type) {
case ast.Set:
return iter(ast.InternedBooleanTerm(true))
return iter(ast.InternedTerm(true))
default:
return iter(ast.InternedBooleanTerm(false))
return iter(ast.InternedTerm(false))
}
}
func builtinIsObject(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
switch operands[0].Value.(type) {
case ast.Object:
return iter(ast.InternedBooleanTerm(true))
return iter(ast.InternedTerm(true))
default:
return iter(ast.InternedBooleanTerm(false))
return iter(ast.InternedTerm(false))
}
}
func builtinIsNull(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
switch operands[0].Value.(type) {
case ast.Null:
return iter(ast.InternedBooleanTerm(true))
return iter(ast.InternedTerm(true))
default:
return iter(ast.InternedBooleanTerm(false))
return iter(ast.InternedTerm(false))
}
}
+7 -7
View File
@@ -13,19 +13,19 @@ import (
func builtinTypeName(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
switch operands[0].Value.(type) {
case ast.Null:
return iter(ast.InternedStringTerm("null"))
return iter(ast.InternedTerm("null"))
case ast.Boolean:
return iter(ast.InternedStringTerm("boolean"))
return iter(ast.InternedTerm("boolean"))
case ast.Number:
return iter(ast.InternedStringTerm("number"))
return iter(ast.InternedTerm("number"))
case ast.String:
return iter(ast.InternedStringTerm("string"))
return iter(ast.InternedTerm("string"))
case *ast.Array:
return iter(ast.InternedStringTerm("array"))
return iter(ast.InternedTerm("array"))
case ast.Object:
return iter(ast.InternedStringTerm("object"))
return iter(ast.InternedTerm("object"))
case ast.Set:
return iter(ast.InternedStringTerm("set"))
return iter(ast.InternedTerm("set"))
}
return errors.New("illegal value")
+2 -2
View File
@@ -57,7 +57,7 @@ func walk(filter, path *ast.Array, input *ast.Term, iter func(*ast.Term) error)
switch v := input.Value.(type) {
case *ast.Array:
for i := range v.Len() {
if err := walk(filter, pathAppend(path, ast.InternedIntNumberTerm(i)), v.Elem(i), iter); err != nil {
if err := walk(filter, pathAppend(path, ast.InternedTerm(i)), v.Elem(i), iter); err != nil {
return err
}
}
@@ -89,7 +89,7 @@ func walkNoPath(input *ast.Term, iter func(*ast.Term) error) error {
}
inputArray := input.Value.(*ast.Array)
value := inputArray.Get(ast.InternedIntNumberTerm(1)).Value
value := inputArray.Get(ast.InternedTerm(1)).Value
switch v := value.(type) {
case ast.Object:
+1 -1
View File
@@ -10,7 +10,7 @@ import (
"runtime/debug"
)
var Version = "1.5.1"
var Version = "1.6.0"
// GoVersion is the version of Go this was built with
var GoVersion = runtime.Version()
+9
View File
@@ -164,6 +164,15 @@ func ErrorPathf(path ast.Path, message string, args ...interface{}) *Error {
}
func ErrorPosf(pos *ast.Position, message string, args ...interface{}) *Error {
if pos == nil {
return ErrorLocf(
"",
-1,
-1,
message,
args...,
)
}
return ErrorLocf(
pos.Src.Name,
pos.Line,
+1 -2
View File
@@ -1,7 +1,6 @@
package parser
import (
"fmt"
"strconv"
"github.com/vektah/gqlparser/v2/ast"
@@ -106,7 +105,7 @@ func (p *parser) next() lexer.Token {
// Increment the token count before reading the next token
p.tokenCount++
if p.maxTokenLimit != 0 && p.tokenCount > p.maxTokenLimit {
p.err = fmt.Errorf("exceeded token limit of %d", p.maxTokenLimit)
p.err = gqlerror.Errorf("exceeded token limit of %d", p.maxTokenLimit)
return p.prev
}
if p.peeked {
+2 -2
View File
@@ -1114,7 +1114,7 @@ github.com/onsi/gomega/matchers/support/goraph/edge
github.com/onsi/gomega/matchers/support/goraph/node
github.com/onsi/gomega/matchers/support/goraph/util
github.com/onsi/gomega/types
# github.com/open-policy-agent/opa v1.5.1
# github.com/open-policy-agent/opa v1.6.0
## explicit; go 1.23.8
github.com/open-policy-agent/opa/ast
github.com/open-policy-agent/opa/ast/json
@@ -1889,7 +1889,7 @@ github.com/unrolled/secure/cspbuilder
# github.com/urfave/cli/v2 v2.27.7
## explicit; go 1.18
github.com/urfave/cli/v2
# github.com/vektah/gqlparser/v2 v2.5.26
# github.com/vektah/gqlparser/v2 v2.5.28
## explicit; go 1.22
github.com/vektah/gqlparser/v2/ast
github.com/vektah/gqlparser/v2/gqlerror