diff --git a/constraint/go.mod b/constraint/go.mod index 602ad6961..19c06a74a 100644 --- a/constraint/go.mod +++ b/constraint/go.mod @@ -7,7 +7,7 @@ require ( github.com/golang/glog v1.2.5 github.com/google/go-cmp v0.7.0 github.com/onsi/gomega v1.43.1 - github.com/open-policy-agent/opa v1.20.2 + github.com/open-policy-agent/opa v1.21.0 github.com/spf13/cobra v1.10.2 github.com/spf13/pflag v1.0.10 go.uber.org/goleak v1.3.0 @@ -50,7 +50,7 @@ require ( github.com/go-openapi/swag/stringutils v0.28.0 // indirect github.com/go-openapi/swag/typeutils v0.28.0 // indirect github.com/go-openapi/swag/yamlutils v0.28.0 // indirect - github.com/gobwas/glob v0.2.3 // indirect + github.com/gobwas/glob v1.0.0 // indirect github.com/goccy/go-json v0.10.6 // indirect github.com/google/cel-go v0.29.0 // indirect github.com/google/gnostic-models v0.7.0 // indirect @@ -59,18 +59,18 @@ require ( github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/lestrrat-go/blackmagic v1.0.4 // indirect - github.com/lestrrat-go/dsig v1.3.0 // indirect + github.com/lestrrat-go/dsig v1.4.0 // indirect github.com/lestrrat-go/dsig-secp256k1 v1.0.0 // indirect github.com/lestrrat-go/httpcc v1.0.1 // indirect github.com/lestrrat-go/httprc/v3 v3.0.6 // indirect - github.com/lestrrat-go/jwx/v3 v3.2.0 // indirect + github.com/lestrrat-go/jwx/v3 v3.3.0 // indirect github.com/lestrrat-go/option/v2 v2.0.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/prometheus/client_golang v1.24.1 // indirect - github.com/prometheus/client_model v0.6.2 // indirect + github.com/prometheus/client_model v0.6.3 // indirect github.com/prometheus/common v0.70.1 // indirect github.com/prometheus/procfs v0.21.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20250401214520-65e299d6c5c9 // indirect @@ -78,7 +78,7 @@ require ( github.com/sirupsen/logrus v1.10.2 // indirect github.com/tchap/go-patricia/v2 v2.3.3 // indirect github.com/valyala/fastjson v1.6.10 // indirect - github.com/vektah/gqlparser/v2 v2.5.36 // indirect + github.com/vektah/gqlparser/v2 v2.5.37 // indirect github.com/x448/float16 v0.8.4 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect @@ -98,11 +98,11 @@ require ( golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93 // indirect golang.org/x/net v0.58.0 // indirect golang.org/x/oauth2 v0.36.0 // indirect - golang.org/x/sync v0.22.0 // indirect - golang.org/x/sys v0.47.0 // indirect - golang.org/x/term v0.45.0 // indirect - golang.org/x/text v0.41.0 // indirect - golang.org/x/time v0.15.0 // indirect + golang.org/x/sync v0.23.0 // indirect + golang.org/x/sys v0.48.0 // indirect + golang.org/x/term v0.46.0 // indirect + golang.org/x/text v0.42.0 // indirect + golang.org/x/time v0.16.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20260819154853-08b0e4226688 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20260819154853-08b0e4226688 // indirect google.golang.org/grpc v1.83.2 // indirect diff --git a/constraint/go.sum b/constraint/go.sum index 8d7aea65b..a140fe6e5 100644 --- a/constraint/go.sum +++ b/constraint/go.sum @@ -92,8 +92,8 @@ github.com/go-openapi/testify/v2 v2.6.0 h1:5PKH2HE7YJ/LuRPQGvSxBRlFXNQhSetBLlGAg github.com/go-openapi/testify/v2 v2.6.0/go.mod h1:SgsVHtfooshd0tublTtJ50FPKhujf47YRqauXXOUxfw= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= -github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= -github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/gobwas/glob v1.0.0 h1:p+FKbLEIsK1yZ39/OINwFvqNb5oyPY4H8xcy6uYu8dg= +github.com/gobwas/glob v1.0.0/go.mod h1:oWCdo522i2P1n/hMXGNWs7yoV4wy/ciZuUIbvKj5rkc= github.com/goccy/go-json v0.10.6 h1:p8HrPJzOakx/mn/bQtjgNjdTcN+/S6FcG2CTtQOrHVU= github.com/goccy/go-json v0.10.6/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= @@ -125,8 +125,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/klauspost/compress v1.19.1 h1:VsB4HPswih7mmZ8WleSFQ75c/Ui1M4trX5oAsJnhSlk= -github.com/klauspost/compress v1.19.1/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= +github.com/klauspost/compress v1.20.0 h1:a3C1ke2ohxFymNlb2HWAHjDeKCI90scRskErZkR0ezA= +github.com/klauspost/compress v1.20.0/go.mod h1:LUdAzn7YLVvxLpc7y3V1m40wESHTgc1422pwwBSKYuI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -135,16 +135,16 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0 github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/lestrrat-go/blackmagic v1.0.4 h1:IwQibdnf8l2KoO+qC3uT4OaTWsW7tuRQXy9TRN9QanA= github.com/lestrrat-go/blackmagic v1.0.4/go.mod h1:6AWFyKNNj0zEXQYfTMPfZrAXUWUfTIZ5ECEUEJaijtw= -github.com/lestrrat-go/dsig v1.3.0 h1:phjMOCXvYzhuIgn7Voe2rex8z166vGfxRxmqM25P9/Q= -github.com/lestrrat-go/dsig v1.3.0/go.mod h1:RD2eOaidyPvpc7IJQoO3Qq52RWdy8ZcJs8lrOnoa1Kc= +github.com/lestrrat-go/dsig v1.4.0 h1:g7LUjK8cT74A5DzBXJI5HzsJuLhoYN0Wzj4nuOMIrH8= +github.com/lestrrat-go/dsig v1.4.0/go.mod h1:I8Nddg/vN2cUl/h8N7SRRApLnNNeyZPIqLYpvpOtGGo= github.com/lestrrat-go/dsig-secp256k1 v1.0.0 h1:JpDe4Aybfl0soBvoVwjqDbp+9S1Y2OM7gcrVVMFPOzY= github.com/lestrrat-go/dsig-secp256k1 v1.0.0/go.mod h1:CxUgAhssb8FToqbL8NjSPoGQlnO4w3LG1P0qPWQm/NU= github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE= github.com/lestrrat-go/httpcc v1.0.1/go.mod h1:qiltp3Mt56+55GPVCbTdM9MlqhvzyuL6W/NMDA8vA5E= github.com/lestrrat-go/httprc/v3 v3.0.6 h1:4FpLQ18KK/ypPbVU3NLWJNRvH3kcYiqKqWfKGqNWxxI= github.com/lestrrat-go/httprc/v3 v3.0.6/go.mod h1:mSMtkZW92Z98M5YoNNztbRGxbXHql7tSitCvaxvo9l0= -github.com/lestrrat-go/jwx/v3 v3.2.0 h1:Jb3zBASTSZXz7gzzSAfYqxXF8KejvKC4xWoePLQqXCA= -github.com/lestrrat-go/jwx/v3 v3.2.0/go.mod h1:38vQ8iWKq3qRSbilbzvzdQPuywhowwuR03lhkYskyrw= +github.com/lestrrat-go/jwx/v3 v3.3.0 h1:OXcYvQOQ7cxWzeZ/Q9sYk8ABe/kCSI371WmuACiCT+4= +github.com/lestrrat-go/jwx/v3 v3.3.0/go.mod h1:eIJhDcKHBwcgxqv8RiIylV67TVl1wJp/265IAHY1Db8= github.com/lestrrat-go/option/v2 v2.0.0 h1:XxrcaJESE1fokHy3FpaQ/cXW8ZsIdWcdFzzLOcID3Ss= github.com/lestrrat-go/option/v2 v2.0.0/go.mod h1:oSySsmzMoR0iRzCDCaUfsCzxQHUEuhOViQObyy7S6Vg= github.com/miekg/dns v1.1.57 h1:Jzi7ApEIzwEPLHWRcafCN9LZSBbqQpxjt/wpgvg7wcM= @@ -161,15 +161,15 @@ github.com/onsi/ginkgo/v2 v2.27.4 h1:fcEcQW/A++6aZAZQNUmNjvA9PSOzefMJBerHJ4t8v8Y github.com/onsi/ginkgo/v2 v2.27.4/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo= github.com/onsi/gomega v1.43.1 h1:vGIPFuYrIO6/0Z09s0I0QQQgFchiX4+tb1re3MScJYo= github.com/onsi/gomega v1.43.1/go.mod h1:e/C2HwaZ1DhvjzXXuFhcR7hY7Sh9pl7MmoWKEjzwcdA= -github.com/open-policy-agent/opa v1.20.2 h1:dlX5VEGA5M62W8+X1nRPEaQIh/CMRn5FcD1mebpKWKg= -github.com/open-policy-agent/opa v1.20.2/go.mod h1:yYKTQAlkbefoXSYChT4ek8gc8WCtScL7L7OSZxFVe0s= +github.com/open-policy-agent/opa v1.21.0 h1:k/N0fieTkBPM0H7mIOrMd/xZPaMsxW70jIzIPeOBst4= +github.com/open-policy-agent/opa v1.21.0/go.mod h1:eJL6KUOIaW5YLnhJEA6sm3FOYRDJaHZvYT6geATbpPk= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v1.24.1 h1:JnJkREXzWxUdCuPFpIWZiPispT9xVV59uiuyR2bPlnU= github.com/prometheus/client_golang v1.24.1/go.mod h1:F+oSRECHg4sse5ucfYpYDeIv/hu68Zo0uoHKetWnzcE= -github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= -github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= +github.com/prometheus/client_model v0.6.3 h1:O0jaTVAYNxTHYInEPFJt5I3+sN8zqBtVMPTB1qyxiEo= +github.com/prometheus/client_model v0.6.3/go.mod h1:gpN5P9S7Rr6Yr92PiQ+Ixvhf6JZEkF1dnxsYL2aPBEM= github.com/prometheus/common v0.70.1 h1:1HvjP4D5oL3t8RsPlwxA9onvvStjtIHYE5XuuwOi/PY= github.com/prometheus/common v0.70.1/go.mod h1:VdFUQDMZK3VLkurFUVhia6uys/0suUp86TJz5qbJRhc= github.com/prometheus/procfs v0.21.1 h1:GljZCt+zSTS+NZq88cyQ1LjZ+RCHp3uVuabBWA5+OJI= @@ -201,8 +201,8 @@ github.com/tetratelabs/wazero v1.12.0 h1:DuWcpNu/FzgEXgGBDp8J1Spc+CWOvvtvVyjKlaZ github.com/tetratelabs/wazero v1.12.0/go.mod h1:LvKtzl2RqO4gyF27BiXU+nKAjcV8f38U+kP/q2vgxh0= github.com/valyala/fastjson v1.6.10 h1:/yjJg8jaVQdYR3arGxPE2X5z89xrlhS0eGXdv+ADTh4= github.com/valyala/fastjson v1.6.10/go.mod h1:e6FubmQouUNP73jtMLmcbxS6ydWIpOfhz34TSfO3JaE= -github.com/vektah/gqlparser/v2 v2.5.36 h1:CN9mKVHgMkc+XftdOWIhb4HEL8wKSYkFAqhf8booa7s= -github.com/vektah/gqlparser/v2 v2.5.36/go.mod h1:cAJ9qwVgPaUkWv6Gn8vn0mqOE0Ui5Pn56wNy5396XWo= +github.com/vektah/gqlparser/v2 v2.5.37 h1:jbb1Ilv+xBklV6653tKb4oVUupPNTLb5LmrnBKVI12Y= +github.com/vektah/gqlparser/v2 v2.5.37/go.mod h1:9O4Ox6Ngd3Y12bMD3w6i3CRQXh8W1oC1q0m6olCymDM= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= @@ -254,24 +254,24 @@ golang.org/x/crypto v0.55.0 h1:+KWHjbgOaAQ66dh/YlkZKHlz9ZUlq61AFirAR9ntP8M= golang.org/x/crypto v0.55.0/go.mod h1:uq0V9dE/fzQuJtbnL+2EhWOE63vo164FY8xqEnV9xis= golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93 h1:fQsdNF2N+/YewlRZiricy4P1iimyPKZ/xwniHj8Q2a0= golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93/go.mod h1:EPRbTFwzwjXj9NpYyyrvenVh9Y+GFeEvMNh7Xuz7xgU= -golang.org/x/mod v0.38.0 h1:MECBjubtXD7yj4HrhIUcywNaGeNVUdfVnxmPajOk4yk= -golang.org/x/mod v0.38.0/go.mod h1:V6Xz0pq8TQ3dGqVQ1FVHuelZpAL0uNhSkk9ogYP3c40= +golang.org/x/mod v0.41.0 h1:qJmnOUb4YB+FsEuM3HcWucdZASCPGhsX6uljO6pog0c= +golang.org/x/mod v0.41.0/go.mod h1:Ek9pY8RKWXwsWvd3rQiHYtMqkjSUV+s1Rj7j4H5Ur6o= golang.org/x/net v0.58.0 h1:ynWG7rqYi4ccpTEuPZ2QGWHktVEM9DMCj9yzDE0Q7To= golang.org/x/net v0.58.0/go.mod h1:YwCddHnFlT7eLQqVprV19OnhLGtc5xOKgE0RyqgfWAU= golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= -golang.org/x/sync v0.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek= -golang.org/x/sync v0.22.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= -golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs= -golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= -golang.org/x/term v0.45.0 h1:NwWyBmoJCbfTHpxrWoZ9C6/VxOf7ic219I8xZZFdrf0= -golang.org/x/term v0.45.0/go.mod h1:9aqxs0blBcrm/n0L9QW0aRVD+ktan8ssZromtqJC43w= -golang.org/x/text v0.41.0 h1:vz/seA0lnX87Othu2f/0L24RcgrXD9/YFTSuGjj3rH8= -golang.org/x/text v0.41.0/go.mod h1:jvf1O8ajNzZqhSrQBPbutR/EB83Cc0CFrezNQIwbb5M= -golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U= -golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno= -golang.org/x/tools v0.48.0 h1:3+hClM1aLL5mjMKm5ovokw9epgRXPuu2tILgismM6RE= -golang.org/x/tools v0.48.0/go.mod h1:08xX0orndb/F7jJxGDicx061tyd5pcMto75YMAXr6lk= +golang.org/x/sync v0.23.0 h1:KameEIfc1IkluZyXWLn39Wd4tURc6GbCiISGiZm2bQk= +golang.org/x/sync v0.23.0/go.mod h1:sUUOizhqBxiL6pEWpqNLUiaJn1ShEbZ6BBqskPbjZm0= +golang.org/x/sys v0.48.0 h1:bbX/i/6MgT9BVLM9RT1thmxL04yeTAhbEz4SyadbXoo= +golang.org/x/sys v0.48.0/go.mod h1:hNLxWAXmnKAxqDtdwIYC4bM9oQPEecfsnNMuSxOs3og= +golang.org/x/term v0.46.0 h1:3+OXuTbaKDgwk8jTi3aSLHRlmWqHEUDUtxnbFigO4YE= +golang.org/x/term v0.46.0/go.mod h1:+K02xbkittuwc0Am4abfA3Fc+XRGXkvBXNO88NCXPoc= +golang.org/x/text v0.42.0 h1:JbOZXgfeCPU9gacVtYliJqOhD+zhrEqK4LfdpmlUZqI= +golang.org/x/text v0.42.0/go.mod h1:ojzP1Z+2QtioaF8DTtO8K5q7JWVVYwZKenzujK0Zd0E= +golang.org/x/time v0.16.0 h1:vMb6ptszcQMkcwiRTAuNNU50gom6++Q/6gY2hDM6VDE= +golang.org/x/time v0.16.0/go.mod h1:rVKOqvZeKvrDKTQiAHJ7wmwP0RzleSphoEA9RcdLA0s= +golang.org/x/tools v0.49.0 h1:3NI7VXzL9+1WZD52Dx2ttoPwD5DWrFGpl9mFZDlmisI= +golang.org/x/tools v0.49.0/go.mod h1:SJNXV9DBKT0UbdttsQjbfJlAE/q+y36++zo3uL3N0Oo= gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= diff --git a/constraint/vendor/github.com/gobwas/glob/.gitignore b/constraint/vendor/github.com/gobwas/glob/.gitignore index b4ae623be..534b466c5 100644 --- a/constraint/vendor/github.com/gobwas/glob/.gitignore +++ b/constraint/vendor/github.com/gobwas/glob/.gitignore @@ -6,3 +6,5 @@ glob.iml *.dot *.png *.svg +patterns.txt +*.bench diff --git a/constraint/vendor/github.com/gobwas/glob/.travis.yml b/constraint/vendor/github.com/gobwas/glob/.travis.yml deleted file mode 100644 index e8a276826..000000000 --- a/constraint/vendor/github.com/gobwas/glob/.travis.yml +++ /dev/null @@ -1,9 +0,0 @@ -sudo: false - -language: go - -go: - - 1.5.3 - -script: - - go test -v ./... diff --git a/constraint/vendor/github.com/gobwas/glob/bench.sh b/constraint/vendor/github.com/gobwas/glob/bench.sh index 804cf22e6..8570697b8 100644 --- a/constraint/vendor/github.com/gobwas/glob/bench.sh +++ b/constraint/vendor/github.com/gobwas/glob/bench.sh @@ -1,26 +1,41 @@ -#! /bin/bash +#!/bin/bash +# +# Compares the benchmarks of the current branch against a git revision: +# +# ./bench.sh v0.2.3 # all the benchmarks +# ./bench.sh master 'Match' # the ones matching a -bench regexp +# +# The results are written to *.bench files in the current directory and +# compared with benchstat (go install golang.org/x/perf/cmd/benchstat@latest). -bench() { - filename="/tmp/$1-$2.bench" - if test -e "${filename}"; - then - echo "Already exists ${filename}" - else - backup=`git rev-parse --abbrev-ref HEAD` - git checkout $1 - echo -n "Creating ${filename}... " - go test ./... -run=NONE -bench=$2 > "${filename}" -benchmem - echo "OK" - git checkout ${backup} - sleep 5 - fi -} +set -eu + +prev=$1 +what=${2:-.} +curr=$(git rev-parse --abbrev-ref HEAD) +rnd=$(head -c4 "$out" + echo "OK" + git checkout -q "$curr" + sleep 5 +} -bench ${to} $2 -bench ${current} $2 +bench "$prev" +bench "$curr" -benchcmp $3 "/tmp/${to}-$2.bench" "/tmp/${current}-$2.bench" +benchstat "$(file "$prev")" "$(file "$curr")" diff --git a/constraint/vendor/github.com/gobwas/glob/compiler/compiler.go b/constraint/vendor/github.com/gobwas/glob/compiler/compiler.go deleted file mode 100644 index 02e7de80a..000000000 --- a/constraint/vendor/github.com/gobwas/glob/compiler/compiler.go +++ /dev/null @@ -1,525 +0,0 @@ -package compiler - -// TODO use constructor with all matchers, and to their structs private -// TODO glue multiple Text nodes (like after QuoteMeta) - -import ( - "fmt" - "reflect" - - "github.com/gobwas/glob/match" - "github.com/gobwas/glob/syntax/ast" - "github.com/gobwas/glob/util/runes" -) - -func optimizeMatcher(matcher match.Matcher) match.Matcher { - switch m := matcher.(type) { - - case match.Any: - if len(m.Separators) == 0 { - return match.NewSuper() - } - - case match.AnyOf: - if len(m.Matchers) == 1 { - return m.Matchers[0] - } - - return m - - case match.List: - if m.Not == false && len(m.List) == 1 { - return match.NewText(string(m.List)) - } - - return m - - case match.BTree: - m.Left = optimizeMatcher(m.Left) - m.Right = optimizeMatcher(m.Right) - - r, ok := m.Value.(match.Text) - if !ok { - return m - } - - var ( - leftNil = m.Left == nil - rightNil = m.Right == nil - ) - if leftNil && rightNil { - return match.NewText(r.Str) - } - - _, leftSuper := m.Left.(match.Super) - lp, leftPrefix := m.Left.(match.Prefix) - la, leftAny := m.Left.(match.Any) - - _, rightSuper := m.Right.(match.Super) - rs, rightSuffix := m.Right.(match.Suffix) - ra, rightAny := m.Right.(match.Any) - - switch { - case leftSuper && rightSuper: - return match.NewContains(r.Str, false) - - case leftSuper && rightNil: - return match.NewSuffix(r.Str) - - case rightSuper && leftNil: - return match.NewPrefix(r.Str) - - case leftNil && rightSuffix: - return match.NewPrefixSuffix(r.Str, rs.Suffix) - - case rightNil && leftPrefix: - return match.NewPrefixSuffix(lp.Prefix, r.Str) - - case rightNil && leftAny: - return match.NewSuffixAny(r.Str, la.Separators) - - case leftNil && rightAny: - return match.NewPrefixAny(r.Str, ra.Separators) - } - - return m - } - - return matcher -} - -func compileMatchers(matchers []match.Matcher) (match.Matcher, error) { - if len(matchers) == 0 { - return nil, fmt.Errorf("compile error: need at least one matcher") - } - if len(matchers) == 1 { - return matchers[0], nil - } - if m := glueMatchers(matchers); m != nil { - return m, nil - } - - idx := -1 - maxLen := -1 - var val match.Matcher - for i, matcher := range matchers { - if l := matcher.Len(); l != -1 && l >= maxLen { - maxLen = l - idx = i - val = matcher - } - } - - if val == nil { // not found matcher with static length - r, err := compileMatchers(matchers[1:]) - if err != nil { - return nil, err - } - return match.NewBTree(matchers[0], nil, r), nil - } - - left := matchers[:idx] - var right []match.Matcher - if len(matchers) > idx+1 { - right = matchers[idx+1:] - } - - var l, r match.Matcher - var err error - if len(left) > 0 { - l, err = compileMatchers(left) - if err != nil { - return nil, err - } - } - - if len(right) > 0 { - r, err = compileMatchers(right) - if err != nil { - return nil, err - } - } - - return match.NewBTree(val, l, r), nil -} - -func glueMatchers(matchers []match.Matcher) match.Matcher { - if m := glueMatchersAsEvery(matchers); m != nil { - return m - } - if m := glueMatchersAsRow(matchers); m != nil { - return m - } - return nil -} - -func glueMatchersAsRow(matchers []match.Matcher) match.Matcher { - if len(matchers) <= 1 { - return nil - } - - var ( - c []match.Matcher - l int - ) - for _, matcher := range matchers { - if ml := matcher.Len(); ml == -1 { - return nil - } else { - c = append(c, matcher) - l += ml - } - } - return match.NewRow(l, c...) -} - -func glueMatchersAsEvery(matchers []match.Matcher) match.Matcher { - if len(matchers) <= 1 { - return nil - } - - var ( - hasAny bool - hasSuper bool - hasSingle bool - min int - separator []rune - ) - - for i, matcher := range matchers { - var sep []rune - - switch m := matcher.(type) { - case match.Super: - sep = []rune{} - hasSuper = true - - case match.Any: - sep = m.Separators - hasAny = true - - case match.Single: - sep = m.Separators - hasSingle = true - min++ - - case match.List: - if !m.Not { - return nil - } - sep = m.List - hasSingle = true - min++ - - default: - return nil - } - - // initialize - if i == 0 { - separator = sep - } - - if runes.Equal(sep, separator) { - continue - } - - return nil - } - - if hasSuper && !hasAny && !hasSingle { - return match.NewSuper() - } - - if hasAny && !hasSuper && !hasSingle { - return match.NewAny(separator) - } - - if (hasAny || hasSuper) && min > 0 && len(separator) == 0 { - return match.NewMin(min) - } - - every := match.NewEveryOf() - - if min > 0 { - every.Add(match.NewMin(min)) - - if !hasAny && !hasSuper { - every.Add(match.NewMax(min)) - } - } - - if len(separator) > 0 { - every.Add(match.NewContains(string(separator), true)) - } - - return every -} - -func minimizeMatchers(matchers []match.Matcher) []match.Matcher { - var done match.Matcher - var left, right, count int - - for l := 0; l < len(matchers); l++ { - for r := len(matchers); r > l; r-- { - if glued := glueMatchers(matchers[l:r]); glued != nil { - var swap bool - - if done == nil { - swap = true - } else { - cl, gl := done.Len(), glued.Len() - swap = cl > -1 && gl > -1 && gl > cl - swap = swap || count < r-l - } - - if swap { - done = glued - left = l - right = r - count = r - l - } - } - } - } - - if done == nil { - return matchers - } - - next := append(append([]match.Matcher{}, matchers[:left]...), done) - if right < len(matchers) { - next = append(next, matchers[right:]...) - } - - if len(next) == len(matchers) { - return next - } - - return minimizeMatchers(next) -} - -// minimizeAnyOf tries to apply some heuristics to minimize number of nodes in given tree -func minimizeTree(tree *ast.Node) *ast.Node { - switch tree.Kind { - case ast.KindAnyOf: - return minimizeTreeAnyOf(tree) - default: - return nil - } -} - -// minimizeAnyOf tries to find common children of given node of AnyOf pattern -// it searches for common children from left and from right -// if any common children are found – then it returns new optimized ast tree -// else it returns nil -func minimizeTreeAnyOf(tree *ast.Node) *ast.Node { - if !areOfSameKind(tree.Children, ast.KindPattern) { - return nil - } - - commonLeft, commonRight := commonChildren(tree.Children) - commonLeftCount, commonRightCount := len(commonLeft), len(commonRight) - if commonLeftCount == 0 && commonRightCount == 0 { // there are no common parts - return nil - } - - var result []*ast.Node - if commonLeftCount > 0 { - result = append(result, ast.NewNode(ast.KindPattern, nil, commonLeft...)) - } - - var anyOf []*ast.Node - for _, child := range tree.Children { - reuse := child.Children[commonLeftCount : len(child.Children)-commonRightCount] - var node *ast.Node - if len(reuse) == 0 { - // this pattern is completely reduced by commonLeft and commonRight patterns - // so it become nothing - node = ast.NewNode(ast.KindNothing, nil) - } else { - node = ast.NewNode(ast.KindPattern, nil, reuse...) - } - anyOf = appendIfUnique(anyOf, node) - } - switch { - case len(anyOf) == 1 && anyOf[0].Kind != ast.KindNothing: - result = append(result, anyOf[0]) - case len(anyOf) > 1: - result = append(result, ast.NewNode(ast.KindAnyOf, nil, anyOf...)) - } - - if commonRightCount > 0 { - result = append(result, ast.NewNode(ast.KindPattern, nil, commonRight...)) - } - - return ast.NewNode(ast.KindPattern, nil, result...) -} - -func commonChildren(nodes []*ast.Node) (commonLeft, commonRight []*ast.Node) { - if len(nodes) <= 1 { - return - } - - // find node that has least number of children - idx := leastChildren(nodes) - if idx == -1 { - return - } - tree := nodes[idx] - treeLength := len(tree.Children) - - // allocate max able size for rightCommon slice - // to get ability insert elements in reverse order (from end to start) - // without sorting - commonRight = make([]*ast.Node, treeLength) - lastRight := treeLength // will use this to get results as commonRight[lastRight:] - - var ( - breakLeft bool - breakRight bool - commonTotal int - ) - for i, j := 0, treeLength-1; commonTotal < treeLength && j >= 0 && !(breakLeft && breakRight); i, j = i+1, j-1 { - treeLeft := tree.Children[i] - treeRight := tree.Children[j] - - for k := 0; k < len(nodes) && !(breakLeft && breakRight); k++ { - // skip least children node - if k == idx { - continue - } - - restLeft := nodes[k].Children[i] - restRight := nodes[k].Children[j+len(nodes[k].Children)-treeLength] - - breakLeft = breakLeft || !treeLeft.Equal(restLeft) - - // disable searching for right common parts, if left part is already overlapping - breakRight = breakRight || (!breakLeft && j <= i) - breakRight = breakRight || !treeRight.Equal(restRight) - } - - if !breakLeft { - commonTotal++ - commonLeft = append(commonLeft, treeLeft) - } - if !breakRight { - commonTotal++ - lastRight = j - commonRight[j] = treeRight - } - } - - commonRight = commonRight[lastRight:] - - return -} - -func appendIfUnique(target []*ast.Node, val *ast.Node) []*ast.Node { - for _, n := range target { - if reflect.DeepEqual(n, val) { - return target - } - } - return append(target, val) -} - -func areOfSameKind(nodes []*ast.Node, kind ast.Kind) bool { - for _, n := range nodes { - if n.Kind != kind { - return false - } - } - return true -} - -func leastChildren(nodes []*ast.Node) int { - min := -1 - idx := -1 - for i, n := range nodes { - if idx == -1 || (len(n.Children) < min) { - min = len(n.Children) - idx = i - } - } - return idx -} - -func compileTreeChildren(tree *ast.Node, sep []rune) ([]match.Matcher, error) { - var matchers []match.Matcher - for _, desc := range tree.Children { - m, err := compile(desc, sep) - if err != nil { - return nil, err - } - matchers = append(matchers, optimizeMatcher(m)) - } - return matchers, nil -} - -func compile(tree *ast.Node, sep []rune) (m match.Matcher, err error) { - switch tree.Kind { - case ast.KindAnyOf: - // todo this could be faster on pattern_alternatives_combine_lite (see glob_test.go) - if n := minimizeTree(tree); n != nil { - return compile(n, sep) - } - matchers, err := compileTreeChildren(tree, sep) - if err != nil { - return nil, err - } - return match.NewAnyOf(matchers...), nil - - case ast.KindPattern: - if len(tree.Children) == 0 { - return match.NewNothing(), nil - } - matchers, err := compileTreeChildren(tree, sep) - if err != nil { - return nil, err - } - m, err = compileMatchers(minimizeMatchers(matchers)) - if err != nil { - return nil, err - } - - case ast.KindAny: - m = match.NewAny(sep) - - case ast.KindSuper: - m = match.NewSuper() - - case ast.KindSingle: - m = match.NewSingle(sep) - - case ast.KindNothing: - m = match.NewNothing() - - case ast.KindList: - l := tree.Value.(ast.List) - m = match.NewList([]rune(l.Chars), l.Not) - - case ast.KindRange: - r := tree.Value.(ast.Range) - m = match.NewRange(r.Lo, r.Hi, r.Not) - - case ast.KindText: - t := tree.Value.(ast.Text) - m = match.NewText(t.Text) - - default: - return nil, fmt.Errorf("could not compile tree: unknown node type") - } - - return optimizeMatcher(m), nil -} - -func Compile(tree *ast.Node, sep []rune) (match.Matcher, error) { - m, err := compile(tree, sep) - if err != nil { - return nil, err - } - - return m, nil -} diff --git a/constraint/vendor/github.com/gobwas/glob/glob.go b/constraint/vendor/github.com/gobwas/glob/glob.go index 2afde343a..fb3e47554 100644 --- a/constraint/vendor/github.com/gobwas/glob/glob.go +++ b/constraint/vendor/github.com/gobwas/glob/glob.go @@ -1,80 +1,158 @@ package glob import ( - "github.com/gobwas/glob/compiler" + "fmt" + + "github.com/gobwas/glob/internal/debug" "github.com/gobwas/glob/syntax" ) -// Glob represents compiled glob pattern. -type Glob interface { - Match(string) bool +// SyntaxError is returned by [Compile] when the given pattern can not be +// parsed. Offset points at the place in the pattern the error was detected +// at, so the tooling can do things like: +// +// {a,b +// ----^ unclosed `{` +type SyntaxError struct { + // Offset is a byte offset in the pattern. + Offset int + // Reason describes the error. + Reason string } -// Compile creates Glob for given pattern and strings (if any present after pattern) as separators. -// The pattern syntax is: +func (s *SyntaxError) Error() string { + return fmt.Sprintf("glob: syntax error at %d: %s", s.Offset, s.Reason) +} + +// Pattern represents a compiled glob pattern. // -// pattern: -// { term } +// A pattern is compiled into a tree of matchers: // -// term: -// `*` matches any sequence of non-separator characters -// `**` matches any sequence of characters -// `?` matches any single non-separator character -// `[` [ `!` ] { character-range } `]` -// character class (must be non-empty) -// `{` pattern-list `}` -// pattern alternatives -// c matches character c (c != `*`, `**`, `?`, `\`, `[`, `{`, `}`) -// `\` c matches character c +// `a` => "a" +// `a*` => ["a"·*] +// `{a*,b}` => {["a"·*]|"b"} // -// character-range: -// c matches character c (c != `\\`, `-`, `]`) -// `\` c matches character c -// lo `-` hi matches character c for lo <= c <= hi +// Matching is a backtracking walk over that tree; see [Pattern.Match]. +type Pattern struct { + // str is the pattern text the Pattern was compiled from; see + // [Pattern.String]. + str string + + // sep are the separators the Pattern was compiled with; see + // [Pattern.Separators]. + sep []rune + + // m is the root of the matcher tree; see [matcher]. + m matcher + + // state tells whether matching m needs the backtracking state, that + // is, whether it may save checkpoints; see [needsState]. A pattern + // without them is matched with a plain call chain. + state bool + + // The match preconditions: every matching string is at least minLen + // bytes and ends with suffix. They fail the obvious mismatches in O(1) + // instead of a backtracking walk -- e.g. `a*a*a*b` requires the + // trailing `b`, no matter how the stars go. + // + // A precondition pays off only when it catches a mismatch earlier than + // the walk would, which is why: + // + // - there is no required prefix: the walk is left-to-right, so a + // leading literal is the first thing checked anyway, while a bad + // suffix or length is discovered last, after the whole + // backtracking exploration; + // + // - they are computed for the stateful patterns only: a stateless + // pattern is a plain call chain whose matchers perform these very + // checks themselves (e.g. suffixMatcher is a HasSuffix), so the + // precondition would only duplicate them. + minLen int + suffix string +} + +// String returns the source text used to compile the pattern, the same way +// [regexp.Regexp.String] does. // -// pattern-list: -// pattern { `,` pattern } -// comma-separated (without spaces) patterns +// Note that separators are not part of String: they are given to Compile +// alongside the pattern text. +func (p *Pattern) String() string { + return p.str +} + +// Separators returns the separators the pattern was compiled with, in the +// order they were given to Compile; nil when there are none. // -func Compile(pattern string, separators ...rune) (Glob, error) { - ast, err := syntax.Parse(pattern) - if err != nil { - return nil, err - } +// The returned slice is the very one given to Compile, sharing its backing +// array: it is not copied on the way in or out. Matching does not use it. +func (p *Pattern) Separators() []rune { + return p.sep +} - matcher, err := compiler.Compile(ast, separators) - if err != nil { - return nil, err +func init() { + // The matcher tree is unexported; hand its rendering to the in-module + // tooling (cmd/globtest -v) without widening the public API. + debug.Tree = func(p any) string { + return p.(*Pattern).m.String() } +} - return matcher, nil +// Compile compiles the glob pattern. The separators, if given, are the +// characters `*` and `?` do not match (`**` does); they can not be changed +// after the compilation, see [Pattern.Separators]. A malformed pattern is +// reported with a [*SyntaxError]. +// +// The pattern syntax is: +// +// pattern: +// { term } +// +// term: +// `*` matches any sequence of non-separator characters +// `**` matches any sequence of characters +// `?` matches any single non-separator character +// `[` [ `!` ] class `]` +// character class; `!` negates it +// `{` pattern-list `}` +// pattern alternatives +// c matches character c (c != `*`, `**`, `?`, `\`, `[`, `{`, `}`) +// `\` c matches character c +// +// class: +// lo `-` hi matches character c for lo <= c <= hi +// { c } matches any of the listed characters (c != `\`, `]`; +// `\` c matches c, `-` is literal here); must be non-empty +// +// pattern-list: +// pattern { `,` pattern } +// comma-separated (without spaces) patterns +func Compile(pattern string, separators ...rune) (*Pattern, error) { + return compile(pattern, separators) } -// MustCompile is the same as Compile, except that if Compile returns error, this will panic -func MustCompile(pattern string, separators ...rune) Glob { +// MustCompile is the same as Compile, except that if Compile returns error, +// this will panic. +func MustCompile(pattern string, separators ...rune) *Pattern { g, err := Compile(pattern, separators...) if err != nil { panic(err) } - return g } -// QuoteMeta returns a string that quotes all glob pattern meta characters -// inside the argument text; For example, QuoteMeta(`{foo*}`) returns `\[foo\*\]`. +// QuoteMeta returns a copy of the s having all glob meta characters escaped. func QuoteMeta(s string) string { + // 2 is a pessimistic way of allocating an extra byte per each byte in s. b := make([]byte, 2*len(s)) - - // a byte loop is correct because all meta characters are ASCII j := 0 + // A byte loop is correct here because all meta characters are ASCII. for i := 0; i < len(s); i++ { - if syntax.Special(s[i]) { + if syntax.IsSpecial(s[i]) { b[j] = '\\' j++ } b[j] = s[i] j++ } - return string(b[0:j]) } diff --git a/constraint/vendor/github.com/gobwas/glob/internal/debug/debug_disabled.go b/constraint/vendor/github.com/gobwas/glob/internal/debug/debug_disabled.go new file mode 100644 index 000000000..1dcc50d44 --- /dev/null +++ b/constraint/vendor/github.com/gobwas/glob/internal/debug/debug_disabled.go @@ -0,0 +1,8 @@ +//go:build !globdebug +// +build !globdebug + +package debug + +const Enabled = false + +func Printf(f string, args ...any) {} diff --git a/constraint/vendor/github.com/gobwas/glob/internal/debug/debug_enabled.go b/constraint/vendor/github.com/gobwas/glob/internal/debug/debug_enabled.go new file mode 100644 index 000000000..26aeebd61 --- /dev/null +++ b/constraint/vendor/github.com/gobwas/glob/internal/debug/debug_enabled.go @@ -0,0 +1,14 @@ +//go:build globdebug +// +build globdebug + +package debug + +import ( + "fmt" +) + +const Enabled = true + +func Printf(f string, args ...any) { + fmt.Printf(f, args...) +} diff --git a/constraint/vendor/github.com/gobwas/glob/internal/debug/tree.go b/constraint/vendor/github.com/gobwas/glob/internal/debug/tree.go new file mode 100644 index 000000000..c716a141e --- /dev/null +++ b/constraint/vendor/github.com/gobwas/glob/internal/debug/tree.go @@ -0,0 +1,8 @@ +package debug + +// Tree renders the matcher tree of a compiled *glob.Pattern. +// +// It is set by package glob at init time: the pattern internals are +// unexported, and this keeps them so while letting the in-module tooling +// (cmd/globtest -v) print them. The format is not stable. +var Tree func(pattern any) string diff --git a/constraint/vendor/github.com/gobwas/glob/match.go b/constraint/vendor/github.com/gobwas/glob/match.go new file mode 100644 index 000000000..2b8425706 --- /dev/null +++ b/constraint/vendor/github.com/gobwas/glob/match.go @@ -0,0 +1,788 @@ +package glob + +import ( + "fmt" + "slices" + "strconv" + "strings" + "sync" + "unicode/utf8" + "unsafe" + + "github.com/gobwas/glob/internal/debug" +) + +// Match reports whether s matches the pattern. +func (p *Pattern) Match(s string) bool { + var x matchContext + if p.state { + if len(s) < p.minLen || !strings.HasSuffix(s, p.suffix) { + return false + } + state := acquireState() + defer releaseState(state) + x.state = state + } + for { + n, match := p.m.Match(x, s[x.offset:]) + // Note: debug.Enabled is a build-tag constant; when it is false the + // whole block (including the argument evaluation) is compiled away. + if debug.Enabled && x.state != nil { + debug.Printf("stack: %s\n", formatStack(x.state.stack)) + debug.Printf("stars: %s\n", formatStack(x.state.stars)) + } + if match && n == len(s[x.offset:]) { + if debug.Enabled { + debug.Printf("match!\n") + } + return true + } + if x.state == nil { + // The pattern never saves checkpoints (see [needsState]): + // nothing to backtrack to. + return false + } + var ( + c checkpoint + k checkpointKind + ) + switch { + case len(x.state.stars) > 0: + if debug.Enabled { + debug.Printf("has star\n") + } + c = popLast(&x.state.stars) + k = checkpointStars + + case len(x.state.stack) > 0: + if debug.Enabled { + debug.Printf("has stack\n") + } + c = popLast(&x.state.stack) + k = checkpointStack + + default: + if debug.Enabled { + debug.Printf("no match\n") + } + return false + } + x.offset = c.offset + x.kind = k + x.frame = frame{ + path: c.path, + depth: 0, + } + } +} + +// matcher is a node of the tree a pattern compiles into. +// +// Match matches the beginning of s and reports how many bytes it consumed; +// the caller goes on with the rest. A matcher may consume nothing and still +// match: a void does, and so does a non-terminal star -- it stores its +// restart points instead and lets the walk continue, to be resumed from one +// of them on a mismatch later; see [Pattern.Match]. The context tells where +// in the input and in the tree the matcher is; see [matchContext]. +// +// String renders the node for the debug output and cmd/globtest -v; the +// notation is described at [Pattern]. +type matcher interface { + Match(matchContext, string) (n int, matched bool) + String() string +} + +// frame tells where in the matcher tree the walk currently is: the path from +// the root down to the current node, and the depth of the node. +// +// A checkpoint stores the frame's path; resuming it re-enters the tree from +// the root and follows the path back to the very node that saved it (an +// alternative to try, or a star to restart) -- see [Pattern.Match], +// [multiMatcher.Match] and [altMatcher.Match]. +// +// For `{a*b,c}y`, compiled into [{["a"·*·"b"]|"c"}·"y"], the frame at each +// node the walk visits is: +// +// node path depth +// [{["a"·*·"b"]|"c"}·"y"] [] 0 the root +// {["a"·*·"b"]|"c"} [0]* 1 +// ["a"·*·"b"] [0 0]* 2 +// "a" [0 0 0]* 3 +// * [0 0 1] 3 +// "b" [0 0 2] 3 +// "c" [0 1] 2 reached only by resuming the +// checkpoint the alt saved +// "y" [1] 1 +// +// * the zeros are virtual: turning to child #0 records nothing, so the +// path actually stored is [] -- see path below. +type frame struct { + // path addresses the current node: path[d] is the index of the child taken + // at depth d, that is, in the multiMatcher or altMatcher d levels below + // the root. + // + // For `{a*b,c}y`, compiled into [{["a"·*·"b"]|"c"}·"y"]: + // + // [0 1] the "c" alternative -- what the alt checkpoints when it + // enters ["a"·*·"b"], to be tried on a mismatch + // + // [0 0 1] the star: child #1 of ["a"·*·"b"], which is alternative #0 + // of the alt, which is child #0 of the root sequence -- what + // the star's restart points carry + // + // It is recorded lazily: an index is stored only when the walk turns to a + // child other than #0 (see [matchContext.branch]), so the path may be + // shorter than the current depth -- the missing trailing entries are + // implicitly zero, and [frame.index] reads them as such. In the example + // above, at "a" the path is still empty, not [0 0 0]: the alt, alternative + // #0 and "a" were all entered as child #0. + path []int + + // depth is the depth of the current node (the one [frame.path] leads to): + // 0 at the root, 1 at its children, and so on; [matchContext.next] + // increments it on every descent. It is also where the node's own entry in + // path lives: path[depth] is the child to take next -- [frame.index] reads + // it, [matchContext.branch] writes it. + // + // It is not len(path): the path is recorded lazily, so it may fall short + // of the depth, and, when resuming a checkpoint, it is the whole path of + // the checkpoint, reaching beyond the depth all the way down to the node + // to resume at. + // + // To say it the other way, depth is what len(path) would be were the path + // always recorded in full -- the virtual zeros included -- and cut at the + // current node: the length of the node's full address in the tree. + // + // For `{a*b,c}y`, compiled into [{["a"·*·"b"]|"c"}·"y"], the nodes at + // each depth are: + // + // 0 [{["a"·*·"b"]|"c"}·"y"] the root sequence + // 1 {["a"·*·"b"]|"c"}, "y" its children + // 2 ["a"·*·"b"], "c" the alternatives + // 3 "a", *, "b" the children of ["a"·*·"b"] + depth int +} + +// index returns the index of the child to take at the current node: the one +// the path leads to when resuming a checkpoint, #0 otherwise. +func (v frame) index() int { + if v.depth >= len(v.path) { + return 0 + } + return v.path[v.depth] +} + +// checkpoint is a place to resume the walk from on a mismatch. +type checkpoint struct { + // offset is the position in the input to resume at. + offset int + + // path leads to the node that saved the checkpoint; see [frame]. + // + // Unlike a live frame's, it is always at full length -- the virtual zeros + // written out -- so len(path) is the depth of that node, and a checkpoint + // needs no depth of its own: resuming starts at the root and tells it has + // arrived by comparing the walk's depth against len(path); see + // [matchContext.branch], [matchContext.storeStar] and [altMatcher.Match]. + path []int +} + +// checkpointKind tells which pile a checkpoint was taken from during the +// backtracking in [Pattern.Match]. +type checkpointKind int + +const ( + // checkpointStack is an alternative checkpoint saved by altMatcher. + checkpointStack checkpointKind = iota + // checkpointStars is a star restart point saved by starMatcher. + checkpointStars +) + +// matchContext is what a matcher is called with: where in the input and in +// the tree it is, plus the backtracking state shared by the whole walk. It +// is passed by value, so a matcher's changes to it are seen by its +// descendants only. +type matchContext struct { + // offset is the position in the whole input the current node matches from. + // The matchers see only the remainder of the input, so it is what a + // checkpoint records to resume at the same place; see [checkpoint]. + offset int + + // frame is where in the matcher tree the current node is; see [frame]. + frame frame + + // state holds the checkpoint piles and the path arena shared by the + // whole walk. + state *matchState + + // kind tells which pile the checkpoint being resumed was taken from. + // See [altMatcher.Match] for its use. + kind checkpointKind + + // starsFloor is the number of star restart points that existed when + // the walk entered the current alternative. The entries below it were + // born outside of the alternative and must not be discarded by the + // stars inside it; see [matchContext.storeStar]. + starsFloor int +} + +// push saves an alternative checkpoint at the current offset for the node f +// leads to; see [altMatcher.Match]. +func (x matchContext) push(f frame) { + x.state.stack = append(x.state.stack, checkpoint{ + offset: x.offset, + path: f.path, + }) + if debug.Enabled { + debug.Printf( + "checkpoint offset=%d path=%v\n", + x.offset, f.path, + ) + } +} + +// storeStar saves a restart point for the current star at offset bytes +// further in the input; reset tells whether the star may discard the pending +// restart points first, see below. +func (x matchContext) storeStar(offset int, reset bool) { + path := x.frame.path + if d := x.frame.depth; len(path) < d { + // The walk records an index in path only when it turns to a child + // other than the first one; levels entered at child #0 are implicit. + // Store the path at its full length (the missing entries are always + // zeros) so that the alts above can tell this checkpoint from their + // own. See [altMatcher.Match]. + p := x.state.allocPath(d) + copy(p, path) + path = p + } + if reset { + // This star can extend over anything the pending restart points could + // reach -- they are redundant, discard them. See + // research.swtch.com/glob. + // + // However, only the restart points born inside the current alternative + // may be discarded. An outer star, when resumed, re-enters the + // enclosing alt and may pick another alternative -- something this + // star, locked inside its own alternative, can not absorb. See the + // `*{*0,}` test: the outer star must survive the inner one to reach + // the empty alternative. + x.state.stars = x.state.stars[:x.starsFloor] + } + x.state.stars = append(x.state.stars, checkpoint{ + offset: x.offset + offset, + path: path, + }) + if debug.Enabled { + debug.Printf( + "star offset=%d path=%v reset=%t\n", + x.offset+offset, path, reset, + ) + } +} + +// next returns the context for a child of the current node, matching offset +// bytes further in the input: one level deeper in the tree. +func (x matchContext) next(offset int) matchContext { + x.offset = x.offset + offset + x.frame.depth += 1 + return x +} + +// branch returns a copy of the current frame with its path turned to child i +// at the current level, discarding the deeper levels. The new path is +// allocated from the state's arena. +func (x matchContext) branch(i int) frame { + f := x.frame + path := x.state.allocPath(f.depth + 1) + copy(path, f.path) + path[f.depth] = i + f.path = path + return f +} + +// matchState holds the backtracking state of a single [Pattern.Match] call. +// The states are pooled globally: the buffers keep their grown capacity +// between the matches, so a steady-state Match does not allocate them. +type matchState struct { + // stars are the star restart points and stack the alternative + // checkpoints, both LIFO. On a mismatch the walk resumes from the most + // recent restart point, if any, before the most recent alternative; see + // [Pattern.Match]. + stars []checkpoint + stack []checkpoint + + // arena is the buffer the checkpoint paths are allocated from; see + // [matchState.allocPath]. It is bulk-freed when the match ends, which + // spares the per-path lifetime reasoning: a path may be shared between + // the current frame and several checkpoints. + arena []int +} + +// allocPath returns a zeroed []int of length n allocated from the state's +// arena. When the arena runs out of capacity, a fresh chunk is started; the +// paths allocated from the previous chunks stay valid, since the chunks are +// kept alive by the paths referencing them. +func (st *matchState) allocPath(n int) []int { + if cap(st.arena)-len(st.arena) < n { + st.arena = make([]int, 0, max(2*cap(st.arena), n, 32)) + } + p := st.arena[len(st.arena) : len(st.arena)+n : len(st.arena)+n] + st.arena = st.arena[:len(st.arena)+n] + clear(p) + return p +} + +var statePool sync.Pool // Pool[*matchState] + +// acquireState takes a state from the pool, or makes a new one. +func acquireState() *matchState { + if st, _ := statePool.Get().(*matchState); st != nil { + return st + } + return &matchState{} +} + +// releaseState empties the state and puts it back to the pool. +func releaseState(st *matchState) { + resetCheckpoints(&st.stars) + resetCheckpoints(&st.stack) + // The arena holds no references; keep the (largest) chunk as is. + st.arena = st.arena[:0] + statePool.Put(st) +} + +// resetCheckpoints empties s keeping its capacity. The whole backing array +// is zeroed (not only the live part) to drop the references to the +// checkpoint paths popped during the match. +func resetCheckpoints(s *[]checkpoint) { + full := (*s)[:cap(*s)] + clear(full) + *s = full[:0] +} + +// multiMatcher is a sequence, ["a"·*·"b"]: it matches its children one +// after another, each on the input the previous ones left. +type multiMatcher []matcher + +func (ms multiMatcher) String() string { + var sb strings.Builder + sb.WriteByte('[') + for i, m := range ms { + if i > 0 { + sb.WriteString("·") + } + sb.WriteString(m.String()) + } + sb.WriteByte(']') + return sb.String() +} + +func (ms multiMatcher) Match(x matchContext, s string) (n int, ok bool) { + for i := x.frame.index(); i < len(ms); i++ { + if i != x.frame.index() && x.state != nil { + // The path is recorded for the checkpoints the descendants may + // save; in a stateless walk (see [needsState]) there are none + // and nobody would ever read it. + x.frame = x.branch(i) + } + child := x.next(n) + k, ok := ms[i].Match(child, s[n:]) + if debug.Enabled { + debug.Printf( + "[%T@%p] #%d match %#q against %[5]T(%[5]s) at path=%v depth=%d => %d %t\n", + ms, unsafe.SliceData(ms), i, s[n:], ms[i], + child.frame.path, child.frame.depth, k, ok, + ) + } + if !ok { + return 0, false + } + n += k + } + return n, true +} + +// altMatcher is a group of alternatives, {"a"|"b"}: it matches the one the +// walk is at (the first one when entered anew), having saved a checkpoint +// for the next one to be tried on a mismatch later. +type altMatcher []matcher + +func (ms altMatcher) String() string { + var sb strings.Builder + sb.WriteByte('{') + for i, m := range ms { + if i > 0 { + sb.WriteString("|") + } + sb.WriteString(m.String()) + } + sb.WriteByte('}') + return sb.String() +} + +func (ms altMatcher) Match(x matchContext, s string) (int, bool) { + i := x.frame.index() + // Save a checkpoint for the next alternative to consider it in case of + // a mismatch later (if any). This must be done only when: + // + // - the alt is entered for the first time (the resume path ends above + // this level, or there is none); + // + // - the resume path ends exactly at this level with an alternative + // checkpoint -- its job is "try alternative #i", so the one for the + // next alternative must be saved now. Note that a star restart point + // may end at this level too (a star being a direct child of the alt, + // as in `{*,b}`) -- it must not trigger a save. + // + // Otherwise the walk is merely passing through this alt on its way to + // resume a deeper checkpoint -- the one for the next alternative was + // already saved when the alt was entered for the first time, and saving + // it again on every star restart would blow the stack up exponentially. + // See the "alternatives" tests. + if next := i + 1; next < len(ms) { + d := len(x.frame.path) + if x.frame.depth >= d || (x.frame.depth == d-1 && x.kind == checkpointStack) { + x.push(x.branch(next)) + } + } + // The stars below this level may only discard the restart points born + // inside the same alternative; see [matchContext.storeStar]. + x.starsFloor = len(x.state.stars) + child := x.next(0) + n, match := ms[i].Match(child, s) + if debug.Enabled { + debug.Printf( + "[%T@%p] #%d match %#q against %[5]T(%[5]s) at path=%v depth=%d => %d %t\n", + ms, unsafe.SliceData(ms), i, s, ms[i], + child.frame.path, child.frame.depth, n, match, + ) + } + return n, match +} + +// textMatcher is a literal, "abc". +type textMatcher struct { + Text string +} + +func (m *textMatcher) String() string { + return strconv.Quote(m.Text) +} + +func (m *textMatcher) Match(_ matchContext, s string) (int, bool) { + if strings.HasPrefix(s, m.Text) { + return len(m.Text), true + } + return 0, false +} + +// charMatcher is a `?`: any single character but a separator. +type charMatcher struct { + Sep []rune +} + +func (m *charMatcher) String() string { + var sb strings.Builder + sb.WriteByte('?') + if len(m.Sep) > 0 { + sb.WriteByte('(') + formatRunes(&sb, m.Sep) + sb.WriteByte(')') + } + return sb.String() +} + +func (m *charMatcher) Match(_ matchContext, s string) (int, bool) { + if len(s) == 0 { + return 0, false + } + r, n := utf8.DecodeRuneInString(s) + if slices.Contains(m.Sep, r) { + return 0, false + } + return n, true +} + +// starMatcher is a `*` or a `**`: any sequence of characters, but for the +// separators in the former case. +type starMatcher struct { + // Sep are the separators the star may not extend over; empty for `**`. + Sep []rune + // SepStr is Sep as a string, for the byte-wise scans below. + SepStr string + + // Next is the literal the matcher right after this star begins with + // (when it is a textMatcher), set by [annotateStars]. A restart point + // at a position where the literal does not occur is a guaranteed + // mismatch, so the star jumps between its occurrences instead of + // retrying at every rune. + Next string + // Terminal is set by [annotateStars] when nothing follows this star + // anywhere in the pattern: the star then consumes everything in its + // reach at once, and no restart point can change the outcome. + Terminal bool +} + +// reach returns the length of the prefix of s the star may extend over: +// everything up to the nearest separator. +func (m *starMatcher) reach(s string) int { + if m.SepStr == "" { + return len(s) + } + if e := strings.IndexAny(s, m.SepStr); e >= 0 { + return e + } + return len(s) +} + +// storeSkip stores the restart point at the next occurrence of the m.Next +// literal instead of the next rune. +func (m *starMatcher) storeSkip(x matchContext, s string) { + reach := m.reach(s) + // Look for the occurrences starting within the star's reach; the + // literal itself may extend past it (it may contain the separators). + // Note that a valid UTF-8 literal can not match at a mid-rune + // position, so the one-byte skip below is rune-safe. + end := min(reach+len(m.Next), len(s)) + j := strings.Index(s[1:end], m.Next) + if j < 0 || 1+j > reach { + return + } + x.storeStar(1+j, len(m.Sep) == 0) +} + +func (m *starMatcher) String() string { + var sb strings.Builder + sb.WriteByte('*') + if len(m.Sep) > 0 { + sb.WriteByte('(') + formatRunes(&sb, m.Sep) + sb.WriteByte(')') + } + return sb.String() +} + +func (m *starMatcher) Match(x matchContext, s string) (int, bool) { + if m.Terminal { + // Nothing follows this star in the pattern: either it consumes + // the whole remainder within its reach, or the match fails. + return m.reach(s), true + } + if len(s) == 0 { + return 0, true + } + if m.Next != "" { + m.storeSkip(x, s) + return 0, true + } + r, n := utf8.DecodeRuneInString(s) + if !slices.Contains(m.Sep, r) { + // The star may extend over the rune: save the restart point past + // it. A separator-free star (`**`) can extend over anything the + // pending restart points could reach, so it may discard them; see + // [matchContext.storeStar]. + x.storeStar(n, len(m.Sep) == 0) + } + return 0, true +} + +// runeRangeMatcher is a character range class, `[a-z]` or `[!a-z]`. +type runeRangeMatcher struct { + Lo rune + Hi rune + Not bool +} + +func (m *runeRangeMatcher) String() string { + var sb strings.Builder + if m.Not { + sb.WriteByte('!') + } + sb.WriteByte('[') + sb.WriteRune(m.Lo) + sb.WriteByte('-') + sb.WriteRune(m.Hi) + sb.WriteByte(']') + return sb.String() +} + +func (m *runeRangeMatcher) Match(_ matchContext, s string) (int, bool) { + // Note that an invalid byte decodes as U+FFFD, and is matched as such, + // the same way regexp does; only the empty input is a mismatch. + r, n := utf8.DecodeRuneInString(s) + if n == 0 { + return 0, false + } + ok := m.Lo <= r && r <= m.Hi + if ok != m.Not { + return n, true + } + return 0, false +} + +// runeSetMatcher is a character set class, `[abc]` or `[!abc]`. +type runeSetMatcher struct { + Set map[rune]struct{} + Not bool +} + +// formatRunes writes rs, sorted and comma-separated, to sb. +func formatRunes(sb *strings.Builder, rs []rune) { + rs = slices.Clone(rs) // Not to reorder the caller's, e.g. a matcher's Sep. + slices.Sort(rs) + for i, r := range rs { + if i > 0 { + sb.WriteByte(',') + } + sb.WriteRune(r) + } +} + +func (m *runeSetMatcher) String() string { + rs := make([]rune, 0, len(m.Set)) + for r := range m.Set { + rs = append(rs, r) + } + var sb strings.Builder + if m.Not { + sb.WriteByte('!') + } + sb.WriteByte('[') + formatRunes(&sb, rs) + sb.WriteByte(']') + return sb.String() +} + +func (m *runeSetMatcher) Match(_ matchContext, s string) (int, bool) { + // See the note in runeRangeMatcher.Match. + r, n := utf8.DecodeRuneInString(s) + if n == 0 { + return 0, false + } + if _, has := m.Set[r]; has != m.Not { + return n, true + } + return 0, false +} + +// voidMatcher matches the empty string: an empty alternative, `{a,}`. In a +// sequence it is dropped by [normalizeSequence]. +type voidMatcher struct{} + +func (*voidMatcher) String() string { + return "void" +} + +func (*voidMatcher) Match(matchContext, string) (int, bool) { + return 0, true +} + +// The shaped matchers below are the compile-time rewrites of the common +// terminal sub-sequences; see [specialize]. Nothing may follow them in the +// pattern, so each one either consumes the whole remainder of the input or +// fails -- deterministically, storing no checkpoints. + +// prefixMatcher is a terminal `abc*`. +type prefixMatcher struct { + Text string + Sep string +} + +func (m *prefixMatcher) String() string { + return "prefix(" + strconv.Quote(m.Text) + ")" +} + +func (m *prefixMatcher) Match(_ matchContext, s string) (int, bool) { + if strings.HasPrefix(s, m.Text) && noSep(s[len(m.Text):], m.Sep) { + return len(s), true + } + return 0, false +} + +// suffixMatcher is a terminal `*abc`. +type suffixMatcher struct { + Text string + Sep string +} + +func (m *suffixMatcher) String() string { + return "suffix(" + strconv.Quote(m.Text) + ")" +} + +func (m *suffixMatcher) Match(_ matchContext, s string) (int, bool) { + if strings.HasSuffix(s, m.Text) && noSep(s[:len(s)-len(m.Text)], m.Sep) { + return len(s), true + } + return 0, false +} + +// prefixSuffixMatcher is a terminal `abc*def`. +type prefixSuffixMatcher struct { + Prefix string + Suffix string + Sep string +} + +func (m *prefixSuffixMatcher) String() string { + return "prefix_suffix(" + strconv.Quote(m.Prefix) + "," + strconv.Quote(m.Suffix) + ")" +} + +func (m *prefixSuffixMatcher) Match(_ matchContext, s string) (int, bool) { + // The length check keeps the prefix and the suffix from overlapping: + // `a*ant` must not match `ant`. + if len(s) >= len(m.Prefix)+len(m.Suffix) && + strings.HasPrefix(s, m.Prefix) && + strings.HasSuffix(s, m.Suffix) && + noSep(s[len(m.Prefix):len(s)-len(m.Suffix)], m.Sep) { + return len(s), true + } + return 0, false +} + +// containsMatcher is a terminal `*abc*` with the separator-free stars. +type containsMatcher struct { + Text string +} + +func (m *containsMatcher) String() string { + return "contains(" + strconv.Quote(m.Text) + ")" +} + +func (m *containsMatcher) Match(_ matchContext, s string) (int, bool) { + if strings.Contains(s, m.Text) { + return len(s), true + } + return 0, false +} + +// noSep reports whether s contains none of the separators. +func noSep(s, sep string) bool { + return sep == "" || !strings.ContainsAny(s, sep) +} + +// formatCheckpoint renders c as path@offset for the debug output. +func formatCheckpoint(c checkpoint) string { + return fmt.Sprintf("%v@%d", c.path, c.offset) +} + +// formatStack renders the checkpoint pile s for the debug output, the most +// recent one last. +func formatStack(s []checkpoint) string { + var sb strings.Builder + for i, c := range s { + if i > 0 { + sb.WriteString(" -> ") + } + sb.WriteString(formatCheckpoint(c)) + } + return sb.String() +} + +// popLast panics if s is empty. +func popLast[T any, E ~[]T](s *E) T { + n := len(*s) + r := (*s)[n-1] + *s = (*s)[:n-1] + return r +} diff --git a/constraint/vendor/github.com/gobwas/glob/match/any.go b/constraint/vendor/github.com/gobwas/glob/match/any.go deleted file mode 100644 index 514a9a5c4..000000000 --- a/constraint/vendor/github.com/gobwas/glob/match/any.go +++ /dev/null @@ -1,45 +0,0 @@ -package match - -import ( - "fmt" - "github.com/gobwas/glob/util/strings" -) - -type Any struct { - Separators []rune -} - -func NewAny(s []rune) Any { - return Any{s} -} - -func (self Any) Match(s string) bool { - return strings.IndexAnyRunes(s, self.Separators) == -1 -} - -func (self Any) Index(s string) (int, []int) { - found := strings.IndexAnyRunes(s, self.Separators) - switch found { - case -1: - case 0: - return 0, segments0 - default: - s = s[:found] - } - - segments := acquireSegments(len(s)) - for i := range s { - segments = append(segments, i) - } - segments = append(segments, len(s)) - - return 0, segments -} - -func (self Any) Len() int { - return lenNo -} - -func (self Any) String() string { - return fmt.Sprintf("", string(self.Separators)) -} diff --git a/constraint/vendor/github.com/gobwas/glob/match/any_of.go b/constraint/vendor/github.com/gobwas/glob/match/any_of.go deleted file mode 100644 index 8e65356cd..000000000 --- a/constraint/vendor/github.com/gobwas/glob/match/any_of.go +++ /dev/null @@ -1,82 +0,0 @@ -package match - -import "fmt" - -type AnyOf struct { - Matchers Matchers -} - -func NewAnyOf(m ...Matcher) AnyOf { - return AnyOf{Matchers(m)} -} - -func (self *AnyOf) Add(m Matcher) error { - self.Matchers = append(self.Matchers, m) - return nil -} - -func (self AnyOf) Match(s string) bool { - for _, m := range self.Matchers { - if m.Match(s) { - return true - } - } - - return false -} - -func (self AnyOf) Index(s string) (int, []int) { - index := -1 - - segments := acquireSegments(len(s)) - for _, m := range self.Matchers { - idx, seg := m.Index(s) - if idx == -1 { - continue - } - - if index == -1 || idx < index { - index = idx - segments = append(segments[:0], seg...) - continue - } - - if idx > index { - continue - } - - // here idx == index - segments = appendMerge(segments, seg) - } - - if index == -1 { - releaseSegments(segments) - return -1, nil - } - - return index, segments -} - -func (self AnyOf) Len() (l int) { - l = -1 - for _, m := range self.Matchers { - ml := m.Len() - switch { - case l == -1: - l = ml - continue - - case ml == -1: - return -1 - - case l != ml: - return -1 - } - } - - return -} - -func (self AnyOf) String() string { - return fmt.Sprintf("", self.Matchers) -} diff --git a/constraint/vendor/github.com/gobwas/glob/match/btree.go b/constraint/vendor/github.com/gobwas/glob/match/btree.go deleted file mode 100644 index a8130e93e..000000000 --- a/constraint/vendor/github.com/gobwas/glob/match/btree.go +++ /dev/null @@ -1,146 +0,0 @@ -package match - -import ( - "fmt" - "unicode/utf8" -) - -type BTree struct { - Value Matcher - Left Matcher - Right Matcher - ValueLengthRunes int - LeftLengthRunes int - RightLengthRunes int - LengthRunes int -} - -func NewBTree(Value, Left, Right Matcher) (tree BTree) { - tree.Value = Value - tree.Left = Left - tree.Right = Right - - lenOk := true - if tree.ValueLengthRunes = Value.Len(); tree.ValueLengthRunes == -1 { - lenOk = false - } - - if Left != nil { - if tree.LeftLengthRunes = Left.Len(); tree.LeftLengthRunes == -1 { - lenOk = false - } - } - - if Right != nil { - if tree.RightLengthRunes = Right.Len(); tree.RightLengthRunes == -1 { - lenOk = false - } - } - - if lenOk { - tree.LengthRunes = tree.LeftLengthRunes + tree.ValueLengthRunes + tree.RightLengthRunes - } else { - tree.LengthRunes = -1 - } - - return tree -} - -func (self BTree) Len() int { - return self.LengthRunes -} - -// todo? -func (self BTree) Index(s string) (int, []int) { - return -1, nil -} - -func (self BTree) Match(s string) bool { - inputLen := len(s) - - // self.Length, self.RLen and self.LLen are values meaning the length of runes for each part - // here we manipulating byte length for better optimizations - // but these checks still works, cause minLen of 1-rune string is 1 byte. - if self.LengthRunes != -1 && self.LengthRunes > inputLen { - return false - } - - // try to cut unnecessary parts - // by knowledge of length of right and left part - var offset, limit int - if self.LeftLengthRunes >= 0 { - offset = self.LeftLengthRunes - } - if self.RightLengthRunes >= 0 { - limit = inputLen - self.RightLengthRunes - } else { - limit = inputLen - } - - for offset < limit { - // search for matching part in substring - index, segments := self.Value.Index(s[offset:limit]) - if index == -1 { - releaseSegments(segments) - return false - } - - l := s[:offset+index] - var left bool - if self.Left != nil { - left = self.Left.Match(l) - } else { - left = l == "" - } - - if left { - for i := len(segments) - 1; i >= 0; i-- { - length := segments[i] - - var right bool - var r string - // if there is no string for the right branch - if inputLen <= offset+index+length { - r = "" - } else { - r = s[offset+index+length:] - } - - if self.Right != nil { - right = self.Right.Match(r) - } else { - right = r == "" - } - - if right { - releaseSegments(segments) - return true - } - } - } - - _, step := utf8.DecodeRuneInString(s[offset+index:]) - offset += index + step - - releaseSegments(segments) - } - - return false -} - -func (self BTree) String() string { - const n string = "" - var l, r string - if self.Left == nil { - l = n - } else { - l = self.Left.String() - } - if self.Right == nil { - r = n - } else { - r = self.Right.String() - } - - return fmt.Sprintf("%s]>", l, self.Value, r) -} diff --git a/constraint/vendor/github.com/gobwas/glob/match/contains.go b/constraint/vendor/github.com/gobwas/glob/match/contains.go deleted file mode 100644 index 0998e95b0..000000000 --- a/constraint/vendor/github.com/gobwas/glob/match/contains.go +++ /dev/null @@ -1,58 +0,0 @@ -package match - -import ( - "fmt" - "strings" -) - -type Contains struct { - Needle string - Not bool -} - -func NewContains(needle string, not bool) Contains { - return Contains{needle, not} -} - -func (self Contains) Match(s string) bool { - return strings.Contains(s, self.Needle) != self.Not -} - -func (self Contains) Index(s string) (int, []int) { - var offset int - - idx := strings.Index(s, self.Needle) - - if !self.Not { - if idx == -1 { - return -1, nil - } - - offset = idx + len(self.Needle) - if len(s) <= offset { - return 0, []int{offset} - } - s = s[offset:] - } else if idx != -1 { - s = s[:idx] - } - - segments := acquireSegments(len(s) + 1) - for i := range s { - segments = append(segments, offset+i) - } - - return 0, append(segments, offset+len(s)) -} - -func (self Contains) Len() int { - return lenNo -} - -func (self Contains) String() string { - var not string - if self.Not { - not = "!" - } - return fmt.Sprintf("", not, self.Needle) -} diff --git a/constraint/vendor/github.com/gobwas/glob/match/every_of.go b/constraint/vendor/github.com/gobwas/glob/match/every_of.go deleted file mode 100644 index 7c968ee36..000000000 --- a/constraint/vendor/github.com/gobwas/glob/match/every_of.go +++ /dev/null @@ -1,99 +0,0 @@ -package match - -import ( - "fmt" -) - -type EveryOf struct { - Matchers Matchers -} - -func NewEveryOf(m ...Matcher) EveryOf { - return EveryOf{Matchers(m)} -} - -func (self *EveryOf) Add(m Matcher) error { - self.Matchers = append(self.Matchers, m) - return nil -} - -func (self EveryOf) Len() (l int) { - for _, m := range self.Matchers { - if ml := m.Len(); l > 0 { - l += ml - } else { - return -1 - } - } - - return -} - -func (self EveryOf) Index(s string) (int, []int) { - var index int - var offset int - - // make `in` with cap as len(s), - // cause it is the maximum size of output segments values - next := acquireSegments(len(s)) - current := acquireSegments(len(s)) - - sub := s - for i, m := range self.Matchers { - idx, seg := m.Index(sub) - if idx == -1 { - releaseSegments(next) - releaseSegments(current) - return -1, nil - } - - if i == 0 { - // we use copy here instead of `current = seg` - // cause seg is a slice from reusable buffer `in` - // and it could be overwritten in next iteration - current = append(current, seg...) - } else { - // clear the next - next = next[:0] - - delta := index - (idx + offset) - for _, ex := range current { - for _, n := range seg { - if ex+delta == n { - next = append(next, n) - } - } - } - - if len(next) == 0 { - releaseSegments(next) - releaseSegments(current) - return -1, nil - } - - current = append(current[:0], next...) - } - - index = idx + offset - sub = s[index:] - offset += idx - } - - releaseSegments(next) - - return index, current -} - -func (self EveryOf) Match(s string) bool { - for _, m := range self.Matchers { - if !m.Match(s) { - return false - } - } - - return true -} - -func (self EveryOf) String() string { - return fmt.Sprintf("", self.Matchers) -} diff --git a/constraint/vendor/github.com/gobwas/glob/match/list.go b/constraint/vendor/github.com/gobwas/glob/match/list.go deleted file mode 100644 index 7fd763ecd..000000000 --- a/constraint/vendor/github.com/gobwas/glob/match/list.go +++ /dev/null @@ -1,49 +0,0 @@ -package match - -import ( - "fmt" - "github.com/gobwas/glob/util/runes" - "unicode/utf8" -) - -type List struct { - List []rune - Not bool -} - -func NewList(list []rune, not bool) List { - return List{list, not} -} - -func (self List) Match(s string) bool { - r, w := utf8.DecodeRuneInString(s) - if len(s) > w { - return false - } - - inList := runes.IndexRune(self.List, r) != -1 - return inList == !self.Not -} - -func (self List) Len() int { - return lenOne -} - -func (self List) Index(s string) (int, []int) { - for i, r := range s { - if self.Not == (runes.IndexRune(self.List, r) == -1) { - return i, segmentsByRuneLength[utf8.RuneLen(r)] - } - } - - return -1, nil -} - -func (self List) String() string { - var not string - if self.Not { - not = "!" - } - - return fmt.Sprintf("", not, string(self.List)) -} diff --git a/constraint/vendor/github.com/gobwas/glob/match/match.go b/constraint/vendor/github.com/gobwas/glob/match/match.go deleted file mode 100644 index f80e007fb..000000000 --- a/constraint/vendor/github.com/gobwas/glob/match/match.go +++ /dev/null @@ -1,81 +0,0 @@ -package match - -// todo common table of rune's length - -import ( - "fmt" - "strings" -) - -const lenOne = 1 -const lenZero = 0 -const lenNo = -1 - -type Matcher interface { - Match(string) bool - Index(string) (int, []int) - Len() int - String() string -} - -type Matchers []Matcher - -func (m Matchers) String() string { - var s []string - for _, matcher := range m { - s = append(s, fmt.Sprint(matcher)) - } - - return fmt.Sprintf("%s", strings.Join(s, ",")) -} - -// appendMerge merges and sorts given already SORTED and UNIQUE segments. -func appendMerge(target, sub []int) []int { - lt, ls := len(target), len(sub) - out := make([]int, 0, lt+ls) - - for x, y := 0, 0; x < lt || y < ls; { - if x >= lt { - out = append(out, sub[y:]...) - break - } - - if y >= ls { - out = append(out, target[x:]...) - break - } - - xValue := target[x] - yValue := sub[y] - - switch { - - case xValue == yValue: - out = append(out, xValue) - x++ - y++ - - case xValue < yValue: - out = append(out, xValue) - x++ - - case yValue < xValue: - out = append(out, yValue) - y++ - - } - } - - target = append(target[:0], out...) - - return target -} - -func reverseSegments(input []int) { - l := len(input) - m := l / 2 - - for i := 0; i < m; i++ { - input[i], input[l-i-1] = input[l-i-1], input[i] - } -} diff --git a/constraint/vendor/github.com/gobwas/glob/match/max.go b/constraint/vendor/github.com/gobwas/glob/match/max.go deleted file mode 100644 index d72f69eff..000000000 --- a/constraint/vendor/github.com/gobwas/glob/match/max.go +++ /dev/null @@ -1,49 +0,0 @@ -package match - -import ( - "fmt" - "unicode/utf8" -) - -type Max struct { - Limit int -} - -func NewMax(l int) Max { - return Max{l} -} - -func (self Max) Match(s string) bool { - var l int - for range s { - l += 1 - if l > self.Limit { - return false - } - } - - return true -} - -func (self Max) Index(s string) (int, []int) { - segments := acquireSegments(self.Limit + 1) - segments = append(segments, 0) - var count int - for i, r := range s { - count++ - if count > self.Limit { - break - } - segments = append(segments, i+utf8.RuneLen(r)) - } - - return 0, segments -} - -func (self Max) Len() int { - return lenNo -} - -func (self Max) String() string { - return fmt.Sprintf("", self.Limit) -} diff --git a/constraint/vendor/github.com/gobwas/glob/match/min.go b/constraint/vendor/github.com/gobwas/glob/match/min.go deleted file mode 100644 index db57ac8eb..000000000 --- a/constraint/vendor/github.com/gobwas/glob/match/min.go +++ /dev/null @@ -1,57 +0,0 @@ -package match - -import ( - "fmt" - "unicode/utf8" -) - -type Min struct { - Limit int -} - -func NewMin(l int) Min { - return Min{l} -} - -func (self Min) Match(s string) bool { - var l int - for range s { - l += 1 - if l >= self.Limit { - return true - } - } - - return false -} - -func (self Min) Index(s string) (int, []int) { - var count int - - c := len(s) - self.Limit + 1 - if c <= 0 { - return -1, nil - } - - segments := acquireSegments(c) - for i, r := range s { - count++ - if count >= self.Limit { - segments = append(segments, i+utf8.RuneLen(r)) - } - } - - if len(segments) == 0 { - return -1, nil - } - - return 0, segments -} - -func (self Min) Len() int { - return lenNo -} - -func (self Min) String() string { - return fmt.Sprintf("", self.Limit) -} diff --git a/constraint/vendor/github.com/gobwas/glob/match/nothing.go b/constraint/vendor/github.com/gobwas/glob/match/nothing.go deleted file mode 100644 index 0d4ecd36b..000000000 --- a/constraint/vendor/github.com/gobwas/glob/match/nothing.go +++ /dev/null @@ -1,27 +0,0 @@ -package match - -import ( - "fmt" -) - -type Nothing struct{} - -func NewNothing() Nothing { - return Nothing{} -} - -func (self Nothing) Match(s string) bool { - return len(s) == 0 -} - -func (self Nothing) Index(s string) (int, []int) { - return 0, segments0 -} - -func (self Nothing) Len() int { - return lenZero -} - -func (self Nothing) String() string { - return fmt.Sprintf("") -} diff --git a/constraint/vendor/github.com/gobwas/glob/match/prefix.go b/constraint/vendor/github.com/gobwas/glob/match/prefix.go deleted file mode 100644 index a7347250e..000000000 --- a/constraint/vendor/github.com/gobwas/glob/match/prefix.go +++ /dev/null @@ -1,50 +0,0 @@ -package match - -import ( - "fmt" - "strings" - "unicode/utf8" -) - -type Prefix struct { - Prefix string -} - -func NewPrefix(p string) Prefix { - return Prefix{p} -} - -func (self Prefix) Index(s string) (int, []int) { - idx := strings.Index(s, self.Prefix) - if idx == -1 { - return -1, nil - } - - length := len(self.Prefix) - var sub string - if len(s) > idx+length { - sub = s[idx+length:] - } else { - sub = "" - } - - segments := acquireSegments(len(sub) + 1) - segments = append(segments, length) - for i, r := range sub { - segments = append(segments, length+i+utf8.RuneLen(r)) - } - - return idx, segments -} - -func (self Prefix) Len() int { - return lenNo -} - -func (self Prefix) Match(s string) bool { - return strings.HasPrefix(s, self.Prefix) -} - -func (self Prefix) String() string { - return fmt.Sprintf("", self.Prefix) -} diff --git a/constraint/vendor/github.com/gobwas/glob/match/prefix_any.go b/constraint/vendor/github.com/gobwas/glob/match/prefix_any.go deleted file mode 100644 index 8ee58fe1b..000000000 --- a/constraint/vendor/github.com/gobwas/glob/match/prefix_any.go +++ /dev/null @@ -1,55 +0,0 @@ -package match - -import ( - "fmt" - "strings" - "unicode/utf8" - - sutil "github.com/gobwas/glob/util/strings" -) - -type PrefixAny struct { - Prefix string - Separators []rune -} - -func NewPrefixAny(s string, sep []rune) PrefixAny { - return PrefixAny{s, sep} -} - -func (self PrefixAny) Index(s string) (int, []int) { - idx := strings.Index(s, self.Prefix) - if idx == -1 { - return -1, nil - } - - n := len(self.Prefix) - sub := s[idx+n:] - i := sutil.IndexAnyRunes(sub, self.Separators) - if i > -1 { - sub = sub[:i] - } - - seg := acquireSegments(len(sub) + 1) - seg = append(seg, n) - for i, r := range sub { - seg = append(seg, n+i+utf8.RuneLen(r)) - } - - return idx, seg -} - -func (self PrefixAny) Len() int { - return lenNo -} - -func (self PrefixAny) Match(s string) bool { - if !strings.HasPrefix(s, self.Prefix) { - return false - } - return sutil.IndexAnyRunes(s[len(self.Prefix):], self.Separators) == -1 -} - -func (self PrefixAny) String() string { - return fmt.Sprintf("", self.Prefix, string(self.Separators)) -} diff --git a/constraint/vendor/github.com/gobwas/glob/match/prefix_suffix.go b/constraint/vendor/github.com/gobwas/glob/match/prefix_suffix.go deleted file mode 100644 index 8208085a1..000000000 --- a/constraint/vendor/github.com/gobwas/glob/match/prefix_suffix.go +++ /dev/null @@ -1,62 +0,0 @@ -package match - -import ( - "fmt" - "strings" -) - -type PrefixSuffix struct { - Prefix, Suffix string -} - -func NewPrefixSuffix(p, s string) PrefixSuffix { - return PrefixSuffix{p, s} -} - -func (self PrefixSuffix) Index(s string) (int, []int) { - prefixIdx := strings.Index(s, self.Prefix) - if prefixIdx == -1 { - return -1, nil - } - - suffixLen := len(self.Suffix) - if suffixLen <= 0 { - return prefixIdx, []int{len(s) - prefixIdx} - } - - if (len(s) - prefixIdx) <= 0 { - return -1, nil - } - - segments := acquireSegments(len(s) - prefixIdx) - for sub := s[prefixIdx:]; ; { - suffixIdx := strings.LastIndex(sub, self.Suffix) - if suffixIdx == -1 { - break - } - - segments = append(segments, suffixIdx+suffixLen) - sub = sub[:suffixIdx] - } - - if len(segments) == 0 { - releaseSegments(segments) - return -1, nil - } - - reverseSegments(segments) - - return prefixIdx, segments -} - -func (self PrefixSuffix) Len() int { - return lenNo -} - -func (self PrefixSuffix) Match(s string) bool { - return strings.HasPrefix(s, self.Prefix) && strings.HasSuffix(s, self.Suffix) -} - -func (self PrefixSuffix) String() string { - return fmt.Sprintf("", self.Prefix, self.Suffix) -} diff --git a/constraint/vendor/github.com/gobwas/glob/match/range.go b/constraint/vendor/github.com/gobwas/glob/match/range.go deleted file mode 100644 index ce30245a4..000000000 --- a/constraint/vendor/github.com/gobwas/glob/match/range.go +++ /dev/null @@ -1,48 +0,0 @@ -package match - -import ( - "fmt" - "unicode/utf8" -) - -type Range struct { - Lo, Hi rune - Not bool -} - -func NewRange(lo, hi rune, not bool) Range { - return Range{lo, hi, not} -} - -func (self Range) Len() int { - return lenOne -} - -func (self Range) Match(s string) bool { - r, w := utf8.DecodeRuneInString(s) - if len(s) > w { - return false - } - - inRange := r >= self.Lo && r <= self.Hi - - return inRange == !self.Not -} - -func (self Range) Index(s string) (int, []int) { - for i, r := range s { - if self.Not != (r >= self.Lo && r <= self.Hi) { - return i, segmentsByRuneLength[utf8.RuneLen(r)] - } - } - - return -1, nil -} - -func (self Range) String() string { - var not string - if self.Not { - not = "!" - } - return fmt.Sprintf("", not, string(self.Lo), string(self.Hi)) -} diff --git a/constraint/vendor/github.com/gobwas/glob/match/row.go b/constraint/vendor/github.com/gobwas/glob/match/row.go deleted file mode 100644 index 4379042e4..000000000 --- a/constraint/vendor/github.com/gobwas/glob/match/row.go +++ /dev/null @@ -1,77 +0,0 @@ -package match - -import ( - "fmt" -) - -type Row struct { - Matchers Matchers - RunesLength int - Segments []int -} - -func NewRow(len int, m ...Matcher) Row { - return Row{ - Matchers: Matchers(m), - RunesLength: len, - Segments: []int{len}, - } -} - -func (self Row) matchAll(s string) bool { - var idx int - for _, m := range self.Matchers { - length := m.Len() - - var next, i int - for next = range s[idx:] { - i++ - if i == length { - break - } - } - - if i < length || !m.Match(s[idx:idx+next+1]) { - return false - } - - idx += next + 1 - } - - return true -} - -func (self Row) lenOk(s string) bool { - var i int - for range s { - i++ - if i > self.RunesLength { - return false - } - } - return self.RunesLength == i -} - -func (self Row) Match(s string) bool { - return self.lenOk(s) && self.matchAll(s) -} - -func (self Row) Len() (l int) { - return self.RunesLength -} - -func (self Row) Index(s string) (int, []int) { - for i := range s { - if len(s[i:]) < self.RunesLength { - break - } - if self.matchAll(s[i:]) { - return i, self.Segments - } - } - return -1, nil -} - -func (self Row) String() string { - return fmt.Sprintf("", self.RunesLength, self.Matchers) -} diff --git a/constraint/vendor/github.com/gobwas/glob/match/segments.go b/constraint/vendor/github.com/gobwas/glob/match/segments.go deleted file mode 100644 index 9ea6f3094..000000000 --- a/constraint/vendor/github.com/gobwas/glob/match/segments.go +++ /dev/null @@ -1,91 +0,0 @@ -package match - -import ( - "sync" -) - -type SomePool interface { - Get() []int - Put([]int) -} - -var segmentsPools [1024]sync.Pool - -func toPowerOfTwo(v int) int { - v-- - v |= v >> 1 - v |= v >> 2 - v |= v >> 4 - v |= v >> 8 - v |= v >> 16 - v++ - - return v -} - -const ( - cacheFrom = 16 - cacheToAndHigher = 1024 - cacheFromIndex = 15 - cacheToAndHigherIndex = 1023 -) - -var ( - segments0 = []int{0} - segments1 = []int{1} - segments2 = []int{2} - segments3 = []int{3} - segments4 = []int{4} -) - -var segmentsByRuneLength [5][]int = [5][]int{ - 0: segments0, - 1: segments1, - 2: segments2, - 3: segments3, - 4: segments4, -} - -func init() { - for i := cacheToAndHigher; i >= cacheFrom; i >>= 1 { - func(i int) { - segmentsPools[i-1] = sync.Pool{New: func() interface{} { - return make([]int, 0, i) - }} - }(i) - } -} - -func getTableIndex(c int) int { - p := toPowerOfTwo(c) - switch { - case p >= cacheToAndHigher: - return cacheToAndHigherIndex - case p <= cacheFrom: - return cacheFromIndex - default: - return p - 1 - } -} - -func acquireSegments(c int) []int { - // make []int with less capacity than cacheFrom - // is faster than acquiring it from pool - if c < cacheFrom { - return make([]int, 0, c) - } - - return segmentsPools[getTableIndex(c)].Get().([]int)[:0] -} - -func releaseSegments(s []int) { - c := cap(s) - - // make []int with less capacity than cacheFrom - // is faster than acquiring it from pool - if c < cacheFrom { - return - } - - segmentsPools[getTableIndex(c)].Put(s) -} diff --git a/constraint/vendor/github.com/gobwas/glob/match/single.go b/constraint/vendor/github.com/gobwas/glob/match/single.go deleted file mode 100644 index ee6e3954c..000000000 --- a/constraint/vendor/github.com/gobwas/glob/match/single.go +++ /dev/null @@ -1,43 +0,0 @@ -package match - -import ( - "fmt" - "github.com/gobwas/glob/util/runes" - "unicode/utf8" -) - -// single represents ? -type Single struct { - Separators []rune -} - -func NewSingle(s []rune) Single { - return Single{s} -} - -func (self Single) Match(s string) bool { - r, w := utf8.DecodeRuneInString(s) - if len(s) > w { - return false - } - - return runes.IndexRune(self.Separators, r) == -1 -} - -func (self Single) Len() int { - return lenOne -} - -func (self Single) Index(s string) (int, []int) { - for i, r := range s { - if runes.IndexRune(self.Separators, r) == -1 { - return i, segmentsByRuneLength[utf8.RuneLen(r)] - } - } - - return -1, nil -} - -func (self Single) String() string { - return fmt.Sprintf("", string(self.Separators)) -} diff --git a/constraint/vendor/github.com/gobwas/glob/match/suffix.go b/constraint/vendor/github.com/gobwas/glob/match/suffix.go deleted file mode 100644 index 85bea8c68..000000000 --- a/constraint/vendor/github.com/gobwas/glob/match/suffix.go +++ /dev/null @@ -1,35 +0,0 @@ -package match - -import ( - "fmt" - "strings" -) - -type Suffix struct { - Suffix string -} - -func NewSuffix(s string) Suffix { - return Suffix{s} -} - -func (self Suffix) Len() int { - return lenNo -} - -func (self Suffix) Match(s string) bool { - return strings.HasSuffix(s, self.Suffix) -} - -func (self Suffix) Index(s string) (int, []int) { - idx := strings.Index(s, self.Suffix) - if idx == -1 { - return -1, nil - } - - return 0, []int{idx + len(self.Suffix)} -} - -func (self Suffix) String() string { - return fmt.Sprintf("", self.Suffix) -} diff --git a/constraint/vendor/github.com/gobwas/glob/match/suffix_any.go b/constraint/vendor/github.com/gobwas/glob/match/suffix_any.go deleted file mode 100644 index c5106f819..000000000 --- a/constraint/vendor/github.com/gobwas/glob/match/suffix_any.go +++ /dev/null @@ -1,43 +0,0 @@ -package match - -import ( - "fmt" - "strings" - - sutil "github.com/gobwas/glob/util/strings" -) - -type SuffixAny struct { - Suffix string - Separators []rune -} - -func NewSuffixAny(s string, sep []rune) SuffixAny { - return SuffixAny{s, sep} -} - -func (self SuffixAny) Index(s string) (int, []int) { - idx := strings.Index(s, self.Suffix) - if idx == -1 { - return -1, nil - } - - i := sutil.LastIndexAnyRunes(s[:idx], self.Separators) + 1 - - return i, []int{idx + len(self.Suffix) - i} -} - -func (self SuffixAny) Len() int { - return lenNo -} - -func (self SuffixAny) Match(s string) bool { - if !strings.HasSuffix(s, self.Suffix) { - return false - } - return sutil.IndexAnyRunes(s[:len(s)-len(self.Suffix)], self.Separators) == -1 -} - -func (self SuffixAny) String() string { - return fmt.Sprintf("", string(self.Separators), self.Suffix) -} diff --git a/constraint/vendor/github.com/gobwas/glob/match/super.go b/constraint/vendor/github.com/gobwas/glob/match/super.go deleted file mode 100644 index 3875950bb..000000000 --- a/constraint/vendor/github.com/gobwas/glob/match/super.go +++ /dev/null @@ -1,33 +0,0 @@ -package match - -import ( - "fmt" -) - -type Super struct{} - -func NewSuper() Super { - return Super{} -} - -func (self Super) Match(s string) bool { - return true -} - -func (self Super) Len() int { - return lenNo -} - -func (self Super) Index(s string) (int, []int) { - segments := acquireSegments(len(s) + 1) - for i := range s { - segments = append(segments, i) - } - segments = append(segments, len(s)) - - return 0, segments -} - -func (self Super) String() string { - return fmt.Sprintf("") -} diff --git a/constraint/vendor/github.com/gobwas/glob/match/text.go b/constraint/vendor/github.com/gobwas/glob/match/text.go deleted file mode 100644 index 0a17616d3..000000000 --- a/constraint/vendor/github.com/gobwas/glob/match/text.go +++ /dev/null @@ -1,45 +0,0 @@ -package match - -import ( - "fmt" - "strings" - "unicode/utf8" -) - -// raw represents raw string to match -type Text struct { - Str string - RunesLength int - BytesLength int - Segments []int -} - -func NewText(s string) Text { - return Text{ - Str: s, - RunesLength: utf8.RuneCountInString(s), - BytesLength: len(s), - Segments: []int{len(s)}, - } -} - -func (self Text) Match(s string) bool { - return self.Str == s -} - -func (self Text) Len() int { - return self.RunesLength -} - -func (self Text) Index(s string) (int, []int) { - index := strings.Index(s, self.Str) - if index == -1 { - return -1, nil - } - - return index, self.Segments -} - -func (self Text) String() string { - return fmt.Sprintf("", self.Str) -} diff --git a/constraint/vendor/github.com/gobwas/glob/parse.go b/constraint/vendor/github.com/gobwas/glob/parse.go new file mode 100644 index 000000000..30114dfcf --- /dev/null +++ b/constraint/vendor/github.com/gobwas/glob/parse.go @@ -0,0 +1,679 @@ +package glob + +import ( + "slices" + "unicode/utf8" + + "github.com/gobwas/glob/internal/debug" + "github.com/gobwas/glob/syntax" +) + +// compile parses the pattern into a matcher tree (see below), simplifies and +// specializes it, and computes the match-time hints and preconditions; see +// [simplify], [specialize], [annotateStars], [needsState], [minLength] and +// [requiredSuffix]. It is what [Compile] wraps. +func compile(str string, sep []rune) (*Pattern, error) { + if debug.Enabled { + debug.Printf("compiling %#q\n", str) + } + // The matchers keep sep and read it while matching, and the variadic slice + // may alias an array owned by the caller: give them a copy of their own. + // + // The pattern itself keeps the slice as given, to return it from + // Separators() without cloning. + var ( + sepCopy = slices.Clone(sep) + sepStr = string(sep) + ) + + type operator struct { + kind int + index int + } + const ( + opTerms = iota + opList + ) + /* + Stack-based parsing is a technique used to evaluate mathematical + expressions by leveraging the properties of the LIFO (Last-In, + First-Out) data structure, the stack. It involves using two stacks: one + for operands (numbers) and one for operators. By processing the + expression from left to right and strategically pushing and popping + elements from the stacks, the expression can be effectively evaluated. + + https://cp-algorithms.com/string/expression_parsing.html + + Here the operands are matchers and the only operators are the braces + and the commas inside them, so it goes as follows: + + - a leaf token (text, `?`, `*`, `**`, `[...]`) pushes its matcher + onto the stack; + + - `{` pushes two operators, both remembering the current stack + length: opTerms marks where the alternatives of the group will + be collected, opList marks where the terms of the current + alternative begin; + + - `,` pops the opList, collapses the terms above its index into a + single multiMatcher (or a voidMatcher when there are none, as in + `{,a}`), and pushes a fresh opList for the next alternative; + + - `}` pops the opList and collapses the last alternative the same + way, then pops the opTerms and collapses everything above its + index -- one matcher per alternative by now -- into an + altMatcher; + + - at the EOF whatever is left on the stack is the top-level + sequence; a leftover operator means an unclosed `{`. + + For example, `a{b*,c}d` goes like this (list@i is an opList with + index i, likewise terms@i): + + token stack operators + a "a" + { "a" terms@1 list@1 + b "a" "b" terms@1 list@1 + * "a" "b" * terms@1 list@1 + , "a" ["b"·*] terms@1 list@2 + c "a" ["b"·*] "c" terms@1 list@2 + } "a" ["b"·*] ["c"] terms@1 + "a" {["b"·*]|["c"]} + d "a" {["b"·*]|["c"]} "d" + EOF ["a"·{["b"·*]|["c"]}·"d"] + + The result is then simplified (["c"] becomes "c") and specialized; + see [simplify] and [specialize]. + */ + var ( + stack []matcher + operators []operator + ) + lex := syntax.NewLexer(str) +parsing: + for { + token := lex.Next() + if debug.Enabled { + debug.Printf("token: %s\n", token) + } + switch token.Type { + case syntax.EOF: + break parsing + + case syntax.Error: + return nil, &SyntaxError{ + Offset: lex.Offset(), + Reason: token.Data, + } + + case syntax.Single: + stack = append(stack, &charMatcher{ + Sep: sepCopy, + }) + + case syntax.Text: + stack = append(stack, &textMatcher{ + Text: token.Data, + }) + + case syntax.RangeOpen: + m, err := parseRange(lex) + if err != nil { + return nil, err + } + stack = append(stack, m) + + case syntax.Any: + stack = append(stack, &starMatcher{ + Sep: sepCopy, + SepStr: sepStr, + }) + + case syntax.Super: + stack = append(stack, &starMatcher{ + Sep: nil, + }) + + case syntax.TermsOpen: + // Note that the `{` opens both the group and its first + // alternative: every alternative is delimited by an opList + // operator. This way TermsClose always collapses the trailing + // alternative into a single matcher first, even when the group + // has no commas at all, e.g. `{ab*}`. + operators = append(operators, + operator{kind: opTerms, index: len(stack)}, + operator{kind: opList, index: len(stack)}, + ) + if debug.Enabled { + debug.Printf("terms enter: %d\n", len(stack)) + } + + case syntax.TermSeparator: + k := len(operators) - 1 + if k < 0 { + return nil, &SyntaxError{ + Offset: lex.Offset(), + Reason: "unexpected `,`", + } + } + x := operators[k] + if x.kind == opList { + // Remove the most recent "comma" operator. + // Note that the previous one is the terms operator. + operators = operators[:k] + } + i := x.index + // Handle the `{,a}` case. + if i == len(stack) { + // Empty matchers. + stack = append(stack, &voidMatcher{}) + } else { + stack[i] = multiMatcher(slices.Clone(stack[i:])) + stack = stack[:i+1] + if debug.Enabled { + debug.Printf("terms next: %d: %s\n", i, stack[i]) + } + } + operators = append(operators, operator{ + kind: opList, + index: len(stack), + }) + if debug.Enabled { + debug.Printf("terms separator: %d\n", len(stack)) + } + + case syntax.TermsClose: + for { + k := len(operators) - 1 + if k < 0 { + return nil, &SyntaxError{ + Offset: lex.Offset(), + Reason: "unexpected `}`", + } + } + x := operators[k] + operators = operators[:k] + + i := x.index + c := slices.Clone(stack[i:]) + var m matcher + switch x.kind { + case opTerms: + m = altMatcher(c) + case opList: + m = multiMatcher(c) + } + // Handle the `{a,}` case. + if i == len(stack) { + stack = append(stack, m) + } else { + stack = stack[:i+1] + stack[i] = m + } + + if debug.Enabled { + debug.Printf( + "terms leave(%d): %d: %s\n", + x.kind, i, stack[i], + ) + } + if x.kind == opTerms { + break + } + } + + default: + return nil, &SyntaxError{ + Offset: lex.Offset(), + Reason: "unexpected token " + token.String(), + } + } + } + if len(operators) != 0 { + return nil, &SyntaxError{ + Offset: lex.Offset(), + Reason: "unclosed `{`", + } + } + m := simplify(multiMatcher(stack)) + m = specialize(m, true) + annotateStars(m, true) + if debug.Enabled { + debug.Printf("compiled %#q: %s\n", str, m) + } + p := &Pattern{ + str: str, + sep: sep, + m: m, + state: needsState(m), + } + if p.state { + p.minLen = minLength(m) + p.suffix = requiredSuffix(m) + } + return p, nil +} + +// parseRange parses a character class, called right after its opening `[` +// was read; it consumes the tokens up to and including the closing `]`. The +// class is either a range, `[a-c]`, or a set, `[abc]`, either possibly +// negated with a leading `!`; see [runeRangeMatcher] and [runeSetMatcher]. +func parseRange(lex *syntax.Lexer) (matcher, error) { + // -1 marks a range boundary as unset: any decoded rune, including + // U+0000, is non-negative. + var ( + not bool + lo, hi rune = -1, -1 + chars map[rune]struct{} + ) + for { + token := lex.Next() + switch token.Type { + case syntax.EOF: + return nil, &SyntaxError{ + Offset: lex.Offset(), + Reason: "unclosed `[`", + } + + case syntax.Error: + return nil, &SyntaxError{ + Offset: lex.Offset(), + Reason: token.Data, + } + + case syntax.Not: + not = true + + case syntax.RangeLo: + r, w := utf8.DecodeRuneInString(token.Data) + if len(token.Data) > w { + return nil, &SyntaxError{ + Offset: lex.Offset(), + Reason: "unexpected length of range lo character", + } + } + lo = r + + case syntax.RangeBetween: + // The `-` between lo and hi: nothing to do. + + case syntax.RangeHi: + r, w := utf8.DecodeRuneInString(token.Data) + if len(token.Data) > w { + return nil, &SyntaxError{ + Offset: lex.Offset(), + Reason: "unexpected length of range hi character", + } + } + hi = r + + if hi < lo { + return nil, &SyntaxError{ + Offset: lex.Offset(), + Reason: "range hi character is less than lo", + } + } + + case syntax.Text: + chars = make(map[rune]struct{}) + for _, r := range token.Data { + chars[r] = struct{}{} + } + + case syntax.RangeClose: + isRange := lo >= 0 && hi >= 0 + isChars := chars != nil + + if isChars == isRange { + return nil, &SyntaxError{ + Offset: lex.Offset(), + Reason: "could not parse range", + } + } + if isRange { + return &runeRangeMatcher{ + Lo: lo, + Hi: hi, + Not: not, + }, nil + } + return &runeSetMatcher{ + Set: chars, + Not: not, + }, nil + } + } +} + +// simplify rewrites the freshly parsed tree into its canonical shape, bottom +// up: the sequences are normalized (see [normalizeSequence]), and a sequence +// or a group of alternatives with a single child is replaced by the child, +// with none -- by a void. +func simplify(m matcher) matcher { + var ( + ms []matcher + isMulti bool + ) + switch v := m.(type) { + case multiMatcher: + ms, isMulti = v, true + case altMatcher: + ms = v + default: + return m + } + for i, m := range ms { + ms[i] = simplify(m) + } + if isMulti { + ms = normalizeSequence(ms) + } + switch len(ms) { + case 0: + return &voidMatcher{} + case 1: + return ms[0] + } + if isMulti { + return multiMatcher(ms) + } + return altMatcher(ms) +} + +// normalizeSequence rewrites a sequence of (already simplified) matchers +// into a simpler equivalent one: +// +// ["a"·["b"·"c"]·"d"] => ["a"·"b"·"c"·"d"] inline the nested sequences +// ["a"·void] => ["a"] drop the void matchers +// ["a"·"b"] => ["ab"] merge the adjacent literals +// [*·**] => [**] coalesce the adjacent stars +// +// Longer literals also make better star jumps; see [annotateStars]. +func normalizeSequence(ms []matcher) []matcher { + if !needsNormalize(ms) { + // The common case: nothing to rewrite, no copy needed. + return ms + } + out := make([]matcher, 0, len(ms)) + var push func(m matcher) + push = func(m matcher) { + switch v := m.(type) { + case multiMatcher: + for _, c := range v { + push(c) + } + return + case *voidMatcher: + return + case *textMatcher: + if len(out) > 0 { + if prev, ok := out[len(out)-1].(*textMatcher); ok { + out[len(out)-1] = &textMatcher{Text: prev.Text + v.Text} + return + } + } + case *starMatcher: + if len(out) > 0 { + if prev, ok := out[len(out)-1].(*starMatcher); ok { + // Adjacent stars are equivalent to the most general + // of them: the one not limited by separators, if any. + if len(prev.Sep) > 0 && len(v.Sep) == 0 { + out[len(out)-1] = v + } + return + } + } + } + out = append(out, m) + } + for _, m := range ms { + push(m) + } + return out +} + +// needsNormalize reports whether [normalizeSequence] would change ms, so +// that the common case skips the copy. +func needsNormalize(ms []matcher) bool { + for i, m := range ms { + switch m.(type) { + case multiMatcher, *voidMatcher: + return true + case *textMatcher: + if i > 0 { + if _, ok := ms[i-1].(*textMatcher); ok { + return true + } + } + case *starMatcher: + if i > 0 { + if _, ok := ms[i-1].(*starMatcher); ok { + return true + } + } + } + } + return false +} + +// specialize rewrites the terminal sub-sequences of the simplified matcher +// tree into the shaped matchers -- [prefixMatcher], [suffixMatcher], +// [prefixSuffixMatcher] and [containsMatcher]; see [foldTail] for the +// rewrites. The tail flag tells whether nothing follows m in the pattern; +// only there the rewrites apply, since a shaped matcher consumes the whole +// remainder of the input. +func specialize(m matcher, tail bool) matcher { + switch v := m.(type) { + case altMatcher: + // Every alternative ends where the alt ends. + for i, c := range v { + v[i] = specialize(c, tail) + } + return v + + case multiMatcher: + for i, c := range v { + v[i] = specialize(c, tail && i == len(v)-1) + } + if !tail { + return v + } + ms := foldTail([]matcher(v)) + if len(ms) == 1 { + return ms[0] + } + return multiMatcher(ms) + } + return m +} + +// foldTail repeatedly folds the two trailing matchers of the terminal +// sequence ms into a shaped one, while possible: +// +// [..·"abc"·*] => [..·prefix("abc")] +// [..·*·"abc"] => [..·suffix("abc")] +// [..·"abc"·prefix("def")] => [..·prefix("abcdef")] +// [..·*·prefix("abc")] => [..·contains("abc")] (separator-free) +// [..·"abc"·suffix("def")] => [..·prefix_suffix("abc","def")] +// [..·*·contains("abc")] => [..·contains("abc")] (separator-free) +func foldTail(ms []matcher) []matcher { + for len(ms) >= 2 { + var ( + prev = ms[len(ms)-2] + folded matcher + ) + switch last := ms[len(ms)-1].(type) { + case *starMatcher: + if t, ok := prev.(*textMatcher); ok { + folded = &prefixMatcher{Text: t.Text, Sep: last.SepStr} + } + + case *textMatcher: + if star, ok := prev.(*starMatcher); ok { + folded = &suffixMatcher{Text: last.Text, Sep: star.SepStr} + } + + case *prefixMatcher: + switch p := prev.(type) { + case *textMatcher: + folded = &prefixMatcher{Text: p.Text + last.Text, Sep: last.Sep} + case *starMatcher: + if p.SepStr == "" && last.Sep == "" { + folded = &containsMatcher{Text: last.Text} + } + } + + case *suffixMatcher: + if t, ok := prev.(*textMatcher); ok { + folded = &prefixSuffixMatcher{ + Prefix: t.Text, + Suffix: last.Text, + Sep: last.Sep, + } + } + + case *containsMatcher: + if star, ok := prev.(*starMatcher); ok && star.SepStr == "" { + folded = last + } + } + if folded == nil { + break + } + ms = ms[:len(ms)-1] + ms[len(ms)-1] = folded + } + return ms +} + +// annotateStars computes the compile-time hints for the star matchers, in +// order to keep the number of restart points they store at match time low: +// +// - a star directly followed by a literal jumps between the literal +// occurrences instead of retrying at every rune (see +// [starMatcher.storeSkip]); +// +// - a star with nothing after it anywhere in the pattern (tail is true +// for m and the star closes it) consumes its whole reach at once and +// stores no restart points at all. +func annotateStars(m matcher, tail bool) { + switch v := m.(type) { + case multiMatcher: + for i, c := range v { + last := i == len(v)-1 + star, ok := c.(*starMatcher) + if !ok { + annotateStars(c, tail && last) + continue + } + star.Terminal = tail && last + if !last { + star.Next = leadingLiteral(v[i+1]) + } + } + case altMatcher: + for _, c := range v { + annotateStars(c, tail) + } + case *starMatcher: + v.Terminal = tail + } +} + +// leadingLiteral returns the literal the given matcher is guaranteed to +// begin its match with, if any. +func leadingLiteral(m matcher) string { + switch v := m.(type) { + case *textMatcher: + return v.Text + case *prefixMatcher: + return v.Text + case *prefixSuffixMatcher: + return v.Prefix + } + return "" +} + +// minLength returns the minimum length in bytes of a string m can match. +func minLength(m matcher) (n int) { + switch v := m.(type) { + case *textMatcher: + return len(v.Text) + case *charMatcher, *runeRangeMatcher, *runeSetMatcher: + return 1 + case *prefixMatcher: + return len(v.Text) + case *suffixMatcher: + return len(v.Text) + case *prefixSuffixMatcher: + return len(v.Prefix) + len(v.Suffix) + case *containsMatcher: + return len(v.Text) + case multiMatcher: + for _, c := range v { + n += minLength(c) + } + return n + case altMatcher: + n = minLength(v[0]) + for _, c := range v[1:] { + n = min(n, minLength(c)) + } + return n + } + return 0 // A star or a void. +} + +// requiredSuffix returns the literal every string m matches must end with. +func requiredSuffix(m matcher) string { + switch v := m.(type) { + case *textMatcher: + return v.Text + case *suffixMatcher: + return v.Text + case *prefixSuffixMatcher: + return v.Suffix + case multiMatcher: + return requiredSuffix(v[len(v)-1]) + case altMatcher: + s := requiredSuffix(v[0]) + for _, c := range v[1:] { + s = commonSuffix(s, requiredSuffix(c)) + if s == "" { + break + } + } + return s + } + return "" // A star, a single-character matcher or a void. +} + +// commonSuffix returns the longest common suffix of a and b, never splitting +// a multi-byte rune. +func commonSuffix(a, b string) string { + i := 0 + for i < len(a) && i < len(b) { + ra, wa := utf8.DecodeLastRuneInString(a[:len(a)-i]) + rb, wb := utf8.DecodeLastRuneInString(b[:len(b)-i]) + if ra != rb || wa != wb { + break + } + i += wa + } + return a[len(a)-i:] +} + +// needsState reports whether matching m may save a checkpoint. Only the +// alts and the non-terminal stars do; a pattern without them is matched +// with a plain call chain -- see [Pattern.Match]. +func needsState(m matcher) bool { + switch v := m.(type) { + case altMatcher: + return true + case multiMatcher: + return slices.ContainsFunc(v, needsState) + case *starMatcher: + return !v.Terminal + } + return false +} diff --git a/constraint/vendor/github.com/gobwas/glob/readme.md b/constraint/vendor/github.com/gobwas/glob/readme.md index f58144e73..9f692571f 100644 --- a/constraint/vendor/github.com/gobwas/glob/readme.md +++ b/constraint/vendor/github.com/gobwas/glob/readme.md @@ -1,6 +1,6 @@ # glob.[go](https://golang.org) -[![GoDoc][godoc-image]][godoc-url] [![Build Status][travis-image]][travis-url] +[![GoDoc][godoc-image]][godoc-url] [![CI][ci-image]][ci-url] > Go Globbing Library. @@ -19,130 +19,225 @@ package main import "github.com/gobwas/glob" func main() { - var g glob.Glob - + var g *glob.Pattern + // create simple glob g = glob.MustCompile("*.github.com") g.Match("api.github.com") // true - - // quote meta characters and then create simple glob + + // quote meta characters and then create simple glob g = glob.MustCompile(glob.QuoteMeta("*.github.com")) g.Match("*.github.com") // true - + // create new glob with set of delimiters as ["."] g = glob.MustCompile("api.*.com", '.') g.Match("api.github.com") // true g.Match("api.gi.hub.com") // false - + // create new glob with set of delimiters as ["."] // but now with super wildcard g = glob.MustCompile("api.**.com", '.') g.Match("api.github.com") // true g.Match("api.gi.hub.com") // true - + // create glob with single symbol wildcard g = glob.MustCompile("?at") g.Match("cat") // true g.Match("fat") // true g.Match("at") // false - + // create glob with single symbol wildcard and delimiters ['f'] g = glob.MustCompile("?at", 'f') g.Match("cat") // true g.Match("fat") // false - g.Match("at") // false - - // create glob with character-list matchers + g.Match("at") // false + + // create glob with character-list matchers g = glob.MustCompile("[abc]at") g.Match("cat") // true g.Match("bat") // true g.Match("fat") // false g.Match("at") // false - - // create glob with character-list matchers + + // create glob with character-list matchers g = glob.MustCompile("[!abc]at") g.Match("cat") // false g.Match("bat") // false g.Match("fat") // true - g.Match("at") // false - - // create glob with character-range matchers + g.Match("at") // false + + // create glob with character-range matchers g = glob.MustCompile("[a-c]at") g.Match("cat") // true g.Match("bat") // true g.Match("fat") // false g.Match("at") // false - - // create glob with character-range matchers + + // create glob with character-range matchers g = glob.MustCompile("[!a-c]at") g.Match("cat") // false g.Match("bat") // false g.Match("fat") // true - g.Match("at") // false - - // create glob with pattern-alternatives list + g.Match("at") // false + + // create glob with pattern-alternatives list g = glob.MustCompile("{cat,bat,[fr]at}") g.Match("cat") // true g.Match("bat") // true g.Match("fat") // true g.Match("rat") // true - g.Match("at") // false - g.Match("zat") // false + g.Match("at") // false + g.Match("zat") // false } ``` +`Compile` reports malformed patterns with a `*glob.SyntaxError` carrying the +byte offset and the reason: + +```go +_, err := glob.Compile("{a,b") +// err: glob: syntax error at 4: unclosed `{` +``` + +A compiled `Pattern` captures what it was compiled from, so it can be passed +around instead of the raw arguments and inspected when needed (`String()` makes +it a `fmt.Stringer`, like `regexp.Regexp`): + +```go +g := glob.MustCompile("*.github.com", '.') +g.String() // "*.github.com" +g.Separators() // []rune{'.'} +``` + +## Syntax + +Syntax is inspired by [standard wildcards](http://tldp.org/LDP/GNU-Linux-Tools-Summary/html/x11655.htm), +with one addition: `**` (the "super-asterisk"), which matches any sequence +of characters *including* the separators, where `*` stops at them. Note that +it is just that -- a `*` that crosses separators -- and not the `**/` +"globstar" of shells and file globbers: `**/x` requires the literal `/`, so +it does not match `x`; use `{**/,}x` for that. The same applies to a +`**` between separators, e.g. `a/**/b` does not match `a/b`. + +``` +pattern: + { term } + +term: + `*` matches any sequence of non-separator characters + `**` matches any sequence of characters + `?` matches any single non-separator character + `[` [ `!` ] class `]` + character class; `!` negates it + `{` pattern-list `}` + pattern alternatives + c matches character c (c != `*`, `**`, `?`, `\`, `[`, `{`, `}`) + `\` c matches character c + +class: + lo `-` hi matches character c for lo <= c <= hi + { c } matches any of the listed characters (c != `\`, `]`; + `\` c matches c, `-` is literal here); must be non-empty + +pattern-list: + pattern { `,` pattern } + comma-separated (without spaces) patterns +``` + +### Escaping + +The backslash is the escape character: `\*` is a literal asterisk, and a +backslash itself is `\\`. Mind the Go string literals: `"foo\\bar"` is the +pattern `foo\bar`, which is the literal `foobar`, not `foo\bar`. To match a +backslash (e.g. in the Windows paths) write `"foo\\\\bar"` or `` `foo\\bar` ``, +or use `QuoteMeta` on the literal part. + +### Separators + +The separators are not part of the pattern syntax -- they are configured +once, at compilation time, as the extra arguments of `Compile`: + +```go +g := glob.MustCompile("api.*.com", '.', '/') +``` + +They only limit the wildcards: `*` and `?` never match a separator, while +`**` matches across them; the literals and the character classes are not +affected. With no separators given, `*` and `**` are equivalent. A compiled +`*glob.Pattern` keeps its separators for all matches -- to match the same +pattern with different separators, compile it again. + ## Performance -This library is created for compile-once patterns. This means, that compilation could take time, but -strings matching is done faster, than in case when always parsing template. +This library is created for compile-once patterns. This means, that +compilation could take time, but strings matching is done faster, than in +case when always parsing template. -If you will not use compiled `glob.Glob` object, and do `g := glob.MustCompile(pattern); g.Match(...)` every time, then your code will be much more slower. +If you will not use compiled `*glob.Pattern` object, and do +`g := glob.MustCompile(pattern); g.Match(...)` every time, then your code +will be much more slower. -Run `go test -bench=.` from source root to see the benchmarks: +`Match` performs zero allocations and is safe for concurrent use. Common +pattern shapes (literals, prefixes, suffixes, substrings) are recognized at +compile time and matched with plain string comparisons; the backtracking +engine behind the rest is differentially fuzzed against the `regexp` package +(see `FuzzMatchRegexp`). -Pattern | Fixture | Match | Speed (ns/op) ---------|---------|-------|-------------- -`[a-z][!a-x]*cat*[h][!b]*eyes*` | `my cat has very bright eyes` | `true` | 432 -`[a-z][!a-x]*cat*[h][!b]*eyes*` | `my dog has very bright eyes` | `false` | 199 -`https://*.google.*` | `https://account.google.com` | `true` | 96 -`https://*.google.*` | `https://google.com` | `false` | 66 -`{https://*.google.*,*yandex.*,*yahoo.*,*mail.ru}` | `http://yahoo.com` | `true` | 163 -`{https://*.google.*,*yandex.*,*yahoo.*,*mail.ru}` | `http://google.com` | `false` | 197 -`{https://*gobwas.com,http://exclude.gobwas.com}` | `https://safe.gobwas.com` | `true` | 22 -`{https://*gobwas.com,http://exclude.gobwas.com}` | `http://safe.gobwas.com` | `false` | 24 -`abc*` | `abcdef` | `true` | 8.15 -`abc*` | `af` | `false` | 5.68 -`*def` | `abcdef` | `true` | 8.84 -`*def` | `af` | `false` | 5.74 -`ab*ef` | `abcdef` | `true` | 15.2 -`ab*ef` | `af` | `false` | 10.4 - -The same things with `regexp` package: +Run `go test -bench=.` from source root to see the benchmarks (the numbers +below are from an Apple M4): Pattern | Fixture | Match | Speed (ns/op) --------|---------|-------|-------------- -`^[a-z][^a-x].*cat.*[h][^b].*eyes.*$` | `my cat has very bright eyes` | `true` | 2553 -`^[a-z][^a-x].*cat.*[h][^b].*eyes.*$` | `my dog has very bright eyes` | `false` | 1383 -`^https:\/\/.*\.google\..*$` | `https://account.google.com` | `true` | 1205 -`^https:\/\/.*\.google\..*$` | `https://google.com` | `false` | 767 -`^(https:\/\/.*\.google\..*|.*yandex\..*|.*yahoo\..*|.*mail\.ru)$` | `http://yahoo.com` | `true` | 1435 -`^(https:\/\/.*\.google\..*|.*yandex\..*|.*yahoo\..*|.*mail\.ru)$` | `http://google.com` | `false` | 1674 -`^(https:\/\/.*gobwas\.com|http://exclude.gobwas.com)$` | `https://safe.gobwas.com` | `true` | 1039 -`^(https:\/\/.*gobwas\.com|http://exclude.gobwas.com)$` | `http://safe.gobwas.com` | `false` | 272 -`^abc.*$` | `abcdef` | `true` | 237 -`^abc.*$` | `af` | `false` | 100 -`^.*def$` | `abcdef` | `true` | 464 -`^.*def$` | `af` | `false` | 265 -`^ab.*ef$` | `abcdef` | `true` | 375 -`^ab.*ef$` | `af` | `false` | 145 - -[godoc-image]: https://godoc.org/github.com/gobwas/glob?status.svg -[godoc-url]: https://godoc.org/github.com/gobwas/glob -[travis-image]: https://travis-ci.org/gobwas/glob.svg?branch=master -[travis-url]: https://travis-ci.org/gobwas/glob - -## Syntax - -Syntax is inspired by [standard wildcards](http://tldp.org/LDP/GNU-Linux-Tools-Summary/html/x11655.htm), -except that `**` is aka super-asterisk, that do not sensitive for separators. \ No newline at end of file +`[a-z][!a-x]*cat*[h][!b]*eyes*` | `my cat has very bright eyes` | `true` | 141 +`[a-z][!a-x]*cat*[h][!b]*eyes*` | `my dog has very bright eyes` | `false` | 46 +`https://*.google.*` | `https://account.google.com` | `true` | 16 +`https://*.google.*` | `https://google.com` | `false` | 13 +`{https://*.google.*,*yandex.*,*yahoo.*,*mail.ru}` | `http://yahoo.com` | `true` | 61 +`{https://*.google.*,*yandex.*,*yahoo.*,*mail.ru}` | `http://google.com` | `false` | 70 +`{https://*gobwas.com,http://exclude.gobwas.com}` | `https://safe.gobwas.com` | `true` | 24 +`{https://*gobwas.com,http://exclude.gobwas.com}` | `http://safe.gobwas.com` | `false` | 32 +`google.com` | `google.com` | `true` | 5.0 +`google.com` | `gobwas.com` | `false` | 3.9 +`abc*` | `abcdef` | `true` | 4.1 +`abc*` | `af` | `false` | 3.0 +`*def` | `abcdef` | `true` | 4.1 +`*def` | `af` | `false` | 2.9 +`ab*ef` | `abcdef` | `true` | 6.0 +`ab*ef` | `af` | `false` | 3.0 + +The same things with the `regexp` package -- not to pick on it (it is a +general-purpose engine with much stronger guarantees), but as a reference +for how the glob-shaped specialization pays off per pattern. The regular +expressions are the exact equivalents: anchored, and with the `s` flag +where there is a `*`, since a `*` matches a newline like any other +character (see `BenchmarkCompareGlobAndRegexp`): + +Pattern | Fixture | Match | Speed (ns/op) | glob is +--------|---------|-------|---------------|-------- +`(?s)^[a-z][^a-x].*cat.*[h][^b].*eyes.*$` | `my cat has very bright eyes` | `true` | 505 | 3.6x faster +`(?s)^[a-z][^a-x].*cat.*[h][^b].*eyes.*$` | `my dog has very bright eyes` | `false` | 221 | 4.9x faster +`(?s)^https://.*\.google\..*$` | `https://account.google.com` | `true` | 251 | 16x faster +`(?s)^https://.*\.google\..*$` | `https://google.com` | `false` | 128 | 9.6x faster +`(?s)^(https://.*\.google\..*\|.*yandex\..*\|.*yahoo\..*\|.*mail\.ru)$` | `http://yahoo.com` | `true` | 396 | 6.5x faster +`(?s)^(https://.*\.google\..*\|.*yandex\..*\|.*yahoo\..*\|.*mail\.ru)$` | `http://google.com` | `false` | 558 | 8.0x faster +`(?s)^(https://.*gobwas\.com\|http://exclude\.gobwas\.com)$` | `https://safe.gobwas.com` | `true` | 210 | 8.8x faster +`(?s)^(https://.*gobwas\.com\|http://exclude\.gobwas\.com)$` | `http://safe.gobwas.com` | `false` | 46 | 1.4x faster +`^google\.com$` | `google.com` | `true` | 25 | 5.0x faster +`^google\.com$` | `gobwas.com` | `false` | 17 | 4.3x faster +`(?s)^abc.*$` | `abcdef` | `true` | 43 | 10x faster +`(?s)^abc.*$` | `af` | `false` | 1.5 | 2.0x slower +`(?s)^.*def$` | `abcdef` | `true` | 73 | 18x faster +`(?s)^.*def$` | `af` | `false` | 1.5 | 1.9x slower +`(?s)^ab.*ef$` | `abcdef` | `true` | 77 | 13x faster +`(?s)^ab.*ef$` | `af` | `false` | 1.5 | 2.0x slower + +(The three `slower` rows are the tiny-mismatch cases. Both engines reject +them with the same literal check; `regexp` just reaches it through less +call overhead. In absolute terms it is 1.5ns vs 3ns -- negligible either +way.) + +[godoc-image]: https://pkg.go.dev/badge/github.com/gobwas/glob.svg +[godoc-url]: https://pkg.go.dev/github.com/gobwas/glob +[ci-image]: https://github.com/gobwas/glob/actions/workflows/ci.yml/badge.svg?branch=master +[ci-url]: https://github.com/gobwas/glob/actions/workflows/ci.yml diff --git a/constraint/vendor/github.com/gobwas/glob/syntax/ast/ast.go b/constraint/vendor/github.com/gobwas/glob/syntax/ast/ast.go deleted file mode 100644 index 3220a694a..000000000 --- a/constraint/vendor/github.com/gobwas/glob/syntax/ast/ast.go +++ /dev/null @@ -1,122 +0,0 @@ -package ast - -import ( - "bytes" - "fmt" -) - -type Node struct { - Parent *Node - Children []*Node - Value interface{} - Kind Kind -} - -func NewNode(k Kind, v interface{}, ch ...*Node) *Node { - n := &Node{ - Kind: k, - Value: v, - } - for _, c := range ch { - Insert(n, c) - } - return n -} - -func (a *Node) Equal(b *Node) bool { - if a.Kind != b.Kind { - return false - } - if a.Value != b.Value { - return false - } - if len(a.Children) != len(b.Children) { - return false - } - for i, c := range a.Children { - if !c.Equal(b.Children[i]) { - return false - } - } - return true -} - -func (a *Node) String() string { - var buf bytes.Buffer - buf.WriteString(a.Kind.String()) - if a.Value != nil { - buf.WriteString(" =") - buf.WriteString(fmt.Sprintf("%v", a.Value)) - } - if len(a.Children) > 0 { - buf.WriteString(" [") - for i, c := range a.Children { - if i > 0 { - buf.WriteString(", ") - } - buf.WriteString(c.String()) - } - buf.WriteString("]") - } - return buf.String() -} - -func Insert(parent *Node, children ...*Node) { - parent.Children = append(parent.Children, children...) - for _, ch := range children { - ch.Parent = parent - } -} - -type List struct { - Not bool - Chars string -} - -type Range struct { - Not bool - Lo, Hi rune -} - -type Text struct { - Text string -} - -type Kind int - -const ( - KindNothing Kind = iota - KindPattern - KindList - KindRange - KindText - KindAny - KindSuper - KindSingle - KindAnyOf -) - -func (k Kind) String() string { - switch k { - case KindNothing: - return "Nothing" - case KindPattern: - return "Pattern" - case KindList: - return "List" - case KindRange: - return "Range" - case KindText: - return "Text" - case KindAny: - return "Any" - case KindSuper: - return "Super" - case KindSingle: - return "Single" - case KindAnyOf: - return "AnyOf" - default: - return "" - } -} diff --git a/constraint/vendor/github.com/gobwas/glob/syntax/ast/parser.go b/constraint/vendor/github.com/gobwas/glob/syntax/ast/parser.go deleted file mode 100644 index 429b40943..000000000 --- a/constraint/vendor/github.com/gobwas/glob/syntax/ast/parser.go +++ /dev/null @@ -1,157 +0,0 @@ -package ast - -import ( - "errors" - "fmt" - "github.com/gobwas/glob/syntax/lexer" - "unicode/utf8" -) - -type Lexer interface { - Next() lexer.Token -} - -type parseFn func(*Node, Lexer) (parseFn, *Node, error) - -func Parse(lexer Lexer) (*Node, error) { - var parser parseFn - - root := NewNode(KindPattern, nil) - - var ( - tree *Node - err error - ) - for parser, tree = parserMain, root; parser != nil; { - parser, tree, err = parser(tree, lexer) - if err != nil { - return nil, err - } - } - - return root, nil -} - -func parserMain(tree *Node, lex Lexer) (parseFn, *Node, error) { - for { - token := lex.Next() - switch token.Type { - case lexer.EOF: - return nil, tree, nil - - case lexer.Error: - return nil, tree, errors.New(token.Raw) - - case lexer.Text: - Insert(tree, NewNode(KindText, Text{token.Raw})) - return parserMain, tree, nil - - case lexer.Any: - Insert(tree, NewNode(KindAny, nil)) - return parserMain, tree, nil - - case lexer.Super: - Insert(tree, NewNode(KindSuper, nil)) - return parserMain, tree, nil - - case lexer.Single: - Insert(tree, NewNode(KindSingle, nil)) - return parserMain, tree, nil - - case lexer.RangeOpen: - return parserRange, tree, nil - - case lexer.TermsOpen: - a := NewNode(KindAnyOf, nil) - Insert(tree, a) - - p := NewNode(KindPattern, nil) - Insert(a, p) - - return parserMain, p, nil - - case lexer.Separator: - p := NewNode(KindPattern, nil) - Insert(tree.Parent, p) - - return parserMain, p, nil - - case lexer.TermsClose: - return parserMain, tree.Parent.Parent, nil - - default: - return nil, tree, fmt.Errorf("unexpected token: %s", token) - } - } - return nil, tree, fmt.Errorf("unknown error") -} - -func parserRange(tree *Node, lex Lexer) (parseFn, *Node, error) { - var ( - not bool - lo rune - hi rune - chars string - ) - for { - token := lex.Next() - switch token.Type { - case lexer.EOF: - return nil, tree, errors.New("unexpected end") - - case lexer.Error: - return nil, tree, errors.New(token.Raw) - - case lexer.Not: - not = true - - case lexer.RangeLo: - r, w := utf8.DecodeRuneInString(token.Raw) - if len(token.Raw) > w { - return nil, tree, fmt.Errorf("unexpected length of lo character") - } - lo = r - - case lexer.RangeBetween: - // - - case lexer.RangeHi: - r, w := utf8.DecodeRuneInString(token.Raw) - if len(token.Raw) > w { - return nil, tree, fmt.Errorf("unexpected length of lo character") - } - - hi = r - - if hi < lo { - return nil, tree, fmt.Errorf("hi character '%s' should be greater than lo '%s'", string(hi), string(lo)) - } - - case lexer.Text: - chars = token.Raw - - case lexer.RangeClose: - isRange := lo != 0 && hi != 0 - isChars := chars != "" - - if isChars == isRange { - return nil, tree, fmt.Errorf("could not parse range") - } - - if isRange { - Insert(tree, NewNode(KindRange, Range{ - Lo: lo, - Hi: hi, - Not: not, - })) - } else { - Insert(tree, NewNode(KindList, List{ - Chars: chars, - Not: not, - })) - } - - return parserMain, tree, nil - } - } -} diff --git a/constraint/vendor/github.com/gobwas/glob/syntax/lexer.go b/constraint/vendor/github.com/gobwas/glob/syntax/lexer.go new file mode 100644 index 000000000..428608023 --- /dev/null +++ b/constraint/vendor/github.com/gobwas/glob/syntax/lexer.go @@ -0,0 +1,381 @@ +// Package syntax implements the lexer of the glob pattern syntax. The parser +// lives in package glob; the syntax itself is described at [glob.Compile]. +package syntax + +import ( + "bytes" + "fmt" + "slices" + "unicode/utf8" +) + +// TokenType tells the kind of a [Token]. +type TokenType int + +const ( + // EOF marks the end of the input; the lexer returns it repeatedly. + EOF TokenType = iota + // Error carries an error message in Token.Data; the lexer keeps + // returning it once it happened. Note that the lexer catches only the + // errors local to a token (an invalid UTF-8 sequence, a malformed + // character class): the structural ones, like an unclosed `{`, are for + // the parser to detect. + Error + // Text is a run of literal characters, with the escapes resolved. + Text + // Any is the `*` wildcard. + Any + // Super is the `**` wildcard. + Super + // Single is the `?` wildcard. + Single + // Not is the `!` right after the `[` of a character class. + Not + // TermSeparator is the `,` between the alternatives of a `{...}` group. + // Outside of a group a comma is a plain Text character. + TermSeparator + // RangeOpen and RangeClose are the `[` and `]` of a character class. + // Between them the lexer produces either a Text token (a set of + // characters, `[abc]`) or a RangeLo, RangeBetween, RangeHi triple (a + // range, `[a-c]`), possibly preceded by Not. + RangeOpen + RangeClose + RangeLo + RangeHi + RangeBetween + // TermsOpen and TermsClose are the `{` and `}` of an alternatives group. + TermsOpen + TermsClose +) + +func (tt TokenType) String() string { + switch tt { + case EOF: + return "eof" + case Error: + return "error" + case Text: + return "text" + case Any: + return "any" + case Super: + return "super" + case Single: + return "single" + case Not: + return "not" + case TermSeparator: + return "separator" + case RangeOpen: + return "range_open" + case RangeClose: + return "range_close" + case RangeLo: + return "range_lo" + case RangeHi: + return "range_hi" + case RangeBetween: + return "range_between" + case TermsOpen: + return "terms_open" + case TermsClose: + return "terms_close" + default: + return "" + } +} + +// Token is a lexeme of the pattern: its kind and the source text it was +// read from (or the error message for Error, the literal characters with +// the escapes resolved for Text). +type Token struct { + Type TokenType + Data string +} + +func (t Token) String() string { + return fmt.Sprintf("%v<%q>", t.Type, t.Data) +} + +const ( + char_any = '*' + char_comma = ',' + char_single = '?' + char_escape = '\\' + char_range_open = '[' + char_range_close = ']' + char_terms_open = '{' + char_terms_close = '}' + char_range_not = '!' + char_range_between = '-' +) + +var specials = []byte{ + char_any, + char_single, + char_escape, + char_range_open, + char_range_close, + char_terms_open, + char_terms_close, +} + +// IsSpecial reports whether c is a glob meta character, that is, one that +// [glob.QuoteMeta] escapes. Note that `,`, `!` and `-` are not among them: +// they are special only inside `{...}` and `[...]` respectively, which are. +func IsSpecial(c byte) bool { + return bytes.IndexByte(specials, c) != -1 +} + +type tokens []Token + +func (i *tokens) shift() (ret Token) { + ret = (*i)[0] + copy(*i, (*i)[1:]) + *i = (*i)[:len(*i)-1] + return +} + +func (i *tokens) push(v Token) { + *i = append(*i, v) +} + +func (i *tokens) empty() bool { + return len(*i) == 0 +} + +// eof is the end-of-input sentinel. It must not collide with any rune that +// can appear in a valid pattern -- note that U+0000 can. +const eof rune = -1 + +// Lexer splits a pattern into tokens; see [Lexer.Next]. +type Lexer struct { + data string + pos int + err error + + tokens tokens + termsLevel int + + lastRune rune + lastRuneSize int + hasRune bool +} + +// NewLexer returns a lexer over the source pattern. +func NewLexer(source string) *Lexer { + l := &Lexer{ + data: source, + tokens: tokens(make([]Token, 0, 4)), + } + return l +} + +// Offset returns the byte offset in the source the lexer stopped at, that +// is, the position right after the most recently returned token. +func (l *Lexer) Offset() int { + return l.pos +} + +// Next returns the next token. Once the input is over it returns EOF, and +// once an error happened it returns that Error, repeatedly. +func (l *Lexer) Next() Token { + if l.err != nil { + return Token{Error, l.err.Error()} + } + if !l.tokens.empty() { + return l.tokens.shift() + } + + l.fetchItem() + return l.Next() +} + +func (l *Lexer) peek() (r rune, w int) { + if l.pos == len(l.data) { + return eof, 0 + } + + r, w = utf8.DecodeRuneInString(l.data[l.pos:]) + if r == utf8.RuneError && w == 1 { + // An invalid encoding: a valid U+FFFD decodes at its width of 3. + l.errorf("invalid UTF-8 sequence") + r = eof + w = 0 + } + + return +} + +func (l *Lexer) read() rune { + if l.hasRune { + l.hasRune = false + l.seek(l.lastRuneSize) + return l.lastRune + } + + r, s := l.peek() + l.seek(s) + + l.lastRune = r + l.lastRuneSize = s + + return r +} + +func (l *Lexer) seek(w int) { + l.pos += w +} + +func (l *Lexer) unread() { + if l.hasRune { + l.errorf("could not unread rune") + return + } + l.seek(-l.lastRuneSize) + l.hasRune = true +} + +func (l *Lexer) errorf(f string, v ...any) { + l.err = fmt.Errorf(f, v...) +} + +func (l *Lexer) inTerms() bool { + return l.termsLevel > 0 +} + +func (l *Lexer) termsEnter() { + l.termsLevel++ +} + +func (l *Lexer) termsLeave() { + l.termsLevel-- +} + +var inTextBreakers = []rune{char_single, char_any, char_range_open, char_terms_open} +var inTermsBreakers = append(inTextBreakers, char_terms_close, char_comma) + +func (l *Lexer) fetchItem() { + r := l.read() + switch { + case r == eof: + l.tokens.push(Token{EOF, ""}) + + case r == char_terms_open: + l.termsEnter() + l.tokens.push(Token{TermsOpen, string(r)}) + + case r == char_comma && l.inTerms(): + l.tokens.push(Token{TermSeparator, string(r)}) + + case r == char_terms_close && l.inTerms(): + l.tokens.push(Token{TermsClose, string(r)}) + l.termsLeave() + + case r == char_range_open: + l.tokens.push(Token{RangeOpen, string(r)}) + l.fetchRange() + + case r == char_single: + l.tokens.push(Token{Single, string(r)}) + + case r == char_any: + if l.read() == char_any { + l.tokens.push(Token{Super, string(r) + string(r)}) + } else { + l.unread() + l.tokens.push(Token{Any, string(r)}) + } + + default: + l.unread() + + var breakers []rune + if l.inTerms() { + breakers = inTermsBreakers + } else { + breakers = inTextBreakers + } + l.fetchText(breakers) + } +} + +func (l *Lexer) fetchRange() { + var wantHi bool + var wantClose bool + var seenNot bool + for { + r := l.read() + if r == eof { + l.errorf("unexpected end of input") + return + } + + if wantClose { + if r != char_range_close { + l.errorf("expected close range character") + } else { + l.tokens.push(Token{RangeClose, string(r)}) + } + return + } + + if wantHi { + l.tokens.push(Token{RangeHi, string(r)}) + wantClose = true + continue + } + + if !seenNot && r == char_range_not { + l.tokens.push(Token{Not, string(r)}) + seenNot = true + continue + } + + if n, w := l.peek(); n == char_range_between { + l.seek(w) + l.tokens.push(Token{RangeLo, string(r)}) + l.tokens.push(Token{RangeBetween, string(n)}) + wantHi = true + continue + } + + l.unread() // unread first peek and fetch as text + l.fetchText([]rune{char_range_close}) + wantClose = true + } +} + +func (l *Lexer) fetchText(breakers []rune) { + var data []rune + var escaped bool + +reading: + for { + r := l.read() + if r == eof { + if escaped { + l.errorf("trailing backslash") + } + break + } + + if !escaped { + if r == char_escape { + escaped = true + continue + } + if slices.Index(breakers, r) != -1 { + l.unread() + break reading + } + } + + escaped = false + data = append(data, r) + } + + if len(data) > 0 { + l.tokens.push(Token{Text, string(data)}) + } +} diff --git a/constraint/vendor/github.com/gobwas/glob/syntax/lexer/lexer.go b/constraint/vendor/github.com/gobwas/glob/syntax/lexer/lexer.go deleted file mode 100644 index a1c8d1962..000000000 --- a/constraint/vendor/github.com/gobwas/glob/syntax/lexer/lexer.go +++ /dev/null @@ -1,273 +0,0 @@ -package lexer - -import ( - "bytes" - "fmt" - "github.com/gobwas/glob/util/runes" - "unicode/utf8" -) - -const ( - char_any = '*' - char_comma = ',' - char_single = '?' - char_escape = '\\' - char_range_open = '[' - char_range_close = ']' - char_terms_open = '{' - char_terms_close = '}' - char_range_not = '!' - char_range_between = '-' -) - -var specials = []byte{ - char_any, - char_single, - char_escape, - char_range_open, - char_range_close, - char_terms_open, - char_terms_close, -} - -func Special(c byte) bool { - return bytes.IndexByte(specials, c) != -1 -} - -type tokens []Token - -func (i *tokens) shift() (ret Token) { - ret = (*i)[0] - copy(*i, (*i)[1:]) - *i = (*i)[:len(*i)-1] - return -} - -func (i *tokens) push(v Token) { - *i = append(*i, v) -} - -func (i *tokens) empty() bool { - return len(*i) == 0 -} - -var eof rune = 0 - -type lexer struct { - data string - pos int - err error - - tokens tokens - termsLevel int - - lastRune rune - lastRuneSize int - hasRune bool -} - -func NewLexer(source string) *lexer { - l := &lexer{ - data: source, - tokens: tokens(make([]Token, 0, 4)), - } - return l -} - -func (l *lexer) Next() Token { - if l.err != nil { - return Token{Error, l.err.Error()} - } - if !l.tokens.empty() { - return l.tokens.shift() - } - - l.fetchItem() - return l.Next() -} - -func (l *lexer) peek() (r rune, w int) { - if l.pos == len(l.data) { - return eof, 0 - } - - r, w = utf8.DecodeRuneInString(l.data[l.pos:]) - if r == utf8.RuneError { - l.errorf("could not read rune") - r = eof - w = 0 - } - - return -} - -func (l *lexer) read() rune { - if l.hasRune { - l.hasRune = false - l.seek(l.lastRuneSize) - return l.lastRune - } - - r, s := l.peek() - l.seek(s) - - l.lastRune = r - l.lastRuneSize = s - - return r -} - -func (l *lexer) seek(w int) { - l.pos += w -} - -func (l *lexer) unread() { - if l.hasRune { - l.errorf("could not unread rune") - return - } - l.seek(-l.lastRuneSize) - l.hasRune = true -} - -func (l *lexer) errorf(f string, v ...interface{}) { - l.err = fmt.Errorf(f, v...) -} - -func (l *lexer) inTerms() bool { - return l.termsLevel > 0 -} - -func (l *lexer) termsEnter() { - l.termsLevel++ -} - -func (l *lexer) termsLeave() { - l.termsLevel-- -} - -var inTextBreakers = []rune{char_single, char_any, char_range_open, char_terms_open} -var inTermsBreakers = append(inTextBreakers, char_terms_close, char_comma) - -func (l *lexer) fetchItem() { - r := l.read() - switch { - case r == eof: - l.tokens.push(Token{EOF, ""}) - - case r == char_terms_open: - l.termsEnter() - l.tokens.push(Token{TermsOpen, string(r)}) - - case r == char_comma && l.inTerms(): - l.tokens.push(Token{Separator, string(r)}) - - case r == char_terms_close && l.inTerms(): - l.tokens.push(Token{TermsClose, string(r)}) - l.termsLeave() - - case r == char_range_open: - l.tokens.push(Token{RangeOpen, string(r)}) - l.fetchRange() - - case r == char_single: - l.tokens.push(Token{Single, string(r)}) - - case r == char_any: - if l.read() == char_any { - l.tokens.push(Token{Super, string(r) + string(r)}) - } else { - l.unread() - l.tokens.push(Token{Any, string(r)}) - } - - default: - l.unread() - - var breakers []rune - if l.inTerms() { - breakers = inTermsBreakers - } else { - breakers = inTextBreakers - } - l.fetchText(breakers) - } -} - -func (l *lexer) fetchRange() { - var wantHi bool - var wantClose bool - var seenNot bool - for { - r := l.read() - if r == eof { - l.errorf("unexpected end of input") - return - } - - if wantClose { - if r != char_range_close { - l.errorf("expected close range character") - } else { - l.tokens.push(Token{RangeClose, string(r)}) - } - return - } - - if wantHi { - l.tokens.push(Token{RangeHi, string(r)}) - wantClose = true - continue - } - - if !seenNot && r == char_range_not { - l.tokens.push(Token{Not, string(r)}) - seenNot = true - continue - } - - if n, w := l.peek(); n == char_range_between { - l.seek(w) - l.tokens.push(Token{RangeLo, string(r)}) - l.tokens.push(Token{RangeBetween, string(n)}) - wantHi = true - continue - } - - l.unread() // unread first peek and fetch as text - l.fetchText([]rune{char_range_close}) - wantClose = true - } -} - -func (l *lexer) fetchText(breakers []rune) { - var data []rune - var escaped bool - -reading: - for { - r := l.read() - if r == eof { - break - } - - if !escaped { - if r == char_escape { - escaped = true - continue - } - - if runes.IndexRune(breakers, r) != -1 { - l.unread() - break reading - } - } - - escaped = false - data = append(data, r) - } - - if len(data) > 0 { - l.tokens.push(Token{Text, string(data)}) - } -} diff --git a/constraint/vendor/github.com/gobwas/glob/syntax/lexer/token.go b/constraint/vendor/github.com/gobwas/glob/syntax/lexer/token.go deleted file mode 100644 index 2797c4e83..000000000 --- a/constraint/vendor/github.com/gobwas/glob/syntax/lexer/token.go +++ /dev/null @@ -1,88 +0,0 @@ -package lexer - -import "fmt" - -type TokenType int - -const ( - EOF TokenType = iota - Error - Text - Char - Any - Super - Single - Not - Separator - RangeOpen - RangeClose - RangeLo - RangeHi - RangeBetween - TermsOpen - TermsClose -) - -func (tt TokenType) String() string { - switch tt { - case EOF: - return "eof" - - case Error: - return "error" - - case Text: - return "text" - - case Char: - return "char" - - case Any: - return "any" - - case Super: - return "super" - - case Single: - return "single" - - case Not: - return "not" - - case Separator: - return "separator" - - case RangeOpen: - return "range_open" - - case RangeClose: - return "range_close" - - case RangeLo: - return "range_lo" - - case RangeHi: - return "range_hi" - - case RangeBetween: - return "range_between" - - case TermsOpen: - return "terms_open" - - case TermsClose: - return "terms_close" - - default: - return "undef" - } -} - -type Token struct { - Type TokenType - Raw string -} - -func (t Token) String() string { - return fmt.Sprintf("%v<%q>", t.Type, t.Raw) -} diff --git a/constraint/vendor/github.com/gobwas/glob/syntax/syntax.go b/constraint/vendor/github.com/gobwas/glob/syntax/syntax.go deleted file mode 100644 index 1d168b148..000000000 --- a/constraint/vendor/github.com/gobwas/glob/syntax/syntax.go +++ /dev/null @@ -1,14 +0,0 @@ -package syntax - -import ( - "github.com/gobwas/glob/syntax/ast" - "github.com/gobwas/glob/syntax/lexer" -) - -func Parse(s string) (*ast.Node, error) { - return ast.Parse(lexer.NewLexer(s)) -} - -func Special(b byte) bool { - return lexer.Special(b) -} diff --git a/constraint/vendor/github.com/gobwas/glob/util/runes/runes.go b/constraint/vendor/github.com/gobwas/glob/util/runes/runes.go deleted file mode 100644 index a72355641..000000000 --- a/constraint/vendor/github.com/gobwas/glob/util/runes/runes.go +++ /dev/null @@ -1,154 +0,0 @@ -package runes - -func Index(s, needle []rune) int { - ls, ln := len(s), len(needle) - - switch { - case ln == 0: - return 0 - case ln == 1: - return IndexRune(s, needle[0]) - case ln == ls: - if Equal(s, needle) { - return 0 - } - return -1 - case ln > ls: - return -1 - } - -head: - for i := 0; i < ls && ls-i >= ln; i++ { - for y := 0; y < ln; y++ { - if s[i+y] != needle[y] { - continue head - } - } - - return i - } - - return -1 -} - -func LastIndex(s, needle []rune) int { - ls, ln := len(s), len(needle) - - switch { - case ln == 0: - if ls == 0 { - return 0 - } - return ls - case ln == 1: - return IndexLastRune(s, needle[0]) - case ln == ls: - if Equal(s, needle) { - return 0 - } - return -1 - case ln > ls: - return -1 - } - -head: - for i := ls - 1; i >= 0 && i >= ln; i-- { - for y := ln - 1; y >= 0; y-- { - if s[i-(ln-y-1)] != needle[y] { - continue head - } - } - - return i - ln + 1 - } - - return -1 -} - -// IndexAny returns the index of the first instance of any Unicode code point -// from chars in s, or -1 if no Unicode code point from chars is present in s. -func IndexAny(s, chars []rune) int { - if len(chars) > 0 { - for i, c := range s { - for _, m := range chars { - if c == m { - return i - } - } - } - } - return -1 -} - -func Contains(s, needle []rune) bool { - return Index(s, needle) >= 0 -} - -func Max(s []rune) (max rune) { - for _, r := range s { - if r > max { - max = r - } - } - - return -} - -func Min(s []rune) rune { - min := rune(-1) - for _, r := range s { - if min == -1 { - min = r - continue - } - - if r < min { - min = r - } - } - - return min -} - -func IndexRune(s []rune, r rune) int { - for i, c := range s { - if c == r { - return i - } - } - return -1 -} - -func IndexLastRune(s []rune, r rune) int { - for i := len(s) - 1; i >= 0; i-- { - if s[i] == r { - return i - } - } - - return -1 -} - -func Equal(a, b []rune) bool { - if len(a) == len(b) { - for i := 0; i < len(a); i++ { - if a[i] != b[i] { - return false - } - } - - return true - } - - return false -} - -// HasPrefix tests whether the string s begins with prefix. -func HasPrefix(s, prefix []rune) bool { - return len(s) >= len(prefix) && Equal(s[0:len(prefix)], prefix) -} - -// HasSuffix tests whether the string s ends with suffix. -func HasSuffix(s, suffix []rune) bool { - return len(s) >= len(suffix) && Equal(s[len(s)-len(suffix):], suffix) -} diff --git a/constraint/vendor/github.com/gobwas/glob/util/strings/strings.go b/constraint/vendor/github.com/gobwas/glob/util/strings/strings.go deleted file mode 100644 index e8ee1920b..000000000 --- a/constraint/vendor/github.com/gobwas/glob/util/strings/strings.go +++ /dev/null @@ -1,39 +0,0 @@ -package strings - -import ( - "strings" - "unicode/utf8" -) - -func IndexAnyRunes(s string, rs []rune) int { - for _, r := range rs { - if i := strings.IndexRune(s, r); i != -1 { - return i - } - } - - return -1 -} - -func LastIndexAnyRunes(s string, rs []rune) int { - for _, r := range rs { - i := -1 - if 0 <= r && r < utf8.RuneSelf { - i = strings.LastIndexByte(s, byte(r)) - } else { - sub := s - for len(sub) > 0 { - j := strings.IndexRune(s, r) - if j == -1 { - break - } - i = j - sub = sub[i+1:] - } - } - if i != -1 { - return i - } - } - return -1 -} diff --git a/constraint/vendor/github.com/lestrrat-go/dsig/.golangci.yml b/constraint/vendor/github.com/lestrrat-go/dsig/.golangci.yml new file mode 100644 index 000000000..8cde331d8 --- /dev/null +++ b/constraint/vendor/github.com/lestrrat-go/dsig/.golangci.yml @@ -0,0 +1,14 @@ +version: "2" + +# The linter set is golangci-lint's default. The point of this file is the +# formatters block below: without it nothing checked gofmt, and the drift that +# allowed put a closing code fence on the same line as a line of Go, which +# broke half of README.md once the doc generator started running. +formatters: + enable: + - gofmt + +issues: + # Report every unformatted file. The default caps repeats of one message at + # three, which would hide the tail of exactly this kind of sweep. + max-same-issues: 0 diff --git a/constraint/vendor/github.com/lestrrat-go/dsig/Changes b/constraint/vendor/github.com/lestrrat-go/dsig/Changes index 9e913f60b..7264f1801 100644 --- a/constraint/vendor/github.com/lestrrat-go/dsig/Changes +++ b/constraint/vendor/github.com/lestrrat-go/dsig/Changes @@ -1,6 +1,24 @@ Changes ======= +v1.4.0 20 Aug 2026 + * Add ML-DSA (FIPS 204) support: the `MLDSA44`, `MLDSA65`, and `MLDSA87` + algorithms, the `SignMLDSA()` / `VerifyMLDSA()` primitives, and a new + `MLDSAFamily` algorithm family. ML-DSA requires Go 1.27 or later, which is + when `crypto/mldsa` joins the standard library; on earlier toolchains the + constants are not declared and the algorithms are not registered. + + An ML-DSA key carries its own parameter set, so naming an algorithm that + disagrees with the key is an error on both the sign and verify paths. + `SignMLDSA()` takes a `crypto.SignerOpts` so that both signing modes stay + reachable: an `*mldsa.Options` supplies a context string, and + `crypto.MLDSAMu` signs a pre-hashed mu message representative. + `VerifyMLDSA()` takes an `*mldsa.Options` because verification has a single + mode. `SignDigest()` and `VerifyDigest()` return an error for ML-DSA, as + they already do for EdDSA. + + * The minimum Go version is now 1.25. + v1.3.0 13 Apr 2026 * Add `SignWithOpts()` and `VerifyWithOpts()`, which thread an optional `crypto.SignerOpts` through to the underlying signer. For built-in @@ -58,4 +76,4 @@ v1.1.0 2 Apr 2026 algorithm name. Use `UnregisterAlgorithm()` first if you need to replace it. v1.0.0 - 18 Aug 2025 - * Initial release \ No newline at end of file + * Initial release diff --git a/constraint/vendor/github.com/lestrrat-go/dsig/README.md b/constraint/vendor/github.com/lestrrat-go/dsig/README.md index b52b998f8..55b75963e 100644 --- a/constraint/vendor/github.com/lestrrat-go/dsig/README.md +++ b/constraint/vendor/github.com/lestrrat-go/dsig/README.md @@ -1,4 +1,4 @@ -# github.com/lestrrat-go/dsig [![CI](https://github.com/lestrrat-go/dsig/actions/workflows/ci.yml/badge.svg)](https://github.com/lestrrat-go/dsig/actions/workflows/ci.yml) [![Go Reference](https://pkg.go.dev/badge/github.com/lestrrat-go/dsig.svg)](https://pkg.go.dev/github.com/lestrrat-go/dsig) [![codecov.io](https://codecov.io/github/lestrrat-go/dsig/coverage.svg?branch=v1)](https://codecov.io/github/lestrrat-go/dsig?branch=v1) +# github.com/lestrrat-go/dsig [![CI](https://github.com/lestrrat-go/dsig/actions/workflows/ci.yml/badge.svg)](https://github.com/lestrrat-go/dsig/actions/workflows/ci.yml) [![Go Reference](https://pkg.go.dev/badge/github.com/lestrrat-go/dsig.svg)](https://pkg.go.dev/github.com/lestrrat-go/dsig) Go module providing low-level digital signature operations. @@ -9,6 +9,7 @@ While there are many standards for generating and verifying digital signatures, * RSA signatures (PKCS1v15 and PSS) * ECDSA signatures (P-256, P-384, P-521) * EdDSA signatures (Ed25519, Ed448) +* ML-DSA post-quantum signatures (ML-DSA-44, ML-DSA-65, ML-DSA-87), on Go 1.27 and later * HMAC signatures (SHA-256, SHA-384, SHA-512) * Support for crypto.Signer interface * Custom algorithm registration via `Signer`/`Verifier` interfaces @@ -143,6 +144,53 @@ source: [examples/dsig_readme_example_test.go](https://github.com/lestrrat-go/ds | `ECDSAWithP384AndSHA384` | ECDSA using P-384 and SHA-384 | *ecdsa.PrivateKey / *ecdsa.PublicKey | | `ECDSAWithP521AndSHA512` | ECDSA using P-521 and SHA-512 | *ecdsa.PrivateKey / *ecdsa.PublicKey | | `EdDSA` | EdDSA using Ed25519 or Ed448 | ed25519.PrivateKey / ed25519.PublicKey | +| `MLDSA44` | ML-DSA-44 (FIPS 204), NIST level 2 | *mldsa.PrivateKey / *mldsa.PublicKey | +| `MLDSA65` | ML-DSA-65 (FIPS 204), NIST level 3 | *mldsa.PrivateKey / *mldsa.PublicKey | +| `MLDSA87` | ML-DSA-87 (FIPS 204), NIST level 5 | *mldsa.PrivateKey / *mldsa.PublicKey | + +The three ML-DSA algorithms need Go 1.27 or later, which is when `crypto/mldsa` +joins the standard library. On earlier toolchains the constants are not declared +and the algorithms are not registered. + +Name the constant that matches the key you generated. A key knows its own +parameter set, and naming a different one is an error, so a key cannot be used +under a weaker set by accident: + +```go +sk, _ := mldsa.GenerateKey(mldsa.MLDSA65()) + +sig, _ := dsig.Sign(sk, dsig.MLDSA65, payload, nil) +err := dsig.Verify(sk.PublicKey(), dsig.MLDSA65, payload, sig) + +_, err = dsig.Sign(sk, dsig.MLDSA44, payload, nil) +// dsig.SignWithOpts: ML-DSA parameter set mismatch: key is ML-DSA-65, algorithm is ML-DSA-44 +``` + +## ML-DSA context strings + +ML-DSA can mix a caller-chosen string into the signature. Give each job a +different context and one key can sign for several of them without a signature +made for one job verifying as another, so a login token cannot be presented as +a file receipt. + +Signing and verifying must use the same context. A verifier that supplies the +wrong one, or none at all, sees an ordinary invalid signature and cannot tell +which mistake was made: + +```go +login := &mldsa.Options{Context: "my-app/login-token"} +receipt := &mldsa.Options{Context: "my-app/file-receipt"} + +sig, _ := dsig.SignWithOpts(sk, dsig.MLDSA65, payload, login, nil) + +err := dsig.VerifyWithOpts(sk.PublicKey(), dsig.MLDSA65, payload, sig, login) +// nil + +err = dsig.VerifyWithOpts(sk.PublicKey(), dsig.MLDSA65, payload, sig, receipt) +// mldsa: invalid signature +``` + +A context is at most 255 bytes, and it is empty when opts is nil. # Description @@ -160,4 +208,4 @@ Please include tests that exercise your changes. # Related Libraries -* [github.com/lestrrat-go/jwx](https://github.com/lestrrat-go/jwx) - JOSE (JWA/JWE/JWK/JWS/JWT) implementation \ No newline at end of file +* [github.com/lestrrat-go/jwx](https://github.com/lestrrat-go/jwx) - JOSE (JWA/JWE/JWK/JWS/JWT) implementation diff --git a/constraint/vendor/github.com/lestrrat-go/dsig/algorithms.go b/constraint/vendor/github.com/lestrrat-go/dsig/algorithms.go index 0895c6476..3cf93b0c7 100644 --- a/constraint/vendor/github.com/lestrrat-go/dsig/algorithms.go +++ b/constraint/vendor/github.com/lestrrat-go/dsig/algorithms.go @@ -34,4 +34,4 @@ const ( // EdDSA signature algorithms // These use Edwards-curve Digital Signature Algorithm (supports Ed25519 and Ed448) EdDSA = "EDDSA" -) \ No newline at end of file +) diff --git a/constraint/vendor/github.com/lestrrat-go/dsig/dsig.go b/constraint/vendor/github.com/lestrrat-go/dsig/dsig.go index 466797b0a..ee278311b 100644 --- a/constraint/vendor/github.com/lestrrat-go/dsig/dsig.go +++ b/constraint/vendor/github.com/lestrrat-go/dsig/dsig.go @@ -28,6 +28,12 @@ const ( ECDSA EdDSAFamily Custom + // MLDSAFamily covers the ML-DSA parameter sets. It is deliberately not + // Custom: Custom means this library knows nothing about the algorithm, + // which would be false here and misleads callers that switch on Family. + // + // It sits after Custom so the values earlier releases assigned stay put. + MLDSAFamily maxFamily ) @@ -44,6 +50,8 @@ func (f Family) String() string { return "EdDSA" case Custom: return "Custom" + case MLDSAFamily: + return "ML-DSA" default: return "InvalidFamily" } @@ -153,13 +161,17 @@ func RegisterAlgorithm(name string, info AlgorithmInfo) error { } case EdDSAFamily: // EdDSA metadata is optional for now - case Custom: + case Custom, MLDSAFamily: + // Both families carry their implementation in Meta. The other families + // put passive metadata there. For ML-DSA this is forced: crypto/mldsa + // exists only from Go 1.27, so the algorithm cannot be described by a + // value type this file could name. _, isSigner := info.Meta.(Signer) _, isSignerWithOpts := info.Meta.(SignerWithOpts) _, isVerifier := info.Meta.(Verifier) _, isVerifierWithOpts := info.Meta.(VerifierWithOpts) if !isSigner && !isSignerWithOpts && !isVerifier && !isVerifierWithOpts { - return fmt.Errorf("custom algorithm %s: Meta must implement Signer, SignerWithOpts, Verifier, or VerifierWithOpts", name) + return fmt.Errorf("%s algorithm %s: Meta must implement Signer, SignerWithOpts, Verifier, or VerifierWithOpts", info.Family, name) } default: return fmt.Errorf("unsupported algorithm family %s for algorithm %s", info.Family, name) @@ -297,4 +309,3 @@ func init() { builtinAlgorithms[name] = struct{}{} } } - diff --git a/constraint/vendor/github.com/lestrrat-go/dsig/ecdsa.go b/constraint/vendor/github.com/lestrrat-go/dsig/ecdsa.go index 570b9ae07..9da4ac244 100644 --- a/constraint/vendor/github.com/lestrrat-go/dsig/ecdsa.go +++ b/constraint/vendor/github.com/lestrrat-go/dsig/ecdsa.go @@ -12,7 +12,6 @@ import ( "github.com/lestrrat-go/dsig/internal/ecutil" ) - func ecdsaGetSignerKey(key any) (*ecdsa.PrivateKey, crypto.Signer, bool, error) { cs, isCryptoSigner := key.(crypto.Signer) if isCryptoSigner { diff --git a/constraint/vendor/github.com/lestrrat-go/dsig/mldsa.go b/constraint/vendor/github.com/lestrrat-go/dsig/mldsa.go new file mode 100644 index 000000000..218204774 --- /dev/null +++ b/constraint/vendor/github.com/lestrrat-go/dsig/mldsa.go @@ -0,0 +1,193 @@ +//go:build go1.27 + +package dsig + +import ( + "crypto" + "crypto/mldsa" + "fmt" + "io" +) + +// ML-DSA signature algorithms, the post-quantum scheme specified in FIPS 204. +// The three names identify the three parameter sets, which differ in security +// level and in key and signature sizes. +// +// These names match what crypto/mldsa's Parameters.String reports, so the +// parameter set a key carries can be compared against the algorithm name +// directly. +// +// ML-DSA is available only when dsig is built with Go 1.27 or later, which is +// when crypto/mldsa becomes part of the standard library. On earlier +// toolchains these algorithms are not registered and not declared. +const ( + MLDSA44 = "ML-DSA-44" + MLDSA65 = "ML-DSA-65" + MLDSA87 = "ML-DSA-87" +) + +func init() { + for _, params := range []mldsa.Parameters{mldsa.MLDSA44(), mldsa.MLDSA65(), mldsa.MLDSA87()} { + name := params.String() + if err := RegisterAlgorithm(name, AlgorithmInfo{ + Family: MLDSAFamily, + Meta: &mldsaAlgorithm{params: params}, + }); err != nil { + panic(fmt.Sprintf("failed to register algorithm %s: %v", name, err)) + } + builtinAlgorithms[name] = struct{}{} + } +} + +// SignMLDSA generates an ML-DSA signature for the given payload. +// +// opts may be nil, which signs payload directly with no context. Pass an +// *[mldsa.Options] to supply a domain-separation context, which [VerifyMLDSA] +// then requires to match. +// +// opts is a [crypto.SignerOpts] so that both of ML-DSA's signing modes stay +// expressible. Passing [crypto.MLDSAMu] means payload holds a pre-hashed μ +// message representative. That mode is a shortcut for callers who already have +// μ, and it produces an ordinary signature; [VerifyMLDSA] checks it against the +// original message, and the verify side needs no counterpart. +// +// crypto/mldsa rejects any other opts value, so a mistaken type cannot be +// silently downgraded to a context-free signature. +func SignMLDSA(key *mldsa.PrivateKey, payload []byte, opts crypto.SignerOpts) ([]byte, error) { + if key == nil { + return nil, fmt.Errorf(`dsig.SignMLDSA: key cannot be nil`) + } + // The io.Reader argument is ignored by crypto/mldsa; signing draws its own + // randomness. SignDeterministic is the variant that draws none. + return key.Sign(nil, payload, opts) +} + +// VerifyMLDSA verifies an ML-DSA signature for the given payload. +// +// opts may be nil. It must carry the same Context that was used to produce the +// signature, otherwise verification fails. +// +// Verification has a single mode, so opts is a concrete *[mldsa.Options]. μ is +// derived from the message, so a signature made from a pre-hashed μ verifies +// here against the original message. +func VerifyMLDSA(key *mldsa.PublicKey, payload, signature []byte, opts *mldsa.Options) error { + if key == nil { + return fmt.Errorf(`dsig.VerifyMLDSA: key cannot be nil`) + } + return mldsa.Verify(key, payload, signature, opts) +} + +// mldsaAlgorithm is the Custom-family adapter that binds one ML-DSA parameter +// set to the registry. It carries the parameter set so that every operation can +// check the caller's key against the algorithm that was asked for. +type mldsaAlgorithm struct { + params mldsa.Parameters +} + +// requireMLDSAParams reports whether a caller-supplied key belongs to the +// parameter set this algorithm was registered for. crypto/mldsa's Parameters is +// a comparable value naming one of the three FIPS 204 sets, so a plain +// comparison suffices. +// +// The check matters because the key owns the parameter set, and the call only +// names one. Without it, an ML-DSA-65 key would happily produce and verify +// ML-DSA-65 signatures while the caller believed it had selected ML-DSA-44. +// Anything that reads the algorithm name to decide a post-quantum security +// level would then be misled, so the mismatch is an error. +func (a *mldsaAlgorithm) requireMLDSAParams(got mldsa.Parameters) error { + if got != a.params { + return fmt.Errorf(`ML-DSA parameter set mismatch: key is %s, algorithm is %s`, got, a.params) + } + return nil +} + +func (a *mldsaAlgorithm) privateKey(key any) (*mldsa.PrivateKey, error) { + sk, ok := key.(*mldsa.PrivateKey) + if !ok { + return nil, fmt.Errorf(`expected *mldsa.PrivateKey, got %T`, key) + } + if err := a.requireMLDSAParams(sk.PublicKey().Parameters()); err != nil { + return nil, err + } + return sk, nil +} + +// publicKey narrows the key types the verify surface accepts. A private key is +// allowed so callers holding only one half do not have to unwrap it themselves. +func (a *mldsaAlgorithm) publicKey(key any) (*mldsa.PublicKey, error) { + var pk *mldsa.PublicKey + switch k := key.(type) { + case *mldsa.PublicKey: + pk = k + case *mldsa.PrivateKey: + pk = k.PublicKey() + default: + return nil, fmt.Errorf(`expected *mldsa.PublicKey or *mldsa.PrivateKey, got %T`, key) + } + if err := a.requireMLDSAParams(pk.Parameters()); err != nil { + return nil, err + } + return pk, nil +} + +// mldsaOptions narrows a crypto.SignerOpts to the concrete type crypto/mldsa +// accepts. A non-nil value of any other type is an error. Dropping it would let +// a caller believe their Context was in force while the operation actually ran +// with an empty context, which is a signature substitution vector for schemes +// that rely on domain separation. +func mldsaOptions(opts crypto.SignerOpts) (*mldsa.Options, error) { + if opts == nil { + return nil, nil + } + mldsaOpts, ok := opts.(*mldsa.Options) + if !ok { + return nil, fmt.Errorf(`expected *mldsa.Options, got %T`, opts) + } + return mldsaOpts, nil +} + +func (a *mldsaAlgorithm) Sign(key any, payload []byte, _ io.Reader) ([]byte, error) { + sk, err := a.privateKey(key) + if err != nil { + return nil, fmt.Errorf(`dsig.Sign: %w`, err) + } + return SignMLDSA(sk, payload, nil) +} + +// SignWithOpts implements [SignerWithOpts], forwarding an *mldsa.Options +// Context to crypto/mldsa. +func (a *mldsaAlgorithm) SignWithOpts(key any, payload []byte, opts crypto.SignerOpts, _ io.Reader) ([]byte, error) { + sk, err := a.privateKey(key) + if err != nil { + return nil, fmt.Errorf(`dsig.SignWithOpts: %w`, err) + } + // Validated but deliberately not narrowed. SignMLDSA takes a + // crypto.SignerOpts, so converting to a typed nil here would hand + // crypto/mldsa a non-nil interface holding a nil pointer. + if _, err := mldsaOptions(opts); err != nil { + return nil, fmt.Errorf(`dsig.SignWithOpts: %w`, err) + } + return SignMLDSA(sk, payload, opts) +} + +func (a *mldsaAlgorithm) Verify(key any, payload, signature []byte) error { + pk, err := a.publicKey(key) + if err != nil { + return fmt.Errorf(`dsig.Verify: %w`, err) + } + return VerifyMLDSA(pk, payload, signature, nil) +} + +// VerifyWithOpts implements [VerifierWithOpts]. See [SignerWithOpts] for the +// rationale on rejecting a foreign opts type. +func (a *mldsaAlgorithm) VerifyWithOpts(key any, payload, signature []byte, opts crypto.SignerOpts) error { + pk, err := a.publicKey(key) + if err != nil { + return fmt.Errorf(`dsig.VerifyWithOpts: %w`, err) + } + mldsaOpts, err := mldsaOptions(opts) + if err != nil { + return fmt.Errorf(`dsig.VerifyWithOpts: %w`, err) + } + return VerifyMLDSA(pk, payload, signature, mldsaOpts) +} diff --git a/constraint/vendor/github.com/lestrrat-go/dsig/sign.go b/constraint/vendor/github.com/lestrrat-go/dsig/sign.go index 6f39f77ff..7d8b9340b 100644 --- a/constraint/vendor/github.com/lestrrat-go/dsig/sign.go +++ b/constraint/vendor/github.com/lestrrat-go/dsig/sign.go @@ -53,8 +53,8 @@ func SignWithOpts(key any, alg string, payload []byte, opts crypto.SignerOpts, r return dispatchECDSASign(key, info, payload, rr) case EdDSAFamily: return dispatchEdDSASign(key, info, payload, rr) - case Custom: - return dispatchCustomSign(key, info, payload, opts, rr) + case Custom, MLDSAFamily: + return dispatchMetaSign(key, info, payload, opts, rr) default: return nil, fmt.Errorf(`dsig.SignWithOpts: unsupported signature family %q`, info.Family) } @@ -124,7 +124,7 @@ func dispatchECDSASign(key any, info AlgorithmInfo, payload []byte, rr io.Reader return SignECDSA(privkey, payload, meta.Hash, rr) } -func dispatchCustomSign(key any, info AlgorithmInfo, payload []byte, opts crypto.SignerOpts, rr io.Reader) ([]byte, error) { +func dispatchMetaSign(key any, info AlgorithmInfo, payload []byte, opts crypto.SignerOpts, rr io.Reader) ([]byte, error) { if signer, ok := info.Meta.(SignerWithOpts); ok { return signer.SignWithOpts(key, payload, opts, rr) } @@ -175,6 +175,11 @@ func SignDigest(key any, alg string, digest []byte, rr io.Reader) ([]byte, error return nil, fmt.Errorf(`dsig.SignDigest: EdDSA does not support digest-based signing`) case Custom: return nil, fmt.Errorf(`dsig.SignDigest: custom algorithms do not support digest-based signing`) + case MLDSAFamily: + // ML-DSA's pre-hashed mode takes a mu representative. That is a + // different thing from a plain digest; pass mu to Sign with + // crypto.MLDSAMu. + return nil, fmt.Errorf(`dsig.SignDigest: ML-DSA does not support digest-based signing`) default: return nil, fmt.Errorf(`dsig.SignDigest: unsupported signature family %q`, info.Family) } @@ -242,4 +247,3 @@ func dispatchECDSASignDigest(key any, info AlgorithmInfo, digest []byte, rr io.R } return PackECDSASignature(r, s, privkey.Curve.Params().BitSize) } - diff --git a/constraint/vendor/github.com/lestrrat-go/dsig/verify.go b/constraint/vendor/github.com/lestrrat-go/dsig/verify.go index 8a3ddb6db..5999e505c 100644 --- a/constraint/vendor/github.com/lestrrat-go/dsig/verify.go +++ b/constraint/vendor/github.com/lestrrat-go/dsig/verify.go @@ -47,8 +47,8 @@ func VerifyWithOpts(key any, alg string, payload, signature []byte, opts crypto. return dispatchECDSAVerify(key, info, payload, signature) case EdDSAFamily: return dispatchEdDSAVerify(key, info, payload, signature) - case Custom: - return dispatchCustomVerify(key, info, payload, signature, opts) + case Custom, MLDSAFamily: + return dispatchMetaVerify(key, info, payload, signature, opts) default: return fmt.Errorf(`dsig.VerifyWithOpts: unsupported signature family %q`, info.Family) } @@ -93,6 +93,9 @@ func VerifyDigest(key any, alg string, digest, signature []byte) error { // TODO: a DigestVerifier interface (optional, checked here) would let // custom algorithms opt in to digest-based verification. return fmt.Errorf(`dsig.VerifyDigest: custom algorithms do not support digest-based verification`) + case MLDSAFamily: + // mu is derived from the message, so there is no digest to supply here. + return fmt.Errorf(`dsig.VerifyDigest: ML-DSA does not support digest-based verification`) default: return fmt.Errorf(`dsig.VerifyDigest: unsupported signature family %q`, info.Family) } @@ -227,7 +230,7 @@ func dispatchEdDSAVerify(key any, _ AlgorithmInfo, payload, signature []byte) er return VerifyEdDSA(pubkey, payload, signature) } -func dispatchCustomVerify(key any, info AlgorithmInfo, payload, signature []byte, opts crypto.SignerOpts) error { +func dispatchMetaVerify(key any, info AlgorithmInfo, payload, signature []byte, opts crypto.SignerOpts) error { if verifier, ok := info.Meta.(VerifierWithOpts); ok { return verifier.VerifyWithOpts(key, payload, signature, opts) } diff --git a/constraint/vendor/github.com/lestrrat-go/jwx/v3/BUILD b/constraint/vendor/github.com/lestrrat-go/jwx/v3/BUILD index 275940888..5da405b23 100644 --- a/constraint/vendor/github.com/lestrrat-go/jwx/v3/BUILD +++ b/constraint/vendor/github.com/lestrrat-go/jwx/v3/BUILD @@ -1,9 +1,15 @@ -load("@rules_go//go:def.bzl", "go_library", "go_test") load("@gazelle//:def.bzl", "gazelle") +load("@rules_go//go:def.bzl", "go_library", "go_test") # gazelle:prefix github.com/lestrrat-go/jwx/v3 # gazelle:go_naming_convention import_alias +# Scratch directories that are not part of the module. Without these, +# gazelle walks bazel's own output tree under .gauntlet and rewrites every +# BUILD file to point at copies of the repo it finds in there. +# gazelle:exclude .gauntlet +# gazelle:exclude .tmp + gazelle(name = "gazelle") go_library( diff --git a/constraint/vendor/github.com/lestrrat-go/jwx/v3/Changes b/constraint/vendor/github.com/lestrrat-go/jwx/v3/Changes index b74d70725..34318280c 100644 --- a/constraint/vendor/github.com/lestrrat-go/jwx/v3/Changes +++ b/constraint/vendor/github.com/lestrrat-go/jwx/v3/Changes @@ -4,6 +4,36 @@ Changes v3 has many incompatibilities with v2. To see the full list of differences between v2 and v3, please read the Changes-v3.md file (https://github.com/lestrrat-go/jwx/blob/develop/v3/Changes-v3.md) +v3.3.0 8 Sep 2026 + * [jwt][jws][jwe][jwk] Custom claim, header, and JWK field names are now + JSON-escaped on output. Previously a name was written between the quotes + as is, so a name containing `"` could close its own member and add + members the application never set. For example, calling `Set` with the + name `x":0,"admin` produced a signed token containing `"admin":true`. + Every name now yields exactly one member, and names that need no + escaping serialize exactly as before. + + If your application accepts custom names from callers, an exact-match + allowlist was never affected. A blocklist of reserved names, or an + allowlist by namespace prefix, could be bypassed by this defect. Both are + reasonable designs; the bug was in the serializer. Prefer an exact-match + allowlist, and if you accept a prefix, require the rest of the name to be + a plain identifier. + + Fixed in v4.5.0 and v3.3.0. v2, v1, and v0 contain the same code and are + unmaintained; see SECURITY.md. (GHSA-4cf7-xm37-g63h) + + * [jws] Added `jws.WithStrictECDSA(bool)`, a `jws.Sign` option that rejects + anything RFC 7518 forbids for an ECDSA signature. Today that is Section + 3.4's binding of ES256 to P-256, ES384 to P-384, and ES512 to P-521, so + signing a P-521 key under `jwa.ES256()` fails instead of producing a JWS + that other JOSE implementations reject. + + The default is unchanged: without the option, a mismatched curve and + algorithm still sign exactly as before. `jws.Verify` is unaffected either + way. `jwt.Sign` callers can reach the option through + `jwt.WithSignOption(jws.WithStrictECDSA(true))`. (#2323) + v3.2.0 27 Jul 2026 * [jwe] Correct the JSON `"aad"` member so it contains only BASE64URL of the external Additional Authenticated Data, rather than the diff --git a/constraint/vendor/github.com/lestrrat-go/jwx/v3/SECURITY.md b/constraint/vendor/github.com/lestrrat-go/jwx/v3/SECURITY.md index 601dced5c..a8d9f83d2 100644 --- a/constraint/vendor/github.com/lestrrat-go/jwx/v3/SECURITY.md +++ b/constraint/vendor/github.com/lestrrat-go/jwx/v3/SECURITY.md @@ -2,13 +2,21 @@ ## Supported Versions -Most recent two major versions will receive security updates +Security fixes are published for the versions marked below. The +[State of support](https://github.com/lestrrat-go/jwx/discussions/1079) +discussion is the canonical, up-to-date statement; this table summarizes it. | Version | Supported | | -------- | ------------------ | -| v3.x.x | :white_check_mark: | -| v2.x.x | :white_check_mark: | -| < v2.0.0 | :x: | +| v4.x.x | :white_check_mark: Current release | +| v3.x.x | :white_check_mark: Previous release; receives regular fixes | +| v2.x.x | :x: Unmaintained. Do not use | +| v1.x.x | :x: Unmaintained. Do not use | +| < v1.0.0 | :x: Unmaintained. Do not use | + +Unmaintained versions receive no fixes of any kind, including for issues +already fixed in a supported version. Each advisory names the versions that +carry the fix; a version not named there stays affected. ## Reporting a Vulnerability diff --git a/constraint/vendor/github.com/lestrrat-go/jwx/v3/internal/json/BUILD.bazel b/constraint/vendor/github.com/lestrrat-go/jwx/v3/internal/json/BUILD.bazel index 4e2dbe12b..29b954455 100644 --- a/constraint/vendor/github.com/lestrrat-go/jwx/v3/internal/json/BUILD.bazel +++ b/constraint/vendor/github.com/lestrrat-go/jwx/v3/internal/json/BUILD.bazel @@ -1,4 +1,4 @@ -load("@rules_go//go:def.bzl", "go_library") +load("@rules_go//go:def.bzl", "go_library", "go_test") go_library( name = "json", @@ -9,7 +9,10 @@ go_library( ], importpath = "github.com/lestrrat-go/jwx/v3/internal/json", visibility = ["//:__subpackages__"], - deps = ["//internal/base64"], + deps = [ + "//internal/base64", + "//internal/tokens", + ], ) alias( @@ -17,3 +20,12 @@ alias( actual = ":json", visibility = ["//:__subpackages__"], ) + +go_test( + name = "json_test", + srcs = ["json_test.go"], + deps = [ + ":json", + "@com_github_stretchr_testify//require", + ], +) diff --git a/constraint/vendor/github.com/lestrrat-go/jwx/v3/internal/json/json.go b/constraint/vendor/github.com/lestrrat-go/jwx/v3/internal/json/json.go index 4dec2b806..91c5cbd1b 100644 --- a/constraint/vendor/github.com/lestrrat-go/jwx/v3/internal/json/json.go +++ b/constraint/vendor/github.com/lestrrat-go/jwx/v3/internal/json/json.go @@ -7,6 +7,7 @@ import ( "sync/atomic" "github.com/lestrrat-go/jwx/v3/internal/base64" + "github.com/lestrrat-go/jwx/v3/internal/tokens" ) var useNumber atomic.Uint32 @@ -164,3 +165,31 @@ func (dc *decodeCtx) Registry() *Registry { func (dc *decodeCtx) StrictStrings() bool { return dc.strictStrings } + +// WriteQuotedKey writes key as a quoted JSON object member name followed by +// the separating colon and a space. +// +// Member names come from public methods such as Set and Builder.Claim, so +// they may contain any byte, including `"`. A name copied raw between the +// quotes could end its own member and start further ones, so the serialized +// object would no longer match the one the caller built +// (GHSA-4cf7-xm37-g63h). A name that needs no escaping is written directly, +// which keeps the common path free of allocations. Every other name goes +// through the JSON string encoder. +func WriteQuotedKey(buf *bytes.Buffer, key string) error { + if tokens.IsJSONSafeASCII(key) { + buf.WriteByte(tokens.DoubleQuote) + buf.WriteString(key) + buf.WriteString(`": `) + return nil + } + + encoded, err := Marshal(key) + if err != nil { + return fmt.Errorf(`failed to encode object member name: %w`, err) + } + buf.Write(encoded) + buf.WriteByte(tokens.Colon) + buf.WriteByte(' ') + return nil +} diff --git a/constraint/vendor/github.com/lestrrat-go/jwx/v3/internal/keyconv/BUILD.bazel b/constraint/vendor/github.com/lestrrat-go/jwx/v3/internal/keyconv/BUILD.bazel index d46d2f381..f6bac2613 100644 --- a/constraint/vendor/github.com/lestrrat-go/jwx/v3/internal/keyconv/BUILD.bazel +++ b/constraint/vendor/github.com/lestrrat-go/jwx/v3/internal/keyconv/BUILD.bazel @@ -8,7 +8,6 @@ go_library( deps = [ "//jwk", "@com_github_lestrrat_go_blackmagic//:blackmagic", - "@org_golang_x_crypto//ed25519", ], ) diff --git a/constraint/vendor/github.com/lestrrat-go/jwx/v3/internal/pool/BUILD.bazel b/constraint/vendor/github.com/lestrrat-go/jwx/v3/internal/pool/BUILD.bazel index c48330e27..04dbd6697 100644 --- a/constraint/vendor/github.com/lestrrat-go/jwx/v3/internal/pool/BUILD.bazel +++ b/constraint/vendor/github.com/lestrrat-go/jwx/v3/internal/pool/BUILD.bazel @@ -21,11 +21,9 @@ alias( go_test( name = "pool_test", - srcs = [ - "byte_slice_test.go", - ], + srcs = ["byte_slice_test.go"], deps = [ ":pool", "@com_github_stretchr_testify//require", ], -) \ No newline at end of file +) diff --git a/constraint/vendor/github.com/lestrrat-go/jwx/v3/internal/tokens/tokens.go b/constraint/vendor/github.com/lestrrat-go/jwx/v3/internal/tokens/tokens.go index 2af3b88de..864a86c42 100644 --- a/constraint/vendor/github.com/lestrrat-go/jwx/v3/internal/tokens/tokens.go +++ b/constraint/vendor/github.com/lestrrat-go/jwx/v3/internal/tokens/tokens.go @@ -11,6 +11,20 @@ const ( Period = '.' ) +// IsJSONSafeASCII reports whether s can be concatenated into a +// hand-built JSON string literal without escaping. Any byte that +// would require a JSON escape (control bytes, `"`, `\`) or any +// non-ASCII byte disqualifies the value. +func IsJSONSafeASCII(s string) bool { + for i := range len(s) { + c := s[i] + if c < 0x20 || c >= 0x7f || c == '"' || c == '\\' { + return false + } + } + return true +} + // Cryptographic key sizes const ( KeySize16 = 16 diff --git a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwa/BUILD.bazel b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwa/BUILD.bazel index 6d0af7efb..cc8bd5bd2 100644 --- a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwa/BUILD.bazel +++ b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwa/BUILD.bazel @@ -24,20 +24,20 @@ go_library( go_test( name = "jwa_test", srcs = [ + "builtin_registry_test.go", "compression_gen_test.go", "content_encryption_gen_test.go", + "cross_kind_test.go", "elliptic_gen_test.go", "jwa_test.go", "key_encryption_gen_test.go", "key_type_gen_test.go", "options_gen_test.go", + "registry_snapshot_test.go", "signature_gen_test.go", ], embed = [":jwa"], - deps = [ - "@com_github_stretchr_testify//require", - "@com_github_lestrrat_go_option_v2//:option", - ], + deps = ["@com_github_stretchr_testify//require"], ) alias( diff --git a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwe/BUILD.bazel b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwe/BUILD.bazel index 539122380..82ef013db 100644 --- a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwe/BUILD.bazel +++ b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwe/BUILD.bazel @@ -23,33 +23,38 @@ go_library( deps = [ "//cert", "//internal/base64", - "//transform", "//internal/json", - "//internal/tokens", "//internal/keyconv", "//internal/pool", + "//internal/tokens", "//jwa", "//jwe/internal/aescbc", - "//jwe/internal/cipher", "//jwe/internal/content_crypt", "//jwe/internal/keygen", "//jwe/jwebb", "//jwk", + "//transform", "@com_github_lestrrat_go_blackmagic//:blackmagic", "@com_github_lestrrat_go_option_v2//:option", - "@org_golang_x_crypto//pbkdf2", ], ) go_test( name = "jwe_test", srcs = [ + "bench_encrypt_test.go", + "encrypt_aad_test.go", "filter_test.go", + "fuzz_test.go", "gh402_test.go", "headers_test.go", + "jwe_aad_internal_test.go", + "jwe_crit_test.go", "jwe_test.go", + "message_aad_test.go", "message_test.go", "options_gen_test.go", + "recipient_headers_test.go", "speed_test.go", "unsupported_key_test.go", ], @@ -58,6 +63,7 @@ go_test( "//cert", "//internal/json", "//internal/jwxtest", + "//internal/tokens", "//jwa", "//jwk", "@com_github_stretchr_testify//require", diff --git a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwe/headers_gen.go b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwe/headers_gen.go index 5390c2be4..53ee8ca5d 100644 --- a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwe/headers_gen.go +++ b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwe/headers_gen.go @@ -962,9 +962,9 @@ func (h *stdHeaders) MarshalJSON() ([]byte, error) { if i > 0 { buf.WriteByte(tokens.Comma) } - buf.WriteByte('"') - buf.WriteString(pair.Name) - buf.WriteString(`": `) + if err := json.WriteQuotedKey(buf, pair.Name); err != nil { + return nil, fmt.Errorf(`failed to encode field name %q: %w`, pair.Name, err) + } buf.Write(pair.Value.([]byte)) } buf.WriteByte(tokens.CloseCurlyBracket) diff --git a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwe/internal/aescbc/BUILD.bazel b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwe/internal/aescbc/BUILD.bazel index 4ed4c53fa..20d86e525 100644 --- a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwe/internal/aescbc/BUILD.bazel +++ b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwe/internal/aescbc/BUILD.bazel @@ -12,7 +12,7 @@ go_test( name = "aescbc_test", srcs = ["aescbc_test.go"], embed = [":aescbc"], - deps = ["@com_github_stretchr_testify//require"] + deps = ["@com_github_stretchr_testify//require"], ) alias( diff --git a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwe/internal/cipher/BUILD.bazel b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwe/internal/cipher/BUILD.bazel index cf642c744..3a6755111 100644 --- a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwe/internal/cipher/BUILD.bazel +++ b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwe/internal/cipher/BUILD.bazel @@ -9,10 +9,9 @@ go_library( importpath = "github.com/lestrrat-go/jwx/v3/jwe/internal/cipher", visibility = ["//:__subpackages__"], deps = [ - "//jwa", + "//internal/tokens", "//jwe/internal/aescbc", "//jwe/internal/keygen", - "//internal/tokens", ], ) @@ -21,7 +20,6 @@ go_test( srcs = ["cipher_test.go"], deps = [ ":cipher", - "//jwa", "//internal/tokens", "@com_github_stretchr_testify//require", ], diff --git a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwe/internal/concatkdf/BUILD.bazel b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwe/internal/concatkdf/BUILD.bazel index 59aeb2cd2..3665c71f5 100644 --- a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwe/internal/concatkdf/BUILD.bazel +++ b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwe/internal/concatkdf/BUILD.bazel @@ -9,7 +9,10 @@ go_library( go_test( name = "concatkdf_test", - srcs = ["concatkdf_test.go"], + srcs = [ + "bench_test.go", + "concatkdf_test.go", + ], embed = [":concatkdf"], deps = [ "//jwa", diff --git a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwe/internal/keygen/BUILD.bazel b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwe/internal/keygen/BUILD.bazel index bde8eb68f..91f5b3973 100644 --- a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwe/internal/keygen/BUILD.bazel +++ b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwe/internal/keygen/BUILD.bazel @@ -1,4 +1,4 @@ -load("@rules_go//go:def.bzl", "go_library") +load("@rules_go//go:def.bzl", "go_library", "go_test") go_library( name = "keygen", @@ -9,10 +9,8 @@ go_library( importpath = "github.com/lestrrat-go/jwx/v3/jwe/internal/keygen", visibility = ["//:__subpackages__"], deps = [ - "//internal/ecutil", - "//jwa", - "//jwe/internal/concatkdf", "//internal/tokens", + "//jwe/internal/concatkdf", "//jwk", ], ) @@ -22,3 +20,12 @@ alias( actual = ":keygen", visibility = ["//jwe:__subpackages__"], ) + +go_test( + name = "keygen_test", + srcs = ["keygen_test.go"], + deps = [ + ":keygen", + "@com_github_stretchr_testify//require", + ], +) diff --git a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwe/jwebb/BUILD.bazel b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwe/jwebb/BUILD.bazel index c410a05cd..03df94b61 100644 --- a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwe/jwebb/BUILD.bazel +++ b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwe/jwebb/BUILD.bazel @@ -4,6 +4,7 @@ go_library( name = "jwebb", srcs = [ "content_cipher.go", + "jwebb.go", "key_decrypt_asymmetric.go", "key_decrypt_symmetric.go", "key_encrypt_asymmetric.go", @@ -16,11 +17,11 @@ go_library( deps = [ "//internal/keyconv", "//internal/pool", + "//internal/tokens", "//jwe/internal/cipher", "//jwe/internal/concatkdf", "//jwe/internal/content_crypt", "//jwe/internal/keygen", - "//internal/tokens", "@org_golang_x_crypto//pbkdf2", ], ) @@ -32,12 +33,18 @@ go_test( "jwebb_test.go", "keywrap_test.go", ], - embed = [":jwebb"], deps = [ + ":jwebb", "//internal/jwxtest", + "//internal/tokens", "//jwa", "//jwe/internal/keygen", - "//internal/tokens", "@com_github_stretchr_testify//require", ], -) \ No newline at end of file +) + +alias( + name = "go_default_library", + actual = ":jwebb", + visibility = ["//visibility:public"], +) diff --git a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwk/BUILD.bazel b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwk/BUILD.bazel index 8f20da9a6..647b9a0ed 100644 --- a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwk/BUILD.bazel +++ b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwk/BUILD.bazel @@ -5,6 +5,7 @@ go_library( srcs = [ "cache.go", "convert.go", + "doc.go", "ecdsa.go", "ecdsa_gen.go", "errors.go", @@ -36,14 +37,14 @@ go_library( "//cert", "//internal/base64", "//internal/ecutil", - "//transform", "//internal/json", "//internal/pool", - "//internal/tokens", + "//internal/tokens", "//jwa", "//jwk/ecdsa", "//jwk/internal/registry", "//jwk/jwkbb", + "//transform", "@com_github_lestrrat_go_blackmagic//:blackmagic", "@com_github_lestrrat_go_httprc_v3//:httprc", "@com_github_lestrrat_go_option_v2//:option", @@ -53,12 +54,18 @@ go_library( go_test( name = "jwk_test", srcs = [ + "bench_set_test.go", + "ecdsa_test.go", "filter_test.go", + "fuzz_test.go", "headers_test.go", - "jwk_internal_test.go", "jwk_test.go", + "jwk_zero_on_error_test.go", + "okp_length_test.go", "options_gen_test.go", "refresh_test.go", + "rsa_thumbprint_test.go", + "rsa_validate_test.go", "set_test.go", "unsupported_test.go", "x5c_test.go", @@ -74,7 +81,7 @@ go_test( "//internal/tokens", "//jwa", "//jwk/ecdsa", - "//jws", + "//jwk/jwkunsafe", "@com_github_lestrrat_go_blackmagic//:blackmagic", "@com_github_lestrrat_go_httprc_v3//:httprc", "@com_github_lestrrat_go_httprc_v3//tracesink", diff --git a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwk/ecdsa/BUILD.bazel b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwk/ecdsa/BUILD.bazel index bf058aa64..8490b202a 100644 --- a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwk/ecdsa/BUILD.bazel +++ b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwk/ecdsa/BUILD.bazel @@ -1,4 +1,4 @@ -load("@rules_go//go:def.bzl", "go_library") +load("@rules_go//go:def.bzl", "go_library", "go_test") go_library( name = "ecdsa", @@ -13,3 +13,13 @@ alias( actual = ":ecdsa", visibility = ["//visibility:public"], ) + +go_test( + name = "ecdsa_test", + srcs = ["ecdsa_test.go"], + embed = [":ecdsa"], + deps = [ + "//jwa", + "@com_github_stretchr_testify//require", + ], +) diff --git a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwk/ecdsa_gen.go b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwk/ecdsa_gen.go index a717e24bb..301d14dbc 100644 --- a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwk/ecdsa_gen.go +++ b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwk/ecdsa_gen.go @@ -734,9 +734,9 @@ func (h *ecdsaPublicKey) MarshalJSON() ([]byte, error) { if i > 0 { buf.WriteByte(tokens.Comma) } - buf.WriteByte('"') - buf.WriteString(pair.Name) - buf.WriteString(`": `) + if err := json.WriteQuotedKey(buf, pair.Name); err != nil { + return nil, fmt.Errorf(`failed to encode field name %q: %w`, pair.Name, err) + } buf.Write(pair.Value.([]byte)) } buf.WriteByte(tokens.CloseCurlyBracket) @@ -1558,9 +1558,9 @@ func (h *ecdsaPrivateKey) MarshalJSON() ([]byte, error) { if i > 0 { buf.WriteByte(tokens.Comma) } - buf.WriteByte('"') - buf.WriteString(pair.Name) - buf.WriteString(`": `) + if err := json.WriteQuotedKey(buf, pair.Name); err != nil { + return nil, fmt.Errorf(`failed to encode field name %q: %w`, pair.Name, err) + } buf.Write(pair.Value.([]byte)) } buf.WriteByte(tokens.CloseCurlyBracket) diff --git a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwk/jwkbb/BUILD.bazel b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwk/jwkbb/BUILD.bazel index baf286688..7c3b89ddd 100644 --- a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwk/jwkbb/BUILD.bazel +++ b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwk/jwkbb/BUILD.bazel @@ -27,4 +27,4 @@ alias( name = "go_default_library", actual = ":jwkbb", visibility = ["//visibility:public"], -) \ No newline at end of file +) diff --git a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwk/okp_gen.go b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwk/okp_gen.go index 3cfac0275..c6ca49bf9 100644 --- a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwk/okp_gen.go +++ b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwk/okp_gen.go @@ -684,9 +684,9 @@ func (h *okpPublicKey) MarshalJSON() ([]byte, error) { if i > 0 { buf.WriteByte(tokens.Comma) } - buf.WriteByte('"') - buf.WriteString(pair.Name) - buf.WriteString(`": `) + if err := json.WriteQuotedKey(buf, pair.Name); err != nil { + return nil, fmt.Errorf(`failed to encode field name %q: %w`, pair.Name, err) + } buf.Write(pair.Value.([]byte)) } buf.WriteByte(tokens.CloseCurlyBracket) @@ -1454,9 +1454,9 @@ func (h *okpPrivateKey) MarshalJSON() ([]byte, error) { if i > 0 { buf.WriteByte(tokens.Comma) } - buf.WriteByte('"') - buf.WriteString(pair.Name) - buf.WriteString(`": `) + if err := json.WriteQuotedKey(buf, pair.Name); err != nil { + return nil, fmt.Errorf(`failed to encode field name %q: %w`, pair.Name, err) + } buf.Write(pair.Value.([]byte)) } buf.WriteByte(tokens.CloseCurlyBracket) diff --git a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwk/rsa_gen.go b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwk/rsa_gen.go index 3ef59aec6..7b44c4e6e 100644 --- a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwk/rsa_gen.go +++ b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwk/rsa_gen.go @@ -692,9 +692,9 @@ func (h *rsaPublicKey) MarshalJSON() ([]byte, error) { if i > 0 { buf.WriteByte(tokens.Comma) } - buf.WriteByte('"') - buf.WriteString(pair.Name) - buf.WriteString(`": `) + if err := json.WriteQuotedKey(buf, pair.Name); err != nil { + return nil, fmt.Errorf(`failed to encode field name %q: %w`, pair.Name, err) + } buf.Write(pair.Value.([]byte)) } buf.WriteByte(tokens.CloseCurlyBracket) @@ -1707,9 +1707,9 @@ func (h *rsaPrivateKey) MarshalJSON() ([]byte, error) { if i > 0 { buf.WriteByte(tokens.Comma) } - buf.WriteByte('"') - buf.WriteString(pair.Name) - buf.WriteString(`": `) + if err := json.WriteQuotedKey(buf, pair.Name); err != nil { + return nil, fmt.Errorf(`failed to encode field name %q: %w`, pair.Name, err) + } buf.Write(pair.Value.([]byte)) } buf.WriteByte(tokens.CloseCurlyBracket) diff --git a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwk/symmetric_gen.go b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwk/symmetric_gen.go index 900ed6537..389ac9acf 100644 --- a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwk/symmetric_gen.go +++ b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwk/symmetric_gen.go @@ -638,9 +638,9 @@ func (h *symmetricKey) MarshalJSON() ([]byte, error) { if i > 0 { buf.WriteByte(tokens.Comma) } - buf.WriteByte('"') - buf.WriteString(pair.Name) - buf.WriteString(`": `) + if err := json.WriteQuotedKey(buf, pair.Name); err != nil { + return nil, fmt.Errorf(`failed to encode field name %q: %w`, pair.Name, err) + } buf.Write(pair.Value.([]byte)) } buf.WriteByte(tokens.CloseCurlyBracket) diff --git a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/BUILD.bazel b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/BUILD.bazel index c03d0f9a0..5f4e5a90d 100644 --- a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/BUILD.bazel +++ b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/BUILD.bazel @@ -15,9 +15,9 @@ go_library( "message.go", "options.go", "options_gen.go", - "signer.go", "sign_context.go", "signature_builder.go", + "signer.go", "streaming_detached.go", "verifier.go", "verify_context.go", @@ -27,14 +27,14 @@ go_library( deps = [ "//cert", "//internal/base64", - "//internal/ecutil", "//internal/json", - "//internal/tokens", "//internal/keyconv", "//internal/pool", + "//internal/tokens", "//jwa", "//jwk", - "//jws/internal/keytype", + "//jws/internal/jwsbb", + "//jws/internal/keyalg", "//jws/jwsbb", "//jws/legacy", "//transform", @@ -47,10 +47,17 @@ go_library( go_test( name = "jws_test", srcs = [ - "es256k_test.go", + "bench_marshal_test.go", + "bench_serialize_test.go", "filter_test.go", + "format_detect_test.go", + "fuzz_test.go", + "headers_nil_test.go", "headers_test.go", + "jws_crit_test.go", + "jws_internal_test.go", "jws_test.go", + "key_provider_test.go", "message_test.go", "options_gen_test.go", "signer_test.go", @@ -61,12 +68,13 @@ go_test( deps = [ "//cert", "//internal/base64", - "//internal/ecutil", "//internal/json", "//internal/jwxtest", + "//internal/tokens", "//jwa", "//jwk", - "//jwt", + "//jws/legacy", + "@com_github_lestrrat_go_dsig//:dsig", "@com_github_lestrrat_go_httprc_v3//:httprc", "@com_github_stretchr_testify//require", ], diff --git a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/errors.go b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/errors.go index e4445bd54..91577a014 100644 --- a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/errors.go +++ b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/errors.go @@ -3,6 +3,8 @@ package jws import ( "errors" "fmt" + + "github.com/lestrrat-go/jwx/v3/jws/internal/keyalg" ) // errCritPresent is returned by VerifyCompactFast when the protected @@ -45,25 +47,17 @@ func ErrB64Present() error { return errB64Present } -// errUnclassifiableKey is the common sentinel for AlgorithmsForKey -// failures: the key shape cannot be matched to any registered key type -// for signing. Three different code paths land here — Import-failed, -// kty-not-registered, and shape-rejected (e.g. ecdh) — but they're all -// the same logical "we can't classify this key" outcome from the -// caller's perspective. Wrap-with-this lets callers branch on -// errors.Is(err, jws.ErrUnclassifiableKey()) instead of pattern-matching -// the three error-message shapes the function previously emitted. -var errUnclassifiableKey = errors.New("jws: key cannot be classified for signing") - -// ErrUnclassifiableKey returns the sentinel that jws.AlgorithmsForKey -// (and indirectly jws.Sign / jws.Verify when option-time validation -// fails) wraps when the supplied key cannot be matched to a registered -// key type. Branching on this sentinel is the right way to ask "is this -// a 'we can't tell what this key is' failure?" — the wrapping error -// also carries the concrete %T or %q diagnostic in its message, so the -// human-readable error stays specific. +// ErrUnclassifiableKey returns the sentinel that jws.Sign and jws.Verify +// wrap when option-time validation cannot match the supplied key to a +// registered key type. Branching on this sentinel is the right way to ask +// "is this a 'we can't tell what this key is' failure?" — the wrapping +// error also carries the concrete %T or %q diagnostic in its message, so +// the human-readable error stays specific. +// +// The sentinel itself lives in jws/internal/keyalg, which owns key +// classification. func ErrUnclassifiableKey() error { - return errUnclassifiableKey + return keyalg.ErrUnclassifiableKey } type signError struct { diff --git a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/headers_gen.go b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/headers_gen.go index 0628e626d..04cf66909 100644 --- a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/headers_gen.go +++ b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/headers_gen.go @@ -812,9 +812,9 @@ func (h *stdHeaders) MarshalJSON() ([]byte, error) { if i > 0 { buf.WriteByte(tokens.Comma) } - buf.WriteByte('"') - buf.WriteString(pair.Name) - buf.WriteString(`": `) + if err := json.WriteQuotedKey(buf, pair.Name); err != nil { + return nil, fmt.Errorf(`failed to encode field name %q: %w`, pair.Name, err) + } buf.Write(pair.Value.([]byte)) } buf.WriteByte(tokens.CloseCurlyBracket) diff --git a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/internal/jwsbb/BUILD.bazel b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/internal/jwsbb/BUILD.bazel new file mode 100644 index 000000000..b762d41a4 --- /dev/null +++ b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/internal/jwsbb/BUILD.bazel @@ -0,0 +1,25 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "jwsbb", + srcs = ["ecdsacurve.go"], + importpath = "github.com/lestrrat-go/jwx/v3/jws/internal/jwsbb", + visibility = ["//jws:__subpackages__"], + deps = ["@com_github_lestrrat_go_dsig//:dsig"], +) + +alias( + name = "go_default_library", + actual = ":jwsbb", + visibility = ["//jws:__subpackages__"], +) + +go_test( + name = "jwsbb_test", + srcs = ["ecdsacurve_test.go"], + deps = [ + ":jwsbb", + "@com_github_lestrrat_go_dsig//:dsig", + "@com_github_stretchr_testify//require", + ], +) diff --git a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/internal/jwsbb/ecdsacurve.go b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/internal/jwsbb/ecdsacurve.go new file mode 100644 index 000000000..c8715e6c6 --- /dev/null +++ b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/internal/jwsbb/ecdsacurve.go @@ -0,0 +1,117 @@ +package jwsbb + +import ( + "crypto" + "crypto/ecdsa" + "crypto/elliptic" + "fmt" + + "github.com/lestrrat-go/dsig" +) + +// This file enforces the RFC 7518 Section 3.4 binding between an ECDSA JWS +// algorithm and the curve its key must sit on (ES256/P-256, ES384/P-384, +// ES512/P-521). It is sign-side only, and jws reaches it only when the caller +// passes jws.WithStrictECDSA(true). +// +// The check is opt-in because the old permissive behavior is an interop +// defect, not a security hole: the signer controls both the key and the +// algorithm at the call site, and the JWS it produces is a genuine signature +// under its own key. Turning the check on by default would break working +// callers to fix a conformance problem they may not have. +// +// jws.Verify never reaches this file at all. It infers algorithms from a key +// when a JWKS entry carries no "alg" (see jws/internal/keyalg.Candidates and +// the deprecated jws.AlgorithmsForKey, whose godoc freezes that inference), +// and it must stay exactly as permissive as it is today. + +// RequireECDSACurve reports whether key sits on the curve RFC 7518 Section +// 3.4 binds joseAlg to. It returns nil -- never an error -- when the binding +// cannot be established: dsigAlg is an ECDSA-family algorithm outside the +// three JOSE built-ins (e.g. ES256K, whether from the jwx_es256k build tag +// or an extension module), or key carries no readable curve. Only positive +// evidence of a mismatch is an error. +func RequireECDSACurve(joseAlg, dsigAlg string, key any) error { + want, ok := curveForDsigAlgorithm(dsigAlg) + if !ok { + return nil + } + + pub := ecdsaPublicKeyOf(key) + if pub == nil || pub.Curve == nil { + return nil + } + + if pub.Curve == want { + return nil + } + gotParams := pub.Curve.Params() + if gotParams == nil { + return nil + } + wantParams := want.Params() + if wantParams != nil && gotParams.Name == wantParams.Name { + return nil + } + + return fmt.Errorf(`ECDSA curve mismatch: key is on %s, algorithm %q requires %s`, + curveName(pub.Curve), joseAlg, curveName(want)) +} + +// curveForDsigAlgorithm maps a dsig ECDSA algorithm name to the curve RFC +// 7518 Section 3.4 requires for it. Only the three JOSE built-ins are +// known; anything else (custom-curve extensions such as ES256K) misses +// deliberately, so the caller passes the key through unchecked. +func curveForDsigAlgorithm(dsigAlg string) (elliptic.Curve, bool) { + switch dsigAlg { + case dsig.ECDSAWithP256AndSHA256: + return elliptic.P256(), true + case dsig.ECDSAWithP384AndSHA384: + return elliptic.P384(), true + case dsig.ECDSAWithP521AndSHA512: + return elliptic.P521(), true + default: + return nil, false + } +} + +// ecdsaPublicKeyOf extracts an *ecdsa.PublicKey from key, or nil when key is +// not (or does not expose) an ECDSA key. Callers pass an already-converted +// key (jwk.Key unwrapping happens before this is called), so only the raw Go +// crypto forms and an opaque crypto.Signer are handled here. +func ecdsaPublicKeyOf(key any) *ecdsa.PublicKey { + switch k := key.(type) { + case *ecdsa.PrivateKey: + if k == nil { + return nil + } + return &k.PublicKey + case ecdsa.PrivateKey: + return &k.PublicKey + case *ecdsa.PublicKey: + return k + case ecdsa.PublicKey: + return &k + case crypto.Signer: + pub, ok := k.Public().(*ecdsa.PublicKey) + if !ok { + return nil + } + return pub + default: + return nil + } +} + +// curveName returns crv.Params().Name, guarding a nil Params() the same way +// the comparison in RequireECDSACurve does. +func curveName(crv elliptic.Curve) string { + if crv == nil { + return "" + } + params := crv.Params() + if params == nil { + return "" + } + return params.Name +} diff --git a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/internal/keyalg/BUILD.bazel b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/internal/keyalg/BUILD.bazel new file mode 100644 index 000000000..97313cd6c --- /dev/null +++ b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/internal/keyalg/BUILD.bazel @@ -0,0 +1,18 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "keyalg", + srcs = ["keyalg.go"], + importpath = "github.com/lestrrat-go/jwx/v3/jws/internal/keyalg", + visibility = ["//jws:__subpackages__"], + deps = [ + "//jwa", + "//jwk", + ], +) + +alias( + name = "go_default_library", + actual = ":keyalg", + visibility = ["//jws:__subpackages__"], +) diff --git a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/internal/keyalg/keyalg.go b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/internal/keyalg/keyalg.go new file mode 100644 index 000000000..09458230b --- /dev/null +++ b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/internal/keyalg/keyalg.go @@ -0,0 +1,259 @@ +// Package keyalg works out which signature algorithms a key can be used +// with, and owns the registration tables it reads to decide. +// +// The answer is a guess, on purpose. jws.Verify uses it to pick +// algorithms to try when a JWKS key has no "alg" field, and option +// handling uses it to catch a key that clearly does not go with the +// algorithm asked for. It is not a check for whether a key and an +// algorithm are a valid pair, and the list can be wider than any one RFC +// allows for a given key. +// +// This package is internal to jwx. The jws package still has +// AlgorithmsForKey, a one-line wrapper over [Candidates], but that is +// deprecated and was never meant for callers outside jwx. Everything in +// the tree calls this package instead. +package keyalg + +import ( + "crypto" + "crypto/ecdh" + "crypto/ecdsa" + "crypto/ed25519" + "crypto/rsa" + "errors" + "fmt" + "slices" + "sync" + + "github.com/lestrrat-go/jwx/v3/jwa" + "github.com/lestrrat-go/jwx/v3/jwk" +) + +// ErrUnclassifiableKey is the common sentinel for [Candidates] failures: +// the key shape cannot be matched to any registered key type for signing. +// Three different code paths land here — Import-failed, kty-not-registered, +// and shape-rejected (e.g. ecdh) — but they're all the same logical "we +// can't classify this key" outcome from the caller's perspective. +// Wrap-with-this lets callers branch on errors.Is instead of +// pattern-matching the three error-message shapes. +// +// The jws package re-exports this through jws.ErrUnclassifiableKey(). +var ErrUnclassifiableKey = errors.New("jws: key cannot be classified for signing") + +// curver is implemented by jwk.Key types that carry curve information. +type curver interface { + Crv() (jwa.EllipticCurveAlgorithm, bool) +} + +var mu sync.RWMutex +var keyTypeToAlgorithms = make(map[jwa.KeyType][]jwa.SignatureAlgorithm) +var algorithmToKeyTypes = make(map[jwa.SignatureAlgorithm][]jwa.KeyType) +var curveToAlgorithms = make(map[jwa.EllipticCurveAlgorithm][]jwa.SignatureAlgorithm) + +func init() { + RegisterForKeyType(jwa.OKP(), jwa.EdDSA()) + RegisterForCurve(jwa.Ed25519(), jwa.EdDSAEd25519()) + for _, alg := range []jwa.SignatureAlgorithm{jwa.HS256(), jwa.HS384(), jwa.HS512()} { + RegisterForKeyType(jwa.OctetSeq(), alg) + } + for _, alg := range []jwa.SignatureAlgorithm{jwa.RS256(), jwa.RS384(), jwa.RS512(), jwa.PS256(), jwa.PS384(), jwa.PS512()} { + RegisterForKeyType(jwa.RSA(), alg) + } + for _, alg := range []jwa.SignatureAlgorithm{jwa.ES256(), jwa.ES384(), jwa.ES512()} { + RegisterForKeyType(jwa.EC(), alg) + } +} + +// RegisterForKeyType records alg as usable with keys of type kty. +// +// This backs jws.RegisterAlgorithmForKeyType, which extension modules +// call from init() to add their own algorithms. +func RegisterForKeyType(kty jwa.KeyType, alg jwa.SignatureAlgorithm) { + mu.Lock() + defer mu.Unlock() + keyTypeToAlgorithms[kty] = append(keyTypeToAlgorithms[kty], alg) + if !slices.Contains(algorithmToKeyTypes[alg], kty) { + algorithmToKeyTypes[alg] = append(algorithmToKeyTypes[alg], kty) + } +} + +// RegisterForCurve scopes alg to the given elliptic curve. When +// [Candidates] can determine a key's curve, an algorithm registered under +// some curve is offered only for keys on that curve, instead of for every +// key of its key type. +// +// This backs jws.RegisterAlgorithmForCurve. It is append-only and +// deduplicates entries, so builtin registrations cannot be overwritten by +// external modules. +func RegisterForCurve(crv jwa.EllipticCurveAlgorithm, alg jwa.SignatureAlgorithm) { + mu.Lock() + defer mu.Unlock() + if slices.Contains(curveToAlgorithms[crv], alg) { + return + } + curveToAlgorithms[crv] = append(curveToAlgorithms[crv], alg) +} + +// KeyTypesFor returns the key types registered for alg. The reverse index +// is maintained at registration time so this is an O(1) lookup. It returns +// nil if no key type is registered for alg, which signals callers to skip +// any prefilter. +func KeyTypesFor(alg jwa.SignatureAlgorithm) []jwa.KeyType { + mu.RLock() + defer mu.RUnlock() + // Copy so the caller can safely iterate without holding the lock; + // RegisterForKeyType may append concurrently after we return. + // Typical length is 1. + return slices.Clone(algorithmToKeyTypes[alg]) +} + +// Candidates returns the signature algorithms that key could be used +// with. It only takes into consideration keys/algorithms for verification +// purposes, as this is the only usage where one may need to dynamically +// figure out which method to use. +// +// When the key's curve is known, algorithms registered for that curve via +// [RegisterForCurve] are combined with key-type-level algorithms to +// produce a more precise result. The curve is known for a [jwk.Key] that +// has a Crv() method, for raw ed25519 keys, and for any raw key that +// reaches the [jwk.Import] fallback below. +// +// ECDSA is the exception. A raw [ecdsa.PublicKey] or [ecdsa.PrivateKey] is +// classified by key type alone and its Curve field is never read. No +// builtin registration binds P-256, P-384, or P-521 to an algorithm +// either, so every EC key reports the full ES* list no matter which curve +// it sits on. RFC 7518 Section 3.4 is stricter than that; jws.Sign +// enforces it only when the caller passes jws.WithStrictECDSA(true). +// +// Accepted key shapes (resolved in order): +// +// 1. [jwk.Key] — kty is read directly; if the implementation also exposes +// Crv(), the curve refines the result. +// 2. Stdlib crypto types: [rsa.PublicKey] / [rsa.PrivateKey] (and pointer +// forms), [ecdsa.PublicKey] / [ecdsa.PrivateKey] (and pointer forms), +// [ed25519.PublicKey], [ed25519.PrivateKey], and [byte] slices for +// symmetric keys. +// 3. [crypto/ecdh.PublicKey] / [crypto/ecdh.PrivateKey] (and pointer +// forms) — explicitly rejected; ECDH keys are key-agreement only. +// Returns an error wrapping [ErrUnclassifiableKey]. +// 4. [crypto.Signer] (e.g. KMS-backed adapters) — resolved once via +// .Public(); the public key is then re-classified through tiers 1–2 +// or the [jwk.Import] fallback below. To prevent infinite recursion, +// a Signer whose .Public() is itself a Signer is left for the +// downstream dispatcher to handle. +// 5. [jwk.Import] fallback — anything else is offered to the import +// registry, allowing extension modules to register their own raw key +// types. +// +// All "we cannot classify this key" failures wrap [ErrUnclassifiableKey], +// so callers can branch with errors.Is rather than pattern-matching error +// strings. The wrapping error keeps the concrete %T or %q diagnostic in +// its message for human readers. +func Candidates(key any) ([]jwa.SignatureAlgorithm, error) { + var kty jwa.KeyType + var crv jwa.EllipticCurveAlgorithm + var hasCrv bool + + switch key := key.(type) { + case jwk.Key: + kty = key.KeyType() + if ck, ok := key.(curver); ok { + crv, hasCrv = ck.Crv() + } + case rsa.PublicKey, *rsa.PublicKey, rsa.PrivateKey, *rsa.PrivateKey: + kty = jwa.RSA() + case ecdsa.PublicKey, *ecdsa.PublicKey, ecdsa.PrivateKey, *ecdsa.PrivateKey: + kty = jwa.EC() + case ed25519.PublicKey, ed25519.PrivateKey: + kty = jwa.OKP() + crv = jwa.Ed25519() + hasCrv = true + case *ecdh.PublicKey, ecdh.PublicKey, *ecdh.PrivateKey, ecdh.PrivateKey: + // ecdh keys are for key agreement (X25519/X448), not signing. + // Reject at the API boundary instead of returning a misleading + // algorithm list that would fail deeper in the signing stack. + return nil, fmt.Errorf(`%w: key type %T cannot be used for signing (ecdh keys are key-agreement only)`, ErrUnclassifiableKey, key) + case []byte: + kty = jwa.OctetSeq() + default: + // For crypto.Signer from external packages (e.g. KMS-backed signers), + // extract the underlying public key type via .Public(). + // Standard library types (*rsa.PrivateKey, etc.) are already handled + // by the concrete cases above. + var signerPubErr error + if signer, ok := key.(crypto.Signer); ok { + pub := signer.Public() + // Guard: only recurse if the public key is not itself a crypto.Signer, + // to prevent infinite recursion from pathological implementations. + if _, isSigner := pub.(crypto.Signer); !isSigner { + algs, err := Candidates(pub) + if err == nil { + return algs, nil + } + // Save the inner classification error so a + // downstream Import-fallback failure can surface + // both diagnostics. A successful Import discards + // signerPubErr — only the eventual failure path + // joins them. + signerPubErr = err + } + } + imported, err := jwk.Import(key) + if err != nil { + outer := fmt.Errorf(`%w: unknown key type %T`, ErrUnclassifiableKey, key) + if signerPubErr != nil { + return nil, errors.Join(outer, signerPubErr) + } + return nil, outer + } + kty = imported.KeyType() + if ck, ok := imported.(curver); ok { + crv, hasCrv = ck.Crv() + } + } + + mu.RLock() + defer mu.RUnlock() + + ktyAlgs, ok := keyTypeToAlgorithms[kty] + if !ok { + return nil, fmt.Errorf(`%w: unregistered key type %q`, ErrUnclassifiableKey, kty) + } + + // If we know the curve and there are curve-specific registrations, + // return only key-type-level algorithms (those not registered under + // any curve) plus curve-specific algorithms for this curve. + if hasCrv { + crvAlgs := curveToAlgorithms[crv] + return filterForCurve(ktyAlgs, crvAlgs), nil + } + + return ktyAlgs, nil +} + +// filterForCurve returns the subset of ktyAlgs that are not registered +// under any curve (i.e., generic for the key type) plus the curve-specific +// algorithms from crvAlgs. +func filterForCurve(ktyAlgs, crvAlgs []jwa.SignatureAlgorithm) []jwa.SignatureAlgorithm { + var result []jwa.SignatureAlgorithm + + // Add key-type-level algorithms that are not claimed by any curve + for _, alg := range ktyAlgs { + if !isRegisteredUnderAnyCurve(alg) { + result = append(result, alg) + } + } + + // Add curve-specific algorithms + result = append(result, crvAlgs...) + return result +} + +func isRegisteredUnderAnyCurve(alg jwa.SignatureAlgorithm) bool { + for _, algs := range curveToAlgorithms { + if slices.Contains(algs, alg) { + return true + } + } + return false +} diff --git a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/internal/keytype/BUILD.bazel b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/internal/keytype/BUILD.bazel index eb8bd94ac..f43eec37a 100644 --- a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/internal/keytype/BUILD.bazel +++ b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/internal/keytype/BUILD.bazel @@ -9,3 +9,9 @@ go_library( "//jwk", ], ) + +alias( + name = "go_default_library", + actual = ":keytype", + visibility = ["//jws:__subpackages__"], +) diff --git a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/jws.go b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/jws.go index ecc6f952f..90fc2d4c4 100644 --- a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/jws.go +++ b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/jws.go @@ -27,11 +27,6 @@ package jws import ( "crypto" - "crypto/ecdh" - "crypto/ecdsa" - "crypto/ed25519" - "crypto/rsa" - "errors" "fmt" "io" "slices" @@ -46,6 +41,7 @@ import ( "github.com/lestrrat-go/jwx/v3/internal/tokens" "github.com/lestrrat-go/jwx/v3/jwa" "github.com/lestrrat-go/jwx/v3/jwk" + "github.com/lestrrat-go/jwx/v3/jws/internal/keyalg" "github.com/lestrrat-go/jwx/v3/jws/jwsbb" ) @@ -535,57 +531,29 @@ func RegisterCustomField(name string, object any) { registry.Register(name, object) } -// curver is implemented by jwk.Key types that carry curve information. -type curver interface { - Crv() (jwa.EllipticCurveAlgorithm, bool) -} - -// Helpers for signature verification -var muAlgorithmMaps sync.RWMutex -var keyTypeToAlgorithms = make(map[jwa.KeyType][]jwa.SignatureAlgorithm) -var algorithmToKeyTypes = make(map[jwa.SignatureAlgorithm][]jwa.KeyType) -var curveToAlgorithms = make(map[jwa.EllipticCurveAlgorithm][]jwa.SignatureAlgorithm) - -func init() { - RegisterAlgorithmForKeyType(jwa.OKP(), jwa.EdDSA()) - RegisterAlgorithmForCurve(jwa.Ed25519(), jwa.EdDSAEd25519()) - for _, alg := range []jwa.SignatureAlgorithm{jwa.HS256(), jwa.HS384(), jwa.HS512()} { - RegisterAlgorithmForKeyType(jwa.OctetSeq(), alg) - } - for _, alg := range []jwa.SignatureAlgorithm{jwa.RS256(), jwa.RS384(), jwa.RS512(), jwa.PS256(), jwa.PS384(), jwa.PS512()} { - RegisterAlgorithmForKeyType(jwa.RSA(), alg) - } - for _, alg := range []jwa.SignatureAlgorithm{jwa.ES256(), jwa.ES384(), jwa.ES512()} { - RegisterAlgorithmForKeyType(jwa.EC(), alg) - } -} - // RegisterAlgorithmForKeyType registers an additional algorithm as valid for -// the given key type. This is used internally by init() and can also be called -// from external modules that provide support for additional algorithms (e.g. Ed448). +// the given key type. This is used internally to register the builtin +// algorithms, and can also be called from external modules that provide +// support for additional algorithms (e.g. Ed448). +// +// Registering an algorithm here makes [Sign] and [Verify] accept it for keys +// of that type, and makes it a candidate when a JWKS key carrying no "alg" +// member is verified under jws.WithInferAlgorithmFromKey(true). func RegisterAlgorithmForKeyType(kty jwa.KeyType, alg jwa.SignatureAlgorithm) { - muAlgorithmMaps.Lock() - defer muAlgorithmMaps.Unlock() - keyTypeToAlgorithms[kty] = append(keyTypeToAlgorithms[kty], alg) - if !slices.Contains(algorithmToKeyTypes[alg], kty) { - algorithmToKeyTypes[alg] = append(algorithmToKeyTypes[alg], kty) - } + keyalg.RegisterForKeyType(kty, alg) } -// RegisterAlgorithmForCurve registers an algorithm as valid for the given -// elliptic curve. When [AlgorithmsForKey] can determine the curve of a key, -// it returns the union of key-type-level algorithms and curve-specific -// algorithms instead of all algorithms for the key type. +// RegisterAlgorithmForCurve scopes an algorithm to the given elliptic curve. +// When the curve of a key can be determined, an algorithm registered under +// some curve is offered only for keys on that curve, instead of for every key +// of its key type. Pair this with [RegisterAlgorithmForKeyType] so that, for +// example, an OKP algorithm meant for one curve does not become a candidate +// for every OKP key. // // This function is append-only and deduplicates entries, so builtin // registrations cannot be overwritten by external modules. func RegisterAlgorithmForCurve(crv jwa.EllipticCurveAlgorithm, alg jwa.SignatureAlgorithm) { - muAlgorithmMaps.Lock() - defer muAlgorithmMaps.Unlock() - if slices.Contains(curveToAlgorithms[crv], alg) { - return - } - curveToAlgorithms[crv] = append(curveToAlgorithms[crv], alg) + keyalg.RegisterForCurve(crv, alg) } // AlgorithmsForKey returns the possible signature algorithms that can @@ -593,10 +561,18 @@ func RegisterAlgorithmForCurve(crv jwa.EllipticCurveAlgorithm, alg jwa.Signature // for verification purposes, as this is the only usage where one may need // dynamically figure out which method to use. // -// When the key's curve can be determined (via [jwk.Key] Crv() method or -// inferred from the raw Go type), curve-specific algorithms registered via +// When the key's curve is known, algorithms registered for that curve via // [RegisterAlgorithmForCurve] are combined with key-type-level algorithms -// to produce a more precise result. +// to produce a more precise result. The curve is known for a [jwk.Key] +// that has a Crv() method, for raw ed25519 keys, and for any raw key that +// reaches the [jwk.Import] fallback below. +// +// ECDSA is the exception. A raw [ecdsa.PublicKey] or [ecdsa.PrivateKey] is +// classified by key type alone and its Curve field is never read. No +// builtin registration binds P-256, P-384, or P-521 to an algorithm +// either, so every EC key reports the full ES* list no matter which curve +// it sits on. RFC 7518 Section 3.4 is stricter than that; see +// [WithStrictECDSA] for enforcing it when signing. // // Accepted key shapes (resolved in order): // @@ -622,113 +598,33 @@ func RegisterAlgorithmForCurve(crv jwa.EllipticCurveAlgorithm, alg jwa.Signature // so callers can branch with errors.Is rather than pattern-matching error // strings. The wrapping error keeps the concrete %T or %q diagnostic in // its message for human readers. +// +// Deprecated: Do not use. This is an internal helper that jwx uses to +// guess which algorithms to try when a JWKS key has no "alg" field. It is +// exported only because it always has been, and was never meant for +// callers outside jwx. It does not tell you whether a key and an +// algorithm go together, so do not use it as that kind of check. The list +// it hands back can be wider than RFC 7518 allows for the key you passed. +// +// It keeps working for the rest of the v3 series, and is deprecated in v4 +// as well. It will not be fixed in the meantime, and the way it picks +// algorithms will not change. The list itself can still grow. An +// extension module that calls [RegisterAlgorithmForKeyType] or +// [RegisterAlgorithmForCurve] adds to what this reports, the same way it +// adds to what [Sign] and [Verify] accept. +// +// To find out whether a key works with an algorithm, pass both to [Sign] +// or [Verify] and check the error. func AlgorithmsForKey(key any) ([]jwa.SignatureAlgorithm, error) { - var kty jwa.KeyType - var crv jwa.EllipticCurveAlgorithm - var hasCrv bool - - switch key := key.(type) { - case jwk.Key: - kty = key.KeyType() - if ck, ok := key.(curver); ok { - crv, hasCrv = ck.Crv() - } - case rsa.PublicKey, *rsa.PublicKey, rsa.PrivateKey, *rsa.PrivateKey: - kty = jwa.RSA() - case ecdsa.PublicKey, *ecdsa.PublicKey, ecdsa.PrivateKey, *ecdsa.PrivateKey: - kty = jwa.EC() - case ed25519.PublicKey, ed25519.PrivateKey: - kty = jwa.OKP() - crv = jwa.Ed25519() - hasCrv = true - case *ecdh.PublicKey, ecdh.PublicKey, *ecdh.PrivateKey, ecdh.PrivateKey: - // ecdh keys are for key agreement (X25519/X448), not signing. - // Reject at the API boundary instead of returning a misleading - // algorithm list that would fail deeper in the signing stack. - return nil, fmt.Errorf(`%w: key type %T cannot be used for signing (ecdh keys are key-agreement only)`, errUnclassifiableKey, key) - case []byte: - kty = jwa.OctetSeq() - default: - // For crypto.Signer from external packages (e.g. KMS-backed signers), - // extract the underlying public key type via .Public(). - // Standard library types (*rsa.PrivateKey, etc.) are already handled - // by the concrete cases above. - var signerPubErr error - if signer, ok := key.(crypto.Signer); ok { - pub := signer.Public() - // Guard: only recurse if the public key is not itself a crypto.Signer, - // to prevent infinite recursion from pathological implementations. - if _, isSigner := pub.(crypto.Signer); !isSigner { - algs, err := AlgorithmsForKey(pub) - if err == nil { - return algs, nil - } - // Save the inner classification error so a - // downstream Import-fallback failure can surface - // both diagnostics. A successful Import discards - // signerPubErr — only the eventual failure path - // joins them. - signerPubErr = err - } - } - imported, err := jwk.Import(key) - if err != nil { - outer := fmt.Errorf(`%w: unknown key type %T`, errUnclassifiableKey, key) - if signerPubErr != nil { - return nil, errors.Join(outer, signerPubErr) - } - return nil, outer - } - kty = imported.KeyType() - if ck, ok := imported.(curver); ok { - crv, hasCrv = ck.Crv() - } - } - - muAlgorithmMaps.RLock() - defer muAlgorithmMaps.RUnlock() - - ktyAlgs, ok := keyTypeToAlgorithms[kty] - if !ok { - return nil, fmt.Errorf(`%w: unregistered key type %q`, errUnclassifiableKey, kty) - } - - // If we know the curve and there are curve-specific registrations, - // return only key-type-level algorithms (those not registered under - // any curve) plus curve-specific algorithms for this curve. - if hasCrv { - crvAlgs := curveToAlgorithms[crv] - return filterAlgorithmsForCurve(ktyAlgs, crvAlgs), nil - } - - return ktyAlgs, nil -} - -// filterAlgorithmsForCurve returns the subset of ktyAlgs that are not -// registered under any curve (i.e., generic for the key type) plus the -// curve-specific algorithms from crvAlgs. -func filterAlgorithmsForCurve(ktyAlgs, crvAlgs []jwa.SignatureAlgorithm) []jwa.SignatureAlgorithm { - var result []jwa.SignatureAlgorithm - - // Add key-type-level algorithms that are not claimed by any curve - for _, alg := range ktyAlgs { - if !isRegisteredUnderAnyCurve(alg) { - result = append(result, alg) - } - } - - // Add curve-specific algorithms - result = append(result, crvAlgs...) - return result -} - -func isRegisteredUnderAnyCurve(alg jwa.SignatureAlgorithm) bool { - for _, algs := range curveToAlgorithms { - if slices.Contains(algs, alg) { - return true - } - } - return false + // The godoc says the way this picks algorithms will not change, so + // calling keyalg only works while keyalg picks them the same way this + // function did before it was deprecated. It does today. If Candidates + // ever changes (narrowing EC keys to the one algorithm their curve + // allows is the likely first case), copy the old code back in here + // instead of letting the change through. An extension registering a + // new algorithm is not that kind of change, because the tables have + // always been an input. + return keyalg.Candidates(key) } // unsupportedKeyError builds the rejection error for a jwk.UnsupportedKey @@ -749,9 +645,9 @@ func unsupportedKeyError(uk jwk.UnsupportedKey, op string) error { // (a) a nil key, used by keyless algorithms (see GH910); // (b) any key handed to an algorithm with a user-registered custom // Signer2/Verifier2 — custom implementations may accept arbitrary key -// types that AlgorithmsForKey cannot classify; and +// types that keyalg.Candidates cannot classify; and // (c) an opaque crypto.Signer whose .Public() is itself a crypto.Signer, -// the one case AlgorithmsForKey refuses to recurse into. +// the one case keyalg.Candidates refuses to recurse into. // Every other classification failure is surfaced so callers get a crisp // option-boundary rejection instead of a deep-stack error. func validateAlgorithmForKey(alg jwa.SignatureAlgorithm, key any) error { @@ -761,7 +657,7 @@ func validateAlgorithmForKey(alg jwa.SignatureAlgorithm, key any) error { if key == nil { return nil } - algs, err := AlgorithmsForKey(key) + algs, err := keyalg.Candidates(key) if err != nil { if hasCustomSigVerifier(alg) { return nil diff --git a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/jwsbb/BUILD.bazel b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/jwsbb/BUILD.bazel index 54e64265a..ca0b96303 100644 --- a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/jwsbb/BUILD.bazel +++ b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/jwsbb/BUILD.bazel @@ -20,9 +20,7 @@ go_library( "//internal/base64", "//internal/ecutil", "//internal/keyconv", - "//internal/pool", "//internal/tokens", - "//jws/internal/keytype", "@com_github_lestrrat_go_dsig//:dsig", "@com_github_valyala_fastjson//:fastjson", ], @@ -30,10 +28,20 @@ go_library( go_test( name = "jwsbb_test", - srcs = ["jwsbb_test.go"], - embed = [":jwsbb"], + srcs = [ + "header_test.go", + "jwsbb_test.go", + ], deps = [ + ":jwsbb", "//internal/base64", + "//internal/pool", "@com_github_stretchr_testify//require", ], ) + +alias( + name = "go_default_library", + actual = ":jwsbb", + visibility = ["//visibility:public"], +) diff --git a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/jwsbb/sign.go b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/jwsbb/sign.go index 8c0c185c5..bcc3bbbd3 100644 --- a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/jwsbb/sign.go +++ b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/jwsbb/sign.go @@ -76,6 +76,11 @@ func dispatchRSASign(key any, dsigAlg string, payload []byte, rr io.Reader) ([]b return dsig.Sign(privkey, dsigAlg, payload, rr) } +// dispatchECDSASign does not enforce the RFC 7518 Section 3.4 binding +// between an ES* algorithm and its curve. That check lives one layer up, in +// jws, behind jws.WithStrictECDSA, because it is opt-in: signing a P-521 key +// under ES256 is non-conformant but has always been allowed here, and jwsbb +// is the raw building-block layer where the caller owns that decision. func dispatchECDSASign(key any, dsigAlg string, payload []byte, rr io.Reader) ([]byte, error) { // Try crypto.Signer first (dsig can handle it directly) if signer, ok := key.(crypto.Signer); ok { diff --git a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/key_provider.go b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/key_provider.go index 2ae7b5f43..a5475341a 100644 --- a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/key_provider.go +++ b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/key_provider.go @@ -10,6 +10,7 @@ import ( "github.com/lestrrat-go/jwx/v3/jwa" "github.com/lestrrat-go/jwx/v3/jwk" + "github.com/lestrrat-go/jwx/v3/jws/internal/keyalg" ) // KeyProvider is responsible for providing key(s) to sign or verify a payload. @@ -142,7 +143,7 @@ func (kp *keySetProvider) selectKey(sink KeySink, key jwk.Key, sig *Signature, _ return false, nil } - algs, err := AlgorithmsForKey(key) + algs, err := keyalg.Candidates(key) if err != nil { return false, fmt.Errorf(`failed to get a list of signature methods for key type %s: %w`, key.KeyType(), err) } @@ -246,14 +247,14 @@ func (kp *keySetProvider) fetchKeysByKid(sink KeySink, sig *Signature, msg *Mess // incompatible (alg, key) pair before running any verifier anyway. // // The allowed-KeyType set is looked up once per FetchKeys call via the -// precomputed algorithmToKeyTypes inverse map, so the per-key check is +// precomputed inverse map in keyalg, so the per-key check is // a cheap KeyType equality over a tiny slice (typically 1 element). // When allowedKtys is nil (no header alg, or alg has no registered // key type), the filter is skipped. func (kp *keySetProvider) fetchAllKeys(sink KeySink, sig *Signature, msg *Message) error { var allowedKtys []jwa.KeyType if hdrAlg, ok := sig.ProtectedHeaders().Algorithm(); ok { - allowedKtys = keyTypesForAlgorithm(hdrAlg) + allowedKtys = keyalg.KeyTypesFor(hdrAlg) } found := false var errs []error @@ -290,20 +291,6 @@ func (kp *keySetProvider) fetchAllKeys(sink KeySink, sig *Signature, msg *Messag return nil } -// keyTypesForAlgorithm returns the registered key types that can -// produce the given signature algorithm. The inverse map is maintained -// at registration time so this is an O(1) lookup. Returns nil if no -// key type is registered for alg, which signals callers to skip the -// prefilter. -func keyTypesForAlgorithm(alg jwa.SignatureAlgorithm) []jwa.KeyType { - muAlgorithmMaps.RLock() - defer muAlgorithmMaps.RUnlock() - // Copy so the caller can safely iterate without holding the - // lock; RegisterAlgorithmForKeyType may append concurrently - // after we return. Typical length is 1. - return slices.Clone(algorithmToKeyTypes[alg]) -} - type jkuProvider struct { fetcher jwk.Fetcher options []jwk.FetchOption @@ -354,7 +341,7 @@ func (kp jkuProvider) FetchKeys(ctx context.Context, sink KeySink, sig *Signatur } } - algs, err := AlgorithmsForKey(key) + algs, err := keyalg.Candidates(key) if err != nil { return fmt.Errorf(`failed to get a list of signature methods for key type %s: %w`, key.KeyType(), err) } diff --git a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/legacy/BUILD.bazel b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/legacy/BUILD.bazel index 8e77cece4..41ee14aa4 100644 --- a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/legacy/BUILD.bazel +++ b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/legacy/BUILD.bazel @@ -14,8 +14,13 @@ go_library( deps = [ "//internal/ecutil", "//internal/keyconv", - "//internal/pool", "//jwa", "//jws/internal/keytype", ], ) + +alias( + name = "go_default_library", + actual = ":legacy", + visibility = ["//visibility:public"], +) diff --git a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/options.go b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/options.go index cc98abc5b..a126dd405 100644 --- a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/options.go +++ b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/options.go @@ -104,6 +104,14 @@ func (w *withKey) Protected(v Headers) Headers { // The algorithm specified in the `alg` parameter MUST be able to support // the type of key you provided, otherwise an error is returned. // +// RFC 7518 Section 3.4 binds each of ES256/ES384/ES512 to one elliptic curve +// (ES256/P-256, ES384/P-384, ES512/P-521), but `jws.Sign()` does not enforce +// that by default: a key on any other curve still signs, and the JWS it +// produces is one strict JOSE implementations reject. Pass +// `jws.WithStrictECDSA(true)` to `jws.Sign()` to reject the mismatch instead. +// `jws.Verify()` is unaffected either way and keeps inferring algorithms from +// a key's curve exactly as before. +// // Any of the following is accepted for the `key` parameter: // * A "raw" key (e.g. rsa.PrivateKey, ecdsa.PrivateKey, etc) // * A crypto.Signer diff --git a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/options.yaml b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/options.yaml index fb8c88db6..326d14a74 100644 --- a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/options.yaml +++ b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/options.yaml @@ -227,6 +227,28 @@ options: the key on-demand each time. By default, the key is not validated. + - ident: StrictECDSA + interface: SignOption + argument_type: bool + comment: | + WithStrictECDSA makes `jws.Sign()` reject anything RFC 7518 forbids for + an ECDSA signature. Today that is exactly one rule: Section 3.4 binds + ES256 to P-256, ES384 to P-384, and ES512 to P-521, so signing with a + key on any other curve fails instead of producing a JWS that strict + JOSE implementations reject. + + Future releases may enforce further RFC 7518 ECDSA rules under this + same option, so enabling it means "be strict about ECDSA", not "check + the curve and nothing else". + + Extension algorithms on their own curves, such as ES256K, are not + affected. Only the three curves the RFC names are checked. + + This option is sign-side only. `jws.Verify()` is unaffected and keeps + inferring algorithms from a key's curve exactly as before, so a JWS + produced without this option still verifies. + + By default, the curve is not checked. - ident: InferAlgorithmFromKey interface: WithKeySetSuboption argument_type: bool diff --git a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/options_gen.go b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/options_gen.go index 10dd96e48..ade61d36c 100644 --- a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/options_gen.go +++ b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/options_gen.go @@ -223,6 +223,7 @@ type identProtectedHeaders struct{} type identPublicHeaders struct{} type identRequireKid struct{} type identSerialization struct{} +type identStrictECDSA struct{} type identUseDefault struct{} type identValidateKey struct{} @@ -306,6 +307,10 @@ func (identSerialization) String() string { return "WithSerialization" } +func (identStrictECDSA) String() string { + return "WithStrictECDSA" +} + func (identUseDefault) String() string { return "WithUseDefault" } @@ -605,6 +610,28 @@ func WithCompact() SignVerifyParseOption { return &signVerifyParseOption{option.New(identSerialization{}, fmtCompact)} } +// WithStrictECDSA makes `jws.Sign()` reject anything RFC 7518 forbids for +// an ECDSA signature. Today that is exactly one rule: Section 3.4 binds +// ES256 to P-256, ES384 to P-384, and ES512 to P-521, so signing with a +// key on any other curve fails instead of producing a JWS that strict +// JOSE implementations reject. +// +// Future releases may enforce further RFC 7518 ECDSA rules under this +// same option, so enabling it means "be strict about ECDSA", not "check +// the curve and nothing else". +// +// Extension algorithms on their own curves, such as ES256K, are not +// affected. Only the three curves the RFC names are checked. +// +// This option is sign-side only. `jws.Verify()` is unaffected and keeps +// inferring algorithms from a key's curve exactly as before, so a JWS +// produced without this option still verifies. +// +// By default, the curve is not checked. +func WithStrictECDSA(v bool) SignOption { + return &signOption{option.New(identStrictECDSA{}, v)} +} + // WithUseDefault specifies that if and only if a jwk.Key contains // exactly one jwk.Key, that key should be used. func WithUseDefault(v bool) WithKeySetSuboption { diff --git a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/sign_context.go b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/sign_context.go index a6cbd045e..f564454f1 100644 --- a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/sign_context.go +++ b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/sign_context.go @@ -14,6 +14,7 @@ type signContext struct { format int detached bool validateKey bool + strictECDSA bool payload []byte payloadReader io.Reader encoder Base64Encoder @@ -39,6 +40,7 @@ func freeSignContext(ctx *signContext) *signContext { ctx.sigbuilders = ctx.sigbuilders[:0] ctx.detached = false ctx.validateKey = false + ctx.strictECDSA = false ctx.encoder = base64.DefaultEncoder() ctx.none = nil ctx.payload = nil @@ -133,6 +135,10 @@ func (sc *signContext) ProcessOptions(options []SignOption) error { if err := option.Value(&sc.validateKey); err != nil { return makeSignError(prefixJwsSign, `failed to retrieve validate-key option value: %w`, err) } + case identStrictECDSA{}: + if err := option.Value(&sc.strictECDSA); err != nil { + return makeSignError(prefixJwsSign, `failed to retrieve strict-ECDSA option value: %w`, err) + } case identBase64Encoder{}: if err := option.Value(&sc.encoder); err != nil { return makeSignError(prefixJwsSign, `failed to retrieve base64-encoder option value: %w`, err) diff --git a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/signature_builder.go b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/signature_builder.go index 2963b6e48..76ed62521 100644 --- a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/signature_builder.go +++ b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/signature_builder.go @@ -2,14 +2,19 @@ package jws import ( "bytes" + "crypto/ecdsa" "fmt" "slices" + "github.com/lestrrat-go/dsig" + "github.com/lestrrat-go/jwx/v3/internal/json" + "github.com/lestrrat-go/jwx/v3/internal/keyconv" "github.com/lestrrat-go/jwx/v3/internal/pool" "github.com/lestrrat-go/jwx/v3/internal/tokens" "github.com/lestrrat-go/jwx/v3/jwa" "github.com/lestrrat-go/jwx/v3/jwk" + jwsbbi "github.com/lestrrat-go/jwx/v3/jws/internal/jwsbb" "github.com/lestrrat-go/jwx/v3/jws/jwsbb" ) @@ -52,7 +57,60 @@ func freeSignatureBuilder(sb *signatureBuilder) *signatureBuilder { return sb } +// requireECDSACurve enforces the RFC 7518 Section 3.4 binding between an ES* +// algorithm and the curve its key must sit on. It is only reached when the +// caller asked for it with jws.WithStrictECDSA(true). +// +// Anything that is not an ECDSA signature passes straight through, as does an +// ECDSA-family algorithm outside the three JOSE built-ins (an extension on its +// own curve, such as ES256K) and a key whose curve cannot be read. Deciding +// those cases is not this check's job; only positive evidence of a mismatch is +// an error. +func requireECDSACurve(alg jwa.SignatureAlgorithm, key any) error { + dsigAlg, ok := jwsbb.GetDsigAlgorithm(alg.String()) + if !ok { + return nil + } + + info, ok := dsig.GetAlgorithmInfo(dsigAlg) + if !ok || info.Family != dsig.ECDSA { + return nil + } + + rawKey, ok := unwrapECDSASignKey(key) + if !ok { + return nil + } + + return jwsbbi.RequireECDSACurve(alg.String(), dsigAlg, rawKey) +} + +// unwrapECDSASignKey returns the key jwsbbi.RequireECDSACurve should inspect. +// That function reads the curve off a raw key or a crypto.Signer, so a +// jwk.Key has to be unwrapped first. +// +// The bool is false when key is a jwk.Key holding something other than an +// ECDSA private key, which leaves the curve unreadable. The caller skips the +// check in that case and lets the signer reject the key on its own terms. +func unwrapECDSASignKey(key any) (any, bool) { + if _, ok := key.(jwk.Key); !ok { + return key, true + } + + var privkey *ecdsa.PrivateKey + if err := keyconv.ECDSAPrivateKey(&privkey, key); err != nil { + return nil, false + } + return privkey, true +} + func (sb *signatureBuilder) Build(sc *signContext, payload []byte) (*Signature, error) { + if sc.strictECDSA { + if err := requireECDSACurve(sb.alg, sb.key); err != nil { + return nil, makeSignError(prefixJwsSign, `%w`, err) + } + } + // Clone caller-provided headers before mutating so that re-using the // same Headers instance across multiple Sign calls does not cause // cross-contamination of alg/kid. diff --git a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/streaming_detached.go b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/streaming_detached.go index 871bb6439..5a2303835 100644 --- a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/streaming_detached.go +++ b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jws/streaming_detached.go @@ -16,6 +16,7 @@ import ( "github.com/lestrrat-go/jwx/v3/internal/tokens" "github.com/lestrrat-go/jwx/v3/jwa" "github.com/lestrrat-go/jwx/v3/jwk" + jwsbbi "github.com/lestrrat-go/jwx/v3/jws/internal/jwsbb" "github.com/lestrrat-go/jwx/v3/jws/jwsbb" ) @@ -85,6 +86,14 @@ func (sc *signContext) signStreaming() ([]byte, error) { return nil, makeSignError(prefixJwsSign, `failed to convert key for signature %d: %w`, idx, err) } + // The non-streaming path runs the same check from + // signatureBuilder.Build, which this path does not go through. + if sc.strictECDSA && dsigInfo.Family == dsig.ECDSA { + if err := jwsbbi.RequireECDSACurve(alg.String(), dsigInfo.Name, rawKey); err != nil { + return nil, makeSignError(prefixJwsSign, `signature %d: %w`, idx, err) + } + } + protected, err := cloneOrNewHeaders(sb.protected) if err != nil { return nil, makeSignError(prefixJwsSign, `failed to clone protected headers for signature %d: %w`, idx, err) diff --git a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwt/BUILD.bazel b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwt/BUILD.bazel index 86197d348..d49f6c1b4 100644 --- a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwt/BUILD.bazel +++ b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwt/BUILD.bazel @@ -4,9 +4,10 @@ go_library( name = "jwt", srcs = [ "builder_gen.go", + "doc.go", "errors.go", - "filter.go", "fastpath.go", + "filter.go", "http.go", "interface.go", "io.go", @@ -24,17 +25,17 @@ go_library( deps = [ "//:jwx", "//internal/base64", - "//transform", "//internal/json", - "//internal/tokens", "//internal/pool", + "//internal/tokens", "//jwa", "//jwe", "//jwk", "//jws", "//jws/jwsbb", - "//jwt/internal/types", "//jwt/internal/errors", + "//jwt/internal/types", + "//transform", "@com_github_lestrrat_go_blackmagic//:blackmagic", "@com_github_lestrrat_go_option_v2//:option", ], @@ -43,6 +44,10 @@ go_library( go_test( name = "jwt_test", srcs = [ + "fastpath_test.go", + "filter_test.go", + "fuzz_test.go", + "jwt_crit_test.go", "jwt_test.go", "options_gen_test.go", "token_options_test.go", @@ -54,13 +59,14 @@ go_test( deps = [ "//internal/json", "//internal/jwxtest", + "//internal/tokens", "//jwa", "//jwe", "//jwk", "//jwk/ecdsa", "//jws", "//jwt/internal/types", - "@com_github_lestrrat_go_httprc_v3//:httprc", + "@com_github_lestrrat_go_httprc_v3//:httprc", "@com_github_stretchr_testify//require", ], ) diff --git a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwt/internal/errors/BUILD.bazel b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwt/internal/errors/BUILD.bazel index a053e8c0a..cb5c4099c 100644 --- a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwt/internal/errors/BUILD.bazel +++ b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwt/internal/errors/BUILD.bazel @@ -2,9 +2,7 @@ load("@rules_go//go:def.bzl", "go_library") go_library( name = "errors", - srcs = [ - "errors.go", - ], + srcs = ["errors.go"], importpath = "github.com/lestrrat-go/jwx/v3/jwt/internal/errors", visibility = ["//jwt:__subpackages__"], ) @@ -13,4 +11,4 @@ alias( name = "go_default_library", actual = ":errors", visibility = ["//jwt:__subpackages__"], -) \ No newline at end of file +) diff --git a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwt/token_gen.go b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwt/token_gen.go index 7a057742a..343e39947 100644 --- a/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwt/token_gen.go +++ b/constraint/vendor/github.com/lestrrat-go/jwx/v3/jwt/token_gen.go @@ -628,9 +628,9 @@ func (t *stdToken) MarshalJSON() ([]byte, error) { if i > 0 { buf.WriteByte(tokens.Comma) } - buf.WriteByte('"') - buf.WriteString(pair.Name) - buf.WriteString(`": `) + if err := json.WriteQuotedKey(buf, pair.Name); err != nil { + return nil, fmt.Errorf(`failed to encode claim name %q: %w`, pair.Name, err) + } buf.Write(pair.Value.([]byte)) } buf.WriteByte(tokens.CloseCurlyBracket) diff --git a/constraint/vendor/github.com/lestrrat-go/jwx/v3/transform/BUILD.bazel b/constraint/vendor/github.com/lestrrat-go/jwx/v3/transform/BUILD.bazel index 3333c6607..9abb3aa5d 100644 --- a/constraint/vendor/github.com/lestrrat-go/jwx/v3/transform/BUILD.bazel +++ b/constraint/vendor/github.com/lestrrat-go/jwx/v3/transform/BUILD.bazel @@ -15,9 +15,7 @@ go_library( go_test( name = "transform_test", - srcs = [ - "map_test.go", - ], + srcs = ["map_test.go"], deps = [ ":transform", "//jwt", @@ -29,4 +27,4 @@ alias( name = "go_default_library", actual = ":transform", visibility = ["//visibility:public"], -) \ No newline at end of file +) diff --git a/constraint/vendor/github.com/open-policy-agent/opa/capabilities/capabilities.go b/constraint/vendor/github.com/open-policy-agent/opa/capabilities/capabilities.go index 5482720f7..c2c35f744 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/capabilities/capabilities.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/capabilities/capabilities.go @@ -1,7 +1,10 @@ -// Copyright 2021 The OPA Authors. All rights reserved. +// Copyright 2026 The OPA Authors. All rights reserved. // Use of this source code is governed by an Apache2 // license that can be found in the LICENSE file. +// Deprecated: This package is intended for older projects transitioning from OPA v0.x and will remain for the lifetime of OPA v1.x, but its use is not recommended. +// For newer features and behaviours, such as defaulting to the Rego v1 syntax, use the corresponding components in the [github.com/open-policy-agent/opa/v1] package instead. +// See https://www.openpolicyagent.org/docs/latest/v0-compatibility/ for more information. package capabilities import ( diff --git a/constraint/vendor/github.com/open-policy-agent/opa/capabilities/doc.go b/constraint/vendor/github.com/open-policy-agent/opa/capabilities/doc.go deleted file mode 100644 index 189c2e727..000000000 --- a/constraint/vendor/github.com/open-policy-agent/opa/capabilities/doc.go +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright 2024 The OPA Authors. All rights reserved. -// Use of this source code is governed by an Apache2 -// license that can be found in the LICENSE file. - -// Deprecated: This package is intended for older projects transitioning from OPA v0.x and will remain for the lifetime of OPA v1.x, but its use is not recommended. -// For newer features and behaviours, such as defaulting to the Rego v1 syntax, use the corresponding components in the [github.com/open-policy-agent/opa/v1] package instead. -// See https://www.openpolicyagent.org/docs/latest/v0-compatibility/ for more information. -package capabilities diff --git a/constraint/vendor/github.com/open-policy-agent/opa/capabilities/v1.21.0.json b/constraint/vendor/github.com/open-policy-agent/opa/capabilities/v1.21.0.json new file mode 100644 index 000000000..73f2fe4b6 --- /dev/null +++ b/constraint/vendor/github.com/open-policy-agent/opa/capabilities/v1.21.0.json @@ -0,0 +1,5030 @@ +{ + "builtins": [ + { + "name": "abs", + "decl": { + "args": [ + { + "type": "number" + } + ], + "result": { + "type": "number" + }, + "type": "function" + } + }, + { + "name": "all", + "decl": { + "args": [ + { + "of": [ + { + "dynamic": { + "type": "any" + }, + "type": "array" + }, + { + "of": { + "type": "any" + }, + "type": "set" + } + ], + "type": "any" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + }, + "deprecated": true + }, + { + "name": "and", + "decl": { + "args": [ + { + "of": { + "type": "any" + }, + "type": "set" + }, + { + "of": { + "type": "any" + }, + "type": "set" + } + ], + "result": { + "of": { + "type": "any" + }, + "type": "set" + }, + "type": "function" + }, + "infix": "\u0026" + }, + { + "name": "any", + "decl": { + "args": [ + { + "of": [ + { + "dynamic": { + "type": "any" + }, + "type": "array" + }, + { + "of": { + "type": "any" + }, + "type": "set" + } + ], + "type": "any" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + }, + "deprecated": true + }, + { + "name": "array.concat", + "decl": { + "args": [ + { + "dynamic": { + "type": "any" + }, + "type": "array" + }, + { + "dynamic": { + "type": "any" + }, + "type": "array" + } + ], + "result": { + "dynamic": { + "type": "any" + }, + "type": "array" + }, + "type": "function" + } + }, + { + "name": "array.flatten", + "decl": { + "args": [ + { + "dynamic": { + "type": "any" + }, + "type": "array" + } + ], + "result": { + "dynamic": { + "type": "any" + }, + "type": "array" + }, + "type": "function" + } + }, + { + "name": "array.reverse", + "decl": { + "args": [ + { + "dynamic": { + "type": "any" + }, + "type": "array" + } + ], + "result": { + "dynamic": { + "type": "any" + }, + "type": "array" + }, + "type": "function" + } + }, + { + "name": "array.slice", + "decl": { + "args": [ + { + "dynamic": { + "type": "any" + }, + "type": "array" + }, + { + "type": "number" + }, + { + "type": "number" + } + ], + "result": { + "dynamic": { + "type": "any" + }, + "type": "array" + }, + "type": "function" + } + }, + { + "name": "assign", + "decl": { + "args": [ + { + "type": "any" + }, + { + "type": "any" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + }, + "infix": ":=" + }, + { + "name": "base64.decode", + "decl": { + "args": [ + { + "type": "string" + } + ], + "result": { + "type": "string" + }, + "type": "function" + } + }, + { + "name": "base64.encode", + "decl": { + "args": [ + { + "type": "string" + } + ], + "result": { + "type": "string" + }, + "type": "function" + } + }, + { + "name": "base64.is_valid", + "decl": { + "args": [ + { + "type": "string" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + } + }, + { + "name": "base64url.decode", + "decl": { + "args": [ + { + "type": "string" + } + ], + "result": { + "type": "string" + }, + "type": "function" + } + }, + { + "name": "base64url.encode", + "decl": { + "args": [ + { + "type": "string" + } + ], + "result": { + "type": "string" + }, + "type": "function" + } + }, + { + "name": "base64url.encode_no_pad", + "decl": { + "args": [ + { + "type": "string" + } + ], + "result": { + "type": "string" + }, + "type": "function" + } + }, + { + "name": "bits.and", + "decl": { + "args": [ + { + "type": "number" + }, + { + "type": "number" + } + ], + "result": { + "type": "number" + }, + "type": "function" + } + }, + { + "name": "bits.lsh", + "decl": { + "args": [ + { + "type": "number" + }, + { + "type": "number" + } + ], + "result": { + "type": "number" + }, + "type": "function" + } + }, + { + "name": "bits.negate", + "decl": { + "args": [ + { + "type": "number" + } + ], + "result": { + "type": "number" + }, + "type": "function" + } + }, + { + "name": "bits.or", + "decl": { + "args": [ + { + "type": "number" + }, + { + "type": "number" + } + ], + "result": { + "type": "number" + }, + "type": "function" + } + }, + { + "name": "bits.rsh", + "decl": { + "args": [ + { + "type": "number" + }, + { + "type": "number" + } + ], + "result": { + "type": "number" + }, + "type": "function" + } + }, + { + "name": "bits.xor", + "decl": { + "args": [ + { + "type": "number" + }, + { + "type": "number" + } + ], + "result": { + "type": "number" + }, + "type": "function" + } + }, + { + "name": "cast_array", + "decl": { + "args": [ + { + "type": "any" + } + ], + "result": { + "dynamic": { + "type": "any" + }, + "type": "array" + }, + "type": "function" + }, + "deprecated": true + }, + { + "name": "cast_boolean", + "decl": { + "args": [ + { + "type": "any" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + }, + "deprecated": true + }, + { + "name": "cast_null", + "decl": { + "args": [ + { + "type": "any" + } + ], + "result": { + "type": "null" + }, + "type": "function" + }, + "deprecated": true + }, + { + "name": "cast_object", + "decl": { + "args": [ + { + "type": "any" + } + ], + "result": { + "dynamic": { + "key": { + "type": "any" + }, + "value": { + "type": "any" + } + }, + "type": "object" + }, + "type": "function" + }, + "deprecated": true + }, + { + "name": "cast_set", + "decl": { + "args": [ + { + "type": "any" + } + ], + "result": { + "of": { + "type": "any" + }, + "type": "set" + }, + "type": "function" + }, + "deprecated": true + }, + { + "name": "cast_string", + "decl": { + "args": [ + { + "type": "any" + } + ], + "result": { + "type": "string" + }, + "type": "function" + }, + "deprecated": true + }, + { + "name": "ceil", + "decl": { + "args": [ + { + "type": "number" + } + ], + "result": { + "type": "number" + }, + "type": "function" + } + }, + { + "name": "concat", + "decl": { + "args": [ + { + "type": "string" + }, + { + "of": [ + { + "dynamic": { + "type": "string" + }, + "type": "array" + }, + { + "of": { + "type": "string" + }, + "type": "set" + } + ], + "type": "any" + } + ], + "result": { + "type": "string" + }, + "type": "function" + } + }, + { + "name": "contains", + "decl": { + "args": [ + { + "type": "string" + }, + { + "type": "string" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + } + }, + { + "name": "count", + "decl": { + "args": [ + { + "of": [ + { + "type": "string" + }, + { + "dynamic": { + "type": "any" + }, + "type": "array" + }, + { + "dynamic": { + "key": { + "type": "any" + }, + "value": { + "type": "any" + } + }, + "type": "object" + }, + { + "of": { + "type": "any" + }, + "type": "set" + } + ], + "type": "any" + } + ], + "result": { + "type": "number" + }, + "type": "function" + } + }, + { + "name": "crypto.hmac.equal", + "decl": { + "args": [ + { + "type": "string" + }, + { + "type": "string" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + } + }, + { + "name": "crypto.hmac.md5", + "decl": { + "args": [ + { + "type": "string" + }, + { + "type": "string" + } + ], + "result": { + "type": "string" + }, + "type": "function" + } + }, + { + "name": "crypto.hmac.sha1", + "decl": { + "args": [ + { + "type": "string" + }, + { + "type": "string" + } + ], + "result": { + "type": "string" + }, + "type": "function" + } + }, + { + "name": "crypto.hmac.sha256", + "decl": { + "args": [ + { + "type": "string" + }, + { + "type": "string" + } + ], + "result": { + "type": "string" + }, + "type": "function" + } + }, + { + "name": "crypto.hmac.sha512", + "decl": { + "args": [ + { + "type": "string" + }, + { + "type": "string" + } + ], + "result": { + "type": "string" + }, + "type": "function" + } + }, + { + "name": "crypto.md5", + "decl": { + "args": [ + { + "type": "string" + } + ], + "result": { + "type": "string" + }, + "type": "function" + } + }, + { + "name": "crypto.parse_private_keys", + "decl": { + "args": [ + { + "type": "string" + } + ], + "result": { + "dynamic": { + "dynamic": { + "key": { + "type": "string" + }, + "value": { + "type": "any" + } + }, + "type": "object" + }, + "type": "array" + }, + "type": "function" + } + }, + { + "name": "crypto.sha1", + "decl": { + "args": [ + { + "type": "string" + } + ], + "result": { + "type": "string" + }, + "type": "function" + } + }, + { + "name": "crypto.sha256", + "decl": { + "args": [ + { + "type": "string" + } + ], + "result": { + "type": "string" + }, + "type": "function" + } + }, + { + "name": "crypto.x509.parse_and_verify_certificates", + "decl": { + "args": [ + { + "type": "string" + } + ], + "result": { + "static": [ + { + "type": "boolean" + }, + { + "dynamic": { + "dynamic": { + "key": { + "type": "string" + }, + "value": { + "type": "any" + } + }, + "type": "object" + }, + "type": "array" + } + ], + "type": "array" + }, + "type": "function" + } + }, + { + "name": "crypto.x509.parse_and_verify_certificates_with_options", + "decl": { + "args": [ + { + "type": "string" + }, + { + "dynamic": { + "key": { + "type": "string" + }, + "value": { + "type": "any" + } + }, + "type": "object" + } + ], + "result": { + "static": [ + { + "type": "boolean" + }, + { + "dynamic": { + "dynamic": { + "key": { + "type": "string" + }, + "value": { + "type": "any" + } + }, + "type": "object" + }, + "type": "array" + } + ], + "type": "array" + }, + "type": "function" + } + }, + { + "name": "crypto.x509.parse_certificate_request", + "decl": { + "args": [ + { + "type": "string" + } + ], + "result": { + "dynamic": { + "key": { + "type": "string" + }, + "value": { + "type": "any" + } + }, + "type": "object" + }, + "type": "function" + } + }, + { + "name": "crypto.x509.parse_certificates", + "decl": { + "args": [ + { + "type": "string" + } + ], + "result": { + "dynamic": { + "dynamic": { + "key": { + "type": "string" + }, + "value": { + "type": "any" + } + }, + "type": "object" + }, + "type": "array" + }, + "type": "function" + } + }, + { + "name": "crypto.x509.parse_keypair", + "decl": { + "args": [ + { + "type": "string" + }, + { + "type": "string" + } + ], + "result": { + "dynamic": { + "key": { + "type": "string" + }, + "value": { + "type": "any" + } + }, + "type": "object" + }, + "type": "function" + } + }, + { + "name": "crypto.x509.parse_rsa_private_key", + "decl": { + "args": [ + { + "type": "string" + } + ], + "result": { + "dynamic": { + "key": { + "type": "string" + }, + "value": { + "type": "any" + } + }, + "type": "object" + }, + "type": "function" + } + }, + { + "name": "div", + "decl": { + "args": [ + { + "type": "number" + }, + { + "type": "number" + } + ], + "result": { + "type": "number" + }, + "type": "function" + }, + "infix": "/" + }, + { + "name": "endswith", + "decl": { + "args": [ + { + "type": "string" + }, + { + "type": "string" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + } + }, + { + "name": "eq", + "decl": { + "args": [ + { + "type": "any" + }, + { + "type": "any" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + }, + "infix": "=" + }, + { + "name": "equal", + "decl": { + "args": [ + { + "type": "any" + }, + { + "type": "any" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + }, + "infix": "==" + }, + { + "name": "floor", + "decl": { + "args": [ + { + "type": "number" + } + ], + "result": { + "type": "number" + }, + "type": "function" + } + }, + { + "name": "format_int", + "decl": { + "args": [ + { + "type": "number" + }, + { + "type": "number" + } + ], + "result": { + "type": "string" + }, + "type": "function" + } + }, + { + "name": "glob.match", + "decl": { + "args": [ + { + "type": "string" + }, + { + "of": [ + { + "type": "null" + }, + { + "dynamic": { + "type": "string" + }, + "type": "array" + } + ], + "type": "any" + }, + { + "type": "string" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + } + }, + { + "name": "glob.quote_meta", + "decl": { + "args": [ + { + "type": "string" + } + ], + "result": { + "type": "string" + }, + "type": "function" + } + }, + { + "name": "graph.reachable", + "decl": { + "args": [ + { + "dynamic": { + "key": { + "type": "any" + }, + "value": { + "of": [ + { + "dynamic": { + "type": "any" + }, + "type": "array" + }, + { + "of": { + "type": "any" + }, + "type": "set" + } + ], + "type": "any" + } + }, + "type": "object" + }, + { + "of": [ + { + "dynamic": { + "type": "any" + }, + "type": "array" + }, + { + "of": { + "type": "any" + }, + "type": "set" + } + ], + "type": "any" + } + ], + "result": { + "of": { + "type": "any" + }, + "type": "set" + }, + "type": "function" + } + }, + { + "name": "graph.reachable_paths", + "decl": { + "args": [ + { + "dynamic": { + "key": { + "type": "any" + }, + "value": { + "of": [ + { + "dynamic": { + "type": "any" + }, + "type": "array" + }, + { + "of": { + "type": "any" + }, + "type": "set" + } + ], + "type": "any" + } + }, + "type": "object" + }, + { + "of": [ + { + "dynamic": { + "type": "any" + }, + "type": "array" + }, + { + "of": { + "type": "any" + }, + "type": "set" + } + ], + "type": "any" + } + ], + "result": { + "of": { + "dynamic": { + "type": "any" + }, + "type": "array" + }, + "type": "set" + }, + "type": "function" + } + }, + { + "name": "graphql.is_valid", + "decl": { + "args": [ + { + "of": [ + { + "type": "string" + }, + { + "dynamic": { + "key": { + "type": "any" + }, + "value": { + "type": "any" + } + }, + "type": "object" + } + ], + "type": "any" + }, + { + "of": [ + { + "type": "string" + }, + { + "dynamic": { + "key": { + "type": "any" + }, + "value": { + "type": "any" + } + }, + "type": "object" + } + ], + "type": "any" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + } + }, + { + "name": "graphql.parse", + "decl": { + "args": [ + { + "of": [ + { + "type": "string" + }, + { + "dynamic": { + "key": { + "type": "any" + }, + "value": { + "type": "any" + } + }, + "type": "object" + } + ], + "type": "any" + }, + { + "of": [ + { + "type": "string" + }, + { + "dynamic": { + "key": { + "type": "any" + }, + "value": { + "type": "any" + } + }, + "type": "object" + } + ], + "type": "any" + } + ], + "result": { + "static": [ + { + "dynamic": { + "key": { + "type": "any" + }, + "value": { + "type": "any" + } + }, + "type": "object" + }, + { + "dynamic": { + "key": { + "type": "any" + }, + "value": { + "type": "any" + } + }, + "type": "object" + } + ], + "type": "array" + }, + "type": "function" + } + }, + { + "name": "graphql.parse_and_verify", + "decl": { + "args": [ + { + "of": [ + { + "type": "string" + }, + { + "dynamic": { + "key": { + "type": "any" + }, + "value": { + "type": "any" + } + }, + "type": "object" + } + ], + "type": "any" + }, + { + "of": [ + { + "type": "string" + }, + { + "dynamic": { + "key": { + "type": "any" + }, + "value": { + "type": "any" + } + }, + "type": "object" + } + ], + "type": "any" + } + ], + "result": { + "static": [ + { + "type": "boolean" + }, + { + "dynamic": { + "key": { + "type": "any" + }, + "value": { + "type": "any" + } + }, + "type": "object" + }, + { + "dynamic": { + "key": { + "type": "any" + }, + "value": { + "type": "any" + } + }, + "type": "object" + } + ], + "type": "array" + }, + "type": "function" + } + }, + { + "name": "graphql.parse_query", + "decl": { + "args": [ + { + "type": "string" + } + ], + "result": { + "dynamic": { + "key": { + "type": "any" + }, + "value": { + "type": "any" + } + }, + "type": "object" + }, + "type": "function" + } + }, + { + "name": "graphql.parse_schema", + "decl": { + "args": [ + { + "type": "string" + } + ], + "result": { + "dynamic": { + "key": { + "type": "any" + }, + "value": { + "type": "any" + } + }, + "type": "object" + }, + "type": "function" + } + }, + { + "name": "graphql.schema_is_valid", + "decl": { + "args": [ + { + "of": [ + { + "type": "string" + }, + { + "dynamic": { + "key": { + "type": "any" + }, + "value": { + "type": "any" + } + }, + "type": "object" + } + ], + "type": "any" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + } + }, + { + "name": "gt", + "decl": { + "args": [ + { + "type": "any" + }, + { + "type": "any" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + }, + "infix": "\u003e" + }, + { + "name": "gte", + "decl": { + "args": [ + { + "type": "any" + }, + { + "type": "any" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + }, + "infix": "\u003e=" + }, + { + "name": "hex.decode", + "decl": { + "args": [ + { + "type": "string" + } + ], + "result": { + "type": "string" + }, + "type": "function" + } + }, + { + "name": "hex.encode", + "decl": { + "args": [ + { + "type": "string" + } + ], + "result": { + "type": "string" + }, + "type": "function" + } + }, + { + "name": "http.send", + "decl": { + "args": [ + { + "dynamic": { + "key": { + "type": "string" + }, + "value": { + "type": "any" + } + }, + "type": "object" + } + ], + "result": { + "dynamic": { + "key": { + "type": "any" + }, + "value": { + "type": "any" + } + }, + "type": "object" + }, + "type": "function" + }, + "nondeterministic": true + }, + { + "name": "indexof", + "decl": { + "args": [ + { + "type": "string" + }, + { + "type": "string" + } + ], + "result": { + "type": "number" + }, + "type": "function" + } + }, + { + "name": "indexof_n", + "decl": { + "args": [ + { + "type": "string" + }, + { + "type": "string" + } + ], + "result": { + "dynamic": { + "type": "number" + }, + "type": "array" + }, + "type": "function" + } + }, + { + "name": "internal.member_2", + "decl": { + "args": [ + { + "type": "any" + }, + { + "type": "any" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + }, + "infix": "in" + }, + { + "name": "internal.member_3", + "decl": { + "args": [ + { + "type": "any" + }, + { + "type": "any" + }, + { + "type": "any" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + }, + "infix": "in" + }, + { + "name": "internal.print", + "decl": { + "args": [ + { + "dynamic": { + "of": { + "type": "any" + }, + "type": "set" + }, + "type": "array" + } + ], + "type": "function" + } + }, + { + "name": "internal.template_string", + "decl": { + "args": [ + { + "dynamic": { + "type": "any" + }, + "type": "array" + } + ], + "result": { + "type": "string" + }, + "type": "function" + } + }, + { + "name": "internal.test_case", + "decl": { + "args": [ + { + "dynamic": { + "type": "any" + }, + "type": "array" + } + ], + "type": "function" + } + }, + { + "name": "intersection", + "decl": { + "args": [ + { + "of": { + "of": { + "type": "any" + }, + "type": "set" + }, + "type": "set" + } + ], + "result": { + "of": { + "type": "any" + }, + "type": "set" + }, + "type": "function" + } + }, + { + "name": "io.jwt.decode", + "decl": { + "args": [ + { + "type": "string" + } + ], + "result": { + "static": [ + { + "dynamic": { + "key": { + "type": "any" + }, + "value": { + "type": "any" + } + }, + "type": "object" + }, + { + "dynamic": { + "key": { + "type": "any" + }, + "value": { + "type": "any" + } + }, + "type": "object" + }, + { + "type": "string" + } + ], + "type": "array" + }, + "type": "function" + } + }, + { + "name": "io.jwt.decode_verify", + "decl": { + "args": [ + { + "type": "string" + }, + { + "dynamic": { + "key": { + "type": "string" + }, + "value": { + "type": "any" + } + }, + "type": "object" + } + ], + "result": { + "static": [ + { + "type": "boolean" + }, + { + "dynamic": { + "key": { + "type": "any" + }, + "value": { + "type": "any" + } + }, + "type": "object" + }, + { + "dynamic": { + "key": { + "type": "any" + }, + "value": { + "type": "any" + } + }, + "type": "object" + } + ], + "type": "array" + }, + "type": "function" + }, + "nondeterministic": true + }, + { + "name": "io.jwt.encode_sign", + "decl": { + "args": [ + { + "dynamic": { + "key": { + "type": "string" + }, + "value": { + "type": "any" + } + }, + "type": "object" + }, + { + "dynamic": { + "key": { + "type": "string" + }, + "value": { + "type": "any" + } + }, + "type": "object" + }, + { + "dynamic": { + "key": { + "type": "string" + }, + "value": { + "type": "any" + } + }, + "type": "object" + } + ], + "result": { + "type": "string" + }, + "type": "function" + }, + "nondeterministic": true + }, + { + "name": "io.jwt.encode_sign_raw", + "decl": { + "args": [ + { + "type": "string" + }, + { + "type": "string" + }, + { + "type": "string" + } + ], + "result": { + "type": "string" + }, + "type": "function" + }, + "nondeterministic": true + }, + { + "name": "io.jwt.verify_eddsa", + "decl": { + "args": [ + { + "type": "string" + }, + { + "type": "string" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + } + }, + { + "name": "io.jwt.verify_es256", + "decl": { + "args": [ + { + "type": "string" + }, + { + "type": "string" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + } + }, + { + "name": "io.jwt.verify_es384", + "decl": { + "args": [ + { + "type": "string" + }, + { + "type": "string" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + } + }, + { + "name": "io.jwt.verify_es512", + "decl": { + "args": [ + { + "type": "string" + }, + { + "type": "string" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + } + }, + { + "name": "io.jwt.verify_hs256", + "decl": { + "args": [ + { + "type": "string" + }, + { + "type": "string" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + } + }, + { + "name": "io.jwt.verify_hs384", + "decl": { + "args": [ + { + "type": "string" + }, + { + "type": "string" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + } + }, + { + "name": "io.jwt.verify_hs512", + "decl": { + "args": [ + { + "type": "string" + }, + { + "type": "string" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + } + }, + { + "name": "io.jwt.verify_ps256", + "decl": { + "args": [ + { + "type": "string" + }, + { + "type": "string" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + } + }, + { + "name": "io.jwt.verify_ps384", + "decl": { + "args": [ + { + "type": "string" + }, + { + "type": "string" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + } + }, + { + "name": "io.jwt.verify_ps512", + "decl": { + "args": [ + { + "type": "string" + }, + { + "type": "string" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + } + }, + { + "name": "io.jwt.verify_rs256", + "decl": { + "args": [ + { + "type": "string" + }, + { + "type": "string" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + } + }, + { + "name": "io.jwt.verify_rs384", + "decl": { + "args": [ + { + "type": "string" + }, + { + "type": "string" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + } + }, + { + "name": "io.jwt.verify_rs512", + "decl": { + "args": [ + { + "type": "string" + }, + { + "type": "string" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + } + }, + { + "name": "is_array", + "decl": { + "args": [ + { + "type": "any" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + } + }, + { + "name": "is_boolean", + "decl": { + "args": [ + { + "type": "any" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + } + }, + { + "name": "is_null", + "decl": { + "args": [ + { + "type": "any" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + } + }, + { + "name": "is_number", + "decl": { + "args": [ + { + "type": "any" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + } + }, + { + "name": "is_object", + "decl": { + "args": [ + { + "type": "any" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + } + }, + { + "name": "is_set", + "decl": { + "args": [ + { + "type": "any" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + } + }, + { + "name": "is_string", + "decl": { + "args": [ + { + "type": "any" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + } + }, + { + "name": "json.filter", + "decl": { + "args": [ + { + "dynamic": { + "key": { + "type": "any" + }, + "value": { + "type": "any" + } + }, + "type": "object" + }, + { + "of": [ + { + "dynamic": { + "of": [ + { + "type": "string" + }, + { + "dynamic": { + "type": "any" + }, + "type": "array" + } + ], + "type": "any" + }, + "type": "array" + }, + { + "of": { + "of": [ + { + "type": "string" + }, + { + "dynamic": { + "type": "any" + }, + "type": "array" + } + ], + "type": "any" + }, + "type": "set" + } + ], + "type": "any" + } + ], + "result": { + "dynamic": { + "key": { + "type": "any" + }, + "value": { + "type": "any" + } + }, + "type": "object" + }, + "type": "function" + } + }, + { + "name": "json.is_valid", + "decl": { + "args": [ + { + "type": "string" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + } + }, + { + "name": "json.marshal", + "decl": { + "args": [ + { + "type": "any" + } + ], + "result": { + "type": "string" + }, + "type": "function" + } + }, + { + "name": "json.marshal_with_options", + "decl": { + "args": [ + { + "type": "any" + }, + { + "dynamic": { + "key": { + "type": "string" + }, + "value": { + "type": "any" + } + }, + "static": [ + { + "key": "indent", + "value": { + "type": "string" + } + }, + { + "key": "prefix", + "value": { + "type": "string" + } + }, + { + "key": "pretty", + "value": { + "type": "boolean" + } + } + ], + "type": "object" + } + ], + "result": { + "type": "string" + }, + "type": "function" + } + }, + { + "name": "json.match_schema", + "decl": { + "args": [ + { + "of": [ + { + "type": "string" + }, + { + "dynamic": { + "key": { + "type": "any" + }, + "value": { + "type": "any" + } + }, + "type": "object" + } + ], + "type": "any" + }, + { + "of": [ + { + "type": "string" + }, + { + "dynamic": { + "key": { + "type": "any" + }, + "value": { + "type": "any" + } + }, + "type": "object" + } + ], + "type": "any" + } + ], + "result": { + "static": [ + { + "type": "boolean" + }, + { + "dynamic": { + "static": [ + { + "key": "desc", + "value": { + "type": "string" + } + }, + { + "key": "error", + "value": { + "type": "string" + } + }, + { + "key": "field", + "value": { + "type": "string" + } + }, + { + "key": "type", + "value": { + "type": "string" + } + } + ], + "type": "object" + }, + "type": "array" + } + ], + "type": "array" + }, + "type": "function" + }, + "nondeterministic": true + }, + { + "name": "json.patch", + "decl": { + "args": [ + { + "type": "any" + }, + { + "dynamic": { + "dynamic": { + "key": { + "type": "any" + }, + "value": { + "type": "any" + } + }, + "static": [ + { + "key": "op", + "value": { + "type": "string" + } + }, + { + "key": "path", + "value": { + "type": "any" + } + } + ], + "type": "object" + }, + "type": "array" + } + ], + "result": { + "type": "any" + }, + "type": "function" + } + }, + { + "name": "json.remove", + "decl": { + "args": [ + { + "dynamic": { + "key": { + "type": "any" + }, + "value": { + "type": "any" + } + }, + "type": "object" + }, + { + "of": [ + { + "dynamic": { + "of": [ + { + "type": "string" + }, + { + "dynamic": { + "type": "any" + }, + "type": "array" + } + ], + "type": "any" + }, + "type": "array" + }, + { + "of": { + "of": [ + { + "type": "string" + }, + { + "dynamic": { + "type": "any" + }, + "type": "array" + } + ], + "type": "any" + }, + "type": "set" + } + ], + "type": "any" + } + ], + "result": { + "dynamic": { + "key": { + "type": "any" + }, + "value": { + "type": "any" + } + }, + "type": "object" + }, + "type": "function" + } + }, + { + "name": "json.unmarshal", + "decl": { + "args": [ + { + "type": "string" + } + ], + "result": { + "type": "any" + }, + "type": "function" + } + }, + { + "name": "json.verify_schema", + "decl": { + "args": [ + { + "of": [ + { + "type": "string" + }, + { + "dynamic": { + "key": { + "type": "any" + }, + "value": { + "type": "any" + } + }, + "type": "object" + } + ], + "type": "any" + } + ], + "result": { + "static": [ + { + "type": "boolean" + }, + { + "of": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "type": "any" + } + ], + "type": "array" + }, + "type": "function" + }, + "nondeterministic": true + }, + { + "name": "lower", + "decl": { + "args": [ + { + "type": "string" + } + ], + "result": { + "type": "string" + }, + "type": "function" + } + }, + { + "name": "lt", + "decl": { + "args": [ + { + "type": "any" + }, + { + "type": "any" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + }, + "infix": "\u003c" + }, + { + "name": "lte", + "decl": { + "args": [ + { + "type": "any" + }, + { + "type": "any" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + }, + "infix": "\u003c=" + }, + { + "name": "max", + "decl": { + "args": [ + { + "of": [ + { + "dynamic": { + "type": "any" + }, + "type": "array" + }, + { + "of": { + "type": "any" + }, + "type": "set" + } + ], + "type": "any" + } + ], + "result": { + "type": "any" + }, + "type": "function" + } + }, + { + "name": "min", + "decl": { + "args": [ + { + "of": [ + { + "dynamic": { + "type": "any" + }, + "type": "array" + }, + { + "of": { + "type": "any" + }, + "type": "set" + } + ], + "type": "any" + } + ], + "result": { + "type": "any" + }, + "type": "function" + } + }, + { + "name": "minus", + "decl": { + "args": [ + { + "of": [ + { + "type": "number" + }, + { + "of": { + "type": "any" + }, + "type": "set" + } + ], + "type": "any" + }, + { + "of": [ + { + "type": "number" + }, + { + "of": { + "type": "any" + }, + "type": "set" + } + ], + "type": "any" + } + ], + "result": { + "of": [ + { + "type": "number" + }, + { + "of": { + "type": "any" + }, + "type": "set" + } + ], + "type": "any" + }, + "type": "function" + }, + "infix": "-" + }, + { + "name": "mul", + "decl": { + "args": [ + { + "type": "number" + }, + { + "type": "number" + } + ], + "result": { + "type": "number" + }, + "type": "function" + }, + "infix": "*" + }, + { + "name": "neq", + "decl": { + "args": [ + { + "type": "any" + }, + { + "type": "any" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + }, + "infix": "!=" + }, + { + "name": "net.cidr_contains", + "decl": { + "args": [ + { + "type": "string" + }, + { + "type": "string" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + } + }, + { + "name": "net.cidr_contains_matches", + "decl": { + "args": [ + { + "of": [ + { + "type": "string" + }, + { + "dynamic": { + "of": [ + { + "type": "string" + }, + { + "dynamic": { + "type": "any" + }, + "type": "array" + } + ], + "type": "any" + }, + "type": "array" + }, + { + "dynamic": { + "key": { + "type": "string" + }, + "value": { + "of": [ + { + "type": "string" + }, + { + "dynamic": { + "type": "any" + }, + "type": "array" + } + ], + "type": "any" + } + }, + "type": "object" + }, + { + "of": { + "of": [ + { + "type": "string" + }, + { + "dynamic": { + "type": "any" + }, + "type": "array" + } + ], + "type": "any" + }, + "type": "set" + } + ], + "type": "any" + }, + { + "of": [ + { + "type": "string" + }, + { + "dynamic": { + "of": [ + { + "type": "string" + }, + { + "dynamic": { + "type": "any" + }, + "type": "array" + } + ], + "type": "any" + }, + "type": "array" + }, + { + "dynamic": { + "key": { + "type": "string" + }, + "value": { + "of": [ + { + "type": "string" + }, + { + "dynamic": { + "type": "any" + }, + "type": "array" + } + ], + "type": "any" + } + }, + "type": "object" + }, + { + "of": { + "of": [ + { + "type": "string" + }, + { + "dynamic": { + "type": "any" + }, + "type": "array" + } + ], + "type": "any" + }, + "type": "set" + } + ], + "type": "any" + } + ], + "result": { + "of": { + "static": [ + { + "type": "any" + }, + { + "type": "any" + } + ], + "type": "array" + }, + "type": "set" + }, + "type": "function" + } + }, + { + "name": "net.cidr_expand", + "decl": { + "args": [ + { + "type": "string" + } + ], + "result": { + "of": { + "type": "string" + }, + "type": "set" + }, + "type": "function" + } + }, + { + "name": "net.cidr_intersects", + "decl": { + "args": [ + { + "type": "string" + }, + { + "type": "string" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + } + }, + { + "name": "net.cidr_is_valid", + "decl": { + "args": [ + { + "type": "string" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + } + }, + { + "name": "net.cidr_merge", + "decl": { + "args": [ + { + "of": [ + { + "dynamic": { + "of": [ + { + "type": "string" + } + ], + "type": "any" + }, + "type": "array" + }, + { + "of": { + "type": "string" + }, + "type": "set" + } + ], + "type": "any" + } + ], + "result": { + "of": { + "type": "string" + }, + "type": "set" + }, + "type": "function" + } + }, + { + "name": "net.cidr_overlap", + "decl": { + "args": [ + { + "type": "string" + }, + { + "type": "string" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + }, + "deprecated": true + }, + { + "name": "net.lookup_ip_addr", + "decl": { + "args": [ + { + "type": "string" + } + ], + "result": { + "of": { + "type": "string" + }, + "type": "set" + }, + "type": "function" + }, + "nondeterministic": true + }, + { + "name": "numbers.range", + "decl": { + "args": [ + { + "type": "number" + }, + { + "type": "number" + } + ], + "result": { + "dynamic": { + "type": "number" + }, + "type": "array" + }, + "type": "function" + } + }, + { + "name": "numbers.range_step", + "decl": { + "args": [ + { + "type": "number" + }, + { + "type": "number" + }, + { + "type": "number" + } + ], + "result": { + "dynamic": { + "type": "number" + }, + "type": "array" + }, + "type": "function" + } + }, + { + "name": "object.filter", + "decl": { + "args": [ + { + "dynamic": { + "key": { + "type": "any" + }, + "value": { + "type": "any" + } + }, + "type": "object" + }, + { + "of": [ + { + "dynamic": { + "type": "any" + }, + "type": "array" + }, + { + "dynamic": { + "key": { + "type": "any" + }, + "value": { + "type": "any" + } + }, + "type": "object" + }, + { + "of": { + "type": "any" + }, + "type": "set" + } + ], + "type": "any" + } + ], + "result": { + "dynamic": { + "key": { + "type": "any" + }, + "value": { + "type": "any" + } + }, + "type": "object" + }, + "type": "function" + } + }, + { + "name": "object.get", + "decl": { + "args": [ + { + "dynamic": { + "key": { + "type": "any" + }, + "value": { + "type": "any" + } + }, + "type": "object" + }, + { + "type": "any" + }, + { + "type": "any" + } + ], + "result": { + "type": "any" + }, + "type": "function" + } + }, + { + "name": "object.keys", + "decl": { + "args": [ + { + "dynamic": { + "key": { + "type": "any" + }, + "value": { + "type": "any" + } + }, + "type": "object" + } + ], + "result": { + "of": { + "type": "any" + }, + "type": "set" + }, + "type": "function" + } + }, + { + "name": "object.remove", + "decl": { + "args": [ + { + "dynamic": { + "key": { + "type": "any" + }, + "value": { + "type": "any" + } + }, + "type": "object" + }, + { + "of": [ + { + "dynamic": { + "type": "any" + }, + "type": "array" + }, + { + "dynamic": { + "key": { + "type": "any" + }, + "value": { + "type": "any" + } + }, + "type": "object" + }, + { + "of": { + "type": "any" + }, + "type": "set" + } + ], + "type": "any" + } + ], + "result": { + "dynamic": { + "key": { + "type": "any" + }, + "value": { + "type": "any" + } + }, + "type": "object" + }, + "type": "function" + } + }, + { + "name": "object.subset", + "decl": { + "args": [ + { + "of": [ + { + "dynamic": { + "type": "any" + }, + "type": "array" + }, + { + "dynamic": { + "key": { + "type": "any" + }, + "value": { + "type": "any" + } + }, + "type": "object" + }, + { + "of": { + "type": "any" + }, + "type": "set" + } + ], + "type": "any" + }, + { + "of": [ + { + "dynamic": { + "type": "any" + }, + "type": "array" + }, + { + "dynamic": { + "key": { + "type": "any" + }, + "value": { + "type": "any" + } + }, + "type": "object" + }, + { + "of": { + "type": "any" + }, + "type": "set" + } + ], + "type": "any" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + } + }, + { + "name": "object.union", + "decl": { + "args": [ + { + "dynamic": { + "key": { + "type": "any" + }, + "value": { + "type": "any" + } + }, + "type": "object" + }, + { + "dynamic": { + "key": { + "type": "any" + }, + "value": { + "type": "any" + } + }, + "type": "object" + } + ], + "result": { + "dynamic": { + "key": { + "type": "any" + }, + "value": { + "type": "any" + } + }, + "type": "object" + }, + "type": "function" + } + }, + { + "name": "object.union_n", + "decl": { + "args": [ + { + "dynamic": { + "dynamic": { + "key": { + "type": "any" + }, + "value": { + "type": "any" + } + }, + "type": "object" + }, + "type": "array" + } + ], + "result": { + "dynamic": { + "key": { + "type": "any" + }, + "value": { + "type": "any" + } + }, + "type": "object" + }, + "type": "function" + } + }, + { + "name": "opa.runtime", + "decl": { + "result": { + "dynamic": { + "key": { + "type": "string" + }, + "value": { + "type": "any" + } + }, + "type": "object" + }, + "type": "function" + }, + "nondeterministic": true + }, + { + "name": "or", + "decl": { + "args": [ + { + "of": { + "type": "any" + }, + "type": "set" + }, + { + "of": { + "type": "any" + }, + "type": "set" + } + ], + "result": { + "of": { + "type": "any" + }, + "type": "set" + }, + "type": "function" + }, + "infix": "|" + }, + { + "name": "plus", + "decl": { + "args": [ + { + "type": "number" + }, + { + "type": "number" + } + ], + "result": { + "type": "number" + }, + "type": "function" + }, + "infix": "+" + }, + { + "name": "print", + "decl": { + "type": "function", + "variadic": { + "type": "any" + } + } + }, + { + "name": "product", + "decl": { + "args": [ + { + "of": [ + { + "dynamic": { + "type": "number" + }, + "type": "array" + }, + { + "of": { + "type": "number" + }, + "type": "set" + } + ], + "type": "any" + } + ], + "result": { + "type": "number" + }, + "type": "function" + } + }, + { + "name": "providers.aws.sign_req", + "decl": { + "args": [ + { + "dynamic": { + "key": { + "type": "string" + }, + "value": { + "type": "any" + } + }, + "type": "object" + }, + { + "dynamic": { + "key": { + "type": "string" + }, + "value": { + "type": "any" + } + }, + "type": "object" + }, + { + "type": "number" + } + ], + "result": { + "dynamic": { + "key": { + "type": "any" + }, + "value": { + "type": "any" + } + }, + "type": "object" + }, + "type": "function" + } + }, + { + "name": "rand.intn", + "decl": { + "args": [ + { + "type": "string" + }, + { + "type": "number" + } + ], + "result": { + "type": "number" + }, + "type": "function" + }, + "nondeterministic": true + }, + { + "name": "re_match", + "decl": { + "args": [ + { + "type": "string" + }, + { + "type": "string" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + }, + "deprecated": true + }, + { + "name": "regex.find_all_string_submatch_n", + "decl": { + "args": [ + { + "type": "string" + }, + { + "type": "string" + }, + { + "type": "number" + } + ], + "result": { + "dynamic": { + "dynamic": { + "type": "string" + }, + "type": "array" + }, + "type": "array" + }, + "type": "function" + } + }, + { + "name": "regex.find_n", + "decl": { + "args": [ + { + "type": "string" + }, + { + "type": "string" + }, + { + "type": "number" + } + ], + "result": { + "dynamic": { + "type": "string" + }, + "type": "array" + }, + "type": "function" + } + }, + { + "name": "regex.globs_match", + "decl": { + "args": [ + { + "type": "string" + }, + { + "type": "string" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + } + }, + { + "name": "regex.is_valid", + "decl": { + "args": [ + { + "type": "string" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + } + }, + { + "name": "regex.match", + "decl": { + "args": [ + { + "type": "string" + }, + { + "type": "string" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + } + }, + { + "name": "regex.replace", + "decl": { + "args": [ + { + "type": "string" + }, + { + "type": "string" + }, + { + "type": "string" + } + ], + "result": { + "type": "string" + }, + "type": "function" + } + }, + { + "name": "regex.split", + "decl": { + "args": [ + { + "type": "string" + }, + { + "type": "string" + } + ], + "result": { + "dynamic": { + "type": "string" + }, + "type": "array" + }, + "type": "function" + } + }, + { + "name": "regex.template_match", + "decl": { + "args": [ + { + "type": "string" + }, + { + "type": "string" + }, + { + "type": "string" + }, + { + "type": "string" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + } + }, + { + "name": "rego.metadata.chain", + "decl": { + "result": { + "dynamic": { + "type": "any" + }, + "type": "array" + }, + "type": "function" + } + }, + { + "name": "rego.metadata.rule", + "decl": { + "result": { + "type": "any" + }, + "type": "function" + } + }, + { + "name": "rego.parse_module", + "decl": { + "args": [ + { + "type": "string" + }, + { + "type": "string" + } + ], + "result": { + "dynamic": { + "key": { + "type": "string" + }, + "value": { + "type": "any" + } + }, + "type": "object" + }, + "type": "function" + } + }, + { + "name": "rem", + "decl": { + "args": [ + { + "type": "number" + }, + { + "type": "number" + } + ], + "result": { + "type": "number" + }, + "type": "function" + }, + "infix": "%" + }, + { + "name": "replace", + "decl": { + "args": [ + { + "type": "string" + }, + { + "type": "string" + }, + { + "type": "string" + } + ], + "result": { + "type": "string" + }, + "type": "function" + } + }, + { + "name": "round", + "decl": { + "args": [ + { + "type": "number" + } + ], + "result": { + "type": "number" + }, + "type": "function" + } + }, + { + "name": "semver.compare", + "decl": { + "args": [ + { + "type": "string" + }, + { + "type": "string" + } + ], + "result": { + "type": "number" + }, + "type": "function" + } + }, + { + "name": "semver.is_valid", + "decl": { + "args": [ + { + "type": "any" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + } + }, + { + "name": "set_diff", + "decl": { + "args": [ + { + "of": { + "type": "any" + }, + "type": "set" + }, + { + "of": { + "type": "any" + }, + "type": "set" + } + ], + "result": { + "of": { + "type": "any" + }, + "type": "set" + }, + "type": "function" + }, + "deprecated": true + }, + { + "name": "sort", + "decl": { + "args": [ + { + "of": [ + { + "dynamic": { + "type": "any" + }, + "type": "array" + }, + { + "of": { + "type": "any" + }, + "type": "set" + } + ], + "type": "any" + } + ], + "result": { + "dynamic": { + "type": "any" + }, + "type": "array" + }, + "type": "function" + } + }, + { + "name": "split", + "decl": { + "args": [ + { + "type": "string" + }, + { + "type": "string" + } + ], + "result": { + "dynamic": { + "type": "string" + }, + "type": "array" + }, + "type": "function" + } + }, + { + "name": "sprintf", + "decl": { + "args": [ + { + "type": "string" + }, + { + "dynamic": { + "type": "any" + }, + "type": "array" + } + ], + "result": { + "type": "string" + }, + "type": "function" + } + }, + { + "name": "startswith", + "decl": { + "args": [ + { + "type": "string" + }, + { + "type": "string" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + } + }, + { + "name": "strings.any_prefix_match", + "decl": { + "args": [ + { + "of": [ + { + "type": "string" + }, + { + "dynamic": { + "type": "string" + }, + "type": "array" + }, + { + "of": { + "type": "string" + }, + "type": "set" + } + ], + "type": "any" + }, + { + "of": [ + { + "type": "string" + }, + { + "dynamic": { + "type": "string" + }, + "type": "array" + }, + { + "of": { + "type": "string" + }, + "type": "set" + } + ], + "type": "any" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + } + }, + { + "name": "strings.any_suffix_match", + "decl": { + "args": [ + { + "of": [ + { + "type": "string" + }, + { + "dynamic": { + "type": "string" + }, + "type": "array" + }, + { + "of": { + "type": "string" + }, + "type": "set" + } + ], + "type": "any" + }, + { + "of": [ + { + "type": "string" + }, + { + "dynamic": { + "type": "string" + }, + "type": "array" + }, + { + "of": { + "type": "string" + }, + "type": "set" + } + ], + "type": "any" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + } + }, + { + "name": "strings.count", + "decl": { + "args": [ + { + "type": "string" + }, + { + "type": "string" + } + ], + "result": { + "type": "number" + }, + "type": "function" + } + }, + { + "name": "strings.render_template", + "decl": { + "args": [ + { + "type": "string" + }, + { + "dynamic": { + "key": { + "type": "string" + }, + "value": { + "type": "any" + } + }, + "type": "object" + } + ], + "result": { + "type": "string" + }, + "type": "function" + } + }, + { + "name": "strings.replace_n", + "decl": { + "args": [ + { + "dynamic": { + "key": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "type": "object" + }, + { + "type": "string" + } + ], + "result": { + "type": "string" + }, + "type": "function" + } + }, + { + "name": "strings.reverse", + "decl": { + "args": [ + { + "type": "string" + } + ], + "result": { + "type": "string" + }, + "type": "function" + } + }, + { + "name": "strings.split_n", + "decl": { + "args": [ + { + "type": "string" + }, + { + "type": "string" + }, + { + "type": "number" + } + ], + "result": { + "dynamic": { + "type": "string" + }, + "type": "array" + }, + "type": "function" + } + }, + { + "name": "substring", + "decl": { + "args": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "number" + } + ], + "result": { + "type": "string" + }, + "type": "function" + } + }, + { + "name": "sum", + "decl": { + "args": [ + { + "of": [ + { + "dynamic": { + "type": "number" + }, + "type": "array" + }, + { + "of": { + "type": "number" + }, + "type": "set" + } + ], + "type": "any" + } + ], + "result": { + "type": "number" + }, + "type": "function" + } + }, + { + "name": "time.add_date", + "decl": { + "args": [ + { + "type": "number" + }, + { + "type": "number" + }, + { + "type": "number" + }, + { + "type": "number" + } + ], + "result": { + "type": "number" + }, + "type": "function" + } + }, + { + "name": "time.clock", + "decl": { + "args": [ + { + "of": [ + { + "type": "number" + }, + { + "static": [ + { + "type": "number" + }, + { + "type": "string" + } + ], + "type": "array" + } + ], + "type": "any" + } + ], + "result": { + "static": [ + { + "type": "number" + }, + { + "type": "number" + }, + { + "type": "number" + } + ], + "type": "array" + }, + "type": "function" + } + }, + { + "name": "time.date", + "decl": { + "args": [ + { + "of": [ + { + "type": "number" + }, + { + "static": [ + { + "type": "number" + }, + { + "type": "string" + } + ], + "type": "array" + } + ], + "type": "any" + } + ], + "result": { + "static": [ + { + "type": "number" + }, + { + "type": "number" + }, + { + "type": "number" + } + ], + "type": "array" + }, + "type": "function" + } + }, + { + "name": "time.diff", + "decl": { + "args": [ + { + "of": [ + { + "type": "number" + }, + { + "static": [ + { + "type": "number" + }, + { + "type": "string" + } + ], + "type": "array" + } + ], + "type": "any" + }, + { + "of": [ + { + "type": "number" + }, + { + "static": [ + { + "type": "number" + }, + { + "type": "string" + } + ], + "type": "array" + } + ], + "type": "any" + } + ], + "result": { + "static": [ + { + "type": "number" + }, + { + "type": "number" + }, + { + "type": "number" + }, + { + "type": "number" + }, + { + "type": "number" + }, + { + "type": "number" + } + ], + "type": "array" + }, + "type": "function" + } + }, + { + "name": "time.format", + "decl": { + "args": [ + { + "of": [ + { + "type": "number" + }, + { + "static": [ + { + "type": "number" + }, + { + "type": "string" + } + ], + "type": "array" + }, + { + "static": [ + { + "type": "number" + }, + { + "type": "string" + }, + { + "type": "string" + } + ], + "type": "array" + } + ], + "type": "any" + } + ], + "result": { + "type": "string" + }, + "type": "function" + } + }, + { + "name": "time.now_ns", + "decl": { + "result": { + "type": "number" + }, + "type": "function" + }, + "nondeterministic": true + }, + { + "name": "time.parse_duration_ns", + "decl": { + "args": [ + { + "type": "string" + } + ], + "result": { + "type": "number" + }, + "type": "function" + } + }, + { + "name": "time.parse_ns", + "decl": { + "args": [ + { + "type": "string" + }, + { + "type": "string" + } + ], + "result": { + "type": "number" + }, + "type": "function" + } + }, + { + "name": "time.parse_rfc3339_ns", + "decl": { + "args": [ + { + "type": "string" + } + ], + "result": { + "type": "number" + }, + "type": "function" + } + }, + { + "name": "time.weekday", + "decl": { + "args": [ + { + "of": [ + { + "type": "number" + }, + { + "static": [ + { + "type": "number" + }, + { + "type": "string" + } + ], + "type": "array" + } + ], + "type": "any" + } + ], + "result": { + "type": "string" + }, + "type": "function" + } + }, + { + "name": "to_number", + "decl": { + "args": [ + { + "of": [ + { + "type": "null" + }, + { + "type": "boolean" + }, + { + "type": "number" + }, + { + "type": "string" + } + ], + "type": "any" + } + ], + "result": { + "type": "number" + }, + "type": "function" + } + }, + { + "name": "trace", + "decl": { + "args": [ + { + "type": "string" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + } + }, + { + "name": "trim", + "decl": { + "args": [ + { + "type": "string" + }, + { + "type": "string" + } + ], + "result": { + "type": "string" + }, + "type": "function" + } + }, + { + "name": "trim_left", + "decl": { + "args": [ + { + "type": "string" + }, + { + "type": "string" + } + ], + "result": { + "type": "string" + }, + "type": "function" + } + }, + { + "name": "trim_prefix", + "decl": { + "args": [ + { + "type": "string" + }, + { + "type": "string" + } + ], + "result": { + "type": "string" + }, + "type": "function" + } + }, + { + "name": "trim_right", + "decl": { + "args": [ + { + "type": "string" + }, + { + "type": "string" + } + ], + "result": { + "type": "string" + }, + "type": "function" + } + }, + { + "name": "trim_space", + "decl": { + "args": [ + { + "type": "string" + } + ], + "result": { + "type": "string" + }, + "type": "function" + } + }, + { + "name": "trim_suffix", + "decl": { + "args": [ + { + "type": "string" + }, + { + "type": "string" + } + ], + "result": { + "type": "string" + }, + "type": "function" + } + }, + { + "name": "type_name", + "decl": { + "args": [ + { + "type": "any" + } + ], + "result": { + "type": "string" + }, + "type": "function" + } + }, + { + "name": "union", + "decl": { + "args": [ + { + "of": { + "of": { + "type": "any" + }, + "type": "set" + }, + "type": "set" + } + ], + "result": { + "of": { + "type": "any" + }, + "type": "set" + }, + "type": "function" + } + }, + { + "name": "units.parse", + "decl": { + "args": [ + { + "type": "string" + } + ], + "result": { + "type": "number" + }, + "type": "function" + } + }, + { + "name": "units.parse_bytes", + "decl": { + "args": [ + { + "type": "string" + } + ], + "result": { + "type": "number" + }, + "type": "function" + } + }, + { + "name": "upper", + "decl": { + "args": [ + { + "type": "string" + } + ], + "result": { + "type": "string" + }, + "type": "function" + } + }, + { + "name": "uri.is_valid", + "decl": { + "args": [ + { + "type": "string" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + } + }, + { + "name": "uri.parse", + "decl": { + "args": [ + { + "type": "string" + } + ], + "result": { + "dynamic": { + "key": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "type": "object" + }, + "type": "function" + } + }, + { + "name": "urlquery.decode", + "decl": { + "args": [ + { + "type": "string" + } + ], + "result": { + "type": "string" + }, + "type": "function" + } + }, + { + "name": "urlquery.decode_object", + "decl": { + "args": [ + { + "type": "string" + } + ], + "result": { + "dynamic": { + "key": { + "type": "string" + }, + "value": { + "dynamic": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "type": "function" + } + }, + { + "name": "urlquery.encode", + "decl": { + "args": [ + { + "type": "string" + } + ], + "result": { + "type": "string" + }, + "type": "function" + } + }, + { + "name": "urlquery.encode_object", + "decl": { + "args": [ + { + "dynamic": { + "key": { + "type": "string" + }, + "value": { + "of": [ + { + "type": "string" + }, + { + "dynamic": { + "type": "string" + }, + "type": "array" + }, + { + "of": { + "type": "string" + }, + "type": "set" + } + ], + "type": "any" + } + }, + "type": "object" + } + ], + "result": { + "type": "string" + }, + "type": "function" + } + }, + { + "name": "uuid.parse", + "decl": { + "args": [ + { + "type": "string" + } + ], + "result": { + "dynamic": { + "key": { + "type": "string" + }, + "value": { + "type": "any" + } + }, + "type": "object" + }, + "type": "function" + } + }, + { + "name": "uuid.rfc4122", + "decl": { + "args": [ + { + "type": "string" + } + ], + "result": { + "type": "string" + }, + "type": "function" + }, + "nondeterministic": true + }, + { + "name": "walk", + "decl": { + "args": [ + { + "type": "any" + } + ], + "result": { + "static": [ + { + "dynamic": { + "type": "any" + }, + "type": "array" + }, + { + "type": "any" + } + ], + "type": "array" + }, + "type": "function" + }, + "relation": true + }, + { + "name": "yaml.is_valid", + "decl": { + "args": [ + { + "type": "string" + } + ], + "result": { + "type": "boolean" + }, + "type": "function" + } + }, + { + "name": "yaml.marshal", + "decl": { + "args": [ + { + "type": "any" + } + ], + "result": { + "type": "string" + }, + "type": "function" + } + }, + { + "name": "yaml.unmarshal", + "decl": { + "args": [ + { + "type": "string" + } + ], + "result": { + "type": "any" + }, + "type": "function" + } + } + ], + "future_keywords": [ + "and", + "not", + "or" + ], + "wasm_abi_versions": [ + { + "version": 1, + "minor_version": 1 + }, + { + "version": 1, + "minor_version": 2 + } + ], + "features": [ + "keywords_in_refs", + "rego_v1", + "template_strings" + ] +} diff --git a/constraint/vendor/github.com/open-policy-agent/opa/internal/cidr/merge/merge.go b/constraint/vendor/github.com/open-policy-agent/opa/internal/cidr/merge/merge.go index 85695b129..e92c8d485 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/internal/cidr/merge/merge.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/internal/cidr/merge/merge.go @@ -22,6 +22,7 @@ import ( "encoding/binary" "math/big" "net" + "slices" ) const ( @@ -61,7 +62,7 @@ func RangeToCIDRs(firstIP, lastIP net.IP) []*net.IPNet { } else { bitLen = ipv6BitLen } - _, _, right := partitionCIDR(spanningCIDR, net.IPNet{IP: prevFirstRangeIP, Mask: net.CIDRMask(bitLen, bitLen)}) + _, right := partitionCIDR(spanningCIDR, net.IPNet{IP: prevFirstRangeIP, Mask: net.CIDRMask(bitLen, bitLen)}) // Append all CIDRs but the first, as this CIDR includes the upper // bound of the spanning CIDR, which we still need to partition on. @@ -84,7 +85,7 @@ func RangeToCIDRs(firstIP, lastIP net.IP) []*net.IPNet { } else { bitLen = ipv6BitLen } - left, _, _ := partitionCIDR(spanningCIDR, net.IPNet{IP: nextFirstRangeIP, Mask: net.CIDRMask(bitLen, bitLen)}) + left, _ := partitionCIDR(spanningCIDR, net.IPNet{IP: nextFirstRangeIP, Mask: net.CIDRMask(bitLen, bitLen)}) cidrList = append(cidrList, left...) } else { // Otherwise, there is no need to partition; just use add the spanning @@ -110,8 +111,7 @@ func GetAddressRange(ipNet net.IPNet) (net.IP, net.IP) { lastIP = append(v4Mappedv6Prefix, lastIP...) } - lastIPMask := make(net.IPMask, len(ipNet.Mask)) - copy(lastIPMask, ipNet.Mask) + lastIPMask := slices.Clone(ipNet.Mask) for i := range lastIPMask { lastIPMask[len(lastIPMask)-i-1] = ^lastIPMask[len(lastIPMask)-i-1] lastIP[net.IPv6len-i-1] |= lastIPMask[len(lastIPMask)-i-1] @@ -127,8 +127,7 @@ func GetPreviousIP(ip net.IP) net.IP { return ip } - previousIP := make(net.IP, len(ip)) - copy(previousIP, ip) + previousIP := slices.Clone(ip) var overflow bool var lowerByteBound int @@ -215,7 +214,7 @@ func createSpanningCIDR(firstIP, lastIP *net.IP) net.IPNet { // contained within the targetCIDR (nil otherwise), and the // third is a list containing the networks to the right of the excludeCIDR in // the partition. -func partitionCIDR(targetCIDR net.IPNet, excludeCIDR net.IPNet) ([]*net.IPNet, []*net.IPNet, []*net.IPNet) { +func partitionCIDR(targetCIDR net.IPNet, excludeCIDR net.IPNet) ([]*net.IPNet, []*net.IPNet) { var targetIsIPv4 bool if targetCIDR.IP.To4() != nil { targetIsIPv4 = true @@ -228,25 +227,20 @@ func partitionCIDR(targetCIDR net.IPNet, excludeCIDR net.IPNet) ([]*net.IPNet, [ excludeMaskSize, _ := excludeCIDR.Mask.Size() if bytes.Compare(excludeLastIP, targetFirstIP) < 0 { - return nil, nil, []*net.IPNet{&targetCIDR} + return nil, []*net.IPNet{&targetCIDR} } else if bytes.Compare(targetLastIP, excludeFirstIP) < 0 { - return []*net.IPNet{&targetCIDR}, nil, nil + return []*net.IPNet{&targetCIDR}, nil } if targetMaskSize >= excludeMaskSize { - return nil, []*net.IPNet{&targetCIDR}, nil + return nil, nil } left := []*net.IPNet{} right := []*net.IPNet{} newPrefixLen := targetMaskSize + 1 - - targetFirstCopy := make(net.IP, len(targetFirstIP)) - copy(targetFirstCopy, targetFirstIP) - - iLowerOld := make(net.IP, len(targetFirstCopy)) - copy(iLowerOld, targetFirstCopy) + targetFirstCopy := slices.Clone(targetFirstIP) // Since golang only supports up to unsigned 64-bit integers, and we need // to perform addition on addresses, use math/big library, which allows @@ -258,12 +252,9 @@ func partitionCIDR(targetCIDR net.IPNet, excludeCIDR net.IPNet) ([]*net.IPNet, [ iUpper := big.NewInt(0) iLower = iLower.SetBytes(targetFirstCopy) - var bitLen int - + bitLen := ipv6BitLen if targetIsIPv4 { bitLen = ipv4BitLen - } else { - bitLen = ipv6BitLen } shiftAmount := (uint)(bitLen - newPrefixLen) @@ -297,7 +288,6 @@ func partitionCIDR(targetCIDR net.IPNet, excludeCIDR net.IPNet) ([]*net.IPNet, [ iUpperBytes = append(zeroBytes, iUpper.Bytes()...) } else { iUpperBytes = iUpper.Bytes() - } iLowerBytesLen := len(iLower.Bytes()) @@ -330,11 +320,9 @@ func partitionCIDR(targetCIDR net.IPNet, excludeCIDR net.IPNet) ([]*net.IPNet, [ iLower = iLower.Set(matched) iUpper = iUpper.Add(matched, big.NewInt(0).Lsh(big.NewInt(1), uint(bitLen-newPrefixLen))) - } - excludeList := []*net.IPNet{&excludeCIDR} - return left, excludeList, right + return left, right } func getNextIP(ip net.IP) net.IP { diff --git a/constraint/vendor/github.com/open-policy-agent/opa/internal/compiler/wasm/opa/callgraph.csv b/constraint/vendor/github.com/open-policy-agent/opa/internal/compiler/wasm/opa/callgraph.csv index 10dc4d482..177aaee91 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/internal/compiler/wasm/opa/callgraph.csv +++ b/constraint/vendor/github.com/open-policy-agent/opa/internal/compiler/wasm/opa/callgraph.csv @@ -636,11 +636,16 @@ opa_strings_replace,opa_realloc opa_strings_replace,memcpy opa_strings_replace,opa_string_allocated opa_strings_replace_n,opa_value_type +opa_strings_replace_n,opa_object_keys opa_strings_replace_n,opa_malloc +opa_strings_replace_n,memset +opa_strings_replace_n,opa_value_get +opa_strings_replace_n,opa_strncmp +opa_strings_replace_n,opa_realloc opa_strings_replace_n,memcpy opa_strings_replace_n,opa_string_allocated -opa_strings_replace_n,opa_strings_replace -opa_strings_replace_n,opa_value_free +opa_strings_replace_n,opa_free +opa_strings_replace_n,opa_array_free opa_strings_reverse,opa_value_type opa_strings_reverse,opa_malloc opa_strings_reverse,opa_unicode_decode_utf8 diff --git a/constraint/vendor/github.com/open-policy-agent/opa/internal/compiler/wasm/opa/opa.wasm b/constraint/vendor/github.com/open-policy-agent/opa/internal/compiler/wasm/opa/opa.wasm index 25d39a83e..6be1842dd 100644 Binary files a/constraint/vendor/github.com/open-policy-agent/opa/internal/compiler/wasm/opa/opa.wasm and b/constraint/vendor/github.com/open-policy-agent/opa/internal/compiler/wasm/opa/opa.wasm differ diff --git a/constraint/vendor/github.com/open-policy-agent/opa/internal/compiler/wasm/wasm.go b/constraint/vendor/github.com/open-policy-agent/opa/internal/compiler/wasm/wasm.go index b7f1a2781..95c02d9e2 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/internal/compiler/wasm/wasm.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/internal/compiler/wasm/wasm.go @@ -1026,9 +1026,7 @@ func (c *Compiler) compileBlock(block *ir.Block) ([]instruction.Instruction, err return nil, err } case *ir.CallDynamicStmt: - if err := c.compileCallDynamicStmt(stmt, &instrs); err != nil { - return nil, err - } + c.compileCallDynamicStmt(stmt, &instrs) case *ir.WithStmt: if err := c.compileWithStmt(stmt, &instrs); err != nil { return instrs, err @@ -1485,7 +1483,7 @@ func (c *Compiler) compileUpsert(local ir.Local, path []int, value ir.Operand, _ ) } -func (c *Compiler) compileCallDynamicStmt(stmt *ir.CallDynamicStmt, result *[]instruction.Instruction) error { +func (c *Compiler) compileCallDynamicStmt(stmt *ir.CallDynamicStmt, result *[]instruction.Instruction) { instrs := make([]instruction.Instruction, 0, 3+3*len(stmt.Path)+len(stmt.Args)+10) larray := c.genLocal() lidx := c.genLocal() @@ -1533,7 +1531,6 @@ func (c *Compiler) compileCallDynamicStmt(stmt *ir.CallDynamicStmt, result *[]in ) *result = append(*result, instrs...) - return nil } func (c *Compiler) compileCallStmt(stmt *ir.CallStmt, result *[]instruction.Instruction) error { diff --git a/constraint/vendor/github.com/open-policy-agent/opa/internal/deepcopy/deepcopy.go b/constraint/vendor/github.com/open-policy-agent/opa/internal/deepcopy/deepcopy.go index dc3a231bc..b0e0bb2fb 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/internal/deepcopy/deepcopy.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/internal/deepcopy/deepcopy.go @@ -4,17 +4,15 @@ package deepcopy +import "github.com/open-policy-agent/opa/v1/util" + // DeepCopy performs a recursive deep copy for nested slices/maps and // returns the copied object. Supports []any // and map[string]any only func DeepCopy(val any) any { switch val := val.(type) { case []any: - cpy := make([]any, len(val)) - for i := range cpy { - cpy[i] = DeepCopy(val[i]) - } - return cpy + return util.Map(val, DeepCopy) case map[string]any: return Map(val) default: diff --git a/constraint/vendor/github.com/open-policy-agent/opa/internal/future/filter_imports.go b/constraint/vendor/github.com/open-policy-agent/opa/internal/future/filter_imports.go index 27ca5559f..c8d136c76 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/internal/future/filter_imports.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/internal/future/filter_imports.go @@ -4,46 +4,36 @@ package future -import "github.com/open-policy-agent/opa/v1/ast" +import ( + "slices" + + "github.com/open-policy-agent/opa/v1/ast" +) // FilterFutureImports filters OUT any future imports from the passed slice of // `*ast.Import`s. func FilterFutureImports(imps []*ast.Import) []*ast.Import { - ret := []*ast.Import{} - for _, imp := range imps { - path := imp.Path.Value.(ast.Ref) - if !ast.FutureRootDocument.Equal(path[0]) { - ret = append(ret, imp) - } - } - return ret + return slices.DeleteFunc(slices.Clone(imps), isFutureKeywordImport) } // IsAllFutureKeywords returns true if the passed *ast.Import is `future.keywords` 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.InternedTerm("keywords")) + return len(path) == 2 && path.HasPrefix(ast.FutureKeywordsRef) } // IsFutureKeyword returns true if the passed *ast.Import is `future.keywords.{kw}` 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.InternedTerm("keywords")) && - path[2].Equal(ast.StringTerm(kw)) + return len(path) == 3 && path.HasPrefix(ast.FutureKeywordsRef) && path[2].Equal(ast.InternedTerm(kw)) } func WhichFutureKeyword(imp *ast.Import) (string, bool) { + name := imp.Name().String() + return name, imp.Alias == "" && IsFutureKeyword(imp, name) +} + +func isFutureKeywordImport(imp *ast.Import) bool { path := imp.Path.Value.(ast.Ref) - if len(path) == 3 && - ast.FutureRootDocument.Equal(path[0]) && - path[1].Equal(ast.InternedTerm("keywords")) { - if str, ok := path[2].Value.(ast.String); ok { - return string(str), true - } - } - return "", false + return len(path) > 0 && path.HasPrefix(ast.FutureKeywordsRef[:1]) } diff --git a/constraint/vendor/github.com/open-policy-agent/opa/internal/future/parser_opts.go b/constraint/vendor/github.com/open-policy-agent/opa/internal/future/parser_opts.go index eaeb87e29..76d30dc51 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/internal/future/parser_opts.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/internal/future/parser_opts.go @@ -15,16 +15,14 @@ import ( // `ast.ParserOptions` that can be used to parse a statement according to the // included "future.keywords" and "future.keywords.xyz" imports. func ParserOptionsFromFutureImports(imports []*ast.Import) (ast.ParserOptions, error) { - popts := ast.ParserOptions{ - FutureKeywords: []string{}, - } + popts := ast.ParserOptions{} for _, imp := range imports { path := imp.Path.Value.(ast.Ref) if !ast.FutureRootDocument.Equal(path[0]) { continue } if len(path) >= 2 { - if string(path[1].Value.(ast.String)) != "keywords" { + if !path.HasPrefix(ast.FutureKeywordsRef) { return popts, fmt.Errorf("unknown future import: %v", imp) } if len(path) == 2 { diff --git a/constraint/vendor/github.com/open-policy-agent/opa/internal/planner/planner.go b/constraint/vendor/github.com/open-policy-agent/opa/internal/planner/planner.go index e5a62a2e0..558d71da9 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/internal/planner/planner.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/internal/planner/planner.go @@ -52,6 +52,7 @@ type Planner struct { allRules map[*ast.Rule]bool // all rules parsed from input modules, used to track unplanned rules for additional reporting (e.g. coverage) plannedRules map[*ast.Rule]bool + planning map[string]struct{} // ground path prefixes currently being planned unplannedRules bool // whether to populate policy.UnplannedRules } @@ -91,6 +92,7 @@ func New() *Planner { allRules: map[*ast.Rule]bool{}, plannedRules: map[*ast.Rule]bool{}, + planning: map[string]struct{}{}, } } @@ -133,18 +135,13 @@ func (p *Planner) WithUnplannedRules(yes bool) *Planner { // Plan returns a IR plan for the policy query. func (p *Planner) Plan() (*ir.Policy, error) { - - if err := p.buildFunctrie(); err != nil { - return nil, err - } + p.buildFunctrie() if err := p.planQueries(); err != nil { return nil, err } - if err := p.planExterns(); err != nil { - return nil, err - } + p.planExterns() if p.unplannedRules { p.buildUnplannedRules() @@ -172,8 +169,7 @@ func (p *Planner) buildUnplannedRules() { }) } -func (p *Planner) buildFunctrie() error { - +func (p *Planner) buildFunctrie() { for _, module := range p.modules { // Create functrie node for empty packages so that extent queries return @@ -200,7 +196,6 @@ func (p *Planner) buildFunctrie() error { val.children = nil } } - return nil } func (p *Planner) planRules(rules []*ast.Rule) (string, error) { @@ -252,6 +247,23 @@ func (p *Planner) planRules(rules []*ast.Rule) (string, error) { return funcName, nil } + // One function is planned per ground path prefix, so rules whose refs only + // differ past a variable share a function. A reference from one of those + // rule bodies back into the same prefix is not recursion the compiler would + // reject, but the planner has no way to evaluate part of a function that is + // still being planned. The generation is left out of the key on purpose: a + // 'with' statement that shadows planned functions bumps it, and keying on + // it would let the same prefix re-enter planning forever. + if _, ok := p.planning[path]; ok { + err := fmt.Errorf("reference to %v is not supported: rules sharing that path prefix are planned as a single function", path) + if p.loc != nil { + return "", fmt.Errorf("%v: %w", p.loc, err) + } + return "", err + } + p.planning[path] = struct{}{} + defer delete(p.planning, path) + // Save current state of planner. // // TODO(tsandall): perhaps we would be better off using stacks here or @@ -580,7 +592,6 @@ func (p *Planner) planFuncParams(params []ir.Local, args ast.Args, idx int, iter } func (p *Planner) planQueries() error { - for _, qs := range p.queries { // Initialize the plan with a block that prepares the query result. @@ -663,7 +674,6 @@ func (p *Planner) planQueries() error { } func (p *Planner) planQuery(q ast.Body, index int, iter planiter) error { - if index >= len(q) { return iter() } @@ -2487,7 +2497,7 @@ func (p *Planner) planTermSliceRec(terms []*ast.Term, locals []ir.Operand, index }) } -func (p *Planner) planExterns() error { +func (p *Planner) planExterns() { p.policy.Static.BuiltinFuncs = make([]*ir.BuiltinFunc, 0, len(p.externs)) for name, decl := range p.externs { @@ -2497,8 +2507,6 @@ func (p *Planner) planExterns() error { slices.SortFunc(p.policy.Static.BuiltinFuncs, func(a, b *ir.BuiltinFunc) int { return strings.Compare(a.Name, b.Name) }) - - return nil } func (p *Planner) getStringConst(s string) int { diff --git a/constraint/vendor/github.com/open-policy-agent/opa/internal/semver/semver.go b/constraint/vendor/github.com/open-policy-agent/opa/internal/semver/semver.go index 61ba1ac42..9c1196b71 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/internal/semver/semver.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/internal/semver/semver.go @@ -45,13 +45,17 @@ type Version struct { func Parse(version string) (v Version, err error) { version = strings.TrimPrefix(version, "v") - version, v.Metadata = cut(version, '+') - if v.Metadata != "" && !reMetaIdentifier.MatchString(v.Metadata) { + var foundMetadata bool + + version, v.Metadata, foundMetadata = strings.Cut(version, "+") + if foundMetadata && !reMetaIdentifier.MatchString(v.Metadata) { return v, fmt.Errorf("invalid metadata identifier: %s", v.Metadata) } - version, v.PreRelease = cut(version, '-') - if v.PreRelease != "" && !reMetaIdentifier.MatchString(v.PreRelease) { + var foundPreRelease bool + + version, v.PreRelease, foundPreRelease = strings.Cut(version, "-") + if foundPreRelease && (!reMetaIdentifier.MatchString(v.PreRelease) || !validPreRelease(v.PreRelease)) { return v, fmt.Errorf("invalid pre-release identifier: %s", v.PreRelease) } @@ -59,19 +63,43 @@ func Parse(version string) (v Version, err error) { return v, fmt.Errorf("%s should contain major, minor, and patch versions", version) } - major, after := cut(version, '.') - if v.Major, err = strconv.ParseInt(major, 10, 64); err != nil { - return v, err + major, after := cutDot(version) + if v.Major, err = parseNumeric(major); err != nil { + return v, fmt.Errorf("invalid major version: %w", err) + } + + minor, after := cutDot(after) + if v.Minor, err = parseNumeric(minor); err != nil { + return v, fmt.Errorf("invalid minor version: %w", err) } - minor, after := cut(after, '.') - if v.Minor, err = strconv.ParseInt(minor, 10, 64); err != nil { - return v, err + if v.Patch, err = parseNumeric(after); err != nil { + return v, fmt.Errorf("invalid patch version: %w", err) } - v.Patch, err = strconv.ParseInt(after, 10, 64) + return v, nil +} + +// parseNumeric parses a major, minor or patch identifier, rejecting the empty +// string, a sign or a leading zero (all forbidden by SemVer 2.0.0) before +// converting to int64. +func parseNumeric(s string) (int64, error) { + if s == "" || s[0] == '+' || s[0] == '-' || (len(s) > 1 && s[0] == '0') { + return 0, fmt.Errorf("%q is not a valid numeric identifier", s) + } + return strconv.ParseInt(s, 10, 64) +} - return v, err +// validPreRelease reports whether every numeric pre-release identifier is free +// of leading zeroes, as required by SemVer 2.0.0. The identifier character set +// has already been checked by reMetaIdentifier. +func validPreRelease(pre string) bool { + for id := range strings.SplitSeq(pre, ".") { + if len(id) > 1 && id[0] == '0' && isAllDecimals(id) { + return false + } + } + return true } // MustParse is like Parse but panics if the version string is invalid instead of returning an error. @@ -162,8 +190,8 @@ func (v Version) Compare(other Version) int { return -1 } - a, afterA := cut(v.PreRelease, '.') - b, afterB := cut(other.PreRelease, '.') + a, afterA := cutDot(v.PreRelease) + b, afterB := cutDot(other.PreRelease) for { if a == "" && b != "" { @@ -209,8 +237,8 @@ func (v Version) Compare(other Version) int { return -1 } - a, afterA = cut(afterA, '.') - b, afterB = cut(afterB, '.') + a, afterA = cutDot(afterA) + b, afterB = cutDot(afterB) } } @@ -235,10 +263,13 @@ func length(v Version) int { return n } -// cut is a *slightly* faster version of strings.Cut only accepting -// single byte separators, and skipping the boolean return value. -func cut(s string, sep byte) (before, after string) { - if i := strings.IndexByte(s, sep); i >= 0 { +// cutDot is a *slightly* faster version of strings.Cut for the '.' separator, +// skipping the boolean return value. strings.Cut looks the separator up with +// strings.Index, which costs ~12% on BenchmarkCompare next to IndexByte. +// +//nolint:modernize // stringscut: measurably slower here, see above. +func cutDot(s string) (before, after string) { + if i := strings.IndexByte(s, '.'); i >= 0 { return s[:i], s[i+1:] } return s, "" diff --git a/constraint/vendor/github.com/open-policy-agent/opa/internal/yaml/yaml.go b/constraint/vendor/github.com/open-policy-agent/opa/internal/yaml/yaml.go new file mode 100644 index 000000000..9f6e53a57 --- /dev/null +++ b/constraint/vendor/github.com/open-policy-agent/opa/internal/yaml/yaml.go @@ -0,0 +1,340 @@ +// Copyright 2026 The OPA Authors. All rights reserved. +// Use of this source code is governed by an Apache2 +// license that can be found in the LICENSE file. + +// Package yaml provides YAML <-> JSON conversion for OPA, on top of +// go.yaml.in/yaml/v3. +// +// It replaces sigs.k8s.io/yaml, which is pinned to go.yaml.in/yaml/v2 and +// therefore resolves YAML 1.1 boolean spellings (on/off/yes/no) in positions +// where the YAML 1.2 core schema calls for strings. +package yaml + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "io" + "reflect" + "strconv" + + "go.yaml.in/yaml/v3" +) + +// Marshal serializes obj as YAML. obj is first round-tripped through +// encoding/json so that `json` struct tags and json.Marshaler +// implementations are honoured, matching the behaviour callers relied on +// from sigs.k8s.io/yaml. +func Marshal(obj any) ([]byte, error) { + bs, err := json.Marshal(obj) + if err != nil { + return nil, fmt.Errorf("error marshaling into JSON: %w", err) + } + var jsonObj any + if err := yaml.Unmarshal(bs, &jsonObj); err != nil { + return nil, err + } + return marshalYAML(jsonObj) +} + +// marshalYAML emits YAML at 2-space indentation. go-yaml v3 defaults to 4, +// where sigs.k8s.io/yaml (on go-yaml v2) emitted 2. +func marshalYAML(obj any) ([]byte, error) { + var buf bytes.Buffer + enc := yaml.NewEncoder(&buf) + enc.SetIndent(2) + if err := enc.Encode(obj); err != nil { + _ = enc.Close() + return nil, err + } + if err := enc.Close(); err != nil { + return nil, err + } + return buf.Bytes(), nil +} + +// JSONOpt configures the encoding/json decoder used by Unmarshal. +type JSONOpt func(*json.Decoder) *json.Decoder + +// Unmarshal decodes a YAML document into obj, using encoding/json semantics +// (`json` struct tags, json.Unmarshaler) rather than go-yaml's. +func Unmarshal(bs []byte, obj any, opts ...JSONOpt) error { + js, err := YAMLToJSON(bs) + if err != nil { + return err + } + d := json.NewDecoder(bytes.NewReader(js)) + for _, opt := range opts { + d = opt(d) + } + if err := d.Decode(obj); err != nil { + return fmt.Errorf("error unmarshaling JSON: %w", err) + } + return nil +} + +// YAMLToJSON converts a single YAML document to JSON. Input holding more than +// one document keeps its historical meaning - only the first is converted - +// but the rest of the stream still has to parse. +func YAMLToJSON(bs []byte) ([]byte, error) { + node, err := firstDocument(bs) + if err != nil { + return nil, err + } + + var obj any + if node != nil { + normalize(node, map[*yaml.Node]struct{}{}) + if err := node.Decode(&obj); err != nil { + return nil, err + } + } + + obj, err = jsonable(obj) + if err != nil { + return nil, err + } + return json.Marshal(obj) +} + +// firstDocument returns the first document in bs, or nil if bs holds none. +// +// The remaining documents are parsed and discarded. go-yaml stops reading at +// the end of the first document, so without this a syntax error further into +// the input is never reported: `" a:\nb: 1"` closes the mapping at the dedent +// and silently drops `b: 1`, rather than failing the way the YAML spec calls +// for (issue 6854). +func firstDocument(bs []byte) (*yaml.Node, error) { + dec := yaml.NewDecoder(bytes.NewReader(bs)) + + var first *yaml.Node + for { + var node yaml.Node + if err := dec.Decode(&node); err != nil { + if errors.Is(err, io.EOF) { + return first, nil + } + return nil, err + } + if first == nil { + first = &node + } + } +} + +// normalize rewrites the node tree before it is decoded, so that documents +// go-yaml v2 accepted keep working under v3. +// +// Implicitly resolved !!timestamp scalars are re-tagged !!str. !!timestamp is +// a YAML 1.1 type that go-yaml v3 still resolves in the core schema; leaving +// it in place would silently rewrite `2023-01-01` to `2023-01-01T00:00:00Z` +// on the way to JSON. +// +// Repeated merge keys are folded into the sequence form, and duplicate +// mapping keys are collapsed to the last occurrence. go-yaml v3 rejects both +// outright; go-yaml v2 accepted them, and turning documents that load today +// into hard errors is a bigger change than this package is trying to make. +// +// Anchors make the node graph a DAG, so visited guards against re-walking a +// shared subtree. +func normalize(n *yaml.Node, visited map[*yaml.Node]struct{}) { + if n == nil { + return + } + if _, ok := visited[n]; ok { + return + } + visited[n] = struct{}{} + + switch n.Kind { + case yaml.ScalarNode: + if n.Tag == "!!timestamp" && n.Style == 0 { + n.Tag = "!!str" + } + case yaml.MappingNode: + n.Content = collapseMergeKeys(n.Content) + n.Content = dedupeKeys(n.Content) + } + + normalize(n.Alias, visited) + for _, c := range n.Content { + normalize(c, visited) + } +} + +// collapseMergeKeys rewrites a mapping that repeats `<<` into the spec's +// sequence form (`<<: [a, b]`), which go-yaml v3 accepts. go-yaml v2 applied +// repeated merge keys in document order, so preserve that order. +func collapseMergeKeys(content []*yaml.Node) []*yaml.Node { + first := -1 + var merged []*yaml.Node + + for i := 0; i+1 < len(content); i += 2 { + if content[i].Kind != yaml.ScalarNode || content[i].Tag != "!!merge" { + continue + } + if first < 0 { + first = i + } + if v := content[i+1]; v.Kind == yaml.SequenceNode { + merged = append(merged, v.Content...) + } else { + merged = append(merged, v) + } + } + + if first < 0 || len(merged) < 2 { + return content + } + + out := make([]*yaml.Node, 0, len(content)) + for i := 0; i+1 < len(content); i += 2 { + switch { + case i == first: + out = append(out, content[i], &yaml.Node{ + Kind: yaml.SequenceNode, + Tag: "!!seq", + Content: merged, + }) + case content[i].Kind == yaml.ScalarNode && content[i].Tag == "!!merge": + // dropped; folded into the sequence above + default: + out = append(out, content[i], content[i+1]) + } + } + return out +} + +// dedupeKeys drops all but the last occurrence of each key in a mapping's +// flattened key/value Content slice, preserving the position of the first +// occurrence the way a last-wins map assignment would. +// +// go-yaml v3 rejects duplicate keys outright, but go-yaml v2 accepted them, +// and turning documents that load today into hard errors is a bigger change +// than this package is trying to make. Keys are compared by the string they +// will occupy in the resulting JSON object, so `1` and `"1"` collide here the +// same way they would there. +func dedupeKeys(content []*yaml.Node) []*yaml.Node { + seen := make(map[string]int, len(content)/2) + dropped := false + + for i := 0; i+1 < len(content); i += 2 { + k := content[i] + // Merge keys are not real keys, and non-scalar keys have no JSON + // representation - both are handled elsewhere. + if k.Kind != yaml.ScalarNode || k.Tag == "!!merge" { + continue + } + var kv any + if err := k.Decode(&kv); err != nil { + continue + } + id, ok := keyString(kv) + if !ok { + continue + } + if prevVal, ok := seen[id]; ok { + // Keep the earlier key node's position, take the later value. + content[prevVal] = content[i+1] + content[i], content[i+1] = nil, nil + dropped = true + continue + } + seen[id] = i + 1 + } + + if !dropped { + return content + } + + out := content[:0] + for _, n := range content { + if n != nil { + out = append(out, n) + } + } + return out +} + +// JSONToYAML converts JSON to YAML, preserving nothing but the value. +func JSONToYAML(bs []byte) ([]byte, error) { + var obj any + // json.Number would be re-encoded as a quoted string by go-yaml, so decode + // numbers as float64 the way encoding/json does by default. + if err := json.Unmarshal(bs, &obj); err != nil { + return nil, err + } + return marshalYAML(obj) +} + +// jsonable rewrites the result of a go-yaml decode into something +// encoding/json can marshal: YAML permits mapping keys of any type, JSON +// only permits strings. +func jsonable(x any) (any, error) { + switch x := x.(type) { + case map[string]any: + for k, v := range x { + v, err := jsonable(v) + if err != nil { + return nil, err + } + x[k] = v + } + return x, nil + case map[any]any: + out := make(map[string]any, len(x)) + for k, v := range x { + ks, ok := keyString(k) + if !ok { + return nil, fmt.Errorf("unsupported map key of type: %s, key: %+#v, value: %+#v", reflect.TypeOf(k), k, v) + } + v, err := jsonable(v) + if err != nil { + return nil, err + } + out[ks] = v + } + return out, nil + case []any: + for i, v := range x { + v, err := jsonable(v) + if err != nil { + return nil, err + } + x[i] = v + } + return x, nil + default: + return x, nil + } +} + +func keyString(k any) (string, bool) { + switch k := k.(type) { + case string: + return k, true + case int: + return strconv.Itoa(k), true + case int64: + return strconv.FormatInt(k, 10), true + case uint64: + return strconv.FormatUint(k, 10), true + case float64: + // Match how go-yaml renders floats when marshaling. + switch s := strconv.FormatFloat(k, 'g', -1, 32); s { + case "+Inf": + return ".inf", true + case "-Inf": + return "-.inf", true + case "NaN": + return ".nan", true + default: + return s, true + } + case bool: + return strconv.FormatBool(k), true + default: + return "", false + } +} diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/annotations.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/annotations.go index 1aaf9680c..0b2569260 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/annotations.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/annotations.go @@ -95,6 +95,14 @@ func (a *Annotations) String() string { return string(bs) } +func (a *Annotations) AppendText(buf []byte) ([]byte, error) { + bs, err := a.MarshalJSON() + if err == nil { + buf = append(buf, bs...) + } + return buf, err +} + // Loc returns the location of this annotation. func (a *Annotations) Loc() *Location { return a.Location diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/builtins.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/builtins.go index 1f92cadd1..8942e4f34 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/builtins.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/builtins.go @@ -3126,6 +3126,8 @@ var JSONSchemaVerify = &Builtin{ Description("`output` is of the form `[valid, error]`. If the schema is valid, then `valid` is `true`, and `error` is `null`. Otherwise, `valid` is `false` and `error` is a string describing the error."), ), Categories: objectCat, + // `$ref`s are dereferenced at evaluation time, so the result depends on what those URLs serve. + Nondeterministic: true, // Needs the BuiltinContext to read the allow_net capability, which // restricts the hosts that remote `$ref`s may be fetched from. CanSkipBctx: false, @@ -3159,8 +3161,10 @@ var JSONMatchSchema = &Builtin{ }, nil)). Description("`output` is of the form `[match, errors]`. If the document is valid given the schema, then `match` is `true`, and `errors` is an empty array. Otherwise, `match` is `false` and `errors` is an array of objects describing the error(s)."), ), - Categories: objectCat, - CanSkipBctx: false, + Categories: objectCat, + // `$ref`s are dereferenced at evaluation time, so the result depends on what those URLs serve. + Nondeterministic: true, + CanSkipBctx: false, } /** diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/capabilities.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/capabilities.go index e804147d6..610de4bc5 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/capabilities.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/capabilities.go @@ -5,7 +5,6 @@ package ast import ( - "bytes" _ "embed" "encoding/json" "fmt" @@ -18,10 +17,51 @@ import ( "github.com/open-policy-agent/opa/internal/semver" "github.com/open-policy-agent/opa/internal/wasm/sdk/opa/capabilities" + "github.com/open-policy-agent/opa/v1/ast/internal/tokens" caps "github.com/open-policy-agent/opa/v1/capabilities" "github.com/open-policy-agent/opa/v1/util" ) +// In the compiler, we used this to check that we're OK working with ref heads. +// If this isn't present, we'll fail. This is to ensure that older versions of +// OPA can work with policies that we're compiling -- if they don't know ref +// heads, they wouldn't be able to parse them. +const ( + FeatureRefHeadStringPrefixes = "rule_head_ref_string_prefixes" + FeatureRefHeads = "rule_head_refs" + FeatureRegoV1 = "rego_v1" + FeatureRegoV1Import = "rego_v1_import" + FeatureKeywordsInRefs = "keywords_in_refs" + FeatureTemplateStrings = "template_strings" +) + +var ( + // Features carries the default features supported by this version of OPA. + // Use RegisterFeatures to add to them. + Features = []string{ + FeatureRegoV1, + FeatureKeywordsInRefs, + FeatureTemplateStrings, + } + v0v1compatFeatures = []string{ + FeatureRefHeadStringPrefixes, + FeatureRefHeads, + FeatureRegoV1Import, + FeatureRegoV1, // Included in v0 capabilities to allow v1 bundles in --v0-compatible mode + FeatureKeywordsInRefs, + } + // NOTE(tsandall): this file is generated by internal/cmd/genversionindex/main.go + // and run as part of go:generate. We generate the version index as part of the + // build process because it's relatively expensive to build (it takes ~500ms on + // my machine) and never changes. + // + //go:embed version_index.json + versionIndexBs []byte + // init only on demand, as JSON unmarshalling comes with some cost, and contributes + // noise to things like pprof stats + minVersionIndexOnce = sync.OnceValue(minVersionIndex) +) + // VersonIndex contains an index from built-in function name, language feature, // and future rego keyword to version number. During the build, this is used to // create an index of the minimum version required for the built-in/feature/kw. @@ -31,51 +71,13 @@ type VersionIndex struct { Keywords map[string]semver.Version `json:"keywords"` } -// NOTE(tsandall): this file is generated by internal/cmd/genversionindex/main.go -// and run as part of go:generate. We generate the version index as part of the -// build process because it's relatively expensive to build (it takes ~500ms on -// my machine) and never changes. -// -//go:embed version_index.json -var versionIndexBs []byte - -// init only on demand, as JSON unmarshalling comes with some cost, and contributes -// noise to things like pprof stats -var minVersionIndexOnce = sync.OnceValue(func() VersionIndex { - var vi VersionIndex - if err := json.Unmarshal(versionIndexBs, &vi); err != nil { - panic(err) - } - return vi -}) - -// In the compiler, we used this to check that we're OK working with ref heads. -// If this isn't present, we'll fail. This is to ensure that older versions of -// OPA can work with policies that we're compiling -- if they don't know ref -// heads, they wouldn't be able to parse them. -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" -const FeatureTemplateStrings = "template_strings" - -// Features carries the default features supported by this version of OPA. -// Use RegisterFeatures to add to them. -var Features = []string{ - FeatureRegoV1, - FeatureKeywordsInRefs, - FeatureTemplateStrings, -} - // RegisterFeatures lets applications wrapping OPA register features, to be // included in `ast.CapabilitiesForThisVersion()`. func RegisterFeatures(fs ...string) { for i := range fs { - if slices.Contains(Features, fs[i]) { - continue + if !slices.Contains(Features, fs[i]) { + Features = append(Features, fs[i]) } - Features = append(Features, fs[i]) } } @@ -113,6 +115,9 @@ type CapabilitiesOptions struct { } func newCapabilitiesOptions(opts []CapabilitiesOption) CapabilitiesOptions { + if len(opts) == 0 { + return CapabilitiesOptions{} + } co := CapabilitiesOptions{} for _, opt := range opts { opt(&co) @@ -146,59 +151,35 @@ func CapabilitiesExperimentalKeywords(yes bool) CapabilitiesOption { // CapabilitiesForThisVersion returns the capabilities of this version of OPA. func CapabilitiesForThisVersion(opts ...CapabilitiesOption) *Capabilities { co := newCapabilitiesOptions(opts) - - f := &Capabilities{} + f := &Capabilities{Builtins: util.SortedFunc(slices.Clone(Builtins), cmpBuiltinName)} for _, vers := range capabilities.ABIVersions() { f.WasmABIVersions = append(f.WasmABIVersions, WasmABIVersion{Version: vers[0], Minor: vers[1]}) } - f.Builtins = make([]*Builtin, len(Builtins)) - copy(f.Builtins, Builtins) - - slices.SortFunc(f.Builtins, func(a, b *Builtin) int { - return strings.Compare(a.Name, b.Name) - }) - switch co.regoVersion { case RegoV0, RegoV0CompatV1: - for kw := range allFutureKeywords { - if _, internal := experimentalFutureKeywords[kw]; internal && !co.experimentalKeywords { - continue - } - f.FutureKeywords = append(f.FutureKeywords, kw) - } - - f.Features = []string{ - FeatureRefHeadStringPrefixes, - FeatureRefHeads, - FeatureRegoV1Import, - FeatureRegoV1, // Included in v0 capabilities to allow v1 bundles in --v0-compatible mode - FeatureKeywordsInRefs, - } + f.FutureKeywords = co.filterFutureKeywords(allFutureKeywords) + f.Features = util.Sorted(slices.Clone(v0v1compatFeatures)) default: - for kw := range futureKeywords { - if _, internal := experimentalFutureKeywords[kw]; internal && !co.experimentalKeywords { - continue - } - f.FutureKeywords = append(f.FutureKeywords, kw) - } - - f.Features = make([]string, len(Features)) - copy(f.Features, Features) + f.FutureKeywords = co.filterFutureKeywords(futureKeywords) + f.Features = util.Sorted(slices.Clone(Features)) } - slices.Sort(f.FutureKeywords) - slices.Sort(f.Features) - return f } +func (co *CapabilitiesOptions) filterFutureKeywords(src map[string]tokens.Token) []string { + if co.experimentalKeywords { + return util.KeysSorted(src) + } + return slices.DeleteFunc(util.KeysSorted(src), isExperimental) +} + // LoadCapabilitiesJSON loads a JSON serialized capabilities structure from the reader r. func LoadCapabilitiesJSON(r io.Reader) (*Capabilities, error) { - d := util.NewJSONDecoder(r) var c Capabilities - return &c, d.Decode(&c) + return &c, util.NewJSONDecoder(r).Decode(&c) } // LoadCapabilitiesVersion loads a JSON serialized capabilities structure from the specific version. @@ -208,18 +189,16 @@ func LoadCapabilitiesVersion(version string) (*Capabilities, error) { return nil, err } - for _, cv := range cvs { - if cv == version { - cont, err := caps.FS.ReadFile(cv + ".json") - if err != nil { - return nil, err - } - - return LoadCapabilitiesJSON(bytes.NewReader(cont)) + if slices.Contains(cvs, version) { + fd, err := caps.FS.Open(version + ".json") + if err != nil { + return nil, err } - + defer fd.Close() + return LoadCapabilitiesJSON(fd) } - return nil, fmt.Errorf("no capabilities version found %v", version) + + return nil, fmt.Errorf("no capabilities version found %s", version) } // LoadCapabilitiesFile loads a JSON serialized capabilities structure from a file. @@ -234,12 +213,11 @@ func LoadCapabilitiesFile(file string) (*Capabilities, error) { // LoadCapabilitiesVersions loads all capabilities versions func LoadCapabilitiesVersions() ([]string, error) { - ents, err := caps.FS.ReadDir(".") + entries, err := caps.FS.ReadDir(".") if err != nil { return nil, err } - - return util.SortedStableFunc(util.Map(ents, removeJsonSuffix), semver.Compare), nil + return util.SortedStableFunc(util.Map(entries, removeJsonSuffix), semver.Compare), nil } // MinimumCompatibleVersion returns the minimum compatible OPA version based on @@ -307,6 +285,13 @@ func (c *Capabilities) addBuiltinSorted(bi *Builtin) { c.Builtins[i] = bi } +func minVersionIndex() (vi VersionIndex) { + if err := json.Unmarshal(versionIndexBs, &vi); err != nil { + panic(err) + } + return vi +} + func cmpBuiltinName(a, b *Builtin) int { return strings.Compare(a.Name, b.Name) } @@ -314,3 +299,8 @@ func cmpBuiltinName(a, b *Builtin) int { func removeJsonSuffix(ent fs.DirEntry) string { return strings.Replace(ent.Name(), ".json", "", 1) } + +func isExperimental(kw string) bool { + _, experimental := experimentalFutureKeywords[kw] + return experimental +} diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/check.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/check.go index c07130d20..05c7f889a 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/check.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/check.go @@ -44,7 +44,14 @@ func newTypeChecker() *typeChecker { func (tc *typeChecker) newEnv(exist *TypeEnv) *TypeEnv { if exist != nil { - return exist.wrap() + env := exist.wrap() + // The wrapped environment would otherwise inherit exist's checker + // factory, which may have been built with a different configuration + // than tc -- the compiler seeds Compiler.TypeEnv from a bare checker, + // for one. Comprehension bodies are typed lazily through this factory, + // so it has to reflect the checker that is running now. + env.newChecker = tc.copyForEnv + return env } env := newTypeEnv(tc.copy) if tc.input != nil { @@ -53,6 +60,14 @@ func (tc *typeChecker) newEnv(exist *TypeEnv) *TypeEnv { return env } +// copyForEnv returns a checker for typing the closures an environment is asked +// about. It drops the required-capabilities accumulator: environments outlive +// the compilation that produced them, and the builtins in those closures are +// already recorded by checkClosures. +func (tc *typeChecker) copyForEnv() *typeChecker { + return tc.copy().WithRequiredCapabilities(nil) +} + func (tc *typeChecker) copy() *typeChecker { return newTypeChecker(). WithVarRewriter(tc.varRewriter). @@ -246,7 +261,6 @@ func (tc *typeChecker) getSchemaType(schemaAnnot *SchemaAnnotation, rule *Rule) } func (tc *typeChecker) checkRule(env *TypeEnv, as *AnnotationSet, rule *Rule) { - env = env.wrap() schemaAnnots := getRuleAnnotation(as, rule) @@ -307,7 +321,16 @@ func (tc *typeChecker) checkRule(env *TypeEnv, as *AnnotationSet, rule *Rule) { args[i] = cpy.GetByValue(rule.Head.Args[i].Value) } - tpe = types.NewFunction(args, cpy.GetByValue(rule.Head.Value.Value)) + result := cpy.GetByValue(rule.Head.Value.Value) + if result == nil && tc.allowUndefinedFuncs { + // The value is only unknown because it came out of a call to an + // undefined function. Recording a function type without a result + // would make callers look like they pass one argument too many, so + // fall back to any. + result = types.A + } + + tpe = types.NewFunction(args, result) } else { switch rule.Head.RuleKind() { case SingleValue: @@ -357,23 +380,17 @@ func nestedObject(env *TypeEnv, path Ref, tpe types.Type) (types.Type, error) { return tpe, nil } - k := path[0] typeV, err := nestedObject(env, path[1:], tpe) - if err != nil { + if err != nil || typeV == nil { return nil, err } - if typeV == nil { - return nil, nil - } - var dynamicProperty *types.DynamicProperty - typeK := env.GetByValue(k.Value) + typeK := env.GetByValue(path[0].Value) if typeK == nil { return nil, nil } - dynamicProperty = types.NewDynamicProperty(typeK, typeV) - return types.NewObject(nil, dynamicProperty), nil + return types.NewObject(nil, types.NewDynamicProperty(typeK, typeV)), nil } func (tc *typeChecker) checkExpr(env *TypeEnv, expr *Expr) *Error { @@ -395,13 +412,75 @@ func (tc *typeChecker) checkExpr(env *TypeEnv, expr *Expr) *Error { } } - if operator == "eq" { + switch operator { + case Equality.Name: return checkExprEq(env, expr) + case Member.Name, MemberWithKey.Name: + if err := checkExprMember(env, expr, operator == MemberWithKey.Name); err != nil { + return err + } } return tc.checkExprBuiltin(env, expr) } +// checkExprMember type checks the `in` operator, whose operands are declared as +// any: what may be found in a collection depends on the collection's own type, +// which a function declaration can't express. +func checkExprMember(env *TypeEnv, expr *Expr, withKey bool) *Error { + arity := Member.Decl.Arity() + if withKey { + arity = MemberWithKey.Decl.Arity() + } + + args := expr.Operands() + if len(args) < arity { + return nil // too few arguments; reported by checkExprBuiltin + } + + collection := env.GetByValue(args[arity-1].Value) + + // `in` yields false rather than erroring for operands it can't enumerate. + values := types.Values(collection) + if values == nil { + return nil + } + + if withKey { + if err := checkExprMemberOperand(env, expr, args[0], types.Keys(collection)); err != nil { + return err + } + } + + return checkExprMemberOperand(env, expr, args[arity-2], values) +} + +// checkExprMemberOperand checks that term can occur in the collection being +// searched, inferring the type of untyped terms (e.g. `some x in xs`) as it goes. +func checkExprMemberOperand(env *TypeEnv, expr *Expr, term *Term, tpe types.Type) *Error { + if tpe == nil || types.Nil(tpe) { + return nil + } + + have := env.GetByValue(term.Value) + + // unifies rejects already-typed terms; unify1 infers types for untyped vars + // and checks the resolved parts of partially typed composites. + if (!types.Nil(have) && !unifies(have, tpe)) || !unify1(env, term, tpe, false) { + return &Error{ + Code: TypeErr, + Location: expr.Location, + Message: "match error", + Details: &UnificationErrDetail{ + Left: have, + Right: tpe, + }, + } + } + + return nil +} + func (tc *typeChecker) checkExprBuiltin(env *TypeEnv, expr *Expr) *Error { // NOTE(tsandall): undefined functions will have been caught earlier in the // compiler. We check for undefined functions before the safety check so @@ -477,14 +556,16 @@ func (tc *typeChecker) checkExprBuiltin(env *TypeEnv, expr *Expr) *Error { } func checkExprEq(env *TypeEnv, expr *Expr) *Error { + ops := expr.Operands() + num := len(ops) - pre := getArgTypes(env, expr.Operands()) - - if len(pre) < Equality.Decl.Arity() { + if num < Equality.Decl.Arity() { + pre := getArgTypes(env, ops) return newArgError(expr.Location, expr.Operator(), "too few arguments", pre, Equality.Decl.FuncArgs()) } - if Equality.Decl.Arity() < len(pre) { + if Equality.Decl.Arity() < num { + pre := getArgTypes(env, ops) return newArgError(expr.Location, expr.Operator(), "too many arguments", pre, Equality.Decl.FuncArgs()) } @@ -896,7 +977,6 @@ func (rc *refChecker) checkApply(curr *TypeEnv, ref Ref) *Error { } func (rc *refChecker) checkRef(curr *TypeEnv, node *typeTreeNode, ref Ref, idx int) *Error { - if idx == len(ref) { return nil } @@ -963,6 +1043,13 @@ func (rc *refChecker) checkRefLeaf(tpe types.Type, ref Ref, idx int) *Error { head := ref[idx] + if isEmptyCollectionType(tpe) { + // The collection has no members at all, so nothing can be selected from + // it. Report that like any other missing key rather than as a value that + // can't be dereferenced at all. + return newRefErrInvalid(ref[0].Location, rc.varRewriter(ref), idx, nil, nil, nil) + } + keys := types.Keys(tpe) if keys == nil { return newRefErrUnsupported(ref[0].Location, rc.varRewriter(ref), idx-1, tpe) @@ -1002,6 +1089,27 @@ func (rc *refChecker) checkRefLeaf(tpe types.Type, ref Ref, idx int) *Error { return rc.checkRefLeaf(types.Values(tpe), ref, idx+1) } +// isEmptyCollectionType returns true if tpe is the type of a collection that +// can hold nothing: an object with neither static nor dynamic properties, an +// array with no items, or a set with no element type. +func isEmptyCollectionType(tpe types.Type) bool { + if named, ok := tpe.(*types.NamedType); ok { + tpe = named.Type + } + if rec, ok := tpe.(*types.Recursive); ok { + tpe = rec.Unwrap() + } + switch tpe := tpe.(type) { + case *types.Object: + return len(tpe.StaticProperties()) == 0 && tpe.DynamicProperties() == nil + case *types.Array: + return tpe.Len() == 0 && tpe.Dynamic() == nil + case *types.Set: + return tpe.Of() == nil + } + return false +} + // unifies checks whether two types are compatible with each other. func unifies(a, b types.Type) bool { @@ -1065,6 +1173,11 @@ func unifies(a, b types.Type) bool { if !ok { return false } + // A set type without an element type is the empty set, which is a + // member of every set type. + if a.Of() == nil || b.Of() == nil { + return true + } return unifies(types.Values(a), types.Values(b)) case *types.Function: // NOTE(sr): variadic functions can only be internal ones, and we've forbidden @@ -1172,10 +1285,42 @@ type ArgErrDetail struct { // Lines returns the string representation of the detail. func (d *ArgErrDetail) Lines() []string { - lines := make([]string, 2) - lines[0] = "have: " + formatArgs(d.Have) - lines[1] = "want: " + d.Want.String() - return lines + have := "have: " + formatArgs(d.Have) + want := "want: " + d.Want.String() + + if !tooWideForTypeErr(have, want) { + return []string{have, want} + } + + // Positions that only exist on one side, as is the case for arity errors, + // have nothing to be compared against, and are collapsed to their outermost + // type constructor. + haveArgs := util.Map(d.Have, elideType) + wantArgs := util.Map(d.Want.Args, elideType) + + for i := range min(len(haveArgs), len(wantArgs)) { + haveArgs[i], wantArgs[i] = diffArg(d.Have[i], d.Want.Args[i]) + } + + if d.Want.Variadic != nil { + wantArgs = append(wantArgs, elideType(d.Want.Variadic)+"...") + } + + return []string{ + "have: (" + strings.Join(haveArgs, ", ") + ")", + "want: (" + strings.Join(wantArgs, ", ") + ")", + } +} + +// diffArg renders an actual and an expected argument type side by side. The two +// are only diffed if they are actually in conflict: an argument that the +// function would have accepted is not what the error is about, and expanding it +// is what makes these messages unreadable in the first place. +func diffArg(have, want types.Type) (string, string) { + if have != nil && want != nil && unifies(unwrapNamedType(have), unwrapNamedType(want)) { + return elideType(have), elideType(want) + } + return sprintDiff(have, want) } func (d *ArgErrDetail) nilType() bool { @@ -1195,10 +1340,15 @@ func (a *UnificationErrDetail) nilType() bool { // Lines returns the string representation of the detail. func (a *UnificationErrDetail) Lines() []string { - lines := make([]string, 2) - lines[0] = fmt.Sprint("left : ", types.Sprint(a.Left)) - lines[1] = fmt.Sprint("right : ", types.Sprint(a.Right)) - return lines + leftLine := "left : " + types.Sprint(a.Left) + rightLine := "right : " + types.Sprint(a.Right) + + if !tooWideForTypeErr(leftLine, rightLine) { + return []string{leftLine, rightLine} + } + + left, right := sprintDiff(a.Left, a.Right) + return []string{"left : " + left, "right : " + right} } // RefErrUnsupportedDetail describes an undefined reference error where the @@ -1211,12 +1361,11 @@ type RefErrUnsupportedDetail struct { // Lines returns the string representation of the detail. func (r *RefErrUnsupportedDetail) Lines() []string { - lines := []string{ + return []string{ r.Ref.String(), strings.Repeat("^", len(r.Ref[:r.Pos+1].String())), fmt.Sprintf("have: %v", r.Have), } - return lines } // RefErrInvalidDetail describes an undefined reference error where the referenced @@ -1243,6 +1392,10 @@ func (r *RefErrInvalidDetail) Lines() []string { } if len(r.OneOf) > 0 { lines = append(lines, fmt.Sprintf("%swant (one of): %v", pad, r.OneOf)) + } else if r.Want == nil { + // Neither candidate keys nor a key type: the referenced value has no + // selectable keys at all (e.g. an empty object). + lines = append(lines, pad+"want (one of): []") } else { lines = append(lines, fmt.Sprintf("%swant (type): %v", pad, r.Want)) } @@ -1313,7 +1466,9 @@ func getOneOfForNode(node *typeTreeNode) []Value { func getOneOfForType(tpe types.Type) (result []Value) { switch tpe := tpe.(type) { case *types.Object: - for _, k := range tpe.Keys() { + keys := tpe.Keys() + result = slices.Grow(result, len(keys)) + for _, k := range keys { v, err := InterfaceToValue(k) if err != nil { panic(err) @@ -1325,6 +1480,7 @@ func getOneOfForType(tpe types.Type) (result []Value) { return getOneOfForType(tpe.Unwrap()) case types.Any: + result = slices.Grow(result, len(tpe)) for _, object := range tpe { objRes := getOneOfForType(object) result = append(result, objRes...) @@ -1419,7 +1575,7 @@ func override(ref Ref, t types.Type, o types.Type, rule *Rule) (types.Type, *Err } func getKeys(ref Ref, rule *Rule) ([]any, *Error) { - keys := []any{} + keys := make([]any, 0, len(ref)) for _, refElem := range ref { key, err := JSON(refElem.Value) if err != nil { @@ -1448,7 +1604,6 @@ func getObjectType(ref Ref, o types.Type, rule *Rule, d *types.DynamicProperty) } func getRuleAnnotation(as *AnnotationSet, rule *Rule) (result []*SchemaAnnotation) { - for _, x := range as.GetSubpackagesScope(rule.Module.Package.Path) { result = append(result, x.Schemas...) } @@ -1469,15 +1624,12 @@ func getRuleAnnotation(as *AnnotationSet, rule *Rule) (result []*SchemaAnnotatio } func processAnnotation(ss *SchemaSet, annot *SchemaAnnotation, rule *Rule, allowNet []string) (types.Type, *Error) { - var schema any - if annot.Schema != nil { if ss == nil { return nil, nil } - schema = ss.Get(annot.Schema) - if schema == nil { + if schema = ss.Get(annot.Schema); schema == nil { return nil, NewError(TypeErr, rule.Location, "undefined schema: %v", annot.Schema) } } else if annot.Definition != nil { diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/check_elide.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/check_elide.go new file mode 100644 index 000000000..9f8ae0537 --- /dev/null +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/check_elide.go @@ -0,0 +1,399 @@ +// Copyright 2025 The OPA Authors. All rights reserved. +// Use of this source code is governed by an Apache2 +// license that can be found in the LICENSE file. + +package ast + +import ( + "fmt" + "strings" + "unicode/utf8" + + "github.com/open-policy-agent/opa/v1/types" + "github.com/open-policy-agent/opa/v1/util" +) + +const ( + typeElision = "..." + + // maxTypeErrLineWidth is the width above which a type error detail line is + // re-rendered with nested type information elided. Details that already fit + // are left alone: eliding them would drop information without buying any + // readability. + maxTypeErrLineWidth = 80 + + // maxElidedTypeWidth is the width above which a type that is not itself the + // subject of the mismatch is collapsed to its outermost constructor. + maxElidedTypeWidth = 32 + + // maxTypeDiffDepth bounds the parallel walk so that deeply nested types + // cannot produce an unreadable message, or, for cyclic types, no message. + maxTypeDiffDepth = 8 +) + +// sprintDiff returns the string representations of a and b, keeping only the +// structure that is needed to see how the two differ. Sub-types that are equal +// on both sides are collapsed to their outermost type constructor, and object +// properties and any-members that are equal on both sides are dropped +// altogether. An ellipsis marks everything that was left out. +func sprintDiff(a, b types.Type) (string, string) { + return diffTypes(a, b, 0) +} + +// sprintElided returns the string representation of t with any type information +// nested more than depth levels below t replaced by an ellipsis. A depth of zero +// keeps the outermost type constructor only; a negative depth renders t in full, +// exactly as types.Sprint does. +func sprintElided(t types.Type, depth int) string { + if depth < 0 { + return types.Sprint(t) + } + + switch t := t.(type) { + case nil: + return types.Sprint(t) + case *types.NamedType: + // A name is not a level of nesting, so depth is passed through. + return t.Name + ": " + sprintElided(t.Type, depth) + case *types.Set: + if t.Of() == nil { + // The empty set has no element type to elide. + return t.String() + } + if depth == 0 { + return "set[" + typeElision + "]" + } + return "set[" + sprintElided(t.Of(), depth-1) + "]" + case *types.Array: + static := make([]string, 0, t.Len()) + if depth == 0 && t.Len() > 0 { + static = append(static, typeElision) + } else { + for i := range t.Len() { + static = append(static, sprintElided(t.Select(i), depth-1)) + } + } + var dynamic string + if dyn := t.Dynamic(); dyn != nil { + if depth == 0 { + dynamic = typeElision + } else { + dynamic = sprintElided(dyn, depth-1) + } + } + return sprintArray(static, dynamic) + case *types.Object: + props := t.StaticProperties() + static := make([]string, 0, len(props)) + if depth == 0 && len(props) > 0 { + static = append(static, typeElision) + } else { + for _, p := range props { + static = append(static, sprintProperty(p.Key, sprintElided(p.Value, depth-1))) + } + } + var dynamic string + if dyn := t.DynamicProperties(); dyn != nil { + if depth == 0 { + dynamic = typeElision + } else { + dynamic = sprintElided(dyn.Key, depth-1) + ": " + sprintElided(dyn.Value, depth-1) + } + } + return sprintObject(static, dynamic) + case types.Any: + if len(t) == 0 { + return t.String() + } + if depth == 0 { + return sprintAny([]string{typeElision}) + } + of := make([]string, len(t)) + for i := range t { + of[i] = sprintElided(t[i], depth-1) + } + return sprintAny(of) + case *types.Function: + args := t.FuncArgs() + params := make([]string, 0, len(args.Args)+1) + if depth == 0 { + if len(args.Args) > 0 || args.Variadic != nil { + params = append(params, typeElision) + } + if t.Result() == nil { + return sprintFunction(params, types.Sprint(nil)) + } + return sprintFunction(params, typeElision) + } + for i := range args.Args { + params = append(params, sprintElided(args.Args[i], depth-1)) + } + if args.Variadic != nil { + params = append(params, sprintElided(args.Variadic, depth-1)+"...") + } + return sprintFunction(params, sprintElided(t.Result(), depth-1)) + default: + // Scalars, and recursive types, which are rendered by name only. + return t.String() + } +} + +// elideType collapses t to its outermost type constructor, unless it is short +// enough that spelling it out costs nothing. +func elideType(t types.Type) string { + if full := types.Sprint(t); utf8.RuneCountInString(full) <= maxElidedTypeWidth { + return full + } + return sprintElided(t, 0) +} + +func unwrapNamedType(t types.Type) types.Type { + if n, ok := t.(*types.NamedType); ok { + return n.Type + } + return t +} + +// typesEqual reports whether a and b would render identically. Comparing the +// rendered form, rather than the type structure, keeps this safe for recursive +// types, which render as a name rather than as their unrolled definition. +func typesEqual(a, b types.Type) bool { + return types.Sprint(a) == types.Sprint(b) +} + +func diffTypes(a, b types.Type, depth int) (string, string) { + // A name is not a level of nesting, so depth is passed through. + if n, ok := a.(*types.NamedType); ok { + left, right := diffTypes(n.Type, b, depth) + return n.Name + ": " + left, right + } + if n, ok := b.(*types.NamedType); ok { + left, right := diffTypes(a, n.Type, depth) + return left, n.Name + ": " + right + } + + if depth >= maxTypeDiffDepth || a == nil || b == nil || typesEqual(a, b) { + return elideType(a), elideType(b) + } + + switch a := a.(type) { + case *types.Set: + if b, ok := b.(*types.Set); ok && a.Of() != nil && b.Of() != nil { + left, right := diffTypes(a.Of(), b.Of(), depth+1) + return "set[" + left + "]", "set[" + right + "]" + } + case *types.Array: + if b, ok := b.(*types.Array); ok { + return diffArrays(a, b, depth) + } + case *types.Object: + if b, ok := b.(*types.Object); ok { + return diffObjects(a, b, depth) + } + case types.Any: + if b, ok := b.(types.Any); ok { + return diffAnys(a, b) + } + case *types.Function: + if b, ok := b.(*types.Function); ok && a.Arity() == b.Arity() { + return diffFunctions(a, b, depth) + } + } + + // The outermost type constructors already differ, which is all the reader + // needs to see. + return elideType(a), elideType(b) +} + +func diffArrays(a, b *types.Array, depth int) (string, string) { + if a.Len() != b.Len() || (a.Dynamic() == nil) != (b.Dynamic() == nil) { + // Element types are still shown so that it is clear which of the two is + // the longer, or which one has a dynamic tail. + return sprintElided(a, 1), sprintElided(b, 1) + } + + // Array elements are positional, so equal ones are collapsed rather than + // dropped, keeping the two renderings aligned. + left := make([]string, 0, a.Len()) + right := make([]string, 0, b.Len()) + for i := range a.Len() { + l, r := diffTypes(a.Select(i), b.Select(i), depth+1) + left = append(left, l) + right = append(right, r) + } + + var dynLeft, dynRight string + if a.Dynamic() != nil { + dynLeft, dynRight = diffTypes(a.Dynamic(), b.Dynamic(), depth+1) + } + + return sprintArray(left, dynLeft), sprintArray(right, dynRight) +} + +func diffObjects(a, b *types.Object, depth int) (string, string) { + aProps, bProps := a.StaticProperties(), b.StaticProperties() + + var left, right []string + var elided bool + + // Static properties are sorted by key on both sides, so they can be walked in + // parallel. Those that are equal say nothing about why the two types were + // reported together, and are dropped. + i, j := 0, 0 + for i < len(aProps) || j < len(bProps) { + switch { + case j == len(bProps): + left = append(left, sprintProperty(aProps[i].Key, elideType(aProps[i].Value))) + i++ + case i == len(aProps): + right = append(right, sprintProperty(bProps[j].Key, elideType(bProps[j].Value))) + j++ + default: + switch util.Compare(aProps[i].Key, bProps[j].Key) { + case -1: + left = append(left, sprintProperty(aProps[i].Key, elideType(aProps[i].Value))) + i++ + case 1: + right = append(right, sprintProperty(bProps[j].Key, elideType(bProps[j].Value))) + j++ + default: + if typesEqual(aProps[i].Value, bProps[j].Value) { + elided = true + } else { + l, r := diffTypes(aProps[i].Value, bProps[j].Value, depth+1) + left = append(left, sprintProperty(aProps[i].Key, l)) + right = append(right, sprintProperty(bProps[j].Key, r)) + } + i++ + j++ + } + } + } + + aDyn, bDyn := a.DynamicProperties(), b.DynamicProperties() + var dynLeft, dynRight string + switch { + case aDyn != nil && bDyn != nil: + keyLeft, keyRight := diffTypes(aDyn.Key, bDyn.Key, depth+1) + valLeft, valRight := diffTypes(aDyn.Value, bDyn.Value, depth+1) + dynLeft, dynRight = keyLeft+": "+valLeft, keyRight+": "+valRight + case aDyn != nil: + dynLeft = elideType(aDyn.Key) + ": " + elideType(aDyn.Value) + case bDyn != nil: + dynRight = elideType(bDyn.Key) + ": " + elideType(bDyn.Value) + } + + return sprintObject(withElision(left, elided), dynLeft), sprintObject(withElision(right, elided), dynRight) +} + +func diffAnys(a, b types.Any) (string, string) { + // The members of an Any are unordered as far as the reader is concerned, so + // those that appear on both sides are dropped rather than collapsed. + left := make([]string, 0, len(a)) + right := make([]string, 0, len(b)) + var elided bool + + for _, tpe := range a { + if containsType(b, tpe) { + elided = true + } else { + left = append(left, elideType(tpe)) + } + } + for _, tpe := range b { + if !containsType(a, tpe) { + right = append(right, elideType(tpe)) + } + } + + return sprintAny(withElision(left, elided)), sprintAny(withElision(right, elided)) +} + +func diffFunctions(a, b *types.Function, depth int) (string, string) { + aArgs, bArgs := a.FuncArgs(), b.FuncArgs() + + left := make([]string, 0, len(aArgs.Args)+1) + right := make([]string, 0, len(bArgs.Args)+1) + for i := range aArgs.Args { + l, r := diffTypes(aArgs.Args[i], bArgs.Args[i], depth+1) + left = append(left, l) + right = append(right, r) + } + switch { + case aArgs.Variadic != nil && bArgs.Variadic != nil: + l, r := diffTypes(aArgs.Variadic, bArgs.Variadic, depth+1) + left = append(left, l+"...") + right = append(right, r+"...") + case aArgs.Variadic != nil: + left = append(left, elideType(aArgs.Variadic)+"...") + case bArgs.Variadic != nil: + right = append(right, elideType(bArgs.Variadic)+"...") + } + + resLeft, resRight := diffTypes(a.Result(), b.Result(), depth+1) + return sprintFunction(left, resLeft), sprintFunction(right, resRight) +} + +func containsType(haystack types.Any, needle types.Type) bool { + for _, tpe := range haystack { + if typesEqual(tpe, needle) { + return true + } + } + return false +} + +func withElision(parts []string, elided bool) []string { + if !elided { + return parts + } + return append(parts, typeElision) +} + +func sprintProperty(key any, value string) string { + return fmt.Sprintf("%v: %v", key, value) +} + +func sprintArray(static []string, dynamic string) string { + return sprintComposite("array", static, dynamic) +} + +func sprintObject(static []string, dynamic string) string { + return sprintComposite("object", static, dynamic) +} + +func sprintComposite(prefix string, static []string, dynamic string) string { + sb := strings.Builder{} + sb.WriteString(prefix) + if len(static) > 0 { + sb.WriteString("<") + sb.WriteString(strings.Join(static, ", ")) + sb.WriteString(">") + } + if dynamic != "" { + sb.WriteString("[") + sb.WriteString(dynamic) + sb.WriteString("]") + } + return sb.String() +} + +func sprintAny(of []string) string { + if len(of) == 0 { + return "any" + } + return "any<" + strings.Join(of, ", ") + ">" +} + +func sprintFunction(args []string, result string) string { + return "(" + strings.Join(args, ", ") + ") => " + result +} + +func tooWideForTypeErr(lines ...string) bool { + for _, line := range lines { + if utf8.RuneCountInString(line) > maxTypeErrLineWidth { + return true + } + } + return false +} diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/compare.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/compare.go index 81038e7a6..d3dde1574 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/compare.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/compare.go @@ -107,10 +107,9 @@ func Compare(a, b any) int { case Var: return VarCompare(a, b.(Var)) case Ref: - return termSliceCompare(a, b.(Ref)) + return slices.CompareFunc(a, b.(Ref), TermValueCompare) case *Array: - b := b.(*Array) - return termSliceCompare(a.elems, b.elems) + return slices.CompareFunc(a.elems, b.(*Array).elems, TermValueCompare) case *lazyObj: return Compare(a.force(), b) case *object: @@ -130,7 +129,7 @@ func Compare(a, b any) int { b := b.(*SetComprehension) return a.Compare(b) case Call: - return termSliceCompare(a, b.(Call)) + return slices.CompareFunc(a, b.(Call), TermValueCompare) case *Expr: return a.Compare(b.(*Expr)) case *SomeDecl: @@ -150,7 +149,7 @@ func Compare(a, b any) int { case *Rule: return a.Compare(b.(*Rule)) case Args: - return termSliceCompare(a, b.(Args)) + return slices.CompareFunc(a, b.(Args), TermValueCompare) case *Import: return a.Compare(b.(*Import)) case *Package: @@ -247,52 +246,6 @@ func sortOrder(x any) int { panic(fmt.Sprintf("illegal value: %T", x)) } -func rulesCompare(a, b []*Rule) int { - minLen := min(len(b), len(a)) - for i := range minLen { - if cmp := a[i].Compare(b[i]); cmp != 0 { - return cmp - } - } - if len(a) < len(b) { - return -1 - } - if len(b) < len(a) { - return 1 - } - return 0 -} - -func termSliceCompare(a, b []*Term) int { - minLen := min(len(b), len(a)) - for i := range minLen { - if cmp := a[i].Value.Compare(b[i].Value); cmp != 0 { - return cmp - } - } - if len(a) < len(b) { - return -1 - } else if len(b) < len(a) { - return 1 - } - return 0 -} - -func withSliceCompare(a, b []*With) int { - minLen := min(len(b), len(a)) - for i := range minLen { - if cmp := a[i].Compare(b[i]); cmp != 0 { - return cmp - } - } - if len(a) < len(b) { - return -1 - } else if len(b) < len(a) { - return 1 - } - return 0 -} - func VarCompare(a, b Var) int { if a == b { return 0 @@ -304,6 +257,9 @@ func VarCompare(a, b Var) int { } func TermValueCompare(a, b *Term) int { + if a == b { + return 0 + } return a.Value.Compare(b.Value) } @@ -329,7 +285,7 @@ func ValueEqual(a, b Value) bool { } func RefCompare(a, b Ref) int { - return termSliceCompare(a, b) + return slices.CompareFunc(a, b, TermValueCompare) } func RefEqual(a, b Ref) bool { diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/compile.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/compile.go index f40835ed7..dae532088 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/compile.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/compile.go @@ -22,13 +22,31 @@ import ( "github.com/open-policy-agent/opa/v1/util" ) -// CompileErrorLimitDefault is the default number errors a compiler will allow before -// exiting. -const CompileErrorLimitDefault = 10 +const ( + // CompileErrorLimitDefault is the default number + // of errors a compiler will allow before exiting. + CompileErrorLimitDefault = 10 + LocalVarPrefix = "__local" + + errAssignInNegated = "cannot assign vars inside negated expression" + errAssignInAndOperand = "cannot assign vars inside implicit and operand" + errAssignInOrOperand = "cannot assign vars inside implicit or operand" +) var ( - errLimitReached = newErrorString(CompileErr, nil, "error limit reached") - emptyPackage = &Package{Path: Ref{VarTerm("")}} + // SafetyCheckVisitorParams defines the AST visitor parameters to use for collecting + // variables during the safety check. This has to be exported because it's relied on + // by the copy propagation implementation in topdown. + SafetyCheckVisitorParams = VarVisitorParams{SkipRefCallHead: true, SkipClosures: true} + // TODO(tsandall): Improve this so that users can either supply this list explicitly + // or the information is maintained on the built-in function declaration. What we really + // need to know is whether the built-in function allows callers to push down output + // values or not. It's unlikely that anything outside of OPA does this today so this + // solution is fine for now. + comprehensionIndexDenylist = map[string]int{WalkBuiltin.Name: len(WalkBuiltin.Decl.FuncArgs().Args)} + errLimitReached = newErrorString(CompileErr, nil, "error limit reached") + emptyPackage = &Package{Path: Ref{VarTerm("")}} + futureKeywordsPrefix = Ref{FutureRootDocument, InternedTerm("keywords")} ) // Compiler contains the state of a compilation process. @@ -161,6 +179,8 @@ type Compiler struct { defaultRegoVersion RegoVersion skipStages map[StageID]struct{} // stages to skip during compilation plan *executionPlan // computed execution plan (cached) + unusedImports []*Import // imports found unused during ref resolution, reported by CheckUnusedImports + unrecoverableErr bool // at least one recorded error prevents the remaining stages from running } func (c *Compiler) DefaultRegoVersion() RegoVersion { @@ -179,6 +199,7 @@ type StageID string // at least lets you know what your attention is needed when you depend on the stages. const ( StageResolveRefs StageID = "ResolveRefs" + StageCheckUnusedImports StageID = "CheckUnusedImports" StageInitLocalVarGen StageID = "InitLocalVarGen" StageRewriteRuleHeadRefs StageID = "RewriteRuleHeadRefs" StageCheckKeywordOverrides StageID = "CheckKeywordOverrides" @@ -221,6 +242,7 @@ const ( func AllStages() []StageID { return []StageID{ StageResolveRefs, + StageCheckUnusedImports, StageInitLocalVarGen, StageRewriteRuleHeadRefs, StageCheckKeywordOverrides, @@ -260,7 +282,7 @@ func AllStages() []StageID { // CompilerEvalMode allows toggling certain stages that are only // needed for certain modes, Concretely, only "topdown" mode will // have the compiler build comprehension and rule indices. -type CompilerEvalMode int +type CompilerEvalMode uint8 const ( // EvalModeTopdown (default) instructs the compiler to build rule @@ -376,7 +398,7 @@ type QueryCompiler interface { // WithStageAfter registers a stage to run during query compilation after // the named stage. // - // Caution: Use [ast.QueryCompiler.WithStageAfterID] instead. It provides + // Caution: Use [QueryCompiler.WithStageAfterID] instead. It provides // more (Golang) compile-time safety WithStageAfter(after string, stage QueryCompilerStageDefinition) QueryCompiler @@ -439,6 +461,7 @@ func NewCompiler() *Compiler { // load additional modules. If any stages run before resolution, they // need to be re-run after resolution. {StageResolveRefs, "compile_stage_resolve_refs", c.resolveAllRefs}, + {StageCheckUnusedImports, "compile_stage_check_unused_imports", c.checkUnusedImports}, // The local variable generator must be initialized after references are // resolved and the dynamic module loader has run but before subsequent // stages that need to generate variables. @@ -515,7 +538,7 @@ func (c *Compiler) WithPathConflictsCheckRoots(rootPaths []string) *Compiler { // WithStageAfter registers a stage to run during compilation after // the named stage. // -// Caution: Consider using [ast.QueryCompiler.WithStageAfterID] instead. It provides +// Caution: Consider using [Compiler.WithStageAfterID] instead. It provides // more (Golang) compile-time safety func (c *Compiler) WithStageAfter(after string, stage CompilerStageDefinition) *Compiler { c.after[after] = append(c.after[after], stage) @@ -836,15 +859,12 @@ func (c *Compiler) GetRulesWithPrefix(ref Ref) (rules []*Rule) { // GetRules("data.a.b.c") => [rule1, rule2] // GetRules("data.a.b.d") => nil func (c *Compiler) GetRules(ref Ref) []*Rule { - set := map[*Rule]struct{}{} + virt := c.GetRulesForVirtualDocument(ref) + pref := c.GetRulesWithPrefix(ref) - for _, rule := range c.GetRulesForVirtualDocument(ref) { - set[rule] = struct{}{} - } - - for _, rule := range c.GetRulesWithPrefix(ref) { - set[rule] = struct{}{} - } + set := make(map[*Rule]struct{}, len(virt)+len(pref)) + insertRules(set, virt) + insertRules(set, pref) return util.Keys(set) } @@ -918,7 +938,7 @@ func (c *Compiler) GetRulesDynamicWithOpts(ref Ref, opts RulesOptions) []*Rule { if child := node.Child(ref[i].Value); child != nil { if len(child.Values) > 0 { // Add any rules at this position - insertRules(set, child.Values) + insertRulesIntersecting(set, child.Values, ref, i+1) } // There might still be "sub-rules" contributing key-value "overrides" for e.g. partial object rules, continue walking walk(child, i+1) @@ -933,7 +953,7 @@ func (c *Compiler) GetRulesDynamicWithOpts(ref Ref, opts RulesOptions) []*Rule { if child.Hide && !opts.IncludeHiddenModules { continue } - insertRules(set, child.Values) + insertRulesIntersecting(set, child.Values, ref, i+1) walk(child, i+1) } } @@ -950,6 +970,31 @@ func insertRules(set map[*Rule]struct{}, rules []*Rule) { } } +// insertRulesIntersecting adds the rules whose refs could still intersect ref +// beyond position i. Rules with general refs are all stored at the ground +// prefix of their ref, so a rule like data.a.p[x].foo.bar sits at data.a.p +// alongside data.a.p[x].foo.baz. Without comparing the remaining parts, a ref +// to one of them would appear to refer to both. +func insertRulesIntersecting(set map[*Rule]struct{}, rules []*Rule, ref Ref, i int) { + for _, rule := range rules { + if refsMayIntersect(rule.Ref(), ref, i) { + set[rule] = struct{}{} + } + } +} + +// refsMayIntersect compares a and b from position i onwards, treating parts +// that aren't statically known as matching anything. +func refsMayIntersect(a, b Ref, i int) bool { + for ; i < len(a) && i < len(b); i++ { + x, y := a[i].Value, b[i].Value + if IsConstant(x) && IsConstant(y) && x.Compare(y) != 0 { + return false + } + } + return true +} + // RuleIndex returns a RuleIndex built for the rule set referred to by path. // The path must refer to the rule set exactly, i.e., given a rule set at path // data.a.b.c.p, refs data.a.b.c.p.x and data.a.b.c would not return a @@ -971,11 +1016,7 @@ func (c *Compiler) PassesTypeCheck(body Body) bool { // PassesTypeCheckRules determines whether the given rules passes type checking func (c *Compiler) PassesTypeCheckRules(rules []*Rule) Errors { - elems := make([]util.T, 0, len(rules)) - - for _, rule := range rules { - elems = append(elems, rule) - } + elems := util.ToSliceOf[util.T](rules) // Load the global input schema if one was provided. if c.schemaSet != nil { @@ -1145,12 +1186,13 @@ func (c *Compiler) buildRuleIndices() { // b.c[x].e := 1 { x := input.x } // b.c.d := 2 // b.c.d2.e[x] := 3 { x := input.x } - for _, child := range node.Children { - child.DepthFirst(func(c *TreeNode) bool { - rules = append(rules, c.Values...) - return false - }) - } + // Cleared rather than truncated: rules aliases node.Values, which the + // walk hands back along with everything below it. + rules = nil + node.DepthFirst(func(c *TreeNode) bool { + rules = append(rules, c.Values...) + return false + }) } index := newBaseDocEqIndex(c.isVirtual) @@ -1180,8 +1222,6 @@ func (c *Compiler) buildComprehensionIndices() { varVisitorPool.Put(vis) } -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 // built-in function dependencies will have already been added by the type @@ -1296,18 +1336,19 @@ func (c *Compiler) checkRecursion() { func (c *Compiler) checkSelfPath(loc *Location, eq func(a, b util.T) bool, a, b util.T) { tr := NewGraphTraversal(c.Graph) if p := util.DFSPath(tr, eq, a, b); len(p) > 0 { + rw := rewriteVarsInRef(c.RewrittenVars) n := make([]string, 0, len(p)) for _, x := range p { - n = append(n, astNodeToString(x)) + n = append(n, astNodeToString(rw, x)) } - if !c.err(NewError(RecursionErr, loc, "rule %v is recursive: %v", astNodeToString(a), strings.Join(n, " -> "))) { + if !c.err(NewError(RecursionErr, loc, "rule %v is recursive: %v", astNodeToString(rw, a), strings.Join(n, " -> "))) { return } } } -func astNodeToString(x any) string { - return x.(*Rule).Ref().String() +func astNodeToString(rw varRewriter, x any) string { + return rw(x.(*Rule).Ref().CopyNonGround()).String() // varRewriter operates in-place } // checkRuleConflicts ensures that rules definitions are not in conflict. @@ -1515,10 +1556,10 @@ func checkUndefinedFuncs(env *TypeEnv, x any, arity func(Ref) int, rwVars map[Va } func arityMismatchError(env *TypeEnv, f Ref, expr *Expr, exp, act int) *Error { - if want, ok := env.Get(f).(*types.Function); ok { // generate richer error for built-in functions + if want, ok := env.GetByRef(f).(*types.Function); ok { // generate richer error for built-in functions have := make([]types.Type, len(expr.Operands())) for i, op := range expr.Operands() { - have[i] = env.Get(op) + have[i] = env.GetByValue(op.Value) } return newArgError(expr.Loc(), f, "arity mismatch", have, want.NamedFuncArgs()) } @@ -1535,18 +1576,19 @@ func (c *Compiler) checkSafetyRuleBodies() { vis := varVisitorPool.Get() for _, name := range c.sorted { - m := c.Modules[name] - scopes := ruleScopes{module: m} - WalkRules(m, func(r *Rule) bool { - vis = vis.Clear() - // vis.vars == safe - vis.vars.Update(ReservedVars) - if len(r.Head.Args) > 0 { - vis.WalkArgs(r.Head.Args) - } - r.Body = c.checkBodySafety(vis.vars, r.Body, r, &scopes) - return false - }) + scopes := ruleScopes{module: c.Modules[name]} + for _, rule := range c.Modules[name].Rules { + WalkRules(rule, func(r *Rule) bool { + vis = vis.Clear() + // vis.vars == safe + vis.vars.Update(ReservedVars) + if len(r.Head.Args) > 0 { + vis.WalkArgs(r.Head.Args) + } + r.Body = c.checkBodySafety(vis.vars, r.Body, r, &scopes) + return false + }) + } } varVisitorPool.Put(vis) @@ -1564,15 +1606,6 @@ func (c *Compiler) checkBodySafety(safe VarSet, b Body, r *Rule, scopes *ruleSco return reordered } -// SafetyCheckVisitorParams defines the AST visitor parameters to use for collecting -// variables during the safety check. This has to be exported because it's relied on -// by the copy propagation implementation in topdown. -// TODO: deprecate? -var SafetyCheckVisitorParams = VarVisitorParams{ - SkipRefCallHead: true, - SkipClosures: true, -} - // checkSafetyRuleHeads ensures that variables appearing in the head of a // rule also appear in the body. func (c *Compiler) checkSafetyRuleHeads() { @@ -1901,9 +1934,7 @@ func (c *Compiler) checkTypes() { as = c.annotationSet } env, errs := checker.CheckTypes(c.TypeEnv, sorted, as) - for _, err := range errs { - c.err(err) - } + c.errRecoverable(errs...) c.TypeEnv = env } @@ -1947,10 +1978,7 @@ func (c *Compiler) checkUnsafeBuiltins() { } for _, name := range c.sorted { - errs := checkUnsafeBuiltins(c.unsafeBuiltinsMap, c.Modules[name]) - for _, err := range errs { - c.err(err) - } + c.errRecoverable(checkUnsafeBuiltins(c.unsafeBuiltinsMap, c.Modules[name])...) } } @@ -1968,7 +1996,7 @@ func (c *Compiler) checkDeprecatedBuiltins() { for _, name := range c.sorted { if c.strict || c.Modules[name].regoV1Compatible() { - c.err(checkDeprecatedBuiltins(c.deprecatedBuiltinsMap, c.Modules[name])...) + c.errRecoverable(checkDeprecatedBuiltins(c.deprecatedBuiltinsMap, c.Modules[name])...) } } } @@ -1976,25 +2004,40 @@ func (c *Compiler) checkDeprecatedBuiltins() { func (c *Compiler) compile() { plan := c.getOrBuildPlan() + defer c.sortErrors() + if c.metrics != nil { for _, s := range plan.stages { c.metrics.Timer(s.metricName).Start() s.f() c.metrics.Timer(s.metricName).Stop() - if c.Failed() { + if c.unrecoverableErr { return } } } else { for _, s := range plan.stages { s.f() - if c.Failed() { + if c.unrecoverableErr { return } } } } +// sortErrors orders errors by location so reports read top-to-bottom. The error +// limit marker has no location of its own and is swapped to the end to keep it +// last, wherever it was recorded. +func (c *Compiler) sortErrors() { + errs := c.Errors + if i := slices.Index(errs, errLimitReached); i >= 0 { + errs[i], errs[len(errs)-1] = errs[len(errs)-1], errs[i] + errs = errs[:len(errs)-1] + } + + errs.Sort() +} + func (c *Compiler) init() { if c.initialized { @@ -2071,7 +2114,19 @@ func (c *Compiler) init() { c.initialized = true } +// err records an error that stops compilation after the current stage. func (c *Compiler) err(errs ...*Error) bool { // returns if we should continue + return c.recordErrs(false, errs...) +} + +// errRecoverable records an error that lets the remaining stages run, so that one +// compilation can report every violation it finds. Only for checks that leave the +// modules in a state later stages can't produce bogus follow-up errors from. +func (c *Compiler) errRecoverable(errs ...*Error) bool { + return c.recordErrs(true, errs...) +} + +func (c *Compiler) recordErrs(recoverable bool, errs ...*Error) bool { if len(errs) == 0 { return true } @@ -2081,6 +2136,7 @@ func (c *Compiler) err(errs ...*Error) bool { // returns if we should continue if c.maxErrs <= 0 { c.Errors = append(c.Errors, errs...) + c.unrecoverableErr = c.unrecoverableErr || !recoverable return true } @@ -2099,6 +2155,8 @@ func (c *Compiler) err(errs ...*Error) bool { // returns if we should continue c.errCount += uint32(numToTake) c.Errors = append(c.Errors, errs[:numToTake]...) + // Nothing left to collect once the limit is hit, so stop there too. + c.unrecoverableErr = c.unrecoverableErr || !recoverable || isLimitReachedInThisCall if isLimitReachedInThisCall { c.Errors = append(c.Errors, errLimitReached) } @@ -2106,42 +2164,35 @@ func (c *Compiler) err(errs ...*Error) bool { // returns if we should continue return !isLimitReachedInThisCall // Return false if the limit was reached, true otherwise. } -func (c *Compiler) getExports() *util.HasherMap[Ref, []Ref] { - rules := util.NewHasherMap[Ref, []Ref](RefEqual) - +func (c *Compiler) getExport(pkg Ref) []Ref { + var refs []Ref for _, name := range c.sorted { - for _, rule := range c.Modules[name].Rules { - hashMapAdd(rules, c.Modules[name].Package.Path, rule.Head.Ref().GroundPrefix()) + if RefEqual(pkg, c.Modules[name].Package.Path) { + refs = slices.Grow(refs, len(c.Modules[name].Rules)) + for _, rule := range c.Modules[name].Rules { + refs = append(refs, rule.Head.Ref().GroundPrefix()) + } } } - - return rules + return refs } -func refSliceEqual(a, b []Ref) bool { - if len(a) != len(b) { - return false - } - for i := range a { - if !a[i].Equal(b[i]) { - return false - } - } - return true -} +// getExports groups every module's exported rule refs by package path in one +// pass. Use this instead of getExport per package, which is quadratic. +func (c *Compiler) getExports() *util.HasherMap[Ref, []Ref] { + rules := util.NewHasherMap[Ref, []Ref](RefEqual) -func hashMapAdd(rules *util.HasherMap[Ref, []Ref], pkg, rule Ref) { - prev, ok := rules.Get(pkg) - if !ok { - rules.Put(pkg, []Ref{rule}) - return - } - for _, p := range prev { - if p.Equal(rule) { - return + for _, name := range c.sorted { + mod := c.Modules[name] + refs, _ := rules.Get(mod.Package.Path) + refs = slices.Grow(refs, len(mod.Rules)) + for _, rule := range mod.Rules { + refs = append(refs, rule.Head.Ref().GroundPrefix()) } + rules.Put(mod.Package.Path, refs) } - rules.Put(pkg, append(prev, rule)) + + return rules } func (c *Compiler) GetAnnotationSet() *AnnotationSet { @@ -2157,7 +2208,7 @@ func (c *Compiler) checkImports() { for _, name := range c.sorted { for _, imp := range c.Modules[name].Imports { if !supportsRegoV1Import && RegoV1CompatibleRef.Equal(imp.Path.Value) { - if !c.err(NewError(CompileErr, imp.Loc(), "rego.v1 import is not supported")) { + if !c.errRecoverable(NewError(CompileErr, imp.Loc(), "rego.v1 import is not supported")) { continue } } @@ -2168,13 +2219,25 @@ func (c *Compiler) checkImports() { } } - c.err(checkDuplicateImports(modules)...) + c.errRecoverable(checkDuplicateImports(modules)...) +} + +// checkUnusedImports reports the imports resolveAllRefs found unused. Strict mode +// only, and a stage of its own so these don't cut compilation short. +func (c *Compiler) checkUnusedImports() { + for _, imp := range c.unusedImports { + if !c.errRecoverable(NewError(CompileErr, imp.Location, "%s unused", imp.String())) { + break + } + } + + c.unusedImports = nil } func (c *Compiler) checkKeywordOverrides() { for _, name := range c.sorted { if c.strict || c.moduleIsRegoV1Compatible(c.Modules[name]) { - if !c.err(checkRootDocumentOverrides(c.Modules[name])...) { + if !c.errRecoverable(checkRootDocumentOverrides(c.Modules[name])...) { continue } } @@ -2227,15 +2290,12 @@ func (c *Compiler) moduleIsRegoV1Compatible(mod *Module) bool { // // The reference "c.d.e" would be resolved to "data.a.b.c.d.e". func (c *Compiler) resolveAllRefs() { - rules := c.getExports() + exports := c.getExports() + c.unusedImports = nil for _, name := range c.sorted { mod := c.Modules[name] - var ruleExports []Ref - if x, ok := rules.Get(mod.Package.Path); ok { - ruleExports = x - } - + ruleExports, _ := exports.Get(mod.Package.Path) globals := getGlobals(mod.Package, ruleExports, mod.Imports) WalkRules(mod, func(rule *Rule) bool { @@ -2246,7 +2306,7 @@ func (c *Compiler) resolveAllRefs() { return false }) - if c.strict { // check for unused imports + if c.strict { // collect unused imports, reported by the CheckUnusedImports stage for _, imp := range mod.Imports { path := imp.Path.Value.(Ref) if FutureRootDocument.Equal(path[0]) || RegoRootDocument.Equal(path[0]) { @@ -2255,9 +2315,7 @@ func (c *Compiler) resolveAllRefs() { for v, u := range globals { if v == imp.Name() && !u.used { - if !c.err(NewError(CompileErr, imp.Location, "%s unused", imp.String())) { - return - } + c.unusedImports = append(c.unusedImports, imp) } } } @@ -2303,10 +2361,23 @@ func (c *Compiler) initLocalVarGen() { func (c *Compiler) rewriteComprehensionTerms() { f := newEqualityFactory(c.localvargen) for _, name := range c.sorted { + // Transform rebuilds what it walks, so finding nothing is not free. + if !ContainsComprehensions(c.Modules[name]) { + continue + } _, _ = rewriteComprehensionTerms(f, c.Modules[name]) // ignore error } } +func containsWith(x any) bool { + found := false + WalkWiths(x, func(*With) bool { + found = true + return found + }) + return found +} + func (c *Compiler) rewriteExprTerms() { for _, name := range c.sorted { WalkRules(c.Modules[name], func(rule *Rule) bool { @@ -2378,6 +2449,8 @@ func (c *Compiler) rewriteRuleHeadRefs() { } } +// checkVoidCalls errors are not recoverable: the type checker has no type for an +// expression using a void result, and reports a bogus "undefined function" for it. func (c *Compiler) checkVoidCalls() { for _, name := range c.sorted { c.err(checkVoidCalls(c.TypeEnv, c.Modules[name])...) @@ -2468,6 +2541,12 @@ func (c *Compiler) rewriteTemplateStrings() { for _, name := range c.sorted { mod := c.Modules[name] WalkRules(mod, func(r *Rule) bool { + // The output vars computed below are read only to resolve a template + // string, and most rules have none to resolve. + if !containsTemplateString(r) { + return false + } + tsr = tsr.Clear() safe := r.Head.Args.Vars() @@ -2497,6 +2576,17 @@ func (c *Compiler) rewriteTemplateStrings() { } } +func containsTemplateString(x any) bool { + found := false + WalkTerms(x, func(t *Term) bool { + if _, ok := t.Value.(*TemplateString); ok { + found = true + } + return found + }) + return found +} + func rewriteTemplateStrings(tsr *templateStringRewriter, globals VarSet, x any) (bool, VarSet, Errors) { var errs Errors var modified bool @@ -2510,7 +2600,7 @@ func rewriteTemplateStrings(tsr *templateStringRewriter, globals VarSet, x any) safe = globals.Copy() } - vis := &GenericVisitor{func(x any) bool { + vis := NewGenericVisitor(func(x any) bool { var modrec bool var errsrec Errors switch x := x.(type) { @@ -2567,7 +2657,7 @@ func rewriteTemplateStrings(tsr *templateStringRewriter, globals VarSet, x any) } errs = append(errs, errsrec...) return false - }} + }) vis.Walk(x) return modified, safe, errs @@ -2723,7 +2813,7 @@ func checkVoidCalls(env *TypeEnv, x any) Errors { var errs Errors WalkTerms(x, func(x *Term) bool { if call, ok := x.Value.(Call); ok { - if tpe, ok := env.Get(call[0]).(*types.Function); ok && tpe.Result() == nil { + if tpe, ok := env.GetByValue(call[0].Value).(*types.Function); ok && tpe.Result() == nil { errs = append(errs, NewError(TypeErr, x.Loc(), "%v used as value", call)) } } @@ -2876,7 +2966,7 @@ func containsNestedBody(x any) bool { func erasePrintCalls(node any) bool { var modified bool - NewGenericVisitor(func(x any) bool { + vis := NewGenericVisitor(func(x any) bool { var modrec bool switch x := x.(type) { case *Rule: @@ -2906,7 +2996,8 @@ func erasePrintCalls(node any) bool { modified = true } return false - }).Walk(node) + }) + vis.Walk(node) return modified } @@ -3258,7 +3349,7 @@ func createMetadataChain(chain []*AnnotationsRef) (*Term, *Error) { func (c *Compiler) rewriteLocalVars() { var assignment bool - args := NewVarVisitor() + args := varVisitorPool.Get() argsStack := newLocalDeclaredVars() for _, name := range c.sorted { @@ -3284,6 +3375,9 @@ func (c *Compiler) rewriteLocalVars() { if !c.err(errs...) { return true } + if !c.errRecoverable(stack.unused...) { + return true + } if stack.assignment { assignment = true } @@ -3299,7 +3393,13 @@ func (c *Compiler) rewriteLocalVars() { // Report an error for each unused function argument for arg := range unusedArgs { if !arg.IsWildcard() { - if !c.err(NewError(CompileErr, rule.Head.Location, "unused argument %v. (hint: use _ (wildcard variable) instead)", arg)) { + err := NewError( + CompileErr, + rule.Head.Location, + "unused argument %v. (hint: use _ (wildcard variable) instead)", + arg, + ) + if !c.errRecoverable(err) { return true } } @@ -3313,6 +3413,8 @@ func (c *Compiler) rewriteLocalVars() { if assignment { c.Required.addBuiltinSorted(Assign) } + + varVisitorPool.Put(args) } func (c *Compiler) rewriteLocalVarsInRule(rule *Rule, unusedArgs VarSet, argsStack *localDeclaredVars, gen *localVarGenerator) (*localDeclaredVars, Errors) { @@ -3337,11 +3439,14 @@ func (c *Compiler) rewriteLocalVarsInRule(rule *Rule, unusedArgs VarSet, argsSta strict: c.strict, } - NewGenericVisitor(nestedXform.Visit).Walk(rule.Head) + nxfVis := NewGenericVisitor(nestedXform.Visit) + nxfVis.Walk(rule.Head) c.err(nestedXform.errs...) // NB(sr): This is a bit bogus -- Why not return them? + c.errRecoverable(nestedXform.unused...) // Rewrite assignments in body. - vis := NewVarVisitor() + vis := varVisitorPool.Get() + defer varVisitorPool.Put(vis) for _, t := range rule.Head.Ref()[1:] { if !IsScalar(t.Value) { @@ -3378,31 +3483,32 @@ func (c *Compiler) rewriteLocalVarsInRule(rule *Rule, unusedArgs VarSet, argsSta // references (stay unsafe-var errors), call operators (SkipRefCallHead), // and `with` targets/values (possible function mocks). if len(c.builtins) > 0 { - bodyVis := NewVarVisitor().WithParams(VarVisitorParams{ + bodyVis := varVisitorPool.Get().WithParams(VarVisitorParams{ SkipRefCallHead: true, SkipClosures: true, }) + defer varVisitorPool.Put(bodyVis) + bodyVis.Walk(rule.Body) bodyVars := bodyVis.Vars() - declaredInBody := declaredVars(rule.Body) + declaredInBody := declaredBodyVars(rule.Body) - withVars := NewVarSet() - NewGenericVisitor(func(x any) bool { - if w, ok := x.(*With); ok { - WalkVars(w, func(v Var) bool { - withVars.Add(v) - return false - }) - } + withVis := varVisitorPool.Get().WithParams(VarVisitorParams{SkipRefCallHead: true}) + defer varVisitorPool.Put(withVis) + + f := func(w *With) bool { + withVis.Walk(w.Target.Value) + withVis.Walk(w.Value.Value) return false - }).Walk(rule) + } + WalkWiths(rule, f) for _, v := range bodyVars.Sorted() { if _, ok := c.builtins[v.String()]; !ok { continue } - if declaredInBody.Contains(v) || withVars.Contains(v) { + if declaredInBody.Contains(v) || withVis.Vars().Contains(v) { continue } if _, ok := stack.Declared(v); ok { @@ -3471,35 +3577,42 @@ func headMayHaveVars(head *Head) bool { type rewriteNestedHeadVarLocalTransform struct { gen *localVarGenerator errs Errors + unused Errors // strict-mode "unused var" diagnostics, see localDeclaredVars.unused RewrittenVars map[Var]Var strict bool } func (xform *rewriteNestedHeadVarLocalTransform) Visit(x any) bool { if term, ok := x.(*Term); ok { + if IsScalar(term.Value) { + return false + } + stop := false stack := newLocalDeclaredVars() switch x := term.Value.(type) { case *object: - vis := NewGenericVisitor(xform.Visit) - cpy, _ := x.Map(func(k, v *Term) (*Term, *Term, error) { - kcpy := k.Copy() - vis.Walk(kcpy) - vcpy := v.Copy() - vis.Walk(vcpy) - return kcpy, vcpy, nil - }) - term.Value = cpy + if !x.IsGround() { + vis := NewGenericVisitor(xform.Visit) + term.Value, _ = x.Map(func(k, v *Term) (*Term, *Term, error) { + kcpy := k.Copy() + vis.Walk(kcpy) + vcpy := v.Copy() + vis.Walk(vcpy) + return kcpy, vcpy, nil + }) + } stop = true case *set: - vis := NewGenericVisitor(xform.Visit) - cpy, _ := x.Map(func(v *Term) (*Term, error) { - vcpy := v.Copy() - vis.Walk(vcpy) - return vcpy, nil - }) - term.Value = cpy + if !x.IsGround() { + vis := NewGenericVisitor(xform.Visit) + term.Value, _ = x.Map(func(v *Term) (*Term, error) { + vcpy := v.Copy() + vis.Walk(vcpy) + return vcpy, nil + }) + } stop = true case *ArrayComprehension: xform.errs = rewriteDeclaredVarsInArrayComprehension(xform.gen, stack, x, xform.errs, xform.strict) @@ -3516,6 +3629,7 @@ func (xform *rewriteNestedHeadVarLocalTransform) Visit(x any) bool { } maps.Copy(xform.RewrittenVars, stack.rewritten) + xform.unused = append(xform.unused, stack.unused...) return stop } @@ -3537,14 +3651,9 @@ func (xform rewriteHeadVarLocalTransform) Transform(x any) (any, error) { } func (c *Compiler) rewriteLocalArgVars(gen *localVarGenerator, stack *localDeclaredVars, rule *Rule) { - vis := &ruleArgLocalRewriter{ - stack: stack, - gen: gen, - } - - for i := range rule.Head.Args { - Walk(vis, rule.Head.Args[i]) - } + vis := &ruleArgLocalRewriter{stack: stack, gen: gen} + vis.gv = &GenericVisitor{f: vis.visit} + vis.gv.Walk(rule.Head.Args) c.err(vis.errs...) } @@ -3552,16 +3661,15 @@ func (c *Compiler) rewriteLocalArgVars(gen *localVarGenerator, stack *localDecla type ruleArgLocalRewriter struct { stack *localDeclaredVars gen *localVarGenerator + gv *GenericVisitor errs []*Error } -func (vis *ruleArgLocalRewriter) Visit(x any) Visitor { - - t, ok := x.(*Term) +func (vis *ruleArgLocalRewriter) visit(a any) bool { + t, ok := a.(*Term) if !ok { - return vis + return false } - switch v := t.Value.(type) { case Var: gv, ok := vis.stack.Declared(v) @@ -3572,37 +3680,39 @@ func (vis *ruleArgLocalRewriter) Visit(x any) Visitor { vis.stack.Insert(v, gv, argVar) } t.Value = gv - return nil + return true case *object: if cpy, err := v.Map(func(k, v *Term) (*Term, *Term, error) { vcpy := v.Copy() - Walk(vis, vcpy) + vis.gv.Walk(vcpy) return k, vcpy, nil }); err != nil { vis.errs = append(vis.errs, newErrorString(CompileErr, t.Location, err.Error())) } else { t.Value = cpy } - return nil + return true case Null, Boolean, Number, String, *ArrayComprehension, *SetComprehension, *ObjectComprehension, Set, *TemplateString: // Scalars are no-ops. Comprehensions and template-strings are handled above. Sets must not // contain variables. - return nil + return true case Call: vis.errs = append(vis.errs, NewError(CompileErr, t.Location, "rule arguments cannot contain calls")) - return nil - default: - // Recurse on refs and arrays. Any embedded - // variables can be rewritten. - return vis + return true } + // Recurse on refs and arrays. Any embedded variables can be rewritten. + return false } func (c *Compiler) rewriteWithModifiers() { f := newEqualityFactory(c.localvargen) for _, name := range c.sorted { mod := c.Modules[name] - t := NewGenericTransformer(func(x any) (any, error) { + // As above: a module with no with modifier would be rebuilt unchanged. + if !containsWith(mod) { + continue + } + t := GenericTransformer{f: func(x any) (any, error) { body, ok := x.(Body) if !ok { return x, nil @@ -3613,7 +3723,7 @@ func (c *Compiler) rewriteWithModifiers() { } return body, nil - }) + }} _, _ = Transform(t, mod) // ignore error } } @@ -3810,18 +3920,13 @@ func (qc *queryCompiler) resolveRefs(qctx *QueryContext, body Body) (Body, error pkg = emptyPackage } if pkg != nil { - var ruleExports []Ref - rules := qc.compiler.getExports() - if exist, ok := rules.Get(pkg.Path); ok { - ruleExports = exist - } - + ruleExports := qc.compiler.getExport(pkg.Path) globals = getGlobals(qctx.Package, ruleExports, qctx.Imports) qctx.Imports = nil } } - ignore := &declaredVarStack{declaredVars(body)} + ignore := &declaredVarStack{declaredBodyVars(body)} return resolveRefsInBody(globals, ignore, body), nil } @@ -3855,6 +3960,7 @@ func (qc *queryCompiler) rewriteLocalVars(_ *QueryContext, body Body) (Body, err gen := newLocalVarGenerator("q", body) stack := newLocalDeclaredVars() body, _, err := rewriteLocalVars(gen, stack, nil, body, qc.compiler.strict) + err = append(err, stack.unused...) if len(err) != 0 { return nil, err } @@ -3984,16 +4090,21 @@ func (ci *ComprehensionIndex) String() string { return fmt.Sprintf("", NewArray(ci.Keys...)) } -func buildComprehensionIndices(dbg debug.Debug, arity func(Ref) int, candidates VarSet, rwVars map[Var]Var, node Body, result map[*Term]*ComprehensionIndex) uint64 { - var n uint64 +func buildComprehensionIndices( + dbg debug.Debug, + arity func(Ref) int, + candidates VarSet, + rwVars map[Var]Var, + node Body, + result map[*Term]*ComprehensionIndex, +) (n uint64) { cpy := candidates.Copy() vis := varVisitorPool.Get() - defer varVisitorPool.Put(vis) WalkBodies(node, func(b Body) bool { for _, expr := range b { - index := getComprehensionIndex(dbg, arity, cpy, rwVars, expr) + index := getComprehensionIndex(dbg, arity, cpy, rwVars, expr, vis) if index != nil { result[index.Term] = index n++ @@ -4001,15 +4112,24 @@ func buildComprehensionIndices(dbg debug.Debug, arity func(Ref) int, candidates // Any variables appearing in the expressions leading up to the comprehension // are fair-game to be used as index keys. vis = vis.Clear().WithParams(VarVisitorParams{SkipClosures: true, SkipRefCallHead: true}) + old := vis.vars + vis.vars = cpy vis.Walk(expr) - cpy.Update(vis.Vars()) + vis.vars = old } return false }) return n } -func getComprehensionIndex(dbg debug.Debug, arity func(Ref) int, candidates VarSet, rwVars map[Var]Var, expr *Expr) *ComprehensionIndex { +func getComprehensionIndex( + dbg debug.Debug, + arity func(Ref) int, + candidates VarSet, + rwVars map[Var]Var, + expr *Expr, + vis *VarVisitor, +) *ComprehensionIndex { // Ignore everything except = expressions. Extract // the comprehension term from the expression. if !expr.IsEquality() || expr.Negated || len(expr.With) > 0 { @@ -4062,10 +4182,14 @@ func getComprehensionIndex(dbg debug.Debug, arity func(Ref) int, candidates VarS body = x.Body } - outputs := outputVarsForBody(body, arity, ReservedVars, nil) - unsafe := body.Vars(SafetyCheckVisitorParams).Diff(outputs).Diff(ReservedVars) + vis = vis.Clear().WithParams(SafetyCheckVisitorParams) + outputs := outputVarsForBody(body, arity, ReservedVars, vis) - if len(unsafe) > 0 { + vis.Clear().WithParams(SafetyCheckVisitorParams).Walk(body) + unsafe := vis.Vars().Diff(outputs) + + if unsafe.DiffCount(ReservedVars) > 0 { + unsafe = unsafe.Diff(ReservedVars) dbg.Printf("%s: comprehension index: unsafe vars: %v", expr.Location, unsafe) return nil } @@ -4100,12 +4224,7 @@ func getComprehensionIndex(dbg debug.Debug, arity func(Ref) int, candidates VarS return nil } - result := make([]*Term, 0, len(indexVars)) - for v := range indexVars { - result = append(result, NewTerm(v)) - } - slices.SortFunc(result, TermValueCompare) - + result := util.SortedFunc(util.MapKeys(indexVars, ToTerm), TermValueCompare) debugRes := make([]*Term, len(result)) for i, r := range result { if o, ok := rwVars[r.Value.(Var)]; ok { @@ -4124,15 +4243,6 @@ type comprehensionIndexRegressionCheckVisitor struct { worse bool } -// TODO(tsandall): Improve this so that users can either supply this list explicitly -// or the information is maintained on the built-in function declaration. What we really -// need to know is whether the built-in function allows callers to push down output -// values or not. It's unlikely that anything outside of OPA does this today so this -// solution is fine for now. -var comprehensionIndexBlacklist = map[string]int{ - WalkBuiltin.Name: len(WalkBuiltin.Decl.FuncArgs().Args), -} - func newComprehensionIndexRegressionCheckVisitor(candidates VarSet) *comprehensionIndexRegressionCheckVisitor { return &comprehensionIndexRegressionCheckVisitor{ candidates: candidates, @@ -4149,7 +4259,7 @@ func (vis *comprehensionIndexRegressionCheckVisitor) visit(x any) bool { switch x := x.(type) { case *Expr: operands := x.Operands() - if pos := comprehensionIndexBlacklist[x.Operator().String()]; pos > 0 && pos < len(operands) { + if pos := comprehensionIndexDenylist[x.Operator().String()]; pos > 0 && pos < len(operands) { vis.assertEmptyIntersection(operands[pos].Vars()) } case Ref: @@ -4543,12 +4653,21 @@ func (n *TreeNode) find(ref Ref) (*TreeNode, Ref) { // DepthFirst performs a depth-first traversal of the rule tree rooted at n. If // f returns true, traversal will not continue to the children of n. +// DepthFirst calls f on n and then, in key order, on everything below it. The +// order is the map's own otherwise, and callers building an index from what they +// walk hand the order on to their results. func (n *TreeNode) DepthFirst(f func(*TreeNode) bool) { if f(n) { return } - for _, node := range n.Children { - node.DepthFirst(f) + if len(n.Children) < 2 { + for _, node := range n.Children { // no order to choose, and no slice to build + node.DepthFirst(f) + } + return + } + for _, key := range util.KeysSortedFunc(n.Children, Value.Compare) { + n.Children[key].DepthFirst(f) } } @@ -4683,8 +4802,7 @@ func (n *TreeNode) Copy() *TreeNode { } if n.Sorted != nil { - result.Sorted = make([]Value, len(n.Sorted)) - copy(result.Sorted, n.Sorted) + result.Sorted = slices.Clone(n.Sorted) } return result @@ -4791,11 +4909,9 @@ func (g *Graph) Sort() (sorted []util.T, ok bool) { temp: map[util.T]struct{}{}, } - nodesList := make([]util.T, 0, len(g.nodes)) - for node := range g.nodes { - nodesList = append(nodesList, node) - } + nodesList := util.Keys(g.nodes) sortGraphNodes(nodesList) + for _, node := range nodesList { if !sorter.Visit(node) { return nil, false @@ -4993,17 +5109,19 @@ func (vs unsafeVars) Slice() (result []unsafePair) { // If the body cannot be reordered to ensure safety, the second return value // contains a mapping of expressions to unsafe variables in those expressions. func reorderBodyForSafety(builtins map[string]*Builtin, arity func(Ref) int, globals VarSet, body Body) (Body, unsafeVars) { - vis := varVisitorPool.Get().WithParams(SafetyCheckVisitorParamsWithArity(arity)) - vis.WalkBody(body) + params := SafetyCheckVisitorParamsWithArity(arity) + vis := varVisitorPool.Get().WithParams(params) defer varVisitorPool.Put(vis) + vis.WalkBody(body) + bodyVars := vis.Vars().Copy() safe := bodyVars.Intersect(globals) unsafe := make(unsafeVars, len(bodyVars)-len(safe)) for _, e := range body { - vis = vis.Clear().WithParams(SafetyCheckVisitorParamsWithArity(arity)) + vis = vis.Clear().WithParams(params) vis.Walk(e) for v := range vis.Vars() { if _, ok := safe[v]; !ok { @@ -5032,15 +5150,19 @@ func reorderBodyForSafety(builtins map[string]*Builtin, arity func(Ref) int, glo cv := unsVis.Vars().Intersect(bodyVars).Diff(globals) unsVis.Clear() - ob := outputVarsForBody(reordered, arity, safe, vis) + // ob is the expensive part of this loop, and an empty cv makes the + // comparisons below hold whatever it is. + if len(cv) > 0 { + ob := outputVarsForBody(reordered, arity, safe, vis) - if cv.DiffCount(ob) > 0 { - uv := cv.Diff(ob) - if uv.Equal(ovs) { // special case "closure-self" - continue + if cv.DiffCount(ob) > 0 { + uv := cv.Diff(ob) + if uv.Equal(ovs) { // special case "closure-self" + continue + } + // The expression is closing over variables not yet present in reordered body + unsafe.Set(e, uv) } - // The expression is closing over variables not yet present in reordered body - unsafe.Set(e, uv) } for v := range unsafe[e] { @@ -5066,19 +5188,20 @@ func reorderBodyForSafety(builtins map[string]*Builtin, arity func(Ref) int, glo // Recursively visit closures and perform the safety checks on them. // Update the globals at each expression to include the variables that could // be closed over. - g := globals.Copy() xform := newBodySafetyTransformer(builtins, arity) xform.gv = NewGenericVisitor(xform.Visit) + xform.unsafe = unsafe + xform.globals = globals.Copy() + + vis = vis.WithParams(params) + vis.vars = xform.globals + for i, e := range reordered { if i > 0 { - vis = vis.Clear().WithParams(SafetyCheckVisitorParamsWithArity(arity)) vis.Walk(reordered[i-1]) - g.Update(vis.Vars()) } xform.current = e - xform.globals = g - xform.unsafe = unsafe xform.gv.Walk(e) } @@ -5173,7 +5296,7 @@ func unsafeImplicitBodyVars(body Body, arity func(Ref) int) VarSet { } if e.IsEquality() { - for v := range outputVarsForExprEq(e, VarSet{}, VarSet{}) { + for v := range outputVarsForExprEq(e, VarSet{}, nil) { bindings[v] = struct{}{} } continue @@ -5241,22 +5364,24 @@ func (xform *bodySafetyTransformer) Visit(x any) bool { case *Term: switch x := term.Value.(type) { case *object: - cpy, _ := x.Map(func(k, v *Term) (*Term, *Term, error) { - kcpy := k.Copy() - xform.gv.Walk(kcpy) - vcpy := v.Copy() - xform.gv.Walk(vcpy) - return kcpy, vcpy, nil - }) - term.Value = cpy + if !x.IsGround() { + term.Value, _ = x.Map(func(k, v *Term) (*Term, *Term, error) { + kcpy := k.Copy() + xform.gv.Walk(kcpy) + vcpy := v.Copy() + xform.gv.Walk(vcpy) + return kcpy, vcpy, nil + }) + } return true case *set: - cpy, _ := x.Map(func(v *Term) (*Term, error) { - vcpy := v.Copy() - xform.gv.Walk(vcpy) - return vcpy, nil - }) - term.Value = cpy + if !x.IsGround() { + term.Value, _ = x.Map(func(v *Term) (*Term, error) { + vcpy := v.Copy() + xform.gv.Walk(vcpy) + return vcpy, nil + }) + } return true case *ArrayComprehension: xform.reorderArrayComprehensionSafety(x) @@ -5428,6 +5553,13 @@ func outputVarsForExprEq(expr *Expr, safe VarSet, output VarSet) VarSet { return safe } + // Clear the shared buffer before use. Callers of outputVarsForExpr reuse the + // same VarSet across candidate expressions in a single reorderBodyForSafety + // pass. Without this, leftover bindings from an earlier (not-yet-schedulable) + // call expression can leak into Unify() via the safe basis and incorrectly + // mark an equality as grounded. See issue #8302. + clear(output) + output = outputVarsForTerms(expr, safe, output) output.Update(safe) if expr.fromAssignment { @@ -5468,8 +5600,15 @@ func outputVarsForExprCall(expr *Expr, arity int, safe VarSet, terms []*Term, vi vis = ClearOrNewVarVisitor(vis).WithParams(params) vis.WalkArgs(Args(terms[:numInputTerms])) - unsafe := vis.Vars().Diff(output).DiffCount(safe) - if unsafe > 0 { + unsafe := vis.Vars() + for i := range output { + delete(unsafe, i) + } + for i := range safe { + delete(unsafe, i) + } + + if len(unsafe) > 0 { return VarSet{} } @@ -5520,9 +5659,6 @@ func (f *equalityFactory) Generate(other *Term) *Expr { return expr } -// TODO: Move to internal package? -const LocalVarPrefix = "__local" - type localVarGenerator struct { exclude VarSet suffix string @@ -5650,8 +5786,6 @@ type usedRef struct { } func resolveRefsInRule(globals map[Var]*usedRef, rule *Rule) error { - ignore := &declaredVarStack{} - vars := NewVarSet() var vis *GenericVisitor var err error @@ -5677,30 +5811,27 @@ func resolveRefsInRule(globals map[Var]*usedRef, rule *Rule) error { return true case *Term: - if _, ok := x.Value.(Ref); ok { - if RootDocumentRefs.Contains(x) { - // We could support args named input, data, etc. however - // this would require rewriting terms in the head and body. - // Preventing root document shadowing is simpler, and - // arguably, will prevent confusing names from being used. - // NOTE: this check is also performed as part of strict-mode in - // checkRootDocumentOverrides. - err = fmt.Errorf("args must not shadow %v (use a different variable name)", x) - return true - } + if TermValueIs[Ref](x) && RootDocumentRefs.Contains(x) { + // We could support args named input, data, etc. however + // this would require rewriting terms in the head and body. + // Preventing root document shadowing is simpler, and + // arguably, will prevent confusing names from being used. + // NOTE: this check is also performed as part of strict-mode in + // checkRootDocumentOverrides. + err = fmt.Errorf("args must not shadow %v (use a different variable name)", x) + return true } } return false }) - vis.Walk(rule.Head.Args) if err != nil { return err } - ignore.Push(vars) - ignore.Push(declaredVars(rule.Body)) + ignore := &declaredVarStack{} + ignore.Push(vars, declaredBodyVars(rule.Body)) ref := rule.Head.Ref() for i := 1; i < len(ref); i++ { @@ -5745,12 +5876,12 @@ func resolveRefsInExpr(globals map[Var]*usedRef, ignore *declaredVarStack, expr } } case *Every: - locals := NewVarSet() + vis := varVisitorPool.Get() if ts.Key != nil { - locals.Update(ts.Key.Vars()) + vis.Walk(ts.Key) } - locals.Update(ts.Value.Vars()) - ignore.Push(locals) + vis.Walk(ts.Value) + ignore.Push(vis.Vars()) cpy.Terms = &Every{ Key: ts.Key.Copy(), // TODO(sr): do more? Value: ts.Value.Copy(), // TODO(sr): do more? @@ -5758,6 +5889,7 @@ func resolveRefsInExpr(globals map[Var]*usedRef, ignore *declaredVarStack, expr Body: resolveRefsInBody(globals, ignore, ts.Body), } ignore.Pop() + varVisitorPool.Put(vis) case *Not: cpy.Terms = &Not{ Body: resolveRefsInBody(globals, ignore, ts.Body), @@ -5801,9 +5933,8 @@ func resolveRefsInTerm(globals map[Var]*usedRef, ignore *declaredVarStack, term } return term case Ref: - fqn := resolveRef(globals, ignore, v) cpy := *term - cpy.Value = fqn + cpy.Value = resolveRef(globals, ignore, v) return &cpy case *object: cpy := *term @@ -5822,38 +5953,37 @@ func resolveRefsInTerm(globals map[Var]*usedRef, ignore *declaredVarStack, term cpy.Value = Call(resolveRefsInTermSlice(globals, ignore, v)) return &cpy case Set: - s, _ := v.Map(func(e *Term) (*Term, error) { + cpy := *term + cpy.Value, _ = v.Map(func(e *Term) (*Term, error) { return resolveRefsInTerm(globals, ignore, e), nil }) - cpy := *term - cpy.Value = s return &cpy case *ArrayComprehension: - ac := &ArrayComprehension{} - ignore.Push(declaredVars(v.Body)) - ac.Term = resolveRefsInTerm(globals, ignore, v.Term) - ac.Body = resolveRefsInBody(globals, ignore, v.Body) + ignore.Push(declaredBodyVars(v.Body)) cpy := *term - cpy.Value = ac + cpy.Value = &ArrayComprehension{ + Term: resolveRefsInTerm(globals, ignore, v.Term), + Body: resolveRefsInBody(globals, ignore, v.Body), + } ignore.Pop() return &cpy case *ObjectComprehension: - oc := &ObjectComprehension{} - ignore.Push(declaredVars(v.Body)) - oc.Key = resolveRefsInTerm(globals, ignore, v.Key) - oc.Value = resolveRefsInTerm(globals, ignore, v.Value) - oc.Body = resolveRefsInBody(globals, ignore, v.Body) + ignore.Push(declaredBodyVars(v.Body)) cpy := *term - cpy.Value = oc + cpy.Value = &ObjectComprehension{ + Key: resolveRefsInTerm(globals, ignore, v.Key), + Value: resolveRefsInTerm(globals, ignore, v.Value), + Body: resolveRefsInBody(globals, ignore, v.Body), + } ignore.Pop() return &cpy case *SetComprehension: - sc := &SetComprehension{} - ignore.Push(declaredVars(v.Body)) - sc.Term = resolveRefsInTerm(globals, ignore, v.Term) - sc.Body = resolveRefsInBody(globals, ignore, v.Body) + ignore.Push(declaredBodyVars(v.Body)) cpy := *term - cpy.Value = sc + cpy.Value = &SetComprehension{ + Term: resolveRefsInTerm(globals, ignore, v.Term), + Body: resolveRefsInBody(globals, ignore, v.Body), + } ignore.Pop() return &cpy case *TemplateString: @@ -5903,12 +6033,8 @@ func (s declaredVarStack) Contains(v Var) bool { return false } -func (s declaredVarStack) Add(v Var) { - s[len(s)-1].Add(v) -} - -func (s *declaredVarStack) Push(vs VarSet) { - *s = append(*s, vs) +func (s *declaredVarStack) Push(vs ...VarSet) { + *s = append(*s, vs...) } func (s *declaredVarStack) Pop() { @@ -5916,16 +6042,31 @@ func (s *declaredVarStack) Pop() { *s = curr[:len(curr)-1] } -func declaredVars(x any) VarSet { +func declaredBodyVars(body Body) VarSet { vars := NewVarSet() + for _, e := range body { + vars = declaredVars(e, vars) + } + return vars +} + +func declaredVars(x any, vars VarSet) VarSet { + if vars == nil { + vars = NewVarSet() + } vis := NewGenericVisitor(func(x any) bool { switch x := x.(type) { case *Expr: if x.IsAssignment() && validEqAssignArgCount(x) { - WalkVars(x.Operand(0), func(v Var) bool { + lhs := x.Operand(0) + if v, ok := lhs.Value.(Var); ok { vars.Add(v) - return false - }) + } else { + WalkVars(lhs, func(v Var) bool { + vars.Add(v) + return false + }) + } } else if decl, ok := x.Terms.(*SomeDecl); ok { for i := range decl.Symbols { switch val := decl.Symbols[i].Value.(type) { @@ -6017,16 +6158,15 @@ func rewriteComprehensionTerms(f *equalityFactory, node any) (any, error) { func rewriteEquals(x any) (modified bool) { // Note: can't use Interned.Refs.Equality here as this may be mutated unifyOp := Equality.Ref() - t := NewGenericTransformer(func(x any) (any, error) { + t := GenericTransformer{f: func(x any) (any, error) { if x, ok := x.(*Expr); ok && x.IsCall() { - operator := x.Operator() - if operator.Equal(Interned.Refs.Equal) && len(x.Operands()) == 2 { + if x.Operator().Equal(Interned.Refs.Equal) && len(x.Operands()) == 2 { modified = true x.SetOperator(NewTerm(unifyOp)) } } return x, nil - }) + }} _, _ = Transform(t, x) // ignore error return modified } @@ -6044,7 +6184,8 @@ func rewriteTestEqualities(f *equalityFactory, body Body) Body { result, terms[2] = rewriteDynamicsShallow(expr, f, terms[2], result) case expr.IsEvery(): // We rewrite equalities inside of every-bodies as a fail here will be the cause of the test-rule fail. - // Failures inside other expressions with closures, such as comprehensions, won't cause the test-rule to fail, so we skip those. + // Failures inside other expressions with closures, such as comprehensions, won't cause the test-rule to + // fail, so we skip those. every := expr.Terms.(*Every) every.Body = rewriteTestEqualities(f, every.Body) } @@ -6201,13 +6342,13 @@ func rewriteDynamicsOne(original *Expr, f *equalityFactory, term *Term, result B }) return result, NewTerm(cpy).SetLocation(term.Location) case Set: - cpy := NewSet() + terms := make([]*Term, 0, v.Len()) for _, term := range v.Slice() { var rw *Term result, rw = rewriteDynamicsOne(original, f, term, result) - cpy.Add(rw) + terms = append(terms, rw) } - return result, NewTerm(cpy).SetLocation(term.Location) + return result, SetTerm(terms...).SetLocation(term.Location) case *ArrayComprehension: var extra *Expr v.Body, extra = rewriteDynamicsComprehensionBody(original, f, v.Body, term) @@ -6502,6 +6643,10 @@ type localDeclaredVars struct { // indicates if an assignment (:= operator) has been seen *ever* assignment bool + + // strict-mode diagnostics for assigned and declared vars that are never used, + // kept apart from the rewrite errors because they're recoverable + unused Errors } type varOccurrence uint8 @@ -6553,6 +6698,7 @@ func (s *localDeclaredVars) Clear() { clear(s.rewritten) s.vars = s.vars[:0] + s.unused = nil if vs != nil { s.vars = append(s.vars, vs.clear()) @@ -6706,13 +6852,15 @@ func rewriteDeclaredVarsInBody(g *localVarGenerator, stack *localDeclaredVars, u cpy.Append(NewExpr(BooleanTerm(true))) } - errs = checkUnusedAssignedVars(body, stack, used, errs, strict) - return cpy, checkUnusedDeclaredVars(body, stack, used, cpy, errs) + checkUnusedAssignedVars(body, stack, used, errs, strict) + checkUnusedDeclaredVars(body, stack, used, cpy, errs) + + return cpy, errs } -func checkUnusedAssignedVars(body Body, stack *localDeclaredVars, used VarSet, errs Errors, strict bool) Errors { - if !strict || len(errs) > 0 { - return errs +func checkUnusedAssignedVars(body Body, stack *localDeclaredVars, used VarSet, errs Errors, strict bool) { + if !strict || len(errs) > 0 || len(stack.unused) > 0 { + return } dvs := stack.Peek() @@ -6724,31 +6872,31 @@ func checkUnusedAssignedVars(body Body, stack *localDeclaredVars, used VarSet, e } } if !hasAssignedVars { - return errs + return } - unused := NewVarSet() + var unused VarSet for v, occ := range dvs.occurrence { // A var that was assigned in this scope must have been seen (used) more than once (the time of assignment) in // the same, or nested, scope to be counted as used. - if !v.IsWildcard() && stack.Count(v) <= 1 && occ == assignedVar { + if !v.IsWildcard() && stack.Count(v) <= 1 && occ == assignedVar && !used.Contains(dvs.vs[v]) { + if unused == nil { + unused = NewVarSet() + } unused.Add(dvs.vs[v]) } } - rewrittenUsed := NewVarSet() + // rewritten unused for v := range used { if gv, ok := stack.Declared(v); ok { - rewrittenUsed.Add(gv) - } else { - rewrittenUsed.Add(v) + delete(unused, gv) } } - unused = unused.Diff(rewrittenUsed) if len(unused) == 0 { - return errs + return } reversed := make(map[Var]Var, len(dvs.vs)) @@ -6760,25 +6908,22 @@ func checkUnusedAssignedVars(body Body, stack *localDeclaredVars, used VarSet, e found := false for i := range body { if body[i].Vars(VarVisitorParams{}).Contains(gv) { - errs = append(errs, NewError(CompileErr, body[i].Loc(), "assigned var %v unused", reversed[gv])) + stack.unused = append(stack.unused, NewError(CompileErr, body[i].Loc(), "assigned var %v unused", reversed[gv])) found = true break } } if !found { - errs = append(errs, NewError(CompileErr, body[0].Loc(), "assigned var %v unused", reversed[gv])) + stack.unused = append(stack.unused, NewError(CompileErr, body[0].Loc(), "assigned var %v unused", reversed[gv])) } } - - return errs } -func checkUnusedDeclaredVars(body Body, stack *localDeclaredVars, used VarSet, cpy Body, errs Errors) Errors { - +func checkUnusedDeclaredVars(body Body, stack *localDeclaredVars, used VarSet, cpy Body, errs Errors) { // NOTE(tsandall): Do not generate more errors if there are existing // declaration errors. - if len(errs) > 0 { - return errs + if len(errs) > 0 || len(stack.unused) > 0 { + return } dvs := stack.Peek() @@ -6790,7 +6935,7 @@ func checkUnusedDeclaredVars(body Body, stack *localDeclaredVars, used VarSet, c } } if !hasDeclaredVars { - return errs + return } declared := NewVarSet() @@ -6813,7 +6958,7 @@ func checkUnusedDeclaredVars(body Body, stack *localDeclaredVars, used VarSet, c dbv := declared.Diff(bodyvars) if dbv.DiffCount(used) == 0 { - return errs + return } reversed := make(map[Var]Var, len(dvs.vs)) @@ -6821,30 +6966,35 @@ func checkUnusedDeclaredVars(body Body, stack *localDeclaredVars, used VarSet, c reversed[v] = k } + var varsDeclaredInExpr VarSet + for _, gv := range dbv.Diff(used).Sorted() { rv := reversed[gv] if !rv.IsGenerated() { // Scan through body exprs, looking for a match between the // bad var's original name, and each expr's declared vars. foundUnusedVarByName := false + if varsDeclaredInExpr == nil { + varsDeclaredInExpr = NewVarSet() + } + for i := range body { - varsDeclaredInExpr := declaredVars(body[i]) + clear(varsDeclaredInExpr) + varsDeclaredInExpr = declaredVars(body[i], varsDeclaredInExpr) if varsDeclaredInExpr.Contains(rv) { // TODO(philipc): Clean up the offset logic here when the parser // reports more accurate locations. - errs = append(errs, NewError(CompileErr, body[i].Loc(), "declared var %v unused", rv)) + stack.unused = append(stack.unused, NewError(CompileErr, body[i].Loc(), "declared var %v unused", rv)) foundUnusedVarByName = true break } } // Default error location returned. if !foundUnusedVarByName { - errs = append(errs, NewError(CompileErr, body[0].Loc(), "declared var %v unused", rv)) + stack.unused = append(stack.unused, NewError(CompileErr, body[0].Loc(), "declared var %v unused", rv)) } } } - - return errs } func rewriteEveryStatement(g *localVarGenerator, stack *localDeclaredVars, expr *Expr, errs Errors, strict bool) (*Expr, Errors) { @@ -6930,12 +7080,6 @@ func rewriteSomeDeclStatement(g *localVarGenerator, stack *localDeclaredVars, ex return nil, errs } -const ( - errAssignInNegated = "cannot assign vars inside negated expression" - errAssignInAndOperand = "cannot assign vars inside implicit and operand" - errAssignInOrOperand = "cannot assign vars inside implicit or operand" -) - func rewriteNotStatement(g *localVarGenerator, stack *localDeclaredVars, expr *Expr, errs Errors, strict bool) (*Expr, Errors) { if not := expr.Terms.(*Not); !not.ExplicitBody { // Only explicit not bodies are allowed to declare vars. @@ -7016,9 +7160,9 @@ func rewriteDeclaredVarsInImplicitBody(g *localVarGenerator, stack *localDeclare } func rewriteDeclaredVarsInExpr(g *localVarGenerator, stack *localDeclaredVars, expr *Expr, errs Errors, strict bool) (*Expr, Errors) { - vis := NewGenericVisitor(func(x any) bool { - var stop bool - // Note: we don't include *Not nodes here, as such bodies are allowed to contain assignments; e.g. 'not {x := input.x; f(x)}' + vis := NewGenericVisitor(func(x any) (stop bool) { + // Note: we don't include *Not nodes here, as such bodies are + // allowed to contain assignments; e.g. 'not {x := input.x; f(x)}' switch x := x.(type) { case *Term: stop, errs = rewriteDeclaredVarsInTerm(g, stack, x, errs, strict) @@ -7032,18 +7176,16 @@ func rewriteDeclaredVarsInExpr(g *localVarGenerator, stack *localDeclaredVars, e } func rewriteDeclaredAssignment(g *localVarGenerator, stack *localDeclaredVars, expr *Expr, errs Errors, strict bool) (*Expr, Errors) { - if expr.Negated { - errs = append(errs, newErrorString(CompileErr, expr.Location, errAssignInNegated)) - return expr, errs + return expr, append(errs, newErrorString(CompileErr, expr.Location, errAssignInNegated)) } - numErrsBefore := len(errs) - if !validEqAssignArgCount(expr) { return expr, errs } + numErrsBefore := len(errs) + // Rewrite terms on right hand side capture seen vars and recursively // process comprehensions before left hand side is processed. Also // rewrite with modifier. @@ -7102,7 +7244,10 @@ func rewriteDeclaredVarsInTerm(g *localVarGenerator, stack *localDeclaredVars, t switch v := term.Value.(type) { case Var: if gv, ok := stack.Declared(v); ok { - term.Value = gv + // don't allocate for boxing Var -> Value unless it changed + if gv != v { + term.Value = gv + } stack.Seen(v) } else if stack.Occurrence(v) == newVar { stack.Insert(v, v, seenVar) @@ -7111,8 +7256,10 @@ func rewriteDeclaredVarsInTerm(g *localVarGenerator, stack *localDeclaredVars, t if RootDocumentRefs.Contains(term) { x := v[0].Value.(Var) if occ, ok := stack.GlobalOccurrence(x); ok && occ != seenVar { - gv, _ := stack.Declared(x) - term.Value = gv + // don't allocate for boxing Var -> Value unless it changed + if gv, _ := stack.Declared(x); gv != x { + term.Value = gv + } } return true, errs @@ -7130,20 +7277,26 @@ func rewriteDeclaredVarsInTerm(g *localVarGenerator, stack *localDeclaredVars, t }) return false, errs case *object: - cpy, _ := v.Map(func(k, v *Term) (*Term, *Term, error) { - kcpy := k.Copy() - errs = rewriteDeclaredVarsInTermRecursive(g, stack, kcpy, errs, strict) - errs = rewriteDeclaredVarsInTermRecursive(g, stack, v, errs, strict) + term.Value, _ = v.Map(func(k, v *Term) (*Term, *Term, error) { + kcpy := k + if !IsScalar(k.Value) { + kcpy = k.Copy() + errs = rewriteDeclaredVarsInTermRecursive(g, stack, kcpy, errs, strict) + } + if !IsScalar(v.Value) { + errs = rewriteDeclaredVarsInTermRecursive(g, stack, v, errs, strict) + } return kcpy, v, nil }) - term.Value = cpy - case Set: - cpy, _ := v.Map(func(elem *Term) (*Term, error) { + case *set: + term.Value, _ = v.Map(func(elem *Term) (*Term, error) { + if IsScalar(elem.Value) { + return elem, nil + } elemcpy := elem.Copy() errs = rewriteDeclaredVarsInTermRecursive(g, stack, elemcpy, errs, strict) return elemcpy, nil }) - term.Value = cpy case *ArrayComprehension: errs = rewriteDeclaredVarsInArrayComprehension(g, stack, v, errs, strict) case *SetComprehension: @@ -7157,8 +7310,7 @@ func rewriteDeclaredVarsInTerm(g *localVarGenerator, stack *localDeclaredVars, t } func rewriteDeclaredVarsInTermRecursive(g *localVarGenerator, stack *localDeclaredVars, term *Term, errs Errors, strict bool) Errors { - WalkTerms(term, func(t *Term) bool { - var stop bool + WalkTerms(term, func(t *Term) (stop bool) { stop, errs = rewriteDeclaredVarsInTerm(g, stack, t, errs, strict) return stop }) @@ -7388,7 +7540,7 @@ func validateWithBuiltinTarget(bi *Builtin, target Ref, loc *location.Location) } switch { - case target.HasPrefix(Ref([]*Term{VarTerm("internal")})): + case len(target) > 0 && Var("internal").Equal(target[0].Value): return NewError(CompileErr, loc, "with keyword replacing built-in function: replacement of internal function %q invalid", target) case bi.Relation: @@ -7437,12 +7589,30 @@ func safetyErrorSlice(unsafe unsafeVars, rewritten map[Var]Var, scope string) (r return } - for _, pair := range unsafe.Vars() { + assignmentLHS := assignmentLHSVars(unsafe, rewritten) + + pairs := unsafe.Vars() + hasNonAssignmentLHS := false + for _, pair := range pairs { + v := pair.Var + if w, ok := rewritten[v]; ok { + v = w + } + if !v.IsGenerated() && !assignmentLHS.Contains(v) && !assignmentLHS.Contains(pair.Var) { + hasNonAssignmentLHS = true + break + } + } + + for _, pair := range pairs { v := pair.Var if w, ok := rewritten[v]; ok { v = w } if !v.IsGenerated() { + if hasNonAssignmentLHS && (assignmentLHS.Contains(v) || assignmentLHS.Contains(pair.Var)) { + continue + } if _, ok := allFutureKeywords[string(v)]; ok { result = append(result, NewError(UnsafeVarErr, pair.Loc, "var %[1]v is unsafe%[2]v (hint: `import future.keywords.%[1]v` to import a future keyword)", v, scope)) @@ -7459,14 +7629,14 @@ func safetyErrorSlice(unsafe unsafeVars, rewritten map[Var]Var, scope string) (r // If the expression contains unsafe generated variables, report which // expressions are unsafe instead of the variables that are unsafe (since // the latter are not meaningful to the user.) - pairs := util.SortedFunc(unsafe.Slice(), func(a, b unsafePair) int { + exprPairs := util.SortedFunc(unsafe.Slice(), func(a, b unsafePair) int { return a.Expr.Location.Compare(b.Expr.Location) }) // Report at most one error per generated variable. seen := NewVarSet() - for _, expr := range pairs { + for _, expr := range exprPairs { before := len(seen) for v := range expr.Vars { if v.IsGenerated() { @@ -7481,6 +7651,23 @@ func safetyErrorSlice(unsafe unsafeVars, rewritten map[Var]Var, scope string) (r return } +func assignmentLHSVars(unsafe unsafeVars, rewritten map[Var]Var) VarSet { + lhs := NewVarSet() + for expr := range unsafe { + if !expr.fromAssignment || !validEqAssignArgCount(expr) { + continue + } + WalkVars(expr.Operand(0), func(v Var) bool { + lhs.Add(v) + if w, ok := rewritten[v]; ok { + lhs.Add(w) + } + return false + }) + } + return lhs +} + // ruleScopes resolves the "in rule ..." label appended to safety errors for the // rules of one module, which is only added where a line holds rules of more than // one name and the location alone is ambiguous. Its index of those lines is built diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/env.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/env.go index ff28b58f4..98c8f4b20 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/env.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/env.go @@ -69,12 +69,7 @@ func (env *TypeEnv) GetByValue(v Value) types.Type { static[i] = env.GetByValue(x.Elem(i).Value) } - var dynamic types.Type - if len(static) == 0 { - dynamic = types.A - } - - return types.NewArray(static, dynamic) + return types.NewArray(static, nil) case *lazyObj: return env.GetByValue(x.force()) @@ -93,10 +88,6 @@ func (env *TypeEnv) GetByValue(v Value) types.Type { dynamic = types.NewDynamicProperty(env.GetByValue(k.Value), env.GetByValue(v.Value)) }) - if len(static) == 0 && dynamic == nil { - dynamic = types.NewDynamicProperty(types.A, types.A) - } - return types.NewObject(static, dynamic) case *set: @@ -104,9 +95,6 @@ func (env *TypeEnv) GetByValue(v Value) types.Type { x.Foreach(func(elem *Term) { tpe = types.Or(tpe, env.GetByValue(elem.Value)) }) - if tpe == nil { - tpe = types.A - } return types.NewSet(tpe) // Comprehensions. @@ -383,6 +371,8 @@ func (n *typeTreeNode) Insert(path Ref, tpe types.Type, env *TypeEnv) { // with an types.Or, instead of being merged. // If 'a' is an Any containing an Object, and 'b' is an Object (or vice versa); AND both objects have no // static properties, they are merged. +// If either object has neither static nor dynamic properties, it is the empty object type, and the other +// type is returned unchanged. // If 'a' and 'b' are different types, they are joined with an types.Or. func mergeTypes(a, b types.Type) types.Type { if a == nil { @@ -403,25 +393,33 @@ func mergeTypes(a, b types.Type) types.Type { switch a := a.(type) { case *types.Object: + aDynProps := a.DynamicProperties() if bObj, ok := b.(*types.Object); ok && len(a.StaticProperties()) == 0 && len(bObj.StaticProperties()) == 0 { - if len(a.StaticProperties()) > 0 || len(bObj.StaticProperties()) > 0 { - return types.Or(a, bObj) + bDynProps := bObj.DynamicProperties() + + // An object type with neither static nor dynamic properties is the + // empty object, which the other object type already covers. + if aDynProps == nil { + return bObj + } + if bDynProps == nil { + return a } - aDynProps := a.DynamicProperties() - bDynProps := bObj.DynamicProperties() dynProps := types.NewDynamicProperty( types.Or(aDynProps.Key, bDynProps.Key), mergeTypes(aDynProps.Value, bDynProps.Value), ) return types.NewObject(nil, dynProps) - } else if bAny, ok := b.(types.Any); ok && len(a.StaticProperties()) == 0 { + } else if bAny, ok := b.(types.Any); ok && len(a.StaticProperties()) == 0 && aDynProps != nil { // If a is an object type with no static components ... for _, t := range bAny { if tObj, ok := t.(*types.Object); ok && len(tObj.StaticProperties()) == 0 { // ... and b is a types.Any containing an object with no static components, we merge them. - aDynProps := a.DynamicProperties() tDynProps := tObj.DynamicProperties() + if tDynProps == nil { + continue + } tDynProps.Key = types.Or(tDynProps.Key, aDynProps.Key) tDynProps.Value = types.Or(tDynProps.Value, aDynProps.Value) return bAny diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/errors.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/errors.go index 1188cd6e0..a1ea43368 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/errors.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/errors.go @@ -9,6 +9,8 @@ import ( "slices" "strconv" "strings" + + "github.com/open-policy-agent/opa/v1/util" ) // Errors represents a series of errors encountered during parsing, compiling, @@ -16,21 +18,14 @@ import ( type Errors []*Error func (e Errors) Error() string { - if len(e) == 0 { return "no error(s)" } - if len(e) == 1 { - return fmt.Sprintf("1 error occurred: %v", e[0].Error()) + return "1 error occurred: " + e[0].Error() } - s := make([]string, len(e)) - for i, err := range e { - s[i] = err.Error() - } - - return fmt.Sprintf("%d errors occurred:\n%s", len(e), strings.Join(s, "\n")) + return fmt.Sprintf("%d errors occurred:\n%s", len(e), strings.Join(util.Map(e, (*Error).Error), "\n")) } // Sort sorts the error slice by location. If the locations are equal then the @@ -67,10 +62,8 @@ const ( // IsError returns true if err is an AST error with code. func IsError(code string, err error) bool { - if err, ok := err.(*Error); ok { - return err.Code == code - } - return false + e, ok := err.(*Error) + return ok && e.Code == code } // ErrorDetails defines the interface for detailed error messages. @@ -90,7 +83,6 @@ func (e *Error) Error() string { var prefix string if e.Location != nil { - if len(e.Location.File) > 0 { prefix += e.Location.File + ":" + strconv.Itoa(e.Location.Row) } else { diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/index.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/index.go index 3c0c89e72..ea96d6f00 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/index.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/index.go @@ -5,7 +5,9 @@ package ast import ( + "cmp" "maps" + "math/bits" "slices" "strings" "sync" @@ -54,6 +56,25 @@ type ( defaultRule *Rule kind RuleKind onlyGroundRefs bool + // rules holds one entry per rule and else branch the trie carries, groups + // the position of its ruleset among the rules Build was given. Reading the + // ids a lookup reached in increasing order groups them and orders each + // group by priority; see trieTraversalResult and gather. + rules []*Rule + groups []int32 + // required holds, per rule id, the refs it needs defined that are not + // trie levels, as positions in requiredRefs. See refindices.partition. + required map[int32][]int32 + // requiredRefs names those refs, indexed by the positions required holds. + // Numbering them keeps a lookup's memo a lookup by position rather than a + // search: a rule reading a ref of its own is the shape that made the memo + // a linear scan over one entry per rule. + requiredRefs []Ref + // memberships holds, per rule id, the collections gather consults; recorded + // by refindices.recordMembership. + memberships map[int32][]membership + // mayEarlyExit decides whether consulting a collection pays; see gather. + mayEarlyExit bool } ) @@ -81,7 +102,7 @@ func (i *baseDocEqIndex) Build(rules []*Rule) bool { } i.kind = rules[0].Head.RuleKind() - indices := newrefindices(i.isVirtual) + indices := newrefindices(i.isVirtual, newRefTable()) values := make(map[Var]Value) // build indices for each rule. @@ -105,159 +126,427 @@ func (i *baseDocEqIndex) Build(rules []*Rule) bool { } // build trie out of indices. - sorted := indices.Sorted() + levels, unvalued := indices.partition(indices.Sorted()) for idx := range rules { - var prio int WalkRules(rules[idx], func(rule *Rule) bool { if rule.Default { return false } + + // Ids are minted in WalkRules' order, so they ascend with priority + // within a ruleset -- the (insertion, priority) pair a node used to + // carry, in one integer: + // + // f(x) := 1 if x == "a" # group 0, id 0 + // else := 2 if x == "b" # id 1 + // f(x) := 3 if x == "c" # group 1, id 2 + id := int32(len(i.rules)) + i.rules = append(i.rules, rule) + i.groups = append(i.groups, int32(idx)) + + if ms := indices.memberships[rule]; len(ms) > 0 { + if i.memberships == nil { + i.memberships = make(map[int32][]membership, len(rules)) + } + i.memberships[id] = ms + } + // Each set of indices the rule can be reached through gets its own - // path. They share a priority, so a lookup arriving at the rule down + // path. They share an id, so a lookup arriving at the rule down // several of them still reports it once (see trieTraversalResult.Add). - if len(indices.disjunctions[rule]) == 0 { - i.insertPath(sorted, indices.rules[rule], [...]int{idx, prio}, rule) + paths := indices.disjunctions[rule] + if len(paths) == 0 { + i.insertPath(indices.table, levels, indices.rules[rule], id, rule) + i.require(indices.table, id, unvalued, alternatives{indices.rules[rule]}) } else { - for _, path := range indices.paths(rule) { - i.insertPath(sorted, path, [...]int{idx, prio}, rule) + alts := indices.paths(rule) + for _, path := range alts { + i.insertPath(indices.table, levels, path, id, rule) } + i.require(indices.table, id, unvalued, alts) } - prio++ return false }) } + + i.root.compact() + i.mayEarlyExit = mayEarlyExit(i.rules) + return true } -func (i *baseDocEqIndex) insertPath(sorted []Ref, path []*refindex, prio [2]int, rule *Rule) { +// mayEarlyExit reports whether a caller could stop at the first of these rules +// that holds. Build asks it of every rule, which is what gather can know before it +// has candidates; Lookup asks resultMayEarlyExit of the candidates, which is finer. +func mayEarlyExit(rules []*Rule) bool { + var value Value + return agreeOnValue(rules, &value) +} + +// require records the refs rule needs defined, of those partition kept out of the +// trie. Only a ref every path to the rule reads is recorded: one an `or` reads on +// a single alternative does not have to hold for the rule to match, and a lookup +// that dropped the rule over it would lose an answer rather than a shortcut. +func (i *baseDocEqIndex) require(table *refTable, id int32, unvalued []refID, paths alternatives) { + if len(unvalued) == 0 || len(paths) == 0 { + return + } + + var required []int32 + for pos, ref := range unvalued { + reads := func(path []*refindex) bool { + return slices.ContainsFunc(path, func(ri *refindex) bool { return ri.ref == ref }) + } + if !slices.ContainsFunc(paths, func(path []*refindex) bool { return !reads(path) }) { + required = append(required, int32(pos)) + } + } + + if len(required) > 0 { + if i.required == nil { + i.required = make(map[int32][]int32, len(unvalued)) + i.requiredRefs = make([]Ref, len(unvalued)) + for pos, ref := range unvalued { + i.requiredRefs[pos] = table.ref(ref) + } + } + i.required[id] = required + } +} + +func (i *baseDocEqIndex) insertPath(table *refTable, levels []refID, path []*refindex, id int32, rule *Rule) { node := i.root - if len(path) > 0 { - for _, ref := range sorted { - var values []*refindex - for _, ri := range path { - if ri.Ref.Equal(ref) { - values = append(values, ri) - } + // The path stops at the last level it constrains. A rule that constrains + // nothing below has nothing to test there, so walking on would only pad the + // path with an "absent" node per remaining level -- a copy of the whole tail + // that no other rule shares, which is what made a trie of n levels cost n^2 + // nodes to build and to walk. The multiple-scalar case below has always + // attached mid-trie for the same reason. + remaining := len(path) + + // One scratch slice for every level, not one per level: a rule's path crosses + // every level above the last it constrains, most of them constraining nothing. + var values []*refindex + + for _, level := range levels { + if remaining == 0 { + break + } + + values = values[:0] + for _, ri := range path { + if ri.ref == level { + values = append(values, ri) } - if len(values) == 0 { - node = node.Insert(ref, nil, nil) - } else if len(values) == 1 { - node = node.Insert(ref, values[0].Value, values[0].Mapper) - } else { - if slices.ContainsFunc(values, (*refindex).isVar) { - child := node.Insert(ref, anyValue, values[0].Mapper) - for i := range values { - if values[i].Mapper != nil { - node.next.addMapper(values[i].Mapper) - } - } - node = child - } else { - // When a rule has multiple scalar values (e.g., internal.member_2 with a set), - // each value should have its own child node, and the rule is appended to each. - // This creates separate paths for each value so different rules with overlapping - // values don't interfere with each other. - for _, val := range values { - child := node.Insert(ref, val.Value, val.Mapper) - child.append(prio, rule) + } + remaining -= len(values) + + ref := table.ref(level) + + // A var value records "this ref can be anything", which a concrete value + // for the same ref supersedes: everything on one path has to hold, so the + // concrete value is the stronger of the two constraints. A chain of + // assignments, `x := input.a; y := x`, leaves one var entry per local + // behind, and only the first of them is replaced when the concrete value + // is inserted. Keeping the rest would index the rule under anyValue below + // and give up all the discrimination the concrete value buys us. + if len(values) > 1 { + if concrete := slices.DeleteFunc(slices.Clone(values), (*refindex).isVar); len(concrete) > 0 { + values = concrete + } + } + + if len(values) == 0 { + node = node.Insert(ref, nil, nil) + } else if len(values) == 1 { + node = values[0].insertInto(node, ref) + } else { + if slices.ContainsFunc(values, (*refindex).isVar) { + child := node.Insert(ref, anyValue, values[0].Mapper) + for i := range values { + if values[i].Mapper != nil { + node.next.addMapper(values[i].Mapper) } - return } + node = child + } else if remaining == 0 || slices.ContainsFunc(values, (*refindex).isAffix) || + slices.ContainsFunc(values, (*refindex).isComposite) { + // Nothing below to continue a path with, so the rule hangs off + // every alternative -- which rules reaching the same values + // share. Affixes always take this route; see alternation, and + // so does anything a converging level could not be keyed on: + // insertValue sends an object or a set to the "anything" node + // and an array into the array trie, which is where a lookup + // goes looking for them. + for _, val := range oneAffixEnd(values) { + child := val.insertInto(node, ref) + child.append(id, rule) + } + return + } else { + // The alternatives meet again on one node, and the rest of the + // path is built from there rather than under each of them. + node = node.insertAlternatives(ref, values) } } } - // Insert rule into trie with (insertion order, priority order) - // tuple. Retaining the insertion order allows us to return rules - // in the order they were passed to this function. - node.append(prio, rule) + node.append(id, rule) } func (i *baseDocEqIndex) Lookup(resolver ValueResolver) (*IndexResult, error) { tr := ttrPool.Get().(*trieTraversalResult) defer func() { - // Note(anderseknert): `clear`ing the map is not good enough here, as it'd mean - // resetting each of its slice values, costing us new allocations on each append - // in subsequent lookups - for i := range tr.unordered { - tr.unordered[i] = tr.unordered[i][:0] - } - tr.ordering = tr.ordering[:0] - tr.multiple = false - tr.exist = nil - + tr.reset() ttrPool.Put(tr) }() + tr.grow(len(i.rules)) err := i.root.Traverse(resolver, tr) if err != nil { return nil, err } - result := IndexResultPool.Get() result.Kind = i.kind result.Default = i.defaultRule result.OnlyGroundRefs = i.onlyGroundRefs - if result.Rules == nil { - result.Rules = make([]*Rule, 0, len(tr.ordering)) - } else { - result.Rules = result.Rules[:0] - } + result.Rules = result.Rules[:0] clear(result.Else) - for _, pos := range tr.ordering { - if len(tr.unordered[pos]) == 0 { + if err := i.gather(tr, resolver, result); err != nil { + IndexResultPool.Put(result) + return nil, err + } + + // Decided over the candidates rather than over what traversal saw, which is + // finer -- and has to be, now that the refs partition keeps out of the trie no + // longer separate the definitions into nodes of their own: of `p := 1 if + // input.foo`, `p := 2 if input.bar` and `p := 1 if input.baz`, the two agreeing + // on 1 are all a lookup returns when input has no bar. + tr.multiple = !resultMayEarlyExit(result) + + result.EarlyExit = !tr.multiple + + return result, nil +} + +// resultMayEarlyExit reports whether a caller could stop at the first candidate +// that holds, the else branches included: they are values it could stop at too. +func resultMayEarlyExit(result *IndexResult) bool { + var value Value + if !agreeOnValue(result.Rules, &value) { + return false + } + for _, branches := range result.Else { + if !agreeOnValue(branches, &value) { + return false + } + } + return true +} + +// agreeOnValue reports whether rules are complete documents agreeing on value, +// which it carries in so that several sets of rules can be asked as one. +func agreeOnValue(rules []*Rule, value *Value) bool { + for _, rule := range rules { + if rule.Head.DocKind() != CompleteDoc { + return false + } + if rule.Head.Value == nil { continue } + // A value that is not ground is a different one per binding, so there is + // no first answer to stop at. + v := rule.Head.Value.Value + if !v.IsGround() { + return false + } + if *value != nil && !ValueEqual(*value, v) { + return false + } + *value = v + } + return true +} - nodes := util.SortedFunc(tr.unordered[pos], (*ruleNode).prio1Cmp) - root := nodes[0].rule +// resolve answers for a reference, asking the resolver the first time only. +func (c *resolveCache) resolve(resolver ValueResolver, ref Ref) (Value, error) { + if c.keyOK && RefEqual(c.keyRef, ref) { + return c.keyVal, nil + } + v, err := resolver.Resolve(ref) + if err != nil { + return nil, err + } + c.keyRef, c.keyVal, c.keyOK = ref, v, true + return v, nil +} - result.Rules = append(result.Rules, root) - if len(nodes) > 1 { - if result.Else == nil { - result.Else = map[*Rule][]*Rule{} +// container resolves the collection at ref, resolving the container holding it +// once: `data.groups.g1.members` and `data.groups.g2.members` share one resolve. +func (c *resolveCache) container(resolver ValueResolver, ref Ref) (Value, error) { + const shared = 2 // data. + + if len(ref) <= shared { + return resolver.Resolve(ref) + } + + prefix := ref[:shared] + if !c.prefixOK || !RefEqual(c.prefix, prefix) { + v, err := resolver.Resolve(prefix) + if err != nil { + return nil, err + } + c.prefix, c.prefixVal, c.prefixOK = prefix, v, true + } + if c.prefixVal == nil { + return nil, nil + } + + v, err := c.prefixVal.Find(ref[shared:]) + if err != nil { + return nil, nil // undefined, not an error + } + return v, nil +} + +// consultsCollections reports whether excluding a candidate is worth consulting +// its collections for. It is not where the caller stops at the first candidate that +// holds: gather would have to consult all of them to exclude any, which is the work +// evaluation was about to do -- the lookup being what the rule tests. Whether a +// caller stops is the caller's own business, not IndexResult.EarlyExit's, which +// says what the ruleset permits, so the resolver is asked rather than assumed. +func (i *baseDocEqIndex) consultsCollections(resolver ValueResolver) bool { + if !i.mayEarlyExit { + return true + } + every, ok := resolver.(IndexEveryCandidateEvaluated) + return ok && every.IndexEveryCandidateEvaluated() +} + +// inCollections reports whether the rule's collection memberships hold. A +// collection the resolver cannot answer for keeps the rule, as does an array: +// the only thing to ask one is a position, which tells a ruleset's rules apart +// only where their lengths differ. +func (i *baseDocEqIndex) inCollections(resolver ValueResolver, id int32, cache *resolveCache) (bool, error) { + for _, m := range i.memberships[id] { + key, err := cache.resolve(resolver, m.key) + if err != nil { + if IsUnknownValueErr(err) { + continue } + return false, err + } + if key == nil { + return false, nil + } + + coll, err := cache.container(resolver, m.collection) + if err != nil { + if IsUnknownValueErr(err) { + continue + } + return false, err + } + if coll == nil { + return false, nil + } - result.Else[root] = make([]*Rule, len(nodes)-1) - for i := 1; i < len(nodes); i++ { - result.Else[root][i-1] = nodes[i].rule + probe := Term{Value: key} + switch c := coll.(type) { + case Object: + if c.Get(&probe) == nil { + return false, nil + } + // Base data read from JSON holds no set, but a store keeping ast.Value can, + // and so can a `with` statement replacing the collection. + case Set: + if !c.Contains(&probe) { + return false, nil } } } - if !tr.multiple { - // even when the indexer hasn't seen multiple values, the rule itself could be one - // where early exit shouldn't be applied. - var lastValue Value - for i := range result.Rules { - if result.Rules[i].Head.DocKind() != CompleteDoc { - tr.multiple = true - break + return true, nil +} + +// gather reads the rules a traversal reached into result. Ids ascend with +// priority, so a run of them sharing a group is that ruleset's definitions in +// order, the first being the one to evaluate. +// +// The refs partition kept out of the trie are checked here rather than as +// traversal reaches a rule: a bit set for a rule that turns out undefined costs +// nothing to leave set, and asking here means the resolver's error is the return +// value of something rather than a field to be picked up afterwards. A nil +// resolver asks nothing, which is what AllRules wants. +func (i *baseDocEqIndex) gather(tr *trieTraversalResult, resolver ValueResolver, result *IndexResult) error { + var cache resolveCache + var root *Rule + group := int32(-1) + consults := i.consultsCollections(resolver) + + // Words are marked as they are first written to, in traversal order. + slices.Sort(tr.touched) + + found := 0 + for _, w := range tr.touched { + found += bits.OnesCount64(tr.hits[w]) + } + result.Rules = slices.Grow(result.Rules, found) + + // A word holds 64 ids: `w<<6` is the id of its first bit, TrailingZeros64 the + // offset of the lowest set one, and `word &= word - 1` clears it. + for _, w := range tr.touched { + for word := tr.hits[w]; word != 0; word &= word - 1 { + id := w<<6 | int32(bits.TrailingZeros64(word)) + + if resolver != nil && len(i.required) > 0 { + defined, err := i.defined(resolver, id, &cache) + if err != nil { + return err + } + if !defined { + continue + } } - if result.Rules[i].Head.Value != nil { - if lastValue != nil && !ValueEqual(lastValue, result.Rules[i].Head.Value.Value) { - tr.multiple = true - break + + if consults && resolver != nil && len(i.memberships) > 0 { + in, err := i.inCollections(resolver, id, &cache) + if err != nil { + return err } - lastValue = result.Rules[i].Head.Value.Value + if !in { + continue + } + } + + rule := i.rules[id] + + if g := i.groups[id]; g != group { + group, root = g, rule + result.Rules = append(result.Rules, rule) + continue + } + + if result.Else == nil { + result.Else = map[*Rule][]*Rule{} } + result.Else[root] = append(result.Else[root], rule) } } - result.EarlyExit = !tr.multiple - - return result, nil + return nil } func (i *baseDocEqIndex) AllRules(ValueResolver) (*IndexResult, error) { tr := newTrieTraversalResult() + tr.grow(len(i.rules)) // Walk over the rule trie and accumulate _all_ rules rw := &ruleWalker{result: tr} @@ -266,27 +555,10 @@ func (i *baseDocEqIndex) AllRules(ValueResolver) (*IndexResult, error) { result := NewIndexResult(i.kind) result.Default = i.defaultRule result.OnlyGroundRefs = i.onlyGroundRefs - result.Rules = make([]*Rule, 0, len(tr.ordering)) - - for _, pos := range tr.ordering { - if len(tr.unordered[pos]) == 0 { - continue - } - slices.SortFunc(tr.unordered[pos], (*ruleNode).prio1Cmp) - nodes := tr.unordered[pos] - root := nodes[0].rule - result.Rules = append(result.Rules, root) - if len(nodes) > 1 { - if result.Else == nil { - result.Else = map[*Rule][]*Rule{} - } - result.Else[root] = make([]*Rule, len(nodes)-1) - for i := 1; i < len(nodes); i++ { - result.Else[root][i-1] = nodes[i].rule - } - } - } + // Every rule the trie holds, so nothing is asked of the resolver and + // nothing can fail; see gather. + _ = i.gather(tr, nil, result) result.EarlyExit = !tr.multiple @@ -308,10 +580,157 @@ type valueMapper struct { MapValue func(Value) Value } +// IndexEveryCandidateEvaluated may be implemented by a ValueResolver to answer +// whether every candidate a lookup returns goes on to be evaluated, rather than the +// caller stopping at the first that holds. Where it does, excluding a candidate +// saves evaluating it; see baseDocEqIndex.gather. +type IndexEveryCandidateEvaluated interface { + IndexEveryCandidateEvaluated() bool +} + +// membership is "the value at key has to be a key of the collection at +// collection", which a lookup asks the collection rather than the trie. +type membership struct{ key, collection Ref } + +// refID identifies one of the references an index is built on. +type refID int32 + +// refTable numbers the references an index is built on. One table is shared by +// every refindices of a build, the scratch ones an `and`/`or` operand is +// indexed into included, so that an id means the same thing wherever it turns +// up. +type refTable struct { + // refs are the references in id order; ids answers the other direction, and + // is only built past refTableScan entries. + refs []Ref + ids *util.HasherMap[Ref, refID] +} + +// refTableScan is how many references a table holds before it builds a map: +// below that, comparing a ref to the few already here beats hashing it, and most +// rulesets are indexed on a handful. +const refTableScan = 8 + +func newRefTable() *refTable { + return &refTable{} +} + +func (t *refTable) intern(ref Ref) refID { + if t.ids == nil { + for id, other := range t.refs { + if RefEqual(other, ref) { + return refID(id) + } + } + if len(t.refs) < refTableScan { + t.refs = append(t.refs, ref) + return refID(len(t.refs) - 1) + } + t.ids = util.NewHasherMap[Ref, refID](RefEqual) + for id, other := range t.refs { + t.ids.Put(other, refID(id)) + } + } + + if id, ok := t.ids.Get(ref); ok { + return id + } + id := refID(len(t.refs)) + t.refs = append(t.refs, ref) + t.ids.Put(ref, id) + return id +} + +func (t *refTable) ref(id refID) Ref { + return t.refs[id] +} + type refindex struct { - Ref Ref Value Value Mapper *valueMapper + // ref is the reference this constrains, as numbered by the build's table. + ref refID + // Affix says whether Value is a string the value at ref has to start or end + // with, rather than one it has to equal -- what startswith, endswith and + // their strings.any_*_match forms contribute. Several of them for one ref + // are alternatives, as for `in`. + Affix affix +} + +// affix is which end of the value at a reference a refindex constrains, if it +// constrains an end rather than the whole of it. +type affix uint8 + +const ( + affixNone affix = iota + affixPrefix + affixSuffix +) + +// insertInto adds the level this index constrains to the path being built, +// returning the node the rest of the path continues from. +func (i *refindex) insertInto(node *trieNode, ref Ref) *trieNode { + switch i.Affix { + case affixPrefix: + return node.InsertPrefix(ref, i.Value) + case affixSuffix: + return node.InsertSuffix(ref, i.Value) + } + return node.Insert(ref, i.Value, i.Mapper) +} + +// oneAffixEnd keeps the affixes of one end of the value where values constrain +// both, and everything that is not an affix. +// +// A rule hung off the leaves of both the prefix and the suffix trie is admitted +// by either, which is the disjunction of what it wrote where it wrote a +// conjunction: +// +// p if { +// strings.any_prefix_match(input.path, ["/a", "/b"]) +// strings.any_suffix_match(input.path, [".go", ".rego"]) +// } +// +// admits "/c/x.go" on the suffix alone. Testing one end and leaving the other to +// evaluation admits a subset of that -- what one end admits, both admit -- so +// one end is kept. A level cannot test both: the tries hold leaves, and a leaf +// cannot be made to depend on another trie's answer. +// +// Which end is kept is decided by the shortest base string of each, since a set +// admits a value that matches any one of its bases and the shortest of them +// admits the most. Counting them instead would keep ["/"] over [".go", +// ".rego"], and every absolute path matches "/". +func oneAffixEnd(values []*refindex) []*refindex { + prefix, suffix := -1, -1 + for _, val := range values { + s, ok := val.Value.(String) + if !ok { + continue + } + switch val.Affix { + case affixPrefix: + if prefix < 0 || len(s) < prefix { + prefix = len(s) + } + case affixSuffix: + if suffix < 0 || len(s) < suffix { + suffix = len(s) + } + } + } + + if prefix < 0 || suffix < 0 { + return values + } + + drop := affixSuffix + if suffix > prefix { + drop = affixPrefix + } + + return slices.DeleteFunc(slices.Clone(values), func(val *refindex) bool { + return val.Affix == drop + }) } // alternatives are sets of indices, any one of which is enough to reach a rule. @@ -325,9 +744,27 @@ type refindices struct { disjunctions map[*Rule][]alternatives // outer holds the enclosing scope's indices when this is the scratch for an // operand body: resolvable from inside, but not the operand's own. - outer []*refindex - frequency *util.HasherMap[Ref, int] - sorted []Ref + outer []*refindex + table *refTable + // memberships holds the collection memberships of each rule; see membership. + memberships map[*Rule][]membership + // stats holds what Sorted ranks the references by, indexed by ref id. + stats []refStats + sorted []refID +} + +// refStats is what one reference accumulated over a build, which is what decides +// the order of the trie's levels. Dropped once the trie is built. +type refStats struct { + // count is how often the ref took part in indexing a rule. Sorted passes + // over the ids that never counted: a scratch interns the refs of an operand + // that may turn out unindexable, and then nothing records them. + count int32 + // alternated is whether some rule reaches the ref by more than one value, + // and what that costs insertPath. An `or` is not recorded: its alternatives + // are separate paths, and only meet a second value for one ref once paths() + // combines them, after Sorted has run. + alternated alternation } // maxIndexPaths caps the ways a single rule may be reached: `or` expressions @@ -335,17 +772,43 @@ type refindices struct { // nodes cost more than evaluating the rule. const maxIndexPaths = 32 -func newrefindices(isVirtual func(Ref) bool) *refindices { +func newrefindices(isVirtual func(Ref) bool, table *refTable) *refindices { return &refindices{ - isVirtual: isVirtual, - rules: map[*Rule][]*refindex{}, - frequency: util.NewHasherMap[Ref, int](RefEqual), + isVirtual: isVirtual, + table: table, + rules: map[*Rule][]*refindex{}, + memberships: map[*Rule][]membership{}, + } +} + +// growTo extends s so that it can be indexed by every id below n, leaving what +// it already holds in place. +func growTo[T any](s []T, n int) []T { + if len(s) >= n { + return s } + return append(s, make([]T, n-len(s))...) +} + +func valueIsVar(v Value) bool { + _, ok := v.(Var) + return ok } func (i *refindex) isVar() bool { - _, isVar := i.Value.(Var) - return isVar + return valueIsVar(i.Value) +} + +func (i *refindex) isAffix() bool { + return i.Affix != affixNone +} + +// isComposite reports whether a lookup could not find this value among a +// level's alternatives, which are keyed on the value as it stands. insertValue +// sends an object or a set to the "anything" node and an array into the array +// trie, which is where a lookup goes looking for them instead. +func (i *refindex) isComposite() bool { + return !IsScalar(i.Value) } // Update attempts to update the refindices for the given expression in the @@ -380,8 +843,13 @@ func (i *refindices) Update(rule *Rule, expr *Expr, values map[Var]Value) { // check for type "Var" here. But since it's impossible to call a // function with a undefined argument, there's no point to recording // "needs to be anything" for function args - if _, ok := ts.Value.(Ref); ok { // "naked ref" - i.updateEq(rule, ts.Value, anyValue, nil) + if ref, ok := ts.Value.(Ref); ok { // "naked ref" + // `data.groups.g1.members[input.subject]` constrains its last + // element to the keys of the collection at the ground prefix, + // which is more than the "is defined" updateEq can record. + if !i.updateCollectionKey(rule, ref) { + i.updateEq(rule, ts.Value, anyValue, nil) + } } } } @@ -408,6 +876,20 @@ func (i *refindices) Update(rule *Rule, expr *Expr, values map[Var]Value) { case op.Equal(Interned.Refs.Member) && len(expr.Operands()) == 2: // NOTE(sr): Again, 3 operands means captured output (like above). i.updateMember(rule, expr, values) + + case op.Equal(Interned.Refs.StartsWith) && len(expr.Operands()) == 2: + // As with equal() above: a third operand captures the result, and a + // rule producing `false` still has to be evaluated. + i.updateAffix(rule, expr, values, affixPrefix) + + case op.Equal(Interned.Refs.AnyPrefixMatch) && len(expr.Operands()) == 2: + i.updateAnyAffixMatch(rule, expr, values, affixPrefix) + + case op.Equal(Interned.Refs.EndsWith) && len(expr.Operands()) == 2: + i.updateAffix(rule, expr, values, affixSuffix) + + case op.Equal(Interned.Refs.AnySuffixMatch) && len(expr.Operands()) == 2: + i.updateAnyAffixMatch(rule, expr, values, affixSuffix) } } @@ -440,7 +922,7 @@ func (i *refindices) require(rule *Rule, alts alternatives) { default: for _, alt := range alts { for _, ri := range alt { - i.count(ri.Ref) + i.count(ri.ref) } } if i.disjunctions == nil { @@ -473,7 +955,7 @@ func (i *refindices) updateLogicalOr(rule *Rule, or *LogicalOr, values map[Var]V // all means nothing about it could be indexed. It is indexed into a scratch, so // that what it requires reaches the rule only through require(). func (i *refindices) operandAlternatives(rule *Rule, body Body, values map[Var]Value) alternatives { - scratch := newrefindices(i.isVirtual) + scratch := newrefindices(i.isVirtual, i.table) scratch.outer = append(slices.Clone(i.rules[rule]), i.outer...) scratch.updateOperand(rule, body, values) @@ -488,7 +970,7 @@ func (i *refindices) operandAlternatives(rule *Rule, body Body, values map[Var]V // resolvable from the outside (see resolveVarToRef); that the ref // has to be defined still holds. if ri.isVar() { - alt[pos] = &refindex{Ref: ri.Ref, Value: anyValue, Mapper: ri.Mapper} + alt[pos] = &refindex{ref: ri.ref, Value: anyValue, Mapper: ri.Mapper} } } } @@ -543,37 +1025,98 @@ func (i *refindices) isValidIndexRef(ref Ref) bool { !i.isVirtual(ref) } -// Sorted returns a sorted list of references that the indices were built from. -// References that appear more frequently in the indexed rules are ordered -// before less frequently appearing references. -func (i *refindices) Sorted() []Ref { - if i.sorted == nil { - i.sorted = util.SortedFunc(i.frequency.Keys(), func(a, b Ref) int { - countsA, _ := i.frequency.Get(a) - countsB, _ := i.frequency.Get(b) - if countsA < countsB { // descending, we want highest-freq first - return 1 - } else if countsA > countsB { - return -1 - } - return a[0].Loc().Compare(b[0].Loc()) - }) +// Sorted returns the references the indices were built from, ordered so that +// the ones appearing in more of the indexed rules come first. +func (i *refindices) Sorted() []refID { + if i.sorted != nil { + return i.sorted } + + for id, stats := range i.stats { + if stats.count > 0 { + i.sorted = append(i.sorted, refID(id)) + } + } + + slices.SortFunc(i.sorted, func(a, b refID) int { + // A ref reached by several values is worth less as an early level, + // and one that ends the rule's path less again, however often + // either was recorded -- so both outrank frequency. + if c := cmp.Compare(i.stats[a].alternated, i.stats[b].alternated); c != 0 { + return c + } + if c := cmp.Compare(i.stats[b].count, i.stats[a].count); c != 0 { // descending + return c + } + if c := i.table.ref(a)[0].Loc().Compare(i.table.ref(b)[0].Loc()); c != 0 { + return c + } + // Refs built rather than parsed -- a function's args[n] -- share a + // location, so fall back on the order they were first seen in. + return cmp.Compare(a, b) + }) + return i.sorted } -func (i *refindices) Value(rule *Rule, ref Ref) Value { - if index := i.index(rule, ref); index != nil { - return index.Value +// partition splits sorted into the refs that become trie levels and the refs that +// do not, which is those no rule constrains to a value. +// +// A ref every rule records only as "holds something" -- which is what +// RewriteDynamicTerms leaves behind when it hoists a term into a local, +// `__local1__ = data.groups.g0.members` -- gives the trie a level whose only +// children are "anything" and "absent". It cannot narrow a lookup by value. What +// it can do is exclude the rules that read the ref when the ref is absent, since +// traversal stops at a level that resolves to nothing, and for a naked reference +// -- `allow if input.x` -- that is the whole of the indexing. +// +// Keeping it as a level is an expensive way to ask that question. Both children +// carry their own copy of the levels below, so the levels multiply out, and each +// lookup resolves a ref per copy. One such level per rule makes traversal +// quadratic: +// +// allow if { input.subject in data.groups.g0.members; input.resource.foo == "A" } +// allow if { input.subject in data.groups.g1.members; input.resource.foo == "A" } +// ... +// +// 500 of those resolve 125k refs on every lookup -- N(N+1)/2 -- to exclude nothing, +// because input.resource.foo is what discriminates. The index costs more than it +// saves there: the same policy evaluates 6.5x faster with indexing disabled, and +// 8.8x at a thousand rules. +// +// So the question moves out of the trie: Lookup checks these refs against the +// candidates traversal produced, which asks it once per surviving rule instead of +// once per copy of the level. The candidates are the same either way. +func (i *refindices) partition(sorted []refID) (levels, unvalued []refID) { + // An `or` records its operands' indices on disjunctions rather than through + // insert, so collect from both rather than counting as they arrive. + valued := make([]bool, len(i.stats)) + note := func(path []*refindex) { + for _, ri := range path { + if !ri.isVar() { + valued[ri.ref] = true + } + } + } + for _, path := range i.rules { + note(path) + } + for _, alts := range i.disjunctions { + for _, alt := range alts { + for _, path := range alt { + note(path) + } + } } - return nil -} -func (i *refindices) Mapper(rule *Rule, ref Ref) *valueMapper { - if index := i.index(rule, ref); index != nil { - return index.Mapper + for _, ref := range sorted { + if valued[ref] { + levels = append(levels, ref) + } else { + unvalued = append(unvalued, ref) + } } - return nil + return levels, unvalued } func (i *refindices) updateEq(rule *Rule, a, b Value, constants map[Var]Value) { @@ -594,6 +1137,11 @@ func (i *refindices) tryIndexWildcardRef(rule *Rule, a, b Value, constants map[V return false } + ref = i.resolveRefHead(rule, rule.Head.Args, ref) + if ref == nil { + return false + } + groundPrefix := ref.GroundPrefix() if len(groundPrefix) != len(ref)-1 || !i.isValidIndexRef(groundPrefix) { return false @@ -614,7 +1162,7 @@ func (i *refindices) tryIndexWildcardRef(rule *Rule, a, b Value, constants map[V return false } - i.insert(rule, &refindex{Ref: groundPrefix, Value: resolvedValue}) + i.insert(rule, &refindex{ref: i.table.intern(groundPrefix), Value: resolvedValue}) return true } @@ -632,9 +1180,9 @@ func (i *refindices) updateGlobMatch(rule *Rule, expr *Expr) { // variable earlier in the query OR a function argument variable. match := expr.Operand(2) if v, ok := match.Value.(Var); ok { - if ref := resolveVarToRef(i.resolvable(rule), args, v); ref != nil { + if ref := i.resolveVarToRef(i.resolvable(rule), args, v); ref != nil { i.insert(rule, &refindex{ - Ref: ref, + ref: i.table.intern(ref), Value: arr.Value, Mapper: &valueMapper{ Key: delim, @@ -655,7 +1203,7 @@ func (i *refindices) updateMember(rule *Rule, expr *Expr, constants map[Var]Valu lhs, rhs := expr.Operand(0), expr.Operand(1) lvar, ok := lhs.Value.(Var) if ok { - lref := resolveVarToRef(i.resolvable(rule), rule.Head.Args, lvar) + lref := i.resolveVarToRef(i.resolvable(rule), rule.Head.Args, lvar) if lref != nil { i.updateMemberRefInValue(rule, lref, rhs, constants) // `ref in value` return @@ -681,7 +1229,7 @@ func (i *refindices) updateMemberValueInRef(rule *Rule, args []*Term, lval Value return } - i.insert(rule, &refindex{Ref: rref, Value: lval}) + i.insert(rule, &refindex{ref: i.table.intern(rref), Value: lval}) } func (i *refindices) updateMemberRefInValue(rule *Rule, ref Ref, rhs *Term, constants map[Var]Value) { @@ -689,33 +1237,184 @@ func (i *refindices) updateMemberRefInValue(rule *Rule, ref Ref, rhs *Term, cons if rvar, ok := rval.(Var); ok { // rhs is var, try to resolve if resolved, ok := constants[rvar]; ok { rval = resolved + } else if cref := i.resolveVarToRef(i.resolvable(rule), rule.Head.Args, rvar); cref != nil { + // The collection is behind a reference the compiler hoisted into a + // local: `__local0__ = data.groups.g1.members` ahead of the call. + rval = cref } } - addRef := func(t *Term) error { - i.insert(rule, &refindex{Ref: ref, Value: t.Value}) - return nil + var ( + forEach func(func(*Term)) + n int + ) + + // `input.subject in data.groups.g1.members` asks for the collection's + // *values*, which base data -- an object or an array, never a set -- answers + // only by being walked. updateCollectionKey has the question it does answer. + if _, ok := rval.(Ref); ok { + return } switch rcol := rval.(type) { case *Array: - _ = rcol.Iter(addRef) + forEach, n = rcol.Foreach, rcol.Len() case Set: - _ = rcol.Iter(addRef) + forEach, n = rcol.Foreach, rcol.Len() case Object: - _ = rcol.Iter(func(_, v *Term) error { - return addRef(v) - }) + n = rcol.Len() + // Function literal does not escape / allocate + if o, ok := rcol.(*object); ok { + forEach = func(f func(*Term)) { + for _, node := range o.sortedKeys() { + f(node.value) + } + } + // Function literal escapes + } else { + forEach = func(f func(*Term)) { + rcol.Foreach(func(_, v *Term) { f(v) }) + } + } + default: + return + } + + members := make([]Value, 0, n) + forEach(func(t *Term) { + members = append(members, t.Value) + }) + + i.insertMembers(rule, ref, members) +} + +// insertMembers records the members of an `in` collection, each a value the +// rule may reach ref by, hoisting insert's scan out of the loop. insertAffixes +// is the same for base strings; the two dedup on different key types. +func (i *refindices) insertMembers(rule *Rule, ref Ref, members []Value) { + id := i.table.intern(ref) + + if len(members) < 2 { + for _, member := range members { + i.insert(rule, &refindex{ref: id, Value: member}) + } + return + } + + // Unlike a prefix, a concrete member takes the place of a "reference is + // anything" entry (see insert), so the first one goes the ordinary way -- + // the rule's list is short at that point, so the scan it costs is cheap. + i.insert(rule, &refindex{ref: id, Value: members[0]}) + + // insert is the only one that may put a value somewhere other than the end + // of the list, which is what a var needs, so those go in through it and are + // left out of the block below. A collection holding one is rare, and paying + // a copy for it keeps the common case a single pass. + rest := members[1:] + if slices.ContainsFunc(rest, valueIsVar) { + for _, member := range rest { + if valueIsVar(member) { + i.insert(rule, &refindex{ref: id, Value: member}) + } + } + rest = slices.DeleteFunc(slices.Clone(rest), valueIsVar) + } + + concrete := 0 + seen := util.NewHasherMap[Value, struct{}](ValueEqual) + + for _, other := range i.rules[rule] { + if other.ref != id { + continue + } + if !other.isVar() { + concrete++ + } + if other.Affix == affixNone { + seen.Put(other.Value, struct{}{}) + } + } + + // One refindex per member, laid down in a single block rather than + // allocated one at a time, as in insertAffixes. Duplicates leave slack at + // the end of the block, which the reslice drops. + pos := len(i.rules[rule]) + indices := util.GrowPtrSlice(i.rules[rule], len(rest)) + + for _, member := range rest { + if _, ok := seen.Get(member); ok { + continue + } + seen.Put(member, struct{}{}) + concrete++ + + *indices[pos] = refindex{ref: id, Value: member} + pos++ + } + i.rules[rule] = indices[:pos] + + i.countN(id, len(rest)) + + if concrete > 1 { + i.alternate(id, alternationConverging) } } +// updateCollectionKey records `[]` -- a reference whose ground +// prefix names a collection in base data and whose last element is the value +// being looked up in it. Reports whether it did. +func (i *refindices) updateCollectionKey(rule *Rule, ref Ref) bool { + if len(ref) < 2 || !ref[0].Equal(DefaultRootDocument) { + return false + } + + prefix := ref[:len(ref)-1] + if !prefix.IsGround() || i.isVirtual(prefix) { + return false + } + + keyRef := i.keyRefOf(rule, ref[len(ref)-1]) + if keyRef == nil || i.isVirtual(keyRef) { + return false + } + + i.recordMembership(rule, keyRef, prefix) + return true +} + +// keyRefOf resolves the term a collection is keyed by to the reference it stands +// for: `input.subject` directly, or the local a rule bound it to. +func (i *refindices) keyRefOf(rule *Rule, term *Term) Ref { + switch v := term.Value.(type) { + case Ref: + if v.IsGround() && !i.isVirtual(v) { + return v + } + case Var: + return i.resolveVarToRef(i.resolvable(rule), rule.Head.Args, v) + } + return nil +} + +// recordMembership notes that rule only matches when the value at key is a key +// of the collection at collection, and that both take part in indexing it. +func (i *refindices) recordMembership(rule *Rule, key, collection Ref) { + for _, m := range i.memberships[rule] { + if RefEqual(m.key, key) && RefEqual(m.collection, collection) { + return + } + } + i.memberships[rule] = append(i.memberships[rule], membership{key: key, collection: collection}) + i.count(i.table.intern(key)) +} + func (i *refindices) resolveAndValidateRef(rule *Rule, args []*Term, term *Term) Ref { var ref Ref switch v := term.Value.(type) { case Ref: ref = v case Var: - ref = resolveVarToRef(i.resolvable(rule), args, v) + ref = i.resolveVarToRef(i.resolvable(rule), args, v) default: return nil } @@ -727,6 +1426,28 @@ func (i *refindices) resolveAndValidateRef(rule *Rule, args []*Term, term *Term) return ref } +// resolveRefHead resolves a ref rooted at a local variable -- what +// +// x := input +// x.foo == "bar" +// +// gets compiled to -- into the ref that local aliases, splicing the remainder of +// the ref onto it: `input.foo`. Refs that are already rooted at a root document +// are returned unchanged; a head that does not resolve yields nil. +func (i *refindices) resolveRefHead(rule *Rule, args []*Term, ref Ref) Ref { + head, isVar := ref[0].Value.(Var) + if !isVar || RootDocumentNames.Contains(ref[0]) { + return ref + } + + resolved := i.resolveVarToRef(i.resolvable(rule), args, head) + if resolved == nil { + return nil + } + + return resolved.Concat(ref[1:]) +} + // resolveVarToRef checks the previously prepared `*refindex` slice for // occurrences of the var `v`. Since we store `ref = var` expressions for // "any" lookups (i.e. "return the rule if ref is anything"), we can @@ -748,10 +1469,10 @@ func (i *refindices) resolveAndValidateRef(rule *Rule, args []*Term, term *Term) // // // as we're not capturing `var = var` expressions in the index. -func resolveVarToRef(ri []*refindex, args []*Term, v Var) Ref { +func (i *refindices) resolveVarToRef(ri []*refindex, args []*Term, v Var) Ref { for _, other := range ri { if v.Equal(other.Value) { - return other.Ref + return i.table.ref(other.ref) } } for j, arg := range args { @@ -774,50 +1495,187 @@ func (i *refindices) resolvable(rule *Rule) []*refindex { // count records that ref took part in indexing a rule, which is what orders the // trie levels (see Sorted). -func (i *refindices) count(ref Ref) { - count, _ := i.frequency.Get(ref) - i.frequency.Put(ref, count+1) +func (i *refindices) count(ref refID) { + i.countN(ref, 1) } -func (i *refindices) insert(rule *Rule, index *refindex) { - i.count(index.Ref) +func (i *refindices) countN(ref refID, n int) { + i.stat(ref).count += int32(n) +} + +// stat returns the reference's statistics, making room for them if this is the +// first thing recorded about it. +func (i *refindices) stat(ref refID) *refStats { + i.stats = growTo(i.stats, int(ref)+1) + return &i.stats[ref] +} + +// alternation is what a ref reached by several values costs the rest of the +// rule's path, and what Sorted ranks such refs by. +type alternation uint8 + +const ( + // alternationNone: no rule reaches the ref by more than one value. + alternationNone alternation = iota + + // alternationConverging: the alternatives meet again on one node, so the + // path continues from there. Still ranked after the plain refs, since the + // rule gets a node of its own and stops sharing what is below. + alternationConverging - _, indexValueIsVar := index.Value.(Var) + // alternationTerminal: the alternatives cannot meet again, so the rule + // hangs off each and whatever it constrains below goes unindexed. Affixes + // are these -- a prefix trie cannot point several leaves at one node. + alternationTerminal +) + +// alternate records that a rule reaches ref by more than one value, and what +// that costs. The worse kind recorded for a ref wins. Only the values +// surviving insertPath's var-stripping count. +func (i *refindices) alternate(ref refID, kind alternation) { + if kind == alternationNone { + return + } + + stats := i.stat(ref) + stats.alternated = max(stats.alternated, kind) +} + +func (i *refindices) insert(rule *Rule, index *refindex) { + indexValueIsVar := index.isVar() + seen := false for pos, other := range i.rules[rule] { - if other.Ref.Equal(index.Ref) { - if ValueEqual(other.Value, index.Value) { + if other.ref == index.ref { + seen = true + if other.Affix == index.Affix && ValueEqual(other.Value, index.Value) { return } - _, otherValueIsVar := other.Value.(Var) - if !indexValueIsVar && otherValueIsVar { + otherValueIsVar := other.isVar() + // An affix constraint does not take the place of the "ref is + // anything" entry the way a concrete value does: that entry is what + // lets a later expression resolve the same local back to this ref + // (see resolveVarToRef), and insertPath drops it anyway once the + // ref has a concrete value on the path. + if !indexValueIsVar && index.Affix == affixNone && otherValueIsVar { i.rules[rule][pos] = index return } + if !indexValueIsVar && !otherValueIsVar { + // insertPath cannot converge a level that any affix reaches, + // so one on either side makes this pair a terminal one. + kind := alternationConverging + if index.Affix != affixNone || other.Affix != affixNone { + kind = alternationTerminal + } + i.alternate(index.ref, kind) + } } } - i.rules[rule] = append(i.rules[rule], index) -} - -func (i *refindices) index(rule *Rule, ref Ref) *refindex { - for _, index := range i.rules[rule] { - if index.Ref.Equal(ref) { - return index - } + if !seen { + i.count(index.ref) } - return nil + i.rules[rule] = append(i.rules[rule], index) } type trieWalker interface { Do(any) trieWalker } +// trieTraversalResult is what a walk of the trie -- a lookup, or the whole of it +// for AllRules -- collects. +// +// The rules reached are a bitset over the index's rule ids, so reaching one down +// several paths costs nothing to notice: the second arrival writes a bit that is +// already set. Reading it back in id order is reading it grouped and in priority +// order, ids having been handed out that way, so there is nothing left to sort. type trieTraversalResult struct { - unordered map[int][]*ruleNode - ordering []int - exist *Term - multiple bool + hits []uint64 + // touched holds the words of hits that were written to, so that clearing + // costs what a lookup found rather than what the index holds. + touched []int32 + exist *Term + multiple bool +} + +// defined reports whether every ref the rule needs resolves to something. A ref +// that is unknown rather than absent cannot exclude it, the same way traversal +// keeps everything below a level it cannot resolve (see traverseUnknown). +func (i *baseDocEqIndex) defined(resolver ValueResolver, id int32, cache *resolveCache) (bool, error) { + for _, pos := range i.required[id] { + defined, err := cache.defined(resolver, i.requiredRefs, pos) + if err != nil { + return false, err + } + if !defined { + return false, nil + } + } + + return true, nil +} + +// resolveCache memoizes, for the length of one lookup, what the resolver answered. +// The refs kept out of the trie are asked for once each however many rules read +// them, and the collections of a ruleset sit under a shared prefix. +// +// Where topdown's baseCache holds what the store gave, making a resolve cheap, this +// skips making the call. +type resolveCache struct { + // required is one entry per ref in the index's requiredRefs, so a memo is + // read at a position rather than searched for. It used to be one entry per + // ref asked about, found by scanning: refs no rule constrains to a value are + // usually the same few, but a rule reading one of its own gives a lookup as + // many distinct ones as there are candidates, and the scan then costs a + // comparison per pair of them. + required []resolved + // keyRef and prefix are the last key and the last collection container asked + // for: a ruleset's rules test the same field, and their collections sit side + // by side under one prefix. + keyRef Ref + keyVal Value + keyOK bool + prefix Ref + prefixVal Value + prefixOK bool +} + +// resolved is a memo entry: unasked until a lookup asks, and then one of the two +// answers. Zero has to mean unasked, so that the buffer needs no initialising +// beyond being allocated. +type resolved uint8 + +const ( + unasked resolved = iota + isDefined + isAbsent +) + +func (c *resolveCache) defined(resolver ValueResolver, refs []Ref, pos int32) (bool, error) { + if c.required == nil { + c.required = make([]resolved, len(refs)) + } + if r := c.required[pos]; r != unasked { + return r == isDefined, nil + } + + v, err := resolver.Resolve(refs[pos]) + if err != nil { + if !IsUnknownValueErr(err) { + return false, err + } + // Unknown rather than absent cannot exclude the rule, the same way + // traversal keeps everything below a level it cannot resolve. + v = Boolean(true) + } + + if v != nil { + c.required[pos] = isDefined + return true, nil + } + c.required[pos] = isAbsent + return false, nil } var ttrPool = &sync.Pool{ @@ -827,20 +1685,34 @@ var ttrPool = &sync.Pool{ } func newTrieTraversalResult() *trieTraversalResult { - return &trieTraversalResult{ - unordered: make(map[int][]*ruleNode, 16), + return &trieTraversalResult{} +} + +// grow makes room for an index holding n rules. The pool never sizes back down, +// which is a byte per eight rules against an index costing hundreds per rule. +func (tr *trieTraversalResult) grow(n int) { + tr.hits = growTo(tr.hits, (n+63)/64) +} + +func (tr *trieTraversalResult) reset() { + for _, w := range tr.touched { + tr.hits[w] = 0 } + tr.touched = tr.touched[:0] + tr.multiple = false + tr.exist = nil } func (tr *trieTraversalResult) Add(t *trieNode) { - for _, node := range t.rules { - root := node.prio[0] - if nodes, ok := tr.unordered[root]; !ok || len(nodes) == 0 { - tr.ordering = append(tr.ordering, root) - tr.unordered[root] = append(nodes, node) - } else if !slices.ContainsFunc(nodes, node.prioEqual) { - tr.unordered[root] = append(nodes, node) + for _, id := range t.rules { + word, bit := id>>6, uint64(1)<<(uint(id)&63) + if tr.hits[word]&bit != 0 { + continue + } + if tr.hits[word] == 0 { + tr.touched = append(tr.touched, word) } + tr.hits[word] |= bit } if t.multiple { tr.multiple = true @@ -856,20 +1728,17 @@ func (tr *trieTraversalResult) Add(t *trieNode) { } type trieNode struct { - ref Ref - mappers []*valueMapper - next *trieNode - any *trieNode - undefined *trieNode - scalars *util.HasherMap[Value, *trieNode] - array *trieNode - rules []*ruleNode - value *Term - multiple bool + // next is the level below this node, nil where the paths under it end. + next *levelDetail + // rules are the ids of the rules whose path ends here, see + // baseDocEqIndex.rules. + rules []int32 + value *Term + multiple bool } -func (node *trieNode) append(prio [2]int, rule *Rule) { - node.rules = append(node.rules, &ruleNode{prio, rule}) +func (node *trieNode) append(id int32, rule *Rule) { + node.rules = append(node.rules, id) if node.value != nil && rule.Head.Value != nil && !node.value.Equal(rule.Head.Value) { node.multiple = true @@ -880,21 +1749,101 @@ func (node *trieNode) append(prio [2]int, rule *Rule) { } } -type ruleNode struct { - prio [2]int - rule *Rule +// levelDetail is everything a trieNode has by virtue of being a *level* -- the +// reference it resolves, the children it dispatches the resolved value to, and +// the constraints that are not exact values. The suffix trie holds its base +// strings reversed, so that requiring one at the end of a value is requiring it +// at the start of the value reversed and the same trie answers both (see +// traverseSuffix). +// +// It is held behind one pointer because a trieNode is allocated per indexed +// value and almost none of them are levels: half a million prefixes make one +// level and half a million nodes that only carry rules. Measured over such an +// index, every field here is set on 0 or 1 of the 500002 nodes. +// +// Where the boundaries fall decides how much that is worth. Inline, these +// fields put trieNode in Go's 160-byte size class; out of line it is 56 bytes, +// which rounds to 64. Moving them out a few at a time buys nothing -- 136 and +// 112 bytes both round up to a class the struct already occupied. +// +// The same reasoning applies once more within levelDetail: alternatives is set +// on the few levels some rule reaches by more than one value, so it costs 8 +// bytes here rather than the 32 its two fields would inline. +type levelDetail struct { + ref Ref + any *trieNode + undefined *trieNode + array *arrayTrie + scalars *util.HasherMap[Value, *trieNode] + mappers []*valueMapper + prefixes *prefixTrie + suffixes *prefixTrie + alternatives *alternativeChildren +} + +// alternativeChildren are the nodes that rules reaching a level by several +// values continue from. The two fields hold the same nodes for two different +// jobs, and neither does the other's: +// +// members answers "which nodes does this value reach", which is what a lookup +// asks. A node is in it under every one of the values that reaches it, so a +// rule with a thousand-member collection puts its one node under a thousand +// keys, and several rules sharing a value put several nodes under that one. +// +// converged answers "which nodes are below this level", which is what the +// walks over the whole trie ask -- traverseUnknown, Do and compact. Reading +// that off members would visit a node once per value that reaches it: correct, +// since trieTraversalResult.Add folds a rule reached twice into one, but a +// thousand times the work for the collection above. So the nodes are listed +// once each here as they are created. +type alternativeChildren struct { + members *util.HasherMap[Value, []*trieNode] + converged []*trieNode +} + +func newTrieNodeImpl() *trieNode { + return &trieNode{} +} + +// level returns the level below node, creating it if this is the first rule to +// be discriminated there. +func (node *trieNode) level() *levelDetail { + node.next = util.Or(node.next, newLevelDetail) + return node.next +} + +func (d *levelDetail) converged() []*trieNode { + if d != nil && d.alternatives != nil { + return d.alternatives.converged + } + return nil +} + +// affixTrie returns the trie for one end of the value, creating it and the +// detail that holds it on first use. +func (d *levelDetail) affixTrie(a affix) *prefixTrie { + detail := d + + switch a { + case affixSuffix: + detail.suffixes = util.Or(detail.suffixes, newPrefixTrie) + return detail.suffixes + default: + detail.prefixes = util.Or(detail.prefixes, newPrefixTrie) + return detail.prefixes + } } -func (a *ruleNode) prio1Cmp(b *ruleNode) int { - return a.prio[1] - b.prio[1] +func newLevelDetail() *levelDetail { + return &levelDetail{} } -func (a *ruleNode) prioEqual(b *ruleNode) bool { - return a.prio == b.prio +func newScalarChildren() *util.HasherMap[Value, *trieNode] { + return util.NewHasherMap[Value, *trieNode](ValueEqual) } -func newTrieNodeImpl() *trieNode { - return &trieNode{} +func newPrefixTrie() *prefixTrie { + return &prefixTrie{} } func (node *trieNode) Do(walker trieWalker) { @@ -906,29 +1855,106 @@ func (node *trieNode) Do(walker trieWalker) { return } - node.any.Do(next) - node.undefined.Do(next) + node.next.do(next) +} - node.scalars.Iter(func(_ Value, child *trieNode) bool { - child.Do(next) +func (d *levelDetail) do(walker trieWalker) { + if d == nil { + return + } + + d.any.Do(walker) + d.undefined.Do(walker) + + d.scalars.Iter(func(_ Value, child *trieNode) bool { + child.Do(walker) return false }) - node.array.Do(next) - node.next.Do(next) + for _, child := range d.converged() { + child.Do(walker) + } + + d.prefixes.do(walker) + d.suffixes.do(walker) + d.array.do(walker) } -func (node *trieNode) Insert(ref Ref, value Value, mapper *valueMapper) *trieNode { - if node.next == nil { - node.next = newTrieNodeImpl() - node.next.ref = ref +// compact walks the trie once the index is built and releases what its slices +// grew but do not use. +func (node *trieNode) compact() { + if node == nil { + return + } + + node.next.compact() +} + +func (d *levelDetail) compact() { + if d == nil { + return + } + + d.prefixes.compact() + d.suffixes.compact() + + d.any.compact() + d.undefined.compact() + d.array.compact() + + for _, child := range d.converged() { + child.compact() + } + + d.scalars.Iter(func(_ Value, child *trieNode) bool { + child.compact() + return false + }) + + if d.alternatives != nil { + d.alternatives.converged = slices.Clip(d.alternatives.converged) } +} + +// insertAlternatives adds a level a rule reaches by any one of several values, +// and returns the one node the rest of its path continues from. Every value +// keys to that node, so what the rule constrains below is built once instead of +// repeated under each alternative. +func (node *trieNode) insertAlternatives(ref Ref, values []*refindex) *trieNode { + level := node.level() + level.ref = ref + level.alternatives = util.Or(level.alternatives, newAlternativeChildren) + alt := level.alternatives + + converge := newTrieNodeImpl() + alt.converged = append(alt.converged, converge) + + for _, val := range values { + if val.Mapper != nil { + level.addMapper(val.Mapper) + } + nodes, _ := alt.members.Get(val.Value) + alt.members.Put(val.Value, append(nodes, converge)) + } + + return converge +} + +func newAlternativeChildren() *alternativeChildren { + return &alternativeChildren{ + members: util.NewHasherMap[Value, []*trieNode](ValueEqual), + } +} + +func (node *trieNode) Insert(ref Ref, value Value, mapper *valueMapper) *trieNode { + level := node.level() + level.ref = ref if mapper != nil { - node.next.addMapper(mapper) + level.addMapper(mapper) } - return node.next.insertValue(value) + return level.insertValue(value) } func (node *trieNode) Traverse(resolver ValueResolver, tr *trieTraversalResult) error { @@ -941,36 +1967,37 @@ func (node *trieNode) Traverse(resolver ValueResolver, tr *trieTraversalResult) return node.next.traverse(resolver, tr) } -func (node *trieNode) addMapper(mapper *valueMapper) { - for i := range node.mappers { - if node.mappers[i].Key == mapper.Key { +func (d *levelDetail) addMapper(mapper *valueMapper) { + detail := d + for i := range detail.mappers { + if detail.mappers[i].Key == mapper.Key { return } } - node.mappers = append(node.mappers, mapper) + detail.mappers = append(detail.mappers, mapper) } -func (node *trieNode) insertValue(value Value) *trieNode { +func (d *levelDetail) insertValue(value Value) *trieNode { + detail := d + switch value := value.(type) { case nil: - node.undefined = util.Or(node.undefined, newTrieNodeImpl) - return node.undefined + detail.undefined = util.Or(detail.undefined, newTrieNodeImpl) + return detail.undefined case Var: - node.any = util.Or(node.any, newTrieNodeImpl) - return node.any + detail.any = util.Or(detail.any, newTrieNodeImpl) + return detail.any case Null, Boolean, Number, String: - child, ok := node.scalars.Get(value) + child, ok := detail.scalars.Get(value) if !ok { child = newTrieNodeImpl() - if node.scalars == nil { - node.scalars = util.NewHasherMap[Value, *trieNode](ValueEqual) - } - node.scalars.Put(value, child) + detail.scalars = util.Or(detail.scalars, newScalarChildren) + detail.scalars.Put(value, child) } return child case *Array: - node.array = util.Or(node.array, newTrieNodeImpl) - return node.array.insertArray(value) + detail.array = util.Or(detail.array, newArrayTrie) + return detail.array.insert(value) // `x in ` (see updateMemberRefInValue) inserts each element of // the literal collection as-is, without restricting it to scalars/arrays @@ -981,59 +2008,147 @@ func (node *trieNode) insertValue(value Value) *trieNode { // Call - can't actually reach here: the compiler rewrites them into // separate statements, bound to a Var, before the index is built.) case Object, Set: - node.any = util.Or(node.any, newTrieNodeImpl) - return node.any + detail.any = util.Or(detail.any, newTrieNodeImpl) + return detail.any } panic("illegal value") } -func (node *trieNode) insertArray(arr *Array) *trieNode { +// arrayTrie dispatches on the elements of an array, one node per position. A +// position dispatches the element after it and ends a rule's array, which a +// trieNode cannot hold at once. +type arrayTrie struct { + any *arrayTrie + scalars *util.HasherMap[Value, *arrayTrie] + // end is where a rule whose array ends at this position continues. + end *trieNode +} + +func newArrayTrie() *arrayTrie { + return &arrayTrie{} +} + +func newArrayChildren() *util.HasherMap[Value, *arrayTrie] { + return util.NewHasherMap[Value, *arrayTrie](ValueEqual) +} + +// insert returns the node the rule's path continues from once arr is consumed. +func (a *arrayTrie) insert(arr *Array) *trieNode { if arr.Len() == 0 { - return node + a.end = util.Or(a.end, newTrieNodeImpl) + return a.end } switch head := arr.Elem(0).Value.(type) { - case Var: - node.any = util.Or(node.any, newTrieNodeImpl) - return node.any.insertArray(arr.Slice(1, -1)) case Null, Boolean, Number, String: - child, ok := node.scalars.Get(head) + child, ok := a.scalars.Get(head) if !ok { - child = newTrieNodeImpl() - if node.scalars == nil { - node.scalars = util.NewHasherMap[Value, *trieNode](ValueEqual) - } - node.scalars.Put(head, child) + child = newArrayTrie() + a.scalars = util.Or(a.scalars, newArrayChildren) + a.scalars.Put(head, child) } - return child.insertArray(arr.Slice(1, -1)) + return child.insert(arr.Slice(1, -1)) - // Same reasoning as in insertValue above: an array element can itself be - // a nested array, object, or set, none of which can be indexed precisely - // at this position, so fall back to "any" and keep indexing the - // remaining elements. - case *Array, Object, Set: - node.any = util.Or(node.any, newTrieNodeImpl) - return node.any.insertArray(arr.Slice(1, -1)) + // An element that is itself an array, object or set cannot be indexed + // precisely at this position, so -- as for a var -- it falls back to any, + // and the elements after it go on being indexed. + case Var, *Array, Object, Set: + a.any = util.Or(a.any, newArrayTrie) + return a.any.insert(arr.Slice(1, -1)) } panic("illegal value") } -func (node *trieNode) traverse(resolver ValueResolver, tr *trieTraversalResult) error { - if node == nil { +func (a *arrayTrie) traverse(resolver ValueResolver, tr *trieTraversalResult, arr *Array) error { + if a == nil { + return nil + } + + if arr.Len() == 0 { + return a.end.Traverse(resolver, tr) + } + + if err := a.any.traverse(resolver, tr, arr.Slice(1, -1)); err != nil { + return err + } + + switch head := arr.Elem(0).Value.(type) { + case Null, Boolean, Number, String: + child, _ := a.scalars.Get(head) + return child.traverse(resolver, tr, arr.Slice(1, -1)) + } + + return nil +} + +func (a *arrayTrie) traverseUnknown(resolver ValueResolver, tr *trieTraversalResult) error { + if a == nil { return nil } - v, err := resolver.Resolve(node.ref) + if err := a.end.Traverse(resolver, tr); err != nil { + return err + } + + if err := a.any.traverseUnknown(resolver, tr); err != nil { + return err + } + + var iterErr error + a.scalars.Iter(func(_ Value, child *arrayTrie) bool { + iterErr = child.traverseUnknown(resolver, tr) + return iterErr != nil + }) + + return iterErr +} + +func (a *arrayTrie) do(walker trieWalker) { + if a == nil { + return + } + + a.end.Do(walker) + a.any.do(walker) + a.scalars.Iter(func(_ Value, child *arrayTrie) bool { + child.do(walker) + return false + }) +} + +func (a *arrayTrie) compact() { + if a == nil { + return + } + + a.end.compact() + a.any.compact() + a.scalars.Iter(func(_ Value, child *arrayTrie) bool { + child.compact() + return false + }) +} + +func (d *levelDetail) traverse(resolver ValueResolver, tr *trieTraversalResult) error { + if d == nil { + return nil + } + + v, err := resolver.Resolve(d.ref) if err != nil { if IsUnknownValueErr(err) { - return node.traverseUnknown(resolver, tr) + return d.traverseUnknown(resolver, tr) } return err } - if err = node.undefined.Traverse(resolver, tr); err != nil { + // Which order the branches below are taken in does not decide the order the + // candidates come back in -- gather reads them by id. Only undefined coming + // before the nil return is load-bearing: a ref that resolved to nothing + // admits the rules wanting it undefined and no others. + if err = d.undefined.Traverse(resolver, tr); err != nil { return err } @@ -1041,18 +2156,30 @@ func (node *trieNode) traverse(resolver ValueResolver, tr *trieTraversalResult) return nil } - if err = node.any.Traverse(resolver, tr); err != nil { + if err = d.any.Traverse(resolver, tr); err != nil { + return err + } + + if err = d.traverseValue(resolver, tr, v); err != nil { + return err + } + + // Prefix constraints are tested against the value as it is, never against + // what a mapper makes of it: the glob mapper turns a string into the array + // of its segments, and matching prefixes against those segments would + // answer a question no rule asked. + if err = d.traversePrefixes(resolver, tr, v); err != nil { return err } - if err = node.traverseValue(resolver, tr, v); err != nil { + if err = d.traverseSuffixes(resolver, tr, v); err != nil { return err } - for i := range node.mappers { - mapped := node.mappers[i].MapValue(v) + for i := range d.mappers { + mapped := d.mappers[i].MapValue(v) if !ValueEqual(mapped, v) { - if err := node.traverseValue(resolver, tr, mapped); err != nil { + if err := d.traverseValue(resolver, tr, mapped); err != nil { return err } } @@ -1061,33 +2188,67 @@ func (node *trieNode) traverse(resolver ValueResolver, tr *trieTraversalResult) return nil } -func (node *trieNode) traverseValue(resolver ValueResolver, tr *trieTraversalResult, value Value) error { +func (d *levelDetail) traverseValue(resolver ValueResolver, tr *trieTraversalResult, value Value) error { switch value := value.(type) { case *Array, Set, Object: - if node.array != nil { + if d.array != nil { if arr, ok := value.(*Array); ok { - if err := node.array.traverseArray(resolver, tr, arr); err != nil { + if err := d.array.traverse(resolver, tr, arr); err != nil { return err } } } - if node.scalars.Len() > 0 { - return node.traverseCollectionMembership(resolver, tr, value) + // Alternatives as well as scalars: a level every rule reaches by + // several values has its children under alternatives and none under + // scalars, and a collection at the reference still has to be tested + // against them. + if d.scalars.Len() > 0 || d.alternatives != nil { + return d.traverseCollectionMembership(resolver, tr, value) } case Null, Boolean, Number, String: - if child, ok := node.scalars.Get(value); ok { - return child.Traverse(resolver, tr) + if child, ok := d.scalars.Get(value); ok { + if err := child.Traverse(resolver, tr); err != nil { + return err + } + } + // A level with no alternatives -- almost all of them -- pays a branch + // and nothing more. + if d.alternatives != nil { + return d.alternatives.traverse(resolver, tr, value) } } return nil } -func (node *trieNode) traverseCollectionMembership(resolver ValueResolver, tr *trieTraversalResult, collection Value) error { +// traverse visits the nodes that the rules reaching this level by value +// continue from. +func (alt *alternativeChildren) traverse(resolver ValueResolver, tr *trieTraversalResult, value Value) error { + nodes, ok := alt.members.Get(value) + if !ok { + return nil + } + + for _, child := range nodes { + if err := child.Traverse(resolver, tr); err != nil { + return err + } + } + + return nil +} + +func (d *levelDetail) traverseCollectionMembership(resolver ValueResolver, tr *trieTraversalResult, collection Value) error { + alt := d.alternatives checkMember := func(t *Term) error { if IsScalar(t.Value) { - child, _ := node.scalars.Get(t.Value) - return child.Traverse(resolver, tr) + child, _ := d.scalars.Get(t.Value) + if err := child.Traverse(resolver, tr); err != nil { + return err + } + if alt != nil { + return alt.traverse(resolver, tr, t.Value) + } } return nil } @@ -1098,6 +2259,13 @@ func (node *trieNode) traverseCollectionMembership(resolver ValueResolver, tr *t case Set: return col.Iter(checkMember) case Object: + // Function literal does not escape + if o, ok := col.(*object); ok { + return o.Iter(func(_, v *Term) error { + return checkMember(v) + }) + } + // Function literal escapes return col.Iter(func(_, v *Term) error { return checkMember(v) }) @@ -1106,50 +2274,44 @@ func (node *trieNode) traverseCollectionMembership(resolver ValueResolver, tr *t return nil } -func (node *trieNode) traverseArray(resolver ValueResolver, tr *trieTraversalResult, arr *Array) (err error) { - if node == nil { +// traverseUnknown visits every child of a level whose reference the resolver +// cannot answer for. What each child constrains below resolves as usual: an +// unknown at one level says nothing about the levels under it. +func (d *levelDetail) traverseUnknown(resolver ValueResolver, tr *trieTraversalResult) error { + if d == nil { return nil } - if arr.Len() == 0 { - return node.Traverse(resolver, tr) - } - - if err = node.any.traverseArray(resolver, tr, arr.Slice(1, -1)); err == nil { - switch head := arr.Elem(0).Value.(type) { - case Null, Boolean, Number, String: - child, _ := node.scalars.Get(head) - return child.traverseArray(resolver, tr, arr.Slice(1, -1)) - } + if err := d.undefined.Traverse(resolver, tr); err != nil { + return err } - return err -} - -func (node *trieNode) traverseUnknown(resolver ValueResolver, tr *trieTraversalResult) error { - if node == nil { - return nil + if err := d.any.Traverse(resolver, tr); err != nil { + return err } - if err := node.Traverse(resolver, tr); err != nil { + if err := d.array.traverseUnknown(resolver, tr); err != nil { return err } - if err := node.undefined.traverseUnknown(resolver, tr); err != nil { + if err := d.prefixes.traverseUnknown(resolver, tr); err != nil { return err } - if err := node.any.traverseUnknown(resolver, tr); err != nil { + if err := d.suffixes.traverseUnknown(resolver, tr); err != nil { return err } - if err := node.array.traverseUnknown(resolver, tr); err != nil { - return err + for _, child := range d.converged() { + if err := child.Traverse(resolver, tr); err != nil { + return err + } } var iterErr error - node.scalars.Iter(func(_ Value, child *trieNode) bool { - return child.traverseUnknown(resolver, tr) != nil + d.scalars.Iter(func(_ Value, child *trieNode) bool { + iterErr = child.Traverse(resolver, tr) + return iterErr != nil }) return iterErr @@ -1171,13 +2333,16 @@ func (i *refindices) eqOperandsToRefAndValue(rule *Rule, args []*Term, a, b Valu if !ok { return false } - if ref := resolveVarToRef(i.resolvable(rule), args, v); ref != nil { - i.insert(rule, &refindex{Ref: ref, Value: bval}) + if ref := i.resolveVarToRef(i.resolvable(rule), args, v); ref != nil { + i.insert(rule, &refindex{ref: i.table.intern(ref), Value: bval}) return true } case Ref: - if !i.isValidIndexRef(v) { + // A ref rooted at a local -- `x := input; x.foo == "bar"` -- indexes the + // same as the ref that local aliases, so long as the local resolves. + v = i.resolveRefHead(rule, args, v) + if v == nil || !i.isValidIndexRef(v) { return false } @@ -1191,7 +2356,7 @@ func (i *refindices) eqOperandsToRefAndValue(rule *Rule, args []*Term, a, b Valu return false } - i.insert(rule, &refindex{Ref: v, Value: b}) + i.insert(rule, &refindex{ref: i.table.intern(v), Value: b}) return true } return false diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/index_affix.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/index_affix.go new file mode 100644 index 000000000..928842864 --- /dev/null +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/index_affix.go @@ -0,0 +1,594 @@ +// Copyright 2026 The OPA Authors. All rights reserved. +// Use of this source code is governed by an Apache2 +// license that can be found in the LICENSE file. + +package ast + +import ( + "slices" + + "github.com/open-policy-agent/opa/v1/util" +) + +// This file holds the indexing of both ends of a string: `startswith` and +// `strings.any_prefix_match`, and `endswith` and `strings.any_suffix_match`. +// One structure answers both -- a suffix trie is a prefixTrie over the base +// strings reversed (see InsertSuffix and traverseSuffix) -- so prefixTrie is +// what the file is named after. +// +// prefixTrie holds the string-prefix constraints recorded for one level of the +// rule index: what `startswith(input.x, "/api/")` and +// `strings.any_prefix_match(input.x, [...])` contribute. +// +// A scalar constraint is answered with a map lookup, but a prefix constraint +// has to answer "which of the recorded prefixes does this value start with", +// and the answer is a set, not a single entry. Testing the value against every +// recorded prefix in turn costs O(p) string comparisons per lookup for p +// prefixes -- which is the work strings.any_prefix_match exists to avoid doing +// in the rule body, so doing it in the index instead would be no bargain. +// +// This is a compressed (radix) trie instead: a lookup walks the value once and +// costs O(len(value)) byte comparisons whatever p is. Compressed rather than +// one node per byte because the node count is then bounded by 2p-1 rather than +// by the total length of all prefixes -- 10k prefixes cost thousands of nodes, +// not hundreds of thousands. +type prefixTrie struct { + // edges are sorted by the first byte of their label, which is unique among + // them, so a step down the trie is a binary search. + edges []prefixEdge + // child is where the rules of the prefixes ending exactly here hang off. It + // is an ordinary trieNode, so whatever a rule constrains below a prefix + // constraint indexes as usual. + child *trieNode +} + +type prefixEdge struct { + label string + // node is the trie under this edge; leaf stands in for it when nothing is + // recorded past the edge's label, which is almost every edge. + node *prefixTrie + leaf *trieNode +} + +// edge locates the edge labelled with first byte b, or the position a new one +// would be inserted at to keep edges sorted. Only that byte is matched; labels +// are compressed, so comparing the rest of one is left to the caller. +func (p *prefixTrie) edge(b byte) (int, bool) { + return slices.BinarySearchFunc(p.edges, b, func(e prefixEdge, b byte) int { + return int(e.label[0]) - int(b) + }) +} + +// insert returns the node that the rules constrained by prefix hang off, +// creating it if this is the first time the prefix is recorded. +func (p *prefixTrie) insert(prefix string) *trieNode { + node := p + + for { + if prefix == "" { + if node.child == nil { + node.child = newTrieNodeImpl() + } + return node.child + } + + pos, found := node.edge(prefix[0]) + if !found { + leaf := newTrieNodeImpl() + node.edges = slices.Insert(node.edges, pos, prefixEdge{label: prefix, leaf: leaf}) + return leaf + } + + edge := node.edges[pos] + common := commonPrefixLen(edge.label, prefix) + + switch { + // The two diverge inside this edge -- "/api/v1" meeting "/api/v2" -- + // so the edge is split where they stop agreeing and what used to hang + // off it moves down onto the tail, whichever kind it is. + case common < len(edge.label): + tail := prefixEdge{label: edge.label[common:], node: edge.node, leaf: edge.leaf} + node.edges[pos] = prefixEdge{ + label: edge.label[:common], + node: &prefixTrie{edges: []prefixEdge{tail}}, + } + + // The prefix ends where an edge does with nothing past it, so its + // continuation is already the answer. + case common == len(prefix) && edge.leaf != nil: + return edge.leaf + + // Something is recorded past the edge now, so its continuation becomes + // the child of a trie of its own. + case edge.node == nil: + node.edges[pos] = prefixEdge{ + label: edge.label, + node: &prefixTrie{child: edge.leaf}, + } + } + + node = node.edges[pos].node + prefix = prefix[common:] + } +} + +// traverse visits the continuation of every recorded prefix that s starts with. +// One walk down the trie finds all of them: the prefixes of s that are in the +// trie are exactly the ends-of-prefix passed on the way down. +func (p *prefixTrie) traverse(s string, resolver ValueResolver, tr *trieTraversalResult) error { + for node := p; node != nil; { + if node.child != nil { + if err := node.child.Traverse(resolver, tr); err != nil { + return err + } + } + + if s == "" { + return nil + } + + pos, found := node.edge(s[0]) + if !found { + return nil + } + + edge := node.edges[pos] + if len(edge.label) > len(s) || s[:len(edge.label)] != edge.label { + return nil + } + + s = s[len(edge.label):] + if edge.node == nil { + return edge.leaf.Traverse(resolver, tr) + } + node = edge.node + } + + return nil +} + +// traverseSuffix is traverse over the end of s. A suffix trie holds its base +// strings reversed (see affixTries), so the walk consumes s from its +// last byte back -- which needs no reversed copy of s to be made per lookup. +func (p *prefixTrie) traverseSuffix(s string, resolver ValueResolver, tr *trieTraversalResult) error { + for node := p; node != nil; { + if node.child != nil { + if err := node.child.Traverse(resolver, tr); err != nil { + return err + } + } + + if s == "" { + return nil + } + + pos, found := node.edge(s[len(s)-1]) + if !found { + return nil + } + + edge := node.edges[pos] + if len(edge.label) > len(s) || !equalReversed(s[len(s)-len(edge.label):], edge.label) { + return nil + } + + s = s[:len(s)-len(edge.label)] + if edge.node == nil { + return edge.leaf.Traverse(resolver, tr) + } + node = edge.node + } + + return nil +} + +// equalReversed reports whether tail read backwards is reversed. +func equalReversed(tail, reversed string) bool { + for i := range reversed { + if reversed[i] != tail[len(tail)-1-i] { + return false + } + } + return true +} + +// reverseString returns s with its bytes reversed. A base string is reversed +// once, when it is recorded; `endswith` is a byte comparison, so reversing +// bytes rather than runes is what makes a suffix of s a prefix of reversed s. +func reverseString(s string) string { + b := []byte(s) + slices.Reverse(b) + + // b was made here and is not written to again, so it can be handed over + // rather than copied a second time. + return util.ByteSliceToString(b) +} + +// compact releases the spare capacity in the edge slices. Edges arrive in +// arbitrary order, so they are placed by insertion and grow the way append does +// -- which leaves 60% of the slots unused across a large prefix set -- and +// nothing inserts once the index is built. slices.Clip only caps the capacity; +// releasing the block means copying out of it. +func (p *prefixTrie) compact() { + if p == nil { + return + } + + if cap(p.edges) > len(p.edges) { + exact := make([]prefixEdge, len(p.edges)) + copy(exact, p.edges) + p.edges = exact + } + + p.child.compact() + + for _, edge := range p.edges { + edge.node.compact() + edge.leaf.compact() + } +} + +func (p *prefixTrie) do(walker trieWalker) { + if p == nil { + return + } + + p.child.Do(walker) + + for _, edge := range p.edges { + edge.node.do(walker) + edge.leaf.Do(walker) + } +} + +func (p *prefixTrie) traverseUnknown(resolver ValueResolver, tr *trieTraversalResult) error { + if p == nil { + return nil + } + + if err := p.child.Traverse(resolver, tr); err != nil { + return err + } + + for _, edge := range p.edges { + if err := edge.node.traverseUnknown(resolver, tr); err != nil { + return err + } + if err := edge.leaf.Traverse(resolver, tr); err != nil { + return err + } + } + + return nil +} + +// prefixEntry is a prefix the trie holds, spelled out, with the node its rules +// hang off. +type prefixEntry struct { + prefix string + node *trieNode +} + +// walk returns the prefixes the trie holds, in lexicographic order. Only the +// index's debug rendering and its tests have any use for reading back what the +// compression made of them. +func (p *prefixTrie) walk() []prefixEntry { + if p == nil { + return nil + } + + var ( + entries []prefixEntry + collect func(node *prefixTrie, prefix string) + ) + + collect = func(node *prefixTrie, prefix string) { + if node.child != nil { + entries = append(entries, prefixEntry{prefix: prefix, node: node.child}) + } + for _, edge := range node.edges { + if edge.node == nil { + entries = append(entries, prefixEntry{prefix: prefix + edge.label, node: edge.leaf}) + continue + } + collect(edge.node, prefix+edge.label) + } + } + + collect(p, "") + + return entries +} + +func commonPrefixLen(a, b string) int { + n := min(len(a), len(b)) + i := 0 + for i < n && a[i] == b[i] { + i++ + } + return i +} + +// InsertPrefix records that the rules below this node require the value at ref +// to be a string starting with prefix. +func (node *trieNode) InsertPrefix(ref Ref, prefix Value) *trieNode { + level := node.level() + level.ref = ref + + s, ok := prefix.(String) + if !ok { + panic("illegal prefix value") + } + + return level.affixTrie(affixPrefix).insert(string(s)) +} + +// InsertSuffix records that the rules below this node require the value at ref +// to be a string ending with suffix. +func (node *trieNode) InsertSuffix(ref Ref, suffix Value) *trieNode { + level := node.level() + level.ref = ref + + s, ok := suffix.(String) + if !ok { + panic("illegal suffix value") + } + + return level.affixTrie(affixSuffix).insert(reverseString(string(s))) +} + +// traversePrefixes visits the rules whose prefix constraints value satisfies. +// +// strings.any_prefix_match takes a collection of search strings as readily as a +// single one, and holds if any of them starts with any of the base strings, so +// a collection is tested element by element -- the same way a scalar constraint +// is matched against the members of a collection (see +// traverseCollectionMembership). +func (d *levelDetail) traversePrefixes(resolver ValueResolver, tr *trieTraversalResult, value Value) error { + prefixes := d.prefixes + if prefixes == nil { + return nil + } + + if s, ok := value.(String); ok { + return prefixes.traverse(string(s), resolver, tr) + } + + checkMember := func(t *Term) error { + if s, ok := t.Value.(String); ok { + return prefixes.traverse(string(s), resolver, tr) + } + return nil + } + + switch col := value.(type) { + case *Array: + return col.Iter(checkMember) + case Set: + return col.Iter(checkMember) + case Object: + if o, ok := col.(*object); ok { + return o.Iter(func(_, v *Term) error { + return checkMember(v) + }) + } + return col.Iter(func(_, v *Term) error { + return checkMember(v) + }) + } + + return nil +} + +// traverseSuffixes visits the rules whose suffix constraints value satisfies. +// A collection is tested element by element, as for prefixes. +func (d *levelDetail) traverseSuffixes(resolver ValueResolver, tr *trieTraversalResult, value Value) error { + suffixes := d.suffixes + if suffixes == nil { + return nil + } + + if s, ok := value.(String); ok { + return suffixes.traverseSuffix(string(s), resolver, tr) + } + + checkMember := func(t *Term) error { + if s, ok := t.Value.(String); ok { + return suffixes.traverseSuffix(string(s), resolver, tr) + } + return nil + } + + switch col := value.(type) { + case *Array: + return col.Iter(checkMember) + case Set: + return col.Iter(checkMember) + case Object: + if o, ok := col.(*object); ok { + // doesn't allocate / escape + for _, node := range o.sortedKeys() { + if err := checkMember(node.value); err != nil { + return err + } + } + return nil + } + // allocates / escapes + return col.Iter(func(_, v *Term) error { + return checkMember(v) + }) + } + + return nil +} + +// updateStartsWith indexes `startswith(x, "base")`: x has to be a string +// starting with base for the rule to hold. +func (i *refindices) updateAffix(rule *Rule, expr *Expr, constants map[Var]Value, a affix) { + ref := i.resolveAndValidateRef(rule, rule.Head.Args, expr.Operand(0)) + if ref == nil { + return + } + + base, ok := constantString(expr.Operand(1), constants) + if !ok { + return + } + + i.insert(rule, &refindex{ref: i.table.intern(ref), Value: base, Affix: a}) +} + +// updateAnyPrefixMatch indexes `strings.any_prefix_match(x, base)`, which is +// a disjunction of startswith calls: each base string is recorded as an +// alternative prefix for x, the same way each element of `x in [...]` is +// recorded as an alternative value (see updateMemberRefInValue). +// +// The search operand has to be a single ref: a collection of search strings +// would need every element of one collection tested against the other, which +// is not a constraint on the value at any one ref. +func (i *refindices) updateAnyAffixMatch(rule *Rule, expr *Expr, constants map[Var]Value, a affix) { + ref := i.resolveAndValidateRef(rule, rule.Head.Args, expr.Operand(0)) + if ref == nil { + return + } + + base := expr.Operand(1).Value + if v, ok := base.(Var); ok { + resolved, ok := constants[v] + if !ok { + return + } + base = resolved + } + + if s, ok := base.(String); ok { + i.insert(rule, &refindex{ref: i.table.intern(ref), Value: s, Affix: a}) + return + } + + // Every base string has to be recorded, or the index would exclude rules + // the dropped ones would have matched -- so a base that isn't a collection + // of ground strings throughout leaves the rule unindexed rather than + // partly indexed. + bases, ok := groundStrings(base) + if !ok || len(bases) == 0 { + return + } + + i.insertAffixes(rule, ref, bases, a) +} + +// insertAffixes records a whole base collection at once, for either end of the +// value. insert() rescans the rule's indices on every call, which is quadratic +// over the thousands strings.any_prefix_match carries, so the scan happens once +// here instead. insertMembers is the same for `in`; the two dedup on different +// key types. +func (i *refindices) insertAffixes(rule *Rule, ref Ref, bases []Value, a affix) { + id := i.table.intern(ref) + + // concrete counts the values this rule already reaches ref by that survive + // insertPath's var-stripping, so that the alternatives the base adds can be + // weighed against them without a second scan (see refindices.alternate). + concrete := 0 + known := false + seen := make(map[String]struct{}, len(bases)) + for _, other := range i.rules[rule] { + if other.ref != id { + continue + } + known = true + if !other.isVar() { + concrete++ + } + if other.Affix == a { + if s, ok := other.Value.(String); ok { + seen[s] = struct{}{} + } + } + } + n := len(bases) + if known && n > 0 { + n-- + } + i.countN(id, n) + + // One refindex per base, laid down in a single block rather than allocated + // one at a time: a base collection runs to thousands of them. Duplicates + // leave slack at the end of the block, which the reslice below drops. + pos := len(i.rules[rule]) + indices := util.GrowPtrSlice(i.rules[rule], len(bases)) + + for _, base := range bases { + // groundStrings has established that every base is a String, and hands + // the Term's own Value over so that refindex.Value costs no second box. + key := base.(String) + if _, ok := seen[key]; ok { + continue + } + seen[key] = struct{}{} + concrete++ + + *indices[pos] = refindex{ref: id, Value: base, Affix: a} + pos++ + } + i.rules[rule] = indices[:pos] + + if concrete > 1 { + i.alternate(id, alternationTerminal) + } +} + +// constantString resolves term to a string literal, following one level of +// var binding recorded earlier in the rule body. +func constantString(term *Term, constants map[Var]Value) (String, bool) { + v := term.Value + if vr, ok := v.(Var); ok { + resolved, ok := constants[vr] + if !ok { + return "", false + } + v = resolved + } + + s, ok := v.(String) + return s, ok +} + +// groundStrings returns the members of an array or set literal, and reports +// false unless every one of them is a string. The member's own Value is what +// comes back, not the String inside it: every caller puts it straight into a +// refindex, and a Term is already holding it boxed. +func groundStrings(v Value) ([]Value, bool) { + var ( + until func(func(*Term) bool) bool + n int + ) + + switch col := v.(type) { + case *Array: + until, n = col.Until, col.Len() + case Set: + until, n = col.Until, col.Len() + default: + return nil, false + } + + // The base of a strings.any_prefix_match runs to thousands of strings, so + // the length is worth taking off the collection rather than growing into. + out := make([]Value, 0, n) + + // Until stops on the first member that is not a string, and reports having + // stopped -- which is the whole of "unless every one of them is a string". + if until(func(t *Term) bool { + _, ok := t.Value.(String) + if ok { + out = append(out, t.Value) + } + return !ok + }) { + return nil, false + } + + return out, true +} diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/index_debug.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/index_debug.go index 17d74072e..18ca875b8 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/index_debug.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/index_debug.go @@ -12,23 +12,24 @@ import ( "github.com/open-policy-agent/opa/v1/util" ) -func (node *trieNode) mermaid() string { +// mermaid renders the trie, naming the rules by their bodies -- which the index +// holds, and the nodes only the ids of. +func (i *baseDocEqIndex) mermaid() string { var sb strings.Builder sb.WriteString("graph TD\n") nodeCounter := 0 nodeIDs := make(map[*trieNode]string) - node.mermaidFormat(&sb, &nodeCounter, nodeIDs, "") + i.root.mermaidFormat(&sb, &nodeCounter, nodeIDs, "", i.rules) return sb.String() } -func (node *trieNode) mermaidFormat(sb *strings.Builder, counter *int, nodeIDs map[*trieNode]string, parentID string) { +func (node *trieNode) mermaidFormat(sb *strings.Builder, counter *int, nodeIDs map[*trieNode]string, parentID string, rules []*Rule) { currentID, exists := nodeIDs[node] if !exists { currentID = fmt.Sprintf("n%d", *counter) *counter++ nodeIDs[node] = currentID - label := node.mermaidLabel() - fmt.Fprintf(sb, " %s[\"%s\"]\n", currentID, label) + fmt.Fprintf(sb, " %s[\"%s\"]\n", currentID, node.mermaidLabel(rules)) } if parentID != "" { @@ -39,101 +40,96 @@ func (node *trieNode) mermaidFormat(sb *strings.Builder, counter *int, nodeIDs m return } - if node.undefined != nil { - if childID, childExists := nodeIDs[node.undefined]; childExists { - fmt.Fprintf(sb, " %s -->|undefined| %s\n", currentID, childID) - } else { - node.undefined.mermaidFormat(sb, counter, nodeIDs, "") - fmt.Fprintf(sb, " %s -->|undefined| %s\n", currentID, nodeIDs[node.undefined]) - } + node.next.mermaidFormat(sb, counter, nodeIDs, currentID, rules) +} + +// mermaidEdge draws one way of matching the level's reference, emitting the +// child first if this is where it is reached from. +func mermaidEdge(sb *strings.Builder, counter *int, nodeIDs map[*trieNode]string, from, label string, child *trieNode, rules []*Rule) { + if child == nil { + return + } + if _, exists := nodeIDs[child]; !exists { + child.mermaidFormat(sb, counter, nodeIDs, "", rules) } + fmt.Fprintf(sb, " %s -->|\"%s\"| %s\n", from, mermaidEscape(label), nodeIDs[child]) +} - if node.any != nil { - if childID, childExists := nodeIDs[node.any]; childExists { - fmt.Fprintf(sb, " %s -->|any| %s\n", currentID, childID) - } else { - node.any.mermaidFormat(sb, counter, nodeIDs, "") - fmt.Fprintf(sb, " %s -->|any| %s\n", currentID, nodeIDs[node.any]) - } +func (d *levelDetail) mermaidFormat(sb *strings.Builder, counter *int, nodeIDs map[*trieNode]string, from string, rules []*Rule) { + if d == nil { + return } - if node.scalars.Len() > 0 { - type scalarPair struct { - key Value - node *trieNode - } - pairs := make([]scalarPair, 0, node.scalars.Len()) - node.scalars.Iter(func(key Value, val *trieNode) bool { - pairs = append(pairs, scalarPair{key, val}) + mermaidEdge(sb, counter, nodeIDs, from, "undefined", d.undefined, rules) + mermaidEdge(sb, counter, nodeIDs, from, "any", d.any, rules) + + d.scalars.Iter(func(key Value, child *trieNode) bool { + mermaidEdge(sb, counter, nodeIDs, from, key.String(), child, rules) + return false + }) + + if d.alternatives != nil { + d.alternatives.members.Iter(func(key Value, nodes []*trieNode) bool { + for _, child := range nodes { + mermaidEdge(sb, counter, nodeIDs, from, key.String(), child, rules) + } return false }) - slices.SortFunc(pairs, func(a, b scalarPair) int { - return a.key.Compare(b.key) - }) - for _, pair := range pairs { - var scalarLabel string - if s, ok := pair.key.(String); ok { - scalarLabel = string(s) - } else { - scalarLabel = pair.key.String() - } - if len(scalarLabel) > 20 { - scalarLabel = scalarLabel[:20] + "..." - } - scalarLabel = mermaidEscape(scalarLabel) - if childID, childExists := nodeIDs[pair.node]; childExists { - fmt.Fprintf(sb, " %s -->|\"%s\"| %s\n", currentID, scalarLabel, childID) - } else { - pair.node.mermaidFormat(sb, counter, nodeIDs, "") - fmt.Fprintf(sb, " %s -->|\"%s\"| %s\n", currentID, scalarLabel, nodeIDs[pair.node]) - } - } } - if node.array != nil { - if childID, childExists := nodeIDs[node.array]; childExists { - fmt.Fprintf(sb, " %s -->|array| %s\n", currentID, childID) - } else { - node.array.mermaidFormat(sb, counter, nodeIDs, "") - fmt.Fprintf(sb, " %s -->|array| %s\n", currentID, nodeIDs[node.array]) - } + for _, p := range d.prefixes.walk() { + mermaidEdge(sb, counter, nodeIDs, from, p.prefix+"*", p.node, rules) } - if node.next != nil { - node.next.mermaidFormat(sb, counter, nodeIDs, currentID) + // A suffix trie holds its bases reversed (see affixTries), so what it + // walks back is what was written. + for _, p := range d.suffixes.walk() { + mermaidEdge(sb, counter, nodeIDs, from, "*"+reverseString(p.prefix), p.node, rules) } + + d.array.mermaidFormat(sb, counter, nodeIDs, from, "array", rules) } -func (node *trieNode) mermaidLabel() string { +func (a *arrayTrie) mermaidFormat(sb *strings.Builder, counter *int, nodeIDs map[*trieNode]string, from, label string, rules []*Rule) { + if a == nil { + return + } + + mermaidEdge(sb, counter, nodeIDs, from, label, a.end, rules) + a.any.mermaidFormat(sb, counter, nodeIDs, from, label+" any", rules) + a.scalars.Iter(func(key Value, child *arrayTrie) bool { + child.mermaidFormat(sb, counter, nodeIDs, from, label+" "+key.String(), rules) + return false + }) +} + +func (node *trieNode) mermaidLabel(rules []*Rule) string { var parts []string - if len(node.ref) > 0 { - parts = append(parts, node.ref.String()) + if node.next != nil && len(node.next.ref) > 0 { + parts = append(parts, node.next.ref.String()) } - if len(node.rules) > 0 { - for _, rn := range node.rules { - bodyStr := "" - if rn.rule.Body != nil { - bodyStr = rn.rule.Body.String() - if len(bodyStr) > 50 { - bodyStr = bodyStr[:50] + "..." - } + for _, id := range node.rules { + bodyStr := "" + if rule := rules[id]; rule.Body != nil { + bodyStr = rule.Body.String() + if len(bodyStr) > 50 { + bodyStr = bodyStr[:50] + "..." } - bodyStr = mermaidEscape(bodyStr) - parts = append(parts, bodyStr) } + parts = append(parts, mermaidEscape(bodyStr)) } - if len(node.mappers) > 0 { - parts = append(parts, fmt.Sprintf("%d mapper(s)", len(node.mappers))) + if node.next != nil && len(node.next.mappers) > 0 { + parts = append(parts, fmt.Sprintf("%d mapper(s)", len(node.next.mappers))) } if node.multiple { parts = append(parts, "multiple") } if len(parts) == 0 { - return "·" + return "\u00b7" } return strings.Join(parts, "
") @@ -151,25 +147,22 @@ func (node *trieNode) String() string { } func (node *trieNode) format(sb *strings.Builder, depth int) { + if node == nil { + return + } + indent := strings.Repeat(" ", depth) - if len(node.ref) > 0 { - sb.WriteString(indent) - sb.WriteString(node.ref.String()) - } else if depth == 0 { + if depth == 0 { sb.WriteString("root") + } else { + sb.WriteString(indent) } - if len(node.rules) > 0 { sb.WriteString(" [") util.WriteInt(sb, len(node.rules)) sb.WriteString(" rule(s)]") } - if len(node.mappers) > 0 { - sb.WriteString(" [") - util.WriteInt(sb, len(node.mappers)) - sb.WriteString(" mapper(s)]") - } if node.value != nil { sb.WriteString(" value=") sb.WriteString(node.value.String()) @@ -179,48 +172,134 @@ func (node *trieNode) format(sb *strings.Builder, depth int) { } sb.WriteByte('\n') - if node.undefined != nil { + node.next.format(sb, depth) +} + +// format prints the level below a node: the reference it resolves, and a line +// per way of matching it. +func (d *levelDetail) format(sb *strings.Builder, depth int) { + if d == nil { + return + } + + indent := strings.Repeat(" ", depth) + + if len(d.ref) > 0 { + sb.WriteString(indent) + sb.WriteString(d.ref.String()) + if len(d.mappers) > 0 { + sb.WriteString(" [") + util.WriteInt(sb, len(d.mappers)) + sb.WriteString(" mapper(s)]") + } + sb.WriteByte('\n') + } + + if d.undefined != nil { sb.WriteString(indent) sb.WriteString(" undefined:\n") - node.undefined.format(sb, depth+2) + d.undefined.format(sb, depth+2) } - if node.any != nil { + if d.any != nil { sb.WriteString(indent) sb.WriteString(" any:\n") - node.any.format(sb, depth+2) + d.any.format(sb, depth+2) } - if node.scalars.Len() > 0 { - scalars := make([]Value, 0, node.scalars.Len()) - nodes := make([]*trieNode, 0, node.scalars.Len()) - node.scalars.Iter(func(key Value, val *trieNode) bool { + if d.scalars.Len() > 0 { + scalars := make([]Value, 0, d.scalars.Len()) + d.scalars.Iter(func(key Value, _ *trieNode) bool { scalars = append(scalars, key) - nodes = append(nodes, val) return false }) slices.SortFunc(scalars, Value.Compare) - for i := range scalars { + for _, k := range scalars { + child, _ := d.scalars.Get(k) sb.WriteString(indent) sb.WriteString(" ") - sb.WriteString(scalars[i].String()) + sb.WriteString(k.String()) sb.WriteString(":\n") - for j := range nodes { - if ValueEqual(scalars[i], scalars[j]) { - nodes[j].format(sb, depth+2) - break + child.format(sb, depth+2) + } + } + + // Several values reaching one node, so the node is printed once and the + // values that reach it are named together (see alternativeChildren). + if d.alternatives != nil { + for i, conv := range d.alternatives.converged { + var keys []Value + d.alternatives.members.Iter(func(k Value, nodes []*trieNode) bool { + if slices.Contains(nodes, conv) { + keys = append(keys, k) } + return false + }) + slices.SortFunc(keys, Value.Compare) + + sb.WriteString(indent) + sb.WriteString(" any of ") + for j, k := range keys { + if j > 0 { + sb.WriteString(", ") + } + sb.WriteString(k.String()) } + fmt.Fprintf(sb, " -> #%d:\n", i) + conv.format(sb, depth+2) } } - if node.array != nil { + if d.array != nil { sb.WriteString(indent) sb.WriteString(" array:\n") - node.array.format(sb, depth+2) + d.array.format(sb, depth+2) + } + + for _, p := range d.prefixes.walk() { + sb.WriteString(indent) + sb.WriteString(` prefix "`) + sb.WriteString(p.prefix) + sb.WriteString("\":\n") + p.node.format(sb, depth+2) + } + + for _, p := range d.suffixes.walk() { + sb.WriteString(indent) + sb.WriteString(` suffix "`) + sb.WriteString(reverseString(p.prefix)) + sb.WriteString("\":\n") + p.node.format(sb, depth+2) + } +} + +func (a *arrayTrie) format(sb *strings.Builder, depth int) { + if a == nil { + return } - if node.next != nil { - node.next.format(sb, depth) + indent := strings.Repeat(" ", depth) + + a.end.format(sb, depth) + + if a.any != nil { + sb.WriteString(indent) + sb.WriteString(" any:\n") + a.any.format(sb, depth+2) + } + + keys := make([]Value, 0, a.scalars.Len()) + a.scalars.Iter(func(k Value, _ *arrayTrie) bool { + keys = append(keys, k) + return false + }) + slices.SortFunc(keys, Value.Compare) + for _, k := range keys { + child, _ := a.scalars.Get(k) + sb.WriteString(indent) + sb.WriteString(" ") + sb.WriteString(k.String()) + sb.WriteString(":\n") + child.format(sb, depth+2) } } diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/internal/scanner/scanner.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/internal/scanner/scanner.go index 6b2b03b27..cbf4cd479 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/internal/scanner/scanner.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/internal/scanner/scanner.go @@ -502,12 +502,9 @@ func (s *Scanner) scanRawTemplateString() (string, tokens.Token) { break } - if ch == '\\' { - switch s.curr { - case '{': - escapes = append(escapes, s.offset-1) - s.next() - } + if ch == '\\' && s.curr == '{' { + escapes = append(escapes, s.offset-1) + s.next() } } diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/interning.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/interning.go index 7e12367ab..7b604d566 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/interning.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/interning.go @@ -18,6 +18,9 @@ type interned struct { } type internedRefs struct { + AnyPrefixMatch Ref + AnySuffixMatch Ref + EndsWith Ref Equal Ref Equality Ref GlobMatch Ref @@ -29,6 +32,7 @@ type internedRefs struct { Print Ref RegoMetadataChain Ref RegoMetadataRule Ref + StartsWith Ref } // NOTE! Great care must be taken **not** to modify the terms returned @@ -39,6 +43,9 @@ type internedRefs struct { var ( Interned = &interned{ Refs: &internedRefs{ + AnyPrefixMatch: AnyPrefixMatch.Ref(), + AnySuffixMatch: AnySuffixMatch.Ref(), + EndsWith: EndsWith.Ref(), Equal: Equal.Ref(), Equality: Equality.Ref(), GlobMatch: GlobMatch.Ref(), @@ -50,6 +57,7 @@ var ( Print: Print.Ref(), RegoMetadataChain: RegoMetadataChain.Ref(), RegoMetadataRule: RegoMetadataRule.Ref(), + StartsWith: StartsWith.Ref(), }, } diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/location/location.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/location/location.go index 9c2213bc5..795480c1b 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/location/location.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/location/location.go @@ -129,7 +129,7 @@ func EndOf(row, col int, text []byte) (endRow, endCol int) { // column of the Location (but not on the text.) Nil locations are greater than // non-nil locations. func (loc *Location) Compare(other *Location) int { - if loc == other { + if loc == other { //nolint:gocritic // this is fine as an ifElseChain return 0 } else if loc == nil { return 1 diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/map.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/map.go index aa0e655b9..2120e00b0 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/map.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/map.go @@ -26,7 +26,7 @@ func NewValueMap() *ValueMap { // MarshalJSON provides a custom marshaller for the ValueMap which // will include the key, value, and value type. func (vs *ValueMap) MarshalJSON() ([]byte, error) { - var tmp []map[string]any + tmp := make([]map[string]any, 0, vs.Len()) vs.Iter(func(k Value, v Value) bool { tmp = append(tmp, map[string]any{ "name": k.String(), diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/parser.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/parser.go index 636d713af..65a3a2a18 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/parser.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/parser.go @@ -62,7 +62,7 @@ var ( // recursion exceeds the maximum allowed depth ErrMaxParsingRecursionDepthExceeded = errors.New("max parsing recursion depth exceeded") - RegoV1CompatibleRef = Ref{VarTerm("rego"), InternedTerm("v1")} + RegoV1CompatibleRef = Ref{RegoRootDocument, InternedTerm("v1")} // this is the name to use for instantiating an empty set, e.g., `set()`. setConstructor = RefTerm(VarTerm("set")) @@ -73,6 +73,7 @@ var ( } metadataBytes = []byte("METADATA") metadataParserPool = util.NewSyncPool[metadataParser]() + noScanOptions []scanner.ScanOption ) func (v RegoVersion) Int() int { @@ -443,6 +444,14 @@ func (p *Parser) Parse() ([]Statement, []*Comment, Errors) { // point trying to parse packages, imports, etc. in the same order. for p.s.tok != tokens.EOF { var s *state + + // Reported here rather than in parseRules: `package := 1` and `import := 1` + // are consumed by the statement parsers below, which fail pointing at the + // assign token instead of the keyword. + if !p.po.SkipRules && p.errKeywordRuleName(false) { + break + } + if p.s.tok == tokens.Package { s = p.save() if pkg := p.parsePackage(); pkg != nil { @@ -459,8 +468,10 @@ func (p *Parser) Parse() ([]Statement, []*Comment, Errors) { if imp := p.parseImport(); imp != nil { if RegoRootDocument.Equal(imp.Path.Value.(Ref)[0]) { p.regoV1Import(imp) + p.reclassifyKeyword() } else if FutureRootDocument.Equal(imp.Path.Value.(Ref)[0]) { p.futureImport(imp, allowedFutureKeywords) + p.reclassifyKeyword() } stmts = append(stmts, imp) continue @@ -766,6 +777,74 @@ func scanAheadRef(p *Parser) bool { return false } +// keywordRuleNameFollowers maps a keyword token to the tokens that, following it, +// make the statement unambiguously a rule declaration. +var ( + ruleNameFollowers = []tokens.Token{tokens.Assign, tokens.Unify, tokens.If, tokens.Contains, tokens.LParen} + // `not`/`and`/`or` drop '(': at the start of a statement, `not (x)` is a negated + // group and `or(x, y)` a call to the set union built-in, not rule heads. + operatorRuleNameFollowers = []tokens.Token{tokens.Assign, tokens.Unify, tokens.If, tokens.Contains} + // `package`/`import` drop `if` and `contains`: both take a path that may itself + // be named after a keyword, as in `package contains` or `import if.foo`. + pathRuleNameFollowers = []tokens.Token{tokens.Assign, tokens.Unify, tokens.LParen} + keywordRuleNameFollowers = map[tokens.Token][]tokens.Token{ + tokens.Every: ruleNameFollowers, + tokens.If: ruleNameFollowers, + tokens.In: ruleNameFollowers, + tokens.Some: ruleNameFollowers, + tokens.As: ruleNameFollowers, + tokens.Package: pathRuleNameFollowers, + tokens.Import: pathRuleNameFollowers, + tokens.Not: operatorRuleNameFollowers, + tokens.LogicalAnd: operatorRuleNameFollowers, + tokens.LogicalOr: operatorRuleNameFollowers, + // `contains` outside of a rule head parses as a plain var, so `contains := x` + // is still a legal query; as a rule it's caught by the rego-v1 check. + tokens.Contains: {tokens.If, tokens.Contains}, + } +) + +// reclassifyKeyword re-tags the lookahead token after an import that registered +// new keywords with the scanner. The parser reads one token ahead, so the first +// token of the statement following the import was scanned before the scanner +// knew about the keyword, and would otherwise be treated as a plain identifier. +func (p *Parser) reclassifyKeyword() { + if p.s.tok != tokens.Ident { + return + } + + if tok, ok := allFutureKeywords[p.s.lit]; ok && p.s.s.IsKeyword(p.s.lit) { + p.s.tok = tok + } +} + +// errKeywordRuleName reports an error if the current token is a keyword used as a +// rule name, e.g. `every := 1`, and returns whether it did. A statement that began +// with `default` can only be a rule, so no lookahead is needed there. +func (p *Parser) errKeywordRuleName(isDefault bool) bool { + followers, ok := keywordRuleNameFollowers[p.s.tok] + if !ok { + return false + } + + keyword, loc := p.s.tok, p.s.Loc() + + if !isDefault { + s := p.save() + p.scan() + next := p.s.tok + p.restore(s) + + if !slices.Contains(followers, next) { + return false + } + } + + p.errorf(loc, "%s keyword cannot be used for rule name", keyword) + + return true +} + // scanAheadLogicalCall rewrites an `and`/`or` keyword token to tokens.Ident when // it's immediately followed by `(`. Only valid where a term is expected: there, // the operator reading is impossible, so it must be a function (`&`/`|` set built-ins). @@ -801,6 +880,9 @@ func (p *Parser) parseRules() []*Rule { } if p.s.tok != tokens.Ident { + if rule.Default { + p.errKeywordRuleName(true) + } return nil } @@ -1191,6 +1273,7 @@ func (p *Parser) parseQuery(requireSemi bool, end tokens.Token) Body { if !p.s.skippedNL { // If there was already an error then don't pile this one on if len(p.s.errors) == 0 { + p.hintMissingInfixKeyword() p.illegal(`expected \n or %s or %s`, tokens.Semicolon, end) } return nil @@ -1473,6 +1556,60 @@ func (p *Parser) attachWith(e *Expr) *Expr { return e } +// infixFutureKeywords are the future keywords usable as infix operators in a +// rule body, mapped to an example of the expression each enables. +var infixFutureKeywords = map[string]string{ + "in": "x in xs", + "and": "x and y", + "or": "x or y", +} + +// hintMissingInfixKeyword hints at the import for a body expression trailed by +// a plain `in`/`and`/`or` identifier, or by the comma of `k, v in xs`. Only +// call it when an error is about to be reported: an unconsumed hint would end +// up attached to a later, unrelated error. +func (p *Parser) hintMissingInfixKeyword() { + // Something more specific, like `some x in xs`, already hinted. + if len(p.s.hints) > 0 { + return + } + + kw := "in" + + switch p.s.tok { + case tokens.Ident: + // An active keyword scans as its own token, so an Ident means it's + // the import that's missing. + kw = p.s.lit + if _, ok := infixFutureKeywords[kw]; !ok { + return + } + case tokens.Comma: + // Only hint on `k, v in xs`, so require a membership expr after the comma. + s := p.save() + p.scan() + term := p.futureParser().parseTermInfixCall() + p.restore(s) + + if term == nil { + return + } + call, ok := term.Value.(Call) + if !ok || len(call) == 0 { + return + } + switch call[0].String() { + case Member.Name, MemberWithKey.Name: + default: + return + } + default: + return + } + + p.hint(fmt.Sprintf("`import future.keywords.%s` for `%s` expressions", kw, infixFutureKeywords[kw])) +} + func (p *Parser) errWithOnOperand(loc *Location, kw string) { p.hint(fmt.Sprintf( "Wrap the operand in `(...)` or `{...}` to scope, or move `with` after the `%s` expression to apply it to the whole expression", @@ -3078,12 +3215,14 @@ func (p *Parser) parseObject(k *Term, potentialComprehension bool) *Term { return nil } - potentialRelation := true if potentialComprehension { switch p.s.tok { case tokens.RBrace, tokens.Comma: - potentialRelation = false - fallthrough + // This is the only parse available, so return its result as-is: + // backtracking would drop the errors reported here in favour of a + // "non-terminated object" pointing at the value we just parsed + // rather than at the offending token. + return p.parseObjectFinish(k, v, true) case tokens.Or: if term := p.parseObjectFinish(k, v, true); term != nil { return term @@ -3093,16 +3232,14 @@ func (p *Parser) parseObject(k *Term, potentialComprehension bool) *Term { p.restore(s) - if potentialRelation { - v := p.parseTermInfixCallInList() - if v == nil { - return nil - } + v = p.parseTermInfixCallInList() + if v == nil { + return nil + } - switch p.s.tok { - case tokens.RBrace, tokens.Comma: - return p.parseObjectFinish(k, v, false) - } + switch p.s.tok { + case tokens.RBrace, tokens.Comma: + return p.parseObjectFinish(k, v, false) } p.illegal("non-terminated object") @@ -3324,8 +3461,6 @@ func (p *Parser) illegalToken() { p.illegal("") } -var noScanOptions []scanner.ScanOption - func (p *Parser) scan() { p.doScan(true, noScanOptions...) } diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/parser_ext.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/parser_ext.go index 4ee762514..6c8537c22 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/parser_ext.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/parser_ext.go @@ -703,7 +703,12 @@ func parseModule(filename string, stmts []Statement, comments []*Comment, regoCo case Body: rule, err := ParseRuleFromBody(mod, stmt) if err != nil { - errs = append(errs, NewError(ParseErr, stmt[0].Location, "%s", err.Error())) + msg := err.Error() + if kw, ok := missingHeadKeyword(mod.regoVersion, stmt, stmts, i+1); ok { + msg = fmt.Sprintf("%s (hint: `import future.keywords.%s` for `%s` rules)", + msg, kw, headFutureKeywords[kw]) + } + errs = append(errs, NewError(ParseErr, stmt[0].Location, "%s", msg)) continue } rule.generatedBody = true @@ -747,6 +752,66 @@ func parseModule(filename string, stmts []Statement, comments []*Comment, regoCo return mod, nil } +// headFutureKeywords are the future keywords used in a rule head, mapped to an +// example of the rule form each enables. +var headFutureKeywords = map[string]string{ + "if": "p if { ... }", + "contains": "p contains x", +} + +// missingHeadKeyword reports the rule-head future keyword a statement was +// misparsed around. Unimported, the keyword is just a var, so `p if { ... }` +// parses as the body `p` followed by a rule named `if`. idx is stmt's index +// within stmts. +func missingHeadKeyword(v RegoVersion, stmt Body, stmts []Statement, idx int) (string, bool) { + // From v1 on these are ordinary keywords. + if v != RegoV0 { + return "", false + } + + if kw, ok := statementHeadKeyword(stmt); ok { + return kw, true + } + + // The keyword starts its own statement; check the next one on the same line. + if idx+1 >= len(stmts) { + return "", false + } + next := stmts[idx+1] + if next.Loc() == nil || stmt.Loc() == nil || next.Loc().Row != stmt.Loc().Row { + return "", false + } + + return statementHeadKeyword(next) +} + +// statementHeadKeyword returns the rule-head future keyword a statement was +// reduced to: a rule named after it, or a body holding only it as a var. +func statementHeadKeyword(stmt Statement) (string, bool) { + var name Var + + switch stmt := stmt.(type) { + case *Rule: + name = stmt.Head.Name + case Body: + if len(stmt) != 1 { + return "", false + } + term, ok := stmt[0].Terms.(*Term) + if !ok { + return "", false + } + if name, ok = term.Value.(Var); !ok { + return "", false + } + default: + return "", false + } + + _, ok := headFutureKeywords[string(name)] + return string(name), ok +} + func ruleDeclarationHasKeyword(rule *Rule, keyword tokens.Token) bool { return slices.Contains(rule.Head.keywords, keyword) } diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/policy.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/policy.go index 863c9ad59..f66e188b8 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/policy.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/policy.go @@ -36,6 +36,8 @@ var FunctionArgRootDocument = VarTerm("args") // features. var FutureRootDocument = VarTerm("future") +var FutureKeywordsRef = Ref{FutureRootDocument, InternedTerm("keywords")} + // RegoRootDocument names the document containing new, to-become-default, // features in a future versioned release. var RegoRootDocument = VarTerm("rego") @@ -225,7 +227,6 @@ type ( // Rule represents a rule as defined in the language. Rules define the // content of documents that represent policy decisions. Rule struct { - Default bool `json:"default,omitempty"` Head *Head `json:"head"` Body Body `json:"body"` Else *Rule `json:"else,omitempty"` @@ -238,6 +239,7 @@ type ( // on the rule (e.g., printing, comparison, visiting, etc.) Module *Module `json:"-"` + Default bool `json:"default,omitempty"` generatedBody bool } @@ -345,7 +347,7 @@ func (mod *Module) Compare(other *Module) int { if cmp := slices.CompareFunc(mod.Annotations, other.Annotations, (*Annotations).Compare); cmp != 0 { return cmp } - return rulesCompare(mod.Rules, other.Rules) + return slices.CompareFunc(mod.Rules, other.Rules, (*Rule).Compare) } // Copy returns a deep copy of mod. @@ -451,8 +453,7 @@ func (c *Comment) String() string { // Copy returns a deep copy of c. func (c *Comment) Copy() *Comment { cpy := *c - cpy.Text = make([]byte, len(c.Text)) - copy(cpy.Text, c.Text) + cpy.Text = slices.Clone(c.Text) return &cpy } @@ -466,7 +467,7 @@ func (c *Comment) Equal(other *Comment) bool { // Compare returns an integer indicating whether pkg is less than, equal to, // or greater than other. func (pkg *Package) Compare(other *Package) int { - return termSliceCompare(pkg.Path, other.Path) + return slices.CompareFunc(pkg.Path, other.Path, TermValueCompare) } // Copy returns a deep copy of pkg. @@ -511,10 +512,8 @@ func IsValidImportPath(v Value) (err error) { if err := IsValidImportPath(v[0].Value); err != nil { return fmt.Errorf("invalid path %v: path must begin with input or data", v) } - for _, e := range v[1:] { - if _, ok := e.Value.(String); !ok { - return fmt.Errorf("invalid path %v: path elements must be strings", v) - } + if !util.Every(v[1:], TermValueIs[String]) { + return fmt.Errorf("invalid path %v: path elements must be strings", v) } default: return fmt.Errorf("invalid path %v: path must be ref or var", v) @@ -823,19 +822,19 @@ func (head *Head) Compare(other *Head) int { } else if !head.Assign && other.Assign { return 1 } - if cmp := termSliceCompare(head.Args, other.Args); cmp != 0 { + if cmp := slices.CompareFunc(head.Args, other.Args, TermValueCompare); cmp != 0 { return cmp } - if cmp := termSliceCompare(head.Reference, other.Reference); cmp != 0 { + if cmp := slices.CompareFunc(head.Reference, other.Reference, TermValueCompare); cmp != 0 { return cmp } if cmp := VarCompare(head.Name, other.Name); cmp != 0 { return cmp } - if cmp := Compare(head.Key, other.Key); cmp != 0 { + if cmp := TermValueCompare(head.Key, other.Key); cmp != 0 { return cmp } - return Compare(head.Value, other.Value) + return TermValueCompare(head.Value, other.Value) } // Copy returns a deep copy of head. @@ -1077,7 +1076,7 @@ func (expr *Expr) Equal(other *Expr) bool { // // Otherwise, the expression terms are compared normally. If both expressions // have the same terms, the modifiers are compared. -func (expr *Expr) Compare(other *Expr) int { +func (expr *Expr) Compare(other *Expr) (c int) { switch { case expr == other: return 0 @@ -1111,36 +1110,25 @@ func (expr *Expr) Compare(other *Expr) int { switch t := expr.Terms.(type) { case *Term: - if cmp := t.Value.Compare(other.Terms.(*Term).Value); cmp != 0 { - return cmp - } + c = TermValueCompare(t, other.Terms.(*Term)) case []*Term: - if cmp := termSliceCompare(t, other.Terms.([]*Term)); cmp != 0 { - return cmp - } + c = slices.CompareFunc(t, other.Terms.([]*Term), TermValueCompare) case *SomeDecl: - if cmp := Compare(t, other.Terms.(*SomeDecl)); cmp != 0 { - return cmp - } + c = t.Compare(other.Terms.(*SomeDecl)) case *Every: - if cmp := Compare(t, other.Terms.(*Every)); cmp != 0 { - return cmp - } + c = t.Compare(other.Terms.(*Every)) case *Not: - if cmp := t.Compare(other.Terms.(*Not)); cmp != 0 { - return cmp - } + c = t.Compare(other.Terms.(*Not)) case *LogicalAnd: - if cmp := Compare(t, other.Terms.(*LogicalAnd)); cmp != 0 { - return cmp - } + c = t.Compare(other.Terms.(*LogicalAnd)) case *LogicalOr: - if cmp := Compare(t, other.Terms.(*LogicalOr)); cmp != 0 { - return cmp - } + c = t.Compare(other.Terms.(*LogicalOr)) } - return withSliceCompare(expr.With, other.With) + if c == 0 { + c = slices.CompareFunc(expr.With, other.With, (*With).Compare) + } + return c } func (expr *Expr) sortOrder() int { @@ -1208,9 +1196,7 @@ func (expr *Expr) Hash() int { case *SomeDecl: s += ts.Hash() case []*Term: - for _, t := range ts { - s += t.Value.Hash() - } + s += termSliceHash(ts) case *Term: s += ts.Value.Hash() case *LogicalAnd: @@ -1343,10 +1329,8 @@ func (expr *Expr) Operands() []*Term { func (expr *Expr) IsGround() bool { switch ts := expr.Terms.(type) { case []*Term: - for _, t := range ts[1:] { - if !t.IsGround() { - return false - } + if !util.Every(ts[1:], (*Term).IsGround) { + return false } case *Term: return ts.IsGround() @@ -1471,7 +1455,7 @@ func (d *SomeDecl) Copy() *SomeDecl { // Compare returns an integer indicating whether d is less than, equal to, or // greater than other. func (d *SomeDecl) Compare(other *SomeDecl) int { - return termSliceCompare(d.Symbols, other.Symbols) + return slices.CompareFunc(d.Symbols, other.Symbols, TermValueCompare) } // Hash returns a hash code of d. @@ -1519,7 +1503,7 @@ func (q *Every) Compare(other *Every) int { {q.Value, other.Value}, {q.Domain, other.Domain}, } { - if d := Compare(terms[0], terms[1]); d != 0 { + if d := TermValueCompare(terms[0], terms[1]); d != 0 { return d } } @@ -1699,18 +1683,19 @@ func (w *With) Equal(other *With) bool { // Compare returns an integer indicating whether w is less than, equal to, or // greater than other. func (w *With) Compare(other *With) int { + if w == other { + return 0 + } if w == nil { - if other == nil { - return 0 - } return -1 - } else if other == nil { + } + if other == nil { return 1 } - if cmp := w.Target.Value.Compare(other.Target.Value); cmp != 0 { + if cmp := TermValueCompare(w.Target, other.Target); cmp != 0 { return cmp } - return w.Value.Value.Compare(other.Value.Value) + return TermValueCompare(w.Value, other.Value) } // Copy returns a deep copy of w. @@ -1780,6 +1765,12 @@ func Copy(x any) any { return x.Copy() case *ObjectComprehension: return x.Copy() + case *LogicalAnd: + return x.Copy() + case *LogicalOr: + return x.Copy() + case *TemplateString: + return x.Copy() case Set: return x.Copy() case *object: @@ -1820,12 +1811,7 @@ func (rs *RuleSet) Add(rule *Rule) { // Contains returns true if rs contains rule. func (rs RuleSet) Contains(rule *Rule) bool { - for i := range rs { - if rs[i].Equal(rule) { - return true - } - } - return false + return slices.ContainsFunc(rs, rule.Equal) } // Diff returns a new RuleSet containing rules in rs that are not in other. @@ -1846,10 +1832,7 @@ func (rs RuleSet) Equal(other RuleSet) bool { // Merge returns a ruleset containing the union of rules from rs an other. func (rs RuleSet) Merge(other RuleSet) RuleSet { - result := NewRuleSet() - for i := range rs { - result.Add(rs[i]) - } + result := NewRuleSet(rs...) for i := range other { result.Add(other[i]) } diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/policy_appenders.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/policy_appenders.go index ccc0554ad..2373d8a89 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/policy_appenders.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/policy_appenders.go @@ -21,7 +21,9 @@ func (mod *Module) AppendText(buf []byte) ([]byte, error) { // rule annotations are attached to rules, so only check for package scoped ones here if annotations.Scope == "package" || annotations.Scope == "subpackages" { buf = append(buf, "# METADATA\n# "...) - buf = append(buf, annotations.String()...) + if buf, err = annotations.AppendText(buf); err != nil { + return nil, err + } buf = append(buf, '\n') } } @@ -98,7 +100,10 @@ func (rule *Rule) appendWithOpts(opts toStringOpts, buf []byte) ([]byte, error) // See note in [Module.AppendText] regarding annotations. for _, annotations := range rule.Annotations { buf = append(buf, "# METADATA\n# "...) - buf = append(buf, annotations.String()...) + var err error + if buf, err = annotations.AppendText(buf); err != nil { + return nil, err + } buf = append(buf, '\n') } diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/rego_v1.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/rego_v1.go index db9e0f722..64fe23bb5 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/rego_v1.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/rego_v1.go @@ -33,14 +33,15 @@ func checkRootDocumentOverrides(node any) Errors { } if ReservedVars.Contains(name) { - errors = append(errors, NewError(CompileErr, rule.Location, "rules must not shadow %v (use a different rule name)", name)) + errors = append(errors, + NewError(CompileErr, rule.Location, "rules must not shadow %v (use a different rule name)", name)) } for _, arg := range rule.Head.Args { - if _, ok := arg.Value.(Ref); ok { - if RootDocumentRefs.Contains(arg) { - errors = append(errors, NewError(CompileErr, arg.Location, "args must not shadow %v (use a different variable name)", arg)) - } + if _, ok := arg.Value.(Ref); ok && RootDocumentRefs.Contains(arg) { + errors = append(errors, NewError( + CompileErr, arg.Location, "args must not shadow %v (use a different variable name)", arg, + )) } } @@ -49,11 +50,12 @@ func checkRootDocumentOverrides(node any) Errors { WalkExprs(node, func(expr *Expr) bool { if expr.IsAssignment() { - // assign() can be called directly, so we need to assert its given first operand exists before checking its name. + // assign() can be called directly, so assert its given first operand exists before checking its name. if nameOp := expr.Operand(0); nameOp != nil { - name := Var(nameOp.String()) - if ReservedVars.Contains(name) { - errors = append(errors, NewError(CompileErr, expr.Location, "variables must not shadow %v (use a different variable name)", name)) + if name := Var(nameOp.String()); ReservedVars.Contains(name) { + errors = append(errors, NewError( + CompileErr, expr.Location, "variables must not shadow %v (use a different variable name)", name, + )) } } } diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/term.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/term.go index 6e4503d4d..5a29c628e 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/term.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/term.go @@ -244,7 +244,7 @@ func valueToInterface(v Value, resolver Resolver, opt JSONOpt) (any, error) { } return v.native, nil case Set: - buf := []any{} + buf := make([]any, 0, v.Len()) iter := func(x *Term) error { x1, err := valueToInterface(x.Value, resolver, opt) if err != nil { @@ -441,6 +441,12 @@ func TermValueIs[T Value](term *Term) (ok bool) { return ok } +// ToTerm exists solely to be able to map concrete Value +// implementations to *Term in util.Map, util.MapKeys, etc. +func ToTerm[T Value](v T) *Term { + return NewTerm(v) +} + // IsConstant returns true if the AST value is constant. // Note that this is only a shallow check as we currently don't have a real // notion of constant "vars" in the AST implementation. Meaning that while we could @@ -1197,8 +1203,7 @@ func (ref Ref) Concat(terms []*Term) Ref { // Dynamic returns the offset of the first non-constant operand of ref. func (ref Ref) Dynamic() int { - switch ref[0].Value.(type) { - case Call: + if TermValueIs[Call](ref[0]) { return 0 } for i := 1; i < len(ref); i++ { @@ -1235,27 +1240,15 @@ func (ref Ref) CopyNonGround() Ref { // Equal returns true if ref is equal to other. func (ref Ref) Equal(other Value) bool { - switch o := other.(type) { - case Ref: - if len(ref) == len(o) { - for i := range ref { - if !ref[i].Equal(o[i]) { - return false - } - } - - return true - } - } - - return false + o, ok := other.(Ref) + return ok && slices.EqualFunc(ref, o, (*Term).Equal) } // Compare compares ref to other, return <0, 0, or >0 if it is less than, equal to, // or greater than other. func (ref Ref) Compare(other Value) int { if o, ok := other.(Ref); ok { - return termSliceCompare(ref, o) + return slices.CompareFunc(ref, o, TermValueCompare) } return valueTypeCompare(ref, other) } @@ -1515,7 +1508,7 @@ func (arr *Array) Equal(other Value) bool { // or greater than other. func (arr *Array) Compare(other Value) int { if b, ok := other.(*Array); ok { - return termSliceCompare(arr.elems, b.elems) + return slices.CompareFunc(arr.elems, b.elems, TermValueCompare) } return valueTypeCompare(arr, other) @@ -1568,9 +1561,11 @@ func (arr *Array) Sorted() *Array { slices.SortFunc(cpy, TermValueCompare) - a := NewArray(cpy...) - a.hashs = arr.hashs - return a + // NewArray has already hashed cpy in its own order. Taking arr.hashs over + // that would leave hashs[i] holding the hash of some other element, which + // Array.set relies on, and would share the slice with arr so that setting + // an element here corrupted arr. + return NewArray(cpy...) } // Hash returns the hash code for the Value. @@ -1615,14 +1610,25 @@ func (arr *Array) rehash() { func (arr *Array) set(i int, v *Term) { arr.ground = arr.ground && v.IsGround() arr.elems[i] = v - arr.hashs[i] = v.Value.Hash() - arr.rehash() + + // arr.hash is the sum of arr.hashs, so swapping one element's hash in is + // enough -- rehashing the whole array here makes building an array of n + // elements O(n^2), which is felt on the large arrays that appear in + // generated policies. + h := v.Value.Hash() + arr.hash += h - arr.hashs[i] + arr.hashs[i] = h } // Slice returns a slice of arr starting from i index to j. -1 // indicates the end of the array. The returned value array is not a // copy and any modifications to either of arrays may be reflected to // the other. +// +// Set on the returned slice writes through to arr's element and to its +// hash, but not to arr's cached sum of those hashes, so arr.Hash() is +// stale from then on and anything holding arr as a map key or set member +// stops finding it. Copy the slice before writing to it. func (arr *Array) Slice(i, j int) *Array { var elems []*Term var hashs []int @@ -1667,10 +1673,11 @@ func (arr *Array) Foreach(f func(*Term)) { // Append appends a term to arr, returning the appended array. func (arr *Array) Append(v *Term) *Array { + vhs := v.Value.Hash() cpy := *arr cpy.elems = append(arr.elems, v) - cpy.hashs = append(arr.hashs, v.Value.Hash()) - cpy.hash = arr.hash + v.Value.Hash() + cpy.hashs = append(arr.hashs, vhs) + cpy.hash += vhs cpy.ground = arr.ground && v.IsGround() return &cpy } @@ -1897,13 +1904,9 @@ func (s *set) Foreach(f func(*Term)) { // Map returns a new Set obtained by applying f to each value in s. func (s *set) Map(f func(*Term) (*Term, error)) (Set, error) { - mapped := make([]*Term, 0, len(s.keys)) - for _, x := range s.sortedKeys() { - term, err := f(x) - if err != nil { - return nil, err - } - mapped = append(mapped, term) + mapped, err := util.TryMap(s.sortedKeys(), f) + if err != nil { + return nil, err } return NewSet(mapped...), nil } @@ -2193,12 +2196,7 @@ func (lob *lazyObj) Keys() []*Term { if lob.strict != nil { return lob.strict.Keys() } - ret := make([]*Term, 0, len(lob.native)) - for k := range lob.native { - ret = append(ret, InternedTerm(k)) - } - - return util.SortedFunc(ret, TermValueCompare) + return util.SortedFunc(util.MapKeys(lob.native, InternedTerm), TermValueCompare) } func (lob *lazyObj) KeysIterator() ObjectKeysIterator { @@ -2982,7 +2980,7 @@ func (c Call) Copy() Call { // or greater than other. func (c Call) Compare(other Value) int { if oc, ok := other.(Call); ok { - return termSliceCompare(c, oc) + return slices.CompareFunc(c, oc, TermValueCompare) } return valueTypeCompare(c, other) } @@ -3072,18 +3070,6 @@ func termSliceCopy(a []*Term) []*Term { return cpy } -func termSliceEqual(a, b []*Term) bool { - if len(a) == len(b) { - for i := range a { - if !a[i].Equal(b[i]) { - return false - } - } - return true - } - return false -} - func termSliceHash(a []*Term) int { var hash int for _, v := range a { diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/transform.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/transform.go index 84e970001..36f414e54 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/transform.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/transform.go @@ -32,6 +32,11 @@ func Transform(t Transformer, x any) (any, error) { return nil, nil } + // The cases below that hold a slice mutate it in place, so this interface + // value goes on describing what they produce. Returning it costs nothing, + // where returning the case variable would box a slice header afresh. + orig := y + var ok bool switch y := y.(type) { case *Module: @@ -137,7 +142,7 @@ func Transform(t Transformer, x any) (any, error) { return nil, err } } - return y, nil + return orig, nil case Body: for i, e := range y { e, err := Transform(t, e) @@ -148,7 +153,7 @@ func Transform(t Transformer, x any) (any, error) { return nil, fmt.Errorf("illegal transform: %T != %T", y[i], e) } } - return y, nil + return orig, nil case *Expr: switch ts := y.Terms.(type) { case *SomeDecl: @@ -238,7 +243,7 @@ func Transform(t Transformer, x any) (any, error) { return nil, err } } - return y, nil + return orig, nil case *object: return y.Map(func(k, v *Term) (*Term, *Term, error) { k, err := transformTerm(t, k) @@ -260,14 +265,10 @@ func Transform(t Transformer, x any) (any, error) { y.set(i, v) } return y, nil - case Set: - y, err = y.Map(func(term *Term) (*Term, error) { + case *set: + return y.Map(func(term *Term) (*Term, error) { return transformTerm(t, term) }) - if err != nil { - return nil, err - } - return y, nil case *ArrayComprehension: if y.Term, err = transformTerm(t, y.Term); err != nil { return nil, err @@ -301,7 +302,7 @@ func Transform(t Transformer, x any) (any, error) { return nil, err } } - return y, nil + return orig, nil case *TemplateString: for i := range y.Parts { if expr, ok := y.Parts[i].(*Expr); ok { @@ -322,29 +323,29 @@ func Transform(t Transformer, x any) (any, error) { // TransformRefs calls the function f on all references under x. func TransformRefs(x any, f func(Ref) (Value, error)) (any, error) { - t := NewGenericTransformer(func(x any) (any, error) { + t := GenericTransformer{f: func(x any) (any, error) { if r, ok := x.(Ref); ok { return f(r) } return x, nil - }) + }} return Transform(t, x) } // TransformVars calls the function f on all vars under x. func TransformVars(x any, f func(Var) (Value, error)) (any, error) { - t := NewGenericTransformer(func(x any) (any, error) { + t := GenericTransformer{f: func(x any) (any, error) { if v, ok := x.(Var); ok { return f(v) } return x, nil - }) + }} return Transform(t, x) } // TransformComprehensions calls the function f on all comprehensions under x. func TransformComprehensions(x any, f func(any) (Value, error)) (any, error) { - t := NewGenericTransformer(func(x any) (any, error) { + t := GenericTransformer{f: func(x any) (any, error) { switch x := x.(type) { case *ArrayComprehension: return f(x) @@ -354,7 +355,7 @@ func TransformComprehensions(x any, f func(any) (Value, error)) (any, error) { return f(x) } return x, nil - }) + }} return Transform(t, x) } @@ -367,13 +368,11 @@ type GenericTransformer struct { // NewGenericTransformer returns a new GenericTransformer that will transform // AST nodes using the function f. func NewGenericTransformer(f func(x any) (any, error)) *GenericTransformer { - return &GenericTransformer{ - f: f, - } + return &GenericTransformer{f: f} } // Transform calls the function f on the GenericTransformer. -func (t *GenericTransformer) Transform(x any) (any, error) { +func (t GenericTransformer) Transform(x any) (any, error) { return t.f(x) } @@ -414,11 +413,24 @@ func transformBody(t Transformer, body Body) (Body, error) { } func transformTerm(t Transformer, term *Term) (*Term, error) { - v, err := transformValue(t, term.Value) + tv, err := transformValue(t, term.Value) if err != nil { return nil, err } - return &Term{Value: v, Location: term.Location}, nil + + // If the term was interned, make sure to return a new one instead + // of replacing the value of the interned term, as that'll be used + // elsewhere, leading to data races + if s, ok := tv.(String); ok { + if it, ok := internedStringTerms[string(s)]; ok && term == it { + return &Term{Value: tv, Location: term.Location}, nil + } + } + + // Not interned = modify the value in place + term.Value = tv + + return term, err } func transformValue(t Transformer, v Value) (Value, error) { diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/unify.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/unify.go index 67b89a2a9..877b576eb 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/unify.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/unify.go @@ -115,8 +115,7 @@ func (u *unifier) unify(a *Term, b *Term) { u.markAllSafe(b) } case *SetComprehension: - switch b := b.Value.(type) { - case Var: + if b, ok := b.Value.(Var); ok { u.markSafe(b) } @@ -166,9 +165,8 @@ func (u *unifier) unify(a *Term, b *Term) { } default: - switch b := b.Value.(type) { - case Var: - u.markSafe(b) + if v, ok := b.Value.(Var); ok { + u.markSafe(v) } } } diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/visit.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/visit.go index c054b92b2..c291bcdc5 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/visit.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/ast/visit.go @@ -48,6 +48,7 @@ type ( SkipWithTarget bool SkipSets bool SkipTemplateStrings bool + SkipWildcardVars bool customVisit func(vis *VarVisitor, v any) bool } @@ -191,9 +192,9 @@ func walk(v Visitor, x any) { Walk(w, t) }) case Set: - x.Foreach(func(t *Term) { + for _, t := range x.Slice() { Walk(w, t) - }) + } case *ArrayComprehension: Walk(w, x.Term) Walk(w, x.Body) @@ -425,10 +426,10 @@ func (tv *typeVisitor[T]) walk(x any, visit func(x T) bool) { tv.walk(x[i], visit) } case *object: - x.Foreach(func(k, v *Term) { - tv.walk(k, visit) - tv.walk(v, visit) - }) + for _, node := range x.sortedKeys() { + tv.walk(node.key, visit) + tv.walk(node.value, visit) + } case Object: for _, k := range x.Keys() { tv.walk(k, visit) @@ -570,10 +571,10 @@ func (vis *GenericVisitor) Walk(x any) { vis.Walk(x[i]) } case *object: - x.Foreach(func(k, _ *Term) { - vis.Walk(k) - vis.Walk(x.Get(k)) - }) + for _, node := range x.sortedKeys() { + vis.Walk(node.key) + vis.Walk(node.value) + } case Object: for _, k := range x.Keys() { vis.Walk(k) @@ -822,6 +823,13 @@ func (vis *VarVisitor) Vars() VarSet { // the visitor will _skip_ that branch of the AST func (vis *VarVisitor) visit(v any) bool { if vis.params.SkipObjectKeys { + if o, ok := v.(*object); ok { + // doesn't allocate / escape + for _, node := range o.sortedKeys() { + vis.Walk(node.value) + } + return true + } if o, ok := v.(Object); ok { o.Foreach(func(_, v *Term) { vis.Walk(v) @@ -910,6 +918,9 @@ func (vis *VarVisitor) visit(v any) bool { } } if v, ok := v.(Var); ok { + if vis.params.SkipWildcardVars && v.IsWildcard() { + return true + } vis.Add(v) return true } @@ -1032,7 +1043,7 @@ func (vis *VarVisitor) Walk(x any) { vis.Walk(x.Parts[i]) } case *Not: - vis.Walk(x.Body) + vis.WalkBody(x.Body) case *LogicalAnd: vis.WalkBody(x.Lhs) vis.WalkBody(x.Rhs) diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/bundle/bundle.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/bundle/bundle.go index c56cd122a..289ba274d 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/bundle/bundle.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/bundle/bundle.go @@ -18,6 +18,7 @@ import ( "path" "path/filepath" "reflect" + "slices" "strings" "sync" @@ -165,7 +166,7 @@ type Manifest struct { } type fileRegoVersion struct { - path glob.Glob + path *glob.Pattern version int } @@ -339,7 +340,7 @@ func (ss stringSet) Equal(other stringSet) bool { return true } -func (m *Manifest) validateAndInjectDefaults(b Bundle) error { +func (m *Manifest) validateAndInjectDefaults(b *Bundle) error { m.Init() // Validate roots in bundle. @@ -680,7 +681,7 @@ func (r *Reader) Read() (Bundle, error) { // Normalize the paths to use `/` separators path := filepath.ToSlash(f.Path()) - if strings.HasSuffix(path, RegoExt) { + if strings.HasSuffix(path, RegoExt) { //nolint: gocritic // ifElseChain fullPath := r.fullPath(path) bs := buf.Bytes() @@ -837,7 +838,7 @@ func (r *Reader) Read() (Bundle, error) { "file(s) %v specified in bundle signatures but not found in the target bundle", util.Keys(r.files)) } - if err := bundle.Manifest.validateAndInjectDefaults(*bundle); err != nil { + if err := bundle.Manifest.validateAndInjectDefaults(bundle); err != nil { return empty, err } @@ -1411,23 +1412,18 @@ func (b Bundle) Equal(other Bundle) bool { // Copy returns a deep copy of the bundle. func (b Bundle) Copy() Bundle { - // Copy data. var x any = b.Data - - if err := util.RoundTrip(&x); err != nil { + if err := util.RoundTripFast(&x); err != nil { panic(err) } - if x != nil { b.Data = x.(map[string]any) } // Copy modules. for i := range b.Modules { - bs := make([]byte, len(b.Modules[i].Raw)) - copy(bs, b.Modules[i].Raw) - b.Modules[i].Raw = bs + b.Modules[i].Raw = slices.Clone(b.Modules[i].Raw) b.Modules[i].Parsed = b.Modules[i].Parsed.Copy() } @@ -1556,12 +1552,14 @@ func MergeWithRegoVersion(bundles []*Bundle, regoVersion ast.RegoVersion, usePat return result, nil } - var roots []string - var result Bundle + var ( + roots []string + planFile string + manifestProto bool + manifestProtoSet bool + ) - var planFile string - var manifestProto bool - var manifestProtoSet bool + result := &Bundle{} for _, b := range bundles { if b.Manifest.Roots == nil { @@ -1632,7 +1630,7 @@ func MergeWithRegoVersion(bundles []*Bundle, regoVersion ast.RegoVersion, usePat return nil, err } - return &result, nil + return result, nil } func bundleRegoVersions(bundle *Bundle, regoVersion ast.RegoVersion, usePath bool) (map[string]int, error) { diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/bundle/file.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/bundle/file.go index beb2e4664..44a0a7797 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/bundle/file.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/bundle/file.go @@ -486,11 +486,16 @@ func NewIterator(raw []Raw) storage.Iterator { func getdepth(path string, isDir bool) int { if isDir { cleanedPath := strings.Trim(filepath.ToSlash(path), "/") - return len(strings.Split(cleanedPath, "/")) + return segmentCount(cleanedPath) } basePath := strings.Trim(filepath.Dir(filepath.ToSlash(path)), "/") - return len(strings.Split(basePath, "/")) + return segmentCount(basePath) +} + +// segmentCount avoids the []string allocation of len(strings.Split(path, "/")). +func segmentCount(path string) int { + return strings.Count(path, "/") + 1 } func getFileStoragePath(path string) (storage.Path, error) { diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/bundle/hash.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/bundle/hash.go index dd9dfe514..66ce6a9ce 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/bundle/hash.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/bundle/hash.go @@ -78,7 +78,7 @@ func NewSignatureHasher(alg HashingAlgorithm) (SignatureHasher, error) { // HashFile hashes the file content, JSON or binary, both in golang native format. func (h *hasher) HashFile(v any) ([]byte, error) { hf := h.h() - walk(v, hf) + walk(v, hf, newPrimitiveEncoder()) return hf.Sum(nil), nil } @@ -91,7 +91,7 @@ func (h *hasher) HashFile(v any) ([]byte, error) { // object: Hash {, then each key (in alphabetical order) and digest of the value, then comma (between items) and finally }. // // array: Hash [, then digest of the value, then comma (between items) and finally ]. -func walk(v any, h io.Writer) { +func walk(v any, h io.Writer, pe *primitiveEncoder) { switch x := v.(type) { case map[string]any: @@ -102,9 +102,9 @@ func walk(v any, h io.Writer) { _, _ = h.Write([]byte(",")) } - _, _ = h.Write(encodePrimitive(key)) + _, _ = h.Write(pe.encode(key)) _, _ = h.Write([]byte(":")) - walk(x[key], h) + walk(x[key], h, pe) } _, _ = h.Write([]byte("}")) @@ -115,21 +115,38 @@ func walk(v any, h io.Writer) { if i > 0 { _, _ = h.Write([]byte(",")) } - walk(e, h) + walk(e, h, pe) } _, _ = h.Write([]byte("]")) case []byte: _, _ = h.Write(x) default: - _, _ = h.Write(encodePrimitive(x)) + _, _ = h.Write(pe.encode(x)) } } +// primitiveEncoder reuses its buffer across encode calls. +type primitiveEncoder struct { + buf *bytes.Buffer + enc *json.Encoder +} + +func newPrimitiveEncoder() *primitiveEncoder { + buf := new(bytes.Buffer) + enc := json.NewEncoder(buf) + enc.SetEscapeHTML(false) + return &primitiveEncoder{buf: buf, enc: enc} +} + +// encode's return value aliases the encoder's buffer and is only valid +// until the next call. +func (pe *primitiveEncoder) encode(v any) []byte { + pe.buf.Reset() + _ = pe.enc.Encode(v) + return bytes.Trim(pe.buf.Bytes(), "\n") +} + func encodePrimitive(v any) []byte { - var buf bytes.Buffer - encoder := json.NewEncoder(&buf) - encoder.SetEscapeHTML(false) - _ = encoder.Encode(v) - return bytes.Trim(buf.Bytes(), "\n") + return newPrimitiveEncoder().encode(v) } diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/bundle/store.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/bundle/store.go index c5726986c..7d283f87b 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/bundle/store.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/bundle/store.go @@ -992,60 +992,6 @@ func compileModules(compiler *ast.Compiler, m metrics.Metrics, bundles map[strin return iCompiler.VerifyAuthorizationPolicySchema(compiler, authorizationDecisionRef) } -func writeModules(ctx context.Context, store storage.Store, txn storage.Transaction, compiler *ast.Compiler, m metrics.Metrics, bundles map[string]*Bundle, extraModules map[string]*ast.Module, legacy bool, externalSources *util.HasherMap[ast.Ref, ast.ExternalRuleSource]) error { - m.Timer(metrics.RegoModuleCompile).Start() - defer m.Timer(metrics.RegoModuleCompile).Stop() - - // Apply external sources before compilation - if externalSources != nil { - externalSources.Iter(func(ref ast.Ref, source ast.ExternalRuleSource) bool { - compiler = compiler.WithExternalSource(ref, source) - return false - }) - } - - modules := map[string]*ast.Module{} - - // preserve any modules already on the compiler - maps.Copy(modules, compiler.Modules) - - // preserve any modules passed in from the store - maps.Copy(modules, extraModules) - - // include all the new bundle modules - for bundleName, b := range bundles { - if legacy { - for _, mf := range b.Modules { - modules[mf.Path] = mf.Parsed - } - } else { - maps.Copy(modules, b.ParsedModules(bundleName)) - } - } - - if compiler.Compile(modules); compiler.Failed() { - return compiler.Errors - } - for bundleName, b := range bundles { - for _, mf := range b.Modules { - var path string - - // For backwards compatibility, in legacy mode, upsert policies to - // the unprefixed path. - if legacy { - path = mf.Path - } else { - path = modulePathWithPrefix(bundleName, mf.Path) - } - - if err := store.UpsertPolicy(ctx, txn, path, mf.Raw); err != nil { - return err - } - } - } - return nil -} - func lookup(path storage.Path, data map[string]any) (any, bool) { if len(path) == 0 { return data, true diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/format/format.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/format/format.go index 860fb1a9e..b91ba6ff2 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/format/format.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/format/format.go @@ -28,6 +28,7 @@ const defaultLocationFile = "__format_default__" var ( expandedConst = ast.NewBody(ast.NewExpr(ast.InternedTerm(true))) commentsSlicePool = util.NewSlicePool[*ast.Comment](50) + negativeRow = &ast.Location{Row: -1} ) // Opts lets you control the code formatting via `AstWithOpts()`. @@ -282,7 +283,7 @@ func AstWithOpts(x any, opts Opts) ([]byte, error) { switch x := x.(type) { case *ast.Module: if regoVersion == ast.RegoV1 && opts.DropV0Imports { - x.Imports = filterRegoV1Import(x.Imports) + x.Imports = slices.DeleteFunc(x.Imports, regoV1Import) } else if regoVersion == ast.RegoV0CompatV1 { x.Imports = ensureRegoV1Import(x.Imports) } @@ -509,10 +510,7 @@ func (w *writer) writeModule(module *ast.Module) error { return err } rules, others = gatherRules(others) - comments, err = w.writeRules(rules, comments) - if err != nil { - return err - } + comments = w.writeRules(rules, comments) } for i, c := range comments { @@ -593,17 +591,19 @@ func (w *writer) writeComments(comments []*ast.Comment) error { return nil } -func (w *writer) writeRules(rules []*ast.Rule, comments []*ast.Comment) ([]*ast.Comment, error) { +func (w *writer) writeRules(rules []*ast.Rule, comments []*ast.Comment) []*ast.Comment { for i, rule := range rules { var err error - comments, err = w.insertComments(comments, rule.Location) - if err != nil && !errors.As(err, &unexpectedCommentError{}) { - w.errs = append(w.errs, ast.NewError(ast.FormatErr, &ast.Location{}, "%s", err.Error())) + if comments, err = w.insertComments(comments, rule.Location); err != nil { + if _, ok := errors.AsType[unexpectedCommentError](err); !ok { + w.errs = append(w.errs, ast.NewError(ast.FormatErr, &ast.Location{}, "%s", err.Error())) + } } - comments, err = w.writeRule(rule, false, comments) - if err != nil && !errors.As(err, &unexpectedCommentError{}) { - w.errs = append(w.errs, ast.NewError(ast.FormatErr, &ast.Location{}, "%s", err.Error())) + if comments, err = w.writeRule(rule, false, comments); err != nil { + if _, ok := errors.AsType[unexpectedCommentError](err); !ok { + w.errs = append(w.errs, ast.NewError(ast.FormatErr, &ast.Location{}, "%s", err.Error())) + } } if i < len(rules)-1 && w.groupableOneLiner(rule) { @@ -616,7 +616,7 @@ func (w *writer) writeRules(rules []*ast.Rule, comments []*ast.Comment) ([]*ast. } w.blankLine() } - return comments, nil + return comments } // groupableOneLiner reports whether rule is written on a single line, and so may @@ -671,9 +671,7 @@ func (w *writer) writeRule(rule *ast.Rule, isElse bool, comments []*ast.Comment) var unexpectedComment bool comments, err = w.writeHead(rule.Head, rule.Default, isExpandedConst, comments) if err != nil { - if errors.As(err, &unexpectedCommentError{}) { - unexpectedComment = true - } else { + if unexpectedComment = isUnexpectedCommentError(err); !unexpectedComment { return nil, err } } @@ -707,7 +705,13 @@ func (w *writer) writeRule(rule *ast.Rule, isElse bool, comments []*ast.Comment) var err error comments, err = w.writeExpr(rule.Body[0], comments) if err != nil { - return nil, err + // An unexpected comment isn't fatal: the expression was + // written as-is, and the comments returned still need + // writing. Dropping them would lose every comment after + // this rule. + if _, ok := errors.AsType[unexpectedCommentError](err); !ok { + return nil, err + } } w.endLine() if rule.Else != nil { @@ -739,7 +743,7 @@ func (w *writer) writeRule(rule *ast.Rule, isElse bool, comments []*ast.Comment) comments, err = w.writeBody(rule.Body, comments) if err != nil { // the unexpected comment error is passed up to be handled by writeHead - if !errors.As(err, &unexpectedCommentError{}) { + if _, ok := errors.AsType[unexpectedCommentError](err); !ok { return nil, err } } @@ -875,10 +879,7 @@ func (w *writer) writeHead(head *ast.Head, isDefault bool, isExpandedConst bool, if len(head.Args) > 0 { w.write("(") - var args []any - for _, arg := range head.Args { - args = append(args, arg) - } + args := util.ToSliceOf[any](head.Args) var err error comments, err = w.writeIterable(args, head.Location, closingLoc(0, 0, '(', ')', head.Location), comments, w.listWriter(false)) w.write(")") @@ -976,9 +977,10 @@ func (w *writer) writeBody(body ast.Body, comments []*ast.Comment) ([]*ast.Comme } w.startLine() - comments, err = w.writeExpr(expr, comments) - if err != nil && !errors.As(err, &unexpectedCommentError{}) { - w.errs = append(w.errs, ast.NewError(ast.FormatErr, &ast.Location{}, "%s", err.Error())) + if comments, err = w.writeExpr(expr, comments); err != nil { + if _, ok := errors.AsType[unexpectedCommentError](err); !ok { + w.errs = append(w.errs, ast.NewError(ast.FormatErr, &ast.Location{}, "%s", err.Error())) + } } w.endLine() } @@ -1209,11 +1211,9 @@ func (w *writer) writeEvery(every *ast.Every, loc *ast.Location, comments []*ast } w.write(" {") comments, err = w.writeComprehensionBody('{', '}', every.Body, loc, loc, comments) - if err != nil { + if err != nil && !isUnexpectedCommentError(err) { // the unexpected comment error is passed up to be handled by writeHead - if !errors.As(err, &unexpectedCommentError{}) { - return nil, err - } + return nil, err } if len(every.Body) == 1 && @@ -1246,10 +1246,8 @@ func (w *writer) writeNot(not *ast.Not, loc *ast.Location, comments []*ast.Comme w.write("{") comments, err = w.writeComprehensionBody('{', '}', not.Body, loc, loc, comments) - if err != nil { - if !errors.As(err, &unexpectedCommentError{}) { - return nil, err - } + if err != nil && !isUnexpectedCommentError(err) { + return nil, err } if last := not.Body[len(not.Body)-1]; last.Location != nil && last.Location.Row == loc.Row { @@ -1263,10 +1261,8 @@ func (w *writer) writeNot(not *ast.Not, loc *ast.Location, comments []*ast.Comme } comments, err = w.writeExpr(not.Body[0], comments) - if err != nil { - if !errors.As(err, &unexpectedCommentError{}) { - return nil, err - } + if err != nil && !isUnexpectedCommentError(err) { + return nil, err } if parens { @@ -1345,7 +1341,7 @@ func (w *writer) writeLogical(expr *ast.Expr, comments []*ast.Comment) ([]*ast.C lhs, steps := flattenLogical(expr) comments, err := w.writeLogicalOperand(lhs, comments) - if err != nil && !errors.As(err, &unexpectedCommentError{}) { + if err != nil && !isUnexpectedCommentError(err) { return comments, err } @@ -1367,7 +1363,7 @@ func (w *writer) writeLogical(expr *ast.Expr, comments []*ast.Comment) ([]*ast.C } comments, err = w.writeLogicalOperand(s.rhs, comments) - if err != nil && !errors.As(err, &unexpectedCommentError{}) { + if err != nil && !isUnexpectedCommentError(err) { return comments, err } } @@ -1398,10 +1394,8 @@ func (w *writer) writeLogicalOperand(o logicalOperand, comments []*ast.Comment) w.write("{") comments, err := w.writeComprehensionBody('{', '}', o.body, o.brace, o.brace, comments) - if err != nil { - if !errors.As(err, &unexpectedCommentError{}) { - return comments, err - } + if err != nil && !isUnexpectedCommentError(err) { + return comments, err } if last := o.body[len(o.body)-1]; last.Location != nil && last.Location.Row == o.brace.Row { @@ -1597,7 +1591,7 @@ func (w *writer) writeFunctionCallPlain(terms []*ast.Term, comments []*ast.Comme w.write("(") defer w.write(")") - args := util.ToSliceOfAny(terms[1:]) + args := util.ToSliceOf[any](terms[1:]) loc := terms[0].Location var err error comments, err = w.writeIterable(args, loc, closingLoc(0, 0, '(', ')', loc), comments, w.listWriter(false)) @@ -1623,14 +1617,12 @@ func (w *writer) writeWith(with *ast.With, comments []*ast.Comment, indented boo } w.write(" as ") comments, err = w.writeTerm(with.Value, comments) - if err != nil { + if err != nil && !isUnexpectedCommentError(err) { // An unexpectedCommentError from writeTerm signals that it fell // back to writing the term's original unformatted text — the value // was written successfully, so don't abort the surrounding chain // of `with` clauses (issue #8765). - if !errors.As(err, &unexpectedCommentError{}) { - return comments, err - } + return comments, err } return comments, nil } @@ -1659,7 +1651,7 @@ func (w *writer) writeTerm(term *ast.Term, comments []*ast.Comment) ([]*ast.Comm comments, err := w.writeTermParens(false, term, comments) if err != nil { - if errors.As(err, &unexpectedCommentError{}) { + if isUnexpectedCommentError(err) { w.buf.Truncate(currentLen) w.level = currentLevel @@ -1921,7 +1913,7 @@ func (w *writer) writeRef(x ast.Ref, comments []*ast.Comment) ([]*ast.Comment, e w.write("[") comments, err = w.writeTerm(t, comments) if err != nil { - if errors.As(err, &unexpectedCommentError{}) { + if _, ok := errors.AsType[unexpectedCommentError](err); ok { // add a new line so that the closing bracket isn't part of the unexpected comment w.write("\n") } else { @@ -2071,7 +2063,7 @@ func (w *writer) writeObject(obj ast.Object, loc *ast.Location, comments []*ast. w.write("{") defer w.write("}") - var s []any + s := make([]any, 0, obj.Len()) obj.Foreach(func(k, v *ast.Term) { s = append(s, ast.Item(k, v)) }) @@ -2082,7 +2074,7 @@ func (w *writer) writeArray(arr *ast.Array, loc *ast.Location, comments []*ast.C w.write("[") defer w.write("]") - var s []any + s := make([]any, 0, arr.Len()) arr.Foreach(func(t *ast.Term) { s = append(s, t) }) @@ -2095,10 +2087,9 @@ func (w *writer) writeArray(arr *ast.Array, loc *ast.Location, comments []*ast.C } func (w *writer) writeSet(set ast.Set, loc *ast.Location, comments []*ast.Comment) ([]*ast.Comment, error) { - + var err error if set.Len() == 0 { w.write("set()") - var err error comments, err = w.insertComments(comments, closingLoc(0, 0, '(', ')', loc)) if err != nil { return nil, err @@ -2109,11 +2100,7 @@ func (w *writer) writeSet(set ast.Set, loc *ast.Location, comments []*ast.Commen w.write("{") defer w.write("}") - var s []any - set.Foreach(func(t *ast.Term) { - s = append(s, t) - }) - var err error + s := util.ToSliceOf[any](set.Slice()) comments, err = w.writeIterable(s, loc, closingLoc(0, 0, '{', '}', loc), comments, w.listWriter(true)) if err != nil { return nil, err @@ -2188,7 +2175,7 @@ func (w *writer) writeComprehension(openChar, closeChar byte, term *ast.Term, bo } func (w *writer) writeComprehensionBody(openChar, closeChar byte, body ast.Body, term, compr *ast.Location, comments []*ast.Comment) ([]*ast.Comment, error) { - lines, err := w.groupIterable(util.ToSliceOfAny(body), term) + lines, err := w.groupIterable(util.ToSliceOf[any](body), term) if err != nil { return nil, err } @@ -2755,8 +2742,6 @@ func getLocs(a, b any) (*ast.Location, *ast.Location, error) { return al, bl, errors.Join(err1, err2) } -var negativeRow = &ast.Location{Row: -1} - func closingLoc(skipOpen, skipClose, openChar, closeChar byte, loc *ast.Location) *ast.Location { i, offset := 0, 0 @@ -2945,10 +2930,9 @@ func ensureFutureKeywordImport(imps []*ast.Import, kw string) []*ast.Import { return imps } } - imp := &ast.Import{ - Path: ast.MustParseTerm("future.keywords." + kw), - } + imp := &ast.Import{Path: ast.MustParseTerm("future.keywords." + kw)} imp.Location = nextImportLoc(imps, imp) + return append(imps, imp) } @@ -2958,7 +2942,7 @@ func nextImportLoc(imps []*ast.Import, node ast.Node) *ast.Location { if imp.Loc() == nil { continue } - if isFutureKeywordsImport(imp) || isRegoV1Compatible(imp) { + if imp.Path.Value.(ast.Ref).HasPrefix(ast.FutureKeywordsRef[:1]) || isRegoV1Compatible(imp) { if imp.Loc().Row > maxRow { maxRow = imp.Loc().Row } @@ -2970,11 +2954,6 @@ func nextImportLoc(imps []*ast.Import, node ast.Node) *ast.Location { return ast.NewLocation([]byte(node.String()), defaultLocationFile, maxRow+1, 1) } -func isFutureKeywordsImport(imp *ast.Import) bool { - path := imp.Path.Value.(ast.Ref) - return len(path) >= 2 && ast.FutureRootDocument.Equal(path[0]) -} - func isAddedImport(imp *ast.Import) bool { return imp.Loc() != nil && imp.Loc().File == defaultLocationFile } @@ -3002,34 +2981,21 @@ func addedImportFollowsRule(others []any) bool { } func ensureRegoV1Import(imps []*ast.Import) []*ast.Import { - return ensureImport(imps, ast.RegoV1CompatibleRef) -} - -func filterRegoV1Import(imps []*ast.Import) []*ast.Import { - var ret []*ast.Import - for _, imp := range imps { - path := imp.Path.Value.(ast.Ref) - if !ast.RegoV1CompatibleRef.Equal(path) { - ret = append(ret, imp) - } - } - return ret -} - -func ensureImport(imps []*ast.Import, path ast.Ref) []*ast.Import { for _, imp := range imps { - p := imp.Path.Value.(ast.Ref) - if p.Equal(path) { + if ast.RegoV1CompatibleRef.Equal(imp.Path.Value) { return imps } } - imp := &ast.Import{ - Path: ast.NewTerm(path), - } + imp := &ast.Import{Path: ast.NewTerm(ast.RegoV1CompatibleRef)} imp.Location = nextImportLoc(imps, imp) + return append(imps, imp) } +func regoV1Import(imp *ast.Import) bool { + return ast.RegoV1CompatibleRef.Equal(imp.Path.Value) +} + // ArityFormatErrDetail but for `fmt` checks since compiler has not run yet. type ArityFormatErrDetail struct { Have []string `json:"have"` @@ -3070,3 +3036,8 @@ func isRegoV1Compatible(imp *ast.Import) bool { ast.RegoRootDocument.Equal(path[0]) && path[1].Equal(ast.InternedTerm("v1")) } + +func isUnexpectedCommentError(err error) bool { + _, ok := errors.AsType[unexpectedCommentError](err) + return ok +} diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/loader/errors.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/loader/errors.go index 55b8e7dc4..3e3fb732d 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/loader/errors.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/loader/errors.go @@ -9,6 +9,7 @@ import ( "strings" "github.com/open-policy-agent/opa/v1/ast" + "github.com/open-policy-agent/opa/v1/util" ) // Errors is a wrapper for multiple loader errors. @@ -21,10 +22,7 @@ func (e Errors) Error() string { if len(e) == 1 { return "1 error occurred during loading: " + e[0].Error() } - buf := make([]string, len(e)) - for i := range buf { - buf[i] = e[i].Error() - } + buf := util.Map(e, error.Error) return fmt.Sprintf("%v errors occurred during loading:\n", len(e)) + strings.Join(buf, "\n") } diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/loader/loader.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/loader/loader.go index f78f9fb1d..81eb9a7ee 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/loader/loader.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/loader/loader.go @@ -15,10 +15,9 @@ import ( "runtime" "strings" - "sigs.k8s.io/yaml" - fileurl "github.com/open-policy-agent/opa/internal/file/url" "github.com/open-policy-agent/opa/internal/merge" + "github.com/open-policy-agent/opa/internal/yaml" "github.com/open-policy-agent/opa/v1/ast" astJSON "github.com/open-policy-agent/opa/v1/ast/json" "github.com/open-policy-agent/opa/v1/bundle" diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/logging/logging.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/logging/logging.go index 03d5f33c6..457ee027a 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/logging/logging.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/logging/logging.go @@ -359,7 +359,7 @@ func (h *SlogHandler) WithAttrs(attrs []slog.Attr) slog.Handler { } } -func (h *SlogHandler) WithGroup(name string) slog.Handler { +func (h *SlogHandler) WithGroup(string) slog.Handler { return h } diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/metrics/metrics.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/metrics/metrics.go index 119af78aa..cc6466542 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/metrics/metrics.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/metrics/metrics.go @@ -346,12 +346,12 @@ var ( noOpCounterInstance = &noOpCounter{} ) -func (*noOpMetrics) Info() Info { return Info{Name: ""} } -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) Info() Info { return Info{Name: ""} } +func (*noOpMetrics) Timer(string) Timer { return noOpTimerInstance } +func (*noOpMetrics) Histogram(string) Histogram { return noOpHistogramInstance } +func (*noOpMetrics) Counter(string) Counter { return noOpCounterInstance } +func (*noOpMetrics) All() map[string]any { return nil } +func (*noOpMetrics) Clear() {} func (*noOpMetrics) MarshalJSON() ([]byte, error) { return []byte(`{"name": ""}`), nil } @@ -361,10 +361,10 @@ 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 (*noOpHistogram) Update(int64) {} +func (*noOpHistogram) Value() any { return nil } func (*noOpCounter) Incr() {} -func (*noOpCounter) Add(_ uint64) {} +func (*noOpCounter) Add(uint64) {} func (*noOpCounter) Value() any { return 0 } func (*noOpCounter) Int64() int64 { return 0 } diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/rego/rego.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/rego/rego.go index fa7d5ed34..3a2ff89ab 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/rego/rego.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/rego/rego.go @@ -7,6 +7,7 @@ package rego import ( "bytes" + "cmp" "context" "errors" "fmt" @@ -479,6 +480,11 @@ func (pq preparedQuery) Modules() map[string]*ast.Module { // once the evaluation is complete to close any transactions that might have // been opened. func (pq preparedQuery) newEvalContext(ctx context.Context, options []EvalOption) (*EvalContext, func(context.Context), error) { + disableInlining, err := parseStringsToRefs(pq.r.disableInlining) + if err != nil { + return nil, func(context.Context) {}, err + } + ectx := &EvalContext{ hasInput: false, rawInput: nil, @@ -491,6 +497,7 @@ func (pq preparedQuery) newEvalContext(ctx context.Context, options []EvalOption queryTracers: nil, unknowns: pq.r.unknowns, parsedUnknowns: pq.r.parsedUnknowns, + disableInlining: disableInlining, nondeterministicBuiltins: pq.r.nondeterministicBuiltins, compiledQuery: compiledQuery{}, indexing: true, @@ -516,12 +523,6 @@ func (pq preparedQuery) newEvalContext(ctx context.Context, options []EvalOption // Default to an empty "finish" function finishFunc := func(context.Context) {} - var err error - ectx.disableInlining, err = parseStringsToRefs(pq.r.disableInlining) - if err != nil { - return nil, finishFunc, err - } - if ectx.txn == nil { ectx.txn, err = pq.r.store.NewTransaction(ctx) if err != nil { @@ -704,6 +705,7 @@ type Rego struct { interQueryBuiltinValueCache cache.InterQueryValueCache ndBuiltinCache builtins.NDBCache strictBuiltinErrors bool + stackTraces bool builtinErrorList *[]topdown.Error resolvers []refResolver externalSources []ast.ExternalRuleSource @@ -767,7 +769,7 @@ func RegisterBuiltin1(decl *Function, impl Builtin1) { }) topdown.RegisterBuiltinFunc(decl.Name, func(bctx BuiltinContext, terms []*ast.Term, iter func(*ast.Term) error) error { result, err := memoize(decl, bctx, terms, func() (*ast.Term, error) { return impl(bctx, terms[0]) }) - return finishFunction(decl.Name, bctx, result, err, iter) + return finishFunction(decl.Name, bctx.Location, result, err, iter) }) } @@ -781,7 +783,7 @@ func RegisterBuiltin2(decl *Function, impl Builtin2) { }) topdown.RegisterBuiltinFunc(decl.Name, func(bctx BuiltinContext, terms []*ast.Term, iter func(*ast.Term) error) error { result, err := memoize(decl, bctx, terms, func() (*ast.Term, error) { return impl(bctx, terms[0], terms[1]) }) - return finishFunction(decl.Name, bctx, result, err, iter) + return finishFunction(decl.Name, bctx.Location, result, err, iter) }) } @@ -795,7 +797,7 @@ func RegisterBuiltin3(decl *Function, impl Builtin3) { }) topdown.RegisterBuiltinFunc(decl.Name, func(bctx BuiltinContext, terms []*ast.Term, iter func(*ast.Term) error) error { result, err := memoize(decl, bctx, terms, func() (*ast.Term, error) { return impl(bctx, terms[0], terms[1], terms[2]) }) - return finishFunction(decl.Name, bctx, result, err, iter) + return finishFunction(decl.Name, bctx.Location, result, err, iter) }) } @@ -809,7 +811,7 @@ func RegisterBuiltin4(decl *Function, impl Builtin4) { }) topdown.RegisterBuiltinFunc(decl.Name, func(bctx BuiltinContext, terms []*ast.Term, iter func(*ast.Term) error) error { result, err := memoize(decl, bctx, terms, func() (*ast.Term, error) { return impl(bctx, terms[0], terms[1], terms[2], terms[3]) }) - return finishFunction(decl.Name, bctx, result, err, iter) + return finishFunction(decl.Name, bctx.Location, result, err, iter) }) } @@ -823,7 +825,7 @@ func RegisterBuiltinDyn(decl *Function, impl BuiltinDyn) { }) topdown.RegisterBuiltinFunc(decl.Name, func(bctx BuiltinContext, terms []*ast.Term, iter func(*ast.Term) error) error { result, err := memoize(decl, bctx, terms, func() (*ast.Term, error) { return impl(bctx, terms) }) - return finishFunction(decl.Name, bctx, result, err, iter) + return finishFunction(decl.Name, bctx.Location, result, err, iter) }) } @@ -831,7 +833,7 @@ func RegisterBuiltinDyn(decl *Function, impl BuiltinDyn) { func Function1(decl *Function, f Builtin1) func(*Rego) { return newFunction(decl, func(bctx BuiltinContext, terms []*ast.Term, iter func(*ast.Term) error) error { result, err := memoize(decl, bctx, terms, func() (*ast.Term, error) { return f(bctx, terms[0]) }) - return finishFunction(decl.Name, bctx, result, err, iter) + return finishFunction(decl.Name, bctx.Location, result, err, iter) }) } @@ -839,7 +841,7 @@ func Function1(decl *Function, f Builtin1) func(*Rego) { func Function2(decl *Function, f Builtin2) func(*Rego) { return newFunction(decl, func(bctx BuiltinContext, terms []*ast.Term, iter func(*ast.Term) error) error { result, err := memoize(decl, bctx, terms, func() (*ast.Term, error) { return f(bctx, terms[0], terms[1]) }) - return finishFunction(decl.Name, bctx, result, err, iter) + return finishFunction(decl.Name, bctx.Location, result, err, iter) }) } @@ -847,7 +849,7 @@ func Function2(decl *Function, f Builtin2) func(*Rego) { func Function3(decl *Function, f Builtin3) func(*Rego) { return newFunction(decl, func(bctx BuiltinContext, terms []*ast.Term, iter func(*ast.Term) error) error { result, err := memoize(decl, bctx, terms, func() (*ast.Term, error) { return f(bctx, terms[0], terms[1], terms[2]) }) - return finishFunction(decl.Name, bctx, result, err, iter) + return finishFunction(decl.Name, bctx.Location, result, err, iter) }) } @@ -855,7 +857,7 @@ func Function3(decl *Function, f Builtin3) func(*Rego) { func Function4(decl *Function, f Builtin4) func(*Rego) { return newFunction(decl, func(bctx BuiltinContext, terms []*ast.Term, iter func(*ast.Term) error) error { result, err := memoize(decl, bctx, terms, func() (*ast.Term, error) { return f(bctx, terms[0], terms[1], terms[2], terms[3]) }) - return finishFunction(decl.Name, bctx, result, err, iter) + return finishFunction(decl.Name, bctx.Location, result, err, iter) }) } @@ -863,7 +865,7 @@ func Function4(decl *Function, f Builtin4) func(*Rego) { func FunctionDyn(decl *Function, f BuiltinDyn) func(*Rego) { return newFunction(decl, func(bctx BuiltinContext, terms []*ast.Term, iter func(*ast.Term) error) error { result, err := memoize(decl, bctx, terms, func() (*ast.Term, error) { return f(bctx, terms) }) - return finishFunction(decl.Name, bctx, result, err, iter) + return finishFunction(decl.Name, bctx.Location, result, err, iter) }) } @@ -1308,6 +1310,16 @@ func StrictBuiltinErrors(yes bool) func(r *Rego) { } } +// StackTraces tells the evaluator to record the stack of queries being evaluated +// when an error occurred on the returned *topdown.Error. The stack is exposed as +// topdown.Error.StackTrace and left out of the error message, so callers render +// it themselves. Off by default; see [topdown.Query.WithStackTraces] for why. +func StackTraces(yes bool) func(r *Rego) { + return func(r *Rego) { + r.stackTraces = yes + } +} + // BuiltinErrorList supplies an error slice to store built-in function errors. func BuiltinErrorList(list *[]topdown.Error) func(r *Rego) { return func(r *Rego) { @@ -1608,8 +1620,10 @@ func (r *Rego) Partial(ctx context.Context) (*PartialQueries, error) { EvalTransaction(r.txn), EvalMetrics(r.metrics), EvalInstrument(r.instrument), + EvalTime(r.time), EvalInterQueryBuiltinCache(r.interQueryBuiltinCache), EvalInterQueryBuiltinValueCache(r.interQueryBuiltinValueCache), + EvalSeed(r.seed), } if r.ndBuiltinCache != nil { @@ -1982,7 +1996,7 @@ func (r *Rego) prepare(ctx context.Context, qType queryType, extras []extraStage var queryImports []*ast.Import for _, imp := range imports { path := imp.Path.Value.(ast.Ref) - if path.HasPrefix([]*ast.Term{ast.FutureRootDocument}) || path.HasPrefix([]*ast.Term{ast.RegoRootDocument}) { + if path.HasPrefix(ast.FutureKeywordsRef[:1]) || path.HasPrefix(ast.RegoV1CompatibleRef[:1]) { queryImports = append(queryImports, imp) } } @@ -2137,7 +2151,7 @@ func (*Rego) parseRawInput(rawInput *any, m metrics.Metrics) (ast.Value, error) // roundtrip through json: this turns slices (e.g. []string, []bool) into // []any, the only array type ast.InterfaceToValue can work with - if err := util.RoundTrip(rawPtr); err != nil { + if err := util.RoundTripFast(rawPtr); err != nil { return nil, err } @@ -2157,24 +2171,21 @@ func (r *Rego) parseQuery(queryImports []*ast.Import, m metrics.Metrics) (ast.Bo return nil, err } popts.RegoVersion = r.regoVersion - popts, err = parserOptionsFromRegoVersionImport(queryImports, popts) - if err != nil { - return nil, err - } + popts = parserOptionsFromRegoVersionImport(queryImports, popts) popts.SkipRules = true popts.Capabilities = r.capabilities return ast.ParseBodyWithOpts(r.query, popts) } -func parserOptionsFromRegoVersionImport(imports []*ast.Import, popts ast.ParserOptions) (ast.ParserOptions, error) { +func parserOptionsFromRegoVersionImport(imports []*ast.Import, popts ast.ParserOptions) ast.ParserOptions { for _, imp := range imports { - if ast.RegoV1CompatibleRef.Compare(imp.Path.Value) == 0 { + if ast.RegoV1CompatibleRef.Equal(imp.Path.Value) { popts.RegoVersion = ast.RegoV1 - return popts, nil + return popts } } - return popts, nil + return popts } func (r *Rego) compileModules(ctx context.Context, txn storage.Transaction, m metrics.Metrics) error { @@ -2336,6 +2347,7 @@ func (r *Rego) eval(ctx context.Context, ectx *EvalContext) (ResultSet, error) { WithInterQueryBuiltinCache(ectx.interQueryBuiltinCache). WithInterQueryBuiltinValueCache(ectx.interQueryBuiltinValueCache). WithStrictBuiltinErrors(r.strictBuiltinErrors). + WithStackTraces(r.stackTraces). WithBuiltinErrorList(ectx.builtinErrorList). WithSeed(ectx.seed). WithPrintHook(ectx.printHook). @@ -2343,13 +2355,8 @@ func (r *Rego) eval(ctx context.Context, ectx *EvalContext) (ResultSet, error) { WithVirtualCache(ectx.virtualCache). WithBaseCache(ectx.baseCache). WithRequestMetadata(ectx.requestMetadata). - WithResponseMetadata(ectx.responseMetadata) - - if ectx.evaluated != nil { - q = q.WithEvaluatedRuleTracker(ectx.evaluated) - } else { - q = q.WithEvaluatedRuleTracker(r.evaluated) - } + WithResponseMetadata(ectx.responseMetadata). + WithEvaluatedRuleTracker(cmp.Or(ectx.evaluated, r.evaluated)) if !ectx.time.IsZero() { q = q.WithTime(ectx.time) @@ -2647,10 +2654,12 @@ func (r *Rego) partial(ctx context.Context, ectx *EvalContext) (*PartialQueries, WithInterQueryBuiltinCache(ectx.interQueryBuiltinCache). WithInterQueryBuiltinValueCache(ectx.interQueryBuiltinValueCache). WithStrictBuiltinErrors(ectx.strictBuiltinErrors). + WithStackTraces(r.stackTraces). WithSeed(ectx.seed). WithPrintHook(ectx.printHook). WithRequestMetadata(ectx.requestMetadata). - WithResponseMetadata(ectx.responseMetadata) + WithResponseMetadata(ectx.responseMetadata). + WithEvaluatedRuleTracker(cmp.Or(ectx.evaluated, r.evaluated)) if !ectx.time.IsZero() { q = q.WithTime(ectx.time) @@ -2841,11 +2850,11 @@ func (r *Rego) generateTermVar() *ast.Term { return ast.VarTerm(fmt.Sprintf("%sterm%v", prefix, r.termVarID)) } -func (r Rego) hasQuery() bool { +func (r *Rego) hasQuery() bool { return len(r.query) != 0 || len(r.parsedQuery) != 0 } -func (r Rego) hasWasmModule() bool { +func (r *Rego) hasWasmModule() bool { for _, b := range r.bundles { if len(b.WasmModules) > 0 { return true @@ -2979,11 +2988,9 @@ func iteration(x any) bool { } case ast.Ref: if !stopped { - if bi := ast.BuiltinMap[x.String()]; bi != nil { - if bi.Relation { - stopped = true - return stopped - } + if bi := ast.BuiltinMap[x.String()]; bi != nil && bi.Relation { + stopped = true + return stopped } for i := 1; i < len(x); i++ { if _, ok := x[i].Value.(ast.Var); ok { @@ -3006,23 +3013,13 @@ func parseStringsToRefs(s []string) ([]ast.Ref, error) { if len(s) == 0 { return nil, nil } - - refs := make([]ast.Ref, len(s)) - for i := range refs { - var err error - refs[i], err = ast.ParseRef(s[i]) - if err != nil { - return nil, err - } - } - - return refs, nil + return util.TryMap(s, ast.ParseRef) } // helper function to finish a built-in function call. If an error occurred, // wrap the error and return it. Otherwise, invoke the iterator if the result // was defined. -func finishFunction(name string, bctx topdown.BuiltinContext, result *ast.Term, err error, iter func(*ast.Term) error) error { +func finishFunction(name string, loc *ast.Location, result *ast.Term, err error, iter func(*ast.Term) error) error { if err != nil { sb := strings.Builder{} if e, ok := errors.AsType[*HaltError](err); ok { @@ -3033,7 +3030,7 @@ func finishFunction(name string, bctx topdown.BuiltinContext, result *ast.Term, tdErr := &topdown.Error{ Code: topdown.BuiltinErr, Message: sb.String(), - Location: bctx.Location, + Location: loc, } return topdown.Halt{Err: tdErr.Wrap(e)} } @@ -3044,7 +3041,7 @@ func finishFunction(name string, bctx topdown.BuiltinContext, result *ast.Term, tdErr := &topdown.Error{ Code: topdown.BuiltinErr, Message: sb.String(), - Location: bctx.Location, + Location: loc, } return tdErr.Wrap(err) } @@ -3070,11 +3067,10 @@ func newFunction(decl *Function, f topdown.BuiltinFunc) func(*Rego) { } func generateJSON(term *ast.Term, ectx *EvalContext) (any, error) { - return ast.JSONWithOpt(term.Value, - ast.JSONOpt{ - SortSets: ectx.sortSets, - CopyMaps: ectx.copyMaps, - }) + return ast.JSONWithOpt(term.Value, ast.JSONOpt{ + SortSets: ectx.sortSets, + CopyMaps: ectx.copyMaps, + }) } func (r *Rego) planQuery(queries []ast.Body, evalQueryType queryType) (*ir.Policy, error) { diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/storage/errors.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/storage/errors.go index 95bf25a15..0781eec4e 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/storage/errors.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/storage/errors.go @@ -52,37 +52,22 @@ func (err *Error) Error() string { // IsNotFound returns true if this error is a NotFoundErr. func IsNotFound(err error) bool { - if err, ok := err.(*Error); ok { - return err.Code == NotFoundErr - } - return false + return isError(err, NotFoundErr) } // IsWriteConflictError returns true if this error a WriteConflictErr. func IsWriteConflictError(err error) bool { - switch err := err.(type) { - case *Error: - return err.Code == WriteConflictErr - } - return false + return isError(err, WriteConflictErr) } // IsInvalidPatch returns true if this error is a InvalidPatchErr. func IsInvalidPatch(err error) bool { - switch err := err.(type) { - case *Error: - return err.Code == InvalidPatchErr - } - return false + return isError(err, InvalidPatchErr) } // IsInvalidTransaction returns true if this error is a InvalidTransactionErr. func IsInvalidTransaction(err error) bool { - switch err := err.(type) { - case *Error: - return err.Code == InvalidTransactionErr - } - return false + return isError(err, InvalidTransactionErr) } // IsIndexingNotSupported is a stub for backwards-compatibility. @@ -115,3 +100,8 @@ func policyNotSupportedError() *Error { Code: PolicyNotSupportedErr, } } + +func isError(err error, code string) bool { + e, ok := err.(*Error) + return ok && e.Code == code +} diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/storage/inmem/ast.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/storage/inmem/ast.go index 40f18ab0d..3f7e93d59 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/storage/inmem/ast.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/storage/inmem/ast.go @@ -284,21 +284,19 @@ func removeInAstArray(arr *ast.Array, path storage.Path) (ast.Value, error) { } if len(path) == 1 { - var elems []*ast.Term // Note: possibly expensive operation for large data. + elems := make([]*ast.Term, 0, arr.Len()-1) for i := range arr.Len() { - if i == idx { - continue + if i != idx { + elems = append(elems, arr.Elem(i)) } - elems = append(elems, arr.Elem(i)) } return ast.NewArray(elems...), nil } updatedChild, err := removeInAst(arr.Elem(idx).Value, path[1:]) - if err != nil { - return nil, err + if err == nil { + arr.Set(idx, ast.NewTerm(updatedChild)) } - arr.Set(idx, ast.NewTerm(updatedChild)) - return arr, nil + return arr, err } diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/storage/inmem/inmem.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/storage/inmem/inmem.go index 77bfada09..d4b2d06d0 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/storage/inmem/inmem.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/storage/inmem/inmem.go @@ -345,7 +345,7 @@ func (db *store) Write(_ context.Context, txn storage.Transaction, op storage.Pa val := util.Reference(value) if db.roundTripOnWrite { - if err := util.RoundTrip(val); err != nil { + if err := util.RoundTripFast(val); err != nil { return err } } diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/bindings.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/bindings.go index 809a31676..6ad36c8ff 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/bindings.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/bindings.go @@ -6,10 +6,10 @@ package topdown import ( "fmt" - "strconv" "strings" "github.com/open-policy-agent/opa/v1/ast" + "github.com/open-policy-agent/opa/v1/util" ) type undo struct { @@ -35,9 +35,9 @@ type bindings struct { instr *Instrumentation } -func newBindings(id uint64, instr *Instrumentation) *bindings { +func newBindings(instr *Instrumentation) *bindings { values := newBindingsArrayHashmap() - return &bindings{id, values, instr} + return &bindings{0, values, instr} } // newBindingsWithSize creates bindings pre-sized for the expected number of entries. @@ -49,7 +49,6 @@ func newBindingsWithSize(id uint64, instr *Instrumentation, sizeHint int) *bindi } func (u *bindings) Iter(caller *bindings, iter func(*ast.Term, *ast.Term) error) error { - var err error u.values.Iter(func(k *ast.Term, _ value) bool { @@ -87,6 +86,10 @@ func (u *bindings) PlugNamespaced(a *ast.Term, caller *bindings) *ast.Term { return u.plugNamespaced(a, caller) } +func (u *bindings) size() int { + return u.values.size() +} + func (u *bindings) plugNamespaced(a *ast.Term, caller *bindings) *ast.Term { switch v := a.Value.(type) { case ast.Var: @@ -189,12 +192,12 @@ func (u *bindings) namespaceVar(v *ast.Term, caller *bindings) *ast.Term { if !ok { panic("illegal value") } - if caller != nil && caller != u { - // Root documents (i.e., data, input) should never be namespaced because they - // are globally unique. - if !ast.RootDocumentNames.Contains(v) { - return ast.VarTerm(string(name) + strconv.FormatUint(u.id, 10)) - } + if caller != nil && caller != u && !ast.RootDocumentNames.Contains(v) { + // Root documents (i.e., data, input) should never be namespaced + // because they are globally unique. + len := len(name) + util.NumDigitsUint(u.id) + buf := util.AppendInt(append(make([]byte, 0, len), name...), u.id) + return ast.VarTerm(util.ByteSliceToString(buf)) } return v } @@ -296,11 +299,7 @@ func (vis namespacingVisitor) namespaceTerm(a *ast.Term) *ast.Term { return &cpy case ast.Ref: cpy := *a - ref := make(ast.Ref, len(v)) - for i := range ref { - ref[i] = vis.namespaceTerm(v[i]) - } - cpy.Value = ref + cpy.Value = ast.Ref(util.Map(v, vis.namespaceTerm)) return &cpy } return a @@ -458,6 +457,13 @@ func (b *bindingsArrayHashmap) Iter(f func(k *ast.Term, v value) bool) { } } +func (b *bindingsArrayHashmap) size() int { + if b.m == nil { + return b.n + } + return len(b.m) +} + func (b *bindingsArrayHashmap) find(key *ast.Term) int { if b.a == nil || b.n == 0 { return -1 diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/cache.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/cache.go index e9bb12ab0..a7022f170 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/cache.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/cache.go @@ -144,7 +144,7 @@ type baseCache struct { root *baseCacheElem } -func newBaseCache() *baseCache { +func newBaseCache() BaseCache { return &baseCache{ root: newBaseCacheElem(), } diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/copypropagation/copypropagation.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/copypropagation/copypropagation.go index e086e5d41..75cc6dbb1 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/copypropagation/copypropagation.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/copypropagation/copypropagation.go @@ -77,9 +77,6 @@ func (p *CopyPropagator) WithCompiler(c *ast.Compiler) *CopyPropagator { // Apply executes the copy propagation optimization and returns a new query. func (p *CopyPropagator) Apply(query ast.Body) ast.Body { - - result := ast.NewBody() - uf, ok := makeDisjointSets(p.livevars, query) if !ok { return query @@ -102,6 +99,7 @@ func (p *CopyPropagator) Apply(query ast.Body) ast.Body { return false }) + result := ast.NewBody() removedEqs := ast.NewValueMap() for _, expr := range query { diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/encoding.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/encoding.go index 5ed8df68f..5e636760f 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/encoding.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/encoding.go @@ -12,8 +12,7 @@ import ( "net/url" "strings" - "sigs.k8s.io/yaml" - + "github.com/open-policy-agent/opa/internal/yaml" "github.com/open-policy-agent/opa/v1/ast" "github.com/open-policy-agent/opa/v1/topdown/builtins" "github.com/open-policy-agent/opa/v1/util" diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/errors.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/errors.go index e2dc597ac..43a2fd72d 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/errors.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/errors.go @@ -12,6 +12,8 @@ import ( "github.com/open-policy-agent/opa/v1/util" ) +var cancelErr = &Error{Code: CancelErr} + // Halt is a special error type that built-in function implementations return to indicate // that policy evaluation should stop immediately. type Halt struct { @@ -30,11 +32,16 @@ type Error struct { Code string `json:"code"` Message string `json:"message"` Location *ast.Location `json:"location,omitempty"` - err error `json:"-"` + + // StackTrace is the stack of queries being evaluated when the error occurred. + // Only populated when enabled (see Query.WithStackTraces), and left out of + // Error() so enabling it doesn't change the messages callers display. + StackTrace StackTrace `json:"stack_trace,omitempty"` + + err error `json:"-"` } const ( - // InternalErr represents an unknown evaluation error. InternalErr string = "eval_internal_error" @@ -62,13 +69,13 @@ const ( // IsError returns true if the err is an Error. func IsError(err error) bool { - var e *Error - return errors.As(err, &e) + _, ok := errors.AsType[*Error](err) + return ok } // IsCancel returns true if err was caused by cancellation. func IsCancel(err error) bool { - return errors.Is(err, &Error{Code: CancelErr}) + return errors.Is(err, cancelErr) } // Is allows matching topdown errors using errors.Is (see IsCancel). @@ -76,7 +83,7 @@ func (e *Error) Is(target error) bool { if t, ok := errors.AsType[*Error](target); ok { return (t.Code == "" || e.Code == t.Code) && (t.Message == "" || e.Message == t.Message) && - (t.Location == nil || t.Location.Compare(e.Location) == 0) + (t.Location == nil || t.Location.Equal(e.Location)) } return false } diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/errors_jsonv2.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/errors_jsonv2.go index 29b6f3761..1d0ed6d72 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/errors_jsonv2.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/errors_jsonv2.go @@ -20,5 +20,9 @@ func (e *Error) MarshalJSONTo(enc *jsontext.Encoder) (err error) { err = jsonv2.WriteField(enc, "location", e.Location) } + if len(e.StackTrace) > 0 { + err = errors.Join(err, jsonv2.WriteFieldValue(enc, "stack_trace", e.StackTrace)) + } + return errors.Join(err, enc.WriteToken(jsontext.EndObject)) } diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/eval.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/eval.go index 457bd38ba..882e24850 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/eval.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/eval.go @@ -107,6 +107,7 @@ type eval struct { inliningControl *inliningControl runtime *ast.Term builtinErrors *builtinErrors + stackCapture *stackTraceCapture roundTripper CustomizeRoundTripper evaluated *EvaluatedRuleTracker genvarprefix string @@ -134,8 +135,8 @@ var ( deecPool = util.NewSyncPool[deferredEarlyExitContainer]() resolverPool = util.NewSyncPool[evalResolver]() arraysRecPool = util.NewSyncPool[biunifyArraysRecParams]() - evalFuncPool = util.NewResettablePool[evalFunc, *evalFunc]() - evalBuiltinPool = util.NewResettablePool[evalBuiltin, *evalBuiltin]() + evalFuncPool = util.NewResettablePool[evalFunc]() + evalBuiltinPool = util.NewResettablePool[evalBuiltin]() ) func (e *eval) Run(iter evalIterator) error { @@ -377,17 +378,13 @@ func (e *eval) evalExpr(iter evalIterator) error { } if e.cancel != nil && e.cancel.Cancelled() { + cancelErr := &Error{Code: CancelErr, Message: "caller cancelled query execution"} if e.ctx != nil && e.ctx.Err() != nil { - return &Error{ - Code: CancelErr, - Message: e.ctx.Err().Error(), - err: e.ctx.Err(), - } - } - return &Error{ - Code: CancelErr, - Message: "caller cancelled query execution", + err := e.ctx.Err() + cancelErr.Message = err.Error() + cancelErr.err = err } + return cancelErr } if e.index >= len(e.query) { @@ -415,9 +412,13 @@ func (e *eval) evalExpr(iter evalIterator) error { return e.evalWith(iter) } - return e.evalStep(func(e *eval) error { + err := e.evalStep(func(e *eval) error { return e.next(iter) }) + + // The innermost point an error passes through with every enclosing query's + // expression index still intact. + return e.withStackTrace(err) } func (e *eval) evalStep(iter evalIterator) (err error) { @@ -736,20 +737,20 @@ func (e *eval) evalWith(iter evalIterator) error { input, err := mergeTermWithValues(e.input, pairsInput) if err != nil { - return &Error{ + return e.withStackTrace(&Error{ Code: ConflictErr, Location: expr.Location, Message: err.Error(), - } + }) } data, err := mergeTermWithValues(e.data, pairsData) if err != nil { - return &Error{ + return e.withStackTrace(&Error{ Code: ConflictErr, Location: expr.Location, Message: err.Error(), - } + }) } oldInput, oldData, pushedFrame := e.evalWithPush(input, data, functionMocks, targets, disable) @@ -760,6 +761,7 @@ func (e *eval) evalWith(iter evalIterator) error { oldInput, oldData, pushedFrame = e.evalWithPush(input, data, functionMocks, targets, disable) return err }) + err = e.withStackTrace(err) e.evalWithPop(oldInput, oldData, pushedFrame) @@ -925,7 +927,6 @@ func (e *eval) evalNotPartial(expr *ast.Expr, unNegateFn unNegateFn, complementF } func (e *eval) evalNotPartialSupport(negationID uint64, expr *ast.Expr, supportTermsFn supportTermsFn, unknowns ast.VarSet, queries []ast.Body, iter evalIterator) error { - // Prepare support rule head. supportName := fmt.Sprintf("__not%d_%d_%d__", e.queryID, e.index, negationID) term := ast.RefTerm(ast.DefaultRootDocument, e.saveNamespace, ast.StringTerm(supportName)) @@ -938,27 +939,15 @@ func (e *eval) evalNotPartialSupport(negationID uint64, expr *ast.Expr, supportT bodyVars.Update(q.Vars(ast.VarVisitorParams{})) } - unknowns = unknowns.Intersect(bodyVars) - // Make rule args. Sort them to ensure order is deterministic. - args := make([]*ast.Term, 0, len(unknowns)) - - for v := range unknowns { - args = append(args, ast.NewTerm(v)) - } - - slices.SortFunc(args, ast.TermValueCompare) - + args := util.SortedFunc(util.MapKeys(unknowns.Intersect(bodyVars), ast.ToTerm), ast.TermValueCompare) if len(args) > 0 { - head.Args = args + head.Args = util.SortedFunc(args, ast.TermValueCompare) } // Save support rules. for _, query := range queries { - e.saveSupport.Insert(path, &ast.Rule{ - Head: head, - Body: query, - }) + e.saveSupport.Insert(path, &ast.Rule{Head: head, Body: query}) } // Save expression that refers to support rule set. @@ -1016,19 +1005,28 @@ func (e *eval) evalCall(terms []*ast.Term, iter unifyIterator) error { ir, err = e.getRules(ref, terms[1:], index) } defer ast.IndexResultPool.Put(ir) - if err != nil { + if err != nil || ir == nil { return err } - if ir == nil { - return nil - } - eval := evalFuncPool.Get() - defer evalFuncPool.Put(eval) + // Since values may outlive the function in partial evaluation, + // only use pooled evalFunc when not doing partial eval. + var eval *evalFunc + if e.partial() { + eval = &evalFunc{} + } else { + eval = evalFuncPool.Get() + defer evalFuncPool.Put(eval) + } eval.e = e - eval.terms = terms eval.ir = ir + eval.terms = slices.Grow(eval.terms, len(terms))[:len(terms)] + copy(eval.terms, terms) + + if eval.cacheKey == nil { + eval.cacheKey, eval.args = make(ast.Ref, 0, 8), make([]*ast.Term, 0, 8) + } return eval.eval(iter) } @@ -1306,8 +1304,7 @@ func (e *eval) biunifyValues(a, b *ast.Term, b1, b2 *bindings, iter unifyIterato // Sets must not contain unbound variables at this point as we cannot unify // them. So simply plug both sides (to substitute any bound variables with // values) and then check for equality. - switch a.Value.(type) { - case ast.Set: + if _, ok := a.Value.(ast.Set); ok { a = b1.Plug(a) b = b2.Plug(b) } @@ -1369,7 +1366,6 @@ func (e *eval) biunifyRef(a, b *ast.Term, b1, b2 *bindings, iter unifyIterator) } func (e *eval) biunifyComprehension(a, b *ast.Term, b1, b2 *bindings, swap bool, iter unifyIterator) error { - if e.unknown(a, b1) { return e.biunifyComprehensionPartial(a, b, b1, b2, swap, iter) } @@ -1427,13 +1423,7 @@ func (e *eval) buildComprehensionCache(a *ast.Term) (*ast.Term, error) { e.instr.counterIncr(evalOpComprehensionCacheHit) } - values := make([]*ast.Term, len(index.Keys)) - - for i := range index.Keys { - values[i] = e.bindings.Plug(index.Keys[i]) - } - - return cache.Get(values), nil + return cache.Get(util.Map(index.Keys, e.bindings.Plug)), nil } func (e *eval) buildComprehensionCacheArray(x *ast.ArrayComprehension, keys []*ast.Term) (*comprehensionCacheElem, error) { @@ -1443,10 +1433,7 @@ func (e *eval) buildComprehensionCacheArray(x *ast.ArrayComprehension, keys []*a e.childWithBindingSizeHint(x.Body, child, ast.EstimateBodyBindingCount(x.Body)) node := newComprehensionCacheElem() return node, child.Run(func(child *eval) error { - values := make([]*ast.Term, len(keys)) - for i := range keys { - values[i] = child.bindings.Plug(keys[i]) - } + values := util.Map(keys, child.bindings.Plug) head := child.bindings.Plug(x.Term) cached := node.Get(values) if cached != nil { @@ -1465,10 +1452,7 @@ func (e *eval) buildComprehensionCacheSet(x *ast.SetComprehension, keys []*ast.T e.childWithBindingSizeHint(x.Body, child, ast.EstimateBodyBindingCount(x.Body)) node := newComprehensionCacheElem() return node, child.Run(func(child *eval) error { - values := make([]*ast.Term, len(keys)) - for i := range keys { - values[i] = child.bindings.Plug(keys[i]) - } + values := util.Map(keys, child.bindings.Plug) head := child.bindings.Plug(x.Term) cached := node.Get(values) if cached != nil { @@ -1488,10 +1472,7 @@ func (e *eval) buildComprehensionCacheObject(x *ast.ObjectComprehension, keys [] e.childWithBindingSizeHint(x.Body, child, ast.EstimateBodyBindingCount(x.Body)) node := newComprehensionCacheElem() return node, child.Run(func(child *eval) error { - values := make([]*ast.Term, len(keys)) - for i := range keys { - values[i] = child.bindings.Plug(keys[i]) - } + values := util.Map(keys, child.bindings.Plug) headKey := child.bindings.Plug(x.Key) headValue := child.bindings.Plug(x.Value) cached := node.Get(values) @@ -1818,6 +1799,17 @@ type evalResolver struct { args []*ast.Term } +// IndexEveryCandidateEvaluated implements ast.IndexEveryCandidateEvaluated. +// +// Partial evaluation never exits early, whatever its definitions resolve to: +// evalExpr raises the error only where `!e.partial()`. So it evaluates every +// candidate even under a ruleset IndexResult.EarlyExit says a caller could stop in +// -- that field is what the ruleset permits, not what this caller does, which is +// why an index has to ask. +func (e *evalResolver) IndexEveryCandidateEvaluated() bool { + return e.e.partial() +} + func (e *evalResolver) Resolve(ref ast.Ref) (ast.Value, error) { e.e.instr.startTimer(evalOpResolve) @@ -2009,24 +2001,20 @@ func (e *eval) rewrittenVar(v ast.Var) (ast.Var, bool) { } func (e *eval) getDeclArgsLen(x *ast.Expr) (int, error) { - if !x.IsCall() { return -1, nil } operator := x.Operator() bi, _, ok := e.builtinFunc(operator.String()) - if ok { return bi.Decl.Arity(), nil } ir, err := e.getRules(operator, nil, e.ruleIndex(operator)) defer ast.IndexResultPool.Put(ir) - if err != nil { + if err != nil || ir == nil || ir.Empty() { return -1, err - } else if ir == nil || ir.Empty() { - return -1, nil } return len(ir.Rules[0].Head.Args), nil @@ -2076,13 +2064,7 @@ func operandRequiresEval(v ast.Value) bool { } func (e *evalBuiltin) eval(iter unifyIterator) error { - - operands := make([]*ast.Term, len(e.terms)) - - for i := range e.terms { - operands[i] = e.e.bindings.Plug(e.terms[i]) - } - + operands := util.Map(e.terms, e.e.bindings.Plug) numDeclArgs := e.bi.Decl.Arity() // NOTE(philipc): We sometimes have to drop the very last term off @@ -2147,12 +2129,9 @@ func (e *evalBuiltin) eval(iter unifyIterator) error { } // Normal unification flow for builtins: - err := e.f(bctx, operands, func(output *ast.Term) error { - + err := e.f(bctx, operands, func(output *ast.Term) (err error) { e.e.instr.stopTimer(evalOpBuiltinCall) - var err error - switch { case e.bi.Decl.Result() == nil: err = iter() @@ -2186,6 +2165,13 @@ func (e *evalBuiltin) eval(iter unifyIterator) error { if t, ok := err.(Halt); ok { err = t.Err } else { + // Built-in errors are collected here rather than unwinding through + // evalExpr, so the stack has to be recorded now. Skip it when the + // collected errors have no consumer: query.go drops them, and a + // policy over messy data reaches this for every row. + if c := e.e.stackCapture; c != nil && c.builtinErrors { + err = e.e.attachStackTrace(err) + } e.e.builtinErrors.errs = append(e.e.builtinErrors.errs, err) err = nil } @@ -2196,15 +2182,21 @@ func (e *evalBuiltin) eval(iter unifyIterator) error { } type evalFunc struct { - e *eval - ir *ast.IndexResult - terms []*ast.Term + terms []*ast.Term + cacheKey []*ast.Term + args []*ast.Term + e *eval + ir *ast.IndexResult } // Reset clears the fields before this evalFunc is returned to its pool, // so pooling it doesn't keep terms/index results from the previous call alive. func (e *evalFunc) Reset() { - e.e, e.terms, e.ir = nil, nil, nil + clear(e.terms) + clear(e.cacheKey) + clear(e.args) + e.terms, e.cacheKey, e.args = e.terms[:0], e.cacheKey[:0], e.args[:0] + e.e, e.ir = nil, nil } func (e *evalFunc) eval(iter unifyIterator) error { @@ -2264,35 +2256,28 @@ func (e *evalFunc) eval(iter unifyIterator) error { } func (e *evalFunc) evalValue(iter unifyIterator, argCount int, findOne bool) error { - var cacheKey ast.Ref if !e.e.partial() { - var hit bool - var err error - cacheKey, hit, err = e.evalCache(argCount, iter) - if err != nil { + hit, err := e.evalCache(argCount, iter) + if err != nil || hit { return err - } else if hit { - return nil } } - // NOTE(anders): While it makes the code a bit more complex, reusing the - // args slice across each function increment saves a lot of resources - // compared to creating a new one inside each call to evalOneRule... so - // think twice before simplifying this :) - args := make([]*ast.Term, len(e.terms)-1) + numArgs := len(e.terms) - 1 + e.args = slices.Grow(e.args, numArgs)[:numArgs] var prev *ast.Term return withSuppressEarlyExit(func() error { var outerEe *deferredEarlyExitError for _, rule := range e.ir.Rules { - copy(args, rule.Head.Args) - if len(args) == len(rule.Head.Args)+1 { - args[len(args)-1] = rule.Head.Value + copy(e.args, rule.Head.Args) + numHeadArgs := len(rule.Head.Args) + if numArgs == numHeadArgs+1 { + e.args[numArgs-1] = rule.Head.Value } - next, err := e.evalOneRule(iter, rule, args, cacheKey, prev, findOne) + next, err := e.evalOneRule(iter, rule, prev, findOne) if err != nil { if oee, ok := err.(*deferredEarlyExitError); ok { if outerEe == nil { @@ -2304,12 +2289,12 @@ func (e *evalFunc) evalValue(iter unifyIterator, argCount int, findOne bool) err } if next == nil { for _, erule := range e.ir.Else[rule] { - copy(args, erule.Head.Args) - if len(args) == len(erule.Head.Args)+1 { - args[len(args)-1] = erule.Head.Value + copy(e.args, erule.Head.Args) + if numArgs == numHeadArgs+1 { + e.args[numArgs-1] = erule.Head.Value } - next, err = e.evalOneRule(iter, erule, args, cacheKey, prev, findOne) + next, err = e.evalOneRule(iter, erule, prev, findOne) if err != nil { if oee, ok := err.(*deferredEarlyExitError); ok { if outerEe == nil { @@ -2330,12 +2315,12 @@ func (e *evalFunc) evalValue(iter unifyIterator, argCount int, findOne bool) err } if e.ir.Default != nil && prev == nil { - copy(args, e.ir.Default.Head.Args) - if len(args) == len(e.ir.Default.Head.Args)+1 { - args[len(args)-1] = e.ir.Default.Head.Value + copy(e.args, e.ir.Default.Head.Args) + if numArgs == len(e.ir.Default.Head.Args)+1 { + e.args[numArgs-1] = e.ir.Default.Head.Value } - _, err := e.evalOneRule(iter, e.ir.Default, args, cacheKey, prev, findOne) + _, err := e.evalOneRule(iter, e.ir.Default, prev, findOne) return err } @@ -2348,46 +2333,43 @@ func (e *evalFunc) evalValue(iter unifyIterator, argCount int, findOne bool) err }) } -func (e *evalFunc) evalCache(argCount int, iter unifyIterator) (ast.Ref, bool, error) { +func (e *evalFunc) evalCache(argCount int, iter unifyIterator) (bool, error) { plen := len(e.terms) if plen == argCount+2 { // func name + output = 2 plen -= 1 } - cacheKey := make([]*ast.Term, plen) + e.cacheKey = slices.Grow(e.cacheKey, plen)[:plen] for i := range plen { - if e.terms[i].IsGround() { - // Avoid expensive copying of ref if it is ground. - cacheKey[i] = e.terms[i] - } else { - cacheKey[i] = e.e.bindings.Plug(e.terms[i]) + e.cacheKey[i] = e.terms[i] // Avoid expensive copying of ref if ground + if !e.terms[i].IsGround() { + e.cacheKey[i] = e.e.bindings.Plug(e.terms[i]) } } - cached, _ := e.e.virtualCache.Get(cacheKey) - if cached != nil { + if cached, _ := e.e.virtualCache.Get(e.cacheKey); cached != nil { e.e.instr.counterIncr(evalOpVirtualCacheHit) if argCount == len(e.terms)-1 { // f(x) if ast.Boolean(false).Equal(cached.Value) { - return nil, true, nil + return true, nil } - return nil, true, iter() + return true, iter() } // f(x, y), y captured output value - return nil, true, e.e.unify(e.terms[len(e.terms)-1] /* y */, cached, iter) + return true, e.e.unify(e.terms[len(e.terms)-1] /* y */, cached, iter) } e.e.instr.counterIncr(evalOpVirtualCacheMiss) - return cacheKey, false, nil + return false, nil } -func (e *evalFunc) evalOneRule(iter unifyIterator, rule *ast.Rule, args []*ast.Term, cacheKey ast.Ref, prev *ast.Term, findOne bool) (*ast.Term, error) { +func (e *evalFunc) evalOneRule(iter unifyIterator, rule *ast.Rule, prev *ast.Term, findOne bool) (*ast.Term, error) { child := evalPool.Get() defer evalPool.Put(child) // Optimization: pre-size bindings based on function argument count to reduce memory waste. // Function argument count is known at compile time and most functions have < 10 arguments. // This avoids allocating the default 16-slot array when only 2-3 bindings are needed. - sizeHint := len(args) + sizeHint := len(e.args) e.e.childWithBindingSizeHint(rule.Body, child, sizeHint) child.findOne = findOne @@ -2395,25 +2377,26 @@ func (e *evalFunc) evalOneRule(iter unifyIterator, rule *ast.Rule, args []*ast.T child.traceEnter(rule) - err := child.biunifyTerms(e.terms[1:], args, e.e.bindings, child.bindings, func() error { + err := child.biunifyTerms(e.terms[1:], e.args, e.e.bindings, child.bindings, func() error { return child.eval(func(child *eval) error { child.traceExit(rule) e.e.evaluated.Record(rule) // Partial evaluation must save an expression that tests the output value if the output value // was not captured to handle the case where the output value may be `false`. - if len(rule.Head.Args) == len(e.terms)-1 && e.e.saveSet.Contains(rule.Head.Value, child.bindings) { + noOutputCapture := len(rule.Head.Args) == len(e.terms)-1 + if noOutputCapture && e.e.saveSet.Contains(rule.Head.Value, child.bindings) { err := e.e.saveExpr(ast.NewExpr(rule.Head.Value), child.bindings, iter) child.traceRedo(rule) return err } result = child.bindings.Plug(rule.Head.Value) - if cacheKey != nil { - e.e.virtualCache.Put(cacheKey, result) // the redos confirm this, or the evaluation is aborted + if e.cacheKey != nil { + e.e.virtualCache.Put(e.cacheKey, result) // the redos confirm this, or the evaluation is aborted } - if len(rule.Head.Args) == len(e.terms)-1 && ast.Boolean(false).Equal(result.Value) { + if noOutputCapture && ast.Boolean(false).Equal(result.Value) { if prev != nil && !prev.Equal(result) { return functionConflictErr(rule.Location) } @@ -2452,15 +2435,13 @@ func (e *evalFunc) partialEvalSupport(declArgsLen int, iter unifyIterator) error if !e.e.saveSupport.Exists(path) { for _, rule := range e.ir.Rules { - err := e.partialEvalSupportRule(rule, path) - if err != nil { + if err := e.partialEvalSupportRule(rule, path); err != nil { return err } } if e.ir.Default != nil { - err := e.partialEvalSupportRule(e.ir.Default, path) - if err != nil { + if err := e.partialEvalSupportRule(e.ir.Default, path); err != nil { return err } } @@ -2470,9 +2451,11 @@ func (e *evalFunc) partialEvalSupport(declArgsLen int, iter unifyIterator) error return nil } - term := ast.NewTerm(path) + terms := make([]*ast.Term, len(e.terms)) + terms[0] = ast.NewTerm(path) + copy(terms[1:], e.terms[1:]) - return e.e.saveCall(declArgsLen, append([]*ast.Term{term}, e.terms[1:]...), iter) + return e.e.saveCall(declArgsLen, terms, iter) } func (e *evalFunc) partialEvalSupportRule(rule *ast.Rule, path ast.Ref) error { @@ -2501,6 +2484,7 @@ func (e *evalFunc) partialEvalSupportRule(rule *ast.Rule, path ast.Ref) error { // Skip this rule body if it fails to type-check. // Type-checking failure means the rule body will never succeed. if e.e.compiler.PassesTypeCheck(plugged) { + e.e.evaluated.Record(rule) head := &ast.Head{ Name: rule.Head.Name, Reference: rule.Head.Reference, @@ -2532,12 +2516,12 @@ type deferredEarlyExitContainer struct { } func (dc *deferredEarlyExitContainer) handleErr(err error) error { - if err == nil { - return nil - } - - if dc.deferred == nil && errors.As(err, &dc.deferred) && dc.deferred != nil { - return nil + if err != nil && dc.deferred == nil { + var ok bool + dc.deferred, ok = errors.AsType[*deferredEarlyExitError](err) + if ok && dc.deferred != nil { + return nil + } } return err @@ -2581,7 +2565,6 @@ func (e evalTree) eval(iter unifyIterator) error { } 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. @@ -2598,7 +2581,6 @@ func (e evalTree) finish(iter unifyIterator) error { } func (e evalTree) next(iter unifyIterator, plugged *ast.Term) error { - var node *ast.TreeNode cpy := e @@ -2651,19 +2633,14 @@ func (e evalTree) next(iter unifyIterator, plugged *ast.Term) error { cacheRef = append(cacheRef, k) } - if !expand { + if !expand && e.e.partial() { // The parameter key(s) are not ground, so we cannot // select a concrete sub-source. Under partial evaluation // the reference is unknown and must be residualized; // otherwise it is simply undefined and we fall through // with the bare (rule-less) external node. - if e.e.partial() { - saved := make(ast.Ref, len(e.ref)) - for i := range e.ref { - saved[i] = e.bindings.Plug(e.ref[i]) - } - return e.e.saveUnify(ast.NewTerm(saved), e.rterm, e.bindings, e.rbindings, iter) - } + saved := ast.Ref(util.Map(e.ref, e.bindings.Plug)) + return e.e.saveUnify(ast.NewTerm(saved), e.rterm, e.bindings, e.rbindings, iter) } } @@ -2787,6 +2764,7 @@ func (e evalTree) enumerate(iter unifyIterator) error { // Use method value to avoid closure allocation. // Create once and reuse for both doc and virtual doc enumeration. en := enumerateNext{iter: iter, e: &e, key: nil} + call := en.call if doc != nil { switch doc := doc.(type) { @@ -2794,7 +2772,7 @@ func (e evalTree) enumerate(iter unifyIterator) error { for i := range doc.Len() { k := ast.InternedTerm(i) en.key = k - err := e.e.biunify(k, e.ref[e.pos], e.bindings, e.bindings, en.call) + err := e.e.biunify(k, e.ref[e.pos], e.bindings, e.bindings, call) if err := dc.handleErr(err); err != nil { return err @@ -2804,7 +2782,7 @@ func (e evalTree) enumerate(iter unifyIterator) error { ki := doc.KeysIterator() for k, more := ki.Next(); more; k, more = ki.Next() { en.key = k - err := e.e.biunify(k, e.ref[e.pos], e.bindings, e.bindings, en.call) + err := e.e.biunify(k, e.ref[e.pos], e.bindings, e.bindings, call) if err := dc.handleErr(err); err != nil { return err } @@ -2813,7 +2791,7 @@ func (e evalTree) enumerate(iter unifyIterator) error { // Use Slice() to avoid closure allocation in Iter() for _, elem := range doc.Slice() { en.key = elem - err := e.e.biunify(elem, e.ref[e.pos], e.bindings, e.bindings, en.call) + err := e.e.biunify(elem, e.ref[e.pos], e.bindings, e.bindings, call) if err := dc.handleErr(err); err != nil { return err } @@ -2840,7 +2818,7 @@ func (e evalTree) enumerate(iter unifyIterator) error { } en.key = key - if err := e.e.biunify(key, e.ref[e.pos], e.bindings, e.bindings, en.call); err != nil { + if err := e.e.biunify(key, e.ref[e.pos], e.bindings, e.bindings, call); err != nil { return err } } @@ -2953,17 +2931,12 @@ type evalVirtual struct { } func (e evalVirtual) eval(iter unifyIterator) error { - ir, err := e.e.getRules(e.plugged[:e.pos+1], nil, e.e.ruleIndex(e.plugged[:e.pos+1])) defer ast.IndexResultPool.Put(ir) - if err != nil { + if err != nil || ir == nil { return err } - if ir == nil { - return nil - } - // 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.unknownRef(e.ref, e.bindings) { @@ -3051,8 +3024,7 @@ func (h *evalVirtualPartialCacheHint) keyWithoutScope() ast.Ref { } func (e evalVirtualPartial) eval(iter unifyIterator) error { - unknown := e.e.unknown(e.ref[:e.pos+1], e.bindings) - + unknown := e.e.unknownRef(e.ref[:e.pos+1], e.bindings) if len(e.ref) == e.pos+1 { if unknown { return e.partialEvalSupport(iter) @@ -3091,7 +3063,7 @@ func (e evalVirtualPartial) evalEachRule(iter unifyIterator, unknown bool) error if e.e.partial() { m := maxRefLength(e.ir.Rules, len(e.ref)) - if e.e.unknown(e.ref[e.pos+1:m], e.bindings) { + if e.e.unknownRef(e.ref[e.pos+1:m], e.bindings) { for _, rule := range e.ir.Rules { if err := e.evalOneRulePostUnify(iter, rule); err != nil { return err @@ -3395,6 +3367,7 @@ func (e evalVirtualPartial) partialEvalSupportRule(rule *ast.Rule, _ ast.Ref) (b // Skip this rule body if it fails to type-check. // Type-checking failure means the rule body will never succeed. if e.e.compiler.PassesTypeCheck(plugged) { + e.e.evaluated.Record(rule) var value *ast.Term if rule.Head.Value != nil { @@ -3458,10 +3431,9 @@ func (e evalVirtualPartial) evalTerm(iter unifyIterator, pos int, term *ast.Term } func (e evalVirtualPartial) evalCache(iter unifyIterator) (evalVirtualPartialCacheHint, error) { - var hint evalVirtualPartialCacheHint - if e.e.unknown(e.ref[:e.pos+1], e.bindings) { + if e.e.unknownRef(e.ref[:e.pos+1], e.bindings) { // FIXME: Return empty hint if unknowns in any e.ref elem overlapping with applicable rule refs? return hint, nil } @@ -3534,8 +3506,7 @@ func (e evalVirtualPartial) evalCache(iter unifyIterator) (evalVirtualPartialCac scope.Ref = append(scope.Ref, plugged) hint.key[len(hint.key)-1] = ast.NewTerm(scope) } else { - scope = vcKeyScope{} - scope.Ref = append(scope.Ref, plugged) + scope = vcKeyScope{Ref: ast.Ref{plugged}} hint.key = append(hint.key, ast.NewTerm(scope)) } } @@ -3770,7 +3741,6 @@ type evalVirtualComplete struct { } func (e evalVirtualComplete) eval(iter unifyIterator) error { - if e.ir.Empty() { return nil } @@ -3892,9 +3862,8 @@ func (e evalVirtualComplete) evalValueRule(iter unifyIterator, rule *ast.Rule, p e.e.evaluated.Record(rule) result = child.bindings.Plug(rule.Head.Value) - if prev != nil { - if ast.Compare(result, prev) != 0 { + if !prev.Equal(result) { return completeDocConflictErr(rule.Location) } child.traceRedo(rule) @@ -3927,6 +3896,7 @@ func (e evalVirtualComplete) partialEval(iter unifyIterator) error { err := child.eval(func(child *eval) error { child.traceExit(rule) + e.e.evaluated.Record(rule) term, termbindings := child.bindings.apply(rule.Head.Value) if err := e.evalTerm(iter, term, termbindings); err != nil { @@ -4012,6 +3982,7 @@ func (e evalVirtualComplete) partialEvalSupportRule(rule *ast.Rule, packagePath // Skip this rule body if it fails to type-check. // Type-checking failure means the rule body will never succeed. if e.e.compiler.PassesTypeCheck(plugged) { + e.e.evaluated.Record(rule) head := ast.RefHead(ruleRef, child.bindings.PlugNamespaced(rule.Head.Value, e.e.caller.bindings)) if !e.e.inliningControl.shallow { @@ -4081,6 +4052,15 @@ func (e evalTerm) eval(iter unifyIterator) error { func (e evalTerm) next(iter unifyIterator, plugged *ast.Term) error { + // Key selects an unknown sub-document: save the reference instead of reading + // a concrete document that may lack the key, or hold a stand-in value. The + // partial() test is inline to keep the call off the non-partial hot path. + if e.e.partial() { + if ref, ok := e.unknownPath(plugged); ok { + return e.e.saveUnify(ast.NewTerm(ref), e.rterm, e.bindings, e.rbindings, iter) + } + } + term, bindings := e.get(plugged) if term == nil { return nil @@ -4093,6 +4073,80 @@ func (e evalTerm) next(iter unifyIterator, plugged *ast.Term) error { return cpy.eval(iter) } +// pluggedPrefix returns e.ref[:e.pos] with variables resolved. +func (e evalTerm) pluggedPrefix() ast.Ref { + prefix := make(ast.Ref, e.pos) + for i := range prefix { + prefix[i] = e.bindings.Plug(e.ref[i]) + } + return prefix +} + +// unknownPath reports whether descending into key lands on an unknown, and if +// so returns the full plugged reference to save. +func (e evalTerm) unknownPath(key *ast.Term) (ast.Ref, bool) { + ref := make(ast.Ref, len(e.ref)) + for i := range ref { + if i == e.pos { + ref[i] = key + } else { + ref[i] = e.bindings.Plug(e.ref[i]) + } + } + + if !e.e.saveSet.Covers(ref[:e.pos+1]) { + return nil, false + } + return ref, true +} + +// enumerateUnknownKeys branches on each key an unknown contributes below the +// current prefix but the concrete document lacks. Without it, input[k] with +// input.x unknown and input = {"y": 2} would only ever consider k = "y". +func (e evalTerm) enumerateUnknownKeys(iter unifyIterator, handleErr func(error) error) error { + prefix := e.pluggedPrefix() + + for _, k := range e.e.saveSet.Keys(prefix) { + if term, _ := e.get(k); term != nil { + continue // already covered by the concrete enumeration above + } + // Nothing concrete to descend into: save the whole remaining reference. + ref := make(ast.Ref, len(e.ref)) + copy(ref, prefix) + ref[e.pos] = k + for i := e.pos + 1; i < len(ref); i++ { + ref[i] = e.bindings.Plug(e.ref[i]) + } + // Positions below the key can still rule the branch out: with input.x.a + // unknown, input[k].b has nothing to match at k = "x". + if !e.e.saveSet.ContainsOverlapping(ast.NewTerm(ref), e.bindings) { + continue + } + err := e.e.biunify(k, e.ref[e.pos], e.bindings, e.bindings, func() error { + return e.e.saveUnify(ast.NewTerm(ref), e.rterm, e.bindings, e.rbindings, iter) + }) + if err := handleErr(err); err != nil { + return err + } + } + + return nil +} + +// evalTermNext is the evalTerm counterpart of enumerateNext: it lets the +// object/set enumeration loops pass a method value to biunify instead of a +// function literal, which would escape to the heap on every iteration. +// evalTerm is held by value so call() doesn't chase a second pointer. +type evalTermNext struct { + e evalTerm + iter unifyIterator + key *ast.Term +} + +func (en *evalTermNext) call() error { + return en.e.next(en.iter, en.e.termbindings.Plug(en.key)) +} + func (e evalTerm) enumerate(iter unifyIterator) error { var deferredEe *deferredEarlyExitError handleErr := func(err error) error { @@ -4137,10 +4191,14 @@ func (e evalTerm) enumerate(iter unifyIterator) error { } } case ast.Object: - for _, k := range v.Keys() { - err := e.e.biunify(k, e.ref[e.pos], e.termbindings, e.bindings, func() error { - return e.next(iter, e.termbindings.Plug(k)) - }) + // Bind the method value once, outside the loop: a func literal — or a method + // value materialized per iteration — escapes to the heap on every key. + en := evalTermNext{iter: iter, e: e} + call := en.call + ki := v.KeysIterator() + for k, more := ki.Next(); more; k, more = ki.Next() { + en.key = k + err := e.e.biunify(k, e.ref[e.pos], e.termbindings, e.bindings, call) if err != nil { if err := handleErr(err); err != nil { return err @@ -4148,10 +4206,11 @@ func (e evalTerm) enumerate(iter unifyIterator) error { } } case ast.Set: + en := evalTermNext{iter: iter, e: e} + call := en.call for _, elem := range v.Slice() { - err := e.e.biunify(elem, e.ref[e.pos], e.termbindings, e.bindings, func() error { - return e.next(iter, e.termbindings.Plug(elem)) - }) + en.key = elem + err := e.e.biunify(elem, e.ref[e.pos], e.termbindings, e.bindings, call) if err != nil { if err := handleErr(err); err != nil { return err @@ -4160,6 +4219,12 @@ func (e evalTerm) enumerate(iter unifyIterator) error { } } + if e.e.partial() { + if err := e.enumerateUnknownKeys(iter, handleErr); err != nil { + return err + } + } + if deferredEe != nil { return deferredEe } @@ -4436,7 +4501,7 @@ func (e evalNot) evalPartial(iter evalIterator) error { expr := e.e.query[e.e.index] - unNegate := func(expr *ast.Expr) ast.Body { + unNegate := func(*ast.Expr) ast.Body { return e.not.Body } @@ -4725,7 +4790,6 @@ func plugKeys(a ast.Object, b *bindings) ast.Object { } func canInlineNegation(safe ast.VarSet, queries []ast.Body) bool { - size := 1 vis := newNestedCheckVisitor() @@ -4793,7 +4857,6 @@ func (v *nestedCheckVisitor) visit(x any) bool { } func containsNestedRefOrCall(vis *nestedCheckVisitor, expr *ast.Expr) bool { - if expr.IsEquality() { for _, term := range expr.Operands() { if containsNestedRefOrCallInTerm(vis, term) { @@ -4849,10 +4912,7 @@ func containsNestedRefOrCallInTerm(vis *nestedCheckVisitor, term *ast.Term) bool return false default: vis.vis.Walk(v) - if vis.found { - return true - } - return false + return vis.found } } @@ -4931,7 +4991,7 @@ func merge(a, b ast.Value) (ast.Value, bool) { // objects can be merged with other objects. If the values cannot be merged, // objB value will be overwritten by objA value. func mergeObjects(objA, objB ast.Object) (result ast.Object, ok bool) { - result = ast.NewObject() + result = ast.NewObjectWithCapacity(objA.Len() + objB.Len()) stop := objA.Until(func(k, v *ast.Term) bool { if v2 := objB.Get(k); v2 == nil { result.Insert(k, v) diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/glob.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/glob.go index 4e80c519b..892471040 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/glob.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/glob.go @@ -16,7 +16,7 @@ const globInterQueryValueCacheHits = "rego_builtin_glob_interquery_value_cache_h var noDelimiters = []rune{} var dotDelimiters = []rune{'.'} var globCacheLock = sync.RWMutex{} -var globCache = map[string]glob.Glob{} +var globCache = map[string]*glob.Pattern{} func builtinGlobMatch(bctx BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error { pattern, err := builtins.StringOperand(operands[0].Value, 1) @@ -66,7 +66,7 @@ func globCompileAndMatch(bctx BuiltinContext, id, pattern, match string, delimit // TODO: Use named cache val, ok := bctx.InterQueryBuiltinValueCache.Get(ast.String(id)) if ok { - pat, valid := val.(glob.Glob) + pat, valid := val.(*glob.Pattern) if !valid { // The cache key may exist for a different value type (eg. regex). // In this case, we calculate the glob and return the result w/o updating the cache. diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/http.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/http.go index 62fd92c35..839725497 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/http.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/http.go @@ -1333,13 +1333,13 @@ func newHTTPRequestExecutor(bctx BuiltinContext, req ast.Object, key ast.Object) } if useInterQueryCache && bctx.InterQueryBuiltinCache != nil { - return newInterQueryCache(bctx, req, key, forceCacheParams) + return newInterQueryCache(bctx, req, key, forceCacheParams), nil } - return newIntraQueryCache(bctx, req, key) + return newIntraQueryCache(bctx, req, key), nil } -func newInterQueryCache(bctx BuiltinContext, req ast.Object, key ast.Object, forceCacheParams forceCacheParams) (*interQueryCache, error) { - return &interQueryCache{bctx: bctx, req: req, key: key, forceCacheParams: forceCacheParams}, nil +func newInterQueryCache(bctx BuiltinContext, req ast.Object, key ast.Object, forceCacheParams forceCacheParams) *interQueryCache { + return &interQueryCache{bctx: bctx, req: req, key: key, forceCacheParams: forceCacheParams} } // CheckCache checks the cache for the value of the key set on this object @@ -1401,8 +1401,8 @@ func (c *interQueryCache) ExecuteHTTPRequest() (*http.Response, error) { return executeHTTPRequest(c.httpReq, c.httpClient, c.req) } -func newIntraQueryCache(bctx BuiltinContext, req ast.Object, key ast.Object) (*intraQueryCache, error) { - return &intraQueryCache{bctx: bctx, req: req, key: key}, nil +func newIntraQueryCache(bctx BuiltinContext, req ast.Object, key ast.Object) *intraQueryCache { + return &intraQueryCache{bctx: bctx, req: req, key: key} } // CheckCache checks the cache for the value of the key set on this object diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/json.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/json.go index bb8cc4925..53989541b 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/json.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/json.go @@ -11,6 +11,7 @@ import ( "github.com/open-policy-agent/opa/v1/ast" "github.com/open-policy-agent/opa/v1/topdown/builtins" + "github.com/open-policy-agent/opa/v1/util" "github.com/open-policy-agent/opa/internal/edittree" ) @@ -150,22 +151,15 @@ func getJSONPaths(operand ast.Value) (paths []ast.Ref, err error) { paths = append(paths, filter) } case ast.Set: - paths = make([]ast.Ref, 0, v.Len()) - for _, item := range v.Slice() { - filter, err := parsePath(item) - if err != nil { - return nil, err - } - paths = append(paths, filter) - } + paths, err = util.TryMap(v.Slice(), parsePath) default: return nil, builtins.NewOperandTypeErr(2, v, "set", "array") } - return paths, nil + return paths, err } -// parsePath parses a JSON pointer path or array of path segments into an ast.Ref. +// parsePath parsese a JSON pointer path or array of path segments into an ast.Ref. func parsePath(path *ast.Term) (ast.Ref, error) { // paths can either be a `/` separated json path or // an array or set of values diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/query.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/query.go index e912bbae5..399b7f0a5 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/query.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/query.go @@ -1,6 +1,7 @@ package topdown import ( + "cmp" "context" "crypto/rand" "io" @@ -57,6 +58,7 @@ type Query struct { interQueryBuiltinValueCache cache.InterQueryValueCache ndBuiltinCache builtins.NDBCache strictBuiltinErrors bool + stackTraces bool builtinErrorList *[]Error strictObjects bool roundTripper CustomizeRoundTripper @@ -272,6 +274,21 @@ func (q *Query) WithStrictBuiltinErrors(yes bool) *Query { return q } +// WithStackTraces tells the evaluator to record the stack of queries being +// evaluated when an error occurred on the returned *Error. The stack is exposed +// as Error.StackTrace and left out of the error message, so callers render it +// themselves. +// +// Off by default because capture is not free: each *Error costs a walk of the +// parent chain and a frame per query on it, resolved against the bindings in +// scope, which on a query collecting one built-in error per row runs from +60% +// to +203% in time (see BenchmarkStackTraceCollectedBuiltinErrors). OPA's own +// CLI and server accept that cost and turn it on. +func (q *Query) WithStackTraces(yes bool) *Query { + q.stackTraces = yes + return q +} + // WithBuiltinErrorList supplies a pointer to an Error slice to store built-in function errors // encountered during evaluation. This error slice can be inspected after evaluation to determine // which built-in function errors occurred. @@ -365,9 +382,7 @@ func (q *Query) WithEvaluatedRuleTracker(t *EvaluatedRuleTracker) *Query { // evaluation may produce additional support modules that should be used in // conjunction with the partially evaluated queries. func (q *Query) PartialRun(ctx context.Context) (partials []ast.Body, support []*ast.Module, err error) { - if q.partialNamespace == "" { - q.partialNamespace = "partial" // lazily initialize partial namespace - } + q.partialNamespace = cmp.Or(q.partialNamespace, "partial") if q.evaluated != nil && q.compiler != nil { q.evaluated.WithAnnotationSet(q.compiler.GetAnnotationSet()) } @@ -380,21 +395,7 @@ func (q *Query) PartialRun(ctx context.Context) (partials []ast.Body, support [] q.metrics = util.Or(q.metrics, metrics.New) f := &queryIDFactory{} - b := newBindings(0, q.instr) - - var vc VirtualCache - if q.virtualCache != nil { - vc = q.virtualCache - } else { - vc = NewVirtualCache() - } - - var bc BaseCache - if q.baseCache != nil { - bc = q.baseCache - } else { - bc = newBaseCache() - } + b := newBindings(q.instr) e := &eval{ ctx: ctx, @@ -409,12 +410,13 @@ func (q *Query) PartialRun(ctx context.Context) (partials []ast.Body, support [] bindings: b, compiler: q.compiler, store: q.store, - baseCache: bc, + baseCache: util.Or(q.baseCache, newBaseCache), txn: q.txn, input: q.input, external: q.external, tracers: q.tracers, traceEnabled: len(q.tracers) > 0, + stackCapture: q.newStackCapture(), plugTraceVars: q.plugTraceVars, instr: q.instr, builtins: q.builtins, @@ -422,7 +424,7 @@ func (q *Query) PartialRun(ctx context.Context) (partials []ast.Body, support [] interQueryBuiltinCache: q.interQueryBuiltinCache, interQueryBuiltinValueCache: q.interQueryBuiltinValueCache, ndBuiltinCache: q.ndBuiltinCache, - virtualCache: vc, + virtualCache: util.Or(q.virtualCache, NewVirtualCache), saveSet: newSaveSet(q.unknowns, b, q.instr), saveStack: newSaveStack(), saveSupport: newSaveSupport(), @@ -462,38 +464,37 @@ func (q *Query) PartialRun(ctx context.Context) (partials []ast.Body, support [] } } - ast.WalkVars(q.query, func(x ast.Var) bool { - if !x.IsGenerated() { - livevars.Add(x) - } - return false - }) + // iterate expressions to avoid Body -> any boxing in WalkVars argument + for _, expr := range q.query { + ast.WalkVars(expr, func(x ast.Var) bool { + if !x.IsGenerated() { + livevars.Add(x) + } + return false + }) + } p := copypropagation.New(livevars).WithCompiler(q.compiler) err = e.Run(func(e *eval) error { - // Build output from saved expressions. - body := ast.NewBody() - - for _, elem := range e.saveStack.Peek() { - body.Append(elem.Plug(e.bindings)) + saved := e.saveStack.Peek() + exprs := make([]*ast.Expr, 0, len(saved)+e.bindings.size()) + for _, elem := range saved { + exprs = append(exprs, elem.Plug(e.bindings)) } // Include bindings as exprs so that when caller evals the result, they // can obtain values for the vars in their query. - bindingExprs := []*ast.Expr{} _ = e.bindings.Iter(e.bindings, func(a, b *ast.Term) error { - bindingExprs = append(bindingExprs, ast.Equality.Expr(a, b)) + exprs = append(exprs, ast.Equality.Expr(a, b)) return nil }) // cannot return error // Sort binding expressions so that results are deterministic. - slices.SortFunc(bindingExprs, (*ast.Expr).Compare) + slices.SortFunc(exprs[len(saved):], (*ast.Expr).Compare) - for i := range bindingExprs { - body.Append(bindingExprs[i]) - } + body := ast.NewBody(exprs...) // Skip this rule body if it fails to type-check. // Type-checking failure means the rule body will never succeed. @@ -509,8 +510,6 @@ func (q *Query) PartialRun(ctx context.Context) (partials []ast.Body, support [] return nil }) - support = e.saveSupport.List() - if len(e.builtinErrors.errs) > 0 { if q.strictBuiltinErrors { err = e.builtinErrors.errs[0] @@ -532,6 +531,8 @@ func (q *Query) PartialRun(ctx context.Context) (partials []ast.Body, support [] } } + support = e.saveSupport.List() + for i, m := range support { if regoVersion := q.compiler.DefaultRegoVersion(); regoVersion != ast.RegoUndefined { ast.SetModuleRegoVersion(m, q.compiler.DefaultRegoVersion()) @@ -557,16 +558,11 @@ func (q *Query) Run(ctx context.Context) (QueryResultSet, error) { func (q *Query) Iter(ctx context.Context, iter func(QueryResult) error) error { // Query evaluation must not be allowed if the compiler has errors and is in an undefined, possibly inconsistent state if q.compiler != nil && len(q.compiler.Errors) > 0 { - return &Error{ - Code: InternalErr, - Message: "compiler has errors", - } + return &Error{Code: InternalErr, Message: "compiler has errors"} } - if q.evaluated != nil && q.compiler != nil { q.evaluated.WithAnnotationSet(q.compiler.GetAnnotationSet()) } - if q.seed == nil { q.seed = rand.Reader } @@ -576,21 +572,6 @@ func (q *Query) Iter(ctx context.Context, iter func(QueryResult) error) error { q.metrics = util.Or(q.metrics, metrics.New) f := &queryIDFactory{} - - var vc VirtualCache - if q.virtualCache != nil { - vc = q.virtualCache - } else { - vc = NewVirtualCache() - } - - var bc BaseCache - if q.baseCache != nil { - bc = q.baseCache - } else { - bc = newBaseCache() - } - e := &eval{ ctx: ctx, metrics: q.metrics, @@ -601,15 +582,16 @@ func (q *Query) Iter(ctx context.Context, iter func(QueryResult) error) error { queryCompiler: q.queryCompiler, queryIDFact: f, queryID: f.Next(), - bindings: newBindings(0, q.instr), + bindings: newBindings(q.instr), compiler: q.compiler, store: q.store, - baseCache: bc, + baseCache: util.Or(q.baseCache, newBaseCache), txn: q.txn, input: q.input, external: q.external, tracers: q.tracers, traceEnabled: len(q.tracers) > 0, + stackCapture: q.newStackCapture(), plugTraceVars: q.plugTraceVars, instr: q.instr, builtins: q.builtins, @@ -617,7 +599,7 @@ func (q *Query) Iter(ctx context.Context, iter func(QueryResult) error) error { interQueryBuiltinCache: q.interQueryBuiltinCache, interQueryBuiltinValueCache: q.interQueryBuiltinValueCache, ndBuiltinCache: q.ndBuiltinCache, - virtualCache: vc, + virtualCache: util.Or(q.virtualCache, NewVirtualCache), genvarprefix: q.genvarprefix, runtime: q.runtime, indexing: q.indexing, @@ -637,7 +619,7 @@ func (q *Query) Iter(ctx context.Context, iter func(QueryResult) error) error { e.caller = e q.metrics.Timer(metrics.RegoQueryEval).Start() err := e.Run(func(e *eval) error { - qr := QueryResult{} + qr := make(QueryResult, e.bindings.size()) _ = e.bindings.Iter(nil, func(k, v *ast.Term) error { qr[k.Value.(ast.Var)] = v return nil diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/regex.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/regex.go index 031345203..6c6de304d 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/regex.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/regex.go @@ -26,6 +26,41 @@ var ( regexpCache = make(map[string]*regexp.Regexp) ) +func regexpCacheGet(pat string) (*regexp.Regexp, error) { + regexpCacheLock.RLock() + v, ok := regexpCache[pat] + regexpCacheLock.RUnlock() + if ok { + return v, nil + } + + // cache miss! + re, err := regexp.Compile(pat) + if err != nil { + return nil, err + } + + regexpCacheLock.Lock() + + // Ensure the cache is below the max size. + for len(regexpCache) >= regexCacheMaxSize { + // Since every caller inserts at most one item, we expect this + // loop to run for at most one iteration. + for k := range regexpCache { + // Go map iteration is semi-random, so this deletes a + // more or less arbitrary key. + delete(regexpCache, k) + break + } + } + + regexpCache[pat] = re + + regexpCacheLock.Unlock() + return re, nil + +} + func builtinRegexIsValid(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error { if s, err := builtins.StringOperand(operands[0].Value, 1); err == nil { if _, err = syntax.Parse(string(s), syntax.Perl); err == nil { @@ -129,46 +164,16 @@ func getRegexp(bctx BuiltinContext, pat string) (*regexp.Regexp, error) { return re, nil } - regexpCacheLock.RLock() - re, ok := regexpCache[pat] - numCached := len(regexpCache) - regexpCacheLock.RUnlock() - if !ok { - var err error - re, err = regexp.Compile(pat) - if err != nil { - return nil, err - } - - regexpCacheLock.Lock() - if numCached >= regexCacheMaxSize { - // Delete a (semi-)random key to make room for the new one. - for k := range regexpCache { - delete(regexpCache, k) - break - } - } - regexpCache[pat] = re - regexpCacheLock.Unlock() - } - return re, nil + return regexpCacheGet(pat) } func getRegexpTemplate(pat string, delimStart, delimEnd byte) (*regexp.Regexp, error) { - regexpCacheLock.RLock() - re, ok := regexpCache[pat] - regexpCacheLock.RUnlock() - if !ok { - var err error - re, err = compileRegexTemplate(pat, delimStart, delimEnd) - if err != nil { - return nil, err - } - regexpCacheLock.Lock() - regexpCache[pat] = re - regexpCacheLock.Unlock() + gen, err := generateRegexTemplate(pat, delimStart, delimEnd) + if err != nil { + return nil, err } - return re, nil + + return regexpCacheGet(gen) } func builtinGlobsMatch(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error { diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/regex_template.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/regex_template.go index 0c1f698bf..f8cc55087 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/regex_template.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/regex_template.go @@ -67,19 +67,13 @@ func delimiterIndices(s string, delimiterStart, delimiterEnd byte) ([]int, error return idxs, nil } -// compileRegexTemplate parses a template and returns a Regexp. -// -// You can define your own delimiters. It is e.g. common to use curly braces {} but I recommend using characters -// which have no special meaning in Regex, e.g.: <, > -// -// reg, err := compiler.CompileRegex("foo:bar.baz:<[0-9]{2,10}>", '<', '>') -// // if err != nil ... -// reg.MatchString("foo:bar.baz:123") -func compileRegexTemplate(tpl string, delimiterStart, delimiterEnd byte) (*regexp.Regexp, error) { +// generateRegexTemplate creates and returns the pattern string compiled by +// compileRegexTemplate(). +func generateRegexTemplate(tpl string, delimiterStart, delimiterEnd byte) (string, error) { // Check if it is well-formed. idxs, errBraces := delimiterIndices(tpl, delimiterStart, delimiterEnd) if errBraces != nil { - return nil, errBraces + return "", errBraces } varsR := make([]*regexp.Regexp, len(idxs)/2) pattern := bytes.NewBufferString("^") @@ -96,7 +90,7 @@ func compileRegexTemplate(tpl string, delimiterStart, delimiterEnd byte) (*regex fmt.Fprintf(pattern, "%s(%s)", regexp.QuoteMeta(raw), patt) varsR[varIdx], err = regexp.Compile(fmt.Sprintf("^%s$", patt)) if err != nil { - return nil, err + return "", err } } @@ -109,6 +103,23 @@ func compileRegexTemplate(tpl string, delimiterStart, delimiterEnd byte) (*regex // WriteByte's error value is always nil for bytes.Buffer, no need to check it. pattern.WriteByte('$') + return pattern.String(), nil +} + +// compileRegexTemplate parses a template and returns a Regexp. +// +// You can define your own delimiters. It is e.g. common to use curly braces {} but I recommend using characters +// which have no special meaning in Regex, e.g.: <, > +// +// reg, err := compiler.CompileRegex("foo:bar.baz:<[0-9]{2,10}>", '<', '>') +// // if err != nil ... +// reg.MatchString("foo:bar.baz:123") +func compileRegexTemplate(tpl string, delimiterStart, delimiterEnd byte) (*regexp.Regexp, error) { + pattern, err := generateRegexTemplate(tpl, delimiterStart, delimiterEnd) + if err != nil { + return nil, err + } + // Compile full regexp. - return regexp.Compile(pattern.String()) + return regexp.Compile(pattern) } diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/save.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/save.go index 30d250f9c..5d2362339 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/save.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/save.go @@ -91,6 +91,76 @@ func (ss *saveSet) containsrec(t *ast.Term, b *bindings) bool { return found } +// ContainsOverlapping is a conservative Contains: it also reports terms that +// may refer to an unknown once resolved, like input[k] when input.x is unknown. +// Callers saving whole expressions need it; evalTerm saves per branch instead. +func (ss *saveSet) ContainsOverlapping(t *ast.Term, b *bindings) bool { + if ss == nil { + return false + } + ss.instr.startTimer(partialOpSaveSetContains) + defer ss.instr.stopTimer(partialOpSaveSetContains) + + other, ok := t.Value.(ast.Ref) + if !ok { + return ss.contains(t, b) + } + + for el := ss.l.Back(); el != nil; el = el.Prev() { + elem := el.Value.(*saveSetElem) + for _, ref := range elem.refs { + if refsMayOverlap(ref, other) { + return true + } + } + if elem.containsVar(other[0], b) { + return true + } + } + return false +} + +// Covers reports whether an unknown sits at or above path, i.e. the whole +// sub-document is unknown. Directional half of Contains: input.z.a being +// unknown leaves input.z.b known, so a walk through input.z keeps descending. +func (ss *saveSet) Covers(path ast.Ref) bool { + if ss == nil { + return false + } + for el := ss.l.Back(); el != nil; el = el.Prev() { + if slices.ContainsFunc(el.Value.(*saveSetElem).refs, path.HasPrefix) { + return true + } + } + return false +} + +// Keys returns the ground keys unknowns contribute directly below prefix. With +// input.x unknown and input = {"y": 2}, iterating input[k] must still produce a +// branch for k = "x". A non-ground prefix matches no unknown, hence no keys. +func (ss *saveSet) Keys(prefix ast.Ref) []*ast.Term { + if ss == nil { + return nil + } + + var keys []*ast.Term + for el := ss.l.Back(); el != nil; el = el.Prev() { + for _, ref := range el.Value.(*saveSetElem).refs { + if len(ref) <= len(prefix) || !ref.HasPrefix(prefix) { + continue + } + k := ref[len(prefix)] + if !k.IsGround() { + continue + } + if !slices.ContainsFunc(keys, k.Equal) { + keys = append(keys, k) + } + } + } + return keys +} + func (ss *saveSet) Vars(caller *bindings) ast.VarSet { result := ast.NewVarSet() for x := ss.l.Front(); x != nil; x = x.Next() { @@ -158,6 +228,31 @@ func (sse *saveSetElem) Contains(t *ast.Term, b *bindings) bool { return false } +// refsMayOverlap returns true if ref (an unknown) and other could refer to the +// same document. Non-ground positions act as wildcards: input[k] may hit +// input.x. Heads are exempt -- ref[0] names a root doc, not an unbound position. +func refsMayOverlap(ref, other ast.Ref) bool { + if len(ref) == 0 || len(other) == 0 { + return true + } + + if !ref[0].Equal(other[0]) { + return false + } + + for i, n := 1, min(len(ref), len(other)); i < n; i++ { + // Two ground positions that differ are the only thing ruling an overlap + // out; a non-ground position on either side acts as a wildcard. `other` + // is the side carrying variables, so test its groundness first. + x, y := ref[i], other[i] + if !x.Equal(y) && y.IsGround() && x.IsGround() { + return false + } + } + + return true +} + func (sse *saveSetElem) String() string { return fmt.Sprintf("(refs: %v, vars: %v, b: %v)", sse.refs, sse.vars, sse.b) } @@ -275,11 +370,7 @@ func newSaveSupport() *saveSupport { } func (s *saveSupport) List() []*ast.Module { - result := make([]*ast.Module, 0, len(s.modules)) - for _, module := range s.modules { - result = append(result, module) - } - return result + return util.Values(s.modules) } func (s *saveSupport) Exists(path ast.Ref) bool { @@ -378,7 +469,7 @@ func saveRequired(compilerTree *ast.TreeNode, extStack *externalTreeStack, ic *i found = true } case ast.Ref: - if ss.Contains(node, b) { + if ss.ContainsOverlapping(node, b) { found = true } else if ic.Disabled(v.ConstantPrefix(), icIgnoreInternal) { found = true diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/stacktrace.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/stacktrace.go new file mode 100644 index 000000000..cf019a9cf --- /dev/null +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/stacktrace.go @@ -0,0 +1,336 @@ +// Copyright 2026 The OPA Authors. All rights reserved. +// Use of this source code is governed by an Apache2 +// license that can be found in the LICENSE file. + +package topdown + +import ( + "bytes" + "slices" + "strconv" + "strings" + + "github.com/open-policy-agent/opa/v1/ast" +) + +// maxStackFrameTextLength keeps frames with large literals in them readable. +const maxStackFrameTextLength = 80 + +// StackFrame is one query in a StackTrace. +type StackFrame struct { + // QueryID matches the QueryID of the trace events for the same query. + QueryID uint64 `json:"query_id"` + + // Location is the expression being evaluated, nil if the query has no + // location information. + Location *ast.Location `json:"location,omitempty"` + + // text is the source at Location with the values bound to its variables + // spliced in, empty when nothing was bound. Unexported to keep the policy + // source out of the marshaled frame; String reports it. + text string +} + +// String returns the frame's position and, when the query has source, the +// expression at it with the values its variables were bound to spliced in. +func (f StackFrame) String() string { + s := strings.Builder{} + f.writeTo(&s) + return s.String() +} + +func (f StackFrame) writeTo(s *strings.Builder) { + loc := f.Location + if loc == nil { + s.WriteString("") + return + } + + if loc.File != "" { + s.WriteString(loc.File) + s.WriteByte(':') + s.WriteString(strconv.Itoa(loc.Row)) + } else { + s.WriteString(strconv.Itoa(loc.Row)) + s.WriteByte(':') + s.WriteString(strconv.Itoa(loc.Col)) + } + + src := f.text + if src == "" && loc.Text != nil { + src = string(loc.Text) + } + + if text := frameText(src); text != "" { + s.WriteString(": ") + s.WriteString(text) + } +} + +// StackTrace is the stack of queries being evaluated when an error occurred, +// innermost first. +type StackTrace []StackFrame + +// String returns one indented frame per line. +func (st StackTrace) String() string { + s := strings.Builder{} + for i := range st { + if i > 0 { + s.WriteByte('\n') + } + s.WriteString(" ") + st[i].writeTo(&s) + } + return s.String() +} + +// frameText collapses src onto one line and truncates it. +func frameText(src string) string { + text := strings.Join(strings.Fields(src), " ") + + var runes int + for i := range text { + if runes == maxStackFrameTextLength { + return text[:i] + "..." + } + runes++ + } + + return text +} + +// stackTrace captures the evaluation stack, innermost first. Enclosing queries +// are still suspended on the call stack here, so their expression indices have +// not been unwound yet. +// +// The chain is walked twice to size the slice: append would cost an allocation +// per doubling, on every error a deep stack raises. +func (e *eval) stackTrace() StackTrace { + var depth int + for curr := e; curr != nil; curr = curr.parent { + depth++ + } + + st := make(StackTrace, 0, depth) + for curr := e; curr != nil; curr = curr.parent { + expr := curr.currentExpr() + if expr == nil { + st = append(st, StackFrame{QueryID: curr.queryID}) + continue + } + st = append(st, StackFrame{ + QueryID: curr.queryID, + Location: expr.Location, + text: curr.resolvedText(expr), + }) + } + return st +} + +// currentExpr returns the expression e is evaluating. Once the whole body has +// succeeded e.index sits one past the end, leaving nothing to point at, so the +// last expression is reported as the nearest position. +func (e *eval) currentExpr() *ast.Expr { + if len(e.query) == 0 { + return nil + } + return e.query[min(e.index, len(e.query)-1)] +} + +// resolvedText renders the source of expr with the values its variables are +// bound to spliced in, so a frame reads fn(1) where the policy wrote fn(x) - the +// argument a call failed on is usually the reason it failed. Returns "" when +// nothing was substituted and the source stands on its own. +// +// Bindings are unwound as evaluation backtracks, so this has to run while the +// error is being raised rather than when the frame is rendered. +func (e *eval) resolvedText(expr *ast.Expr) string { + loc := expr.Location + if loc == nil || len(loc.Text) == 0 { + return "" + } + + capture := e.stackCapture + capture.vars = appendReadVars(capture.vars[:0], expr) + subs := capture.subs[:0] + + for _, t := range capture.vars { + start, ok := sourceSpan(loc, t.Location) + if !ok { + continue + } + + // An unbound var plugs to itself, and a value too long to fit in a frame + // is better left as the name the policy gave it. + bound := e.bindings.Plug(t) + if bound == t || !bound.IsGround() || bound.StringLength() > maxStackFrameTextLength { + continue + } + + subs = append(subs, textSub{start: start, end: start + len(t.Location.Text), value: bound.String()}) + } + + capture.subs = subs + + if len(subs) == 0 { + return "" + } + + slices.SortFunc(subs, func(a, b textSub) int { return a.start - b.start }) + + s := strings.Builder{} + prev := 0 + for _, sub := range subs { + // A var reached twice, or one nested in the span of another, resolves to + // the same text the first one already wrote. + if sub.start < prev { + continue + } + s.Write(loc.Text[prev:sub.start]) + s.WriteString(sub.value) + prev = sub.end + } + s.Write(loc.Text[prev:]) + + return s.String() +} + +// textSub is a span of an expression's source to replace with a value. +type textSub struct { + start, end int + value string +} + +// stackTraceCapture is the state Query.WithStackTraces turns on. A non-nil one +// on an eval means capture is enabled, so the feature adds a single field to a +// struct that is copied for every query. +type stackTraceCapture struct { + // builtinErrors records whether collected built-in errors have a consumer. + // Without one query.go drops them, and a policy over messy data reaches that + // path for every row. + builtinErrors bool + + // Working space for resolvedText, shared by every eval of the query - + // evaluation is single threaded - rather than reallocated per stack. + vars []*ast.Term + subs []textSub +} + +// newStackCapture returns the capture state to share across q's evals, nil when +// stack traces are off and nothing will ask for it. +func (q *Query) newStackCapture() *stackTraceCapture { + if !q.stackTraces { + return nil + } + return &stackTraceCapture{builtinErrors: q.strictBuiltinErrors || q.builtinErrorList != nil} +} + +// appendReadVars appends every variable expr reads to dst. ast.WalkTerms would +// find the same ones, but it allocates a visitor and a closure per call and this +// runs once per frame of every captured stack. +// +// Positions that declare a variable rather than read one are skipped, so an +// every keeps its own name in the head instead of reading `every 1 in [1]`. So +// are comprehension bodies: their variables belong to a child query's bindings, +// which the frame cannot resolve. +func appendReadVars(dst []*ast.Term, expr *ast.Expr) []*ast.Term { + switch terms := expr.Terms.(type) { + case *ast.Term: + dst = appendVarsInTerm(dst, terms) + case []*ast.Term: + // terms[0] is the operator, a ref to a built-in or to a rule. + for _, t := range terms[1:] { + dst = appendVarsInTerm(dst, t) + } + case *ast.Every: + // Key and Value are the every's to declare, but its body reads them. + dst = appendVarsInTerm(dst, terms.Domain) + for _, e := range terms.Body { + dst = appendReadVars(dst, e) + } + } + + for _, w := range expr.With { + dst = appendVarsInTerm(dst, w.Value) + } + + return dst +} + +func appendVarsInTerm(dst []*ast.Term, t *ast.Term) []*ast.Term { + // Composites track their groundness, so this prunes most of the walk for + // the cost of a field read. + if t.IsGround() { + return dst + } + + switch v := t.Value.(type) { + case ast.Var: + dst = append(dst, t) + case ast.Ref: + for _, t := range v { + dst = appendVarsInTerm(dst, t) + } + case ast.Call: + for _, t := range v[1:] { + dst = appendVarsInTerm(dst, t) + } + case *ast.Array: + for i := range v.Len() { + dst = appendVarsInTerm(dst, v.Elem(i)) + } + case ast.Set: + // Slice and Keys allocate where Foreach wouldn't, but a closure over dst + // would put it on the heap for every call, ground terms included. + for _, t := range v.Slice() { + dst = appendVarsInTerm(dst, t) + } + case ast.Object: + for _, k := range v.Keys() { + dst = appendVarsInTerm(dst, k) + dst = appendVarsInTerm(dst, v.Get(k)) + } + } + + return dst +} + +// sourceSpan returns where term's source sits within expr's, and false when the +// two don't line up. Terms shared across a policy - the data root document, for +// one - carry the location of wherever they were first parsed, so matching the +// offset alone isn't enough. +func sourceSpan(expr, term *ast.Location) (int, bool) { + if term == nil || len(term.Text) == 0 || term.File != expr.File { + return 0, false + } + + start := term.Offset - expr.Offset + end := start + len(term.Text) + if start < 0 || end > len(expr.Text) || !bytes.Equal(expr.Text[start:end], term.Text) { + return 0, false + } + + return start, true +} + +// withStackTrace records the evaluation stack on err, if enabled. Kept small +// enough to inline, so the disabled case costs only a branch. +func (e *eval) withStackTrace(err error) error { + if err == nil || e.stackCapture == nil { + return err + } + return e.attachStackTrace(err) +} + +// attachStackTrace returns err carrying the evaluation stack, or unchanged if it +// already has one - the innermost stack wins. err is copied, not annotated in +// place: shared errors like errInScopeWithStmt would otherwise race, and leak +// one query's stack into every later occurrence. +func (e *eval) attachStackTrace(err error) error { + if tdErr, ok := err.(*Error); ok && tdErr.StackTrace == nil { + cpy := *tdErr + cpy.StackTrace = e.stackTrace() + return &cpy + } + return err +} diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/strings.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/strings.go index 69495cc8b..e26ec2c39 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/strings.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/strings.go @@ -71,10 +71,7 @@ func builtinAnySuffixMatch(_ BuiltinContext, operands []*ast.Term, iter func(*as if err != nil { return err } - strsReversed = make([]string, len(strs)) - for i := range strs { - strsReversed[i] = reverseString(strs[i]) - } + strsReversed = util.Map(strs, reverseString) default: return builtins.NewOperandTypeErr(1, a, "string", "set", "array") } @@ -88,10 +85,7 @@ func builtinAnySuffixMatch(_ BuiltinContext, operands []*ast.Term, iter func(*as if err != nil { return err } - suffixesReversed = make([]string, len(suffixes)) - for i := range suffixes { - suffixesReversed[i] = reverseString(suffixes[i]) - } + suffixesReversed = util.Map(suffixes, reverseString) default: return builtins.NewOperandTypeErr(2, b, "string", "set", "array") } @@ -791,7 +785,7 @@ func builtinSprintf(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) // Optimized path for where sprintf is used as a "to_string" function for // a single integer, i.e. sprintf("%d", [x]) where x is an integer. if s == "%d" && a.Len() == 1 { - if n, ok := a.Elem(0).Value.(ast.Number); ok { + if n, ok := a.Elem(0).Value.(ast.Number); ok && !isFloatNumber(string(n)) { if i, ok := n.Int(); ok { if interned := ast.InternedIntegerString(i); interned != nil { return iter(interned) @@ -808,23 +802,18 @@ func builtinSprintf(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) switch v := t.Value.(type) { case ast.Number: ns := string(v) - if x, ok := util.Atoi64(ns); ok { - args[i] = x - } else { - if strings.ContainsRune(ns, '.') { - if f, ok := v.Float64(); ok { - args[i] = f - continue - } else { - args[i] = ns - } + if isFloatNumber(ns) { + if f, ok := v.Float64(); ok { + args[i] = f } else { - if b, ok := new(big.Int).SetString(ns, 10); ok { - args[i] = b - } else { - args[i] = ns - } + args[i] = ns } + } else if x, ok := util.Atoi64(ns); ok { + args[i] = x + } else if b, ok := new(big.Int).SetString(ns, 10); ok { + args[i] = b + } else { + args[i] = ns } case ast.String: args[i] = string(v) @@ -836,6 +825,15 @@ func builtinSprintf(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) return iter(ast.InternedTerm(fmt.Sprintf(string(s), args...))) } +// isFloatNumber reports whether the textual representation of a number is that +// of a floating point value, i.e. it has a fraction or an exponent. Since +// util.Atoi64 parses numbers with only zeros past the decimal point (1.0) as +// integers, the text, and not the parsed value, decides how a number is +// formatted by sprintf. +func isFloatNumber(s string) bool { + return strings.ContainsAny(s, ".eE") +} + func builtinReverse(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error { s, err := builtins.StringOperand(operands[0].Value, 1) if err != nil { diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/subset.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/subset.go index d50dc2db7..93fd75e13 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/subset.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/subset.go @@ -182,7 +182,7 @@ func arraySubset(super, sub *ast.Array) bool { } subElem := sub.Elem(subCursor) - if superElem.Value.Compare(subElem.Value) == 0 { + if superElem.Equal(subElem) { subCursor++ } else { superCursor++ diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/template_string.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/template_string.go index 0e705b81b..c9a4984a7 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/template_string.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/template_string.go @@ -20,7 +20,7 @@ func builtinTemplateString(bctx BuiltinContext, operands []*ast.Term, iter func( buf := make([]string, arr.Len()) var count int - err = builtinPrintCrossProductOperands(bctx.Location, buf, arr, 0, func(buf []string) error { + err = builtinPrintCrossProductOperands(bctx.Location, buf, arr, 0, func([]string) error { count += 1 // Precautionary run-time assertion that template-strings can't produce multiple outputs; e.g. for custom relation type built-ins not known at compile-time. if count > 1 { diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/tokens.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/tokens.go index 622f376c7..ffd3d5e00 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/tokens.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/tokens.go @@ -822,9 +822,7 @@ func tokenHeaderString(name string, where *string, value ast.Value) error { // parseTokenHeader parses the JWT header. func parseTokenHeader(token *JSONWebToken) (*tokenHeader, error) { - header := tokenHeader{ - unknown: []string{}, - } + header := tokenHeader{} if err := token.decodedHeader.Iter(func(k *ast.Term, v *ast.Term) error { ks := string(k.Value.(ast.String)) handler, ok := tokenHeaderTypes[ks] diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/trace.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/trace.go index ae6191f5e..ceb8f7e10 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/trace.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/topdown/trace.go @@ -20,7 +20,7 @@ import ( ) const ( - minLocationWidth = 5 // len("query") + minLocationWidth = len("query") maxIdealLocationWidth = 64 columnPadding = 4 maxExprVarWidth = 32 @@ -267,10 +267,6 @@ type PrettyTraceOptions struct { type traceRow []string -func (r *traceRow) add(s string) { - *r = append(*r, s) -} - type traceTable struct { rows []traceRow maxWidths []int @@ -315,10 +311,10 @@ func PrettyTraceWithOpts(w io.Writer, trace []*Event, opts PrettyTraceOptions) { row := traceRow{} if opts.Locations { - row.add(formatLocation(event, filePathAliases)) + row = append(row, formatLocation(event, filePathAliases)) } - row.add(formatEvent(event, depth)) + row = append(row, formatEvent(event, depth)) if opts.ExprVariables { vars := exprLocalVars(event) @@ -342,7 +338,7 @@ func PrettyTraceWithOpts(w io.Writer, trace []*Event, opts PrettyTraceOptions) { } buf.WriteByte('}') - row.add(buf.String()) + row = append(row, buf.String()) } if opts.LocalVariables { @@ -365,9 +361,9 @@ func PrettyTraceWithOpts(w io.Writer, trace []*Event, opts PrettyTraceOptions) { } buf.WriteByte('}') - row.add(buf.String()) + row = append(row, buf.String()) } else { - row.add("{}") + row = append(row, "{}") } } @@ -652,7 +648,7 @@ func (v varInfo) Value() string { func (v varInfo) Title() string { if v.exprLoc != nil && v.exprLoc.Text != nil { - return string(v.exprLoc.Text) + return util.ByteSliceToString(v.exprLoc.Text) } return string(v.Name) } @@ -662,8 +658,7 @@ func padLocationText(loc *ast.Location) string { return "" } - text := string(loc.Text) - + text := util.ByteSliceToString(loc.Text) if loc.Col == 0 { return text } @@ -868,11 +863,7 @@ func printPrettyVars(w *bytes.Buffer, exprVars map[string]varInfo) { return } - byCol := make([]varInfo, 0, len(exprVars)) - for _, info := range exprVars { - byCol = append(byCol, info) - } - slices.SortFunc(byCol, func(a, b varInfo) int { + byCol := util.SortedFunc(util.Values(exprVars), func(a, b varInfo) int { // sort first by column, then by reverse row (to present vars in the same order they appear in the expr) if a.col == b.col { if a.exprLoc.Row == b.exprLoc.Row { diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/types/decode.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/types/decode.go index f2515d5df..a571d565f 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/types/decode.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/types/decode.go @@ -25,8 +25,7 @@ const ( ) // Unmarshal deserializes bs and returns the resulting type. -func Unmarshal(bs []byte) (result Type, err error) { - +func Unmarshal[T byte, BS ~[]byte](bs BS) (result Type, err error) { var hint rawtype if err = util.UnmarshalJSON(bs, &hint); err == nil { @@ -45,7 +44,7 @@ func Unmarshal(bs []byte) (result Type, err error) { var err error var static []Type var dynamic Type - if static, err = unmarshalSlice(arr.Static); err != nil { + if static, err = util.TryMap(arr.Static, Unmarshal); err != nil { return nil, err } if len(arr.Dynamic) != 0 { @@ -81,14 +80,14 @@ func Unmarshal(bs []byte) (result Type, err error) { var union rawunion if err = util.UnmarshalJSON(bs, &union); err == nil { var of []Type - if of, err = unmarshalSlice(union.Of); err == nil { + if of, err = util.TryMap(union.Of, Unmarshal); err == nil { result = NewAny(of...) } } case typeFunction: var decl rawdecl if err = util.UnmarshalJSON(bs, &decl); err == nil { - args, err := unmarshalSlice(decl.Args) + args, err := util.TryMap(decl.Args, Unmarshal) if err != nil { return nil, err } @@ -155,16 +154,6 @@ type rawdecl struct { Variadic json.RawMessage `json:"variadic"` } -func unmarshalSlice(elems []json.RawMessage) (result []Type, err error) { - result = make([]Type, len(elems)) - for i := range elems { - if result[i], err = Unmarshal(elems[i]); err != nil { - return nil, err - } - } - return result, err -} - func unmarshalStaticPropertySlice(elems []rawstaticproperty) (result []*StaticProperty, err error) { result = make([]*StaticProperty, len(elems)) for i := range elems { diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/types/types.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/types/types.go index c02fee4d4..c9f958161 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/types/types.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/types/types.go @@ -26,10 +26,15 @@ var ( // N represents an instance of the number type. N Type = NewNumber() // A represents the superset of all types. - A Type = NewAny() + A Type = Any{} // Boxed set types. SetOfAny, SetOfStr, SetOfNum Type = NewSet(A), NewSet(S), NewSet(N) + + jsonString = [...]byte{'{', '"', 't', 'y', 'p', 'e', '"', ':', '"', 's', 't', 'r', 'i', 'n', 'g', '"', '}'} + jsonBoolean = [...]byte{'{', '"', 't', 'y', 'p', 'e', '"', ':', '"', 'b', 'o', 'o', 'l', 'e', 'a', 'n', '"', '}'} + jsonNumber = [...]byte{'{', '"', 't', 'y', 'p', 'e', '"', ':', '"', 'n', 'u', 'm', 'b', 'e', 'r', '"', '}'} + jsonNull = [...]byte{'{', '"', 't', 'y', 'p', 'e', '"', ':', '"', 'n', 'u', 'l', 'l', '"', '}'} ) // Sprint returns the string representation of the type. @@ -108,10 +113,8 @@ func Named(name string, t Type) *NamedType { } // MarshalJSON returns the JSON encoding of t. -func (t Null) MarshalJSON() ([]byte, error) { - return json.Marshal(map[string]any{ - "type": t.typeMarker(), - }) +func (Null) MarshalJSON() ([]byte, error) { + return jsonNull[:], nil } func unwrap(t Type) Type { @@ -144,7 +147,7 @@ func NewBoolean() Boolean { // MarshalJSON returns the JSON encoding of t. func (Boolean) MarshalJSON() ([]byte, error) { - return util.StringToByteSlice(`{"type":"boolean"}`), nil + return jsonBoolean[:], nil } func (t Boolean) String() string { @@ -161,7 +164,7 @@ func NewString() String { // MarshalJSON returns the JSON encoding of t. func (String) MarshalJSON() ([]byte, error) { - return util.StringToByteSlice(`{"type":"string"}`), nil + return jsonString[:], nil } func (String) String() string { @@ -178,7 +181,7 @@ func NewNumber() Number { // MarshalJSON returns the JSON encoding of t. func (Number) MarshalJSON() ([]byte, error) { - return util.StringToByteSlice(`{"type":"number"}`), nil + return jsonNumber[:], nil } func (Number) String() string { @@ -219,10 +222,7 @@ func (t *Array) toMap() map[string]any { func (t *Array) String() string { prefix := "array" - buf := make([]string, 0, len(t.static)) - for _, tpe := range t.static { - buf = append(buf, Sprint(tpe)) - } + buf := util.Map(t.static, Sprint) repr := prefix if len(buf) > 0 { repr += "<" + strings.Join(buf, ", ") + ">" @@ -288,6 +288,9 @@ func (t *Set) toMap() map[string]any { } func (t *Set) String() string { + if t.of == nil { + return typeSet + } return typeSet + "[" + Sprint(t.of) + "]" } @@ -647,15 +650,11 @@ func (t Any) Union(other Any) Any { } func (t Any) String() string { - prefix := "any" if len(t) == 0 { - return prefix - } - buf := make([]string, len(t)) - for i := range t { - buf[i] = Sprint(t[i]) + return "any" } - return prefix + "<" + strings.Join(buf, ", ") + ">" + buf := util.Map(t, Sprint) + return "any<" + strings.Join(buf, ", ") + ">" } // Function represents a function type. @@ -720,20 +719,14 @@ func (t *Function) FuncArgs() FuncArgs { // NamedFuncArgs returns the function's arguments, with a name and // description if available. func (t *Function) NamedFuncArgs() FuncArgs { - args := make([]Type, len(t.args)) - copy(args, t.args) - return FuncArgs{Args: args, Variadic: t.variadic} + return FuncArgs{Args: slices.Clone(t.args), Variadic: t.variadic} } // Args returns the function's arguments as a slice, ignoring variadic arguments. // // Deprecated: Use FuncArgs instead. func (t *Function) Args() []Type { - cpy := make([]Type, len(t.args)) - for i := range t.args { - cpy[i] = unwrap(t.args[i]) - } - return cpy + return util.Map(t.args, unwrap) } // Arity returns the number of arguments in the function signature. @@ -856,8 +849,7 @@ func (a FuncArgs) Arg(x int) Type { // Compare returns -1, 0, 1 based on comparison between a and b. func Compare(a, b Type) int { a, b = unwrapRecursive(unwrap(a)), unwrapRecursive(unwrap(b)) - x := typeOrder(a) - y := typeOrder(b) + x, y := typeOrder(a), typeOrder(b) if x > y { return 1 } else if x < y { diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/util/channel.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/util/channel.go deleted file mode 100644 index e2653ac7f..000000000 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/util/channel.go +++ /dev/null @@ -1,32 +0,0 @@ -package util - -import ( - "github.com/open-policy-agent/opa/v1/metrics" -) - -// This prevents getting blocked forever writing to a full buffer, in case another routine fills the last space. -// Retrying maxEventRetry times to drop the oldest event. Dropping the incoming event if there still isn't room. -const maxEventRetry = 1000 - -// PushFIFO pushes data into a buffered channel without blocking when full, making room by dropping the oldest data. -// An optional metric can be recorded when data is dropped. -func PushFIFO[T any](buffer chan T, data T, metrics metrics.Metrics, metricName string) { - - for range maxEventRetry { - // non-blocking send to the buffer, to prevent blocking if buffer is full so room can be made. - select { - case buffer <- data: - return - default: - } - - // non-blocking drop from the buffer to make room for incoming event - select { - case <-buffer: - if metrics != nil && metricName != "" { - metrics.Counter(metricName).Incr() - } - default: - } - } -} diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/util/compare.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/util/compare.go index d9e6702d8..3825ef24b 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/util/compare.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/util/compare.go @@ -59,6 +59,14 @@ func SliceLenCompare[T any, S ~[]T](a, b S) int { return 1 } +// CmpEqual is a functional helper for equals comparison of comparable values +// (i.e. using ==), meant to be used for stdlib funtions like [slices.DeleteFunc]. +func CmpEqual[T comparable](a T) func(b T) bool { + return func(b T) bool { + return a == b + } +} + // Compare returns 0 if a equals b, -1 if a is less than b, and 1 if b is than a. // // For comparison between values of different types, the following ordering is used: @@ -77,8 +85,7 @@ func Compare(a, b any) int { case nil: return 0 case bool: - switch b := b.(type) { - case bool: + if b, ok := b.(bool); ok { if a == b { return 0 } @@ -88,13 +95,11 @@ func Compare(a, b any) int { return 1 } case json.Number: - switch b := b.(type) { - case json.Number: + if b, ok := b.(json.Number); ok { return compareJSONNumber(a, b) } case int: - switch b := b.(type) { - case int: + if b, ok := b.(int); ok { if a == b { return 0 } else if a < b { @@ -103,8 +108,7 @@ func Compare(a, b any) int { return 1 } case float64: - switch b := b.(type) { - case float64: + if b, ok := b.(float64); ok { if a == b { return 0 } else if a < b { @@ -113,8 +117,7 @@ func Compare(a, b any) int { return 1 } case string: - switch b := b.(type) { - case string: + if b, ok := b.(string); ok { if a == b { return 0 } else if a < b { @@ -123,8 +126,7 @@ func Compare(a, b any) int { return 1 } case []any: - switch b := b.(type) { - case []any: + if b, ok := b.([]any); ok { bLen := len(b) aLen := len(a) minLen := min(bLen, aLen) @@ -142,8 +144,7 @@ func Compare(a, b any) int { return 1 } case map[string]any: - switch b := b.(type) { - case map[string]any: + if b, ok := b.(map[string]any); ok { aKeys := KeysSorted(a) bKeys := KeysSorted(b) aLen := len(aKeys) diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/util/errors.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/util/errors.go new file mode 100644 index 000000000..18558129f --- /dev/null +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/util/errors.go @@ -0,0 +1,11 @@ +package util + +import "errors" + +// ErrorIs is a shorthand for [errors.AsType] returning only the boolean result. +// This is typically cheaper than [errors.Is], but it's not a drop-in replacement +// for scenario where e.g. custom `Is` methods need to be taken into account. +func ErrorIs[E error](err error) bool { + _, ok := errors.AsType[E](err) + return ok +} diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/util/json.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/util/json.go index de95ed50b..cc0e5793f 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/util/json.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/util/json.go @@ -9,11 +9,12 @@ import ( "encoding/json" "fmt" "io" + "maps" "reflect" + "slices" "strconv" - "sigs.k8s.io/yaml" - + "github.com/open-policy-agent/opa/internal/yaml" "github.com/open-policy-agent/opa/v1/loader/extension" ) @@ -140,7 +141,16 @@ func RoundTrip(x *any) error { if err != nil { return err } - return UnmarshalJSON(bs, x) + + // Decode into a fresh value instead of reusing *x: if *x holds a non-nil + // pointer, json.Unmarshal decodes into the pointed-to value in place + // rather than replacing it. + var y any + if err := UnmarshalJSON(bs, &y); err != nil { + return err + } + *x = y + return nil } // NeedsRoundTrip returns true if the value won't change as a result of @@ -156,6 +166,90 @@ func NeedsRoundTrip(x any) bool { return true } +// RoundTripFast is equivalent to [RoundTrip], but recurses natively through +// map[string]any and []any instead of going through JSON bytes, falling +// back to [RoundTrip] for any other type. +func RoundTripFast(x *any) error { + if x == nil { + return nil + } + y, err := roundTripFastValue(*x, 0, nil) + if err != nil { + return err + } + *x = y + return nil +} + +// startDetectingCyclesAfter matches encoding/json's own threshold. +const startDetectingCyclesAfter = 1000 + +// depth/seen detect cycles the way encoding/json does: native recursion +// doesn't get that check for free from json.Marshal like RoundTrip's +// fallback path does. +func roundTripFastValue(v any, depth int, seen map[uintptr]struct{}) (any, error) { + switch x := v.(type) { + case nil, bool, string, json.Number: + return x, nil + case map[string]any: + if x == nil { + return nil, nil + } + ptr := uintptr(reflect.ValueOf(x).UnsafePointer()) + if depth >= startDetectingCyclesAfter { + if _, ok := seen[ptr]; ok { + return nil, fmt.Errorf("json: unsupported value: encountered a cycle via %T", x) + } + seen = markSeen(seen, ptr) + } + cpy := maps.Clone(x) + for k, e := range cpy { + c, err := roundTripFastValue(e, depth+1, seen) + if err != nil { + return nil, err + } + cpy[k] = c + } + delete(seen, ptr) + return cpy, nil + case []any: + if x == nil { + return nil, nil + } + ptr := uintptr(reflect.ValueOf(x).UnsafePointer()) + if depth >= startDetectingCyclesAfter { + if _, ok := seen[ptr]; ok { + return nil, fmt.Errorf("json: unsupported value: encountered a cycle via %T", x) + } + seen = markSeen(seen, ptr) + } + cpy := slices.Clone(x) + for i, e := range cpy { + c, err := roundTripFastValue(e, depth+1, seen) + if err != nil { + return nil, err + } + cpy[i] = c + } + delete(seen, ptr) + return cpy, nil + default: + y := v + if err := RoundTrip(&y); err != nil { + return nil, err + } + return y, nil + } +} + +func markSeen(seen map[uintptr]struct{}, ptr uintptr) map[uintptr]struct{} { + if seen == nil { + seen = map[uintptr]struct{}{} + } + seen[ptr] = struct{}{} + return seen +} + // Reference returns a pointer to its argument unless the argument already is // a pointer. If the argument is **t, or ***t, etc, it will return *t. // diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/util/maps.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/util/maps.go index b56d57a5f..bbcb76975 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/util/maps.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/util/maps.go @@ -2,6 +2,7 @@ package util import ( "cmp" + "slices" ) // Keys returns a slice of keys from any map. @@ -18,6 +19,22 @@ func KeysSorted[M ~map[K]V, K cmp.Ordered, V any](m M) []K { return Sorted(Keys(m)) } +// KeysSortedFunc returns a slice of keys from any map, sorted by cmp. +func KeysSortedFunc[M ~map[K]V, K comparable, V any](m M, cmp func(K, K) int) []K { + keys := Keys(m) + slices.SortFunc(keys, cmp) + return keys +} + +// MapKeys returns a slice of keys from m, transformed by f. +func MapKeys[M ~map[K]V, K comparable, V, R any](m M, f func(K) R) []R { + r := make([]R, 0, len(m)) + for k := range m { + r = append(r, f(k)) + } + return r +} + // Values returns a slice of values from any map. Copied from golang.org/x/exp/maps. func Values[M ~map[K]V, K comparable, V any](m M) []V { r := make([]V, 0, len(m)) diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/util/performance.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/util/performance.go index 553a4ec11..ea31d16a3 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/util/performance.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/util/performance.go @@ -12,6 +12,8 @@ import ( "unsafe" ) +var emptyByteSlice = []byte{} + // SyncPool is a generic sync.Pool for type T, providing some convenience // over sync.Pool directly: [SyncPool.Put] ensures that nil values are not // put into the pool, and [SyncPool.Get] returns a pointer to T without having @@ -112,7 +114,7 @@ func StringToByteSlice[T ~string](s T) []byte { // unsafe.StringData's return value is unspecified for the empty string, // so don't build a slice on top of it. Doing so currently yields a nil // slice, which callers may treat differently from an empty one. - return []byte{} + return emptyByteSlice } return unsafe.Slice(unsafe.StringData(string(s)), len(s)) } diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/util/slices.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/util/slices.go index 21864ea5b..6184feb15 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/util/slices.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/util/slices.go @@ -55,14 +55,15 @@ func TryMap[T any, U any](s []T, f func(T) (U, error)) (r []U, err error) { return r, nil } -// ToSliceOfAny converts a slice of any type T to []any. -func ToSliceOfAny[T any](s []T) []any { +// ToSliceOf converts a slice of T to slice of R, via round-trip +// through any. Needless to say, T must be assignable to R. +func ToSliceOf[R, T any](s []T) []R { if s == nil { return nil } - r := make([]any, len(s)) + r := make([]R, len(s)) for i, v := range s { - r[i] = v + r[i] = any(v).(R) } return r } diff --git a/constraint/vendor/github.com/open-policy-agent/opa/v1/version/version.go b/constraint/vendor/github.com/open-policy-agent/opa/v1/version/version.go index 2acf6ef67..37415e463 100644 --- a/constraint/vendor/github.com/open-policy-agent/opa/v1/version/version.go +++ b/constraint/vendor/github.com/open-policy-agent/opa/v1/version/version.go @@ -10,7 +10,7 @@ import ( "runtime/debug" ) -var Version = "1.20.2" +var Version = "1.21.0" // GoVersion is the version of Go this was built with var GoVersion = runtime.Version() diff --git a/constraint/vendor/github.com/vektah/gqlparser/v2/ast/value.go b/constraint/vendor/github.com/vektah/gqlparser/v2/ast/value.go index 83b471633..a2f28db9e 100644 --- a/constraint/vendor/github.com/vektah/gqlparser/v2/ast/value.go +++ b/constraint/vendor/github.com/vektah/gqlparser/v2/ast/value.go @@ -42,6 +42,18 @@ type ChildValue struct { Comment *CommentGroup } +// isUnsetVariable reports whether v is a variable reference with no supplied +// value and no default — it should be treated as absent, not null. +func (v *Value) isUnsetVariable(vars map[string]any) bool { + if v.Kind != Variable { + return false + } + if _, ok := vars[v.Raw]; ok { + return false + } + return v.VariableDefinition == nil || v.VariableDefinition.DefaultValue == nil +} + func (v *Value) Value(vars map[string]any) (any, error) { if v == nil { return nil, nil @@ -78,6 +90,9 @@ func (v *Value) Value(vars map[string]any) (any, error) { case ObjectValue: val := map[string]any{} for _, elem := range v.Children { + if elem.Value.isUnsetVariable(vars) { + continue + } elemVal, err := elem.Value.Value(vars) if err != nil { return val, err diff --git a/constraint/vendor/github.com/vektah/gqlparser/v2/gqlerror/error.go b/constraint/vendor/github.com/vektah/gqlparser/v2/gqlerror/error.go index b2ba01bbe..0615f3d26 100644 --- a/constraint/vendor/github.com/vektah/gqlparser/v2/gqlerror/error.go +++ b/constraint/vendor/github.com/vektah/gqlparser/v2/gqlerror/error.go @@ -1,6 +1,7 @@ package gqlerror import ( + "encoding/json" "errors" "fmt" "strconv" @@ -35,6 +36,202 @@ type Location struct { Column int `json:"column,omitempty"` } +// SourceLocation pairs a GraphQL line and column with its source document. +// Source is nil when the location has no source document. +type SourceLocation struct { + Line int `json:"line,omitempty"` + Column int `json:"column,omitempty"` + Source *ast.Source `json:"-"` +} + +// ErrorWithSources is the source-aware validation error returned by the +// opt-in validator API. It retains the standard GraphQL error fields while +// Locations stores each location together with its source document. Source is +// omitted from JSON, leaving the standard GraphQL line and column fields. +type ErrorWithSources struct { + Err error `json:"-"` + Message string `json:"message"` + Path ast.Path `json:"path,omitempty"` + Locations []SourceLocation `json:"locations,omitempty"` + Extensions map[string]any `json:"extensions,omitempty"` + Rule string `json:"-"` + + legacyLocations bool +} + +// NewErrorWithSources pairs an existing GraphQL error with source-aware +// locations. The location slice is copied so callers cannot change the error's +// source associations by mutating their input slice. +func NewErrorWithSources(err *Error, locations []SourceLocation) *ErrorWithSources { + if err == nil { + return nil + } + legacyLocations := locations == nil + if len(locations) > 0 && len(err.Locations) > 0 { + if len(locations) != len(err.Locations) { + panic(fmt.Sprintf( + "gqlerror: source location count %d does not match location count %d", + len(locations), + len(err.Locations), + )) + } + for i, location := range err.Locations { + if locations[i].Line != location.Line || locations[i].Column != location.Column { + panic(fmt.Sprintf( + "gqlerror: source location %d does not match location coordinates", + i, + )) + } + } + } + if len(locations) == 0 && len(err.Locations) > 0 { + locations = make([]SourceLocation, len(err.Locations)) + for i, location := range err.Locations { + locations[i] = SourceLocation{ + Line: location.Line, + Column: location.Column, + } + } + } + return &ErrorWithSources{ + Err: err.Err, + Message: err.Message, + Path: err.Path, + Locations: append([]SourceLocation(nil), locations...), + Extensions: err.Extensions, + Rule: err.Rule, + legacyLocations: legacyLocations, + } +} + +// UnmarshalJSON discards source documents because GraphQL error JSON does not +// encode them. +func (err *ErrorWithSources) UnmarshalJSON(data []byte) error { + type errorWithoutMethods ErrorWithSources + err.Locations = nil + err.legacyLocations = true + return json.Unmarshal(data, (*errorWithoutMethods)(err)) +} + +func (err *ErrorWithSources) Error() string { + if err == nil { + return "" + } + locations := make([]Location, len(err.Locations)) + for i, sourceLocation := range err.Locations { + locations[i] = Location{ + Line: sourceLocation.Line, + Column: sourceLocation.Column, + } + } + base := &Error{ + Err: err.Err, + Message: err.Message, + Path: err.Path, + Locations: locations, + Extensions: cloneExtensions(err.Extensions), + Rule: err.Rule, + } + if base.Extensions == nil { + base.Extensions = map[string]any{} + } + filename, _ := base.Extensions["file"].(string) + if len(err.Locations) == 1 { + if filename == "" { + if source := err.Locations[0].Source; source != nil && source.Name != "" { + filename = source.Name + } + } + } else if len(err.Locations) > 1 { + if source := err.Locations[0].Source; source != nil { + filename = source.Name + } else if !err.legacyLocations { + filename = "" + } + } + if filename != "" { + base.Extensions["file"] = filename + } else { + delete(base.Extensions, "file") + } + return base.Error() +} + +func cloneExtensions(extensions map[string]any) map[string]any { + if extensions == nil { + return nil + } + clone := make(map[string]any, len(extensions)) + for key, value := range extensions { + clone[key] = value + } + return clone +} + +func (err *ErrorWithSources) Unwrap() error { + if err == nil { + return nil + } + return err.Err +} + +func (err *ErrorWithSources) AsError() error { + if err == nil { + return nil + } + return err +} + +// SourceLocations returns a shallow copy of the source-aware locations in +// validation order. +func (err *ErrorWithSources) SourceLocations() []SourceLocation { + if err == nil || len(err.Locations) == 0 { + return nil + } + locations := make([]SourceLocation, len(err.Locations)) + copy(locations, err.Locations) + return locations +} + +// SourceList is the result type returned by the opt-in source-aware validator +// APIs. +type SourceList []*ErrorWithSources + +func (errs SourceList) Error() string { + var buf strings.Builder + for _, err := range errs { + buf.WriteString(err.Error()) + buf.WriteByte('\n') + } + return buf.String() +} + +func (errs SourceList) Is(target error) bool { + for _, err := range errs { + if errors.Is(err, target) { + return true + } + } + return false +} + +func (errs SourceList) As(target any) bool { + for _, err := range errs { + if errors.As(err, target) { + return true + } + } + return false +} + +func (errs SourceList) Unwrap() []error { + l := make([]error, len(errs)) + for i, err := range errs { + l[i] = err + } + return l +} + type List []*Error func (err *Error) Error() string { diff --git a/constraint/vendor/github.com/vektah/gqlparser/v2/validator/core/helpers.go b/constraint/vendor/github.com/vektah/gqlparser/v2/validator/core/helpers.go index f977d00a8..963eba6ea 100644 --- a/constraint/vendor/github.com/vektah/gqlparser/v2/validator/core/helpers.go +++ b/constraint/vendor/github.com/vektah/gqlparser/v2/validator/core/helpers.go @@ -28,6 +28,10 @@ func At(position *ast.Position) ErrorOption { Line: position.Line, Column: position.Column, }) + recordSourceLocation(err, gqlerror.Location{ + Line: position.Line, + Column: position.Column, + }, position.Src) if position.Src.Name != "" { err.SetFile(position.Src.Name) } diff --git a/constraint/vendor/github.com/vektah/gqlparser/v2/validator/core/source_capture.go b/constraint/vendor/github.com/vektah/gqlparser/v2/validator/core/source_capture.go new file mode 100644 index 000000000..3cc3b1ef1 --- /dev/null +++ b/constraint/vendor/github.com/vektah/gqlparser/v2/validator/core/source_capture.go @@ -0,0 +1,82 @@ +package core + +import ( + "fmt" + "sync" + + "github.com/vektah/gqlparser/v2/ast" + "github.com/vektah/gqlparser/v2/gqlerror" +) + +type sourceCapture struct { + locations []gqlerror.SourceLocation +} + +// sourceCaptures bridges the legacy ErrorOption API: At receives only an +// *gqlerror.Error and cannot access CaptureSourceLocations' local capture. +// Entries exist only while source-aware options are being applied. +var sourceCaptures sync.Map // map[*gqlerror.Error]*sourceCapture + +// CaptureSourceLocations applies error options while recording the source +// documents supplied to At. It returns source-aware locations in the same +// order as err.Locations. +// Source-aware validation uses this helper; the regular validation API does +// not install a capture and keeps its existing behavior. +func CaptureSourceLocations(err *gqlerror.Error, apply func()) []gqlerror.SourceLocation { + if err == nil { + panic("gqlparser: cannot capture source locations for a nil error") + } + capture := &sourceCapture{} + sourceCaptures.Store(err, capture) + defer sourceCaptures.Delete(err) + + apply() + if len(err.Locations) == 0 { + if len(capture.locations) > 0 { + panic(fmt.Sprintf( + "gqlparser: captured source location %d does not match the final error locations", + 0, + )) + } + return nil + } + locations := make([]gqlerror.SourceLocation, len(err.Locations)) + for i, location := range err.Locations { + locations[i] = gqlerror.SourceLocation{ + Line: location.Line, + Column: location.Column, + } + } + recorded := 0 + for i, location := range err.Locations { + if recorded == len(capture.locations) { + break + } + captured := capture.locations[recorded] + if captured.Line != location.Line || captured.Column != location.Column { + continue + } + locations[i].Source = captured.Source + recorded++ + } + if recorded != len(capture.locations) { + panic(fmt.Sprintf( + "gqlparser: captured source location %d does not match the final error locations", + recorded, + )) + } + return locations +} + +func recordSourceLocation(err *gqlerror.Error, location gqlerror.Location, source *ast.Source) { + value, ok := sourceCaptures.Load(err) + if !ok { + return + } + capture := value.(*sourceCapture) + capture.locations = append(capture.locations, gqlerror.SourceLocation{ + Line: location.Line, + Column: location.Column, + Source: source, + }) +} diff --git a/constraint/vendor/github.com/vektah/gqlparser/v2/validator/schema.go b/constraint/vendor/github.com/vektah/gqlparser/v2/validator/schema.go index f8d947275..3a0d1377a 100644 --- a/constraint/vendor/github.com/vektah/gqlparser/v2/validator/schema.go +++ b/constraint/vendor/github.com/vektah/gqlparser/v2/validator/schema.go @@ -189,6 +189,10 @@ func ValidateSchemaDocument(sd *SchemaDocument) (*Schema, error) { return nil, err } + if err := validateInputObjectCircularRefs(&schema); err != nil { + return nil, err + } + if err := validateDirectiveDefinitions(&schema); err != nil { return nil, err } @@ -245,6 +249,75 @@ func validateTypeDefinitions(schema *Schema) *gqlerror.Error { return nil } +// validateInputObjectCircularRefs rejects input object cycles of non-null fields. +// https://spec.graphql.org/October2021/#sec-Input-Objects.Circular-References +func validateInputObjectCircularRefs(schema *Schema) *gqlerror.Error { + types := make([]string, 0, len(schema.Types)) + for typ := range schema.Types { + types = append(types, typ) + } + sort.Strings(types) + + // A type still on fieldPath means a cycle. A visited type was already checked. + visited := make(map[string]bool, len(schema.Types)) + fieldPath := make([]*FieldDefinition, 0, len(schema.Types)) + fieldPathIndexByTypeName := make(map[string]int, len(schema.Types)) + + var detectCycle func(def *Definition) *gqlerror.Error + detectCycle = func(def *Definition) *gqlerror.Error { + if visited[def.Name] { + return nil + } + visited[def.Name] = true + fieldPathIndexByTypeName[def.Name] = len(fieldPath) + + for _, field := range def.Fields { + // A nullable field or any list breaks the chain. + if !field.Type.NonNull || field.Type.NamedType == "" { + continue + } + fieldType := schema.Types[field.Type.NamedType] + if fieldType == nil || fieldType.Kind != InputObject { + continue + } + + fieldPath = append(fieldPath, field) + if cycleIndex, ok := fieldPathIndexByTypeName[fieldType.Name]; ok { + cyclePath := fieldPath[cycleIndex:] + fieldNames := make([]string, len(cyclePath)) + for i, cycleField := range cyclePath { + fieldNames[i] = cycleField.Name + } + return gqlerror.ErrorPosf( + cyclePath[0].Position, + "Cannot reference Input Object %s within itself through "+ + "a series of non-null fields: %s.", + strconv.Quote(fieldType.Name), + strconv.Quote(strings.Join(fieldNames, ".")), + ) + } + if err := detectCycle(fieldType); err != nil { + return err + } + fieldPath = fieldPath[:len(fieldPath)-1] + } + + delete(fieldPathIndexByTypeName, def.Name) + return nil + } + + for _, typ := range types { + def := schema.Types[typ] + if def.Kind != InputObject { + continue + } + if err := detectCycle(def); err != nil { + return err + } + } + return nil +} + func validateDirectiveDefinitions(schema *Schema) *gqlerror.Error { directives := make([]string, 0, len(schema.Directives)) for directive := range schema.Directives { diff --git a/constraint/vendor/github.com/vektah/gqlparser/v2/validator/schema_test.yml b/constraint/vendor/github.com/vektah/gqlparser/v2/validator/schema_test.yml index b66e1e3d5..589df95cc 100644 --- a/constraint/vendor/github.com/vektah/gqlparser/v2/validator/schema_test.yml +++ b/constraint/vendor/github.com/vektah/gqlparser/v2/validator/schema_test.yml @@ -386,6 +386,116 @@ inputs: message: 'UNION a: field must be one of SCALAR, ENUM, INPUT_OBJECT.' locations: [{line: 3, column: 13}] + - name: cannot reference itself through a non-null field + input: | + input T { + self: T! + } + error: + message: 'Cannot reference Input Object "T" within itself through a series of non-null fields: "self".' + locations: [{line: 2, column: 3}] + + - name: cannot reference itself through a chain of non-null fields + input: | + input A { + startLoop: B! + } + input B { + nextInLoop: C! + } + input C { + closeLoop: A! + } + error: + message: 'Cannot reference Input Object "A" within itself through a series of non-null fields: "startLoop.nextInLoop.closeLoop".' + locations: [{line: 2, column: 3}] + + - name: cannot reference itself through a non-null field added by an extension + input: | + input T { + id: ID + } + extend input T { + self: T! + } + error: + message: 'Cannot reference Input Object "T" within itself through a series of non-null fields: "self".' + locations: [{line: 5, column: 3}] + + - name: cannot reference itself through a non-null field on a nested cycle + input: | + input Outer { + inner: Inner! + } + input Inner { + self: Inner! + } + error: + message: 'Cannot reference Input Object "Inner" within itself through a series of non-null fields: "self".' + locations: [{line: 5, column: 3}] + + - name: cannot reference itself when an earlier input object is cycle free + input: | + input Entry { + maybe: Loop + } + input Loop { + self: Loop! + } + error: + message: 'Cannot reference Input Object "Loop" within itself through a series of non-null fields: "self".' + locations: [{line: 5, column: 3}] + + - name: can reference itself through a nullable field + input: | + input T { + self: T + } + + - name: can reference itself through a list field + input: | + input T { + a: [T!]! + b: [T]! + c: [T!] + d: [T] + e: [[T!]!]! + } + + - name: can reference itself when the chain is broken by a list + input: | + input A { + startLoop: B! + } + input B { + loopBack: [A!]! + } + + - name: can reference itself when the chain is broken by a nullable field + input: | + input A { + startLoop: B! + } + input B { + nextInLoop: C + } + input C { + closeLoop: A! + } + + - name: can reference the same input object twice without a cycle + input: | + input A { + b: B! + c: C! + } + input B { + c: C! + } + input C { + id: ID! + } + args: - name: Valid arg types input: | diff --git a/constraint/vendor/github.com/vektah/gqlparser/v2/validator/validator.go b/constraint/vendor/github.com/vektah/gqlparser/v2/validator/validator.go index 9fb40d6a1..8efacf676 100644 --- a/constraint/vendor/github.com/vektah/gqlparser/v2/validator/validator.go +++ b/constraint/vendor/github.com/vektah/gqlparser/v2/validator/validator.go @@ -118,6 +118,16 @@ func Validate(schema *Schema, doc *QueryDocument, rules ...Rule) gqlerror.List { return errs } +// ValidateWithSources is the source-aware counterpart to Validate. It keeps +// source documents for every location recorded by the built-in At option while +// leaving Error and the regular validation API unchanged. +func ValidateWithSources(schema *Schema, doc *QueryDocument, rules ...Rule) gqlerror.SourceList { + if rules == nil { + rules = specifiedRules + } + return validateWithSources(schema, doc, rules) +} + func ValidateWithRules( schema *Schema, doc *QueryDocument, @@ -161,3 +171,59 @@ func ValidateWithRules( Walk(schema, doc, observers) return errs } + +// ValidateWithRulesWithSources is the source-aware counterpart to +// ValidateWithRules. +func ValidateWithRulesWithSources( + schema *Schema, + doc *QueryDocument, + rules *validatorrules.Rules, +) gqlerror.SourceList { + if rules == nil { + rules = validatorrules.NewDefaultRules() + } + + var currentRules []Rule //nolint:prealloc // would require extra local refs for len + for name, ruleFunc := range rules.GetInner() { + currentRules = append(currentRules, Rule{Name: name, RuleFunc: ruleFunc}) + // ensure deterministic order evaluation + sort.Sort(core.NameSorter(currentRules)) + } + return validateWithSources(schema, doc, currentRules) +} + +func validateWithSources(schema *Schema, doc *QueryDocument, rules []Rule) gqlerror.SourceList { + var errs gqlerror.SourceList + if schema == nil { + errs = append(errs, gqlerror.NewErrorWithSources( + gqlerror.Errorf("cannot validate as Schema is nil"), + nil, + )) + } + if doc == nil { + errs = append(errs, gqlerror.NewErrorWithSources( + gqlerror.Errorf("cannot validate as QueryDocument is nil"), + nil, + )) + } + if len(errs) > 0 { + return errs + } + + observers := &core.Events{} + for i := range rules { + rule := rules[i] + rule.RuleFunc(observers, func(options ...ErrorOption) { + err := &gqlerror.Error{Rule: rule.Name} + sources := core.CaptureSourceLocations(err, func() { + for _, option := range options { + option(err) + } + }) + errs = append(errs, gqlerror.NewErrorWithSources(err, sources)) + }) + } + + Walk(schema, doc, observers) + return errs +} diff --git a/constraint/vendor/golang.org/x/sys/cpu/cpu.go b/constraint/vendor/golang.org/x/sys/cpu/cpu.go index f1ce515d5..df8dbd1db 100644 --- a/constraint/vendor/golang.org/x/sys/cpu/cpu.go +++ b/constraint/vendor/golang.org/x/sys/cpu/cpu.go @@ -182,12 +182,13 @@ var MIPS64X struct { // require kernel support to work (DARN, SCV), so there are feature bits for // those as well. The struct is padded to avoid false sharing. var PPC64 struct { - _ CacheLinePad - HasDARN bool // Hardware random number generator (requires kernel enablement) - HasSCV bool // Syscall vectored (requires kernel enablement) - IsPOWER8 bool // ISA v2.07 (POWER8) - IsPOWER9 bool // ISA v3.00 (POWER9), implies IsPOWER8 - _ CacheLinePad + _ CacheLinePad + HasDARN bool // Hardware random number generator (requires kernel enablement) + HasSCV bool // Syscall vectored (requires kernel enablement) + IsPOWER8 bool // ISA v2.07 (POWER8) + IsPOWER9 bool // ISA v3.00 (POWER9), implies IsPOWER8 + IsPOWER10 bool // ISA v3.1 (POWER10 and POWER11; POWER11 did not add a new architected level), implies IsPOWER9 + _ CacheLinePad } // S390X contains the supported CPU features of the current IBM Z @@ -248,13 +249,21 @@ var RISCV64 struct { HasZvks bool // ShangMi Algorithm Suite HasZvksc bool // ShangMi Algorithm Suite with carryless multiplication HasZvksg bool // ShangMi Algorithm Suite with GCM + VLENB uint // Vector register length in bytes, 0 if undetected _ CacheLinePad } +// doDerived, if non-nil, is called after processing GODEBUG to set "derived" +// feature flags. +var doDerived func() + func init() { archInit() initOptions() processOptions() + if doDerived != nil { + doDerived() + } } // options contains the cpu debug options that can be used in GODEBUG. diff --git a/constraint/vendor/golang.org/x/sys/cpu/cpu_gc_riscv64.go b/constraint/vendor/golang.org/x/sys/cpu/cpu_gc_riscv64.go new file mode 100644 index 000000000..3d660dd48 --- /dev/null +++ b/constraint/vendor/golang.org/x/sys/cpu/cpu_gc_riscv64.go @@ -0,0 +1,11 @@ +// Copyright 2026 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build gc + +package cpu + +// Can only be called when the vector extension is present. +// Implemented in cpu_riscv64.s. +func readVLENB() uint diff --git a/constraint/vendor/golang.org/x/sys/cpu/cpu_linux_ppc64x.go b/constraint/vendor/golang.org/x/sys/cpu/cpu_linux_ppc64x.go index 197188e67..70b3dc7dd 100644 --- a/constraint/vendor/golang.org/x/sys/cpu/cpu_linux_ppc64x.go +++ b/constraint/vendor/golang.org/x/sys/cpu/cpu_linux_ppc64x.go @@ -11,6 +11,7 @@ const ( // ISA Level _PPC_FEATURE2_ARCH_2_07 = 0x80000000 _PPC_FEATURE2_ARCH_3_00 = 0x00800000 + _PPC_FEATURE2_ARCH_3_1 = 0x00040000 // CPU features _PPC_FEATURE2_DARN = 0x00200000 @@ -21,6 +22,9 @@ func doinit() { // HWCAP2 feature bits PPC64.IsPOWER8 = isSet(hwCap2, _PPC_FEATURE2_ARCH_2_07) PPC64.IsPOWER9 = isSet(hwCap2, _PPC_FEATURE2_ARCH_3_00) + // ISA 3.1 covers both POWER10 and POWER11: POWER11 did not introduce a + // new architected HWCAP level, so there is no separate IsPOWER11. + PPC64.IsPOWER10 = isSet(hwCap2, _PPC_FEATURE2_ARCH_3_1) PPC64.HasDARN = isSet(hwCap2, _PPC_FEATURE2_DARN) PPC64.HasSCV = isSet(hwCap2, _PPC_FEATURE2_SCV) } diff --git a/constraint/vendor/golang.org/x/sys/cpu/cpu_linux_riscv64.go b/constraint/vendor/golang.org/x/sys/cpu/cpu_linux_riscv64.go index f4fb52ee9..53e909114 100644 --- a/constraint/vendor/golang.org/x/sys/cpu/cpu_linux_riscv64.go +++ b/constraint/vendor/golang.org/x/sys/cpu/cpu_linux_riscv64.go @@ -130,6 +130,9 @@ func doinit() { RISCV64.HasFastMisaligned = v == riscv_HWPROBE_MISALIGNED_FAST } } + if RISCV64.HasV { + RISCV64.VLENB = readVLENB() + } // Let's double check with HWCAP if the C extension does not appear to be supported. // This may happen if we're running on a kernel older than 6.4. @@ -137,6 +140,14 @@ func doinit() { if !RISCV64.HasC { RISCV64.HasC = isSet(hwCap, hwcap_RISCV_ISA_C) } + + doDerived = func() { + // If the vector extension is disabled by GODEBUG, then the VLENB is zero. + if !RISCV64.HasV { + RISCV64.VLENB = 0 + } + } + } func isSet(hwc uint, value uint) bool { diff --git a/constraint/vendor/golang.org/x/sys/cpu/cpu_netbsd_amd64.go b/constraint/vendor/golang.org/x/sys/cpu/cpu_netbsd_amd64.go new file mode 100644 index 000000000..4f981b1c8 --- /dev/null +++ b/constraint/vendor/golang.org/x/sys/cpu/cpu_netbsd_amd64.go @@ -0,0 +1,47 @@ +// Copyright 2026 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build netbsd && amd64 && gc + +package cpu + +func doinit() { + // NetBSD corrupts avx registers when receiving signals. + // See issue 80285. + // TODO: when NetBSD fixes the bug, add a version + // check and skip here. + X86.HasAVX = false + X86.HasAVX2 = false + // Set these also, just to be safe + X86.HasAVXVNNI = false + X86.HasAVX512 = false + X86.HasAVX512F = false + X86.HasAVX512CD = false + X86.HasAVX512CD = false + X86.HasAVX512ER = false + X86.HasAVX512PF = false + X86.HasAVX512VL = false + X86.HasAVX512BW = false + X86.HasAVX512DQ = false + X86.HasAVX512IFMA = false + X86.HasAVX512VBMI = false + X86.HasAVX5124VNNIW = false + X86.HasAVX5124FMAPS = false + X86.HasAVX512VPOPCNTDQ = false + X86.HasAVX512VPCLMULQDQ = false + X86.HasAVX512VNNI = false + X86.HasAVX512GFNI = false + X86.HasAVX512VAES = false + X86.HasAVX512VBMI2 = false + X86.HasAVX512BITALG = false + X86.HasAVX512BF16 = false + X86.HasAVXIFMA = false + X86.HasAVXVNNI = false + X86.HasAVXVNNIInt8 = false + +} + +func darwinSupportsAVX512() bool { + panic("only implemented for gc && amd64 && darwin") +} diff --git a/constraint/vendor/golang.org/x/sys/cpu/cpu_other_x86.go b/constraint/vendor/golang.org/x/sys/cpu/cpu_other_x86.go index a0fd7e2f7..82b7580d0 100644 --- a/constraint/vendor/golang.org/x/sys/cpu/cpu_other_x86.go +++ b/constraint/vendor/golang.org/x/sys/cpu/cpu_other_x86.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build 386 || amd64p32 || (amd64 && (!darwin || !gc)) +//go:build 386 || amd64p32 || (amd64 && ((!darwin && !netbsd) || !gc)) package cpu diff --git a/constraint/vendor/golang.org/x/sys/cpu/cpu_riscv64.s b/constraint/vendor/golang.org/x/sys/cpu/cpu_riscv64.s new file mode 100644 index 000000000..b092fb269 --- /dev/null +++ b/constraint/vendor/golang.org/x/sys/cpu/cpu_riscv64.s @@ -0,0 +1,17 @@ +// Copyright 2026 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build gc + +#include "textflag.h" + +// Read the vector register length in bytes from the vlenb CSR. +// May only be called when the vector extension is present. +// func readVLENB() uint +TEXT ·readVLENB(SB), NOSPLIT|NOFRAME, $0-8 + // Go 1.25's assembler does not recognize VLENB, so use its raw CSRR encoding. + // Replace WORD with CSRR VLENB, X10 once go.mod requires Go 1.27. + WORD $0xc2202573 + MOV X10, ret+0(FP) + RET diff --git a/constraint/vendor/golang.org/x/sys/cpu/cpu_sparc64.go b/constraint/vendor/golang.org/x/sys/cpu/cpu_sparc64.go new file mode 100644 index 000000000..0199ef19b --- /dev/null +++ b/constraint/vendor/golang.org/x/sys/cpu/cpu_sparc64.go @@ -0,0 +1,12 @@ +// Copyright 2026 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build sparc64 + +package cpu + +// The L1 line is 32 bytes; false sharing is governed by the 64-byte L2 line. +const cacheLineSize = 64 + +func initOptions() {} diff --git a/constraint/vendor/golang.org/x/sys/unix/ifreq_linux.go b/constraint/vendor/golang.org/x/sys/unix/ifreq_linux.go index 309f5a2b0..3f7fa7664 100644 --- a/constraint/vendor/golang.org/x/sys/unix/ifreq_linux.go +++ b/constraint/vendor/golang.org/x/sys/unix/ifreq_linux.go @@ -22,7 +22,13 @@ import ( // fields can be get and set using the following methods: // - Uint16/SetUint16: flags // - Uint32/SetUint32: ifindex, metric, mtu -type Ifreq struct{ raw ifreq } +type Ifreq struct { + // Aligns the union for the accessors below, which cast it in place; + // the generated ifreq is all byte arrays, so its alignment is one. + _ [0]int64 + + raw ifreq +} // NewIfreq creates an Ifreq with the input network interface name after // validating the name does not exceed IFNAMSIZ-1 (trailing NULL required) diff --git a/constraint/vendor/golang.org/x/sys/unix/ioctl_linux.go b/constraint/vendor/golang.org/x/sys/unix/ioctl_linux.go index 7ca4fa12a..5589d4f66 100644 --- a/constraint/vendor/golang.org/x/sys/unix/ioctl_linux.go +++ b/constraint/vendor/golang.org/x/sys/unix/ioctl_linux.go @@ -332,3 +332,10 @@ func IoctlLoopSetStatus64(fd int, value *LoopInfo64) error { func IoctlLoopConfigure(fd int, value *LoopConfig) error { return ioctlPtr(fd, LOOP_CONFIGURE, unsafe.Pointer(value)) } + +// IoctlPidfdInfo fetches information about a pidfd. +// The Mask field of the info argument indicates which +// values to fetch. +func IoctlPidfdInfo(fd int, info *PidfdInfo) error { + return ioctlPtr(fd, PIDFD_GET_INFO, unsafe.Pointer(info)) +} diff --git a/constraint/vendor/golang.org/x/sys/unix/mkerrors.sh b/constraint/vendor/golang.org/x/sys/unix/mkerrors.sh index fa74cfe9e..9e907ac29 100644 --- a/constraint/vendor/golang.org/x/sys/unix/mkerrors.sh +++ b/constraint/vendor/golang.org/x/sys/unix/mkerrors.sh @@ -290,14 +290,7 @@ struct ltchars { #include #include -#if defined(__sparc__) -// On sparc{,64}, the kernel defines struct termios2 itself which clashes with the -// definition in glibc. As only the error constants are needed here, include the -// generic termibits.h (which is included by termbits.h on sparc). -#include -#else #include -#endif #ifndef PTRACE_GETREGS #define PTRACE_GETREGS 0xc @@ -544,7 +537,7 @@ ccflags="$@" $2 ~ /^LO_(KEY|NAME)_SIZE$/ || $2 ~ /^LOOP_(CLR|CTL|GET|SET)_/ || $2 == "LOOP_CONFIGURE" || - $2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|TCP|MCAST|EVFILT|NOTE|SHUT|PROT|MAP|MREMAP|MFD|T?PACKET|MSG|SCM|MCL|DT|MADV|PR|LOCAL|TCPOPT|UDP)_/ || + $2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|TCP|MCAST|EVFILT|NOTE|SHUT|PROT|MAP|MREMAP|MFD|MLOCK|T?PACKET|MSG|SCM|MCL|DT|MADV|PR|LOCAL|TCPOPT|UDP)_/ || $2 ~ /^NFC_(GENL|PROTO|COMM|RF|SE|DIRECTION|LLCP|SOCKPROTO)_/ || $2 ~ /^NFC_.*_(MAX)?SIZE$/ || $2 ~ /^PTP_/ || diff --git a/constraint/vendor/golang.org/x/sys/unix/syscall.go b/constraint/vendor/golang.org/x/sys/unix/syscall.go index 5ea74da98..8f27e7ecb 100644 --- a/constraint/vendor/golang.org/x/sys/unix/syscall.go +++ b/constraint/vendor/golang.org/x/sys/unix/syscall.go @@ -76,7 +76,7 @@ func BytePtrToString(p *byte) string { // Find NUL terminator. n := 0 for ptr := unsafe.Pointer(p); *(*byte)(ptr) != 0; n++ { - ptr = unsafe.Pointer(uintptr(ptr) + 1) + ptr = unsafe.Add(ptr, 1) } return string(unsafe.Slice(p, n)) diff --git a/constraint/vendor/golang.org/x/sys/unix/syscall_bsd.go b/constraint/vendor/golang.org/x/sys/unix/syscall_bsd.go index a00c3e545..035c2cd91 100644 --- a/constraint/vendor/golang.org/x/sys/unix/syscall_bsd.go +++ b/constraint/vendor/golang.org/x/sys/unix/syscall_bsd.go @@ -188,7 +188,7 @@ func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, _Socklen, error) { } sa.raw.Len = byte(3 + n) // 2 for Family, Len; 1 for NUL sa.raw.Family = AF_UNIX - for i := 0; i < n; i++ { + for i := range n { sa.raw.Path[i] = int8(name[i]) } return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil diff --git a/constraint/vendor/golang.org/x/sys/unix/syscall_linux.go b/constraint/vendor/golang.org/x/sys/unix/syscall_linux.go index 21e2bfa39..6926057e9 100644 --- a/constraint/vendor/golang.org/x/sys/unix/syscall_linux.go +++ b/constraint/vendor/golang.org/x/sys/unix/syscall_linux.go @@ -2363,7 +2363,7 @@ func (fh *FileHandle) Bytes() []byte { if n == 0 { return nil } - return unsafe.Slice((*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(&fh.fileHandle.Type))+4)), n) + return unsafe.Slice((*byte)(unsafe.Add(unsafe.Pointer(&fh.fileHandle.Type), 4)), n) } // NameToHandleAt wraps the name_to_handle_at system call; it obtains diff --git a/constraint/vendor/golang.org/x/sys/unix/zerrors_linux.go b/constraint/vendor/golang.org/x/sys/unix/zerrors_linux.go index 5bb51d7ae..45feb1245 100644 --- a/constraint/vendor/golang.org/x/sys/unix/zerrors_linux.go +++ b/constraint/vendor/golang.org/x/sys/unix/zerrors_linux.go @@ -2048,6 +2048,7 @@ const ( MINIX3_SUPER_MAGIC = 0x4d5a MINIX_SUPER_MAGIC = 0x137f MINIX_SUPER_MAGIC2 = 0x138f + MLOCK_ONFAULT = 0x1 MNT_DETACH = 0x2 MNT_EXPIRE = 0x4 MNT_FORCE = 0x1 @@ -3862,6 +3863,7 @@ const ( TIOCPKT_NOSTOP = 0x10 TIOCPKT_START = 0x8 TIOCPKT_STOP = 0x4 + TIOCSER_TEMT = 0x1 TIPC_ADDR_ID = 0x3 TIPC_ADDR_MCAST = 0x1 TIPC_ADDR_NAME = 0x2 diff --git a/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_386.go b/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_386.go index c0a8ea1de..6f74d4a0c 100644 --- a/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_386.go +++ b/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_386.go @@ -483,7 +483,6 @@ const ( TIOCSERGWILD = 0x5454 TIOCSERSETMULTI = 0x545b TIOCSERSWILD = 0x5455 - TIOCSER_TEMT = 0x1 TIOCSETD = 0x5423 TIOCSIG = 0x40045436 TIOCSISO7816 = 0xc0285443 diff --git a/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go b/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go index ff927c830..36c1f0b68 100644 --- a/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go +++ b/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go @@ -484,7 +484,6 @@ const ( TIOCSERGWILD = 0x5454 TIOCSERSETMULTI = 0x545b TIOCSERSWILD = 0x5455 - TIOCSER_TEMT = 0x1 TIOCSETD = 0x5423 TIOCSIG = 0x40045436 TIOCSISO7816 = 0xc0285443 diff --git a/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go b/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go index 55294eda5..c5512dbea 100644 --- a/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go +++ b/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go @@ -489,7 +489,6 @@ const ( TIOCSERGWILD = 0x5454 TIOCSERSETMULTI = 0x545b TIOCSERSWILD = 0x5455 - TIOCSER_TEMT = 0x1 TIOCSETD = 0x5423 TIOCSIG = 0x40045436 TIOCSISO7816 = 0xc0285443 diff --git a/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go b/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go index 5dac54c35..4dabfae07 100644 --- a/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go +++ b/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go @@ -483,7 +483,6 @@ const ( TIOCSERGWILD = 0x5454 TIOCSERSETMULTI = 0x545b TIOCSERSWILD = 0x5455 - TIOCSER_TEMT = 0x1 TIOCSETD = 0x5423 TIOCSIG = 0x40045436 TIOCSISO7816 = 0xc0285443 diff --git a/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go b/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go index 46ac1fcb2..ea97930f1 100644 --- a/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go +++ b/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go @@ -476,7 +476,6 @@ const ( TIOCSERGWILD = 0x5454 TIOCSERSETMULTI = 0x545b TIOCSERSWILD = 0x5455 - TIOCSER_TEMT = 0x1 TIOCSETD = 0x5423 TIOCSIG = 0x40045436 TIOCSISO7816 = 0xc0285443 diff --git a/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go b/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go index b55483e8a..0826a929e 100644 --- a/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go +++ b/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go @@ -481,7 +481,6 @@ const ( TIOCSERGWILD = 0x5489 TIOCSERSETMULTI = 0x5490 TIOCSERSWILD = 0x548a - TIOCSER_TEMT = 0x1 TIOCSETD = 0x7401 TIOCSETN = 0x740a TIOCSETP = 0x7409 diff --git a/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go b/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go index 71890c98a..139deedd9 100644 --- a/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go +++ b/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go @@ -481,7 +481,6 @@ const ( TIOCSERGWILD = 0x5489 TIOCSERSETMULTI = 0x5490 TIOCSERSWILD = 0x548a - TIOCSER_TEMT = 0x1 TIOCSETD = 0x7401 TIOCSETN = 0x740a TIOCSETP = 0x7409 diff --git a/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go b/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go index a78b6cc14..b8018af33 100644 --- a/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go +++ b/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go @@ -481,7 +481,6 @@ const ( TIOCSERGWILD = 0x5489 TIOCSERSETMULTI = 0x5490 TIOCSERSWILD = 0x548a - TIOCSER_TEMT = 0x1 TIOCSETD = 0x7401 TIOCSETN = 0x740a TIOCSETP = 0x7409 diff --git a/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go b/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go index d0e38ca73..deb5c2e6a 100644 --- a/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go +++ b/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go @@ -481,7 +481,6 @@ const ( TIOCSERGWILD = 0x5489 TIOCSERSETMULTI = 0x5490 TIOCSERSWILD = 0x548a - TIOCSER_TEMT = 0x1 TIOCSETD = 0x7401 TIOCSETN = 0x740a TIOCSETP = 0x7409 diff --git a/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go b/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go index c883e14c7..0603bf3a1 100644 --- a/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go +++ b/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go @@ -535,7 +535,6 @@ const ( TIOCSERGWILD = 0x5454 TIOCSERSETMULTI = 0x545b TIOCSERSWILD = 0x5455 - TIOCSER_TEMT = 0x1 TIOCSETC = 0x80067411 TIOCSETD = 0x5423 TIOCSETN = 0x8006740a diff --git a/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go b/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go index 1834273d4..5fa8a5d36 100644 --- a/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go +++ b/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go @@ -539,7 +539,6 @@ const ( TIOCSERGWILD = 0x5454 TIOCSERSETMULTI = 0x545b TIOCSERSWILD = 0x5455 - TIOCSER_TEMT = 0x1 TIOCSETC = 0x80067411 TIOCSETD = 0x5423 TIOCSETN = 0x8006740a diff --git a/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go b/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go index 39945dd9a..2733e9993 100644 --- a/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go +++ b/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go @@ -539,7 +539,6 @@ const ( TIOCSERGWILD = 0x5454 TIOCSERSETMULTI = 0x545b TIOCSERSWILD = 0x5455 - TIOCSER_TEMT = 0x1 TIOCSETC = 0x80067411 TIOCSETD = 0x5423 TIOCSETN = 0x8006740a diff --git a/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go b/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go index bc0f37241..1470172fd 100644 --- a/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go +++ b/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go @@ -486,7 +486,6 @@ const ( TIOCSERGWILD = 0x5454 TIOCSERSETMULTI = 0x545b TIOCSERSWILD = 0x5455 - TIOCSER_TEMT = 0x1 TIOCSETD = 0x5423 TIOCSIG = 0x40045436 TIOCSISO7816 = 0xc0285443 diff --git a/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go b/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go index 6e87bd659..1871579c5 100644 --- a/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go +++ b/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go @@ -545,7 +545,6 @@ const ( TIOCSERGWILD = 0x5454 TIOCSERSETMULTI = 0x545b TIOCSERSWILD = 0x5455 - TIOCSER_TEMT = 0x1 TIOCSETD = 0x5423 TIOCSIG = 0x40045436 TIOCSISO7816 = 0xc0285443 diff --git a/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go b/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go index 7e2b2e8a6..10881cf6d 100644 --- a/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go +++ b/constraint/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go @@ -14,21 +14,21 @@ const ( ASI_LEON_DFLUSH = 0x11 ASI_LEON_IFLUSH = 0x10 ASI_LEON_MMUFLUSH = 0x18 - B1000000 = 0x1008 + B1000000 = 0x100c B115200 = 0x1002 - B1152000 = 0x1009 - B1500000 = 0x100a - B2000000 = 0x100b + B1152000 = 0x100d + B1500000 = 0x100e + B153600 = 0x1006 + B2000000 = 0x100f B230400 = 0x1003 - B2500000 = 0x100c - B3000000 = 0x100d - B3500000 = 0x100e - B4000000 = 0x100f + B307200 = 0x1007 B460800 = 0x1004 - B500000 = 0x1005 + B500000 = 0x100a B57600 = 0x1001 - B576000 = 0x1006 - B921600 = 0x1007 + B576000 = 0x100b + B614400 = 0x1008 + B76800 = 0x1005 + B921600 = 0x1009 BLKALIGNOFF = 0x2000127a BLKBSZGET = 0x40081270 BLKBSZSET = 0x80081271 @@ -91,7 +91,7 @@ const ( FFDLY = 0x8000 FICLONE = 0x80049409 FICLONERANGE = 0x8020940d - FLUSHO = 0x1000 + FLUSHO = 0x2000 FS_IOC_ENABLE_VERITY = 0x80806685 FS_IOC_GETFLAGS = 0x40086601 FS_IOC_GET_ENCRYPTION_NONCE = 0x4010661b @@ -563,6 +563,9 @@ const ( TIOCM_CD = 0x40 TIOCM_CTS = 0x20 TIOCM_DSR = 0x100 + TIOCM_LOOP = 0x8000 + TIOCM_OUT1 = 0x2000 + TIOCM_OUT2 = 0x4000 TIOCM_RI = 0x80 TIOCM_RNG = 0x80 TIOCM_SR = 0x10 @@ -641,10 +644,11 @@ const ( UBI_IOCVOLRMBLK = 0x20004f08 UBI_IOCVOLUP = 0x80084f00 VDISCARD = 0xd + VDSUSP = 0xb VEOF = 0x4 - VEOL = 0xb - VEOL2 = 0x10 - VMIN = 0x6 + VEOL = 0x5 + VEOL2 = 0x6 + VMIN = 0x4 VREPRINT = 0xc VSTART = 0x8 VSTOP = 0x9 @@ -664,6 +668,7 @@ const ( WDIOC_KEEPALIVE = 0x40045705 WDIOC_SETOPTIONS = 0x40045704 WORDSIZE = 0x40 + WRAP = 0x20000 XCASE = 0x4 XTABS = 0x1800 _HIDIOCGRAWNAME = 0x40804804 diff --git a/constraint/vendor/golang.org/x/sys/unix/ztypes_linux.go b/constraint/vendor/golang.org/x/sys/unix/ztypes_linux.go index 526a0d5f4..538a18f27 100644 --- a/constraint/vendor/golang.org/x/sys/unix/ztypes_linux.go +++ b/constraint/vendor/golang.org/x/sys/unix/ztypes_linux.go @@ -4264,19 +4264,29 @@ type HwTstampConfig struct { } const ( - HWTSTAMP_FILTER_NONE = 0x0 - HWTSTAMP_FILTER_ALL = 0x1 - HWTSTAMP_FILTER_SOME = 0x2 - HWTSTAMP_FILTER_PTP_V1_L4_EVENT = 0x3 - HWTSTAMP_FILTER_PTP_V2_L4_EVENT = 0x6 - HWTSTAMP_FILTER_PTP_V2_L2_EVENT = 0x9 - HWTSTAMP_FILTER_PTP_V2_EVENT = 0xc + HWTSTAMP_FILTER_NONE = 0x0 + HWTSTAMP_FILTER_ALL = 0x1 + HWTSTAMP_FILTER_SOME = 0x2 + HWTSTAMP_FILTER_PTP_V1_L4_EVENT = 0x3 + HWTSTAMP_FILTER_PTP_V1_L4_SYNC = 0x4 + HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ = 0x5 + HWTSTAMP_FILTER_PTP_V2_L4_EVENT = 0x6 + HWTSTAMP_FILTER_PTP_V2_L4_SYNC = 0x7 + HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ = 0x8 + HWTSTAMP_FILTER_PTP_V2_L2_EVENT = 0x9 + HWTSTAMP_FILTER_PTP_V2_L2_SYNC = 0xa + HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ = 0xb + HWTSTAMP_FILTER_PTP_V2_EVENT = 0xc + HWTSTAMP_FILTER_PTP_V2_SYNC = 0xd + HWTSTAMP_FILTER_PTP_V2_DELAY_REQ = 0xe + HWTSTAMP_FILTER_NTP_ALL = 0xf ) const ( HWTSTAMP_TX_OFF = 0x0 HWTSTAMP_TX_ON = 0x1 HWTSTAMP_TX_ONESTEP_SYNC = 0x2 + HWTSTAMP_TX_ONESTEP_P2P = 0x3 ) type ( @@ -4541,6 +4551,48 @@ const ( LANDLOCK_RULE_PATH_BENEATH = 0x1 ) +const ( + PIDFD_SIGNAL_THREAD = 0x1 + PIDFD_SIGNAL_THREAD_GROUP = 0x2 + PIDFD_SIGNAL_PROCESS_GROUP = 0x4 + PIDFD_SELF_THREAD = -0x2710 + PIDFD_SELF_THREAD_GROUP = -0x2711 + PIDFD_SELF = -0x2710 + PIDFD_SELF_PROCESS = -0x2711 + PIDFD_INFO_PID = 0x1 + PIDFD_INFO_CREDS = 0x2 + PIDFD_INFO_CGROUPID = 0x4 + PIDFD_INFO_EXIT = 0x8 + PIDFD_INFO_COREDUMP = 0x10 + PIDFD_COREDUMPED = 0x1 + PIDFD_COREDUMP_SKIP = 0x2 + PIDFD_COREDUMP_USER = 0x4 + PIDFD_COREDUMP_ROOT = 0x8 + PIDFD_INFO_SIZE_VER0 = 0x40 + PIDFD_GET_INFO = 0xc048ff0b +) + +const SizeofPidfdInfo = 0x48 + +type PidfdInfo struct { + Mask uint64 + Cgroupid uint64 + Pid uint32 + Tgid uint32 + Ppid uint32 + Ruid uint32 + Rgid uint32 + Euid uint32 + Egid uint32 + Suid uint32 + Sgid uint32 + Fsuid uint32 + Fsgid uint32 + Exit_code int32 + Coredump_mask uint32 + _ uint32 +} + const ( IPC_CREAT = 0x200 IPC_EXCL = 0x400 @@ -6473,3 +6525,23 @@ type GPIOV2LineEvent struct { Line_seqno uint32 _ [6]uint32 } + +const ( + IPMI_MAX_ADDR_SIZE = 0x20 + IPMI_SYSTEM_INTERFACE_ADDR_TYPE = 0xc + IPMI_BMC_CHANNEL = 0xf + IPMI_RESPONSE_RECV_TYPE = 0x1 +) + +type IPMISystemInterfaceAddr struct { + Type int32 + Channel int16 + Lun uint8 + _ [1]byte +} +type IPMIMsg struct { + Netfn uint8 + Cmd uint8 + Len uint16 + Data *uint8 +} diff --git a/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_386.go b/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_386.go index aede1de7f..38658a345 100644 --- a/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_386.go +++ b/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_386.go @@ -680,7 +680,18 @@ const ( ) const ( - PIDFD_NONBLOCK = 0x800 + PIDFD_NONBLOCK = 0x800 + PIDFD_THREAD = 0x80 + PIDFD_GET_CGROUP_NAMESPACE = 0xff01 + PIDFD_GET_IPC_NAMESPACE = 0xff02 + PIDFD_GET_MNT_NAMESPACE = 0xff03 + PIDFD_GET_NET_NAMESPACE = 0xff04 + PIDFD_GET_PID_NAMESPACE = 0xff05 + PIDFD_GET_PID_FOR_CHILDREN_NAMESPACE = 0xff06 + PIDFD_GET_TIME_NAMESPACE = 0xff07 + PIDFD_GET_TIME_FOR_CHILDREN_NAMESPACE = 0xff08 + PIDFD_GET_USER_NAMESPACE = 0xff09 + PIDFD_GET_UTS_NAMESPACE = 0xff0a ) type SysvIpcPerm struct { @@ -715,3 +726,22 @@ type SysvShmDesc struct { const ( GPIO_GET_CHIPINFO_IOCTL = 0x8044b401 ) + +const ( + IPMICTL_SEND_COMMAND = 0x8014690d + IPMICTL_RECEIVE_MSG = 0xc018690c +) + +type IPMIReq struct { + Addr *uint8 + Len uint32 + Msgid int32 + Msg IPMIMsg +} +type IPMIRecv struct { + Recv_type int32 + Addr *uint8 + Addr_len uint32 + Msgid int32 + Msg IPMIMsg +} diff --git a/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go b/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go index bb3bc4dc2..267ffe05f 100644 --- a/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go +++ b/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go @@ -697,7 +697,18 @@ const ( ) const ( - PIDFD_NONBLOCK = 0x800 + PIDFD_NONBLOCK = 0x800 + PIDFD_THREAD = 0x80 + PIDFD_GET_CGROUP_NAMESPACE = 0xff01 + PIDFD_GET_IPC_NAMESPACE = 0xff02 + PIDFD_GET_MNT_NAMESPACE = 0xff03 + PIDFD_GET_NET_NAMESPACE = 0xff04 + PIDFD_GET_PID_NAMESPACE = 0xff05 + PIDFD_GET_PID_FOR_CHILDREN_NAMESPACE = 0xff06 + PIDFD_GET_TIME_NAMESPACE = 0xff07 + PIDFD_GET_TIME_FOR_CHILDREN_NAMESPACE = 0xff08 + PIDFD_GET_USER_NAMESPACE = 0xff09 + PIDFD_GET_UTS_NAMESPACE = 0xff0a ) type SysvIpcPerm struct { @@ -729,3 +740,22 @@ type SysvShmDesc struct { const ( GPIO_GET_CHIPINFO_IOCTL = 0x8044b401 ) + +const ( + IPMICTL_SEND_COMMAND = 0x8028690d + IPMICTL_RECEIVE_MSG = 0xc030690c +) + +type IPMIReq struct { + Addr *uint8 + Len uint32 + Msgid int64 + Msg IPMIMsg +} +type IPMIRecv struct { + Recv_type int32 + Addr *uint8 + Addr_len uint32 + Msgid int64 + Msg IPMIMsg +} diff --git a/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go b/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go index 1fdf4c517..ec459d5f3 100644 --- a/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go +++ b/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go @@ -674,7 +674,18 @@ const ( ) const ( - PIDFD_NONBLOCK = 0x800 + PIDFD_NONBLOCK = 0x800 + PIDFD_THREAD = 0x80 + PIDFD_GET_CGROUP_NAMESPACE = 0xff01 + PIDFD_GET_IPC_NAMESPACE = 0xff02 + PIDFD_GET_MNT_NAMESPACE = 0xff03 + PIDFD_GET_NET_NAMESPACE = 0xff04 + PIDFD_GET_PID_NAMESPACE = 0xff05 + PIDFD_GET_PID_FOR_CHILDREN_NAMESPACE = 0xff06 + PIDFD_GET_TIME_NAMESPACE = 0xff07 + PIDFD_GET_TIME_FOR_CHILDREN_NAMESPACE = 0xff08 + PIDFD_GET_USER_NAMESPACE = 0xff09 + PIDFD_GET_UTS_NAMESPACE = 0xff0a ) type SysvIpcPerm struct { @@ -709,3 +720,22 @@ type SysvShmDesc struct { const ( GPIO_GET_CHIPINFO_IOCTL = 0x8044b401 ) + +const ( + IPMICTL_SEND_COMMAND = 0x8014690d + IPMICTL_RECEIVE_MSG = 0xc018690c +) + +type IPMIReq struct { + Addr *uint8 + Len uint32 + Msgid int32 + Msg IPMIMsg +} +type IPMIRecv struct { + Recv_type int32 + Addr *uint8 + Addr_len uint32 + Msgid int32 + Msg IPMIMsg +} diff --git a/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go b/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go index 063e6f0b4..fa45ab7d2 100644 --- a/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go +++ b/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go @@ -676,7 +676,18 @@ const ( ) const ( - PIDFD_NONBLOCK = 0x800 + PIDFD_NONBLOCK = 0x800 + PIDFD_THREAD = 0x80 + PIDFD_GET_CGROUP_NAMESPACE = 0xff01 + PIDFD_GET_IPC_NAMESPACE = 0xff02 + PIDFD_GET_MNT_NAMESPACE = 0xff03 + PIDFD_GET_NET_NAMESPACE = 0xff04 + PIDFD_GET_PID_NAMESPACE = 0xff05 + PIDFD_GET_PID_FOR_CHILDREN_NAMESPACE = 0xff06 + PIDFD_GET_TIME_NAMESPACE = 0xff07 + PIDFD_GET_TIME_FOR_CHILDREN_NAMESPACE = 0xff08 + PIDFD_GET_USER_NAMESPACE = 0xff09 + PIDFD_GET_UTS_NAMESPACE = 0xff0a ) type SysvIpcPerm struct { @@ -708,3 +719,22 @@ type SysvShmDesc struct { const ( GPIO_GET_CHIPINFO_IOCTL = 0x8044b401 ) + +const ( + IPMICTL_SEND_COMMAND = 0x8028690d + IPMICTL_RECEIVE_MSG = 0xc030690c +) + +type IPMIReq struct { + Addr *uint8 + Len uint32 + Msgid int64 + Msg IPMIMsg +} +type IPMIRecv struct { + Recv_type int32 + Addr *uint8 + Addr_len uint32 + Msgid int64 + Msg IPMIMsg +} diff --git a/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go b/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go index 9cf836c70..3da72ccdf 100644 --- a/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go +++ b/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go @@ -677,7 +677,18 @@ const ( ) const ( - PIDFD_NONBLOCK = 0x800 + PIDFD_NONBLOCK = 0x800 + PIDFD_THREAD = 0x80 + PIDFD_GET_CGROUP_NAMESPACE = 0xff01 + PIDFD_GET_IPC_NAMESPACE = 0xff02 + PIDFD_GET_MNT_NAMESPACE = 0xff03 + PIDFD_GET_NET_NAMESPACE = 0xff04 + PIDFD_GET_PID_NAMESPACE = 0xff05 + PIDFD_GET_PID_FOR_CHILDREN_NAMESPACE = 0xff06 + PIDFD_GET_TIME_NAMESPACE = 0xff07 + PIDFD_GET_TIME_FOR_CHILDREN_NAMESPACE = 0xff08 + PIDFD_GET_USER_NAMESPACE = 0xff09 + PIDFD_GET_UTS_NAMESPACE = 0xff0a ) type SysvIpcPerm struct { @@ -709,3 +720,22 @@ type SysvShmDesc struct { const ( GPIO_GET_CHIPINFO_IOCTL = 0x8044b401 ) + +const ( + IPMICTL_SEND_COMMAND = 0x8028690d + IPMICTL_RECEIVE_MSG = 0xc030690c +) + +type IPMIReq struct { + Addr *uint8 + Len uint32 + Msgid int64 + Msg IPMIMsg +} +type IPMIRecv struct { + Recv_type int32 + Addr *uint8 + Addr_len uint32 + Msgid int64 + Msg IPMIMsg +} diff --git a/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go b/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go index 1d222fcb3..78f8c6d55 100644 --- a/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go +++ b/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go @@ -680,7 +680,18 @@ const ( ) const ( - PIDFD_NONBLOCK = 0x80 + PIDFD_NONBLOCK = 0x80 + PIDFD_THREAD = 0x400 + PIDFD_GET_CGROUP_NAMESPACE = 0x2000ff01 + PIDFD_GET_IPC_NAMESPACE = 0x2000ff02 + PIDFD_GET_MNT_NAMESPACE = 0x2000ff03 + PIDFD_GET_NET_NAMESPACE = 0x2000ff04 + PIDFD_GET_PID_NAMESPACE = 0x2000ff05 + PIDFD_GET_PID_FOR_CHILDREN_NAMESPACE = 0x2000ff06 + PIDFD_GET_TIME_NAMESPACE = 0x2000ff07 + PIDFD_GET_TIME_FOR_CHILDREN_NAMESPACE = 0x2000ff08 + PIDFD_GET_USER_NAMESPACE = 0x2000ff09 + PIDFD_GET_UTS_NAMESPACE = 0x2000ff0a ) type SysvIpcPerm struct { @@ -714,3 +725,22 @@ type SysvShmDesc struct { const ( GPIO_GET_CHIPINFO_IOCTL = 0x4044b401 ) + +const ( + IPMICTL_SEND_COMMAND = 0x4014690d + IPMICTL_RECEIVE_MSG = 0xc018690c +) + +type IPMIReq struct { + Addr *uint8 + Len uint32 + Msgid int32 + Msg IPMIMsg +} +type IPMIRecv struct { + Recv_type int32 + Addr *uint8 + Addr_len uint32 + Msgid int32 + Msg IPMIMsg +} diff --git a/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go b/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go index 912cc4ab6..bbd4c6c2b 100644 --- a/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go +++ b/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go @@ -679,7 +679,18 @@ const ( ) const ( - PIDFD_NONBLOCK = 0x80 + PIDFD_NONBLOCK = 0x80 + PIDFD_THREAD = 0x400 + PIDFD_GET_CGROUP_NAMESPACE = 0x2000ff01 + PIDFD_GET_IPC_NAMESPACE = 0x2000ff02 + PIDFD_GET_MNT_NAMESPACE = 0x2000ff03 + PIDFD_GET_NET_NAMESPACE = 0x2000ff04 + PIDFD_GET_PID_NAMESPACE = 0x2000ff05 + PIDFD_GET_PID_FOR_CHILDREN_NAMESPACE = 0x2000ff06 + PIDFD_GET_TIME_NAMESPACE = 0x2000ff07 + PIDFD_GET_TIME_FOR_CHILDREN_NAMESPACE = 0x2000ff08 + PIDFD_GET_USER_NAMESPACE = 0x2000ff09 + PIDFD_GET_UTS_NAMESPACE = 0x2000ff0a ) type SysvIpcPerm struct { @@ -711,3 +722,22 @@ type SysvShmDesc struct { const ( GPIO_GET_CHIPINFO_IOCTL = 0x4044b401 ) + +const ( + IPMICTL_SEND_COMMAND = 0x4028690d + IPMICTL_RECEIVE_MSG = 0xc030690c +) + +type IPMIReq struct { + Addr *uint8 + Len uint32 + Msgid int64 + Msg IPMIMsg +} +type IPMIRecv struct { + Recv_type int32 + Addr *uint8 + Addr_len uint32 + Msgid int64 + Msg IPMIMsg +} diff --git a/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go b/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go index 1e358ef34..644d31d6a 100644 --- a/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go +++ b/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go @@ -679,7 +679,18 @@ const ( ) const ( - PIDFD_NONBLOCK = 0x80 + PIDFD_NONBLOCK = 0x80 + PIDFD_THREAD = 0x400 + PIDFD_GET_CGROUP_NAMESPACE = 0x2000ff01 + PIDFD_GET_IPC_NAMESPACE = 0x2000ff02 + PIDFD_GET_MNT_NAMESPACE = 0x2000ff03 + PIDFD_GET_NET_NAMESPACE = 0x2000ff04 + PIDFD_GET_PID_NAMESPACE = 0x2000ff05 + PIDFD_GET_PID_FOR_CHILDREN_NAMESPACE = 0x2000ff06 + PIDFD_GET_TIME_NAMESPACE = 0x2000ff07 + PIDFD_GET_TIME_FOR_CHILDREN_NAMESPACE = 0x2000ff08 + PIDFD_GET_USER_NAMESPACE = 0x2000ff09 + PIDFD_GET_UTS_NAMESPACE = 0x2000ff0a ) type SysvIpcPerm struct { @@ -711,3 +722,22 @@ type SysvShmDesc struct { const ( GPIO_GET_CHIPINFO_IOCTL = 0x4044b401 ) + +const ( + IPMICTL_SEND_COMMAND = 0x4028690d + IPMICTL_RECEIVE_MSG = 0xc030690c +) + +type IPMIReq struct { + Addr *uint8 + Len uint32 + Msgid int64 + Msg IPMIMsg +} +type IPMIRecv struct { + Recv_type int32 + Addr *uint8 + Addr_len uint32 + Msgid int64 + Msg IPMIMsg +} diff --git a/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go b/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go index df59f32f5..a976f6267 100644 --- a/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go +++ b/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go @@ -680,7 +680,18 @@ const ( ) const ( - PIDFD_NONBLOCK = 0x80 + PIDFD_NONBLOCK = 0x80 + PIDFD_THREAD = 0x400 + PIDFD_GET_CGROUP_NAMESPACE = 0x2000ff01 + PIDFD_GET_IPC_NAMESPACE = 0x2000ff02 + PIDFD_GET_MNT_NAMESPACE = 0x2000ff03 + PIDFD_GET_NET_NAMESPACE = 0x2000ff04 + PIDFD_GET_PID_NAMESPACE = 0x2000ff05 + PIDFD_GET_PID_FOR_CHILDREN_NAMESPACE = 0x2000ff06 + PIDFD_GET_TIME_NAMESPACE = 0x2000ff07 + PIDFD_GET_TIME_FOR_CHILDREN_NAMESPACE = 0x2000ff08 + PIDFD_GET_USER_NAMESPACE = 0x2000ff09 + PIDFD_GET_UTS_NAMESPACE = 0x2000ff0a ) type SysvIpcPerm struct { @@ -714,3 +725,22 @@ type SysvShmDesc struct { const ( GPIO_GET_CHIPINFO_IOCTL = 0x4044b401 ) + +const ( + IPMICTL_SEND_COMMAND = 0x4014690d + IPMICTL_RECEIVE_MSG = 0xc018690c +) + +type IPMIReq struct { + Addr *uint8 + Len uint32 + Msgid int32 + Msg IPMIMsg +} +type IPMIRecv struct { + Recv_type int32 + Addr *uint8 + Addr_len uint32 + Msgid int32 + Msg IPMIMsg +} diff --git a/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go b/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go index 29355aa0b..46324695f 100644 --- a/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go +++ b/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go @@ -686,7 +686,18 @@ const ( ) const ( - PIDFD_NONBLOCK = 0x800 + PIDFD_NONBLOCK = 0x800 + PIDFD_THREAD = 0x80 + PIDFD_GET_CGROUP_NAMESPACE = 0x2000ff01 + PIDFD_GET_IPC_NAMESPACE = 0x2000ff02 + PIDFD_GET_MNT_NAMESPACE = 0x2000ff03 + PIDFD_GET_NET_NAMESPACE = 0x2000ff04 + PIDFD_GET_PID_NAMESPACE = 0x2000ff05 + PIDFD_GET_PID_FOR_CHILDREN_NAMESPACE = 0x2000ff06 + PIDFD_GET_TIME_NAMESPACE = 0x2000ff07 + PIDFD_GET_TIME_FOR_CHILDREN_NAMESPACE = 0x2000ff08 + PIDFD_GET_USER_NAMESPACE = 0x2000ff09 + PIDFD_GET_UTS_NAMESPACE = 0x2000ff0a ) type SysvIpcPerm struct { @@ -722,3 +733,22 @@ type SysvShmDesc struct { const ( GPIO_GET_CHIPINFO_IOCTL = 0x4044b401 ) + +const ( + IPMICTL_SEND_COMMAND = 0x4014690d + IPMICTL_RECEIVE_MSG = 0xc018690c +) + +type IPMIReq struct { + Addr *uint8 + Len uint32 + Msgid int32 + Msg IPMIMsg +} +type IPMIRecv struct { + Recv_type int32 + Addr *uint8 + Addr_len uint32 + Msgid int32 + Msg IPMIMsg +} diff --git a/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go b/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go index c6083a15d..cbc303974 100644 --- a/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go +++ b/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go @@ -686,7 +686,18 @@ const ( ) const ( - PIDFD_NONBLOCK = 0x800 + PIDFD_NONBLOCK = 0x800 + PIDFD_THREAD = 0x80 + PIDFD_GET_CGROUP_NAMESPACE = 0x2000ff01 + PIDFD_GET_IPC_NAMESPACE = 0x2000ff02 + PIDFD_GET_MNT_NAMESPACE = 0x2000ff03 + PIDFD_GET_NET_NAMESPACE = 0x2000ff04 + PIDFD_GET_PID_NAMESPACE = 0x2000ff05 + PIDFD_GET_PID_FOR_CHILDREN_NAMESPACE = 0x2000ff06 + PIDFD_GET_TIME_NAMESPACE = 0x2000ff07 + PIDFD_GET_TIME_FOR_CHILDREN_NAMESPACE = 0x2000ff08 + PIDFD_GET_USER_NAMESPACE = 0x2000ff09 + PIDFD_GET_UTS_NAMESPACE = 0x2000ff0a ) type SysvIpcPerm struct { @@ -717,3 +728,22 @@ type SysvShmDesc struct { const ( GPIO_GET_CHIPINFO_IOCTL = 0x4044b401 ) + +const ( + IPMICTL_SEND_COMMAND = 0x4028690d + IPMICTL_RECEIVE_MSG = 0xc030690c +) + +type IPMIReq struct { + Addr *uint8 + Len uint32 + Msgid int64 + Msg IPMIMsg +} +type IPMIRecv struct { + Recv_type int32 + Addr *uint8 + Addr_len uint32 + Msgid int64 + Msg IPMIMsg +} diff --git a/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go b/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go index 6321cc762..b47f7b498 100644 --- a/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go +++ b/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go @@ -686,7 +686,18 @@ const ( ) const ( - PIDFD_NONBLOCK = 0x800 + PIDFD_NONBLOCK = 0x800 + PIDFD_THREAD = 0x80 + PIDFD_GET_CGROUP_NAMESPACE = 0x2000ff01 + PIDFD_GET_IPC_NAMESPACE = 0x2000ff02 + PIDFD_GET_MNT_NAMESPACE = 0x2000ff03 + PIDFD_GET_NET_NAMESPACE = 0x2000ff04 + PIDFD_GET_PID_NAMESPACE = 0x2000ff05 + PIDFD_GET_PID_FOR_CHILDREN_NAMESPACE = 0x2000ff06 + PIDFD_GET_TIME_NAMESPACE = 0x2000ff07 + PIDFD_GET_TIME_FOR_CHILDREN_NAMESPACE = 0x2000ff08 + PIDFD_GET_USER_NAMESPACE = 0x2000ff09 + PIDFD_GET_UTS_NAMESPACE = 0x2000ff0a ) type SysvIpcPerm struct { @@ -717,3 +728,22 @@ type SysvShmDesc struct { const ( GPIO_GET_CHIPINFO_IOCTL = 0x4044b401 ) + +const ( + IPMICTL_SEND_COMMAND = 0x4028690d + IPMICTL_RECEIVE_MSG = 0xc030690c +) + +type IPMIReq struct { + Addr *uint8 + Len uint32 + Msgid int64 + Msg IPMIMsg +} +type IPMIRecv struct { + Recv_type int32 + Addr *uint8 + Addr_len uint32 + Msgid int64 + Msg IPMIMsg +} diff --git a/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go b/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go index b44f402fe..cb16add54 100644 --- a/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go +++ b/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go @@ -704,7 +704,18 @@ const ( ) const ( - PIDFD_NONBLOCK = 0x800 + PIDFD_NONBLOCK = 0x800 + PIDFD_THREAD = 0x80 + PIDFD_GET_CGROUP_NAMESPACE = 0xff01 + PIDFD_GET_IPC_NAMESPACE = 0xff02 + PIDFD_GET_MNT_NAMESPACE = 0xff03 + PIDFD_GET_NET_NAMESPACE = 0xff04 + PIDFD_GET_PID_NAMESPACE = 0xff05 + PIDFD_GET_PID_FOR_CHILDREN_NAMESPACE = 0xff06 + PIDFD_GET_TIME_NAMESPACE = 0xff07 + PIDFD_GET_TIME_FOR_CHILDREN_NAMESPACE = 0xff08 + PIDFD_GET_USER_NAMESPACE = 0xff09 + PIDFD_GET_UTS_NAMESPACE = 0xff0a ) type SysvIpcPerm struct { @@ -796,3 +807,22 @@ const ( const ( GPIO_GET_CHIPINFO_IOCTL = 0x8044b401 ) + +const ( + IPMICTL_SEND_COMMAND = 0x8028690d + IPMICTL_RECEIVE_MSG = 0xc030690c +) + +type IPMIReq struct { + Addr *uint8 + Len uint32 + Msgid int64 + Msg IPMIMsg +} +type IPMIRecv struct { + Recv_type int32 + Addr *uint8 + Addr_len uint32 + Msgid int64 + Msg IPMIMsg +} diff --git a/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go b/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go index b22c795a6..a57ab8fad 100644 --- a/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go +++ b/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go @@ -700,7 +700,18 @@ const ( ) const ( - PIDFD_NONBLOCK = 0x800 + PIDFD_NONBLOCK = 0x800 + PIDFD_THREAD = 0x80 + PIDFD_GET_CGROUP_NAMESPACE = 0xff01 + PIDFD_GET_IPC_NAMESPACE = 0xff02 + PIDFD_GET_MNT_NAMESPACE = 0xff03 + PIDFD_GET_NET_NAMESPACE = 0xff04 + PIDFD_GET_PID_NAMESPACE = 0xff05 + PIDFD_GET_PID_FOR_CHILDREN_NAMESPACE = 0xff06 + PIDFD_GET_TIME_NAMESPACE = 0xff07 + PIDFD_GET_TIME_FOR_CHILDREN_NAMESPACE = 0xff08 + PIDFD_GET_USER_NAMESPACE = 0xff09 + PIDFD_GET_UTS_NAMESPACE = 0xff0a ) type SysvIpcPerm struct { @@ -731,3 +742,22 @@ type SysvShmDesc struct { const ( GPIO_GET_CHIPINFO_IOCTL = 0x8044b401 ) + +const ( + IPMICTL_SEND_COMMAND = 0x8028690d + IPMICTL_RECEIVE_MSG = 0xc030690c +) + +type IPMIReq struct { + Addr *uint8 + Len uint32 + Msgid int64 + Msg IPMIMsg +} +type IPMIRecv struct { + Recv_type int32 + Addr *uint8 + Addr_len uint32 + Msgid int64 + Msg IPMIMsg +} diff --git a/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go b/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go index 0b18075b5..bf99635d8 100644 --- a/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go +++ b/constraint/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go @@ -681,7 +681,18 @@ const ( ) const ( - PIDFD_NONBLOCK = 0x4000 + PIDFD_NONBLOCK = 0x4000 + PIDFD_THREAD = 0x800 + PIDFD_GET_CGROUP_NAMESPACE = 0x2000ff01 + PIDFD_GET_IPC_NAMESPACE = 0x2000ff02 + PIDFD_GET_MNT_NAMESPACE = 0x2000ff03 + PIDFD_GET_NET_NAMESPACE = 0x2000ff04 + PIDFD_GET_PID_NAMESPACE = 0x2000ff05 + PIDFD_GET_PID_FOR_CHILDREN_NAMESPACE = 0x2000ff06 + PIDFD_GET_TIME_NAMESPACE = 0x2000ff07 + PIDFD_GET_TIME_FOR_CHILDREN_NAMESPACE = 0x2000ff08 + PIDFD_GET_USER_NAMESPACE = 0x2000ff09 + PIDFD_GET_UTS_NAMESPACE = 0x2000ff0a ) type SysvIpcPerm struct { @@ -712,3 +723,22 @@ type SysvShmDesc struct { const ( GPIO_GET_CHIPINFO_IOCTL = 0x4044b401 ) + +const ( + IPMICTL_SEND_COMMAND = 0x4028690d + IPMICTL_RECEIVE_MSG = 0xc030690c +) + +type IPMIReq struct { + Addr *uint8 + Len uint32 + Msgid int64 + Msg IPMIMsg +} +type IPMIRecv struct { + Recv_type int32 + Addr *uint8 + Addr_len uint32 + Msgid int64 + Msg IPMIMsg +} diff --git a/constraint/vendor/golang.org/x/sys/windows/types_windows.go b/constraint/vendor/golang.org/x/sys/windows/types_windows.go index 75a50b316..643737d45 100644 --- a/constraint/vendor/golang.org/x/sys/windows/types_windows.go +++ b/constraint/vendor/golang.org/x/sys/windows/types_windows.go @@ -1065,6 +1065,7 @@ const ( SO_BROADCAST = 32 SO_LINGER = 128 SO_RCVBUF = 0x1002 + SO_SNDTIMEO = 0x1005 SO_RCVTIMEO = 0x1006 SO_SNDBUF = 0x1001 SO_UPDATE_ACCEPT_CONTEXT = 0x700b diff --git a/constraint/vendor/golang.org/x/term/terminal.go b/constraint/vendor/golang.org/x/term/terminal.go index 6ec537cdc..e8327c83f 100644 --- a/constraint/vendor/golang.org/x/term/terminal.go +++ b/constraint/vendor/golang.org/x/term/terminal.go @@ -106,6 +106,9 @@ type Terminal struct { // a read. It aliases into inBuf. remainder []byte inBuf [256]byte + // readErr is an error returned by a read that also returned data. It is + // reported after all of that data has been processed. + readErr error // History records and retrieves lines of input read by [ReadLine] which // a user can retrieve and navigate using the up and down arrow keys. @@ -788,7 +791,11 @@ func (t *Terminal) ReadPassword(prompt string) (line string, err error) { return } -// ReadLine returns a line of input from the terminal. +// ReadLine returns a line of input from the terminal, excluding the +// trailing newline. It may return partial data along with an error. +// An [io.EOF] error indicates the end of the stream. For other errors, +// such as [ErrPasteIndicator] in bracketed paste mode, a subsequent +// call may return more data. func (t *Terminal) ReadLine() (line string, err error) { t.lock.Lock() defer t.lock.Unlock() @@ -863,21 +870,24 @@ func (t *Terminal) readLine() (line string, err error) { } return } + if t.readErr != nil { + err = t.readErr + t.readErr = nil + return + } // t.remainder is a slice at the beginning of t.inBuf // containing a partial key sequence readBuf := t.inBuf[len(t.remainder):] - var n int t.lock.Unlock() - n, err = t.c.Read(readBuf) + n, readErr := t.c.Read(readBuf) t.lock.Lock() - if err != nil { - return - } - t.remainder = t.inBuf[:n+len(t.remainder)] + if readErr != nil { + t.readErr = readErr + } } } diff --git a/constraint/vendor/golang.org/x/text/encoding/japanese/iso2022jp.go b/constraint/vendor/golang.org/x/text/encoding/japanese/iso2022jp.go index 6f7bd460a..10fbd86bc 100644 --- a/constraint/vendor/golang.org/x/text/encoding/japanese/iso2022jp.go +++ b/constraint/vendor/golang.org/x/text/encoding/japanese/iso2022jp.go @@ -14,6 +14,16 @@ import ( ) // ISO2022JP is the ISO-2022-JP encoding. +// +// Decoding accepts ISO-2022-JP as specified in RFC 2237, +// which includes support for inputs which are not supported by +// the intentionally more restrictive WHATWG Encoding Standard, +// such as JIS X 0212 and half-width Katakana characters. +// +// Encoding always produces output that is valid according to WHATWG. +// +// Programs which forward inputs after parsing should take care to +// re-encode the parsed input for forwarding. var ISO2022JP encoding.Encoding = &iso2022JP var iso2022JP = internal.Encoding{ diff --git a/constraint/vendor/golang.org/x/text/unicode/bidi/core.go b/constraint/vendor/golang.org/x/text/unicode/bidi/core.go index fb8273236..e28ac8c8a 100644 --- a/constraint/vendor/golang.org/x/text/unicode/bidi/core.go +++ b/constraint/vendor/golang.org/x/text/unicode/bidi/core.go @@ -6,7 +6,6 @@ package bidi import ( "fmt" - "log" ) // This implementation is a port based on the reference implementation found at: @@ -248,7 +247,7 @@ func (p *paragraph) determineParagraphEmbeddingLevel(start, end int) level { } else if t.in(FSI, LRI, RLI) { i = p.matchingPDI[i] // skip over to the matching PDI if i > end { - log.Panic("assert (i <= end)") + panic("assert (i <= end)") } } } @@ -729,7 +728,7 @@ loop: continue loop } } - log.Panicf("invalid bidi code %v present in assertOnly at position %d", t, s.indexes[i]) + panic(fmt.Errorf("invalid bidi code %v present in assertOnly at position %d", t, s.indexes[i])) } } diff --git a/constraint/vendor/golang.org/x/text/unicode/norm/composition.go b/constraint/vendor/golang.org/x/text/unicode/norm/composition.go index e2087bce5..e024e74b9 100644 --- a/constraint/vendor/golang.org/x/text/unicode/norm/composition.go +++ b/constraint/vendor/golang.org/x/text/unicode/norm/composition.go @@ -449,6 +449,16 @@ func (rb *reorderBuffer) combineHangul(s, i, k int) { // ACxx plus 11Ax to LVT rb.assignRune(s, l+v-jamoTBase) default: + // Not a Hangul composition. The segment may still + // contain regular canonical compositions, such as + // combining marks following a Hangul syllable, so + // fall back to the composition table. + if b[i].combinesBackward() { + if combined := combine(l, v); combined != 0 { + rb.assignRune(s, combined) + continue + } + } b[k] = b[i] k++ } @@ -484,25 +494,27 @@ func (rb *reorderBuffer) compose() { return } ii := b[i] + // Track the last starter unconditionally: b[i] must be blocked by + // any starter between it and s, even one that b[i] itself cannot + // combine with, and even if the runes in between never enter the + // combinesBackward branch below. + cccB := b[k-1].ccc + cccC := ii.ccc + blocked := false // b[i] blocked by starter or greater or equal CCC? + if cccB == 0 { + s = k - 1 + } else { + blocked = s != k-1 && cccB >= cccC + } // We can only use combineForward as a filter if we later // get the info for the combined character. This is more // expensive than using the filter. Using combinesBackward() // is safe. - if ii.combinesBackward() { - cccB := b[k-1].ccc - cccC := ii.ccc - blocked := false // b[i] blocked by starter or greater or equal CCC? - if cccB == 0 { - s = k - 1 - } else { - blocked = s != k-1 && cccB >= cccC - } - if !blocked { - combined := combine(rb.runeAt(s), rb.runeAt(i)) - if combined != 0 { - rb.assignRune(s, combined) - continue - } + if ii.combinesBackward() && !blocked { + combined := combine(rb.runeAt(s), rb.runeAt(i)) + if combined != 0 { + rb.assignRune(s, combined) + continue } } b[k] = b[i] diff --git a/constraint/vendor/golang.org/x/text/unicode/norm/forminfo.go b/constraint/vendor/golang.org/x/text/unicode/norm/forminfo.go index b3cf5d9bd..956708eec 100644 --- a/constraint/vendor/golang.org/x/text/unicode/norm/forminfo.go +++ b/constraint/vendor/golang.org/x/text/unicode/norm/forminfo.go @@ -191,30 +191,30 @@ func (p Properties) TrailCCC() uint8 { return ccc[p.tccc] } +// Recomposition +// Each entry of recompMapPacked holds the two runes of the key and the +// composed rune of the value packed into a big-endian uint64 as three +// 21-bit fields, which is wide enough for any rune. +// Note that the recomposition map for NFC and NFKC are identical. + +const recompShift = 21 + func buildRecompMap() { - recompMap = make(map[uint32]rune, len(recompMapPacked)/8) + recompMap = make(map[uint64]rune, len(recompMapPacked)/8) var buf [8]byte for i := 0; i < len(recompMapPacked); i += 8 { copy(buf[:], recompMapPacked[i:i+8]) - key := binary.BigEndian.Uint32(buf[:4]) - val := binary.BigEndian.Uint32(buf[4:]) - recompMap[key] = rune(val) + e := binary.BigEndian.Uint64(buf[:]) + recompMap[e>>recompShift] = rune(e & (1<" + // 0x006C030C: 0x0000013E - "\x00N\x03\x01\x00\x00\x01C" + // 0x004E0301: 0x00000143 - "\x00n\x03\x01\x00\x00\x01D" + // 0x006E0301: 0x00000144 - "\x00N\x03'\x00\x00\x01E" + // 0x004E0327: 0x00000145 - "\x00n\x03'\x00\x00\x01F" + // 0x006E0327: 0x00000146 - "\x00N\x03\f\x00\x00\x01G" + // 0x004E030C: 0x00000147 - "\x00n\x03\f\x00\x00\x01H" + // 0x006E030C: 0x00000148 - "\x00O\x03\x04\x00\x00\x01L" + // 0x004F0304: 0x0000014C - "\x00o\x03\x04\x00\x00\x01M" + // 0x006F0304: 0x0000014D - "\x00O\x03\x06\x00\x00\x01N" + // 0x004F0306: 0x0000014E - "\x00o\x03\x06\x00\x00\x01O" + // 0x006F0306: 0x0000014F - "\x00O\x03\v\x00\x00\x01P" + // 0x004F030B: 0x00000150 - "\x00o\x03\v\x00\x00\x01Q" + // 0x006F030B: 0x00000151 - "\x00R\x03\x01\x00\x00\x01T" + // 0x00520301: 0x00000154 - "\x00r\x03\x01\x00\x00\x01U" + // 0x00720301: 0x00000155 - "\x00R\x03'\x00\x00\x01V" + // 0x00520327: 0x00000156 - "\x00r\x03'\x00\x00\x01W" + // 0x00720327: 0x00000157 - "\x00R\x03\f\x00\x00\x01X" + // 0x0052030C: 0x00000158 - "\x00r\x03\f\x00\x00\x01Y" + // 0x0072030C: 0x00000159 - "\x00S\x03\x01\x00\x00\x01Z" + // 0x00530301: 0x0000015A - "\x00s\x03\x01\x00\x00\x01[" + // 0x00730301: 0x0000015B - "\x00S\x03\x02\x00\x00\x01\\" + // 0x00530302: 0x0000015C - "\x00s\x03\x02\x00\x00\x01]" + // 0x00730302: 0x0000015D - "\x00S\x03'\x00\x00\x01^" + // 0x00530327: 0x0000015E - "\x00s\x03'\x00\x00\x01_" + // 0x00730327: 0x0000015F - "\x00S\x03\f\x00\x00\x01`" + // 0x0053030C: 0x00000160 - "\x00s\x03\f\x00\x00\x01a" + // 0x0073030C: 0x00000161 - "\x00T\x03'\x00\x00\x01b" + // 0x00540327: 0x00000162 - "\x00t\x03'\x00\x00\x01c" + // 0x00740327: 0x00000163 - "\x00T\x03\f\x00\x00\x01d" + // 0x0054030C: 0x00000164 - "\x00t\x03\f\x00\x00\x01e" + // 0x0074030C: 0x00000165 - "\x00U\x03\x03\x00\x00\x01h" + // 0x00550303: 0x00000168 - "\x00u\x03\x03\x00\x00\x01i" + // 0x00750303: 0x00000169 - "\x00U\x03\x04\x00\x00\x01j" + // 0x00550304: 0x0000016A - "\x00u\x03\x04\x00\x00\x01k" + // 0x00750304: 0x0000016B - "\x00U\x03\x06\x00\x00\x01l" + // 0x00550306: 0x0000016C - "\x00u\x03\x06\x00\x00\x01m" + // 0x00750306: 0x0000016D - "\x00U\x03\n\x00\x00\x01n" + // 0x0055030A: 0x0000016E - "\x00u\x03\n\x00\x00\x01o" + // 0x0075030A: 0x0000016F - "\x00U\x03\v\x00\x00\x01p" + // 0x0055030B: 0x00000170 - "\x00u\x03\v\x00\x00\x01q" + // 0x0075030B: 0x00000171 - "\x00U\x03(\x00\x00\x01r" + // 0x00550328: 0x00000172 - "\x00u\x03(\x00\x00\x01s" + // 0x00750328: 0x00000173 - "\x00W\x03\x02\x00\x00\x01t" + // 0x00570302: 0x00000174 - "\x00w\x03\x02\x00\x00\x01u" + // 0x00770302: 0x00000175 - "\x00Y\x03\x02\x00\x00\x01v" + // 0x00590302: 0x00000176 - "\x00y\x03\x02\x00\x00\x01w" + // 0x00790302: 0x00000177 - "\x00Y\x03\b\x00\x00\x01x" + // 0x00590308: 0x00000178 - "\x00Z\x03\x01\x00\x00\x01y" + // 0x005A0301: 0x00000179 - "\x00z\x03\x01\x00\x00\x01z" + // 0x007A0301: 0x0000017A - "\x00Z\x03\a\x00\x00\x01{" + // 0x005A0307: 0x0000017B - "\x00z\x03\a\x00\x00\x01|" + // 0x007A0307: 0x0000017C - "\x00Z\x03\f\x00\x00\x01}" + // 0x005A030C: 0x0000017D - "\x00z\x03\f\x00\x00\x01~" + // 0x007A030C: 0x0000017E - "\x00O\x03\x1b\x00\x00\x01\xa0" + // 0x004F031B: 0x000001A0 - "\x00o\x03\x1b\x00\x00\x01\xa1" + // 0x006F031B: 0x000001A1 - "\x00U\x03\x1b\x00\x00\x01\xaf" + // 0x0055031B: 0x000001AF - "\x00u\x03\x1b\x00\x00\x01\xb0" + // 0x0075031B: 0x000001B0 - "\x00A\x03\f\x00\x00\x01\xcd" + // 0x0041030C: 0x000001CD - "\x00a\x03\f\x00\x00\x01\xce" + // 0x0061030C: 0x000001CE - "\x00I\x03\f\x00\x00\x01\xcf" + // 0x0049030C: 0x000001CF - "\x00i\x03\f\x00\x00\x01\xd0" + // 0x0069030C: 0x000001D0 - "\x00O\x03\f\x00\x00\x01\xd1" + // 0x004F030C: 0x000001D1 - "\x00o\x03\f\x00\x00\x01\xd2" + // 0x006F030C: 0x000001D2 - "\x00U\x03\f\x00\x00\x01\xd3" + // 0x0055030C: 0x000001D3 - "\x00u\x03\f\x00\x00\x01\xd4" + // 0x0075030C: 0x000001D4 - "\x00\xdc\x03\x04\x00\x00\x01\xd5" + // 0x00DC0304: 0x000001D5 - "\x00\xfc\x03\x04\x00\x00\x01\xd6" + // 0x00FC0304: 0x000001D6 - "\x00\xdc\x03\x01\x00\x00\x01\xd7" + // 0x00DC0301: 0x000001D7 - "\x00\xfc\x03\x01\x00\x00\x01\xd8" + // 0x00FC0301: 0x000001D8 - "\x00\xdc\x03\f\x00\x00\x01\xd9" + // 0x00DC030C: 0x000001D9 - "\x00\xfc\x03\f\x00\x00\x01\xda" + // 0x00FC030C: 0x000001DA - "\x00\xdc\x03\x00\x00\x00\x01\xdb" + // 0x00DC0300: 0x000001DB - "\x00\xfc\x03\x00\x00\x00\x01\xdc" + // 0x00FC0300: 0x000001DC - "\x00\xc4\x03\x04\x00\x00\x01\xde" + // 0x00C40304: 0x000001DE - "\x00\xe4\x03\x04\x00\x00\x01\xdf" + // 0x00E40304: 0x000001DF - "\x02&\x03\x04\x00\x00\x01\xe0" + // 0x02260304: 0x000001E0 - "\x02'\x03\x04\x00\x00\x01\xe1" + // 0x02270304: 0x000001E1 - "\x00\xc6\x03\x04\x00\x00\x01\xe2" + // 0x00C60304: 0x000001E2 - "\x00\xe6\x03\x04\x00\x00\x01\xe3" + // 0x00E60304: 0x000001E3 - "\x00G\x03\f\x00\x00\x01\xe6" + // 0x0047030C: 0x000001E6 - "\x00g\x03\f\x00\x00\x01\xe7" + // 0x0067030C: 0x000001E7 - "\x00K\x03\f\x00\x00\x01\xe8" + // 0x004B030C: 0x000001E8 - "\x00k\x03\f\x00\x00\x01\xe9" + // 0x006B030C: 0x000001E9 - "\x00O\x03(\x00\x00\x01\xea" + // 0x004F0328: 0x000001EA - "\x00o\x03(\x00\x00\x01\xeb" + // 0x006F0328: 0x000001EB - "\x01\xea\x03\x04\x00\x00\x01\xec" + // 0x01EA0304: 0x000001EC - "\x01\xeb\x03\x04\x00\x00\x01\xed" + // 0x01EB0304: 0x000001ED - "\x01\xb7\x03\f\x00\x00\x01\xee" + // 0x01B7030C: 0x000001EE - "\x02\x92\x03\f\x00\x00\x01\xef" + // 0x0292030C: 0x000001EF - "\x00j\x03\f\x00\x00\x01\xf0" + // 0x006A030C: 0x000001F0 - "\x00G\x03\x01\x00\x00\x01\xf4" + // 0x00470301: 0x000001F4 - "\x00g\x03\x01\x00\x00\x01\xf5" + // 0x00670301: 0x000001F5 - "\x00N\x03\x00\x00\x00\x01\xf8" + // 0x004E0300: 0x000001F8 - "\x00n\x03\x00\x00\x00\x01\xf9" + // 0x006E0300: 0x000001F9 - "\x00\xc5\x03\x01\x00\x00\x01\xfa" + // 0x00C50301: 0x000001FA - "\x00\xe5\x03\x01\x00\x00\x01\xfb" + // 0x00E50301: 0x000001FB - "\x00\xc6\x03\x01\x00\x00\x01\xfc" + // 0x00C60301: 0x000001FC - "\x00\xe6\x03\x01\x00\x00\x01\xfd" + // 0x00E60301: 0x000001FD - "\x00\xd8\x03\x01\x00\x00\x01\xfe" + // 0x00D80301: 0x000001FE - "\x00\xf8\x03\x01\x00\x00\x01\xff" + // 0x00F80301: 0x000001FF - "\x00A\x03\x0f\x00\x00\x02\x00" + // 0x0041030F: 0x00000200 - "\x00a\x03\x0f\x00\x00\x02\x01" + // 0x0061030F: 0x00000201 - "\x00A\x03\x11\x00\x00\x02\x02" + // 0x00410311: 0x00000202 - "\x00a\x03\x11\x00\x00\x02\x03" + // 0x00610311: 0x00000203 - "\x00E\x03\x0f\x00\x00\x02\x04" + // 0x0045030F: 0x00000204 - "\x00e\x03\x0f\x00\x00\x02\x05" + // 0x0065030F: 0x00000205 - "\x00E\x03\x11\x00\x00\x02\x06" + // 0x00450311: 0x00000206 - "\x00e\x03\x11\x00\x00\x02\a" + // 0x00650311: 0x00000207 - "\x00I\x03\x0f\x00\x00\x02\b" + // 0x0049030F: 0x00000208 - "\x00i\x03\x0f\x00\x00\x02\t" + // 0x0069030F: 0x00000209 - "\x00I\x03\x11\x00\x00\x02\n" + // 0x00490311: 0x0000020A - "\x00i\x03\x11\x00\x00\x02\v" + // 0x00690311: 0x0000020B - "\x00O\x03\x0f\x00\x00\x02\f" + // 0x004F030F: 0x0000020C - "\x00o\x03\x0f\x00\x00\x02\r" + // 0x006F030F: 0x0000020D - "\x00O\x03\x11\x00\x00\x02\x0e" + // 0x004F0311: 0x0000020E - "\x00o\x03\x11\x00\x00\x02\x0f" + // 0x006F0311: 0x0000020F - "\x00R\x03\x0f\x00\x00\x02\x10" + // 0x0052030F: 0x00000210 - "\x00r\x03\x0f\x00\x00\x02\x11" + // 0x0072030F: 0x00000211 - "\x00R\x03\x11\x00\x00\x02\x12" + // 0x00520311: 0x00000212 - "\x00r\x03\x11\x00\x00\x02\x13" + // 0x00720311: 0x00000213 - "\x00U\x03\x0f\x00\x00\x02\x14" + // 0x0055030F: 0x00000214 - "\x00u\x03\x0f\x00\x00\x02\x15" + // 0x0075030F: 0x00000215 - "\x00U\x03\x11\x00\x00\x02\x16" + // 0x00550311: 0x00000216 - "\x00u\x03\x11\x00\x00\x02\x17" + // 0x00750311: 0x00000217 - "\x00S\x03&\x00\x00\x02\x18" + // 0x00530326: 0x00000218 - "\x00s\x03&\x00\x00\x02\x19" + // 0x00730326: 0x00000219 - "\x00T\x03&\x00\x00\x02\x1a" + // 0x00540326: 0x0000021A - "\x00t\x03&\x00\x00\x02\x1b" + // 0x00740326: 0x0000021B - "\x00H\x03\f\x00\x00\x02\x1e" + // 0x0048030C: 0x0000021E - "\x00h\x03\f\x00\x00\x02\x1f" + // 0x0068030C: 0x0000021F - "\x00A\x03\a\x00\x00\x02&" + // 0x00410307: 0x00000226 - "\x00a\x03\a\x00\x00\x02'" + // 0x00610307: 0x00000227 - "\x00E\x03'\x00\x00\x02(" + // 0x00450327: 0x00000228 - "\x00e\x03'\x00\x00\x02)" + // 0x00650327: 0x00000229 - "\x00\xd6\x03\x04\x00\x00\x02*" + // 0x00D60304: 0x0000022A - "\x00\xf6\x03\x04\x00\x00\x02+" + // 0x00F60304: 0x0000022B - "\x00\xd5\x03\x04\x00\x00\x02," + // 0x00D50304: 0x0000022C - "\x00\xf5\x03\x04\x00\x00\x02-" + // 0x00F50304: 0x0000022D - "\x00O\x03\a\x00\x00\x02." + // 0x004F0307: 0x0000022E - "\x00o\x03\a\x00\x00\x02/" + // 0x006F0307: 0x0000022F - "\x02.\x03\x04\x00\x00\x020" + // 0x022E0304: 0x00000230 - "\x02/\x03\x04\x00\x00\x021" + // 0x022F0304: 0x00000231 - "\x00Y\x03\x04\x00\x00\x022" + // 0x00590304: 0x00000232 - "\x00y\x03\x04\x00\x00\x023" + // 0x00790304: 0x00000233 - "\x00\xa8\x03\x01\x00\x00\x03\x85" + // 0x00A80301: 0x00000385 - "\x03\x91\x03\x01\x00\x00\x03\x86" + // 0x03910301: 0x00000386 - "\x03\x95\x03\x01\x00\x00\x03\x88" + // 0x03950301: 0x00000388 - "\x03\x97\x03\x01\x00\x00\x03\x89" + // 0x03970301: 0x00000389 - "\x03\x99\x03\x01\x00\x00\x03\x8a" + // 0x03990301: 0x0000038A - "\x03\x9f\x03\x01\x00\x00\x03\x8c" + // 0x039F0301: 0x0000038C - "\x03\xa5\x03\x01\x00\x00\x03\x8e" + // 0x03A50301: 0x0000038E - "\x03\xa9\x03\x01\x00\x00\x03\x8f" + // 0x03A90301: 0x0000038F - "\x03\xca\x03\x01\x00\x00\x03\x90" + // 0x03CA0301: 0x00000390 - "\x03\x99\x03\b\x00\x00\x03\xaa" + // 0x03990308: 0x000003AA - "\x03\xa5\x03\b\x00\x00\x03\xab" + // 0x03A50308: 0x000003AB - "\x03\xb1\x03\x01\x00\x00\x03\xac" + // 0x03B10301: 0x000003AC - "\x03\xb5\x03\x01\x00\x00\x03\xad" + // 0x03B50301: 0x000003AD - "\x03\xb7\x03\x01\x00\x00\x03\xae" + // 0x03B70301: 0x000003AE - "\x03\xb9\x03\x01\x00\x00\x03\xaf" + // 0x03B90301: 0x000003AF - "\x03\xcb\x03\x01\x00\x00\x03\xb0" + // 0x03CB0301: 0x000003B0 - "\x03\xb9\x03\b\x00\x00\x03\xca" + // 0x03B90308: 0x000003CA - "\x03\xc5\x03\b\x00\x00\x03\xcb" + // 0x03C50308: 0x000003CB - "\x03\xbf\x03\x01\x00\x00\x03\xcc" + // 0x03BF0301: 0x000003CC - "\x03\xc5\x03\x01\x00\x00\x03\xcd" + // 0x03C50301: 0x000003CD - "\x03\xc9\x03\x01\x00\x00\x03\xce" + // 0x03C90301: 0x000003CE - "\x03\xd2\x03\x01\x00\x00\x03\xd3" + // 0x03D20301: 0x000003D3 - "\x03\xd2\x03\b\x00\x00\x03\xd4" + // 0x03D20308: 0x000003D4 - "\x04\x15\x03\x00\x00\x00\x04\x00" + // 0x04150300: 0x00000400 - "\x04\x15\x03\b\x00\x00\x04\x01" + // 0x04150308: 0x00000401 - "\x04\x13\x03\x01\x00\x00\x04\x03" + // 0x04130301: 0x00000403 - "\x04\x06\x03\b\x00\x00\x04\a" + // 0x04060308: 0x00000407 - "\x04\x1a\x03\x01\x00\x00\x04\f" + // 0x041A0301: 0x0000040C - "\x04\x18\x03\x00\x00\x00\x04\r" + // 0x04180300: 0x0000040D - "\x04#\x03\x06\x00\x00\x04\x0e" + // 0x04230306: 0x0000040E - "\x04\x18\x03\x06\x00\x00\x04\x19" + // 0x04180306: 0x00000419 - "\x048\x03\x06\x00\x00\x049" + // 0x04380306: 0x00000439 - "\x045\x03\x00\x00\x00\x04P" + // 0x04350300: 0x00000450 - "\x045\x03\b\x00\x00\x04Q" + // 0x04350308: 0x00000451 - "\x043\x03\x01\x00\x00\x04S" + // 0x04330301: 0x00000453 - "\x04V\x03\b\x00\x00\x04W" + // 0x04560308: 0x00000457 - "\x04:\x03\x01\x00\x00\x04\\" + // 0x043A0301: 0x0000045C - "\x048\x03\x00\x00\x00\x04]" + // 0x04380300: 0x0000045D - "\x04C\x03\x06\x00\x00\x04^" + // 0x04430306: 0x0000045E - "\x04t\x03\x0f\x00\x00\x04v" + // 0x0474030F: 0x00000476 - "\x04u\x03\x0f\x00\x00\x04w" + // 0x0475030F: 0x00000477 - "\x04\x16\x03\x06\x00\x00\x04\xc1" + // 0x04160306: 0x000004C1 - "\x046\x03\x06\x00\x00\x04\xc2" + // 0x04360306: 0x000004C2 - "\x04\x10\x03\x06\x00\x00\x04\xd0" + // 0x04100306: 0x000004D0 - "\x040\x03\x06\x00\x00\x04\xd1" + // 0x04300306: 0x000004D1 - "\x04\x10\x03\b\x00\x00\x04\xd2" + // 0x04100308: 0x000004D2 - "\x040\x03\b\x00\x00\x04\xd3" + // 0x04300308: 0x000004D3 - "\x04\x15\x03\x06\x00\x00\x04\xd6" + // 0x04150306: 0x000004D6 - "\x045\x03\x06\x00\x00\x04\xd7" + // 0x04350306: 0x000004D7 - "\x04\xd8\x03\b\x00\x00\x04\xda" + // 0x04D80308: 0x000004DA - "\x04\xd9\x03\b\x00\x00\x04\xdb" + // 0x04D90308: 0x000004DB - "\x04\x16\x03\b\x00\x00\x04\xdc" + // 0x04160308: 0x000004DC - "\x046\x03\b\x00\x00\x04\xdd" + // 0x04360308: 0x000004DD - "\x04\x17\x03\b\x00\x00\x04\xde" + // 0x04170308: 0x000004DE - "\x047\x03\b\x00\x00\x04\xdf" + // 0x04370308: 0x000004DF - "\x04\x18\x03\x04\x00\x00\x04\xe2" + // 0x04180304: 0x000004E2 - "\x048\x03\x04\x00\x00\x04\xe3" + // 0x04380304: 0x000004E3 - "\x04\x18\x03\b\x00\x00\x04\xe4" + // 0x04180308: 0x000004E4 - "\x048\x03\b\x00\x00\x04\xe5" + // 0x04380308: 0x000004E5 - "\x04\x1e\x03\b\x00\x00\x04\xe6" + // 0x041E0308: 0x000004E6 - "\x04>\x03\b\x00\x00\x04\xe7" + // 0x043E0308: 0x000004E7 - "\x04\xe8\x03\b\x00\x00\x04\xea" + // 0x04E80308: 0x000004EA - "\x04\xe9\x03\b\x00\x00\x04\xeb" + // 0x04E90308: 0x000004EB - "\x04-\x03\b\x00\x00\x04\xec" + // 0x042D0308: 0x000004EC - "\x04M\x03\b\x00\x00\x04\xed" + // 0x044D0308: 0x000004ED - "\x04#\x03\x04\x00\x00\x04\xee" + // 0x04230304: 0x000004EE - "\x04C\x03\x04\x00\x00\x04\xef" + // 0x04430304: 0x000004EF - "\x04#\x03\b\x00\x00\x04\xf0" + // 0x04230308: 0x000004F0 - "\x04C\x03\b\x00\x00\x04\xf1" + // 0x04430308: 0x000004F1 - "\x04#\x03\v\x00\x00\x04\xf2" + // 0x0423030B: 0x000004F2 - "\x04C\x03\v\x00\x00\x04\xf3" + // 0x0443030B: 0x000004F3 - "\x04'\x03\b\x00\x00\x04\xf4" + // 0x04270308: 0x000004F4 - "\x04G\x03\b\x00\x00\x04\xf5" + // 0x04470308: 0x000004F5 - "\x04+\x03\b\x00\x00\x04\xf8" + // 0x042B0308: 0x000004F8 - "\x04K\x03\b\x00\x00\x04\xf9" + // 0x044B0308: 0x000004F9 - "\x06'\x06S\x00\x00\x06\"" + // 0x06270653: 0x00000622 - "\x06'\x06T\x00\x00\x06#" + // 0x06270654: 0x00000623 - "\x06H\x06T\x00\x00\x06$" + // 0x06480654: 0x00000624 - "\x06'\x06U\x00\x00\x06%" + // 0x06270655: 0x00000625 - "\x06J\x06T\x00\x00\x06&" + // 0x064A0654: 0x00000626 - "\x06\xd5\x06T\x00\x00\x06\xc0" + // 0x06D50654: 0x000006C0 - "\x06\xc1\x06T\x00\x00\x06\xc2" + // 0x06C10654: 0x000006C2 - "\x06\xd2\x06T\x00\x00\x06\xd3" + // 0x06D20654: 0x000006D3 - "\t(\t<\x00\x00\t)" + // 0x0928093C: 0x00000929 - "\t0\t<\x00\x00\t1" + // 0x0930093C: 0x00000931 - "\t3\t<\x00\x00\t4" + // 0x0933093C: 0x00000934 - "\t\xc7\t\xbe\x00\x00\t\xcb" + // 0x09C709BE: 0x000009CB - "\t\xc7\t\xd7\x00\x00\t\xcc" + // 0x09C709D7: 0x000009CC - "\vG\vV\x00\x00\vH" + // 0x0B470B56: 0x00000B48 - "\vG\v>\x00\x00\vK" + // 0x0B470B3E: 0x00000B4B - "\vG\vW\x00\x00\vL" + // 0x0B470B57: 0x00000B4C - "\v\x92\v\xd7\x00\x00\v\x94" + // 0x0B920BD7: 0x00000B94 - "\v\xc6\v\xbe\x00\x00\v\xca" + // 0x0BC60BBE: 0x00000BCA - "\v\xc7\v\xbe\x00\x00\v\xcb" + // 0x0BC70BBE: 0x00000BCB - "\v\xc6\v\xd7\x00\x00\v\xcc" + // 0x0BC60BD7: 0x00000BCC - "\fF\fV\x00\x00\fH" + // 0x0C460C56: 0x00000C48 - "\f\xbf\f\xd5\x00\x00\f\xc0" + // 0x0CBF0CD5: 0x00000CC0 - "\f\xc6\f\xd5\x00\x00\f\xc7" + // 0x0CC60CD5: 0x00000CC7 - "\f\xc6\f\xd6\x00\x00\f\xc8" + // 0x0CC60CD6: 0x00000CC8 - "\f\xc6\f\xc2\x00\x00\f\xca" + // 0x0CC60CC2: 0x00000CCA - "\f\xca\f\xd5\x00\x00\f\xcb" + // 0x0CCA0CD5: 0x00000CCB - "\rF\r>\x00\x00\rJ" + // 0x0D460D3E: 0x00000D4A - "\rG\r>\x00\x00\rK" + // 0x0D470D3E: 0x00000D4B - "\rF\rW\x00\x00\rL" + // 0x0D460D57: 0x00000D4C - "\r\xd9\r\xca\x00\x00\r\xda" + // 0x0DD90DCA: 0x00000DDA - "\r\xd9\r\xcf\x00\x00\r\xdc" + // 0x0DD90DCF: 0x00000DDC - "\r\xdc\r\xca\x00\x00\r\xdd" + // 0x0DDC0DCA: 0x00000DDD - "\r\xd9\r\xdf\x00\x00\r\xde" + // 0x0DD90DDF: 0x00000DDE - "\x10%\x10.\x00\x00\x10&" + // 0x1025102E: 0x00001026 - "\x1b\x05\x1b5\x00\x00\x1b\x06" + // 0x1B051B35: 0x00001B06 - "\x1b\a\x1b5\x00\x00\x1b\b" + // 0x1B071B35: 0x00001B08 - "\x1b\t\x1b5\x00\x00\x1b\n" + // 0x1B091B35: 0x00001B0A - "\x1b\v\x1b5\x00\x00\x1b\f" + // 0x1B0B1B35: 0x00001B0C - "\x1b\r\x1b5\x00\x00\x1b\x0e" + // 0x1B0D1B35: 0x00001B0E - "\x1b\x11\x1b5\x00\x00\x1b\x12" + // 0x1B111B35: 0x00001B12 - "\x1b:\x1b5\x00\x00\x1b;" + // 0x1B3A1B35: 0x00001B3B - "\x1b<\x1b5\x00\x00\x1b=" + // 0x1B3C1B35: 0x00001B3D - "\x1b>\x1b5\x00\x00\x1b@" + // 0x1B3E1B35: 0x00001B40 - "\x1b?\x1b5\x00\x00\x1bA" + // 0x1B3F1B35: 0x00001B41 - "\x1bB\x1b5\x00\x00\x1bC" + // 0x1B421B35: 0x00001B43 - "\x00A\x03%\x00\x00\x1e\x00" + // 0x00410325: 0x00001E00 - "\x00a\x03%\x00\x00\x1e\x01" + // 0x00610325: 0x00001E01 - "\x00B\x03\a\x00\x00\x1e\x02" + // 0x00420307: 0x00001E02 - "\x00b\x03\a\x00\x00\x1e\x03" + // 0x00620307: 0x00001E03 - "\x00B\x03#\x00\x00\x1e\x04" + // 0x00420323: 0x00001E04 - "\x00b\x03#\x00\x00\x1e\x05" + // 0x00620323: 0x00001E05 - "\x00B\x031\x00\x00\x1e\x06" + // 0x00420331: 0x00001E06 - "\x00b\x031\x00\x00\x1e\a" + // 0x00620331: 0x00001E07 - "\x00\xc7\x03\x01\x00\x00\x1e\b" + // 0x00C70301: 0x00001E08 - "\x00\xe7\x03\x01\x00\x00\x1e\t" + // 0x00E70301: 0x00001E09 - "\x00D\x03\a\x00\x00\x1e\n" + // 0x00440307: 0x00001E0A - "\x00d\x03\a\x00\x00\x1e\v" + // 0x00640307: 0x00001E0B - "\x00D\x03#\x00\x00\x1e\f" + // 0x00440323: 0x00001E0C - "\x00d\x03#\x00\x00\x1e\r" + // 0x00640323: 0x00001E0D - "\x00D\x031\x00\x00\x1e\x0e" + // 0x00440331: 0x00001E0E - "\x00d\x031\x00\x00\x1e\x0f" + // 0x00640331: 0x00001E0F - "\x00D\x03'\x00\x00\x1e\x10" + // 0x00440327: 0x00001E10 - "\x00d\x03'\x00\x00\x1e\x11" + // 0x00640327: 0x00001E11 - "\x00D\x03-\x00\x00\x1e\x12" + // 0x0044032D: 0x00001E12 - "\x00d\x03-\x00\x00\x1e\x13" + // 0x0064032D: 0x00001E13 - "\x01\x12\x03\x00\x00\x00\x1e\x14" + // 0x01120300: 0x00001E14 - "\x01\x13\x03\x00\x00\x00\x1e\x15" + // 0x01130300: 0x00001E15 - "\x01\x12\x03\x01\x00\x00\x1e\x16" + // 0x01120301: 0x00001E16 - "\x01\x13\x03\x01\x00\x00\x1e\x17" + // 0x01130301: 0x00001E17 - "\x00E\x03-\x00\x00\x1e\x18" + // 0x0045032D: 0x00001E18 - "\x00e\x03-\x00\x00\x1e\x19" + // 0x0065032D: 0x00001E19 - "\x00E\x030\x00\x00\x1e\x1a" + // 0x00450330: 0x00001E1A - "\x00e\x030\x00\x00\x1e\x1b" + // 0x00650330: 0x00001E1B - "\x02(\x03\x06\x00\x00\x1e\x1c" + // 0x02280306: 0x00001E1C - "\x02)\x03\x06\x00\x00\x1e\x1d" + // 0x02290306: 0x00001E1D - "\x00F\x03\a\x00\x00\x1e\x1e" + // 0x00460307: 0x00001E1E - "\x00f\x03\a\x00\x00\x1e\x1f" + // 0x00660307: 0x00001E1F - "\x00G\x03\x04\x00\x00\x1e " + // 0x00470304: 0x00001E20 - "\x00g\x03\x04\x00\x00\x1e!" + // 0x00670304: 0x00001E21 - "\x00H\x03\a\x00\x00\x1e\"" + // 0x00480307: 0x00001E22 - "\x00h\x03\a\x00\x00\x1e#" + // 0x00680307: 0x00001E23 - "\x00H\x03#\x00\x00\x1e$" + // 0x00480323: 0x00001E24 - "\x00h\x03#\x00\x00\x1e%" + // 0x00680323: 0x00001E25 - "\x00H\x03\b\x00\x00\x1e&" + // 0x00480308: 0x00001E26 - "\x00h\x03\b\x00\x00\x1e'" + // 0x00680308: 0x00001E27 - "\x00H\x03'\x00\x00\x1e(" + // 0x00480327: 0x00001E28 - "\x00h\x03'\x00\x00\x1e)" + // 0x00680327: 0x00001E29 - "\x00H\x03.\x00\x00\x1e*" + // 0x0048032E: 0x00001E2A - "\x00h\x03.\x00\x00\x1e+" + // 0x0068032E: 0x00001E2B - "\x00I\x030\x00\x00\x1e," + // 0x00490330: 0x00001E2C - "\x00i\x030\x00\x00\x1e-" + // 0x00690330: 0x00001E2D - "\x00\xcf\x03\x01\x00\x00\x1e." + // 0x00CF0301: 0x00001E2E - "\x00\xef\x03\x01\x00\x00\x1e/" + // 0x00EF0301: 0x00001E2F - "\x00K\x03\x01\x00\x00\x1e0" + // 0x004B0301: 0x00001E30 - "\x00k\x03\x01\x00\x00\x1e1" + // 0x006B0301: 0x00001E31 - "\x00K\x03#\x00\x00\x1e2" + // 0x004B0323: 0x00001E32 - "\x00k\x03#\x00\x00\x1e3" + // 0x006B0323: 0x00001E33 - "\x00K\x031\x00\x00\x1e4" + // 0x004B0331: 0x00001E34 - "\x00k\x031\x00\x00\x1e5" + // 0x006B0331: 0x00001E35 - "\x00L\x03#\x00\x00\x1e6" + // 0x004C0323: 0x00001E36 - "\x00l\x03#\x00\x00\x1e7" + // 0x006C0323: 0x00001E37 - "\x1e6\x03\x04\x00\x00\x1e8" + // 0x1E360304: 0x00001E38 - "\x1e7\x03\x04\x00\x00\x1e9" + // 0x1E370304: 0x00001E39 - "\x00L\x031\x00\x00\x1e:" + // 0x004C0331: 0x00001E3A - "\x00l\x031\x00\x00\x1e;" + // 0x006C0331: 0x00001E3B - "\x00L\x03-\x00\x00\x1e<" + // 0x004C032D: 0x00001E3C - "\x00l\x03-\x00\x00\x1e=" + // 0x006C032D: 0x00001E3D - "\x00M\x03\x01\x00\x00\x1e>" + // 0x004D0301: 0x00001E3E - "\x00m\x03\x01\x00\x00\x1e?" + // 0x006D0301: 0x00001E3F - "\x00M\x03\a\x00\x00\x1e@" + // 0x004D0307: 0x00001E40 - "\x00m\x03\a\x00\x00\x1eA" + // 0x006D0307: 0x00001E41 - "\x00M\x03#\x00\x00\x1eB" + // 0x004D0323: 0x00001E42 - "\x00m\x03#\x00\x00\x1eC" + // 0x006D0323: 0x00001E43 - "\x00N\x03\a\x00\x00\x1eD" + // 0x004E0307: 0x00001E44 - "\x00n\x03\a\x00\x00\x1eE" + // 0x006E0307: 0x00001E45 - "\x00N\x03#\x00\x00\x1eF" + // 0x004E0323: 0x00001E46 - "\x00n\x03#\x00\x00\x1eG" + // 0x006E0323: 0x00001E47 - "\x00N\x031\x00\x00\x1eH" + // 0x004E0331: 0x00001E48 - "\x00n\x031\x00\x00\x1eI" + // 0x006E0331: 0x00001E49 - "\x00N\x03-\x00\x00\x1eJ" + // 0x004E032D: 0x00001E4A - "\x00n\x03-\x00\x00\x1eK" + // 0x006E032D: 0x00001E4B - "\x00\xd5\x03\x01\x00\x00\x1eL" + // 0x00D50301: 0x00001E4C - "\x00\xf5\x03\x01\x00\x00\x1eM" + // 0x00F50301: 0x00001E4D - "\x00\xd5\x03\b\x00\x00\x1eN" + // 0x00D50308: 0x00001E4E - "\x00\xf5\x03\b\x00\x00\x1eO" + // 0x00F50308: 0x00001E4F - "\x01L\x03\x00\x00\x00\x1eP" + // 0x014C0300: 0x00001E50 - "\x01M\x03\x00\x00\x00\x1eQ" + // 0x014D0300: 0x00001E51 - "\x01L\x03\x01\x00\x00\x1eR" + // 0x014C0301: 0x00001E52 - "\x01M\x03\x01\x00\x00\x1eS" + // 0x014D0301: 0x00001E53 - "\x00P\x03\x01\x00\x00\x1eT" + // 0x00500301: 0x00001E54 - "\x00p\x03\x01\x00\x00\x1eU" + // 0x00700301: 0x00001E55 - "\x00P\x03\a\x00\x00\x1eV" + // 0x00500307: 0x00001E56 - "\x00p\x03\a\x00\x00\x1eW" + // 0x00700307: 0x00001E57 - "\x00R\x03\a\x00\x00\x1eX" + // 0x00520307: 0x00001E58 - "\x00r\x03\a\x00\x00\x1eY" + // 0x00720307: 0x00001E59 - "\x00R\x03#\x00\x00\x1eZ" + // 0x00520323: 0x00001E5A - "\x00r\x03#\x00\x00\x1e[" + // 0x00720323: 0x00001E5B - "\x1eZ\x03\x04\x00\x00\x1e\\" + // 0x1E5A0304: 0x00001E5C - "\x1e[\x03\x04\x00\x00\x1e]" + // 0x1E5B0304: 0x00001E5D - "\x00R\x031\x00\x00\x1e^" + // 0x00520331: 0x00001E5E - "\x00r\x031\x00\x00\x1e_" + // 0x00720331: 0x00001E5F - "\x00S\x03\a\x00\x00\x1e`" + // 0x00530307: 0x00001E60 - "\x00s\x03\a\x00\x00\x1ea" + // 0x00730307: 0x00001E61 - "\x00S\x03#\x00\x00\x1eb" + // 0x00530323: 0x00001E62 - "\x00s\x03#\x00\x00\x1ec" + // 0x00730323: 0x00001E63 - "\x01Z\x03\a\x00\x00\x1ed" + // 0x015A0307: 0x00001E64 - "\x01[\x03\a\x00\x00\x1ee" + // 0x015B0307: 0x00001E65 - "\x01`\x03\a\x00\x00\x1ef" + // 0x01600307: 0x00001E66 - "\x01a\x03\a\x00\x00\x1eg" + // 0x01610307: 0x00001E67 - "\x1eb\x03\a\x00\x00\x1eh" + // 0x1E620307: 0x00001E68 - "\x1ec\x03\a\x00\x00\x1ei" + // 0x1E630307: 0x00001E69 - "\x00T\x03\a\x00\x00\x1ej" + // 0x00540307: 0x00001E6A - "\x00t\x03\a\x00\x00\x1ek" + // 0x00740307: 0x00001E6B - "\x00T\x03#\x00\x00\x1el" + // 0x00540323: 0x00001E6C - "\x00t\x03#\x00\x00\x1em" + // 0x00740323: 0x00001E6D - "\x00T\x031\x00\x00\x1en" + // 0x00540331: 0x00001E6E - "\x00t\x031\x00\x00\x1eo" + // 0x00740331: 0x00001E6F - "\x00T\x03-\x00\x00\x1ep" + // 0x0054032D: 0x00001E70 - "\x00t\x03-\x00\x00\x1eq" + // 0x0074032D: 0x00001E71 - "\x00U\x03$\x00\x00\x1er" + // 0x00550324: 0x00001E72 - "\x00u\x03$\x00\x00\x1es" + // 0x00750324: 0x00001E73 - "\x00U\x030\x00\x00\x1et" + // 0x00550330: 0x00001E74 - "\x00u\x030\x00\x00\x1eu" + // 0x00750330: 0x00001E75 - "\x00U\x03-\x00\x00\x1ev" + // 0x0055032D: 0x00001E76 - "\x00u\x03-\x00\x00\x1ew" + // 0x0075032D: 0x00001E77 - "\x01h\x03\x01\x00\x00\x1ex" + // 0x01680301: 0x00001E78 - "\x01i\x03\x01\x00\x00\x1ey" + // 0x01690301: 0x00001E79 - "\x01j\x03\b\x00\x00\x1ez" + // 0x016A0308: 0x00001E7A - "\x01k\x03\b\x00\x00\x1e{" + // 0x016B0308: 0x00001E7B - "\x00V\x03\x03\x00\x00\x1e|" + // 0x00560303: 0x00001E7C - "\x00v\x03\x03\x00\x00\x1e}" + // 0x00760303: 0x00001E7D - "\x00V\x03#\x00\x00\x1e~" + // 0x00560323: 0x00001E7E - "\x00v\x03#\x00\x00\x1e\x7f" + // 0x00760323: 0x00001E7F - "\x00W\x03\x00\x00\x00\x1e\x80" + // 0x00570300: 0x00001E80 - "\x00w\x03\x00\x00\x00\x1e\x81" + // 0x00770300: 0x00001E81 - "\x00W\x03\x01\x00\x00\x1e\x82" + // 0x00570301: 0x00001E82 - "\x00w\x03\x01\x00\x00\x1e\x83" + // 0x00770301: 0x00001E83 - "\x00W\x03\b\x00\x00\x1e\x84" + // 0x00570308: 0x00001E84 - "\x00w\x03\b\x00\x00\x1e\x85" + // 0x00770308: 0x00001E85 - "\x00W\x03\a\x00\x00\x1e\x86" + // 0x00570307: 0x00001E86 - "\x00w\x03\a\x00\x00\x1e\x87" + // 0x00770307: 0x00001E87 - "\x00W\x03#\x00\x00\x1e\x88" + // 0x00570323: 0x00001E88 - "\x00w\x03#\x00\x00\x1e\x89" + // 0x00770323: 0x00001E89 - "\x00X\x03\a\x00\x00\x1e\x8a" + // 0x00580307: 0x00001E8A - "\x00x\x03\a\x00\x00\x1e\x8b" + // 0x00780307: 0x00001E8B - "\x00X\x03\b\x00\x00\x1e\x8c" + // 0x00580308: 0x00001E8C - "\x00x\x03\b\x00\x00\x1e\x8d" + // 0x00780308: 0x00001E8D - "\x00Y\x03\a\x00\x00\x1e\x8e" + // 0x00590307: 0x00001E8E - "\x00y\x03\a\x00\x00\x1e\x8f" + // 0x00790307: 0x00001E8F - "\x00Z\x03\x02\x00\x00\x1e\x90" + // 0x005A0302: 0x00001E90 - "\x00z\x03\x02\x00\x00\x1e\x91" + // 0x007A0302: 0x00001E91 - "\x00Z\x03#\x00\x00\x1e\x92" + // 0x005A0323: 0x00001E92 - "\x00z\x03#\x00\x00\x1e\x93" + // 0x007A0323: 0x00001E93 - "\x00Z\x031\x00\x00\x1e\x94" + // 0x005A0331: 0x00001E94 - "\x00z\x031\x00\x00\x1e\x95" + // 0x007A0331: 0x00001E95 - "\x00h\x031\x00\x00\x1e\x96" + // 0x00680331: 0x00001E96 - "\x00t\x03\b\x00\x00\x1e\x97" + // 0x00740308: 0x00001E97 - "\x00w\x03\n\x00\x00\x1e\x98" + // 0x0077030A: 0x00001E98 - "\x00y\x03\n\x00\x00\x1e\x99" + // 0x0079030A: 0x00001E99 - "\x01\x7f\x03\a\x00\x00\x1e\x9b" + // 0x017F0307: 0x00001E9B - "\x00A\x03#\x00\x00\x1e\xa0" + // 0x00410323: 0x00001EA0 - "\x00a\x03#\x00\x00\x1e\xa1" + // 0x00610323: 0x00001EA1 - "\x00A\x03\t\x00\x00\x1e\xa2" + // 0x00410309: 0x00001EA2 - "\x00a\x03\t\x00\x00\x1e\xa3" + // 0x00610309: 0x00001EA3 - "\x00\xc2\x03\x01\x00\x00\x1e\xa4" + // 0x00C20301: 0x00001EA4 - "\x00\xe2\x03\x01\x00\x00\x1e\xa5" + // 0x00E20301: 0x00001EA5 - "\x00\xc2\x03\x00\x00\x00\x1e\xa6" + // 0x00C20300: 0x00001EA6 - "\x00\xe2\x03\x00\x00\x00\x1e\xa7" + // 0x00E20300: 0x00001EA7 - "\x00\xc2\x03\t\x00\x00\x1e\xa8" + // 0x00C20309: 0x00001EA8 - "\x00\xe2\x03\t\x00\x00\x1e\xa9" + // 0x00E20309: 0x00001EA9 - "\x00\xc2\x03\x03\x00\x00\x1e\xaa" + // 0x00C20303: 0x00001EAA - "\x00\xe2\x03\x03\x00\x00\x1e\xab" + // 0x00E20303: 0x00001EAB - "\x1e\xa0\x03\x02\x00\x00\x1e\xac" + // 0x1EA00302: 0x00001EAC - "\x1e\xa1\x03\x02\x00\x00\x1e\xad" + // 0x1EA10302: 0x00001EAD - "\x01\x02\x03\x01\x00\x00\x1e\xae" + // 0x01020301: 0x00001EAE - "\x01\x03\x03\x01\x00\x00\x1e\xaf" + // 0x01030301: 0x00001EAF - "\x01\x02\x03\x00\x00\x00\x1e\xb0" + // 0x01020300: 0x00001EB0 - "\x01\x03\x03\x00\x00\x00\x1e\xb1" + // 0x01030300: 0x00001EB1 - "\x01\x02\x03\t\x00\x00\x1e\xb2" + // 0x01020309: 0x00001EB2 - "\x01\x03\x03\t\x00\x00\x1e\xb3" + // 0x01030309: 0x00001EB3 - "\x01\x02\x03\x03\x00\x00\x1e\xb4" + // 0x01020303: 0x00001EB4 - "\x01\x03\x03\x03\x00\x00\x1e\xb5" + // 0x01030303: 0x00001EB5 - "\x1e\xa0\x03\x06\x00\x00\x1e\xb6" + // 0x1EA00306: 0x00001EB6 - "\x1e\xa1\x03\x06\x00\x00\x1e\xb7" + // 0x1EA10306: 0x00001EB7 - "\x00E\x03#\x00\x00\x1e\xb8" + // 0x00450323: 0x00001EB8 - "\x00e\x03#\x00\x00\x1e\xb9" + // 0x00650323: 0x00001EB9 - "\x00E\x03\t\x00\x00\x1e\xba" + // 0x00450309: 0x00001EBA - "\x00e\x03\t\x00\x00\x1e\xbb" + // 0x00650309: 0x00001EBB - "\x00E\x03\x03\x00\x00\x1e\xbc" + // 0x00450303: 0x00001EBC - "\x00e\x03\x03\x00\x00\x1e\xbd" + // 0x00650303: 0x00001EBD - "\x00\xca\x03\x01\x00\x00\x1e\xbe" + // 0x00CA0301: 0x00001EBE - "\x00\xea\x03\x01\x00\x00\x1e\xbf" + // 0x00EA0301: 0x00001EBF - "\x00\xca\x03\x00\x00\x00\x1e\xc0" + // 0x00CA0300: 0x00001EC0 - "\x00\xea\x03\x00\x00\x00\x1e\xc1" + // 0x00EA0300: 0x00001EC1 - "\x00\xca\x03\t\x00\x00\x1e\xc2" + // 0x00CA0309: 0x00001EC2 - "\x00\xea\x03\t\x00\x00\x1e\xc3" + // 0x00EA0309: 0x00001EC3 - "\x00\xca\x03\x03\x00\x00\x1e\xc4" + // 0x00CA0303: 0x00001EC4 - "\x00\xea\x03\x03\x00\x00\x1e\xc5" + // 0x00EA0303: 0x00001EC5 - "\x1e\xb8\x03\x02\x00\x00\x1e\xc6" + // 0x1EB80302: 0x00001EC6 - "\x1e\xb9\x03\x02\x00\x00\x1e\xc7" + // 0x1EB90302: 0x00001EC7 - "\x00I\x03\t\x00\x00\x1e\xc8" + // 0x00490309: 0x00001EC8 - "\x00i\x03\t\x00\x00\x1e\xc9" + // 0x00690309: 0x00001EC9 - "\x00I\x03#\x00\x00\x1e\xca" + // 0x00490323: 0x00001ECA - "\x00i\x03#\x00\x00\x1e\xcb" + // 0x00690323: 0x00001ECB - "\x00O\x03#\x00\x00\x1e\xcc" + // 0x004F0323: 0x00001ECC - "\x00o\x03#\x00\x00\x1e\xcd" + // 0x006F0323: 0x00001ECD - "\x00O\x03\t\x00\x00\x1e\xce" + // 0x004F0309: 0x00001ECE - "\x00o\x03\t\x00\x00\x1e\xcf" + // 0x006F0309: 0x00001ECF - "\x00\xd4\x03\x01\x00\x00\x1e\xd0" + // 0x00D40301: 0x00001ED0 - "\x00\xf4\x03\x01\x00\x00\x1e\xd1" + // 0x00F40301: 0x00001ED1 - "\x00\xd4\x03\x00\x00\x00\x1e\xd2" + // 0x00D40300: 0x00001ED2 - "\x00\xf4\x03\x00\x00\x00\x1e\xd3" + // 0x00F40300: 0x00001ED3 - "\x00\xd4\x03\t\x00\x00\x1e\xd4" + // 0x00D40309: 0x00001ED4 - "\x00\xf4\x03\t\x00\x00\x1e\xd5" + // 0x00F40309: 0x00001ED5 - "\x00\xd4\x03\x03\x00\x00\x1e\xd6" + // 0x00D40303: 0x00001ED6 - "\x00\xf4\x03\x03\x00\x00\x1e\xd7" + // 0x00F40303: 0x00001ED7 - "\x1e\xcc\x03\x02\x00\x00\x1e\xd8" + // 0x1ECC0302: 0x00001ED8 - "\x1e\xcd\x03\x02\x00\x00\x1e\xd9" + // 0x1ECD0302: 0x00001ED9 - "\x01\xa0\x03\x01\x00\x00\x1e\xda" + // 0x01A00301: 0x00001EDA - "\x01\xa1\x03\x01\x00\x00\x1e\xdb" + // 0x01A10301: 0x00001EDB - "\x01\xa0\x03\x00\x00\x00\x1e\xdc" + // 0x01A00300: 0x00001EDC - "\x01\xa1\x03\x00\x00\x00\x1e\xdd" + // 0x01A10300: 0x00001EDD - "\x01\xa0\x03\t\x00\x00\x1e\xde" + // 0x01A00309: 0x00001EDE - "\x01\xa1\x03\t\x00\x00\x1e\xdf" + // 0x01A10309: 0x00001EDF - "\x01\xa0\x03\x03\x00\x00\x1e\xe0" + // 0x01A00303: 0x00001EE0 - "\x01\xa1\x03\x03\x00\x00\x1e\xe1" + // 0x01A10303: 0x00001EE1 - "\x01\xa0\x03#\x00\x00\x1e\xe2" + // 0x01A00323: 0x00001EE2 - "\x01\xa1\x03#\x00\x00\x1e\xe3" + // 0x01A10323: 0x00001EE3 - "\x00U\x03#\x00\x00\x1e\xe4" + // 0x00550323: 0x00001EE4 - "\x00u\x03#\x00\x00\x1e\xe5" + // 0x00750323: 0x00001EE5 - "\x00U\x03\t\x00\x00\x1e\xe6" + // 0x00550309: 0x00001EE6 - "\x00u\x03\t\x00\x00\x1e\xe7" + // 0x00750309: 0x00001EE7 - "\x01\xaf\x03\x01\x00\x00\x1e\xe8" + // 0x01AF0301: 0x00001EE8 - "\x01\xb0\x03\x01\x00\x00\x1e\xe9" + // 0x01B00301: 0x00001EE9 - "\x01\xaf\x03\x00\x00\x00\x1e\xea" + // 0x01AF0300: 0x00001EEA - "\x01\xb0\x03\x00\x00\x00\x1e\xeb" + // 0x01B00300: 0x00001EEB - "\x01\xaf\x03\t\x00\x00\x1e\xec" + // 0x01AF0309: 0x00001EEC - "\x01\xb0\x03\t\x00\x00\x1e\xed" + // 0x01B00309: 0x00001EED - "\x01\xaf\x03\x03\x00\x00\x1e\xee" + // 0x01AF0303: 0x00001EEE - "\x01\xb0\x03\x03\x00\x00\x1e\xef" + // 0x01B00303: 0x00001EEF - "\x01\xaf\x03#\x00\x00\x1e\xf0" + // 0x01AF0323: 0x00001EF0 - "\x01\xb0\x03#\x00\x00\x1e\xf1" + // 0x01B00323: 0x00001EF1 - "\x00Y\x03\x00\x00\x00\x1e\xf2" + // 0x00590300: 0x00001EF2 - "\x00y\x03\x00\x00\x00\x1e\xf3" + // 0x00790300: 0x00001EF3 - "\x00Y\x03#\x00\x00\x1e\xf4" + // 0x00590323: 0x00001EF4 - "\x00y\x03#\x00\x00\x1e\xf5" + // 0x00790323: 0x00001EF5 - "\x00Y\x03\t\x00\x00\x1e\xf6" + // 0x00590309: 0x00001EF6 - "\x00y\x03\t\x00\x00\x1e\xf7" + // 0x00790309: 0x00001EF7 - "\x00Y\x03\x03\x00\x00\x1e\xf8" + // 0x00590303: 0x00001EF8 - "\x00y\x03\x03\x00\x00\x1e\xf9" + // 0x00790303: 0x00001EF9 - "\x03\xb1\x03\x13\x00\x00\x1f\x00" + // 0x03B10313: 0x00001F00 - "\x03\xb1\x03\x14\x00\x00\x1f\x01" + // 0x03B10314: 0x00001F01 - "\x1f\x00\x03\x00\x00\x00\x1f\x02" + // 0x1F000300: 0x00001F02 - "\x1f\x01\x03\x00\x00\x00\x1f\x03" + // 0x1F010300: 0x00001F03 - "\x1f\x00\x03\x01\x00\x00\x1f\x04" + // 0x1F000301: 0x00001F04 - "\x1f\x01\x03\x01\x00\x00\x1f\x05" + // 0x1F010301: 0x00001F05 - "\x1f\x00\x03B\x00\x00\x1f\x06" + // 0x1F000342: 0x00001F06 - "\x1f\x01\x03B\x00\x00\x1f\a" + // 0x1F010342: 0x00001F07 - "\x03\x91\x03\x13\x00\x00\x1f\b" + // 0x03910313: 0x00001F08 - "\x03\x91\x03\x14\x00\x00\x1f\t" + // 0x03910314: 0x00001F09 - "\x1f\b\x03\x00\x00\x00\x1f\n" + // 0x1F080300: 0x00001F0A - "\x1f\t\x03\x00\x00\x00\x1f\v" + // 0x1F090300: 0x00001F0B - "\x1f\b\x03\x01\x00\x00\x1f\f" + // 0x1F080301: 0x00001F0C - "\x1f\t\x03\x01\x00\x00\x1f\r" + // 0x1F090301: 0x00001F0D - "\x1f\b\x03B\x00\x00\x1f\x0e" + // 0x1F080342: 0x00001F0E - "\x1f\t\x03B\x00\x00\x1f\x0f" + // 0x1F090342: 0x00001F0F - "\x03\xb5\x03\x13\x00\x00\x1f\x10" + // 0x03B50313: 0x00001F10 - "\x03\xb5\x03\x14\x00\x00\x1f\x11" + // 0x03B50314: 0x00001F11 - "\x1f\x10\x03\x00\x00\x00\x1f\x12" + // 0x1F100300: 0x00001F12 - "\x1f\x11\x03\x00\x00\x00\x1f\x13" + // 0x1F110300: 0x00001F13 - "\x1f\x10\x03\x01\x00\x00\x1f\x14" + // 0x1F100301: 0x00001F14 - "\x1f\x11\x03\x01\x00\x00\x1f\x15" + // 0x1F110301: 0x00001F15 - "\x03\x95\x03\x13\x00\x00\x1f\x18" + // 0x03950313: 0x00001F18 - "\x03\x95\x03\x14\x00\x00\x1f\x19" + // 0x03950314: 0x00001F19 - "\x1f\x18\x03\x00\x00\x00\x1f\x1a" + // 0x1F180300: 0x00001F1A - "\x1f\x19\x03\x00\x00\x00\x1f\x1b" + // 0x1F190300: 0x00001F1B - "\x1f\x18\x03\x01\x00\x00\x1f\x1c" + // 0x1F180301: 0x00001F1C - "\x1f\x19\x03\x01\x00\x00\x1f\x1d" + // 0x1F190301: 0x00001F1D - "\x03\xb7\x03\x13\x00\x00\x1f " + // 0x03B70313: 0x00001F20 - "\x03\xb7\x03\x14\x00\x00\x1f!" + // 0x03B70314: 0x00001F21 - "\x1f \x03\x00\x00\x00\x1f\"" + // 0x1F200300: 0x00001F22 - "\x1f!\x03\x00\x00\x00\x1f#" + // 0x1F210300: 0x00001F23 - "\x1f \x03\x01\x00\x00\x1f$" + // 0x1F200301: 0x00001F24 - "\x1f!\x03\x01\x00\x00\x1f%" + // 0x1F210301: 0x00001F25 - "\x1f \x03B\x00\x00\x1f&" + // 0x1F200342: 0x00001F26 - "\x1f!\x03B\x00\x00\x1f'" + // 0x1F210342: 0x00001F27 - "\x03\x97\x03\x13\x00\x00\x1f(" + // 0x03970313: 0x00001F28 - "\x03\x97\x03\x14\x00\x00\x1f)" + // 0x03970314: 0x00001F29 - "\x1f(\x03\x00\x00\x00\x1f*" + // 0x1F280300: 0x00001F2A - "\x1f)\x03\x00\x00\x00\x1f+" + // 0x1F290300: 0x00001F2B - "\x1f(\x03\x01\x00\x00\x1f," + // 0x1F280301: 0x00001F2C - "\x1f)\x03\x01\x00\x00\x1f-" + // 0x1F290301: 0x00001F2D - "\x1f(\x03B\x00\x00\x1f." + // 0x1F280342: 0x00001F2E - "\x1f)\x03B\x00\x00\x1f/" + // 0x1F290342: 0x00001F2F - "\x03\xb9\x03\x13\x00\x00\x1f0" + // 0x03B90313: 0x00001F30 - "\x03\xb9\x03\x14\x00\x00\x1f1" + // 0x03B90314: 0x00001F31 - "\x1f0\x03\x00\x00\x00\x1f2" + // 0x1F300300: 0x00001F32 - "\x1f1\x03\x00\x00\x00\x1f3" + // 0x1F310300: 0x00001F33 - "\x1f0\x03\x01\x00\x00\x1f4" + // 0x1F300301: 0x00001F34 - "\x1f1\x03\x01\x00\x00\x1f5" + // 0x1F310301: 0x00001F35 - "\x1f0\x03B\x00\x00\x1f6" + // 0x1F300342: 0x00001F36 - "\x1f1\x03B\x00\x00\x1f7" + // 0x1F310342: 0x00001F37 - "\x03\x99\x03\x13\x00\x00\x1f8" + // 0x03990313: 0x00001F38 - "\x03\x99\x03\x14\x00\x00\x1f9" + // 0x03990314: 0x00001F39 - "\x1f8\x03\x00\x00\x00\x1f:" + // 0x1F380300: 0x00001F3A - "\x1f9\x03\x00\x00\x00\x1f;" + // 0x1F390300: 0x00001F3B - "\x1f8\x03\x01\x00\x00\x1f<" + // 0x1F380301: 0x00001F3C - "\x1f9\x03\x01\x00\x00\x1f=" + // 0x1F390301: 0x00001F3D - "\x1f8\x03B\x00\x00\x1f>" + // 0x1F380342: 0x00001F3E - "\x1f9\x03B\x00\x00\x1f?" + // 0x1F390342: 0x00001F3F - "\x03\xbf\x03\x13\x00\x00\x1f@" + // 0x03BF0313: 0x00001F40 - "\x03\xbf\x03\x14\x00\x00\x1fA" + // 0x03BF0314: 0x00001F41 - "\x1f@\x03\x00\x00\x00\x1fB" + // 0x1F400300: 0x00001F42 - "\x1fA\x03\x00\x00\x00\x1fC" + // 0x1F410300: 0x00001F43 - "\x1f@\x03\x01\x00\x00\x1fD" + // 0x1F400301: 0x00001F44 - "\x1fA\x03\x01\x00\x00\x1fE" + // 0x1F410301: 0x00001F45 - "\x03\x9f\x03\x13\x00\x00\x1fH" + // 0x039F0313: 0x00001F48 - "\x03\x9f\x03\x14\x00\x00\x1fI" + // 0x039F0314: 0x00001F49 - "\x1fH\x03\x00\x00\x00\x1fJ" + // 0x1F480300: 0x00001F4A - "\x1fI\x03\x00\x00\x00\x1fK" + // 0x1F490300: 0x00001F4B - "\x1fH\x03\x01\x00\x00\x1fL" + // 0x1F480301: 0x00001F4C - "\x1fI\x03\x01\x00\x00\x1fM" + // 0x1F490301: 0x00001F4D - "\x03\xc5\x03\x13\x00\x00\x1fP" + // 0x03C50313: 0x00001F50 - "\x03\xc5\x03\x14\x00\x00\x1fQ" + // 0x03C50314: 0x00001F51 - "\x1fP\x03\x00\x00\x00\x1fR" + // 0x1F500300: 0x00001F52 - "\x1fQ\x03\x00\x00\x00\x1fS" + // 0x1F510300: 0x00001F53 - "\x1fP\x03\x01\x00\x00\x1fT" + // 0x1F500301: 0x00001F54 - "\x1fQ\x03\x01\x00\x00\x1fU" + // 0x1F510301: 0x00001F55 - "\x1fP\x03B\x00\x00\x1fV" + // 0x1F500342: 0x00001F56 - "\x1fQ\x03B\x00\x00\x1fW" + // 0x1F510342: 0x00001F57 - "\x03\xa5\x03\x14\x00\x00\x1fY" + // 0x03A50314: 0x00001F59 - "\x1fY\x03\x00\x00\x00\x1f[" + // 0x1F590300: 0x00001F5B - "\x1fY\x03\x01\x00\x00\x1f]" + // 0x1F590301: 0x00001F5D - "\x1fY\x03B\x00\x00\x1f_" + // 0x1F590342: 0x00001F5F - "\x03\xc9\x03\x13\x00\x00\x1f`" + // 0x03C90313: 0x00001F60 - "\x03\xc9\x03\x14\x00\x00\x1fa" + // 0x03C90314: 0x00001F61 - "\x1f`\x03\x00\x00\x00\x1fb" + // 0x1F600300: 0x00001F62 - "\x1fa\x03\x00\x00\x00\x1fc" + // 0x1F610300: 0x00001F63 - "\x1f`\x03\x01\x00\x00\x1fd" + // 0x1F600301: 0x00001F64 - "\x1fa\x03\x01\x00\x00\x1fe" + // 0x1F610301: 0x00001F65 - "\x1f`\x03B\x00\x00\x1ff" + // 0x1F600342: 0x00001F66 - "\x1fa\x03B\x00\x00\x1fg" + // 0x1F610342: 0x00001F67 - "\x03\xa9\x03\x13\x00\x00\x1fh" + // 0x03A90313: 0x00001F68 - "\x03\xa9\x03\x14\x00\x00\x1fi" + // 0x03A90314: 0x00001F69 - "\x1fh\x03\x00\x00\x00\x1fj" + // 0x1F680300: 0x00001F6A - "\x1fi\x03\x00\x00\x00\x1fk" + // 0x1F690300: 0x00001F6B - "\x1fh\x03\x01\x00\x00\x1fl" + // 0x1F680301: 0x00001F6C - "\x1fi\x03\x01\x00\x00\x1fm" + // 0x1F690301: 0x00001F6D - "\x1fh\x03B\x00\x00\x1fn" + // 0x1F680342: 0x00001F6E - "\x1fi\x03B\x00\x00\x1fo" + // 0x1F690342: 0x00001F6F - "\x03\xb1\x03\x00\x00\x00\x1fp" + // 0x03B10300: 0x00001F70 - "\x03\xb5\x03\x00\x00\x00\x1fr" + // 0x03B50300: 0x00001F72 - "\x03\xb7\x03\x00\x00\x00\x1ft" + // 0x03B70300: 0x00001F74 - "\x03\xb9\x03\x00\x00\x00\x1fv" + // 0x03B90300: 0x00001F76 - "\x03\xbf\x03\x00\x00\x00\x1fx" + // 0x03BF0300: 0x00001F78 - "\x03\xc5\x03\x00\x00\x00\x1fz" + // 0x03C50300: 0x00001F7A - "\x03\xc9\x03\x00\x00\x00\x1f|" + // 0x03C90300: 0x00001F7C - "\x1f\x00\x03E\x00\x00\x1f\x80" + // 0x1F000345: 0x00001F80 - "\x1f\x01\x03E\x00\x00\x1f\x81" + // 0x1F010345: 0x00001F81 - "\x1f\x02\x03E\x00\x00\x1f\x82" + // 0x1F020345: 0x00001F82 - "\x1f\x03\x03E\x00\x00\x1f\x83" + // 0x1F030345: 0x00001F83 - "\x1f\x04\x03E\x00\x00\x1f\x84" + // 0x1F040345: 0x00001F84 - "\x1f\x05\x03E\x00\x00\x1f\x85" + // 0x1F050345: 0x00001F85 - "\x1f\x06\x03E\x00\x00\x1f\x86" + // 0x1F060345: 0x00001F86 - "\x1f\a\x03E\x00\x00\x1f\x87" + // 0x1F070345: 0x00001F87 - "\x1f\b\x03E\x00\x00\x1f\x88" + // 0x1F080345: 0x00001F88 - "\x1f\t\x03E\x00\x00\x1f\x89" + // 0x1F090345: 0x00001F89 - "\x1f\n\x03E\x00\x00\x1f\x8a" + // 0x1F0A0345: 0x00001F8A - "\x1f\v\x03E\x00\x00\x1f\x8b" + // 0x1F0B0345: 0x00001F8B - "\x1f\f\x03E\x00\x00\x1f\x8c" + // 0x1F0C0345: 0x00001F8C - "\x1f\r\x03E\x00\x00\x1f\x8d" + // 0x1F0D0345: 0x00001F8D - "\x1f\x0e\x03E\x00\x00\x1f\x8e" + // 0x1F0E0345: 0x00001F8E - "\x1f\x0f\x03E\x00\x00\x1f\x8f" + // 0x1F0F0345: 0x00001F8F - "\x1f \x03E\x00\x00\x1f\x90" + // 0x1F200345: 0x00001F90 - "\x1f!\x03E\x00\x00\x1f\x91" + // 0x1F210345: 0x00001F91 - "\x1f\"\x03E\x00\x00\x1f\x92" + // 0x1F220345: 0x00001F92 - "\x1f#\x03E\x00\x00\x1f\x93" + // 0x1F230345: 0x00001F93 - "\x1f$\x03E\x00\x00\x1f\x94" + // 0x1F240345: 0x00001F94 - "\x1f%\x03E\x00\x00\x1f\x95" + // 0x1F250345: 0x00001F95 - "\x1f&\x03E\x00\x00\x1f\x96" + // 0x1F260345: 0x00001F96 - "\x1f'\x03E\x00\x00\x1f\x97" + // 0x1F270345: 0x00001F97 - "\x1f(\x03E\x00\x00\x1f\x98" + // 0x1F280345: 0x00001F98 - "\x1f)\x03E\x00\x00\x1f\x99" + // 0x1F290345: 0x00001F99 - "\x1f*\x03E\x00\x00\x1f\x9a" + // 0x1F2A0345: 0x00001F9A - "\x1f+\x03E\x00\x00\x1f\x9b" + // 0x1F2B0345: 0x00001F9B - "\x1f,\x03E\x00\x00\x1f\x9c" + // 0x1F2C0345: 0x00001F9C - "\x1f-\x03E\x00\x00\x1f\x9d" + // 0x1F2D0345: 0x00001F9D - "\x1f.\x03E\x00\x00\x1f\x9e" + // 0x1F2E0345: 0x00001F9E - "\x1f/\x03E\x00\x00\x1f\x9f" + // 0x1F2F0345: 0x00001F9F - "\x1f`\x03E\x00\x00\x1f\xa0" + // 0x1F600345: 0x00001FA0 - "\x1fa\x03E\x00\x00\x1f\xa1" + // 0x1F610345: 0x00001FA1 - "\x1fb\x03E\x00\x00\x1f\xa2" + // 0x1F620345: 0x00001FA2 - "\x1fc\x03E\x00\x00\x1f\xa3" + // 0x1F630345: 0x00001FA3 - "\x1fd\x03E\x00\x00\x1f\xa4" + // 0x1F640345: 0x00001FA4 - "\x1fe\x03E\x00\x00\x1f\xa5" + // 0x1F650345: 0x00001FA5 - "\x1ff\x03E\x00\x00\x1f\xa6" + // 0x1F660345: 0x00001FA6 - "\x1fg\x03E\x00\x00\x1f\xa7" + // 0x1F670345: 0x00001FA7 - "\x1fh\x03E\x00\x00\x1f\xa8" + // 0x1F680345: 0x00001FA8 - "\x1fi\x03E\x00\x00\x1f\xa9" + // 0x1F690345: 0x00001FA9 - "\x1fj\x03E\x00\x00\x1f\xaa" + // 0x1F6A0345: 0x00001FAA - "\x1fk\x03E\x00\x00\x1f\xab" + // 0x1F6B0345: 0x00001FAB - "\x1fl\x03E\x00\x00\x1f\xac" + // 0x1F6C0345: 0x00001FAC - "\x1fm\x03E\x00\x00\x1f\xad" + // 0x1F6D0345: 0x00001FAD - "\x1fn\x03E\x00\x00\x1f\xae" + // 0x1F6E0345: 0x00001FAE - "\x1fo\x03E\x00\x00\x1f\xaf" + // 0x1F6F0345: 0x00001FAF - "\x03\xb1\x03\x06\x00\x00\x1f\xb0" + // 0x03B10306: 0x00001FB0 - "\x03\xb1\x03\x04\x00\x00\x1f\xb1" + // 0x03B10304: 0x00001FB1 - "\x1fp\x03E\x00\x00\x1f\xb2" + // 0x1F700345: 0x00001FB2 - "\x03\xb1\x03E\x00\x00\x1f\xb3" + // 0x03B10345: 0x00001FB3 - "\x03\xac\x03E\x00\x00\x1f\xb4" + // 0x03AC0345: 0x00001FB4 - "\x03\xb1\x03B\x00\x00\x1f\xb6" + // 0x03B10342: 0x00001FB6 - "\x1f\xb6\x03E\x00\x00\x1f\xb7" + // 0x1FB60345: 0x00001FB7 - "\x03\x91\x03\x06\x00\x00\x1f\xb8" + // 0x03910306: 0x00001FB8 - "\x03\x91\x03\x04\x00\x00\x1f\xb9" + // 0x03910304: 0x00001FB9 - "\x03\x91\x03\x00\x00\x00\x1f\xba" + // 0x03910300: 0x00001FBA - "\x03\x91\x03E\x00\x00\x1f\xbc" + // 0x03910345: 0x00001FBC - "\x00\xa8\x03B\x00\x00\x1f\xc1" + // 0x00A80342: 0x00001FC1 - "\x1ft\x03E\x00\x00\x1f\xc2" + // 0x1F740345: 0x00001FC2 - "\x03\xb7\x03E\x00\x00\x1f\xc3" + // 0x03B70345: 0x00001FC3 - "\x03\xae\x03E\x00\x00\x1f\xc4" + // 0x03AE0345: 0x00001FC4 - "\x03\xb7\x03B\x00\x00\x1f\xc6" + // 0x03B70342: 0x00001FC6 - "\x1f\xc6\x03E\x00\x00\x1f\xc7" + // 0x1FC60345: 0x00001FC7 - "\x03\x95\x03\x00\x00\x00\x1f\xc8" + // 0x03950300: 0x00001FC8 - "\x03\x97\x03\x00\x00\x00\x1f\xca" + // 0x03970300: 0x00001FCA - "\x03\x97\x03E\x00\x00\x1f\xcc" + // 0x03970345: 0x00001FCC - "\x1f\xbf\x03\x00\x00\x00\x1f\xcd" + // 0x1FBF0300: 0x00001FCD - "\x1f\xbf\x03\x01\x00\x00\x1f\xce" + // 0x1FBF0301: 0x00001FCE - "\x1f\xbf\x03B\x00\x00\x1f\xcf" + // 0x1FBF0342: 0x00001FCF - "\x03\xb9\x03\x06\x00\x00\x1f\xd0" + // 0x03B90306: 0x00001FD0 - "\x03\xb9\x03\x04\x00\x00\x1f\xd1" + // 0x03B90304: 0x00001FD1 - "\x03\xca\x03\x00\x00\x00\x1f\xd2" + // 0x03CA0300: 0x00001FD2 - "\x03\xb9\x03B\x00\x00\x1f\xd6" + // 0x03B90342: 0x00001FD6 - "\x03\xca\x03B\x00\x00\x1f\xd7" + // 0x03CA0342: 0x00001FD7 - "\x03\x99\x03\x06\x00\x00\x1f\xd8" + // 0x03990306: 0x00001FD8 - "\x03\x99\x03\x04\x00\x00\x1f\xd9" + // 0x03990304: 0x00001FD9 - "\x03\x99\x03\x00\x00\x00\x1f\xda" + // 0x03990300: 0x00001FDA - "\x1f\xfe\x03\x00\x00\x00\x1f\xdd" + // 0x1FFE0300: 0x00001FDD - "\x1f\xfe\x03\x01\x00\x00\x1f\xde" + // 0x1FFE0301: 0x00001FDE - "\x1f\xfe\x03B\x00\x00\x1f\xdf" + // 0x1FFE0342: 0x00001FDF - "\x03\xc5\x03\x06\x00\x00\x1f\xe0" + // 0x03C50306: 0x00001FE0 - "\x03\xc5\x03\x04\x00\x00\x1f\xe1" + // 0x03C50304: 0x00001FE1 - "\x03\xcb\x03\x00\x00\x00\x1f\xe2" + // 0x03CB0300: 0x00001FE2 - "\x03\xc1\x03\x13\x00\x00\x1f\xe4" + // 0x03C10313: 0x00001FE4 - "\x03\xc1\x03\x14\x00\x00\x1f\xe5" + // 0x03C10314: 0x00001FE5 - "\x03\xc5\x03B\x00\x00\x1f\xe6" + // 0x03C50342: 0x00001FE6 - "\x03\xcb\x03B\x00\x00\x1f\xe7" + // 0x03CB0342: 0x00001FE7 - "\x03\xa5\x03\x06\x00\x00\x1f\xe8" + // 0x03A50306: 0x00001FE8 - "\x03\xa5\x03\x04\x00\x00\x1f\xe9" + // 0x03A50304: 0x00001FE9 - "\x03\xa5\x03\x00\x00\x00\x1f\xea" + // 0x03A50300: 0x00001FEA - "\x03\xa1\x03\x14\x00\x00\x1f\xec" + // 0x03A10314: 0x00001FEC - "\x00\xa8\x03\x00\x00\x00\x1f\xed" + // 0x00A80300: 0x00001FED - "\x1f|\x03E\x00\x00\x1f\xf2" + // 0x1F7C0345: 0x00001FF2 - "\x03\xc9\x03E\x00\x00\x1f\xf3" + // 0x03C90345: 0x00001FF3 - "\x03\xce\x03E\x00\x00\x1f\xf4" + // 0x03CE0345: 0x00001FF4 - "\x03\xc9\x03B\x00\x00\x1f\xf6" + // 0x03C90342: 0x00001FF6 - "\x1f\xf6\x03E\x00\x00\x1f\xf7" + // 0x1FF60345: 0x00001FF7 - "\x03\x9f\x03\x00\x00\x00\x1f\xf8" + // 0x039F0300: 0x00001FF8 - "\x03\xa9\x03\x00\x00\x00\x1f\xfa" + // 0x03A90300: 0x00001FFA - "\x03\xa9\x03E\x00\x00\x1f\xfc" + // 0x03A90345: 0x00001FFC - "!\x90\x038\x00\x00!\x9a" + // 0x21900338: 0x0000219A - "!\x92\x038\x00\x00!\x9b" + // 0x21920338: 0x0000219B - "!\x94\x038\x00\x00!\xae" + // 0x21940338: 0x000021AE - "!\xd0\x038\x00\x00!\xcd" + // 0x21D00338: 0x000021CD - "!\xd4\x038\x00\x00!\xce" + // 0x21D40338: 0x000021CE - "!\xd2\x038\x00\x00!\xcf" + // 0x21D20338: 0x000021CF - "\"\x03\x038\x00\x00\"\x04" + // 0x22030338: 0x00002204 - "\"\b\x038\x00\x00\"\t" + // 0x22080338: 0x00002209 - "\"\v\x038\x00\x00\"\f" + // 0x220B0338: 0x0000220C - "\"#\x038\x00\x00\"$" + // 0x22230338: 0x00002224 - "\"%\x038\x00\x00\"&" + // 0x22250338: 0x00002226 - "\"<\x038\x00\x00\"A" + // 0x223C0338: 0x00002241 - "\"C\x038\x00\x00\"D" + // 0x22430338: 0x00002244 - "\"E\x038\x00\x00\"G" + // 0x22450338: 0x00002247 - "\"H\x038\x00\x00\"I" + // 0x22480338: 0x00002249 - "\x00=\x038\x00\x00\"`" + // 0x003D0338: 0x00002260 - "\"a\x038\x00\x00\"b" + // 0x22610338: 0x00002262 - "\"M\x038\x00\x00\"m" + // 0x224D0338: 0x0000226D - "\x00<\x038\x00\x00\"n" + // 0x003C0338: 0x0000226E - "\x00>\x038\x00\x00\"o" + // 0x003E0338: 0x0000226F - "\"d\x038\x00\x00\"p" + // 0x22640338: 0x00002270 - "\"e\x038\x00\x00\"q" + // 0x22650338: 0x00002271 - "\"r\x038\x00\x00\"t" + // 0x22720338: 0x00002274 - "\"s\x038\x00\x00\"u" + // 0x22730338: 0x00002275 - "\"v\x038\x00\x00\"x" + // 0x22760338: 0x00002278 - "\"w\x038\x00\x00\"y" + // 0x22770338: 0x00002279 - "\"z\x038\x00\x00\"\x80" + // 0x227A0338: 0x00002280 - "\"{\x038\x00\x00\"\x81" + // 0x227B0338: 0x00002281 - "\"\x82\x038\x00\x00\"\x84" + // 0x22820338: 0x00002284 - "\"\x83\x038\x00\x00\"\x85" + // 0x22830338: 0x00002285 - "\"\x86\x038\x00\x00\"\x88" + // 0x22860338: 0x00002288 - "\"\x87\x038\x00\x00\"\x89" + // 0x22870338: 0x00002289 - "\"\xa2\x038\x00\x00\"\xac" + // 0x22A20338: 0x000022AC - "\"\xa8\x038\x00\x00\"\xad" + // 0x22A80338: 0x000022AD - "\"\xa9\x038\x00\x00\"\xae" + // 0x22A90338: 0x000022AE - "\"\xab\x038\x00\x00\"\xaf" + // 0x22AB0338: 0x000022AF - "\"|\x038\x00\x00\"\xe0" + // 0x227C0338: 0x000022E0 - "\"}\x038\x00\x00\"\xe1" + // 0x227D0338: 0x000022E1 - "\"\x91\x038\x00\x00\"\xe2" + // 0x22910338: 0x000022E2 - "\"\x92\x038\x00\x00\"\xe3" + // 0x22920338: 0x000022E3 - "\"\xb2\x038\x00\x00\"\xea" + // 0x22B20338: 0x000022EA - "\"\xb3\x038\x00\x00\"\xeb" + // 0x22B30338: 0x000022EB - "\"\xb4\x038\x00\x00\"\xec" + // 0x22B40338: 0x000022EC - "\"\xb5\x038\x00\x00\"\xed" + // 0x22B50338: 0x000022ED - "0K0\x99\x00\x000L" + // 0x304B3099: 0x0000304C - "0M0\x99\x00\x000N" + // 0x304D3099: 0x0000304E - "0O0\x99\x00\x000P" + // 0x304F3099: 0x00003050 - "0Q0\x99\x00\x000R" + // 0x30513099: 0x00003052 - "0S0\x99\x00\x000T" + // 0x30533099: 0x00003054 - "0U0\x99\x00\x000V" + // 0x30553099: 0x00003056 - "0W0\x99\x00\x000X" + // 0x30573099: 0x00003058 - "0Y0\x99\x00\x000Z" + // 0x30593099: 0x0000305A - "0[0\x99\x00\x000\\" + // 0x305B3099: 0x0000305C - "0]0\x99\x00\x000^" + // 0x305D3099: 0x0000305E - "0_0\x99\x00\x000`" + // 0x305F3099: 0x00003060 - "0a0\x99\x00\x000b" + // 0x30613099: 0x00003062 - "0d0\x99\x00\x000e" + // 0x30643099: 0x00003065 - "0f0\x99\x00\x000g" + // 0x30663099: 0x00003067 - "0h0\x99\x00\x000i" + // 0x30683099: 0x00003069 - "0o0\x99\x00\x000p" + // 0x306F3099: 0x00003070 - "0o0\x9a\x00\x000q" + // 0x306F309A: 0x00003071 - "0r0\x99\x00\x000s" + // 0x30723099: 0x00003073 - "0r0\x9a\x00\x000t" + // 0x3072309A: 0x00003074 - "0u0\x99\x00\x000v" + // 0x30753099: 0x00003076 - "0u0\x9a\x00\x000w" + // 0x3075309A: 0x00003077 - "0x0\x99\x00\x000y" + // 0x30783099: 0x00003079 - "0x0\x9a\x00\x000z" + // 0x3078309A: 0x0000307A - "0{0\x99\x00\x000|" + // 0x307B3099: 0x0000307C - "0{0\x9a\x00\x000}" + // 0x307B309A: 0x0000307D - "0F0\x99\x00\x000\x94" + // 0x30463099: 0x00003094 - "0\x9d0\x99\x00\x000\x9e" + // 0x309D3099: 0x0000309E - "0\xab0\x99\x00\x000\xac" + // 0x30AB3099: 0x000030AC - "0\xad0\x99\x00\x000\xae" + // 0x30AD3099: 0x000030AE - "0\xaf0\x99\x00\x000\xb0" + // 0x30AF3099: 0x000030B0 - "0\xb10\x99\x00\x000\xb2" + // 0x30B13099: 0x000030B2 - "0\xb30\x99\x00\x000\xb4" + // 0x30B33099: 0x000030B4 - "0\xb50\x99\x00\x000\xb6" + // 0x30B53099: 0x000030B6 - "0\xb70\x99\x00\x000\xb8" + // 0x30B73099: 0x000030B8 - "0\xb90\x99\x00\x000\xba" + // 0x30B93099: 0x000030BA - "0\xbb0\x99\x00\x000\xbc" + // 0x30BB3099: 0x000030BC - "0\xbd0\x99\x00\x000\xbe" + // 0x30BD3099: 0x000030BE - "0\xbf0\x99\x00\x000\xc0" + // 0x30BF3099: 0x000030C0 - "0\xc10\x99\x00\x000\xc2" + // 0x30C13099: 0x000030C2 - "0\xc40\x99\x00\x000\xc5" + // 0x30C43099: 0x000030C5 - "0\xc60\x99\x00\x000\xc7" + // 0x30C63099: 0x000030C7 - "0\xc80\x99\x00\x000\xc9" + // 0x30C83099: 0x000030C9 - "0\xcf0\x99\x00\x000\xd0" + // 0x30CF3099: 0x000030D0 - "0\xcf0\x9a\x00\x000\xd1" + // 0x30CF309A: 0x000030D1 - "0\xd20\x99\x00\x000\xd3" + // 0x30D23099: 0x000030D3 - "0\xd20\x9a\x00\x000\xd4" + // 0x30D2309A: 0x000030D4 - "0\xd50\x99\x00\x000\xd6" + // 0x30D53099: 0x000030D6 - "0\xd50\x9a\x00\x000\xd7" + // 0x30D5309A: 0x000030D7 - "0\xd80\x99\x00\x000\xd9" + // 0x30D83099: 0x000030D9 - "0\xd80\x9a\x00\x000\xda" + // 0x30D8309A: 0x000030DA - "0\xdb0\x99\x00\x000\xdc" + // 0x30DB3099: 0x000030DC - "0\xdb0\x9a\x00\x000\xdd" + // 0x30DB309A: 0x000030DD - "0\xa60\x99\x00\x000\xf4" + // 0x30A63099: 0x000030F4 - "0\xef0\x99\x00\x000\xf7" + // 0x30EF3099: 0x000030F7 - "0\xf00\x99\x00\x000\xf8" + // 0x30F03099: 0x000030F8 - "0\xf10\x99\x00\x000\xf9" + // 0x30F13099: 0x000030F9 - "0\xf20\x99\x00\x000\xfa" + // 0x30F23099: 0x000030FA - "0\xfd0\x99\x00\x000\xfe" + // 0x30FD3099: 0x000030FE - "\x10\x99\x10\xba\x00\x01\x10\x9a" + // 0x109910BA: 0x0001109A - "\x10\x9b\x10\xba\x00\x01\x10\x9c" + // 0x109B10BA: 0x0001109C - "\x10\xa5\x10\xba\x00\x01\x10\xab" + // 0x10A510BA: 0x000110AB - "\x111\x11'\x00\x01\x11." + // 0x11311127: 0x0001112E - "\x112\x11'\x00\x01\x11/" + // 0x11321127: 0x0001112F - "\x13G\x13>\x00\x01\x13K" + // 0x1347133E: 0x0001134B - "\x13G\x13W\x00\x01\x13L" + // 0x13471357: 0x0001134C - "\x14\xb9\x14\xba\x00\x01\x14\xbb" + // 0x14B914BA: 0x000114BB - "\x14\xb9\x14\xb0\x00\x01\x14\xbc" + // 0x14B914B0: 0x000114BC - "\x14\xb9\x14\xbd\x00\x01\x14\xbe" + // 0x14B914BD: 0x000114BE - "\x15\xb8\x15\xaf\x00\x01\x15\xba" + // 0x15B815AF: 0x000115BA - "\x15\xb9\x15\xaf\x00\x01\x15\xbb" + // 0x15B915AF: 0x000115BB - "\x195\x190\x00\x01\x198" + // 0x19351930: 0x00011938 + "\x00\x01\x04\x00`\x00\x00\xc0" + // 0x00041 0x00300: 0x000C0 + "\x00\x01\x04\x00` \x00\xc1" + // 0x00041 0x00301: 0x000C1 + "\x00\x01\x04\x00`@\x00\xc2" + // 0x00041 0x00302: 0x000C2 + "\x00\x01\x04\x00``\x00\xc3" + // 0x00041 0x00303: 0x000C3 + "\x00\x01\x04\x00a\x00\x00\xc4" + // 0x00041 0x00308: 0x000C4 + "\x00\x01\x04\x00a@\x00\xc5" + // 0x00041 0x0030A: 0x000C5 + "\x00\x01\f\x00d\xe0\x00\xc7" + // 0x00043 0x00327: 0x000C7 + "\x00\x01\x14\x00`\x00\x00\xc8" + // 0x00045 0x00300: 0x000C8 + "\x00\x01\x14\x00` \x00\xc9" + // 0x00045 0x00301: 0x000C9 + "\x00\x01\x14\x00`@\x00\xca" + // 0x00045 0x00302: 0x000CA + "\x00\x01\x14\x00a\x00\x00\xcb" + // 0x00045 0x00308: 0x000CB + "\x00\x01$\x00`\x00\x00\xcc" + // 0x00049 0x00300: 0x000CC + "\x00\x01$\x00` \x00\xcd" + // 0x00049 0x00301: 0x000CD + "\x00\x01$\x00`@\x00\xce" + // 0x00049 0x00302: 0x000CE + "\x00\x01$\x00a\x00\x00\xcf" + // 0x00049 0x00308: 0x000CF + "\x00\x018\x00``\x00\xd1" + // 0x0004E 0x00303: 0x000D1 + "\x00\x01<\x00`\x00\x00\xd2" + // 0x0004F 0x00300: 0x000D2 + "\x00\x01<\x00` \x00\xd3" + // 0x0004F 0x00301: 0x000D3 + "\x00\x01<\x00`@\x00\xd4" + // 0x0004F 0x00302: 0x000D4 + "\x00\x01<\x00``\x00\xd5" + // 0x0004F 0x00303: 0x000D5 + "\x00\x01<\x00a\x00\x00\xd6" + // 0x0004F 0x00308: 0x000D6 + "\x00\x01T\x00`\x00\x00\xd9" + // 0x00055 0x00300: 0x000D9 + "\x00\x01T\x00` \x00\xda" + // 0x00055 0x00301: 0x000DA + "\x00\x01T\x00`@\x00\xdb" + // 0x00055 0x00302: 0x000DB + "\x00\x01T\x00a\x00\x00\xdc" + // 0x00055 0x00308: 0x000DC + "\x00\x01d\x00` \x00\xdd" + // 0x00059 0x00301: 0x000DD + "\x00\x01\x84\x00`\x00\x00\xe0" + // 0x00061 0x00300: 0x000E0 + "\x00\x01\x84\x00` \x00\xe1" + // 0x00061 0x00301: 0x000E1 + "\x00\x01\x84\x00`@\x00\xe2" + // 0x00061 0x00302: 0x000E2 + "\x00\x01\x84\x00``\x00\xe3" + // 0x00061 0x00303: 0x000E3 + "\x00\x01\x84\x00a\x00\x00\xe4" + // 0x00061 0x00308: 0x000E4 + "\x00\x01\x84\x00a@\x00\xe5" + // 0x00061 0x0030A: 0x000E5 + "\x00\x01\x8c\x00d\xe0\x00\xe7" + // 0x00063 0x00327: 0x000E7 + "\x00\x01\x94\x00`\x00\x00\xe8" + // 0x00065 0x00300: 0x000E8 + "\x00\x01\x94\x00` \x00\xe9" + // 0x00065 0x00301: 0x000E9 + "\x00\x01\x94\x00`@\x00\xea" + // 0x00065 0x00302: 0x000EA + "\x00\x01\x94\x00a\x00\x00\xeb" + // 0x00065 0x00308: 0x000EB + "\x00\x01\xa4\x00`\x00\x00\xec" + // 0x00069 0x00300: 0x000EC + "\x00\x01\xa4\x00` \x00\xed" + // 0x00069 0x00301: 0x000ED + "\x00\x01\xa4\x00`@\x00\xee" + // 0x00069 0x00302: 0x000EE + "\x00\x01\xa4\x00a\x00\x00\xef" + // 0x00069 0x00308: 0x000EF + "\x00\x01\xb8\x00``\x00\xf1" + // 0x0006E 0x00303: 0x000F1 + "\x00\x01\xbc\x00`\x00\x00\xf2" + // 0x0006F 0x00300: 0x000F2 + "\x00\x01\xbc\x00` \x00\xf3" + // 0x0006F 0x00301: 0x000F3 + "\x00\x01\xbc\x00`@\x00\xf4" + // 0x0006F 0x00302: 0x000F4 + "\x00\x01\xbc\x00``\x00\xf5" + // 0x0006F 0x00303: 0x000F5 + "\x00\x01\xbc\x00a\x00\x00\xf6" + // 0x0006F 0x00308: 0x000F6 + "\x00\x01\xd4\x00`\x00\x00\xf9" + // 0x00075 0x00300: 0x000F9 + "\x00\x01\xd4\x00` \x00\xfa" + // 0x00075 0x00301: 0x000FA + "\x00\x01\xd4\x00`@\x00\xfb" + // 0x00075 0x00302: 0x000FB + "\x00\x01\xd4\x00a\x00\x00\xfc" + // 0x00075 0x00308: 0x000FC + "\x00\x01\xe4\x00` \x00\xfd" + // 0x00079 0x00301: 0x000FD + "\x00\x01\xe4\x00a\x00\x00\xff" + // 0x00079 0x00308: 0x000FF + "\x00\x01\x04\x00`\x80\x01\x00" + // 0x00041 0x00304: 0x00100 + "\x00\x01\x84\x00`\x80\x01\x01" + // 0x00061 0x00304: 0x00101 + "\x00\x01\x04\x00`\xc0\x01\x02" + // 0x00041 0x00306: 0x00102 + "\x00\x01\x84\x00`\xc0\x01\x03" + // 0x00061 0x00306: 0x00103 + "\x00\x01\x04\x00e\x00\x01\x04" + // 0x00041 0x00328: 0x00104 + "\x00\x01\x84\x00e\x00\x01\x05" + // 0x00061 0x00328: 0x00105 + "\x00\x01\f\x00` \x01\x06" + // 0x00043 0x00301: 0x00106 + "\x00\x01\x8c\x00` \x01\a" + // 0x00063 0x00301: 0x00107 + "\x00\x01\f\x00`@\x01\b" + // 0x00043 0x00302: 0x00108 + "\x00\x01\x8c\x00`@\x01\t" + // 0x00063 0x00302: 0x00109 + "\x00\x01\f\x00`\xe0\x01\n" + // 0x00043 0x00307: 0x0010A + "\x00\x01\x8c\x00`\xe0\x01\v" + // 0x00063 0x00307: 0x0010B + "\x00\x01\f\x00a\x80\x01\f" + // 0x00043 0x0030C: 0x0010C + "\x00\x01\x8c\x00a\x80\x01\r" + // 0x00063 0x0030C: 0x0010D + "\x00\x01\x10\x00a\x80\x01\x0e" + // 0x00044 0x0030C: 0x0010E + "\x00\x01\x90\x00a\x80\x01\x0f" + // 0x00064 0x0030C: 0x0010F + "\x00\x01\x14\x00`\x80\x01\x12" + // 0x00045 0x00304: 0x00112 + "\x00\x01\x94\x00`\x80\x01\x13" + // 0x00065 0x00304: 0x00113 + "\x00\x01\x14\x00`\xc0\x01\x14" + // 0x00045 0x00306: 0x00114 + "\x00\x01\x94\x00`\xc0\x01\x15" + // 0x00065 0x00306: 0x00115 + "\x00\x01\x14\x00`\xe0\x01\x16" + // 0x00045 0x00307: 0x00116 + "\x00\x01\x94\x00`\xe0\x01\x17" + // 0x00065 0x00307: 0x00117 + "\x00\x01\x14\x00e\x00\x01\x18" + // 0x00045 0x00328: 0x00118 + "\x00\x01\x94\x00e\x00\x01\x19" + // 0x00065 0x00328: 0x00119 + "\x00\x01\x14\x00a\x80\x01\x1a" + // 0x00045 0x0030C: 0x0011A + "\x00\x01\x94\x00a\x80\x01\x1b" + // 0x00065 0x0030C: 0x0011B + "\x00\x01\x1c\x00`@\x01\x1c" + // 0x00047 0x00302: 0x0011C + "\x00\x01\x9c\x00`@\x01\x1d" + // 0x00067 0x00302: 0x0011D + "\x00\x01\x1c\x00`\xc0\x01\x1e" + // 0x00047 0x00306: 0x0011E + "\x00\x01\x9c\x00`\xc0\x01\x1f" + // 0x00067 0x00306: 0x0011F + "\x00\x01\x1c\x00`\xe0\x01 " + // 0x00047 0x00307: 0x00120 + "\x00\x01\x9c\x00`\xe0\x01!" + // 0x00067 0x00307: 0x00121 + "\x00\x01\x1c\x00d\xe0\x01\"" + // 0x00047 0x00327: 0x00122 + "\x00\x01\x9c\x00d\xe0\x01#" + // 0x00067 0x00327: 0x00123 + "\x00\x01 \x00`@\x01$" + // 0x00048 0x00302: 0x00124 + "\x00\x01\xa0\x00`@\x01%" + // 0x00068 0x00302: 0x00125 + "\x00\x01$\x00``\x01(" + // 0x00049 0x00303: 0x00128 + "\x00\x01\xa4\x00``\x01)" + // 0x00069 0x00303: 0x00129 + "\x00\x01$\x00`\x80\x01*" + // 0x00049 0x00304: 0x0012A + "\x00\x01\xa4\x00`\x80\x01+" + // 0x00069 0x00304: 0x0012B + "\x00\x01$\x00`\xc0\x01," + // 0x00049 0x00306: 0x0012C + "\x00\x01\xa4\x00`\xc0\x01-" + // 0x00069 0x00306: 0x0012D + "\x00\x01$\x00e\x00\x01." + // 0x00049 0x00328: 0x0012E + "\x00\x01\xa4\x00e\x00\x01/" + // 0x00069 0x00328: 0x0012F + "\x00\x01$\x00`\xe0\x010" + // 0x00049 0x00307: 0x00130 + "\x00\x01(\x00`@\x014" + // 0x0004A 0x00302: 0x00134 + "\x00\x01\xa8\x00`@\x015" + // 0x0006A 0x00302: 0x00135 + "\x00\x01,\x00d\xe0\x016" + // 0x0004B 0x00327: 0x00136 + "\x00\x01\xac\x00d\xe0\x017" + // 0x0006B 0x00327: 0x00137 + "\x00\x010\x00` \x019" + // 0x0004C 0x00301: 0x00139 + "\x00\x01\xb0\x00` \x01:" + // 0x0006C 0x00301: 0x0013A + "\x00\x010\x00d\xe0\x01;" + // 0x0004C 0x00327: 0x0013B + "\x00\x01\xb0\x00d\xe0\x01<" + // 0x0006C 0x00327: 0x0013C + "\x00\x010\x00a\x80\x01=" + // 0x0004C 0x0030C: 0x0013D + "\x00\x01\xb0\x00a\x80\x01>" + // 0x0006C 0x0030C: 0x0013E + "\x00\x018\x00` \x01C" + // 0x0004E 0x00301: 0x00143 + "\x00\x01\xb8\x00` \x01D" + // 0x0006E 0x00301: 0x00144 + "\x00\x018\x00d\xe0\x01E" + // 0x0004E 0x00327: 0x00145 + "\x00\x01\xb8\x00d\xe0\x01F" + // 0x0006E 0x00327: 0x00146 + "\x00\x018\x00a\x80\x01G" + // 0x0004E 0x0030C: 0x00147 + "\x00\x01\xb8\x00a\x80\x01H" + // 0x0006E 0x0030C: 0x00148 + "\x00\x01<\x00`\x80\x01L" + // 0x0004F 0x00304: 0x0014C + "\x00\x01\xbc\x00`\x80\x01M" + // 0x0006F 0x00304: 0x0014D + "\x00\x01<\x00`\xc0\x01N" + // 0x0004F 0x00306: 0x0014E + "\x00\x01\xbc\x00`\xc0\x01O" + // 0x0006F 0x00306: 0x0014F + "\x00\x01<\x00a`\x01P" + // 0x0004F 0x0030B: 0x00150 + "\x00\x01\xbc\x00a`\x01Q" + // 0x0006F 0x0030B: 0x00151 + "\x00\x01H\x00` \x01T" + // 0x00052 0x00301: 0x00154 + "\x00\x01\xc8\x00` \x01U" + // 0x00072 0x00301: 0x00155 + "\x00\x01H\x00d\xe0\x01V" + // 0x00052 0x00327: 0x00156 + "\x00\x01\xc8\x00d\xe0\x01W" + // 0x00072 0x00327: 0x00157 + "\x00\x01H\x00a\x80\x01X" + // 0x00052 0x0030C: 0x00158 + "\x00\x01\xc8\x00a\x80\x01Y" + // 0x00072 0x0030C: 0x00159 + "\x00\x01L\x00` \x01Z" + // 0x00053 0x00301: 0x0015A + "\x00\x01\xcc\x00` \x01[" + // 0x00073 0x00301: 0x0015B + "\x00\x01L\x00`@\x01\\" + // 0x00053 0x00302: 0x0015C + "\x00\x01\xcc\x00`@\x01]" + // 0x00073 0x00302: 0x0015D + "\x00\x01L\x00d\xe0\x01^" + // 0x00053 0x00327: 0x0015E + "\x00\x01\xcc\x00d\xe0\x01_" + // 0x00073 0x00327: 0x0015F + "\x00\x01L\x00a\x80\x01`" + // 0x00053 0x0030C: 0x00160 + "\x00\x01\xcc\x00a\x80\x01a" + // 0x00073 0x0030C: 0x00161 + "\x00\x01P\x00d\xe0\x01b" + // 0x00054 0x00327: 0x00162 + "\x00\x01\xd0\x00d\xe0\x01c" + // 0x00074 0x00327: 0x00163 + "\x00\x01P\x00a\x80\x01d" + // 0x00054 0x0030C: 0x00164 + "\x00\x01\xd0\x00a\x80\x01e" + // 0x00074 0x0030C: 0x00165 + "\x00\x01T\x00``\x01h" + // 0x00055 0x00303: 0x00168 + "\x00\x01\xd4\x00``\x01i" + // 0x00075 0x00303: 0x00169 + "\x00\x01T\x00`\x80\x01j" + // 0x00055 0x00304: 0x0016A + "\x00\x01\xd4\x00`\x80\x01k" + // 0x00075 0x00304: 0x0016B + "\x00\x01T\x00`\xc0\x01l" + // 0x00055 0x00306: 0x0016C + "\x00\x01\xd4\x00`\xc0\x01m" + // 0x00075 0x00306: 0x0016D + "\x00\x01T\x00a@\x01n" + // 0x00055 0x0030A: 0x0016E + "\x00\x01\xd4\x00a@\x01o" + // 0x00075 0x0030A: 0x0016F + "\x00\x01T\x00a`\x01p" + // 0x00055 0x0030B: 0x00170 + "\x00\x01\xd4\x00a`\x01q" + // 0x00075 0x0030B: 0x00171 + "\x00\x01T\x00e\x00\x01r" + // 0x00055 0x00328: 0x00172 + "\x00\x01\xd4\x00e\x00\x01s" + // 0x00075 0x00328: 0x00173 + "\x00\x01\\\x00`@\x01t" + // 0x00057 0x00302: 0x00174 + "\x00\x01\xdc\x00`@\x01u" + // 0x00077 0x00302: 0x00175 + "\x00\x01d\x00`@\x01v" + // 0x00059 0x00302: 0x00176 + "\x00\x01\xe4\x00`@\x01w" + // 0x00079 0x00302: 0x00177 + "\x00\x01d\x00a\x00\x01x" + // 0x00059 0x00308: 0x00178 + "\x00\x01h\x00` \x01y" + // 0x0005A 0x00301: 0x00179 + "\x00\x01\xe8\x00` \x01z" + // 0x0007A 0x00301: 0x0017A + "\x00\x01h\x00`\xe0\x01{" + // 0x0005A 0x00307: 0x0017B + "\x00\x01\xe8\x00`\xe0\x01|" + // 0x0007A 0x00307: 0x0017C + "\x00\x01h\x00a\x80\x01}" + // 0x0005A 0x0030C: 0x0017D + "\x00\x01\xe8\x00a\x80\x01~" + // 0x0007A 0x0030C: 0x0017E + "\x00\x01<\x00c`\x01\xa0" + // 0x0004F 0x0031B: 0x001A0 + "\x00\x01\xbc\x00c`\x01\xa1" + // 0x0006F 0x0031B: 0x001A1 + "\x00\x01T\x00c`\x01\xaf" + // 0x00055 0x0031B: 0x001AF + "\x00\x01\xd4\x00c`\x01\xb0" + // 0x00075 0x0031B: 0x001B0 + "\x00\x01\x04\x00a\x80\x01\xcd" + // 0x00041 0x0030C: 0x001CD + "\x00\x01\x84\x00a\x80\x01\xce" + // 0x00061 0x0030C: 0x001CE + "\x00\x01$\x00a\x80\x01\xcf" + // 0x00049 0x0030C: 0x001CF + "\x00\x01\xa4\x00a\x80\x01\xd0" + // 0x00069 0x0030C: 0x001D0 + "\x00\x01<\x00a\x80\x01\xd1" + // 0x0004F 0x0030C: 0x001D1 + "\x00\x01\xbc\x00a\x80\x01\xd2" + // 0x0006F 0x0030C: 0x001D2 + "\x00\x01T\x00a\x80\x01\xd3" + // 0x00055 0x0030C: 0x001D3 + "\x00\x01\xd4\x00a\x80\x01\xd4" + // 0x00075 0x0030C: 0x001D4 + "\x00\x03p\x00`\x80\x01\xd5" + // 0x000DC 0x00304: 0x001D5 + "\x00\x03\xf0\x00`\x80\x01\xd6" + // 0x000FC 0x00304: 0x001D6 + "\x00\x03p\x00` \x01\xd7" + // 0x000DC 0x00301: 0x001D7 + "\x00\x03\xf0\x00` \x01\xd8" + // 0x000FC 0x00301: 0x001D8 + "\x00\x03p\x00a\x80\x01\xd9" + // 0x000DC 0x0030C: 0x001D9 + "\x00\x03\xf0\x00a\x80\x01\xda" + // 0x000FC 0x0030C: 0x001DA + "\x00\x03p\x00`\x00\x01\xdb" + // 0x000DC 0x00300: 0x001DB + "\x00\x03\xf0\x00`\x00\x01\xdc" + // 0x000FC 0x00300: 0x001DC + "\x00\x03\x10\x00`\x80\x01\xde" + // 0x000C4 0x00304: 0x001DE + "\x00\x03\x90\x00`\x80\x01\xdf" + // 0x000E4 0x00304: 0x001DF + "\x00\b\x98\x00`\x80\x01\xe0" + // 0x00226 0x00304: 0x001E0 + "\x00\b\x9c\x00`\x80\x01\xe1" + // 0x00227 0x00304: 0x001E1 + "\x00\x03\x18\x00`\x80\x01\xe2" + // 0x000C6 0x00304: 0x001E2 + "\x00\x03\x98\x00`\x80\x01\xe3" + // 0x000E6 0x00304: 0x001E3 + "\x00\x01\x1c\x00a\x80\x01\xe6" + // 0x00047 0x0030C: 0x001E6 + "\x00\x01\x9c\x00a\x80\x01\xe7" + // 0x00067 0x0030C: 0x001E7 + "\x00\x01,\x00a\x80\x01\xe8" + // 0x0004B 0x0030C: 0x001E8 + "\x00\x01\xac\x00a\x80\x01\xe9" + // 0x0006B 0x0030C: 0x001E9 + "\x00\x01<\x00e\x00\x01\xea" + // 0x0004F 0x00328: 0x001EA + "\x00\x01\xbc\x00e\x00\x01\xeb" + // 0x0006F 0x00328: 0x001EB + "\x00\a\xa8\x00`\x80\x01\xec" + // 0x001EA 0x00304: 0x001EC + "\x00\a\xac\x00`\x80\x01\xed" + // 0x001EB 0x00304: 0x001ED + "\x00\x06\xdc\x00a\x80\x01\xee" + // 0x001B7 0x0030C: 0x001EE + "\x00\nH\x00a\x80\x01\xef" + // 0x00292 0x0030C: 0x001EF + "\x00\x01\xa8\x00a\x80\x01\xf0" + // 0x0006A 0x0030C: 0x001F0 + "\x00\x01\x1c\x00` \x01\xf4" + // 0x00047 0x00301: 0x001F4 + "\x00\x01\x9c\x00` \x01\xf5" + // 0x00067 0x00301: 0x001F5 + "\x00\x018\x00`\x00\x01\xf8" + // 0x0004E 0x00300: 0x001F8 + "\x00\x01\xb8\x00`\x00\x01\xf9" + // 0x0006E 0x00300: 0x001F9 + "\x00\x03\x14\x00` \x01\xfa" + // 0x000C5 0x00301: 0x001FA + "\x00\x03\x94\x00` \x01\xfb" + // 0x000E5 0x00301: 0x001FB + "\x00\x03\x18\x00` \x01\xfc" + // 0x000C6 0x00301: 0x001FC + "\x00\x03\x98\x00` \x01\xfd" + // 0x000E6 0x00301: 0x001FD + "\x00\x03`\x00` \x01\xfe" + // 0x000D8 0x00301: 0x001FE + "\x00\x03\xe0\x00` \x01\xff" + // 0x000F8 0x00301: 0x001FF + "\x00\x01\x04\x00a\xe0\x02\x00" + // 0x00041 0x0030F: 0x00200 + "\x00\x01\x84\x00a\xe0\x02\x01" + // 0x00061 0x0030F: 0x00201 + "\x00\x01\x04\x00b \x02\x02" + // 0x00041 0x00311: 0x00202 + "\x00\x01\x84\x00b \x02\x03" + // 0x00061 0x00311: 0x00203 + "\x00\x01\x14\x00a\xe0\x02\x04" + // 0x00045 0x0030F: 0x00204 + "\x00\x01\x94\x00a\xe0\x02\x05" + // 0x00065 0x0030F: 0x00205 + "\x00\x01\x14\x00b \x02\x06" + // 0x00045 0x00311: 0x00206 + "\x00\x01\x94\x00b \x02\a" + // 0x00065 0x00311: 0x00207 + "\x00\x01$\x00a\xe0\x02\b" + // 0x00049 0x0030F: 0x00208 + "\x00\x01\xa4\x00a\xe0\x02\t" + // 0x00069 0x0030F: 0x00209 + "\x00\x01$\x00b \x02\n" + // 0x00049 0x00311: 0x0020A + "\x00\x01\xa4\x00b \x02\v" + // 0x00069 0x00311: 0x0020B + "\x00\x01<\x00a\xe0\x02\f" + // 0x0004F 0x0030F: 0x0020C + "\x00\x01\xbc\x00a\xe0\x02\r" + // 0x0006F 0x0030F: 0x0020D + "\x00\x01<\x00b \x02\x0e" + // 0x0004F 0x00311: 0x0020E + "\x00\x01\xbc\x00b \x02\x0f" + // 0x0006F 0x00311: 0x0020F + "\x00\x01H\x00a\xe0\x02\x10" + // 0x00052 0x0030F: 0x00210 + "\x00\x01\xc8\x00a\xe0\x02\x11" + // 0x00072 0x0030F: 0x00211 + "\x00\x01H\x00b \x02\x12" + // 0x00052 0x00311: 0x00212 + "\x00\x01\xc8\x00b \x02\x13" + // 0x00072 0x00311: 0x00213 + "\x00\x01T\x00a\xe0\x02\x14" + // 0x00055 0x0030F: 0x00214 + "\x00\x01\xd4\x00a\xe0\x02\x15" + // 0x00075 0x0030F: 0x00215 + "\x00\x01T\x00b \x02\x16" + // 0x00055 0x00311: 0x00216 + "\x00\x01\xd4\x00b \x02\x17" + // 0x00075 0x00311: 0x00217 + "\x00\x01L\x00d\xc0\x02\x18" + // 0x00053 0x00326: 0x00218 + "\x00\x01\xcc\x00d\xc0\x02\x19" + // 0x00073 0x00326: 0x00219 + "\x00\x01P\x00d\xc0\x02\x1a" + // 0x00054 0x00326: 0x0021A + "\x00\x01\xd0\x00d\xc0\x02\x1b" + // 0x00074 0x00326: 0x0021B + "\x00\x01 \x00a\x80\x02\x1e" + // 0x00048 0x0030C: 0x0021E + "\x00\x01\xa0\x00a\x80\x02\x1f" + // 0x00068 0x0030C: 0x0021F + "\x00\x01\x04\x00`\xe0\x02&" + // 0x00041 0x00307: 0x00226 + "\x00\x01\x84\x00`\xe0\x02'" + // 0x00061 0x00307: 0x00227 + "\x00\x01\x14\x00d\xe0\x02(" + // 0x00045 0x00327: 0x00228 + "\x00\x01\x94\x00d\xe0\x02)" + // 0x00065 0x00327: 0x00229 + "\x00\x03X\x00`\x80\x02*" + // 0x000D6 0x00304: 0x0022A + "\x00\x03\xd8\x00`\x80\x02+" + // 0x000F6 0x00304: 0x0022B + "\x00\x03T\x00`\x80\x02," + // 0x000D5 0x00304: 0x0022C + "\x00\x03\xd4\x00`\x80\x02-" + // 0x000F5 0x00304: 0x0022D + "\x00\x01<\x00`\xe0\x02." + // 0x0004F 0x00307: 0x0022E + "\x00\x01\xbc\x00`\xe0\x02/" + // 0x0006F 0x00307: 0x0022F + "\x00\b\xb8\x00`\x80\x020" + // 0x0022E 0x00304: 0x00230 + "\x00\b\xbc\x00`\x80\x021" + // 0x0022F 0x00304: 0x00231 + "\x00\x01d\x00`\x80\x022" + // 0x00059 0x00304: 0x00232 + "\x00\x01\xe4\x00`\x80\x023" + // 0x00079 0x00304: 0x00233 + "\x00\x02\xa0\x00` \x03\x85" + // 0x000A8 0x00301: 0x00385 + "\x00\x0eD\x00` \x03\x86" + // 0x00391 0x00301: 0x00386 + "\x00\x0eT\x00` \x03\x88" + // 0x00395 0x00301: 0x00388 + "\x00\x0e\\\x00` \x03\x89" + // 0x00397 0x00301: 0x00389 + "\x00\x0ed\x00` \x03\x8a" + // 0x00399 0x00301: 0x0038A + "\x00\x0e|\x00` \x03\x8c" + // 0x0039F 0x00301: 0x0038C + "\x00\x0e\x94\x00` \x03\x8e" + // 0x003A5 0x00301: 0x0038E + "\x00\x0e\xa4\x00` \x03\x8f" + // 0x003A9 0x00301: 0x0038F + "\x00\x0f(\x00` \x03\x90" + // 0x003CA 0x00301: 0x00390 + "\x00\x0ed\x00a\x00\x03\xaa" + // 0x00399 0x00308: 0x003AA + "\x00\x0e\x94\x00a\x00\x03\xab" + // 0x003A5 0x00308: 0x003AB + "\x00\x0e\xc4\x00` \x03\xac" + // 0x003B1 0x00301: 0x003AC + "\x00\x0e\xd4\x00` \x03\xad" + // 0x003B5 0x00301: 0x003AD + "\x00\x0e\xdc\x00` \x03\xae" + // 0x003B7 0x00301: 0x003AE + "\x00\x0e\xe4\x00` \x03\xaf" + // 0x003B9 0x00301: 0x003AF + "\x00\x0f,\x00` \x03\xb0" + // 0x003CB 0x00301: 0x003B0 + "\x00\x0e\xe4\x00a\x00\x03\xca" + // 0x003B9 0x00308: 0x003CA + "\x00\x0f\x14\x00a\x00\x03\xcb" + // 0x003C5 0x00308: 0x003CB + "\x00\x0e\xfc\x00` \x03\xcc" + // 0x003BF 0x00301: 0x003CC + "\x00\x0f\x14\x00` \x03\xcd" + // 0x003C5 0x00301: 0x003CD + "\x00\x0f$\x00` \x03\xce" + // 0x003C9 0x00301: 0x003CE + "\x00\x0fH\x00` \x03\xd3" + // 0x003D2 0x00301: 0x003D3 + "\x00\x0fH\x00a\x00\x03\xd4" + // 0x003D2 0x00308: 0x003D4 + "\x00\x10T\x00`\x00\x04\x00" + // 0x00415 0x00300: 0x00400 + "\x00\x10T\x00a\x00\x04\x01" + // 0x00415 0x00308: 0x00401 + "\x00\x10L\x00` \x04\x03" + // 0x00413 0x00301: 0x00403 + "\x00\x10\x18\x00a\x00\x04\a" + // 0x00406 0x00308: 0x00407 + "\x00\x10h\x00` \x04\f" + // 0x0041A 0x00301: 0x0040C + "\x00\x10`\x00`\x00\x04\r" + // 0x00418 0x00300: 0x0040D + "\x00\x10\x8c\x00`\xc0\x04\x0e" + // 0x00423 0x00306: 0x0040E + "\x00\x10`\x00`\xc0\x04\x19" + // 0x00418 0x00306: 0x00419 + "\x00\x10\xe0\x00`\xc0\x049" + // 0x00438 0x00306: 0x00439 + "\x00\x10\xd4\x00`\x00\x04P" + // 0x00435 0x00300: 0x00450 + "\x00\x10\xd4\x00a\x00\x04Q" + // 0x00435 0x00308: 0x00451 + "\x00\x10\xcc\x00` \x04S" + // 0x00433 0x00301: 0x00453 + "\x00\x11X\x00a\x00\x04W" + // 0x00456 0x00308: 0x00457 + "\x00\x10\xe8\x00` \x04\\" + // 0x0043A 0x00301: 0x0045C + "\x00\x10\xe0\x00`\x00\x04]" + // 0x00438 0x00300: 0x0045D + "\x00\x11\f\x00`\xc0\x04^" + // 0x00443 0x00306: 0x0045E + "\x00\x11\xd0\x00a\xe0\x04v" + // 0x00474 0x0030F: 0x00476 + "\x00\x11\xd4\x00a\xe0\x04w" + // 0x00475 0x0030F: 0x00477 + "\x00\x10X\x00`\xc0\x04\xc1" + // 0x00416 0x00306: 0x004C1 + "\x00\x10\xd8\x00`\xc0\x04\xc2" + // 0x00436 0x00306: 0x004C2 + "\x00\x10@\x00`\xc0\x04\xd0" + // 0x00410 0x00306: 0x004D0 + "\x00\x10\xc0\x00`\xc0\x04\xd1" + // 0x00430 0x00306: 0x004D1 + "\x00\x10@\x00a\x00\x04\xd2" + // 0x00410 0x00308: 0x004D2 + "\x00\x10\xc0\x00a\x00\x04\xd3" + // 0x00430 0x00308: 0x004D3 + "\x00\x10T\x00`\xc0\x04\xd6" + // 0x00415 0x00306: 0x004D6 + "\x00\x10\xd4\x00`\xc0\x04\xd7" + // 0x00435 0x00306: 0x004D7 + "\x00\x13`\x00a\x00\x04\xda" + // 0x004D8 0x00308: 0x004DA + "\x00\x13d\x00a\x00\x04\xdb" + // 0x004D9 0x00308: 0x004DB + "\x00\x10X\x00a\x00\x04\xdc" + // 0x00416 0x00308: 0x004DC + "\x00\x10\xd8\x00a\x00\x04\xdd" + // 0x00436 0x00308: 0x004DD + "\x00\x10\\\x00a\x00\x04\xde" + // 0x00417 0x00308: 0x004DE + "\x00\x10\xdc\x00a\x00\x04\xdf" + // 0x00437 0x00308: 0x004DF + "\x00\x10`\x00`\x80\x04\xe2" + // 0x00418 0x00304: 0x004E2 + "\x00\x10\xe0\x00`\x80\x04\xe3" + // 0x00438 0x00304: 0x004E3 + "\x00\x10`\x00a\x00\x04\xe4" + // 0x00418 0x00308: 0x004E4 + "\x00\x10\xe0\x00a\x00\x04\xe5" + // 0x00438 0x00308: 0x004E5 + "\x00\x10x\x00a\x00\x04\xe6" + // 0x0041E 0x00308: 0x004E6 + "\x00\x10\xf8\x00a\x00\x04\xe7" + // 0x0043E 0x00308: 0x004E7 + "\x00\x13\xa0\x00a\x00\x04\xea" + // 0x004E8 0x00308: 0x004EA + "\x00\x13\xa4\x00a\x00\x04\xeb" + // 0x004E9 0x00308: 0x004EB + "\x00\x10\xb4\x00a\x00\x04\xec" + // 0x0042D 0x00308: 0x004EC + "\x00\x114\x00a\x00\x04\xed" + // 0x0044D 0x00308: 0x004ED + "\x00\x10\x8c\x00`\x80\x04\xee" + // 0x00423 0x00304: 0x004EE + "\x00\x11\f\x00`\x80\x04\xef" + // 0x00443 0x00304: 0x004EF + "\x00\x10\x8c\x00a\x00\x04\xf0" + // 0x00423 0x00308: 0x004F0 + "\x00\x11\f\x00a\x00\x04\xf1" + // 0x00443 0x00308: 0x004F1 + "\x00\x10\x8c\x00a`\x04\xf2" + // 0x00423 0x0030B: 0x004F2 + "\x00\x11\f\x00a`\x04\xf3" + // 0x00443 0x0030B: 0x004F3 + "\x00\x10\x9c\x00a\x00\x04\xf4" + // 0x00427 0x00308: 0x004F4 + "\x00\x11\x1c\x00a\x00\x04\xf5" + // 0x00447 0x00308: 0x004F5 + "\x00\x10\xac\x00a\x00\x04\xf8" + // 0x0042B 0x00308: 0x004F8 + "\x00\x11,\x00a\x00\x04\xf9" + // 0x0044B 0x00308: 0x004F9 + "\x00\x18\x9c\x00\xca`\x06\"" + // 0x00627 0x00653: 0x00622 + "\x00\x18\x9c\x00ʀ\x06#" + // 0x00627 0x00654: 0x00623 + "\x00\x19 \x00ʀ\x06$" + // 0x00648 0x00654: 0x00624 + "\x00\x18\x9c\x00ʠ\x06%" + // 0x00627 0x00655: 0x00625 + "\x00\x19(\x00ʀ\x06&" + // 0x0064A 0x00654: 0x00626 + "\x00\x1bT\x00ʀ\x06\xc0" + // 0x006D5 0x00654: 0x006C0 + "\x00\x1b\x04\x00ʀ\x06\xc2" + // 0x006C1 0x00654: 0x006C2 + "\x00\x1bH\x00ʀ\x06\xd3" + // 0x006D2 0x00654: 0x006D3 + "\x00$\xa0\x01'\x80\t)" + // 0x00928 0x0093C: 0x00929 + "\x00$\xc0\x01'\x80\t1" + // 0x00930 0x0093C: 0x00931 + "\x00$\xcc\x01'\x80\t4" + // 0x00933 0x0093C: 0x00934 + "\x00'\x1c\x017\xc0\t\xcb" + // 0x009C7 0x009BE: 0x009CB + "\x00'\x1c\x01:\xe0\t\xcc" + // 0x009C7 0x009D7: 0x009CC + "\x00-\x1c\x01j\xc0\vH" + // 0x00B47 0x00B56: 0x00B48 + "\x00-\x1c\x01g\xc0\vK" + // 0x00B47 0x00B3E: 0x00B4B + "\x00-\x1c\x01j\xe0\vL" + // 0x00B47 0x00B57: 0x00B4C + "\x00.H\x01z\xe0\v\x94" + // 0x00B92 0x00BD7: 0x00B94 + "\x00/\x18\x01w\xc0\v\xca" + // 0x00BC6 0x00BBE: 0x00BCA + "\x00/\x1c\x01w\xc0\v\xcb" + // 0x00BC7 0x00BBE: 0x00BCB + "\x00/\x18\x01z\xe0\v\xcc" + // 0x00BC6 0x00BD7: 0x00BCC + "\x001\x18\x01\x8a\xc0\fH" + // 0x00C46 0x00C56: 0x00C48 + "\x002\xfc\x01\x9a\xa0\f\xc0" + // 0x00CBF 0x00CD5: 0x00CC0 + "\x003\x18\x01\x9a\xa0\f\xc7" + // 0x00CC6 0x00CD5: 0x00CC7 + "\x003\x18\x01\x9a\xc0\f\xc8" + // 0x00CC6 0x00CD6: 0x00CC8 + "\x003\x18\x01\x98@\f\xca" + // 0x00CC6 0x00CC2: 0x00CCA + "\x003(\x01\x9a\xa0\f\xcb" + // 0x00CCA 0x00CD5: 0x00CCB + "\x005\x18\x01\xa7\xc0\rJ" + // 0x00D46 0x00D3E: 0x00D4A + "\x005\x1c\x01\xa7\xc0\rK" + // 0x00D47 0x00D3E: 0x00D4B + "\x005\x18\x01\xaa\xe0\rL" + // 0x00D46 0x00D57: 0x00D4C + "\x007d\x01\xb9@\r\xda" + // 0x00DD9 0x00DCA: 0x00DDA + "\x007d\x01\xb9\xe0\r\xdc" + // 0x00DD9 0x00DCF: 0x00DDC + "\x007p\x01\xb9@\r\xdd" + // 0x00DDC 0x00DCA: 0x00DDD + "\x007d\x01\xbb\xe0\r\xde" + // 0x00DD9 0x00DDF: 0x00DDE + "\x00@\x94\x02\x05\xc0\x10&" + // 0x01025 0x0102E: 0x01026 + "\x00l\x14\x03f\xa0\x1b\x06" + // 0x01B05 0x01B35: 0x01B06 + "\x00l\x1c\x03f\xa0\x1b\b" + // 0x01B07 0x01B35: 0x01B08 + "\x00l$\x03f\xa0\x1b\n" + // 0x01B09 0x01B35: 0x01B0A + "\x00l,\x03f\xa0\x1b\f" + // 0x01B0B 0x01B35: 0x01B0C + "\x00l4\x03f\xa0\x1b\x0e" + // 0x01B0D 0x01B35: 0x01B0E + "\x00lD\x03f\xa0\x1b\x12" + // 0x01B11 0x01B35: 0x01B12 + "\x00l\xe8\x03f\xa0\x1b;" + // 0x01B3A 0x01B35: 0x01B3B + "\x00l\xf0\x03f\xa0\x1b=" + // 0x01B3C 0x01B35: 0x01B3D + "\x00l\xf8\x03f\xa0\x1b@" + // 0x01B3E 0x01B35: 0x01B40 + "\x00l\xfc\x03f\xa0\x1bA" + // 0x01B3F 0x01B35: 0x01B41 + "\x00m\b\x03f\xa0\x1bC" + // 0x01B42 0x01B35: 0x01B43 + "\x00\x01\x04\x00d\xa0\x1e\x00" + // 0x00041 0x00325: 0x01E00 + "\x00\x01\x84\x00d\xa0\x1e\x01" + // 0x00061 0x00325: 0x01E01 + "\x00\x01\b\x00`\xe0\x1e\x02" + // 0x00042 0x00307: 0x01E02 + "\x00\x01\x88\x00`\xe0\x1e\x03" + // 0x00062 0x00307: 0x01E03 + "\x00\x01\b\x00d`\x1e\x04" + // 0x00042 0x00323: 0x01E04 + "\x00\x01\x88\x00d`\x1e\x05" + // 0x00062 0x00323: 0x01E05 + "\x00\x01\b\x00f \x1e\x06" + // 0x00042 0x00331: 0x01E06 + "\x00\x01\x88\x00f \x1e\a" + // 0x00062 0x00331: 0x01E07 + "\x00\x03\x1c\x00` \x1e\b" + // 0x000C7 0x00301: 0x01E08 + "\x00\x03\x9c\x00` \x1e\t" + // 0x000E7 0x00301: 0x01E09 + "\x00\x01\x10\x00`\xe0\x1e\n" + // 0x00044 0x00307: 0x01E0A + "\x00\x01\x90\x00`\xe0\x1e\v" + // 0x00064 0x00307: 0x01E0B + "\x00\x01\x10\x00d`\x1e\f" + // 0x00044 0x00323: 0x01E0C + "\x00\x01\x90\x00d`\x1e\r" + // 0x00064 0x00323: 0x01E0D + "\x00\x01\x10\x00f \x1e\x0e" + // 0x00044 0x00331: 0x01E0E + "\x00\x01\x90\x00f \x1e\x0f" + // 0x00064 0x00331: 0x01E0F + "\x00\x01\x10\x00d\xe0\x1e\x10" + // 0x00044 0x00327: 0x01E10 + "\x00\x01\x90\x00d\xe0\x1e\x11" + // 0x00064 0x00327: 0x01E11 + "\x00\x01\x10\x00e\xa0\x1e\x12" + // 0x00044 0x0032D: 0x01E12 + "\x00\x01\x90\x00e\xa0\x1e\x13" + // 0x00064 0x0032D: 0x01E13 + "\x00\x04H\x00`\x00\x1e\x14" + // 0x00112 0x00300: 0x01E14 + "\x00\x04L\x00`\x00\x1e\x15" + // 0x00113 0x00300: 0x01E15 + "\x00\x04H\x00` \x1e\x16" + // 0x00112 0x00301: 0x01E16 + "\x00\x04L\x00` \x1e\x17" + // 0x00113 0x00301: 0x01E17 + "\x00\x01\x14\x00e\xa0\x1e\x18" + // 0x00045 0x0032D: 0x01E18 + "\x00\x01\x94\x00e\xa0\x1e\x19" + // 0x00065 0x0032D: 0x01E19 + "\x00\x01\x14\x00f\x00\x1e\x1a" + // 0x00045 0x00330: 0x01E1A + "\x00\x01\x94\x00f\x00\x1e\x1b" + // 0x00065 0x00330: 0x01E1B + "\x00\b\xa0\x00`\xc0\x1e\x1c" + // 0x00228 0x00306: 0x01E1C + "\x00\b\xa4\x00`\xc0\x1e\x1d" + // 0x00229 0x00306: 0x01E1D + "\x00\x01\x18\x00`\xe0\x1e\x1e" + // 0x00046 0x00307: 0x01E1E + "\x00\x01\x98\x00`\xe0\x1e\x1f" + // 0x00066 0x00307: 0x01E1F + "\x00\x01\x1c\x00`\x80\x1e " + // 0x00047 0x00304: 0x01E20 + "\x00\x01\x9c\x00`\x80\x1e!" + // 0x00067 0x00304: 0x01E21 + "\x00\x01 \x00`\xe0\x1e\"" + // 0x00048 0x00307: 0x01E22 + "\x00\x01\xa0\x00`\xe0\x1e#" + // 0x00068 0x00307: 0x01E23 + "\x00\x01 \x00d`\x1e$" + // 0x00048 0x00323: 0x01E24 + "\x00\x01\xa0\x00d`\x1e%" + // 0x00068 0x00323: 0x01E25 + "\x00\x01 \x00a\x00\x1e&" + // 0x00048 0x00308: 0x01E26 + "\x00\x01\xa0\x00a\x00\x1e'" + // 0x00068 0x00308: 0x01E27 + "\x00\x01 \x00d\xe0\x1e(" + // 0x00048 0x00327: 0x01E28 + "\x00\x01\xa0\x00d\xe0\x1e)" + // 0x00068 0x00327: 0x01E29 + "\x00\x01 \x00e\xc0\x1e*" + // 0x00048 0x0032E: 0x01E2A + "\x00\x01\xa0\x00e\xc0\x1e+" + // 0x00068 0x0032E: 0x01E2B + "\x00\x01$\x00f\x00\x1e," + // 0x00049 0x00330: 0x01E2C + "\x00\x01\xa4\x00f\x00\x1e-" + // 0x00069 0x00330: 0x01E2D + "\x00\x03<\x00` \x1e." + // 0x000CF 0x00301: 0x01E2E + "\x00\x03\xbc\x00` \x1e/" + // 0x000EF 0x00301: 0x01E2F + "\x00\x01,\x00` \x1e0" + // 0x0004B 0x00301: 0x01E30 + "\x00\x01\xac\x00` \x1e1" + // 0x0006B 0x00301: 0x01E31 + "\x00\x01,\x00d`\x1e2" + // 0x0004B 0x00323: 0x01E32 + "\x00\x01\xac\x00d`\x1e3" + // 0x0006B 0x00323: 0x01E33 + "\x00\x01,\x00f \x1e4" + // 0x0004B 0x00331: 0x01E34 + "\x00\x01\xac\x00f \x1e5" + // 0x0006B 0x00331: 0x01E35 + "\x00\x010\x00d`\x1e6" + // 0x0004C 0x00323: 0x01E36 + "\x00\x01\xb0\x00d`\x1e7" + // 0x0006C 0x00323: 0x01E37 + "\x00x\xd8\x00`\x80\x1e8" + // 0x01E36 0x00304: 0x01E38 + "\x00x\xdc\x00`\x80\x1e9" + // 0x01E37 0x00304: 0x01E39 + "\x00\x010\x00f \x1e:" + // 0x0004C 0x00331: 0x01E3A + "\x00\x01\xb0\x00f \x1e;" + // 0x0006C 0x00331: 0x01E3B + "\x00\x010\x00e\xa0\x1e<" + // 0x0004C 0x0032D: 0x01E3C + "\x00\x01\xb0\x00e\xa0\x1e=" + // 0x0006C 0x0032D: 0x01E3D + "\x00\x014\x00` \x1e>" + // 0x0004D 0x00301: 0x01E3E + "\x00\x01\xb4\x00` \x1e?" + // 0x0006D 0x00301: 0x01E3F + "\x00\x014\x00`\xe0\x1e@" + // 0x0004D 0x00307: 0x01E40 + "\x00\x01\xb4\x00`\xe0\x1eA" + // 0x0006D 0x00307: 0x01E41 + "\x00\x014\x00d`\x1eB" + // 0x0004D 0x00323: 0x01E42 + "\x00\x01\xb4\x00d`\x1eC" + // 0x0006D 0x00323: 0x01E43 + "\x00\x018\x00`\xe0\x1eD" + // 0x0004E 0x00307: 0x01E44 + "\x00\x01\xb8\x00`\xe0\x1eE" + // 0x0006E 0x00307: 0x01E45 + "\x00\x018\x00d`\x1eF" + // 0x0004E 0x00323: 0x01E46 + "\x00\x01\xb8\x00d`\x1eG" + // 0x0006E 0x00323: 0x01E47 + "\x00\x018\x00f \x1eH" + // 0x0004E 0x00331: 0x01E48 + "\x00\x01\xb8\x00f \x1eI" + // 0x0006E 0x00331: 0x01E49 + "\x00\x018\x00e\xa0\x1eJ" + // 0x0004E 0x0032D: 0x01E4A + "\x00\x01\xb8\x00e\xa0\x1eK" + // 0x0006E 0x0032D: 0x01E4B + "\x00\x03T\x00` \x1eL" + // 0x000D5 0x00301: 0x01E4C + "\x00\x03\xd4\x00` \x1eM" + // 0x000F5 0x00301: 0x01E4D + "\x00\x03T\x00a\x00\x1eN" + // 0x000D5 0x00308: 0x01E4E + "\x00\x03\xd4\x00a\x00\x1eO" + // 0x000F5 0x00308: 0x01E4F + "\x00\x050\x00`\x00\x1eP" + // 0x0014C 0x00300: 0x01E50 + "\x00\x054\x00`\x00\x1eQ" + // 0x0014D 0x00300: 0x01E51 + "\x00\x050\x00` \x1eR" + // 0x0014C 0x00301: 0x01E52 + "\x00\x054\x00` \x1eS" + // 0x0014D 0x00301: 0x01E53 + "\x00\x01@\x00` \x1eT" + // 0x00050 0x00301: 0x01E54 + "\x00\x01\xc0\x00` \x1eU" + // 0x00070 0x00301: 0x01E55 + "\x00\x01@\x00`\xe0\x1eV" + // 0x00050 0x00307: 0x01E56 + "\x00\x01\xc0\x00`\xe0\x1eW" + // 0x00070 0x00307: 0x01E57 + "\x00\x01H\x00`\xe0\x1eX" + // 0x00052 0x00307: 0x01E58 + "\x00\x01\xc8\x00`\xe0\x1eY" + // 0x00072 0x00307: 0x01E59 + "\x00\x01H\x00d`\x1eZ" + // 0x00052 0x00323: 0x01E5A + "\x00\x01\xc8\x00d`\x1e[" + // 0x00072 0x00323: 0x01E5B + "\x00yh\x00`\x80\x1e\\" + // 0x01E5A 0x00304: 0x01E5C + "\x00yl\x00`\x80\x1e]" + // 0x01E5B 0x00304: 0x01E5D + "\x00\x01H\x00f \x1e^" + // 0x00052 0x00331: 0x01E5E + "\x00\x01\xc8\x00f \x1e_" + // 0x00072 0x00331: 0x01E5F + "\x00\x01L\x00`\xe0\x1e`" + // 0x00053 0x00307: 0x01E60 + "\x00\x01\xcc\x00`\xe0\x1ea" + // 0x00073 0x00307: 0x01E61 + "\x00\x01L\x00d`\x1eb" + // 0x00053 0x00323: 0x01E62 + "\x00\x01\xcc\x00d`\x1ec" + // 0x00073 0x00323: 0x01E63 + "\x00\x05h\x00`\xe0\x1ed" + // 0x0015A 0x00307: 0x01E64 + "\x00\x05l\x00`\xe0\x1ee" + // 0x0015B 0x00307: 0x01E65 + "\x00\x05\x80\x00`\xe0\x1ef" + // 0x00160 0x00307: 0x01E66 + "\x00\x05\x84\x00`\xe0\x1eg" + // 0x00161 0x00307: 0x01E67 + "\x00y\x88\x00`\xe0\x1eh" + // 0x01E62 0x00307: 0x01E68 + "\x00y\x8c\x00`\xe0\x1ei" + // 0x01E63 0x00307: 0x01E69 + "\x00\x01P\x00`\xe0\x1ej" + // 0x00054 0x00307: 0x01E6A + "\x00\x01\xd0\x00`\xe0\x1ek" + // 0x00074 0x00307: 0x01E6B + "\x00\x01P\x00d`\x1el" + // 0x00054 0x00323: 0x01E6C + "\x00\x01\xd0\x00d`\x1em" + // 0x00074 0x00323: 0x01E6D + "\x00\x01P\x00f \x1en" + // 0x00054 0x00331: 0x01E6E + "\x00\x01\xd0\x00f \x1eo" + // 0x00074 0x00331: 0x01E6F + "\x00\x01P\x00e\xa0\x1ep" + // 0x00054 0x0032D: 0x01E70 + "\x00\x01\xd0\x00e\xa0\x1eq" + // 0x00074 0x0032D: 0x01E71 + "\x00\x01T\x00d\x80\x1er" + // 0x00055 0x00324: 0x01E72 + "\x00\x01\xd4\x00d\x80\x1es" + // 0x00075 0x00324: 0x01E73 + "\x00\x01T\x00f\x00\x1et" + // 0x00055 0x00330: 0x01E74 + "\x00\x01\xd4\x00f\x00\x1eu" + // 0x00075 0x00330: 0x01E75 + "\x00\x01T\x00e\xa0\x1ev" + // 0x00055 0x0032D: 0x01E76 + "\x00\x01\xd4\x00e\xa0\x1ew" + // 0x00075 0x0032D: 0x01E77 + "\x00\x05\xa0\x00` \x1ex" + // 0x00168 0x00301: 0x01E78 + "\x00\x05\xa4\x00` \x1ey" + // 0x00169 0x00301: 0x01E79 + "\x00\x05\xa8\x00a\x00\x1ez" + // 0x0016A 0x00308: 0x01E7A + "\x00\x05\xac\x00a\x00\x1e{" + // 0x0016B 0x00308: 0x01E7B + "\x00\x01X\x00``\x1e|" + // 0x00056 0x00303: 0x01E7C + "\x00\x01\xd8\x00``\x1e}" + // 0x00076 0x00303: 0x01E7D + "\x00\x01X\x00d`\x1e~" + // 0x00056 0x00323: 0x01E7E + "\x00\x01\xd8\x00d`\x1e\x7f" + // 0x00076 0x00323: 0x01E7F + "\x00\x01\\\x00`\x00\x1e\x80" + // 0x00057 0x00300: 0x01E80 + "\x00\x01\xdc\x00`\x00\x1e\x81" + // 0x00077 0x00300: 0x01E81 + "\x00\x01\\\x00` \x1e\x82" + // 0x00057 0x00301: 0x01E82 + "\x00\x01\xdc\x00` \x1e\x83" + // 0x00077 0x00301: 0x01E83 + "\x00\x01\\\x00a\x00\x1e\x84" + // 0x00057 0x00308: 0x01E84 + "\x00\x01\xdc\x00a\x00\x1e\x85" + // 0x00077 0x00308: 0x01E85 + "\x00\x01\\\x00`\xe0\x1e\x86" + // 0x00057 0x00307: 0x01E86 + "\x00\x01\xdc\x00`\xe0\x1e\x87" + // 0x00077 0x00307: 0x01E87 + "\x00\x01\\\x00d`\x1e\x88" + // 0x00057 0x00323: 0x01E88 + "\x00\x01\xdc\x00d`\x1e\x89" + // 0x00077 0x00323: 0x01E89 + "\x00\x01`\x00`\xe0\x1e\x8a" + // 0x00058 0x00307: 0x01E8A + "\x00\x01\xe0\x00`\xe0\x1e\x8b" + // 0x00078 0x00307: 0x01E8B + "\x00\x01`\x00a\x00\x1e\x8c" + // 0x00058 0x00308: 0x01E8C + "\x00\x01\xe0\x00a\x00\x1e\x8d" + // 0x00078 0x00308: 0x01E8D + "\x00\x01d\x00`\xe0\x1e\x8e" + // 0x00059 0x00307: 0x01E8E + "\x00\x01\xe4\x00`\xe0\x1e\x8f" + // 0x00079 0x00307: 0x01E8F + "\x00\x01h\x00`@\x1e\x90" + // 0x0005A 0x00302: 0x01E90 + "\x00\x01\xe8\x00`@\x1e\x91" + // 0x0007A 0x00302: 0x01E91 + "\x00\x01h\x00d`\x1e\x92" + // 0x0005A 0x00323: 0x01E92 + "\x00\x01\xe8\x00d`\x1e\x93" + // 0x0007A 0x00323: 0x01E93 + "\x00\x01h\x00f \x1e\x94" + // 0x0005A 0x00331: 0x01E94 + "\x00\x01\xe8\x00f \x1e\x95" + // 0x0007A 0x00331: 0x01E95 + "\x00\x01\xa0\x00f \x1e\x96" + // 0x00068 0x00331: 0x01E96 + "\x00\x01\xd0\x00a\x00\x1e\x97" + // 0x00074 0x00308: 0x01E97 + "\x00\x01\xdc\x00a@\x1e\x98" + // 0x00077 0x0030A: 0x01E98 + "\x00\x01\xe4\x00a@\x1e\x99" + // 0x00079 0x0030A: 0x01E99 + "\x00\x05\xfc\x00`\xe0\x1e\x9b" + // 0x0017F 0x00307: 0x01E9B + "\x00\x01\x04\x00d`\x1e\xa0" + // 0x00041 0x00323: 0x01EA0 + "\x00\x01\x84\x00d`\x1e\xa1" + // 0x00061 0x00323: 0x01EA1 + "\x00\x01\x04\x00a \x1e\xa2" + // 0x00041 0x00309: 0x01EA2 + "\x00\x01\x84\x00a \x1e\xa3" + // 0x00061 0x00309: 0x01EA3 + "\x00\x03\b\x00` \x1e\xa4" + // 0x000C2 0x00301: 0x01EA4 + "\x00\x03\x88\x00` \x1e\xa5" + // 0x000E2 0x00301: 0x01EA5 + "\x00\x03\b\x00`\x00\x1e\xa6" + // 0x000C2 0x00300: 0x01EA6 + "\x00\x03\x88\x00`\x00\x1e\xa7" + // 0x000E2 0x00300: 0x01EA7 + "\x00\x03\b\x00a \x1e\xa8" + // 0x000C2 0x00309: 0x01EA8 + "\x00\x03\x88\x00a \x1e\xa9" + // 0x000E2 0x00309: 0x01EA9 + "\x00\x03\b\x00``\x1e\xaa" + // 0x000C2 0x00303: 0x01EAA + "\x00\x03\x88\x00``\x1e\xab" + // 0x000E2 0x00303: 0x01EAB + "\x00z\x80\x00`@\x1e\xac" + // 0x01EA0 0x00302: 0x01EAC + "\x00z\x84\x00`@\x1e\xad" + // 0x01EA1 0x00302: 0x01EAD + "\x00\x04\b\x00` \x1e\xae" + // 0x00102 0x00301: 0x01EAE + "\x00\x04\f\x00` \x1e\xaf" + // 0x00103 0x00301: 0x01EAF + "\x00\x04\b\x00`\x00\x1e\xb0" + // 0x00102 0x00300: 0x01EB0 + "\x00\x04\f\x00`\x00\x1e\xb1" + // 0x00103 0x00300: 0x01EB1 + "\x00\x04\b\x00a \x1e\xb2" + // 0x00102 0x00309: 0x01EB2 + "\x00\x04\f\x00a \x1e\xb3" + // 0x00103 0x00309: 0x01EB3 + "\x00\x04\b\x00``\x1e\xb4" + // 0x00102 0x00303: 0x01EB4 + "\x00\x04\f\x00``\x1e\xb5" + // 0x00103 0x00303: 0x01EB5 + "\x00z\x80\x00`\xc0\x1e\xb6" + // 0x01EA0 0x00306: 0x01EB6 + "\x00z\x84\x00`\xc0\x1e\xb7" + // 0x01EA1 0x00306: 0x01EB7 + "\x00\x01\x14\x00d`\x1e\xb8" + // 0x00045 0x00323: 0x01EB8 + "\x00\x01\x94\x00d`\x1e\xb9" + // 0x00065 0x00323: 0x01EB9 + "\x00\x01\x14\x00a \x1e\xba" + // 0x00045 0x00309: 0x01EBA + "\x00\x01\x94\x00a \x1e\xbb" + // 0x00065 0x00309: 0x01EBB + "\x00\x01\x14\x00``\x1e\xbc" + // 0x00045 0x00303: 0x01EBC + "\x00\x01\x94\x00``\x1e\xbd" + // 0x00065 0x00303: 0x01EBD + "\x00\x03(\x00` \x1e\xbe" + // 0x000CA 0x00301: 0x01EBE + "\x00\x03\xa8\x00` \x1e\xbf" + // 0x000EA 0x00301: 0x01EBF + "\x00\x03(\x00`\x00\x1e\xc0" + // 0x000CA 0x00300: 0x01EC0 + "\x00\x03\xa8\x00`\x00\x1e\xc1" + // 0x000EA 0x00300: 0x01EC1 + "\x00\x03(\x00a \x1e\xc2" + // 0x000CA 0x00309: 0x01EC2 + "\x00\x03\xa8\x00a \x1e\xc3" + // 0x000EA 0x00309: 0x01EC3 + "\x00\x03(\x00``\x1e\xc4" + // 0x000CA 0x00303: 0x01EC4 + "\x00\x03\xa8\x00``\x1e\xc5" + // 0x000EA 0x00303: 0x01EC5 + "\x00z\xe0\x00`@\x1e\xc6" + // 0x01EB8 0x00302: 0x01EC6 + "\x00z\xe4\x00`@\x1e\xc7" + // 0x01EB9 0x00302: 0x01EC7 + "\x00\x01$\x00a \x1e\xc8" + // 0x00049 0x00309: 0x01EC8 + "\x00\x01\xa4\x00a \x1e\xc9" + // 0x00069 0x00309: 0x01EC9 + "\x00\x01$\x00d`\x1e\xca" + // 0x00049 0x00323: 0x01ECA + "\x00\x01\xa4\x00d`\x1e\xcb" + // 0x00069 0x00323: 0x01ECB + "\x00\x01<\x00d`\x1e\xcc" + // 0x0004F 0x00323: 0x01ECC + "\x00\x01\xbc\x00d`\x1e\xcd" + // 0x0006F 0x00323: 0x01ECD + "\x00\x01<\x00a \x1e\xce" + // 0x0004F 0x00309: 0x01ECE + "\x00\x01\xbc\x00a \x1e\xcf" + // 0x0006F 0x00309: 0x01ECF + "\x00\x03P\x00` \x1e\xd0" + // 0x000D4 0x00301: 0x01ED0 + "\x00\x03\xd0\x00` \x1e\xd1" + // 0x000F4 0x00301: 0x01ED1 + "\x00\x03P\x00`\x00\x1e\xd2" + // 0x000D4 0x00300: 0x01ED2 + "\x00\x03\xd0\x00`\x00\x1e\xd3" + // 0x000F4 0x00300: 0x01ED3 + "\x00\x03P\x00a \x1e\xd4" + // 0x000D4 0x00309: 0x01ED4 + "\x00\x03\xd0\x00a \x1e\xd5" + // 0x000F4 0x00309: 0x01ED5 + "\x00\x03P\x00``\x1e\xd6" + // 0x000D4 0x00303: 0x01ED6 + "\x00\x03\xd0\x00``\x1e\xd7" + // 0x000F4 0x00303: 0x01ED7 + "\x00{0\x00`@\x1e\xd8" + // 0x01ECC 0x00302: 0x01ED8 + "\x00{4\x00`@\x1e\xd9" + // 0x01ECD 0x00302: 0x01ED9 + "\x00\x06\x80\x00` \x1e\xda" + // 0x001A0 0x00301: 0x01EDA + "\x00\x06\x84\x00` \x1e\xdb" + // 0x001A1 0x00301: 0x01EDB + "\x00\x06\x80\x00`\x00\x1e\xdc" + // 0x001A0 0x00300: 0x01EDC + "\x00\x06\x84\x00`\x00\x1e\xdd" + // 0x001A1 0x00300: 0x01EDD + "\x00\x06\x80\x00a \x1e\xde" + // 0x001A0 0x00309: 0x01EDE + "\x00\x06\x84\x00a \x1e\xdf" + // 0x001A1 0x00309: 0x01EDF + "\x00\x06\x80\x00``\x1e\xe0" + // 0x001A0 0x00303: 0x01EE0 + "\x00\x06\x84\x00``\x1e\xe1" + // 0x001A1 0x00303: 0x01EE1 + "\x00\x06\x80\x00d`\x1e\xe2" + // 0x001A0 0x00323: 0x01EE2 + "\x00\x06\x84\x00d`\x1e\xe3" + // 0x001A1 0x00323: 0x01EE3 + "\x00\x01T\x00d`\x1e\xe4" + // 0x00055 0x00323: 0x01EE4 + "\x00\x01\xd4\x00d`\x1e\xe5" + // 0x00075 0x00323: 0x01EE5 + "\x00\x01T\x00a \x1e\xe6" + // 0x00055 0x00309: 0x01EE6 + "\x00\x01\xd4\x00a \x1e\xe7" + // 0x00075 0x00309: 0x01EE7 + "\x00\x06\xbc\x00` \x1e\xe8" + // 0x001AF 0x00301: 0x01EE8 + "\x00\x06\xc0\x00` \x1e\xe9" + // 0x001B0 0x00301: 0x01EE9 + "\x00\x06\xbc\x00`\x00\x1e\xea" + // 0x001AF 0x00300: 0x01EEA + "\x00\x06\xc0\x00`\x00\x1e\xeb" + // 0x001B0 0x00300: 0x01EEB + "\x00\x06\xbc\x00a \x1e\xec" + // 0x001AF 0x00309: 0x01EEC + "\x00\x06\xc0\x00a \x1e\xed" + // 0x001B0 0x00309: 0x01EED + "\x00\x06\xbc\x00``\x1e\xee" + // 0x001AF 0x00303: 0x01EEE + "\x00\x06\xc0\x00``\x1e\xef" + // 0x001B0 0x00303: 0x01EEF + "\x00\x06\xbc\x00d`\x1e\xf0" + // 0x001AF 0x00323: 0x01EF0 + "\x00\x06\xc0\x00d`\x1e\xf1" + // 0x001B0 0x00323: 0x01EF1 + "\x00\x01d\x00`\x00\x1e\xf2" + // 0x00059 0x00300: 0x01EF2 + "\x00\x01\xe4\x00`\x00\x1e\xf3" + // 0x00079 0x00300: 0x01EF3 + "\x00\x01d\x00d`\x1e\xf4" + // 0x00059 0x00323: 0x01EF4 + "\x00\x01\xe4\x00d`\x1e\xf5" + // 0x00079 0x00323: 0x01EF5 + "\x00\x01d\x00a \x1e\xf6" + // 0x00059 0x00309: 0x01EF6 + "\x00\x01\xe4\x00a \x1e\xf7" + // 0x00079 0x00309: 0x01EF7 + "\x00\x01d\x00``\x1e\xf8" + // 0x00059 0x00303: 0x01EF8 + "\x00\x01\xe4\x00``\x1e\xf9" + // 0x00079 0x00303: 0x01EF9 + "\x00\x0e\xc4\x00b`\x1f\x00" + // 0x003B1 0x00313: 0x01F00 + "\x00\x0e\xc4\x00b\x80\x1f\x01" + // 0x003B1 0x00314: 0x01F01 + "\x00|\x00\x00`\x00\x1f\x02" + // 0x01F00 0x00300: 0x01F02 + "\x00|\x04\x00`\x00\x1f\x03" + // 0x01F01 0x00300: 0x01F03 + "\x00|\x00\x00` \x1f\x04" + // 0x01F00 0x00301: 0x01F04 + "\x00|\x04\x00` \x1f\x05" + // 0x01F01 0x00301: 0x01F05 + "\x00|\x00\x00h@\x1f\x06" + // 0x01F00 0x00342: 0x01F06 + "\x00|\x04\x00h@\x1f\a" + // 0x01F01 0x00342: 0x01F07 + "\x00\x0eD\x00b`\x1f\b" + // 0x00391 0x00313: 0x01F08 + "\x00\x0eD\x00b\x80\x1f\t" + // 0x00391 0x00314: 0x01F09 + "\x00| \x00`\x00\x1f\n" + // 0x01F08 0x00300: 0x01F0A + "\x00|$\x00`\x00\x1f\v" + // 0x01F09 0x00300: 0x01F0B + "\x00| \x00` \x1f\f" + // 0x01F08 0x00301: 0x01F0C + "\x00|$\x00` \x1f\r" + // 0x01F09 0x00301: 0x01F0D + "\x00| \x00h@\x1f\x0e" + // 0x01F08 0x00342: 0x01F0E + "\x00|$\x00h@\x1f\x0f" + // 0x01F09 0x00342: 0x01F0F + "\x00\x0e\xd4\x00b`\x1f\x10" + // 0x003B5 0x00313: 0x01F10 + "\x00\x0e\xd4\x00b\x80\x1f\x11" + // 0x003B5 0x00314: 0x01F11 + "\x00|@\x00`\x00\x1f\x12" + // 0x01F10 0x00300: 0x01F12 + "\x00|D\x00`\x00\x1f\x13" + // 0x01F11 0x00300: 0x01F13 + "\x00|@\x00` \x1f\x14" + // 0x01F10 0x00301: 0x01F14 + "\x00|D\x00` \x1f\x15" + // 0x01F11 0x00301: 0x01F15 + "\x00\x0eT\x00b`\x1f\x18" + // 0x00395 0x00313: 0x01F18 + "\x00\x0eT\x00b\x80\x1f\x19" + // 0x00395 0x00314: 0x01F19 + "\x00|`\x00`\x00\x1f\x1a" + // 0x01F18 0x00300: 0x01F1A + "\x00|d\x00`\x00\x1f\x1b" + // 0x01F19 0x00300: 0x01F1B + "\x00|`\x00` \x1f\x1c" + // 0x01F18 0x00301: 0x01F1C + "\x00|d\x00` \x1f\x1d" + // 0x01F19 0x00301: 0x01F1D + "\x00\x0e\xdc\x00b`\x1f " + // 0x003B7 0x00313: 0x01F20 + "\x00\x0e\xdc\x00b\x80\x1f!" + // 0x003B7 0x00314: 0x01F21 + "\x00|\x80\x00`\x00\x1f\"" + // 0x01F20 0x00300: 0x01F22 + "\x00|\x84\x00`\x00\x1f#" + // 0x01F21 0x00300: 0x01F23 + "\x00|\x80\x00` \x1f$" + // 0x01F20 0x00301: 0x01F24 + "\x00|\x84\x00` \x1f%" + // 0x01F21 0x00301: 0x01F25 + "\x00|\x80\x00h@\x1f&" + // 0x01F20 0x00342: 0x01F26 + "\x00|\x84\x00h@\x1f'" + // 0x01F21 0x00342: 0x01F27 + "\x00\x0e\\\x00b`\x1f(" + // 0x00397 0x00313: 0x01F28 + "\x00\x0e\\\x00b\x80\x1f)" + // 0x00397 0x00314: 0x01F29 + "\x00|\xa0\x00`\x00\x1f*" + // 0x01F28 0x00300: 0x01F2A + "\x00|\xa4\x00`\x00\x1f+" + // 0x01F29 0x00300: 0x01F2B + "\x00|\xa0\x00` \x1f," + // 0x01F28 0x00301: 0x01F2C + "\x00|\xa4\x00` \x1f-" + // 0x01F29 0x00301: 0x01F2D + "\x00|\xa0\x00h@\x1f." + // 0x01F28 0x00342: 0x01F2E + "\x00|\xa4\x00h@\x1f/" + // 0x01F29 0x00342: 0x01F2F + "\x00\x0e\xe4\x00b`\x1f0" + // 0x003B9 0x00313: 0x01F30 + "\x00\x0e\xe4\x00b\x80\x1f1" + // 0x003B9 0x00314: 0x01F31 + "\x00|\xc0\x00`\x00\x1f2" + // 0x01F30 0x00300: 0x01F32 + "\x00|\xc4\x00`\x00\x1f3" + // 0x01F31 0x00300: 0x01F33 + "\x00|\xc0\x00` \x1f4" + // 0x01F30 0x00301: 0x01F34 + "\x00|\xc4\x00` \x1f5" + // 0x01F31 0x00301: 0x01F35 + "\x00|\xc0\x00h@\x1f6" + // 0x01F30 0x00342: 0x01F36 + "\x00|\xc4\x00h@\x1f7" + // 0x01F31 0x00342: 0x01F37 + "\x00\x0ed\x00b`\x1f8" + // 0x00399 0x00313: 0x01F38 + "\x00\x0ed\x00b\x80\x1f9" + // 0x00399 0x00314: 0x01F39 + "\x00|\xe0\x00`\x00\x1f:" + // 0x01F38 0x00300: 0x01F3A + "\x00|\xe4\x00`\x00\x1f;" + // 0x01F39 0x00300: 0x01F3B + "\x00|\xe0\x00` \x1f<" + // 0x01F38 0x00301: 0x01F3C + "\x00|\xe4\x00` \x1f=" + // 0x01F39 0x00301: 0x01F3D + "\x00|\xe0\x00h@\x1f>" + // 0x01F38 0x00342: 0x01F3E + "\x00|\xe4\x00h@\x1f?" + // 0x01F39 0x00342: 0x01F3F + "\x00\x0e\xfc\x00b`\x1f@" + // 0x003BF 0x00313: 0x01F40 + "\x00\x0e\xfc\x00b\x80\x1fA" + // 0x003BF 0x00314: 0x01F41 + "\x00}\x00\x00`\x00\x1fB" + // 0x01F40 0x00300: 0x01F42 + "\x00}\x04\x00`\x00\x1fC" + // 0x01F41 0x00300: 0x01F43 + "\x00}\x00\x00` \x1fD" + // 0x01F40 0x00301: 0x01F44 + "\x00}\x04\x00` \x1fE" + // 0x01F41 0x00301: 0x01F45 + "\x00\x0e|\x00b`\x1fH" + // 0x0039F 0x00313: 0x01F48 + "\x00\x0e|\x00b\x80\x1fI" + // 0x0039F 0x00314: 0x01F49 + "\x00} \x00`\x00\x1fJ" + // 0x01F48 0x00300: 0x01F4A + "\x00}$\x00`\x00\x1fK" + // 0x01F49 0x00300: 0x01F4B + "\x00} \x00` \x1fL" + // 0x01F48 0x00301: 0x01F4C + "\x00}$\x00` \x1fM" + // 0x01F49 0x00301: 0x01F4D + "\x00\x0f\x14\x00b`\x1fP" + // 0x003C5 0x00313: 0x01F50 + "\x00\x0f\x14\x00b\x80\x1fQ" + // 0x003C5 0x00314: 0x01F51 + "\x00}@\x00`\x00\x1fR" + // 0x01F50 0x00300: 0x01F52 + "\x00}D\x00`\x00\x1fS" + // 0x01F51 0x00300: 0x01F53 + "\x00}@\x00` \x1fT" + // 0x01F50 0x00301: 0x01F54 + "\x00}D\x00` \x1fU" + // 0x01F51 0x00301: 0x01F55 + "\x00}@\x00h@\x1fV" + // 0x01F50 0x00342: 0x01F56 + "\x00}D\x00h@\x1fW" + // 0x01F51 0x00342: 0x01F57 + "\x00\x0e\x94\x00b\x80\x1fY" + // 0x003A5 0x00314: 0x01F59 + "\x00}d\x00`\x00\x1f[" + // 0x01F59 0x00300: 0x01F5B + "\x00}d\x00` \x1f]" + // 0x01F59 0x00301: 0x01F5D + "\x00}d\x00h@\x1f_" + // 0x01F59 0x00342: 0x01F5F + "\x00\x0f$\x00b`\x1f`" + // 0x003C9 0x00313: 0x01F60 + "\x00\x0f$\x00b\x80\x1fa" + // 0x003C9 0x00314: 0x01F61 + "\x00}\x80\x00`\x00\x1fb" + // 0x01F60 0x00300: 0x01F62 + "\x00}\x84\x00`\x00\x1fc" + // 0x01F61 0x00300: 0x01F63 + "\x00}\x80\x00` \x1fd" + // 0x01F60 0x00301: 0x01F64 + "\x00}\x84\x00` \x1fe" + // 0x01F61 0x00301: 0x01F65 + "\x00}\x80\x00h@\x1ff" + // 0x01F60 0x00342: 0x01F66 + "\x00}\x84\x00h@\x1fg" + // 0x01F61 0x00342: 0x01F67 + "\x00\x0e\xa4\x00b`\x1fh" + // 0x003A9 0x00313: 0x01F68 + "\x00\x0e\xa4\x00b\x80\x1fi" + // 0x003A9 0x00314: 0x01F69 + "\x00}\xa0\x00`\x00\x1fj" + // 0x01F68 0x00300: 0x01F6A + "\x00}\xa4\x00`\x00\x1fk" + // 0x01F69 0x00300: 0x01F6B + "\x00}\xa0\x00` \x1fl" + // 0x01F68 0x00301: 0x01F6C + "\x00}\xa4\x00` \x1fm" + // 0x01F69 0x00301: 0x01F6D + "\x00}\xa0\x00h@\x1fn" + // 0x01F68 0x00342: 0x01F6E + "\x00}\xa4\x00h@\x1fo" + // 0x01F69 0x00342: 0x01F6F + "\x00\x0e\xc4\x00`\x00\x1fp" + // 0x003B1 0x00300: 0x01F70 + "\x00\x0e\xd4\x00`\x00\x1fr" + // 0x003B5 0x00300: 0x01F72 + "\x00\x0e\xdc\x00`\x00\x1ft" + // 0x003B7 0x00300: 0x01F74 + "\x00\x0e\xe4\x00`\x00\x1fv" + // 0x003B9 0x00300: 0x01F76 + "\x00\x0e\xfc\x00`\x00\x1fx" + // 0x003BF 0x00300: 0x01F78 + "\x00\x0f\x14\x00`\x00\x1fz" + // 0x003C5 0x00300: 0x01F7A + "\x00\x0f$\x00`\x00\x1f|" + // 0x003C9 0x00300: 0x01F7C + "\x00|\x00\x00h\xa0\x1f\x80" + // 0x01F00 0x00345: 0x01F80 + "\x00|\x04\x00h\xa0\x1f\x81" + // 0x01F01 0x00345: 0x01F81 + "\x00|\b\x00h\xa0\x1f\x82" + // 0x01F02 0x00345: 0x01F82 + "\x00|\f\x00h\xa0\x1f\x83" + // 0x01F03 0x00345: 0x01F83 + "\x00|\x10\x00h\xa0\x1f\x84" + // 0x01F04 0x00345: 0x01F84 + "\x00|\x14\x00h\xa0\x1f\x85" + // 0x01F05 0x00345: 0x01F85 + "\x00|\x18\x00h\xa0\x1f\x86" + // 0x01F06 0x00345: 0x01F86 + "\x00|\x1c\x00h\xa0\x1f\x87" + // 0x01F07 0x00345: 0x01F87 + "\x00| \x00h\xa0\x1f\x88" + // 0x01F08 0x00345: 0x01F88 + "\x00|$\x00h\xa0\x1f\x89" + // 0x01F09 0x00345: 0x01F89 + "\x00|(\x00h\xa0\x1f\x8a" + // 0x01F0A 0x00345: 0x01F8A + "\x00|,\x00h\xa0\x1f\x8b" + // 0x01F0B 0x00345: 0x01F8B + "\x00|0\x00h\xa0\x1f\x8c" + // 0x01F0C 0x00345: 0x01F8C + "\x00|4\x00h\xa0\x1f\x8d" + // 0x01F0D 0x00345: 0x01F8D + "\x00|8\x00h\xa0\x1f\x8e" + // 0x01F0E 0x00345: 0x01F8E + "\x00|<\x00h\xa0\x1f\x8f" + // 0x01F0F 0x00345: 0x01F8F + "\x00|\x80\x00h\xa0\x1f\x90" + // 0x01F20 0x00345: 0x01F90 + "\x00|\x84\x00h\xa0\x1f\x91" + // 0x01F21 0x00345: 0x01F91 + "\x00|\x88\x00h\xa0\x1f\x92" + // 0x01F22 0x00345: 0x01F92 + "\x00|\x8c\x00h\xa0\x1f\x93" + // 0x01F23 0x00345: 0x01F93 + "\x00|\x90\x00h\xa0\x1f\x94" + // 0x01F24 0x00345: 0x01F94 + "\x00|\x94\x00h\xa0\x1f\x95" + // 0x01F25 0x00345: 0x01F95 + "\x00|\x98\x00h\xa0\x1f\x96" + // 0x01F26 0x00345: 0x01F96 + "\x00|\x9c\x00h\xa0\x1f\x97" + // 0x01F27 0x00345: 0x01F97 + "\x00|\xa0\x00h\xa0\x1f\x98" + // 0x01F28 0x00345: 0x01F98 + "\x00|\xa4\x00h\xa0\x1f\x99" + // 0x01F29 0x00345: 0x01F99 + "\x00|\xa8\x00h\xa0\x1f\x9a" + // 0x01F2A 0x00345: 0x01F9A + "\x00|\xac\x00h\xa0\x1f\x9b" + // 0x01F2B 0x00345: 0x01F9B + "\x00|\xb0\x00h\xa0\x1f\x9c" + // 0x01F2C 0x00345: 0x01F9C + "\x00|\xb4\x00h\xa0\x1f\x9d" + // 0x01F2D 0x00345: 0x01F9D + "\x00|\xb8\x00h\xa0\x1f\x9e" + // 0x01F2E 0x00345: 0x01F9E + "\x00|\xbc\x00h\xa0\x1f\x9f" + // 0x01F2F 0x00345: 0x01F9F + "\x00}\x80\x00h\xa0\x1f\xa0" + // 0x01F60 0x00345: 0x01FA0 + "\x00}\x84\x00h\xa0\x1f\xa1" + // 0x01F61 0x00345: 0x01FA1 + "\x00}\x88\x00h\xa0\x1f\xa2" + // 0x01F62 0x00345: 0x01FA2 + "\x00}\x8c\x00h\xa0\x1f\xa3" + // 0x01F63 0x00345: 0x01FA3 + "\x00}\x90\x00h\xa0\x1f\xa4" + // 0x01F64 0x00345: 0x01FA4 + "\x00}\x94\x00h\xa0\x1f\xa5" + // 0x01F65 0x00345: 0x01FA5 + "\x00}\x98\x00h\xa0\x1f\xa6" + // 0x01F66 0x00345: 0x01FA6 + "\x00}\x9c\x00h\xa0\x1f\xa7" + // 0x01F67 0x00345: 0x01FA7 + "\x00}\xa0\x00h\xa0\x1f\xa8" + // 0x01F68 0x00345: 0x01FA8 + "\x00}\xa4\x00h\xa0\x1f\xa9" + // 0x01F69 0x00345: 0x01FA9 + "\x00}\xa8\x00h\xa0\x1f\xaa" + // 0x01F6A 0x00345: 0x01FAA + "\x00}\xac\x00h\xa0\x1f\xab" + // 0x01F6B 0x00345: 0x01FAB + "\x00}\xb0\x00h\xa0\x1f\xac" + // 0x01F6C 0x00345: 0x01FAC + "\x00}\xb4\x00h\xa0\x1f\xad" + // 0x01F6D 0x00345: 0x01FAD + "\x00}\xb8\x00h\xa0\x1f\xae" + // 0x01F6E 0x00345: 0x01FAE + "\x00}\xbc\x00h\xa0\x1f\xaf" + // 0x01F6F 0x00345: 0x01FAF + "\x00\x0e\xc4\x00`\xc0\x1f\xb0" + // 0x003B1 0x00306: 0x01FB0 + "\x00\x0e\xc4\x00`\x80\x1f\xb1" + // 0x003B1 0x00304: 0x01FB1 + "\x00}\xc0\x00h\xa0\x1f\xb2" + // 0x01F70 0x00345: 0x01FB2 + "\x00\x0e\xc4\x00h\xa0\x1f\xb3" + // 0x003B1 0x00345: 0x01FB3 + "\x00\x0e\xb0\x00h\xa0\x1f\xb4" + // 0x003AC 0x00345: 0x01FB4 + "\x00\x0e\xc4\x00h@\x1f\xb6" + // 0x003B1 0x00342: 0x01FB6 + "\x00~\xd8\x00h\xa0\x1f\xb7" + // 0x01FB6 0x00345: 0x01FB7 + "\x00\x0eD\x00`\xc0\x1f\xb8" + // 0x00391 0x00306: 0x01FB8 + "\x00\x0eD\x00`\x80\x1f\xb9" + // 0x00391 0x00304: 0x01FB9 + "\x00\x0eD\x00`\x00\x1f\xba" + // 0x00391 0x00300: 0x01FBA + "\x00\x0eD\x00h\xa0\x1f\xbc" + // 0x00391 0x00345: 0x01FBC + "\x00\x02\xa0\x00h@\x1f\xc1" + // 0x000A8 0x00342: 0x01FC1 + "\x00}\xd0\x00h\xa0\x1f\xc2" + // 0x01F74 0x00345: 0x01FC2 + "\x00\x0e\xdc\x00h\xa0\x1f\xc3" + // 0x003B7 0x00345: 0x01FC3 + "\x00\x0e\xb8\x00h\xa0\x1f\xc4" + // 0x003AE 0x00345: 0x01FC4 + "\x00\x0e\xdc\x00h@\x1f\xc6" + // 0x003B7 0x00342: 0x01FC6 + "\x00\x7f\x18\x00h\xa0\x1f\xc7" + // 0x01FC6 0x00345: 0x01FC7 + "\x00\x0eT\x00`\x00\x1f\xc8" + // 0x00395 0x00300: 0x01FC8 + "\x00\x0e\\\x00`\x00\x1f\xca" + // 0x00397 0x00300: 0x01FCA + "\x00\x0e\\\x00h\xa0\x1f\xcc" + // 0x00397 0x00345: 0x01FCC + "\x00~\xfc\x00`\x00\x1f\xcd" + // 0x01FBF 0x00300: 0x01FCD + "\x00~\xfc\x00` \x1f\xce" + // 0x01FBF 0x00301: 0x01FCE + "\x00~\xfc\x00h@\x1f\xcf" + // 0x01FBF 0x00342: 0x01FCF + "\x00\x0e\xe4\x00`\xc0\x1f\xd0" + // 0x003B9 0x00306: 0x01FD0 + "\x00\x0e\xe4\x00`\x80\x1f\xd1" + // 0x003B9 0x00304: 0x01FD1 + "\x00\x0f(\x00`\x00\x1f\xd2" + // 0x003CA 0x00300: 0x01FD2 + "\x00\x0e\xe4\x00h@\x1f\xd6" + // 0x003B9 0x00342: 0x01FD6 + "\x00\x0f(\x00h@\x1f\xd7" + // 0x003CA 0x00342: 0x01FD7 + "\x00\x0ed\x00`\xc0\x1f\xd8" + // 0x00399 0x00306: 0x01FD8 + "\x00\x0ed\x00`\x80\x1f\xd9" + // 0x00399 0x00304: 0x01FD9 + "\x00\x0ed\x00`\x00\x1f\xda" + // 0x00399 0x00300: 0x01FDA + "\x00\x7f\xf8\x00`\x00\x1f\xdd" + // 0x01FFE 0x00300: 0x01FDD + "\x00\x7f\xf8\x00` \x1f\xde" + // 0x01FFE 0x00301: 0x01FDE + "\x00\x7f\xf8\x00h@\x1f\xdf" + // 0x01FFE 0x00342: 0x01FDF + "\x00\x0f\x14\x00`\xc0\x1f\xe0" + // 0x003C5 0x00306: 0x01FE0 + "\x00\x0f\x14\x00`\x80\x1f\xe1" + // 0x003C5 0x00304: 0x01FE1 + "\x00\x0f,\x00`\x00\x1f\xe2" + // 0x003CB 0x00300: 0x01FE2 + "\x00\x0f\x04\x00b`\x1f\xe4" + // 0x003C1 0x00313: 0x01FE4 + "\x00\x0f\x04\x00b\x80\x1f\xe5" + // 0x003C1 0x00314: 0x01FE5 + "\x00\x0f\x14\x00h@\x1f\xe6" + // 0x003C5 0x00342: 0x01FE6 + "\x00\x0f,\x00h@\x1f\xe7" + // 0x003CB 0x00342: 0x01FE7 + "\x00\x0e\x94\x00`\xc0\x1f\xe8" + // 0x003A5 0x00306: 0x01FE8 + "\x00\x0e\x94\x00`\x80\x1f\xe9" + // 0x003A5 0x00304: 0x01FE9 + "\x00\x0e\x94\x00`\x00\x1f\xea" + // 0x003A5 0x00300: 0x01FEA + "\x00\x0e\x84\x00b\x80\x1f\xec" + // 0x003A1 0x00314: 0x01FEC + "\x00\x02\xa0\x00`\x00\x1f\xed" + // 0x000A8 0x00300: 0x01FED + "\x00}\xf0\x00h\xa0\x1f\xf2" + // 0x01F7C 0x00345: 0x01FF2 + "\x00\x0f$\x00h\xa0\x1f\xf3" + // 0x003C9 0x00345: 0x01FF3 + "\x00\x0f8\x00h\xa0\x1f\xf4" + // 0x003CE 0x00345: 0x01FF4 + "\x00\x0f$\x00h@\x1f\xf6" + // 0x003C9 0x00342: 0x01FF6 + "\x00\x7f\xd8\x00h\xa0\x1f\xf7" + // 0x01FF6 0x00345: 0x01FF7 + "\x00\x0e|\x00`\x00\x1f\xf8" + // 0x0039F 0x00300: 0x01FF8 + "\x00\x0e\xa4\x00`\x00\x1f\xfa" + // 0x003A9 0x00300: 0x01FFA + "\x00\x0e\xa4\x00h\xa0\x1f\xfc" + // 0x003A9 0x00345: 0x01FFC + "\x00\x86@\x00g\x00!\x9a" + // 0x02190 0x00338: 0x0219A + "\x00\x86H\x00g\x00!\x9b" + // 0x02192 0x00338: 0x0219B + "\x00\x86P\x00g\x00!\xae" + // 0x02194 0x00338: 0x021AE + "\x00\x87@\x00g\x00!\xcd" + // 0x021D0 0x00338: 0x021CD + "\x00\x87P\x00g\x00!\xce" + // 0x021D4 0x00338: 0x021CE + "\x00\x87H\x00g\x00!\xcf" + // 0x021D2 0x00338: 0x021CF + "\x00\x88\f\x00g\x00\"\x04" + // 0x02203 0x00338: 0x02204 + "\x00\x88 \x00g\x00\"\t" + // 0x02208 0x00338: 0x02209 + "\x00\x88,\x00g\x00\"\f" + // 0x0220B 0x00338: 0x0220C + "\x00\x88\x8c\x00g\x00\"$" + // 0x02223 0x00338: 0x02224 + "\x00\x88\x94\x00g\x00\"&" + // 0x02225 0x00338: 0x02226 + "\x00\x88\xf0\x00g\x00\"A" + // 0x0223C 0x00338: 0x02241 + "\x00\x89\f\x00g\x00\"D" + // 0x02243 0x00338: 0x02244 + "\x00\x89\x14\x00g\x00\"G" + // 0x02245 0x00338: 0x02247 + "\x00\x89 \x00g\x00\"I" + // 0x02248 0x00338: 0x02249 + "\x00\x00\xf4\x00g\x00\"`" + // 0x0003D 0x00338: 0x02260 + "\x00\x89\x84\x00g\x00\"b" + // 0x02261 0x00338: 0x02262 + "\x00\x894\x00g\x00\"m" + // 0x0224D 0x00338: 0x0226D + "\x00\x00\xf0\x00g\x00\"n" + // 0x0003C 0x00338: 0x0226E + "\x00\x00\xf8\x00g\x00\"o" + // 0x0003E 0x00338: 0x0226F + "\x00\x89\x90\x00g\x00\"p" + // 0x02264 0x00338: 0x02270 + "\x00\x89\x94\x00g\x00\"q" + // 0x02265 0x00338: 0x02271 + "\x00\x89\xc8\x00g\x00\"t" + // 0x02272 0x00338: 0x02274 + "\x00\x89\xcc\x00g\x00\"u" + // 0x02273 0x00338: 0x02275 + "\x00\x89\xd8\x00g\x00\"x" + // 0x02276 0x00338: 0x02278 + "\x00\x89\xdc\x00g\x00\"y" + // 0x02277 0x00338: 0x02279 + "\x00\x89\xe8\x00g\x00\"\x80" + // 0x0227A 0x00338: 0x02280 + "\x00\x89\xec\x00g\x00\"\x81" + // 0x0227B 0x00338: 0x02281 + "\x00\x8a\b\x00g\x00\"\x84" + // 0x02282 0x00338: 0x02284 + "\x00\x8a\f\x00g\x00\"\x85" + // 0x02283 0x00338: 0x02285 + "\x00\x8a\x18\x00g\x00\"\x88" + // 0x02286 0x00338: 0x02288 + "\x00\x8a\x1c\x00g\x00\"\x89" + // 0x02287 0x00338: 0x02289 + "\x00\x8a\x88\x00g\x00\"\xac" + // 0x022A2 0x00338: 0x022AC + "\x00\x8a\xa0\x00g\x00\"\xad" + // 0x022A8 0x00338: 0x022AD + "\x00\x8a\xa4\x00g\x00\"\xae" + // 0x022A9 0x00338: 0x022AE + "\x00\x8a\xac\x00g\x00\"\xaf" + // 0x022AB 0x00338: 0x022AF + "\x00\x89\xf0\x00g\x00\"\xe0" + // 0x0227C 0x00338: 0x022E0 + "\x00\x89\xf4\x00g\x00\"\xe1" + // 0x0227D 0x00338: 0x022E1 + "\x00\x8aD\x00g\x00\"\xe2" + // 0x02291 0x00338: 0x022E2 + "\x00\x8aH\x00g\x00\"\xe3" + // 0x02292 0x00338: 0x022E3 + "\x00\x8a\xc8\x00g\x00\"\xea" + // 0x022B2 0x00338: 0x022EA + "\x00\x8a\xcc\x00g\x00\"\xeb" + // 0x022B3 0x00338: 0x022EB + "\x00\x8a\xd0\x00g\x00\"\xec" + // 0x022B4 0x00338: 0x022EC + "\x00\x8a\xd4\x00g\x00\"\xed" + // 0x022B5 0x00338: 0x022ED + "\x00\xc1,\x06\x13 0L" + // 0x0304B 0x03099: 0x0304C + "\x00\xc14\x06\x13 0N" + // 0x0304D 0x03099: 0x0304E + "\x00\xc1<\x06\x13 0P" + // 0x0304F 0x03099: 0x03050 + "\x00\xc1D\x06\x13 0R" + // 0x03051 0x03099: 0x03052 + "\x00\xc1L\x06\x13 0T" + // 0x03053 0x03099: 0x03054 + "\x00\xc1T\x06\x13 0V" + // 0x03055 0x03099: 0x03056 + "\x00\xc1\\\x06\x13 0X" + // 0x03057 0x03099: 0x03058 + "\x00\xc1d\x06\x13 0Z" + // 0x03059 0x03099: 0x0305A + "\x00\xc1l\x06\x13 0\\" + // 0x0305B 0x03099: 0x0305C + "\x00\xc1t\x06\x13 0^" + // 0x0305D 0x03099: 0x0305E + "\x00\xc1|\x06\x13 0`" + // 0x0305F 0x03099: 0x03060 + "\x00\xc1\x84\x06\x13 0b" + // 0x03061 0x03099: 0x03062 + "\x00\xc1\x90\x06\x13 0e" + // 0x03064 0x03099: 0x03065 + "\x00\xc1\x98\x06\x13 0g" + // 0x03066 0x03099: 0x03067 + "\x00\xc1\xa0\x06\x13 0i" + // 0x03068 0x03099: 0x03069 + "\x00\xc1\xbc\x06\x13 0p" + // 0x0306F 0x03099: 0x03070 + "\x00\xc1\xbc\x06\x13@0q" + // 0x0306F 0x0309A: 0x03071 + "\x00\xc1\xc8\x06\x13 0s" + // 0x03072 0x03099: 0x03073 + "\x00\xc1\xc8\x06\x13@0t" + // 0x03072 0x0309A: 0x03074 + "\x00\xc1\xd4\x06\x13 0v" + // 0x03075 0x03099: 0x03076 + "\x00\xc1\xd4\x06\x13@0w" + // 0x03075 0x0309A: 0x03077 + "\x00\xc1\xe0\x06\x13 0y" + // 0x03078 0x03099: 0x03079 + "\x00\xc1\xe0\x06\x13@0z" + // 0x03078 0x0309A: 0x0307A + "\x00\xc1\xec\x06\x13 0|" + // 0x0307B 0x03099: 0x0307C + "\x00\xc1\xec\x06\x13@0}" + // 0x0307B 0x0309A: 0x0307D + "\x00\xc1\x18\x06\x13 0\x94" + // 0x03046 0x03099: 0x03094 + "\x00\xc2t\x06\x13 0\x9e" + // 0x0309D 0x03099: 0x0309E + "\x00¬\x06\x13 0\xac" + // 0x030AB 0x03099: 0x030AC + "\x00´\x06\x13 0\xae" + // 0x030AD 0x03099: 0x030AE + "\x00¼\x06\x13 0\xb0" + // 0x030AF 0x03099: 0x030B0 + "\x00\xc2\xc4\x06\x13 0\xb2" + // 0x030B1 0x03099: 0x030B2 + "\x00\xc2\xcc\x06\x13 0\xb4" + // 0x030B3 0x03099: 0x030B4 + "\x00\xc2\xd4\x06\x13 0\xb6" + // 0x030B5 0x03099: 0x030B6 + "\x00\xc2\xdc\x06\x13 0\xb8" + // 0x030B7 0x03099: 0x030B8 + "\x00\xc2\xe4\x06\x13 0\xba" + // 0x030B9 0x03099: 0x030BA + "\x00\xc2\xec\x06\x13 0\xbc" + // 0x030BB 0x03099: 0x030BC + "\x00\xc2\xf4\x06\x13 0\xbe" + // 0x030BD 0x03099: 0x030BE + "\x00\xc2\xfc\x06\x13 0\xc0" + // 0x030BF 0x03099: 0x030C0 + "\x00\xc3\x04\x06\x13 0\xc2" + // 0x030C1 0x03099: 0x030C2 + "\x00\xc3\x10\x06\x13 0\xc5" + // 0x030C4 0x03099: 0x030C5 + "\x00\xc3\x18\x06\x13 0\xc7" + // 0x030C6 0x03099: 0x030C7 + "\x00\xc3 \x06\x13 0\xc9" + // 0x030C8 0x03099: 0x030C9 + "\x00\xc3<\x06\x13 0\xd0" + // 0x030CF 0x03099: 0x030D0 + "\x00\xc3<\x06\x13@0\xd1" + // 0x030CF 0x0309A: 0x030D1 + "\x00\xc3H\x06\x13 0\xd3" + // 0x030D2 0x03099: 0x030D3 + "\x00\xc3H\x06\x13@0\xd4" + // 0x030D2 0x0309A: 0x030D4 + "\x00\xc3T\x06\x13 0\xd6" + // 0x030D5 0x03099: 0x030D6 + "\x00\xc3T\x06\x13@0\xd7" + // 0x030D5 0x0309A: 0x030D7 + "\x00\xc3`\x06\x13 0\xd9" + // 0x030D8 0x03099: 0x030D9 + "\x00\xc3`\x06\x13@0\xda" + // 0x030D8 0x0309A: 0x030DA + "\x00\xc3l\x06\x13 0\xdc" + // 0x030DB 0x03099: 0x030DC + "\x00\xc3l\x06\x13@0\xdd" + // 0x030DB 0x0309A: 0x030DD + "\x00\u0098\x06\x13 0\xf4" + // 0x030A6 0x03099: 0x030F4 + "\x00ü\x06\x13 0\xf7" + // 0x030EF 0x03099: 0x030F7 + "\x00\xc3\xc0\x06\x13 0\xf8" + // 0x030F0 0x03099: 0x030F8 + "\x00\xc3\xc4\x06\x13 0\xf9" + // 0x030F1 0x03099: 0x030F9 + "\x00\xc3\xc8\x06\x13 0\xfa" + // 0x030F2 0x03099: 0x030FA + "\x00\xc3\xf4\x06\x13 0\xfe" + // 0x030FD 0x03099: 0x030FE + "\x04Bd\"\x17A\x10\x9a" + // 0x11099 0x110BA: 0x1109A + "\x04Bl\"\x17A\x10\x9c" + // 0x1109B 0x110BA: 0x1109C + "\x04B\x94\"\x17A\x10\xab" + // 0x110A5 0x110BA: 0x110AB + "\x04D\xc4\"$\xe1\x11." + // 0x11131 0x11127: 0x1112E + "\x04D\xc8\"$\xe1\x11/" + // 0x11132 0x11127: 0x1112F + "\x04M\x1c\"g\xc1\x13K" + // 0x11347 0x1133E: 0x1134B + "\x04M\x1c\"j\xe1\x13L" + // 0x11347 0x11357: 0x1134C + "\x04R\xe4\"\x97A\x14\xbb" + // 0x114B9 0x114BA: 0x114BB + "\x04R\xe4\"\x96\x01\x14\xbc" + // 0x114B9 0x114B0: 0x114BC + "\x04R\xe4\"\x97\xa1\x14\xbe" + // 0x114B9 0x114BD: 0x114BE + "\x04V\xe0\"\xb5\xe1\x15\xba" + // 0x115B8 0x115AF: 0x115BA + "\x04V\xe4\"\xb5\xe1\x15\xbb" + // 0x115B9 0x115AF: 0x115BB + "\x04d\xd4#&\x01\x198" + // 0x11935 0x11930: 0x11938 "" // Total size of tables: 56KB (57068 bytes) diff --git a/constraint/vendor/golang.org/x/text/unicode/norm/tables17.0.0.go b/constraint/vendor/golang.org/x/text/unicode/norm/tables17.0.0.go index dfd555fc1..c32318912 100644 --- a/constraint/vendor/golang.org/x/text/unicode/norm/tables17.0.0.go +++ b/constraint/vendor/golang.org/x/text/unicode/norm/tables17.0.0.go @@ -7135,970 +7135,970 @@ var nfkcSparseValues = [980]valueRange{ } // recompMap: 7688 bytes (entries only) -var recompMap map[uint32]rune +var recompMap map[uint64]rune var recompMapOnce sync.Once const recompMapPacked = "" + - "\x00A\x03\x00\x00\x00\x00\xc0" + // 0x00410300: 0x000000C0 - "\x00A\x03\x01\x00\x00\x00\xc1" + // 0x00410301: 0x000000C1 - "\x00A\x03\x02\x00\x00\x00\xc2" + // 0x00410302: 0x000000C2 - "\x00A\x03\x03\x00\x00\x00\xc3" + // 0x00410303: 0x000000C3 - "\x00A\x03\b\x00\x00\x00\xc4" + // 0x00410308: 0x000000C4 - "\x00A\x03\n\x00\x00\x00\xc5" + // 0x0041030A: 0x000000C5 - "\x00C\x03'\x00\x00\x00\xc7" + // 0x00430327: 0x000000C7 - "\x00E\x03\x00\x00\x00\x00\xc8" + // 0x00450300: 0x000000C8 - "\x00E\x03\x01\x00\x00\x00\xc9" + // 0x00450301: 0x000000C9 - "\x00E\x03\x02\x00\x00\x00\xca" + // 0x00450302: 0x000000CA - "\x00E\x03\b\x00\x00\x00\xcb" + // 0x00450308: 0x000000CB - "\x00I\x03\x00\x00\x00\x00\xcc" + // 0x00490300: 0x000000CC - "\x00I\x03\x01\x00\x00\x00\xcd" + // 0x00490301: 0x000000CD - "\x00I\x03\x02\x00\x00\x00\xce" + // 0x00490302: 0x000000CE - "\x00I\x03\b\x00\x00\x00\xcf" + // 0x00490308: 0x000000CF - "\x00N\x03\x03\x00\x00\x00\xd1" + // 0x004E0303: 0x000000D1 - "\x00O\x03\x00\x00\x00\x00\xd2" + // 0x004F0300: 0x000000D2 - "\x00O\x03\x01\x00\x00\x00\xd3" + // 0x004F0301: 0x000000D3 - "\x00O\x03\x02\x00\x00\x00\xd4" + // 0x004F0302: 0x000000D4 - "\x00O\x03\x03\x00\x00\x00\xd5" + // 0x004F0303: 0x000000D5 - "\x00O\x03\b\x00\x00\x00\xd6" + // 0x004F0308: 0x000000D6 - "\x00U\x03\x00\x00\x00\x00\xd9" + // 0x00550300: 0x000000D9 - "\x00U\x03\x01\x00\x00\x00\xda" + // 0x00550301: 0x000000DA - "\x00U\x03\x02\x00\x00\x00\xdb" + // 0x00550302: 0x000000DB - "\x00U\x03\b\x00\x00\x00\xdc" + // 0x00550308: 0x000000DC - "\x00Y\x03\x01\x00\x00\x00\xdd" + // 0x00590301: 0x000000DD - "\x00a\x03\x00\x00\x00\x00\xe0" + // 0x00610300: 0x000000E0 - "\x00a\x03\x01\x00\x00\x00\xe1" + // 0x00610301: 0x000000E1 - "\x00a\x03\x02\x00\x00\x00\xe2" + // 0x00610302: 0x000000E2 - "\x00a\x03\x03\x00\x00\x00\xe3" + // 0x00610303: 0x000000E3 - "\x00a\x03\b\x00\x00\x00\xe4" + // 0x00610308: 0x000000E4 - "\x00a\x03\n\x00\x00\x00\xe5" + // 0x0061030A: 0x000000E5 - "\x00c\x03'\x00\x00\x00\xe7" + // 0x00630327: 0x000000E7 - "\x00e\x03\x00\x00\x00\x00\xe8" + // 0x00650300: 0x000000E8 - "\x00e\x03\x01\x00\x00\x00\xe9" + // 0x00650301: 0x000000E9 - "\x00e\x03\x02\x00\x00\x00\xea" + // 0x00650302: 0x000000EA - "\x00e\x03\b\x00\x00\x00\xeb" + // 0x00650308: 0x000000EB - "\x00i\x03\x00\x00\x00\x00\xec" + // 0x00690300: 0x000000EC - "\x00i\x03\x01\x00\x00\x00\xed" + // 0x00690301: 0x000000ED - "\x00i\x03\x02\x00\x00\x00\xee" + // 0x00690302: 0x000000EE - "\x00i\x03\b\x00\x00\x00\xef" + // 0x00690308: 0x000000EF - "\x00n\x03\x03\x00\x00\x00\xf1" + // 0x006E0303: 0x000000F1 - "\x00o\x03\x00\x00\x00\x00\xf2" + // 0x006F0300: 0x000000F2 - "\x00o\x03\x01\x00\x00\x00\xf3" + // 0x006F0301: 0x000000F3 - "\x00o\x03\x02\x00\x00\x00\xf4" + // 0x006F0302: 0x000000F4 - "\x00o\x03\x03\x00\x00\x00\xf5" + // 0x006F0303: 0x000000F5 - "\x00o\x03\b\x00\x00\x00\xf6" + // 0x006F0308: 0x000000F6 - "\x00u\x03\x00\x00\x00\x00\xf9" + // 0x00750300: 0x000000F9 - "\x00u\x03\x01\x00\x00\x00\xfa" + // 0x00750301: 0x000000FA - "\x00u\x03\x02\x00\x00\x00\xfb" + // 0x00750302: 0x000000FB - "\x00u\x03\b\x00\x00\x00\xfc" + // 0x00750308: 0x000000FC - "\x00y\x03\x01\x00\x00\x00\xfd" + // 0x00790301: 0x000000FD - "\x00y\x03\b\x00\x00\x00\xff" + // 0x00790308: 0x000000FF - "\x00A\x03\x04\x00\x00\x01\x00" + // 0x00410304: 0x00000100 - "\x00a\x03\x04\x00\x00\x01\x01" + // 0x00610304: 0x00000101 - "\x00A\x03\x06\x00\x00\x01\x02" + // 0x00410306: 0x00000102 - "\x00a\x03\x06\x00\x00\x01\x03" + // 0x00610306: 0x00000103 - "\x00A\x03(\x00\x00\x01\x04" + // 0x00410328: 0x00000104 - "\x00a\x03(\x00\x00\x01\x05" + // 0x00610328: 0x00000105 - "\x00C\x03\x01\x00\x00\x01\x06" + // 0x00430301: 0x00000106 - "\x00c\x03\x01\x00\x00\x01\a" + // 0x00630301: 0x00000107 - "\x00C\x03\x02\x00\x00\x01\b" + // 0x00430302: 0x00000108 - "\x00c\x03\x02\x00\x00\x01\t" + // 0x00630302: 0x00000109 - "\x00C\x03\a\x00\x00\x01\n" + // 0x00430307: 0x0000010A - "\x00c\x03\a\x00\x00\x01\v" + // 0x00630307: 0x0000010B - "\x00C\x03\f\x00\x00\x01\f" + // 0x0043030C: 0x0000010C - "\x00c\x03\f\x00\x00\x01\r" + // 0x0063030C: 0x0000010D - "\x00D\x03\f\x00\x00\x01\x0e" + // 0x0044030C: 0x0000010E - "\x00d\x03\f\x00\x00\x01\x0f" + // 0x0064030C: 0x0000010F - "\x00E\x03\x04\x00\x00\x01\x12" + // 0x00450304: 0x00000112 - "\x00e\x03\x04\x00\x00\x01\x13" + // 0x00650304: 0x00000113 - "\x00E\x03\x06\x00\x00\x01\x14" + // 0x00450306: 0x00000114 - "\x00e\x03\x06\x00\x00\x01\x15" + // 0x00650306: 0x00000115 - "\x00E\x03\a\x00\x00\x01\x16" + // 0x00450307: 0x00000116 - "\x00e\x03\a\x00\x00\x01\x17" + // 0x00650307: 0x00000117 - "\x00E\x03(\x00\x00\x01\x18" + // 0x00450328: 0x00000118 - "\x00e\x03(\x00\x00\x01\x19" + // 0x00650328: 0x00000119 - "\x00E\x03\f\x00\x00\x01\x1a" + // 0x0045030C: 0x0000011A - "\x00e\x03\f\x00\x00\x01\x1b" + // 0x0065030C: 0x0000011B - "\x00G\x03\x02\x00\x00\x01\x1c" + // 0x00470302: 0x0000011C - "\x00g\x03\x02\x00\x00\x01\x1d" + // 0x00670302: 0x0000011D - "\x00G\x03\x06\x00\x00\x01\x1e" + // 0x00470306: 0x0000011E - "\x00g\x03\x06\x00\x00\x01\x1f" + // 0x00670306: 0x0000011F - "\x00G\x03\a\x00\x00\x01 " + // 0x00470307: 0x00000120 - "\x00g\x03\a\x00\x00\x01!" + // 0x00670307: 0x00000121 - "\x00G\x03'\x00\x00\x01\"" + // 0x00470327: 0x00000122 - "\x00g\x03'\x00\x00\x01#" + // 0x00670327: 0x00000123 - "\x00H\x03\x02\x00\x00\x01$" + // 0x00480302: 0x00000124 - "\x00h\x03\x02\x00\x00\x01%" + // 0x00680302: 0x00000125 - "\x00I\x03\x03\x00\x00\x01(" + // 0x00490303: 0x00000128 - "\x00i\x03\x03\x00\x00\x01)" + // 0x00690303: 0x00000129 - "\x00I\x03\x04\x00\x00\x01*" + // 0x00490304: 0x0000012A - "\x00i\x03\x04\x00\x00\x01+" + // 0x00690304: 0x0000012B - "\x00I\x03\x06\x00\x00\x01," + // 0x00490306: 0x0000012C - "\x00i\x03\x06\x00\x00\x01-" + // 0x00690306: 0x0000012D - "\x00I\x03(\x00\x00\x01." + // 0x00490328: 0x0000012E - "\x00i\x03(\x00\x00\x01/" + // 0x00690328: 0x0000012F - "\x00I\x03\a\x00\x00\x010" + // 0x00490307: 0x00000130 - "\x00J\x03\x02\x00\x00\x014" + // 0x004A0302: 0x00000134 - "\x00j\x03\x02\x00\x00\x015" + // 0x006A0302: 0x00000135 - "\x00K\x03'\x00\x00\x016" + // 0x004B0327: 0x00000136 - "\x00k\x03'\x00\x00\x017" + // 0x006B0327: 0x00000137 - "\x00L\x03\x01\x00\x00\x019" + // 0x004C0301: 0x00000139 - "\x00l\x03\x01\x00\x00\x01:" + // 0x006C0301: 0x0000013A - "\x00L\x03'\x00\x00\x01;" + // 0x004C0327: 0x0000013B - "\x00l\x03'\x00\x00\x01<" + // 0x006C0327: 0x0000013C - "\x00L\x03\f\x00\x00\x01=" + // 0x004C030C: 0x0000013D - "\x00l\x03\f\x00\x00\x01>" + // 0x006C030C: 0x0000013E - "\x00N\x03\x01\x00\x00\x01C" + // 0x004E0301: 0x00000143 - "\x00n\x03\x01\x00\x00\x01D" + // 0x006E0301: 0x00000144 - "\x00N\x03'\x00\x00\x01E" + // 0x004E0327: 0x00000145 - "\x00n\x03'\x00\x00\x01F" + // 0x006E0327: 0x00000146 - "\x00N\x03\f\x00\x00\x01G" + // 0x004E030C: 0x00000147 - "\x00n\x03\f\x00\x00\x01H" + // 0x006E030C: 0x00000148 - "\x00O\x03\x04\x00\x00\x01L" + // 0x004F0304: 0x0000014C - "\x00o\x03\x04\x00\x00\x01M" + // 0x006F0304: 0x0000014D - "\x00O\x03\x06\x00\x00\x01N" + // 0x004F0306: 0x0000014E - "\x00o\x03\x06\x00\x00\x01O" + // 0x006F0306: 0x0000014F - "\x00O\x03\v\x00\x00\x01P" + // 0x004F030B: 0x00000150 - "\x00o\x03\v\x00\x00\x01Q" + // 0x006F030B: 0x00000151 - "\x00R\x03\x01\x00\x00\x01T" + // 0x00520301: 0x00000154 - "\x00r\x03\x01\x00\x00\x01U" + // 0x00720301: 0x00000155 - "\x00R\x03'\x00\x00\x01V" + // 0x00520327: 0x00000156 - "\x00r\x03'\x00\x00\x01W" + // 0x00720327: 0x00000157 - "\x00R\x03\f\x00\x00\x01X" + // 0x0052030C: 0x00000158 - "\x00r\x03\f\x00\x00\x01Y" + // 0x0072030C: 0x00000159 - "\x00S\x03\x01\x00\x00\x01Z" + // 0x00530301: 0x0000015A - "\x00s\x03\x01\x00\x00\x01[" + // 0x00730301: 0x0000015B - "\x00S\x03\x02\x00\x00\x01\\" + // 0x00530302: 0x0000015C - "\x00s\x03\x02\x00\x00\x01]" + // 0x00730302: 0x0000015D - "\x00S\x03'\x00\x00\x01^" + // 0x00530327: 0x0000015E - "\x00s\x03'\x00\x00\x01_" + // 0x00730327: 0x0000015F - "\x00S\x03\f\x00\x00\x01`" + // 0x0053030C: 0x00000160 - "\x00s\x03\f\x00\x00\x01a" + // 0x0073030C: 0x00000161 - "\x00T\x03'\x00\x00\x01b" + // 0x00540327: 0x00000162 - "\x00t\x03'\x00\x00\x01c" + // 0x00740327: 0x00000163 - "\x00T\x03\f\x00\x00\x01d" + // 0x0054030C: 0x00000164 - "\x00t\x03\f\x00\x00\x01e" + // 0x0074030C: 0x00000165 - "\x00U\x03\x03\x00\x00\x01h" + // 0x00550303: 0x00000168 - "\x00u\x03\x03\x00\x00\x01i" + // 0x00750303: 0x00000169 - "\x00U\x03\x04\x00\x00\x01j" + // 0x00550304: 0x0000016A - "\x00u\x03\x04\x00\x00\x01k" + // 0x00750304: 0x0000016B - "\x00U\x03\x06\x00\x00\x01l" + // 0x00550306: 0x0000016C - "\x00u\x03\x06\x00\x00\x01m" + // 0x00750306: 0x0000016D - "\x00U\x03\n\x00\x00\x01n" + // 0x0055030A: 0x0000016E - "\x00u\x03\n\x00\x00\x01o" + // 0x0075030A: 0x0000016F - "\x00U\x03\v\x00\x00\x01p" + // 0x0055030B: 0x00000170 - "\x00u\x03\v\x00\x00\x01q" + // 0x0075030B: 0x00000171 - "\x00U\x03(\x00\x00\x01r" + // 0x00550328: 0x00000172 - "\x00u\x03(\x00\x00\x01s" + // 0x00750328: 0x00000173 - "\x00W\x03\x02\x00\x00\x01t" + // 0x00570302: 0x00000174 - "\x00w\x03\x02\x00\x00\x01u" + // 0x00770302: 0x00000175 - "\x00Y\x03\x02\x00\x00\x01v" + // 0x00590302: 0x00000176 - "\x00y\x03\x02\x00\x00\x01w" + // 0x00790302: 0x00000177 - "\x00Y\x03\b\x00\x00\x01x" + // 0x00590308: 0x00000178 - "\x00Z\x03\x01\x00\x00\x01y" + // 0x005A0301: 0x00000179 - "\x00z\x03\x01\x00\x00\x01z" + // 0x007A0301: 0x0000017A - "\x00Z\x03\a\x00\x00\x01{" + // 0x005A0307: 0x0000017B - "\x00z\x03\a\x00\x00\x01|" + // 0x007A0307: 0x0000017C - "\x00Z\x03\f\x00\x00\x01}" + // 0x005A030C: 0x0000017D - "\x00z\x03\f\x00\x00\x01~" + // 0x007A030C: 0x0000017E - "\x00O\x03\x1b\x00\x00\x01\xa0" + // 0x004F031B: 0x000001A0 - "\x00o\x03\x1b\x00\x00\x01\xa1" + // 0x006F031B: 0x000001A1 - "\x00U\x03\x1b\x00\x00\x01\xaf" + // 0x0055031B: 0x000001AF - "\x00u\x03\x1b\x00\x00\x01\xb0" + // 0x0075031B: 0x000001B0 - "\x00A\x03\f\x00\x00\x01\xcd" + // 0x0041030C: 0x000001CD - "\x00a\x03\f\x00\x00\x01\xce" + // 0x0061030C: 0x000001CE - "\x00I\x03\f\x00\x00\x01\xcf" + // 0x0049030C: 0x000001CF - "\x00i\x03\f\x00\x00\x01\xd0" + // 0x0069030C: 0x000001D0 - "\x00O\x03\f\x00\x00\x01\xd1" + // 0x004F030C: 0x000001D1 - "\x00o\x03\f\x00\x00\x01\xd2" + // 0x006F030C: 0x000001D2 - "\x00U\x03\f\x00\x00\x01\xd3" + // 0x0055030C: 0x000001D3 - "\x00u\x03\f\x00\x00\x01\xd4" + // 0x0075030C: 0x000001D4 - "\x00\xdc\x03\x04\x00\x00\x01\xd5" + // 0x00DC0304: 0x000001D5 - "\x00\xfc\x03\x04\x00\x00\x01\xd6" + // 0x00FC0304: 0x000001D6 - "\x00\xdc\x03\x01\x00\x00\x01\xd7" + // 0x00DC0301: 0x000001D7 - "\x00\xfc\x03\x01\x00\x00\x01\xd8" + // 0x00FC0301: 0x000001D8 - "\x00\xdc\x03\f\x00\x00\x01\xd9" + // 0x00DC030C: 0x000001D9 - "\x00\xfc\x03\f\x00\x00\x01\xda" + // 0x00FC030C: 0x000001DA - "\x00\xdc\x03\x00\x00\x00\x01\xdb" + // 0x00DC0300: 0x000001DB - "\x00\xfc\x03\x00\x00\x00\x01\xdc" + // 0x00FC0300: 0x000001DC - "\x00\xc4\x03\x04\x00\x00\x01\xde" + // 0x00C40304: 0x000001DE - "\x00\xe4\x03\x04\x00\x00\x01\xdf" + // 0x00E40304: 0x000001DF - "\x02&\x03\x04\x00\x00\x01\xe0" + // 0x02260304: 0x000001E0 - "\x02'\x03\x04\x00\x00\x01\xe1" + // 0x02270304: 0x000001E1 - "\x00\xc6\x03\x04\x00\x00\x01\xe2" + // 0x00C60304: 0x000001E2 - "\x00\xe6\x03\x04\x00\x00\x01\xe3" + // 0x00E60304: 0x000001E3 - "\x00G\x03\f\x00\x00\x01\xe6" + // 0x0047030C: 0x000001E6 - "\x00g\x03\f\x00\x00\x01\xe7" + // 0x0067030C: 0x000001E7 - "\x00K\x03\f\x00\x00\x01\xe8" + // 0x004B030C: 0x000001E8 - "\x00k\x03\f\x00\x00\x01\xe9" + // 0x006B030C: 0x000001E9 - "\x00O\x03(\x00\x00\x01\xea" + // 0x004F0328: 0x000001EA - "\x00o\x03(\x00\x00\x01\xeb" + // 0x006F0328: 0x000001EB - "\x01\xea\x03\x04\x00\x00\x01\xec" + // 0x01EA0304: 0x000001EC - "\x01\xeb\x03\x04\x00\x00\x01\xed" + // 0x01EB0304: 0x000001ED - "\x01\xb7\x03\f\x00\x00\x01\xee" + // 0x01B7030C: 0x000001EE - "\x02\x92\x03\f\x00\x00\x01\xef" + // 0x0292030C: 0x000001EF - "\x00j\x03\f\x00\x00\x01\xf0" + // 0x006A030C: 0x000001F0 - "\x00G\x03\x01\x00\x00\x01\xf4" + // 0x00470301: 0x000001F4 - "\x00g\x03\x01\x00\x00\x01\xf5" + // 0x00670301: 0x000001F5 - "\x00N\x03\x00\x00\x00\x01\xf8" + // 0x004E0300: 0x000001F8 - "\x00n\x03\x00\x00\x00\x01\xf9" + // 0x006E0300: 0x000001F9 - "\x00\xc5\x03\x01\x00\x00\x01\xfa" + // 0x00C50301: 0x000001FA - "\x00\xe5\x03\x01\x00\x00\x01\xfb" + // 0x00E50301: 0x000001FB - "\x00\xc6\x03\x01\x00\x00\x01\xfc" + // 0x00C60301: 0x000001FC - "\x00\xe6\x03\x01\x00\x00\x01\xfd" + // 0x00E60301: 0x000001FD - "\x00\xd8\x03\x01\x00\x00\x01\xfe" + // 0x00D80301: 0x000001FE - "\x00\xf8\x03\x01\x00\x00\x01\xff" + // 0x00F80301: 0x000001FF - "\x00A\x03\x0f\x00\x00\x02\x00" + // 0x0041030F: 0x00000200 - "\x00a\x03\x0f\x00\x00\x02\x01" + // 0x0061030F: 0x00000201 - "\x00A\x03\x11\x00\x00\x02\x02" + // 0x00410311: 0x00000202 - "\x00a\x03\x11\x00\x00\x02\x03" + // 0x00610311: 0x00000203 - "\x00E\x03\x0f\x00\x00\x02\x04" + // 0x0045030F: 0x00000204 - "\x00e\x03\x0f\x00\x00\x02\x05" + // 0x0065030F: 0x00000205 - "\x00E\x03\x11\x00\x00\x02\x06" + // 0x00450311: 0x00000206 - "\x00e\x03\x11\x00\x00\x02\a" + // 0x00650311: 0x00000207 - "\x00I\x03\x0f\x00\x00\x02\b" + // 0x0049030F: 0x00000208 - "\x00i\x03\x0f\x00\x00\x02\t" + // 0x0069030F: 0x00000209 - "\x00I\x03\x11\x00\x00\x02\n" + // 0x00490311: 0x0000020A - "\x00i\x03\x11\x00\x00\x02\v" + // 0x00690311: 0x0000020B - "\x00O\x03\x0f\x00\x00\x02\f" + // 0x004F030F: 0x0000020C - "\x00o\x03\x0f\x00\x00\x02\r" + // 0x006F030F: 0x0000020D - "\x00O\x03\x11\x00\x00\x02\x0e" + // 0x004F0311: 0x0000020E - "\x00o\x03\x11\x00\x00\x02\x0f" + // 0x006F0311: 0x0000020F - "\x00R\x03\x0f\x00\x00\x02\x10" + // 0x0052030F: 0x00000210 - "\x00r\x03\x0f\x00\x00\x02\x11" + // 0x0072030F: 0x00000211 - "\x00R\x03\x11\x00\x00\x02\x12" + // 0x00520311: 0x00000212 - "\x00r\x03\x11\x00\x00\x02\x13" + // 0x00720311: 0x00000213 - "\x00U\x03\x0f\x00\x00\x02\x14" + // 0x0055030F: 0x00000214 - "\x00u\x03\x0f\x00\x00\x02\x15" + // 0x0075030F: 0x00000215 - "\x00U\x03\x11\x00\x00\x02\x16" + // 0x00550311: 0x00000216 - "\x00u\x03\x11\x00\x00\x02\x17" + // 0x00750311: 0x00000217 - "\x00S\x03&\x00\x00\x02\x18" + // 0x00530326: 0x00000218 - "\x00s\x03&\x00\x00\x02\x19" + // 0x00730326: 0x00000219 - "\x00T\x03&\x00\x00\x02\x1a" + // 0x00540326: 0x0000021A - "\x00t\x03&\x00\x00\x02\x1b" + // 0x00740326: 0x0000021B - "\x00H\x03\f\x00\x00\x02\x1e" + // 0x0048030C: 0x0000021E - "\x00h\x03\f\x00\x00\x02\x1f" + // 0x0068030C: 0x0000021F - "\x00A\x03\a\x00\x00\x02&" + // 0x00410307: 0x00000226 - "\x00a\x03\a\x00\x00\x02'" + // 0x00610307: 0x00000227 - "\x00E\x03'\x00\x00\x02(" + // 0x00450327: 0x00000228 - "\x00e\x03'\x00\x00\x02)" + // 0x00650327: 0x00000229 - "\x00\xd6\x03\x04\x00\x00\x02*" + // 0x00D60304: 0x0000022A - "\x00\xf6\x03\x04\x00\x00\x02+" + // 0x00F60304: 0x0000022B - "\x00\xd5\x03\x04\x00\x00\x02," + // 0x00D50304: 0x0000022C - "\x00\xf5\x03\x04\x00\x00\x02-" + // 0x00F50304: 0x0000022D - "\x00O\x03\a\x00\x00\x02." + // 0x004F0307: 0x0000022E - "\x00o\x03\a\x00\x00\x02/" + // 0x006F0307: 0x0000022F - "\x02.\x03\x04\x00\x00\x020" + // 0x022E0304: 0x00000230 - "\x02/\x03\x04\x00\x00\x021" + // 0x022F0304: 0x00000231 - "\x00Y\x03\x04\x00\x00\x022" + // 0x00590304: 0x00000232 - "\x00y\x03\x04\x00\x00\x023" + // 0x00790304: 0x00000233 - "\x00\xa8\x03\x01\x00\x00\x03\x85" + // 0x00A80301: 0x00000385 - "\x03\x91\x03\x01\x00\x00\x03\x86" + // 0x03910301: 0x00000386 - "\x03\x95\x03\x01\x00\x00\x03\x88" + // 0x03950301: 0x00000388 - "\x03\x97\x03\x01\x00\x00\x03\x89" + // 0x03970301: 0x00000389 - "\x03\x99\x03\x01\x00\x00\x03\x8a" + // 0x03990301: 0x0000038A - "\x03\x9f\x03\x01\x00\x00\x03\x8c" + // 0x039F0301: 0x0000038C - "\x03\xa5\x03\x01\x00\x00\x03\x8e" + // 0x03A50301: 0x0000038E - "\x03\xa9\x03\x01\x00\x00\x03\x8f" + // 0x03A90301: 0x0000038F - "\x03\xca\x03\x01\x00\x00\x03\x90" + // 0x03CA0301: 0x00000390 - "\x03\x99\x03\b\x00\x00\x03\xaa" + // 0x03990308: 0x000003AA - "\x03\xa5\x03\b\x00\x00\x03\xab" + // 0x03A50308: 0x000003AB - "\x03\xb1\x03\x01\x00\x00\x03\xac" + // 0x03B10301: 0x000003AC - "\x03\xb5\x03\x01\x00\x00\x03\xad" + // 0x03B50301: 0x000003AD - "\x03\xb7\x03\x01\x00\x00\x03\xae" + // 0x03B70301: 0x000003AE - "\x03\xb9\x03\x01\x00\x00\x03\xaf" + // 0x03B90301: 0x000003AF - "\x03\xcb\x03\x01\x00\x00\x03\xb0" + // 0x03CB0301: 0x000003B0 - "\x03\xb9\x03\b\x00\x00\x03\xca" + // 0x03B90308: 0x000003CA - "\x03\xc5\x03\b\x00\x00\x03\xcb" + // 0x03C50308: 0x000003CB - "\x03\xbf\x03\x01\x00\x00\x03\xcc" + // 0x03BF0301: 0x000003CC - "\x03\xc5\x03\x01\x00\x00\x03\xcd" + // 0x03C50301: 0x000003CD - "\x03\xc9\x03\x01\x00\x00\x03\xce" + // 0x03C90301: 0x000003CE - "\x03\xd2\x03\x01\x00\x00\x03\xd3" + // 0x03D20301: 0x000003D3 - "\x03\xd2\x03\b\x00\x00\x03\xd4" + // 0x03D20308: 0x000003D4 - "\x04\x15\x03\x00\x00\x00\x04\x00" + // 0x04150300: 0x00000400 - "\x04\x15\x03\b\x00\x00\x04\x01" + // 0x04150308: 0x00000401 - "\x04\x13\x03\x01\x00\x00\x04\x03" + // 0x04130301: 0x00000403 - "\x04\x06\x03\b\x00\x00\x04\a" + // 0x04060308: 0x00000407 - "\x04\x1a\x03\x01\x00\x00\x04\f" + // 0x041A0301: 0x0000040C - "\x04\x18\x03\x00\x00\x00\x04\r" + // 0x04180300: 0x0000040D - "\x04#\x03\x06\x00\x00\x04\x0e" + // 0x04230306: 0x0000040E - "\x04\x18\x03\x06\x00\x00\x04\x19" + // 0x04180306: 0x00000419 - "\x048\x03\x06\x00\x00\x049" + // 0x04380306: 0x00000439 - "\x045\x03\x00\x00\x00\x04P" + // 0x04350300: 0x00000450 - "\x045\x03\b\x00\x00\x04Q" + // 0x04350308: 0x00000451 - "\x043\x03\x01\x00\x00\x04S" + // 0x04330301: 0x00000453 - "\x04V\x03\b\x00\x00\x04W" + // 0x04560308: 0x00000457 - "\x04:\x03\x01\x00\x00\x04\\" + // 0x043A0301: 0x0000045C - "\x048\x03\x00\x00\x00\x04]" + // 0x04380300: 0x0000045D - "\x04C\x03\x06\x00\x00\x04^" + // 0x04430306: 0x0000045E - "\x04t\x03\x0f\x00\x00\x04v" + // 0x0474030F: 0x00000476 - "\x04u\x03\x0f\x00\x00\x04w" + // 0x0475030F: 0x00000477 - "\x04\x16\x03\x06\x00\x00\x04\xc1" + // 0x04160306: 0x000004C1 - "\x046\x03\x06\x00\x00\x04\xc2" + // 0x04360306: 0x000004C2 - "\x04\x10\x03\x06\x00\x00\x04\xd0" + // 0x04100306: 0x000004D0 - "\x040\x03\x06\x00\x00\x04\xd1" + // 0x04300306: 0x000004D1 - "\x04\x10\x03\b\x00\x00\x04\xd2" + // 0x04100308: 0x000004D2 - "\x040\x03\b\x00\x00\x04\xd3" + // 0x04300308: 0x000004D3 - "\x04\x15\x03\x06\x00\x00\x04\xd6" + // 0x04150306: 0x000004D6 - "\x045\x03\x06\x00\x00\x04\xd7" + // 0x04350306: 0x000004D7 - "\x04\xd8\x03\b\x00\x00\x04\xda" + // 0x04D80308: 0x000004DA - "\x04\xd9\x03\b\x00\x00\x04\xdb" + // 0x04D90308: 0x000004DB - "\x04\x16\x03\b\x00\x00\x04\xdc" + // 0x04160308: 0x000004DC - "\x046\x03\b\x00\x00\x04\xdd" + // 0x04360308: 0x000004DD - "\x04\x17\x03\b\x00\x00\x04\xde" + // 0x04170308: 0x000004DE - "\x047\x03\b\x00\x00\x04\xdf" + // 0x04370308: 0x000004DF - "\x04\x18\x03\x04\x00\x00\x04\xe2" + // 0x04180304: 0x000004E2 - "\x048\x03\x04\x00\x00\x04\xe3" + // 0x04380304: 0x000004E3 - "\x04\x18\x03\b\x00\x00\x04\xe4" + // 0x04180308: 0x000004E4 - "\x048\x03\b\x00\x00\x04\xe5" + // 0x04380308: 0x000004E5 - "\x04\x1e\x03\b\x00\x00\x04\xe6" + // 0x041E0308: 0x000004E6 - "\x04>\x03\b\x00\x00\x04\xe7" + // 0x043E0308: 0x000004E7 - "\x04\xe8\x03\b\x00\x00\x04\xea" + // 0x04E80308: 0x000004EA - "\x04\xe9\x03\b\x00\x00\x04\xeb" + // 0x04E90308: 0x000004EB - "\x04-\x03\b\x00\x00\x04\xec" + // 0x042D0308: 0x000004EC - "\x04M\x03\b\x00\x00\x04\xed" + // 0x044D0308: 0x000004ED - "\x04#\x03\x04\x00\x00\x04\xee" + // 0x04230304: 0x000004EE - "\x04C\x03\x04\x00\x00\x04\xef" + // 0x04430304: 0x000004EF - "\x04#\x03\b\x00\x00\x04\xf0" + // 0x04230308: 0x000004F0 - "\x04C\x03\b\x00\x00\x04\xf1" + // 0x04430308: 0x000004F1 - "\x04#\x03\v\x00\x00\x04\xf2" + // 0x0423030B: 0x000004F2 - "\x04C\x03\v\x00\x00\x04\xf3" + // 0x0443030B: 0x000004F3 - "\x04'\x03\b\x00\x00\x04\xf4" + // 0x04270308: 0x000004F4 - "\x04G\x03\b\x00\x00\x04\xf5" + // 0x04470308: 0x000004F5 - "\x04+\x03\b\x00\x00\x04\xf8" + // 0x042B0308: 0x000004F8 - "\x04K\x03\b\x00\x00\x04\xf9" + // 0x044B0308: 0x000004F9 - "\x06'\x06S\x00\x00\x06\"" + // 0x06270653: 0x00000622 - "\x06'\x06T\x00\x00\x06#" + // 0x06270654: 0x00000623 - "\x06H\x06T\x00\x00\x06$" + // 0x06480654: 0x00000624 - "\x06'\x06U\x00\x00\x06%" + // 0x06270655: 0x00000625 - "\x06J\x06T\x00\x00\x06&" + // 0x064A0654: 0x00000626 - "\x06\xd5\x06T\x00\x00\x06\xc0" + // 0x06D50654: 0x000006C0 - "\x06\xc1\x06T\x00\x00\x06\xc2" + // 0x06C10654: 0x000006C2 - "\x06\xd2\x06T\x00\x00\x06\xd3" + // 0x06D20654: 0x000006D3 - "\t(\t<\x00\x00\t)" + // 0x0928093C: 0x00000929 - "\t0\t<\x00\x00\t1" + // 0x0930093C: 0x00000931 - "\t3\t<\x00\x00\t4" + // 0x0933093C: 0x00000934 - "\t\xc7\t\xbe\x00\x00\t\xcb" + // 0x09C709BE: 0x000009CB - "\t\xc7\t\xd7\x00\x00\t\xcc" + // 0x09C709D7: 0x000009CC - "\vG\vV\x00\x00\vH" + // 0x0B470B56: 0x00000B48 - "\vG\v>\x00\x00\vK" + // 0x0B470B3E: 0x00000B4B - "\vG\vW\x00\x00\vL" + // 0x0B470B57: 0x00000B4C - "\v\x92\v\xd7\x00\x00\v\x94" + // 0x0B920BD7: 0x00000B94 - "\v\xc6\v\xbe\x00\x00\v\xca" + // 0x0BC60BBE: 0x00000BCA - "\v\xc7\v\xbe\x00\x00\v\xcb" + // 0x0BC70BBE: 0x00000BCB - "\v\xc6\v\xd7\x00\x00\v\xcc" + // 0x0BC60BD7: 0x00000BCC - "\fF\fV\x00\x00\fH" + // 0x0C460C56: 0x00000C48 - "\f\xbf\f\xd5\x00\x00\f\xc0" + // 0x0CBF0CD5: 0x00000CC0 - "\f\xc6\f\xd5\x00\x00\f\xc7" + // 0x0CC60CD5: 0x00000CC7 - "\f\xc6\f\xd6\x00\x00\f\xc8" + // 0x0CC60CD6: 0x00000CC8 - "\f\xc6\f\xc2\x00\x00\f\xca" + // 0x0CC60CC2: 0x00000CCA - "\f\xca\f\xd5\x00\x00\f\xcb" + // 0x0CCA0CD5: 0x00000CCB - "\rF\r>\x00\x00\rJ" + // 0x0D460D3E: 0x00000D4A - "\rG\r>\x00\x00\rK" + // 0x0D470D3E: 0x00000D4B - "\rF\rW\x00\x00\rL" + // 0x0D460D57: 0x00000D4C - "\r\xd9\r\xca\x00\x00\r\xda" + // 0x0DD90DCA: 0x00000DDA - "\r\xd9\r\xcf\x00\x00\r\xdc" + // 0x0DD90DCF: 0x00000DDC - "\r\xdc\r\xca\x00\x00\r\xdd" + // 0x0DDC0DCA: 0x00000DDD - "\r\xd9\r\xdf\x00\x00\r\xde" + // 0x0DD90DDF: 0x00000DDE - "\x10%\x10.\x00\x00\x10&" + // 0x1025102E: 0x00001026 - "\x1b\x05\x1b5\x00\x00\x1b\x06" + // 0x1B051B35: 0x00001B06 - "\x1b\a\x1b5\x00\x00\x1b\b" + // 0x1B071B35: 0x00001B08 - "\x1b\t\x1b5\x00\x00\x1b\n" + // 0x1B091B35: 0x00001B0A - "\x1b\v\x1b5\x00\x00\x1b\f" + // 0x1B0B1B35: 0x00001B0C - "\x1b\r\x1b5\x00\x00\x1b\x0e" + // 0x1B0D1B35: 0x00001B0E - "\x1b\x11\x1b5\x00\x00\x1b\x12" + // 0x1B111B35: 0x00001B12 - "\x1b:\x1b5\x00\x00\x1b;" + // 0x1B3A1B35: 0x00001B3B - "\x1b<\x1b5\x00\x00\x1b=" + // 0x1B3C1B35: 0x00001B3D - "\x1b>\x1b5\x00\x00\x1b@" + // 0x1B3E1B35: 0x00001B40 - "\x1b?\x1b5\x00\x00\x1bA" + // 0x1B3F1B35: 0x00001B41 - "\x1bB\x1b5\x00\x00\x1bC" + // 0x1B421B35: 0x00001B43 - "\x00A\x03%\x00\x00\x1e\x00" + // 0x00410325: 0x00001E00 - "\x00a\x03%\x00\x00\x1e\x01" + // 0x00610325: 0x00001E01 - "\x00B\x03\a\x00\x00\x1e\x02" + // 0x00420307: 0x00001E02 - "\x00b\x03\a\x00\x00\x1e\x03" + // 0x00620307: 0x00001E03 - "\x00B\x03#\x00\x00\x1e\x04" + // 0x00420323: 0x00001E04 - "\x00b\x03#\x00\x00\x1e\x05" + // 0x00620323: 0x00001E05 - "\x00B\x031\x00\x00\x1e\x06" + // 0x00420331: 0x00001E06 - "\x00b\x031\x00\x00\x1e\a" + // 0x00620331: 0x00001E07 - "\x00\xc7\x03\x01\x00\x00\x1e\b" + // 0x00C70301: 0x00001E08 - "\x00\xe7\x03\x01\x00\x00\x1e\t" + // 0x00E70301: 0x00001E09 - "\x00D\x03\a\x00\x00\x1e\n" + // 0x00440307: 0x00001E0A - "\x00d\x03\a\x00\x00\x1e\v" + // 0x00640307: 0x00001E0B - "\x00D\x03#\x00\x00\x1e\f" + // 0x00440323: 0x00001E0C - "\x00d\x03#\x00\x00\x1e\r" + // 0x00640323: 0x00001E0D - "\x00D\x031\x00\x00\x1e\x0e" + // 0x00440331: 0x00001E0E - "\x00d\x031\x00\x00\x1e\x0f" + // 0x00640331: 0x00001E0F - "\x00D\x03'\x00\x00\x1e\x10" + // 0x00440327: 0x00001E10 - "\x00d\x03'\x00\x00\x1e\x11" + // 0x00640327: 0x00001E11 - "\x00D\x03-\x00\x00\x1e\x12" + // 0x0044032D: 0x00001E12 - "\x00d\x03-\x00\x00\x1e\x13" + // 0x0064032D: 0x00001E13 - "\x01\x12\x03\x00\x00\x00\x1e\x14" + // 0x01120300: 0x00001E14 - "\x01\x13\x03\x00\x00\x00\x1e\x15" + // 0x01130300: 0x00001E15 - "\x01\x12\x03\x01\x00\x00\x1e\x16" + // 0x01120301: 0x00001E16 - "\x01\x13\x03\x01\x00\x00\x1e\x17" + // 0x01130301: 0x00001E17 - "\x00E\x03-\x00\x00\x1e\x18" + // 0x0045032D: 0x00001E18 - "\x00e\x03-\x00\x00\x1e\x19" + // 0x0065032D: 0x00001E19 - "\x00E\x030\x00\x00\x1e\x1a" + // 0x00450330: 0x00001E1A - "\x00e\x030\x00\x00\x1e\x1b" + // 0x00650330: 0x00001E1B - "\x02(\x03\x06\x00\x00\x1e\x1c" + // 0x02280306: 0x00001E1C - "\x02)\x03\x06\x00\x00\x1e\x1d" + // 0x02290306: 0x00001E1D - "\x00F\x03\a\x00\x00\x1e\x1e" + // 0x00460307: 0x00001E1E - "\x00f\x03\a\x00\x00\x1e\x1f" + // 0x00660307: 0x00001E1F - "\x00G\x03\x04\x00\x00\x1e " + // 0x00470304: 0x00001E20 - "\x00g\x03\x04\x00\x00\x1e!" + // 0x00670304: 0x00001E21 - "\x00H\x03\a\x00\x00\x1e\"" + // 0x00480307: 0x00001E22 - "\x00h\x03\a\x00\x00\x1e#" + // 0x00680307: 0x00001E23 - "\x00H\x03#\x00\x00\x1e$" + // 0x00480323: 0x00001E24 - "\x00h\x03#\x00\x00\x1e%" + // 0x00680323: 0x00001E25 - "\x00H\x03\b\x00\x00\x1e&" + // 0x00480308: 0x00001E26 - "\x00h\x03\b\x00\x00\x1e'" + // 0x00680308: 0x00001E27 - "\x00H\x03'\x00\x00\x1e(" + // 0x00480327: 0x00001E28 - "\x00h\x03'\x00\x00\x1e)" + // 0x00680327: 0x00001E29 - "\x00H\x03.\x00\x00\x1e*" + // 0x0048032E: 0x00001E2A - "\x00h\x03.\x00\x00\x1e+" + // 0x0068032E: 0x00001E2B - "\x00I\x030\x00\x00\x1e," + // 0x00490330: 0x00001E2C - "\x00i\x030\x00\x00\x1e-" + // 0x00690330: 0x00001E2D - "\x00\xcf\x03\x01\x00\x00\x1e." + // 0x00CF0301: 0x00001E2E - "\x00\xef\x03\x01\x00\x00\x1e/" + // 0x00EF0301: 0x00001E2F - "\x00K\x03\x01\x00\x00\x1e0" + // 0x004B0301: 0x00001E30 - "\x00k\x03\x01\x00\x00\x1e1" + // 0x006B0301: 0x00001E31 - "\x00K\x03#\x00\x00\x1e2" + // 0x004B0323: 0x00001E32 - "\x00k\x03#\x00\x00\x1e3" + // 0x006B0323: 0x00001E33 - "\x00K\x031\x00\x00\x1e4" + // 0x004B0331: 0x00001E34 - "\x00k\x031\x00\x00\x1e5" + // 0x006B0331: 0x00001E35 - "\x00L\x03#\x00\x00\x1e6" + // 0x004C0323: 0x00001E36 - "\x00l\x03#\x00\x00\x1e7" + // 0x006C0323: 0x00001E37 - "\x1e6\x03\x04\x00\x00\x1e8" + // 0x1E360304: 0x00001E38 - "\x1e7\x03\x04\x00\x00\x1e9" + // 0x1E370304: 0x00001E39 - "\x00L\x031\x00\x00\x1e:" + // 0x004C0331: 0x00001E3A - "\x00l\x031\x00\x00\x1e;" + // 0x006C0331: 0x00001E3B - "\x00L\x03-\x00\x00\x1e<" + // 0x004C032D: 0x00001E3C - "\x00l\x03-\x00\x00\x1e=" + // 0x006C032D: 0x00001E3D - "\x00M\x03\x01\x00\x00\x1e>" + // 0x004D0301: 0x00001E3E - "\x00m\x03\x01\x00\x00\x1e?" + // 0x006D0301: 0x00001E3F - "\x00M\x03\a\x00\x00\x1e@" + // 0x004D0307: 0x00001E40 - "\x00m\x03\a\x00\x00\x1eA" + // 0x006D0307: 0x00001E41 - "\x00M\x03#\x00\x00\x1eB" + // 0x004D0323: 0x00001E42 - "\x00m\x03#\x00\x00\x1eC" + // 0x006D0323: 0x00001E43 - "\x00N\x03\a\x00\x00\x1eD" + // 0x004E0307: 0x00001E44 - "\x00n\x03\a\x00\x00\x1eE" + // 0x006E0307: 0x00001E45 - "\x00N\x03#\x00\x00\x1eF" + // 0x004E0323: 0x00001E46 - "\x00n\x03#\x00\x00\x1eG" + // 0x006E0323: 0x00001E47 - "\x00N\x031\x00\x00\x1eH" + // 0x004E0331: 0x00001E48 - "\x00n\x031\x00\x00\x1eI" + // 0x006E0331: 0x00001E49 - "\x00N\x03-\x00\x00\x1eJ" + // 0x004E032D: 0x00001E4A - "\x00n\x03-\x00\x00\x1eK" + // 0x006E032D: 0x00001E4B - "\x00\xd5\x03\x01\x00\x00\x1eL" + // 0x00D50301: 0x00001E4C - "\x00\xf5\x03\x01\x00\x00\x1eM" + // 0x00F50301: 0x00001E4D - "\x00\xd5\x03\b\x00\x00\x1eN" + // 0x00D50308: 0x00001E4E - "\x00\xf5\x03\b\x00\x00\x1eO" + // 0x00F50308: 0x00001E4F - "\x01L\x03\x00\x00\x00\x1eP" + // 0x014C0300: 0x00001E50 - "\x01M\x03\x00\x00\x00\x1eQ" + // 0x014D0300: 0x00001E51 - "\x01L\x03\x01\x00\x00\x1eR" + // 0x014C0301: 0x00001E52 - "\x01M\x03\x01\x00\x00\x1eS" + // 0x014D0301: 0x00001E53 - "\x00P\x03\x01\x00\x00\x1eT" + // 0x00500301: 0x00001E54 - "\x00p\x03\x01\x00\x00\x1eU" + // 0x00700301: 0x00001E55 - "\x00P\x03\a\x00\x00\x1eV" + // 0x00500307: 0x00001E56 - "\x00p\x03\a\x00\x00\x1eW" + // 0x00700307: 0x00001E57 - "\x00R\x03\a\x00\x00\x1eX" + // 0x00520307: 0x00001E58 - "\x00r\x03\a\x00\x00\x1eY" + // 0x00720307: 0x00001E59 - "\x00R\x03#\x00\x00\x1eZ" + // 0x00520323: 0x00001E5A - "\x00r\x03#\x00\x00\x1e[" + // 0x00720323: 0x00001E5B - "\x1eZ\x03\x04\x00\x00\x1e\\" + // 0x1E5A0304: 0x00001E5C - "\x1e[\x03\x04\x00\x00\x1e]" + // 0x1E5B0304: 0x00001E5D - "\x00R\x031\x00\x00\x1e^" + // 0x00520331: 0x00001E5E - "\x00r\x031\x00\x00\x1e_" + // 0x00720331: 0x00001E5F - "\x00S\x03\a\x00\x00\x1e`" + // 0x00530307: 0x00001E60 - "\x00s\x03\a\x00\x00\x1ea" + // 0x00730307: 0x00001E61 - "\x00S\x03#\x00\x00\x1eb" + // 0x00530323: 0x00001E62 - "\x00s\x03#\x00\x00\x1ec" + // 0x00730323: 0x00001E63 - "\x01Z\x03\a\x00\x00\x1ed" + // 0x015A0307: 0x00001E64 - "\x01[\x03\a\x00\x00\x1ee" + // 0x015B0307: 0x00001E65 - "\x01`\x03\a\x00\x00\x1ef" + // 0x01600307: 0x00001E66 - "\x01a\x03\a\x00\x00\x1eg" + // 0x01610307: 0x00001E67 - "\x1eb\x03\a\x00\x00\x1eh" + // 0x1E620307: 0x00001E68 - "\x1ec\x03\a\x00\x00\x1ei" + // 0x1E630307: 0x00001E69 - "\x00T\x03\a\x00\x00\x1ej" + // 0x00540307: 0x00001E6A - "\x00t\x03\a\x00\x00\x1ek" + // 0x00740307: 0x00001E6B - "\x00T\x03#\x00\x00\x1el" + // 0x00540323: 0x00001E6C - "\x00t\x03#\x00\x00\x1em" + // 0x00740323: 0x00001E6D - "\x00T\x031\x00\x00\x1en" + // 0x00540331: 0x00001E6E - "\x00t\x031\x00\x00\x1eo" + // 0x00740331: 0x00001E6F - "\x00T\x03-\x00\x00\x1ep" + // 0x0054032D: 0x00001E70 - "\x00t\x03-\x00\x00\x1eq" + // 0x0074032D: 0x00001E71 - "\x00U\x03$\x00\x00\x1er" + // 0x00550324: 0x00001E72 - "\x00u\x03$\x00\x00\x1es" + // 0x00750324: 0x00001E73 - "\x00U\x030\x00\x00\x1et" + // 0x00550330: 0x00001E74 - "\x00u\x030\x00\x00\x1eu" + // 0x00750330: 0x00001E75 - "\x00U\x03-\x00\x00\x1ev" + // 0x0055032D: 0x00001E76 - "\x00u\x03-\x00\x00\x1ew" + // 0x0075032D: 0x00001E77 - "\x01h\x03\x01\x00\x00\x1ex" + // 0x01680301: 0x00001E78 - "\x01i\x03\x01\x00\x00\x1ey" + // 0x01690301: 0x00001E79 - "\x01j\x03\b\x00\x00\x1ez" + // 0x016A0308: 0x00001E7A - "\x01k\x03\b\x00\x00\x1e{" + // 0x016B0308: 0x00001E7B - "\x00V\x03\x03\x00\x00\x1e|" + // 0x00560303: 0x00001E7C - "\x00v\x03\x03\x00\x00\x1e}" + // 0x00760303: 0x00001E7D - "\x00V\x03#\x00\x00\x1e~" + // 0x00560323: 0x00001E7E - "\x00v\x03#\x00\x00\x1e\x7f" + // 0x00760323: 0x00001E7F - "\x00W\x03\x00\x00\x00\x1e\x80" + // 0x00570300: 0x00001E80 - "\x00w\x03\x00\x00\x00\x1e\x81" + // 0x00770300: 0x00001E81 - "\x00W\x03\x01\x00\x00\x1e\x82" + // 0x00570301: 0x00001E82 - "\x00w\x03\x01\x00\x00\x1e\x83" + // 0x00770301: 0x00001E83 - "\x00W\x03\b\x00\x00\x1e\x84" + // 0x00570308: 0x00001E84 - "\x00w\x03\b\x00\x00\x1e\x85" + // 0x00770308: 0x00001E85 - "\x00W\x03\a\x00\x00\x1e\x86" + // 0x00570307: 0x00001E86 - "\x00w\x03\a\x00\x00\x1e\x87" + // 0x00770307: 0x00001E87 - "\x00W\x03#\x00\x00\x1e\x88" + // 0x00570323: 0x00001E88 - "\x00w\x03#\x00\x00\x1e\x89" + // 0x00770323: 0x00001E89 - "\x00X\x03\a\x00\x00\x1e\x8a" + // 0x00580307: 0x00001E8A - "\x00x\x03\a\x00\x00\x1e\x8b" + // 0x00780307: 0x00001E8B - "\x00X\x03\b\x00\x00\x1e\x8c" + // 0x00580308: 0x00001E8C - "\x00x\x03\b\x00\x00\x1e\x8d" + // 0x00780308: 0x00001E8D - "\x00Y\x03\a\x00\x00\x1e\x8e" + // 0x00590307: 0x00001E8E - "\x00y\x03\a\x00\x00\x1e\x8f" + // 0x00790307: 0x00001E8F - "\x00Z\x03\x02\x00\x00\x1e\x90" + // 0x005A0302: 0x00001E90 - "\x00z\x03\x02\x00\x00\x1e\x91" + // 0x007A0302: 0x00001E91 - "\x00Z\x03#\x00\x00\x1e\x92" + // 0x005A0323: 0x00001E92 - "\x00z\x03#\x00\x00\x1e\x93" + // 0x007A0323: 0x00001E93 - "\x00Z\x031\x00\x00\x1e\x94" + // 0x005A0331: 0x00001E94 - "\x00z\x031\x00\x00\x1e\x95" + // 0x007A0331: 0x00001E95 - "\x00h\x031\x00\x00\x1e\x96" + // 0x00680331: 0x00001E96 - "\x00t\x03\b\x00\x00\x1e\x97" + // 0x00740308: 0x00001E97 - "\x00w\x03\n\x00\x00\x1e\x98" + // 0x0077030A: 0x00001E98 - "\x00y\x03\n\x00\x00\x1e\x99" + // 0x0079030A: 0x00001E99 - "\x01\x7f\x03\a\x00\x00\x1e\x9b" + // 0x017F0307: 0x00001E9B - "\x00A\x03#\x00\x00\x1e\xa0" + // 0x00410323: 0x00001EA0 - "\x00a\x03#\x00\x00\x1e\xa1" + // 0x00610323: 0x00001EA1 - "\x00A\x03\t\x00\x00\x1e\xa2" + // 0x00410309: 0x00001EA2 - "\x00a\x03\t\x00\x00\x1e\xa3" + // 0x00610309: 0x00001EA3 - "\x00\xc2\x03\x01\x00\x00\x1e\xa4" + // 0x00C20301: 0x00001EA4 - "\x00\xe2\x03\x01\x00\x00\x1e\xa5" + // 0x00E20301: 0x00001EA5 - "\x00\xc2\x03\x00\x00\x00\x1e\xa6" + // 0x00C20300: 0x00001EA6 - "\x00\xe2\x03\x00\x00\x00\x1e\xa7" + // 0x00E20300: 0x00001EA7 - "\x00\xc2\x03\t\x00\x00\x1e\xa8" + // 0x00C20309: 0x00001EA8 - "\x00\xe2\x03\t\x00\x00\x1e\xa9" + // 0x00E20309: 0x00001EA9 - "\x00\xc2\x03\x03\x00\x00\x1e\xaa" + // 0x00C20303: 0x00001EAA - "\x00\xe2\x03\x03\x00\x00\x1e\xab" + // 0x00E20303: 0x00001EAB - "\x1e\xa0\x03\x02\x00\x00\x1e\xac" + // 0x1EA00302: 0x00001EAC - "\x1e\xa1\x03\x02\x00\x00\x1e\xad" + // 0x1EA10302: 0x00001EAD - "\x01\x02\x03\x01\x00\x00\x1e\xae" + // 0x01020301: 0x00001EAE - "\x01\x03\x03\x01\x00\x00\x1e\xaf" + // 0x01030301: 0x00001EAF - "\x01\x02\x03\x00\x00\x00\x1e\xb0" + // 0x01020300: 0x00001EB0 - "\x01\x03\x03\x00\x00\x00\x1e\xb1" + // 0x01030300: 0x00001EB1 - "\x01\x02\x03\t\x00\x00\x1e\xb2" + // 0x01020309: 0x00001EB2 - "\x01\x03\x03\t\x00\x00\x1e\xb3" + // 0x01030309: 0x00001EB3 - "\x01\x02\x03\x03\x00\x00\x1e\xb4" + // 0x01020303: 0x00001EB4 - "\x01\x03\x03\x03\x00\x00\x1e\xb5" + // 0x01030303: 0x00001EB5 - "\x1e\xa0\x03\x06\x00\x00\x1e\xb6" + // 0x1EA00306: 0x00001EB6 - "\x1e\xa1\x03\x06\x00\x00\x1e\xb7" + // 0x1EA10306: 0x00001EB7 - "\x00E\x03#\x00\x00\x1e\xb8" + // 0x00450323: 0x00001EB8 - "\x00e\x03#\x00\x00\x1e\xb9" + // 0x00650323: 0x00001EB9 - "\x00E\x03\t\x00\x00\x1e\xba" + // 0x00450309: 0x00001EBA - "\x00e\x03\t\x00\x00\x1e\xbb" + // 0x00650309: 0x00001EBB - "\x00E\x03\x03\x00\x00\x1e\xbc" + // 0x00450303: 0x00001EBC - "\x00e\x03\x03\x00\x00\x1e\xbd" + // 0x00650303: 0x00001EBD - "\x00\xca\x03\x01\x00\x00\x1e\xbe" + // 0x00CA0301: 0x00001EBE - "\x00\xea\x03\x01\x00\x00\x1e\xbf" + // 0x00EA0301: 0x00001EBF - "\x00\xca\x03\x00\x00\x00\x1e\xc0" + // 0x00CA0300: 0x00001EC0 - "\x00\xea\x03\x00\x00\x00\x1e\xc1" + // 0x00EA0300: 0x00001EC1 - "\x00\xca\x03\t\x00\x00\x1e\xc2" + // 0x00CA0309: 0x00001EC2 - "\x00\xea\x03\t\x00\x00\x1e\xc3" + // 0x00EA0309: 0x00001EC3 - "\x00\xca\x03\x03\x00\x00\x1e\xc4" + // 0x00CA0303: 0x00001EC4 - "\x00\xea\x03\x03\x00\x00\x1e\xc5" + // 0x00EA0303: 0x00001EC5 - "\x1e\xb8\x03\x02\x00\x00\x1e\xc6" + // 0x1EB80302: 0x00001EC6 - "\x1e\xb9\x03\x02\x00\x00\x1e\xc7" + // 0x1EB90302: 0x00001EC7 - "\x00I\x03\t\x00\x00\x1e\xc8" + // 0x00490309: 0x00001EC8 - "\x00i\x03\t\x00\x00\x1e\xc9" + // 0x00690309: 0x00001EC9 - "\x00I\x03#\x00\x00\x1e\xca" + // 0x00490323: 0x00001ECA - "\x00i\x03#\x00\x00\x1e\xcb" + // 0x00690323: 0x00001ECB - "\x00O\x03#\x00\x00\x1e\xcc" + // 0x004F0323: 0x00001ECC - "\x00o\x03#\x00\x00\x1e\xcd" + // 0x006F0323: 0x00001ECD - "\x00O\x03\t\x00\x00\x1e\xce" + // 0x004F0309: 0x00001ECE - "\x00o\x03\t\x00\x00\x1e\xcf" + // 0x006F0309: 0x00001ECF - "\x00\xd4\x03\x01\x00\x00\x1e\xd0" + // 0x00D40301: 0x00001ED0 - "\x00\xf4\x03\x01\x00\x00\x1e\xd1" + // 0x00F40301: 0x00001ED1 - "\x00\xd4\x03\x00\x00\x00\x1e\xd2" + // 0x00D40300: 0x00001ED2 - "\x00\xf4\x03\x00\x00\x00\x1e\xd3" + // 0x00F40300: 0x00001ED3 - "\x00\xd4\x03\t\x00\x00\x1e\xd4" + // 0x00D40309: 0x00001ED4 - "\x00\xf4\x03\t\x00\x00\x1e\xd5" + // 0x00F40309: 0x00001ED5 - "\x00\xd4\x03\x03\x00\x00\x1e\xd6" + // 0x00D40303: 0x00001ED6 - "\x00\xf4\x03\x03\x00\x00\x1e\xd7" + // 0x00F40303: 0x00001ED7 - "\x1e\xcc\x03\x02\x00\x00\x1e\xd8" + // 0x1ECC0302: 0x00001ED8 - "\x1e\xcd\x03\x02\x00\x00\x1e\xd9" + // 0x1ECD0302: 0x00001ED9 - "\x01\xa0\x03\x01\x00\x00\x1e\xda" + // 0x01A00301: 0x00001EDA - "\x01\xa1\x03\x01\x00\x00\x1e\xdb" + // 0x01A10301: 0x00001EDB - "\x01\xa0\x03\x00\x00\x00\x1e\xdc" + // 0x01A00300: 0x00001EDC - "\x01\xa1\x03\x00\x00\x00\x1e\xdd" + // 0x01A10300: 0x00001EDD - "\x01\xa0\x03\t\x00\x00\x1e\xde" + // 0x01A00309: 0x00001EDE - "\x01\xa1\x03\t\x00\x00\x1e\xdf" + // 0x01A10309: 0x00001EDF - "\x01\xa0\x03\x03\x00\x00\x1e\xe0" + // 0x01A00303: 0x00001EE0 - "\x01\xa1\x03\x03\x00\x00\x1e\xe1" + // 0x01A10303: 0x00001EE1 - "\x01\xa0\x03#\x00\x00\x1e\xe2" + // 0x01A00323: 0x00001EE2 - "\x01\xa1\x03#\x00\x00\x1e\xe3" + // 0x01A10323: 0x00001EE3 - "\x00U\x03#\x00\x00\x1e\xe4" + // 0x00550323: 0x00001EE4 - "\x00u\x03#\x00\x00\x1e\xe5" + // 0x00750323: 0x00001EE5 - "\x00U\x03\t\x00\x00\x1e\xe6" + // 0x00550309: 0x00001EE6 - "\x00u\x03\t\x00\x00\x1e\xe7" + // 0x00750309: 0x00001EE7 - "\x01\xaf\x03\x01\x00\x00\x1e\xe8" + // 0x01AF0301: 0x00001EE8 - "\x01\xb0\x03\x01\x00\x00\x1e\xe9" + // 0x01B00301: 0x00001EE9 - "\x01\xaf\x03\x00\x00\x00\x1e\xea" + // 0x01AF0300: 0x00001EEA - "\x01\xb0\x03\x00\x00\x00\x1e\xeb" + // 0x01B00300: 0x00001EEB - "\x01\xaf\x03\t\x00\x00\x1e\xec" + // 0x01AF0309: 0x00001EEC - "\x01\xb0\x03\t\x00\x00\x1e\xed" + // 0x01B00309: 0x00001EED - "\x01\xaf\x03\x03\x00\x00\x1e\xee" + // 0x01AF0303: 0x00001EEE - "\x01\xb0\x03\x03\x00\x00\x1e\xef" + // 0x01B00303: 0x00001EEF - "\x01\xaf\x03#\x00\x00\x1e\xf0" + // 0x01AF0323: 0x00001EF0 - "\x01\xb0\x03#\x00\x00\x1e\xf1" + // 0x01B00323: 0x00001EF1 - "\x00Y\x03\x00\x00\x00\x1e\xf2" + // 0x00590300: 0x00001EF2 - "\x00y\x03\x00\x00\x00\x1e\xf3" + // 0x00790300: 0x00001EF3 - "\x00Y\x03#\x00\x00\x1e\xf4" + // 0x00590323: 0x00001EF4 - "\x00y\x03#\x00\x00\x1e\xf5" + // 0x00790323: 0x00001EF5 - "\x00Y\x03\t\x00\x00\x1e\xf6" + // 0x00590309: 0x00001EF6 - "\x00y\x03\t\x00\x00\x1e\xf7" + // 0x00790309: 0x00001EF7 - "\x00Y\x03\x03\x00\x00\x1e\xf8" + // 0x00590303: 0x00001EF8 - "\x00y\x03\x03\x00\x00\x1e\xf9" + // 0x00790303: 0x00001EF9 - "\x03\xb1\x03\x13\x00\x00\x1f\x00" + // 0x03B10313: 0x00001F00 - "\x03\xb1\x03\x14\x00\x00\x1f\x01" + // 0x03B10314: 0x00001F01 - "\x1f\x00\x03\x00\x00\x00\x1f\x02" + // 0x1F000300: 0x00001F02 - "\x1f\x01\x03\x00\x00\x00\x1f\x03" + // 0x1F010300: 0x00001F03 - "\x1f\x00\x03\x01\x00\x00\x1f\x04" + // 0x1F000301: 0x00001F04 - "\x1f\x01\x03\x01\x00\x00\x1f\x05" + // 0x1F010301: 0x00001F05 - "\x1f\x00\x03B\x00\x00\x1f\x06" + // 0x1F000342: 0x00001F06 - "\x1f\x01\x03B\x00\x00\x1f\a" + // 0x1F010342: 0x00001F07 - "\x03\x91\x03\x13\x00\x00\x1f\b" + // 0x03910313: 0x00001F08 - "\x03\x91\x03\x14\x00\x00\x1f\t" + // 0x03910314: 0x00001F09 - "\x1f\b\x03\x00\x00\x00\x1f\n" + // 0x1F080300: 0x00001F0A - "\x1f\t\x03\x00\x00\x00\x1f\v" + // 0x1F090300: 0x00001F0B - "\x1f\b\x03\x01\x00\x00\x1f\f" + // 0x1F080301: 0x00001F0C - "\x1f\t\x03\x01\x00\x00\x1f\r" + // 0x1F090301: 0x00001F0D - "\x1f\b\x03B\x00\x00\x1f\x0e" + // 0x1F080342: 0x00001F0E - "\x1f\t\x03B\x00\x00\x1f\x0f" + // 0x1F090342: 0x00001F0F - "\x03\xb5\x03\x13\x00\x00\x1f\x10" + // 0x03B50313: 0x00001F10 - "\x03\xb5\x03\x14\x00\x00\x1f\x11" + // 0x03B50314: 0x00001F11 - "\x1f\x10\x03\x00\x00\x00\x1f\x12" + // 0x1F100300: 0x00001F12 - "\x1f\x11\x03\x00\x00\x00\x1f\x13" + // 0x1F110300: 0x00001F13 - "\x1f\x10\x03\x01\x00\x00\x1f\x14" + // 0x1F100301: 0x00001F14 - "\x1f\x11\x03\x01\x00\x00\x1f\x15" + // 0x1F110301: 0x00001F15 - "\x03\x95\x03\x13\x00\x00\x1f\x18" + // 0x03950313: 0x00001F18 - "\x03\x95\x03\x14\x00\x00\x1f\x19" + // 0x03950314: 0x00001F19 - "\x1f\x18\x03\x00\x00\x00\x1f\x1a" + // 0x1F180300: 0x00001F1A - "\x1f\x19\x03\x00\x00\x00\x1f\x1b" + // 0x1F190300: 0x00001F1B - "\x1f\x18\x03\x01\x00\x00\x1f\x1c" + // 0x1F180301: 0x00001F1C - "\x1f\x19\x03\x01\x00\x00\x1f\x1d" + // 0x1F190301: 0x00001F1D - "\x03\xb7\x03\x13\x00\x00\x1f " + // 0x03B70313: 0x00001F20 - "\x03\xb7\x03\x14\x00\x00\x1f!" + // 0x03B70314: 0x00001F21 - "\x1f \x03\x00\x00\x00\x1f\"" + // 0x1F200300: 0x00001F22 - "\x1f!\x03\x00\x00\x00\x1f#" + // 0x1F210300: 0x00001F23 - "\x1f \x03\x01\x00\x00\x1f$" + // 0x1F200301: 0x00001F24 - "\x1f!\x03\x01\x00\x00\x1f%" + // 0x1F210301: 0x00001F25 - "\x1f \x03B\x00\x00\x1f&" + // 0x1F200342: 0x00001F26 - "\x1f!\x03B\x00\x00\x1f'" + // 0x1F210342: 0x00001F27 - "\x03\x97\x03\x13\x00\x00\x1f(" + // 0x03970313: 0x00001F28 - "\x03\x97\x03\x14\x00\x00\x1f)" + // 0x03970314: 0x00001F29 - "\x1f(\x03\x00\x00\x00\x1f*" + // 0x1F280300: 0x00001F2A - "\x1f)\x03\x00\x00\x00\x1f+" + // 0x1F290300: 0x00001F2B - "\x1f(\x03\x01\x00\x00\x1f," + // 0x1F280301: 0x00001F2C - "\x1f)\x03\x01\x00\x00\x1f-" + // 0x1F290301: 0x00001F2D - "\x1f(\x03B\x00\x00\x1f." + // 0x1F280342: 0x00001F2E - "\x1f)\x03B\x00\x00\x1f/" + // 0x1F290342: 0x00001F2F - "\x03\xb9\x03\x13\x00\x00\x1f0" + // 0x03B90313: 0x00001F30 - "\x03\xb9\x03\x14\x00\x00\x1f1" + // 0x03B90314: 0x00001F31 - "\x1f0\x03\x00\x00\x00\x1f2" + // 0x1F300300: 0x00001F32 - "\x1f1\x03\x00\x00\x00\x1f3" + // 0x1F310300: 0x00001F33 - "\x1f0\x03\x01\x00\x00\x1f4" + // 0x1F300301: 0x00001F34 - "\x1f1\x03\x01\x00\x00\x1f5" + // 0x1F310301: 0x00001F35 - "\x1f0\x03B\x00\x00\x1f6" + // 0x1F300342: 0x00001F36 - "\x1f1\x03B\x00\x00\x1f7" + // 0x1F310342: 0x00001F37 - "\x03\x99\x03\x13\x00\x00\x1f8" + // 0x03990313: 0x00001F38 - "\x03\x99\x03\x14\x00\x00\x1f9" + // 0x03990314: 0x00001F39 - "\x1f8\x03\x00\x00\x00\x1f:" + // 0x1F380300: 0x00001F3A - "\x1f9\x03\x00\x00\x00\x1f;" + // 0x1F390300: 0x00001F3B - "\x1f8\x03\x01\x00\x00\x1f<" + // 0x1F380301: 0x00001F3C - "\x1f9\x03\x01\x00\x00\x1f=" + // 0x1F390301: 0x00001F3D - "\x1f8\x03B\x00\x00\x1f>" + // 0x1F380342: 0x00001F3E - "\x1f9\x03B\x00\x00\x1f?" + // 0x1F390342: 0x00001F3F - "\x03\xbf\x03\x13\x00\x00\x1f@" + // 0x03BF0313: 0x00001F40 - "\x03\xbf\x03\x14\x00\x00\x1fA" + // 0x03BF0314: 0x00001F41 - "\x1f@\x03\x00\x00\x00\x1fB" + // 0x1F400300: 0x00001F42 - "\x1fA\x03\x00\x00\x00\x1fC" + // 0x1F410300: 0x00001F43 - "\x1f@\x03\x01\x00\x00\x1fD" + // 0x1F400301: 0x00001F44 - "\x1fA\x03\x01\x00\x00\x1fE" + // 0x1F410301: 0x00001F45 - "\x03\x9f\x03\x13\x00\x00\x1fH" + // 0x039F0313: 0x00001F48 - "\x03\x9f\x03\x14\x00\x00\x1fI" + // 0x039F0314: 0x00001F49 - "\x1fH\x03\x00\x00\x00\x1fJ" + // 0x1F480300: 0x00001F4A - "\x1fI\x03\x00\x00\x00\x1fK" + // 0x1F490300: 0x00001F4B - "\x1fH\x03\x01\x00\x00\x1fL" + // 0x1F480301: 0x00001F4C - "\x1fI\x03\x01\x00\x00\x1fM" + // 0x1F490301: 0x00001F4D - "\x03\xc5\x03\x13\x00\x00\x1fP" + // 0x03C50313: 0x00001F50 - "\x03\xc5\x03\x14\x00\x00\x1fQ" + // 0x03C50314: 0x00001F51 - "\x1fP\x03\x00\x00\x00\x1fR" + // 0x1F500300: 0x00001F52 - "\x1fQ\x03\x00\x00\x00\x1fS" + // 0x1F510300: 0x00001F53 - "\x1fP\x03\x01\x00\x00\x1fT" + // 0x1F500301: 0x00001F54 - "\x1fQ\x03\x01\x00\x00\x1fU" + // 0x1F510301: 0x00001F55 - "\x1fP\x03B\x00\x00\x1fV" + // 0x1F500342: 0x00001F56 - "\x1fQ\x03B\x00\x00\x1fW" + // 0x1F510342: 0x00001F57 - "\x03\xa5\x03\x14\x00\x00\x1fY" + // 0x03A50314: 0x00001F59 - "\x1fY\x03\x00\x00\x00\x1f[" + // 0x1F590300: 0x00001F5B - "\x1fY\x03\x01\x00\x00\x1f]" + // 0x1F590301: 0x00001F5D - "\x1fY\x03B\x00\x00\x1f_" + // 0x1F590342: 0x00001F5F - "\x03\xc9\x03\x13\x00\x00\x1f`" + // 0x03C90313: 0x00001F60 - "\x03\xc9\x03\x14\x00\x00\x1fa" + // 0x03C90314: 0x00001F61 - "\x1f`\x03\x00\x00\x00\x1fb" + // 0x1F600300: 0x00001F62 - "\x1fa\x03\x00\x00\x00\x1fc" + // 0x1F610300: 0x00001F63 - "\x1f`\x03\x01\x00\x00\x1fd" + // 0x1F600301: 0x00001F64 - "\x1fa\x03\x01\x00\x00\x1fe" + // 0x1F610301: 0x00001F65 - "\x1f`\x03B\x00\x00\x1ff" + // 0x1F600342: 0x00001F66 - "\x1fa\x03B\x00\x00\x1fg" + // 0x1F610342: 0x00001F67 - "\x03\xa9\x03\x13\x00\x00\x1fh" + // 0x03A90313: 0x00001F68 - "\x03\xa9\x03\x14\x00\x00\x1fi" + // 0x03A90314: 0x00001F69 - "\x1fh\x03\x00\x00\x00\x1fj" + // 0x1F680300: 0x00001F6A - "\x1fi\x03\x00\x00\x00\x1fk" + // 0x1F690300: 0x00001F6B - "\x1fh\x03\x01\x00\x00\x1fl" + // 0x1F680301: 0x00001F6C - "\x1fi\x03\x01\x00\x00\x1fm" + // 0x1F690301: 0x00001F6D - "\x1fh\x03B\x00\x00\x1fn" + // 0x1F680342: 0x00001F6E - "\x1fi\x03B\x00\x00\x1fo" + // 0x1F690342: 0x00001F6F - "\x03\xb1\x03\x00\x00\x00\x1fp" + // 0x03B10300: 0x00001F70 - "\x03\xb5\x03\x00\x00\x00\x1fr" + // 0x03B50300: 0x00001F72 - "\x03\xb7\x03\x00\x00\x00\x1ft" + // 0x03B70300: 0x00001F74 - "\x03\xb9\x03\x00\x00\x00\x1fv" + // 0x03B90300: 0x00001F76 - "\x03\xbf\x03\x00\x00\x00\x1fx" + // 0x03BF0300: 0x00001F78 - "\x03\xc5\x03\x00\x00\x00\x1fz" + // 0x03C50300: 0x00001F7A - "\x03\xc9\x03\x00\x00\x00\x1f|" + // 0x03C90300: 0x00001F7C - "\x1f\x00\x03E\x00\x00\x1f\x80" + // 0x1F000345: 0x00001F80 - "\x1f\x01\x03E\x00\x00\x1f\x81" + // 0x1F010345: 0x00001F81 - "\x1f\x02\x03E\x00\x00\x1f\x82" + // 0x1F020345: 0x00001F82 - "\x1f\x03\x03E\x00\x00\x1f\x83" + // 0x1F030345: 0x00001F83 - "\x1f\x04\x03E\x00\x00\x1f\x84" + // 0x1F040345: 0x00001F84 - "\x1f\x05\x03E\x00\x00\x1f\x85" + // 0x1F050345: 0x00001F85 - "\x1f\x06\x03E\x00\x00\x1f\x86" + // 0x1F060345: 0x00001F86 - "\x1f\a\x03E\x00\x00\x1f\x87" + // 0x1F070345: 0x00001F87 - "\x1f\b\x03E\x00\x00\x1f\x88" + // 0x1F080345: 0x00001F88 - "\x1f\t\x03E\x00\x00\x1f\x89" + // 0x1F090345: 0x00001F89 - "\x1f\n\x03E\x00\x00\x1f\x8a" + // 0x1F0A0345: 0x00001F8A - "\x1f\v\x03E\x00\x00\x1f\x8b" + // 0x1F0B0345: 0x00001F8B - "\x1f\f\x03E\x00\x00\x1f\x8c" + // 0x1F0C0345: 0x00001F8C - "\x1f\r\x03E\x00\x00\x1f\x8d" + // 0x1F0D0345: 0x00001F8D - "\x1f\x0e\x03E\x00\x00\x1f\x8e" + // 0x1F0E0345: 0x00001F8E - "\x1f\x0f\x03E\x00\x00\x1f\x8f" + // 0x1F0F0345: 0x00001F8F - "\x1f \x03E\x00\x00\x1f\x90" + // 0x1F200345: 0x00001F90 - "\x1f!\x03E\x00\x00\x1f\x91" + // 0x1F210345: 0x00001F91 - "\x1f\"\x03E\x00\x00\x1f\x92" + // 0x1F220345: 0x00001F92 - "\x1f#\x03E\x00\x00\x1f\x93" + // 0x1F230345: 0x00001F93 - "\x1f$\x03E\x00\x00\x1f\x94" + // 0x1F240345: 0x00001F94 - "\x1f%\x03E\x00\x00\x1f\x95" + // 0x1F250345: 0x00001F95 - "\x1f&\x03E\x00\x00\x1f\x96" + // 0x1F260345: 0x00001F96 - "\x1f'\x03E\x00\x00\x1f\x97" + // 0x1F270345: 0x00001F97 - "\x1f(\x03E\x00\x00\x1f\x98" + // 0x1F280345: 0x00001F98 - "\x1f)\x03E\x00\x00\x1f\x99" + // 0x1F290345: 0x00001F99 - "\x1f*\x03E\x00\x00\x1f\x9a" + // 0x1F2A0345: 0x00001F9A - "\x1f+\x03E\x00\x00\x1f\x9b" + // 0x1F2B0345: 0x00001F9B - "\x1f,\x03E\x00\x00\x1f\x9c" + // 0x1F2C0345: 0x00001F9C - "\x1f-\x03E\x00\x00\x1f\x9d" + // 0x1F2D0345: 0x00001F9D - "\x1f.\x03E\x00\x00\x1f\x9e" + // 0x1F2E0345: 0x00001F9E - "\x1f/\x03E\x00\x00\x1f\x9f" + // 0x1F2F0345: 0x00001F9F - "\x1f`\x03E\x00\x00\x1f\xa0" + // 0x1F600345: 0x00001FA0 - "\x1fa\x03E\x00\x00\x1f\xa1" + // 0x1F610345: 0x00001FA1 - "\x1fb\x03E\x00\x00\x1f\xa2" + // 0x1F620345: 0x00001FA2 - "\x1fc\x03E\x00\x00\x1f\xa3" + // 0x1F630345: 0x00001FA3 - "\x1fd\x03E\x00\x00\x1f\xa4" + // 0x1F640345: 0x00001FA4 - "\x1fe\x03E\x00\x00\x1f\xa5" + // 0x1F650345: 0x00001FA5 - "\x1ff\x03E\x00\x00\x1f\xa6" + // 0x1F660345: 0x00001FA6 - "\x1fg\x03E\x00\x00\x1f\xa7" + // 0x1F670345: 0x00001FA7 - "\x1fh\x03E\x00\x00\x1f\xa8" + // 0x1F680345: 0x00001FA8 - "\x1fi\x03E\x00\x00\x1f\xa9" + // 0x1F690345: 0x00001FA9 - "\x1fj\x03E\x00\x00\x1f\xaa" + // 0x1F6A0345: 0x00001FAA - "\x1fk\x03E\x00\x00\x1f\xab" + // 0x1F6B0345: 0x00001FAB - "\x1fl\x03E\x00\x00\x1f\xac" + // 0x1F6C0345: 0x00001FAC - "\x1fm\x03E\x00\x00\x1f\xad" + // 0x1F6D0345: 0x00001FAD - "\x1fn\x03E\x00\x00\x1f\xae" + // 0x1F6E0345: 0x00001FAE - "\x1fo\x03E\x00\x00\x1f\xaf" + // 0x1F6F0345: 0x00001FAF - "\x03\xb1\x03\x06\x00\x00\x1f\xb0" + // 0x03B10306: 0x00001FB0 - "\x03\xb1\x03\x04\x00\x00\x1f\xb1" + // 0x03B10304: 0x00001FB1 - "\x1fp\x03E\x00\x00\x1f\xb2" + // 0x1F700345: 0x00001FB2 - "\x03\xb1\x03E\x00\x00\x1f\xb3" + // 0x03B10345: 0x00001FB3 - "\x03\xac\x03E\x00\x00\x1f\xb4" + // 0x03AC0345: 0x00001FB4 - "\x03\xb1\x03B\x00\x00\x1f\xb6" + // 0x03B10342: 0x00001FB6 - "\x1f\xb6\x03E\x00\x00\x1f\xb7" + // 0x1FB60345: 0x00001FB7 - "\x03\x91\x03\x06\x00\x00\x1f\xb8" + // 0x03910306: 0x00001FB8 - "\x03\x91\x03\x04\x00\x00\x1f\xb9" + // 0x03910304: 0x00001FB9 - "\x03\x91\x03\x00\x00\x00\x1f\xba" + // 0x03910300: 0x00001FBA - "\x03\x91\x03E\x00\x00\x1f\xbc" + // 0x03910345: 0x00001FBC - "\x00\xa8\x03B\x00\x00\x1f\xc1" + // 0x00A80342: 0x00001FC1 - "\x1ft\x03E\x00\x00\x1f\xc2" + // 0x1F740345: 0x00001FC2 - "\x03\xb7\x03E\x00\x00\x1f\xc3" + // 0x03B70345: 0x00001FC3 - "\x03\xae\x03E\x00\x00\x1f\xc4" + // 0x03AE0345: 0x00001FC4 - "\x03\xb7\x03B\x00\x00\x1f\xc6" + // 0x03B70342: 0x00001FC6 - "\x1f\xc6\x03E\x00\x00\x1f\xc7" + // 0x1FC60345: 0x00001FC7 - "\x03\x95\x03\x00\x00\x00\x1f\xc8" + // 0x03950300: 0x00001FC8 - "\x03\x97\x03\x00\x00\x00\x1f\xca" + // 0x03970300: 0x00001FCA - "\x03\x97\x03E\x00\x00\x1f\xcc" + // 0x03970345: 0x00001FCC - "\x1f\xbf\x03\x00\x00\x00\x1f\xcd" + // 0x1FBF0300: 0x00001FCD - "\x1f\xbf\x03\x01\x00\x00\x1f\xce" + // 0x1FBF0301: 0x00001FCE - "\x1f\xbf\x03B\x00\x00\x1f\xcf" + // 0x1FBF0342: 0x00001FCF - "\x03\xb9\x03\x06\x00\x00\x1f\xd0" + // 0x03B90306: 0x00001FD0 - "\x03\xb9\x03\x04\x00\x00\x1f\xd1" + // 0x03B90304: 0x00001FD1 - "\x03\xca\x03\x00\x00\x00\x1f\xd2" + // 0x03CA0300: 0x00001FD2 - "\x03\xb9\x03B\x00\x00\x1f\xd6" + // 0x03B90342: 0x00001FD6 - "\x03\xca\x03B\x00\x00\x1f\xd7" + // 0x03CA0342: 0x00001FD7 - "\x03\x99\x03\x06\x00\x00\x1f\xd8" + // 0x03990306: 0x00001FD8 - "\x03\x99\x03\x04\x00\x00\x1f\xd9" + // 0x03990304: 0x00001FD9 - "\x03\x99\x03\x00\x00\x00\x1f\xda" + // 0x03990300: 0x00001FDA - "\x1f\xfe\x03\x00\x00\x00\x1f\xdd" + // 0x1FFE0300: 0x00001FDD - "\x1f\xfe\x03\x01\x00\x00\x1f\xde" + // 0x1FFE0301: 0x00001FDE - "\x1f\xfe\x03B\x00\x00\x1f\xdf" + // 0x1FFE0342: 0x00001FDF - "\x03\xc5\x03\x06\x00\x00\x1f\xe0" + // 0x03C50306: 0x00001FE0 - "\x03\xc5\x03\x04\x00\x00\x1f\xe1" + // 0x03C50304: 0x00001FE1 - "\x03\xcb\x03\x00\x00\x00\x1f\xe2" + // 0x03CB0300: 0x00001FE2 - "\x03\xc1\x03\x13\x00\x00\x1f\xe4" + // 0x03C10313: 0x00001FE4 - "\x03\xc1\x03\x14\x00\x00\x1f\xe5" + // 0x03C10314: 0x00001FE5 - "\x03\xc5\x03B\x00\x00\x1f\xe6" + // 0x03C50342: 0x00001FE6 - "\x03\xcb\x03B\x00\x00\x1f\xe7" + // 0x03CB0342: 0x00001FE7 - "\x03\xa5\x03\x06\x00\x00\x1f\xe8" + // 0x03A50306: 0x00001FE8 - "\x03\xa5\x03\x04\x00\x00\x1f\xe9" + // 0x03A50304: 0x00001FE9 - "\x03\xa5\x03\x00\x00\x00\x1f\xea" + // 0x03A50300: 0x00001FEA - "\x03\xa1\x03\x14\x00\x00\x1f\xec" + // 0x03A10314: 0x00001FEC - "\x00\xa8\x03\x00\x00\x00\x1f\xed" + // 0x00A80300: 0x00001FED - "\x1f|\x03E\x00\x00\x1f\xf2" + // 0x1F7C0345: 0x00001FF2 - "\x03\xc9\x03E\x00\x00\x1f\xf3" + // 0x03C90345: 0x00001FF3 - "\x03\xce\x03E\x00\x00\x1f\xf4" + // 0x03CE0345: 0x00001FF4 - "\x03\xc9\x03B\x00\x00\x1f\xf6" + // 0x03C90342: 0x00001FF6 - "\x1f\xf6\x03E\x00\x00\x1f\xf7" + // 0x1FF60345: 0x00001FF7 - "\x03\x9f\x03\x00\x00\x00\x1f\xf8" + // 0x039F0300: 0x00001FF8 - "\x03\xa9\x03\x00\x00\x00\x1f\xfa" + // 0x03A90300: 0x00001FFA - "\x03\xa9\x03E\x00\x00\x1f\xfc" + // 0x03A90345: 0x00001FFC - "!\x90\x038\x00\x00!\x9a" + // 0x21900338: 0x0000219A - "!\x92\x038\x00\x00!\x9b" + // 0x21920338: 0x0000219B - "!\x94\x038\x00\x00!\xae" + // 0x21940338: 0x000021AE - "!\xd0\x038\x00\x00!\xcd" + // 0x21D00338: 0x000021CD - "!\xd4\x038\x00\x00!\xce" + // 0x21D40338: 0x000021CE - "!\xd2\x038\x00\x00!\xcf" + // 0x21D20338: 0x000021CF - "\"\x03\x038\x00\x00\"\x04" + // 0x22030338: 0x00002204 - "\"\b\x038\x00\x00\"\t" + // 0x22080338: 0x00002209 - "\"\v\x038\x00\x00\"\f" + // 0x220B0338: 0x0000220C - "\"#\x038\x00\x00\"$" + // 0x22230338: 0x00002224 - "\"%\x038\x00\x00\"&" + // 0x22250338: 0x00002226 - "\"<\x038\x00\x00\"A" + // 0x223C0338: 0x00002241 - "\"C\x038\x00\x00\"D" + // 0x22430338: 0x00002244 - "\"E\x038\x00\x00\"G" + // 0x22450338: 0x00002247 - "\"H\x038\x00\x00\"I" + // 0x22480338: 0x00002249 - "\x00=\x038\x00\x00\"`" + // 0x003D0338: 0x00002260 - "\"a\x038\x00\x00\"b" + // 0x22610338: 0x00002262 - "\"M\x038\x00\x00\"m" + // 0x224D0338: 0x0000226D - "\x00<\x038\x00\x00\"n" + // 0x003C0338: 0x0000226E - "\x00>\x038\x00\x00\"o" + // 0x003E0338: 0x0000226F - "\"d\x038\x00\x00\"p" + // 0x22640338: 0x00002270 - "\"e\x038\x00\x00\"q" + // 0x22650338: 0x00002271 - "\"r\x038\x00\x00\"t" + // 0x22720338: 0x00002274 - "\"s\x038\x00\x00\"u" + // 0x22730338: 0x00002275 - "\"v\x038\x00\x00\"x" + // 0x22760338: 0x00002278 - "\"w\x038\x00\x00\"y" + // 0x22770338: 0x00002279 - "\"z\x038\x00\x00\"\x80" + // 0x227A0338: 0x00002280 - "\"{\x038\x00\x00\"\x81" + // 0x227B0338: 0x00002281 - "\"\x82\x038\x00\x00\"\x84" + // 0x22820338: 0x00002284 - "\"\x83\x038\x00\x00\"\x85" + // 0x22830338: 0x00002285 - "\"\x86\x038\x00\x00\"\x88" + // 0x22860338: 0x00002288 - "\"\x87\x038\x00\x00\"\x89" + // 0x22870338: 0x00002289 - "\"\xa2\x038\x00\x00\"\xac" + // 0x22A20338: 0x000022AC - "\"\xa8\x038\x00\x00\"\xad" + // 0x22A80338: 0x000022AD - "\"\xa9\x038\x00\x00\"\xae" + // 0x22A90338: 0x000022AE - "\"\xab\x038\x00\x00\"\xaf" + // 0x22AB0338: 0x000022AF - "\"|\x038\x00\x00\"\xe0" + // 0x227C0338: 0x000022E0 - "\"}\x038\x00\x00\"\xe1" + // 0x227D0338: 0x000022E1 - "\"\x91\x038\x00\x00\"\xe2" + // 0x22910338: 0x000022E2 - "\"\x92\x038\x00\x00\"\xe3" + // 0x22920338: 0x000022E3 - "\"\xb2\x038\x00\x00\"\xea" + // 0x22B20338: 0x000022EA - "\"\xb3\x038\x00\x00\"\xeb" + // 0x22B30338: 0x000022EB - "\"\xb4\x038\x00\x00\"\xec" + // 0x22B40338: 0x000022EC - "\"\xb5\x038\x00\x00\"\xed" + // 0x22B50338: 0x000022ED - "0K0\x99\x00\x000L" + // 0x304B3099: 0x0000304C - "0M0\x99\x00\x000N" + // 0x304D3099: 0x0000304E - "0O0\x99\x00\x000P" + // 0x304F3099: 0x00003050 - "0Q0\x99\x00\x000R" + // 0x30513099: 0x00003052 - "0S0\x99\x00\x000T" + // 0x30533099: 0x00003054 - "0U0\x99\x00\x000V" + // 0x30553099: 0x00003056 - "0W0\x99\x00\x000X" + // 0x30573099: 0x00003058 - "0Y0\x99\x00\x000Z" + // 0x30593099: 0x0000305A - "0[0\x99\x00\x000\\" + // 0x305B3099: 0x0000305C - "0]0\x99\x00\x000^" + // 0x305D3099: 0x0000305E - "0_0\x99\x00\x000`" + // 0x305F3099: 0x00003060 - "0a0\x99\x00\x000b" + // 0x30613099: 0x00003062 - "0d0\x99\x00\x000e" + // 0x30643099: 0x00003065 - "0f0\x99\x00\x000g" + // 0x30663099: 0x00003067 - "0h0\x99\x00\x000i" + // 0x30683099: 0x00003069 - "0o0\x99\x00\x000p" + // 0x306F3099: 0x00003070 - "0o0\x9a\x00\x000q" + // 0x306F309A: 0x00003071 - "0r0\x99\x00\x000s" + // 0x30723099: 0x00003073 - "0r0\x9a\x00\x000t" + // 0x3072309A: 0x00003074 - "0u0\x99\x00\x000v" + // 0x30753099: 0x00003076 - "0u0\x9a\x00\x000w" + // 0x3075309A: 0x00003077 - "0x0\x99\x00\x000y" + // 0x30783099: 0x00003079 - "0x0\x9a\x00\x000z" + // 0x3078309A: 0x0000307A - "0{0\x99\x00\x000|" + // 0x307B3099: 0x0000307C - "0{0\x9a\x00\x000}" + // 0x307B309A: 0x0000307D - "0F0\x99\x00\x000\x94" + // 0x30463099: 0x00003094 - "0\x9d0\x99\x00\x000\x9e" + // 0x309D3099: 0x0000309E - "0\xab0\x99\x00\x000\xac" + // 0x30AB3099: 0x000030AC - "0\xad0\x99\x00\x000\xae" + // 0x30AD3099: 0x000030AE - "0\xaf0\x99\x00\x000\xb0" + // 0x30AF3099: 0x000030B0 - "0\xb10\x99\x00\x000\xb2" + // 0x30B13099: 0x000030B2 - "0\xb30\x99\x00\x000\xb4" + // 0x30B33099: 0x000030B4 - "0\xb50\x99\x00\x000\xb6" + // 0x30B53099: 0x000030B6 - "0\xb70\x99\x00\x000\xb8" + // 0x30B73099: 0x000030B8 - "0\xb90\x99\x00\x000\xba" + // 0x30B93099: 0x000030BA - "0\xbb0\x99\x00\x000\xbc" + // 0x30BB3099: 0x000030BC - "0\xbd0\x99\x00\x000\xbe" + // 0x30BD3099: 0x000030BE - "0\xbf0\x99\x00\x000\xc0" + // 0x30BF3099: 0x000030C0 - "0\xc10\x99\x00\x000\xc2" + // 0x30C13099: 0x000030C2 - "0\xc40\x99\x00\x000\xc5" + // 0x30C43099: 0x000030C5 - "0\xc60\x99\x00\x000\xc7" + // 0x30C63099: 0x000030C7 - "0\xc80\x99\x00\x000\xc9" + // 0x30C83099: 0x000030C9 - "0\xcf0\x99\x00\x000\xd0" + // 0x30CF3099: 0x000030D0 - "0\xcf0\x9a\x00\x000\xd1" + // 0x30CF309A: 0x000030D1 - "0\xd20\x99\x00\x000\xd3" + // 0x30D23099: 0x000030D3 - "0\xd20\x9a\x00\x000\xd4" + // 0x30D2309A: 0x000030D4 - "0\xd50\x99\x00\x000\xd6" + // 0x30D53099: 0x000030D6 - "0\xd50\x9a\x00\x000\xd7" + // 0x30D5309A: 0x000030D7 - "0\xd80\x99\x00\x000\xd9" + // 0x30D83099: 0x000030D9 - "0\xd80\x9a\x00\x000\xda" + // 0x30D8309A: 0x000030DA - "0\xdb0\x99\x00\x000\xdc" + // 0x30DB3099: 0x000030DC - "0\xdb0\x9a\x00\x000\xdd" + // 0x30DB309A: 0x000030DD - "0\xa60\x99\x00\x000\xf4" + // 0x30A63099: 0x000030F4 - "0\xef0\x99\x00\x000\xf7" + // 0x30EF3099: 0x000030F7 - "0\xf00\x99\x00\x000\xf8" + // 0x30F03099: 0x000030F8 - "0\xf10\x99\x00\x000\xf9" + // 0x30F13099: 0x000030F9 - "0\xf20\x99\x00\x000\xfa" + // 0x30F23099: 0x000030FA - "0\xfd0\x99\x00\x000\xfe" + // 0x30FD3099: 0x000030FE - "\x05\xd2\x03\a\x00\x01\x05\xc9" + // 0x05D20307: 0x000105C9 - "\x05\xda\x03\a\x00\x01\x05\xe4" + // 0x05DA0307: 0x000105E4 - "\x10\x99\x10\xba\x00\x01\x10\x9a" + // 0x109910BA: 0x0001109A - "\x10\x9b\x10\xba\x00\x01\x10\x9c" + // 0x109B10BA: 0x0001109C - "\x10\xa5\x10\xba\x00\x01\x10\xab" + // 0x10A510BA: 0x000110AB - "\x111\x11'\x00\x01\x11." + // 0x11311127: 0x0001112E - "\x112\x11'\x00\x01\x11/" + // 0x11321127: 0x0001112F - "\x13G\x13>\x00\x01\x13K" + // 0x1347133E: 0x0001134B - "\x13G\x13W\x00\x01\x13L" + // 0x13471357: 0x0001134C - "\x13\x82\x13\xc9\x00\x01\x13\x83" + // 0x138213C9: 0x00011383 - "\x13\x84\x13\xbb\x00\x01\x13\x85" + // 0x138413BB: 0x00011385 - "\x13\x8b\x13\xc2\x00\x01\x13\x8e" + // 0x138B13C2: 0x0001138E - "\x13\x90\x13\xc9\x00\x01\x13\x91" + // 0x139013C9: 0x00011391 - "\x13\xc2\x13\xc2\x00\x01\x13\xc5" + // 0x13C213C2: 0x000113C5 - "\x13\xc2\x13\xb8\x00\x01\x13\xc7" + // 0x13C213B8: 0x000113C7 - "\x13\xc2\x13\xc9\x00\x01\x13\xc8" + // 0x13C213C9: 0x000113C8 - "\x14\xb9\x14\xba\x00\x01\x14\xbb" + // 0x14B914BA: 0x000114BB - "\x14\xb9\x14\xb0\x00\x01\x14\xbc" + // 0x14B914B0: 0x000114BC - "\x14\xb9\x14\xbd\x00\x01\x14\xbe" + // 0x14B914BD: 0x000114BE - "\x15\xb8\x15\xaf\x00\x01\x15\xba" + // 0x15B815AF: 0x000115BA - "\x15\xb9\x15\xaf\x00\x01\x15\xbb" + // 0x15B915AF: 0x000115BB - "\x195\x190\x00\x01\x198" + // 0x19351930: 0x00011938 - "a\x1ea\x1e\x00\x01a!" + // 0x611E611E: 0x00016121 - "a\x1ea)\x00\x01a\"" + // 0x611E6129: 0x00016122 - "a\x1ea\x1f\x00\x01a#" + // 0x611E611F: 0x00016123 - "a)a\x1f\x00\x01a$" + // 0x6129611F: 0x00016124 - "a\x1ea \x00\x01a%" + // 0x611E6120: 0x00016125 - "a!a\x1f\x00\x01a&" + // 0x6121611F: 0x00016126 - "a\"a\x1f\x00\x01a'" + // 0x6122611F: 0x00016127 - "a!a \x00\x01a(" + // 0x61216120: 0x00016128 - "mgmg\x00\x01mh" + // 0x6D676D67: 0x00016D68 - "mcmg\x00\x01mi" + // 0x6D636D67: 0x00016D69 - "mimg\x00\x01mj" + // 0x6D696D67: 0x00016D6A + "\x00\x01\x04\x00`\x00\x00\xc0" + // 0x00041 0x00300: 0x000C0 + "\x00\x01\x04\x00` \x00\xc1" + // 0x00041 0x00301: 0x000C1 + "\x00\x01\x04\x00`@\x00\xc2" + // 0x00041 0x00302: 0x000C2 + "\x00\x01\x04\x00``\x00\xc3" + // 0x00041 0x00303: 0x000C3 + "\x00\x01\x04\x00a\x00\x00\xc4" + // 0x00041 0x00308: 0x000C4 + "\x00\x01\x04\x00a@\x00\xc5" + // 0x00041 0x0030A: 0x000C5 + "\x00\x01\f\x00d\xe0\x00\xc7" + // 0x00043 0x00327: 0x000C7 + "\x00\x01\x14\x00`\x00\x00\xc8" + // 0x00045 0x00300: 0x000C8 + "\x00\x01\x14\x00` \x00\xc9" + // 0x00045 0x00301: 0x000C9 + "\x00\x01\x14\x00`@\x00\xca" + // 0x00045 0x00302: 0x000CA + "\x00\x01\x14\x00a\x00\x00\xcb" + // 0x00045 0x00308: 0x000CB + "\x00\x01$\x00`\x00\x00\xcc" + // 0x00049 0x00300: 0x000CC + "\x00\x01$\x00` \x00\xcd" + // 0x00049 0x00301: 0x000CD + "\x00\x01$\x00`@\x00\xce" + // 0x00049 0x00302: 0x000CE + "\x00\x01$\x00a\x00\x00\xcf" + // 0x00049 0x00308: 0x000CF + "\x00\x018\x00``\x00\xd1" + // 0x0004E 0x00303: 0x000D1 + "\x00\x01<\x00`\x00\x00\xd2" + // 0x0004F 0x00300: 0x000D2 + "\x00\x01<\x00` \x00\xd3" + // 0x0004F 0x00301: 0x000D3 + "\x00\x01<\x00`@\x00\xd4" + // 0x0004F 0x00302: 0x000D4 + "\x00\x01<\x00``\x00\xd5" + // 0x0004F 0x00303: 0x000D5 + "\x00\x01<\x00a\x00\x00\xd6" + // 0x0004F 0x00308: 0x000D6 + "\x00\x01T\x00`\x00\x00\xd9" + // 0x00055 0x00300: 0x000D9 + "\x00\x01T\x00` \x00\xda" + // 0x00055 0x00301: 0x000DA + "\x00\x01T\x00`@\x00\xdb" + // 0x00055 0x00302: 0x000DB + "\x00\x01T\x00a\x00\x00\xdc" + // 0x00055 0x00308: 0x000DC + "\x00\x01d\x00` \x00\xdd" + // 0x00059 0x00301: 0x000DD + "\x00\x01\x84\x00`\x00\x00\xe0" + // 0x00061 0x00300: 0x000E0 + "\x00\x01\x84\x00` \x00\xe1" + // 0x00061 0x00301: 0x000E1 + "\x00\x01\x84\x00`@\x00\xe2" + // 0x00061 0x00302: 0x000E2 + "\x00\x01\x84\x00``\x00\xe3" + // 0x00061 0x00303: 0x000E3 + "\x00\x01\x84\x00a\x00\x00\xe4" + // 0x00061 0x00308: 0x000E4 + "\x00\x01\x84\x00a@\x00\xe5" + // 0x00061 0x0030A: 0x000E5 + "\x00\x01\x8c\x00d\xe0\x00\xe7" + // 0x00063 0x00327: 0x000E7 + "\x00\x01\x94\x00`\x00\x00\xe8" + // 0x00065 0x00300: 0x000E8 + "\x00\x01\x94\x00` \x00\xe9" + // 0x00065 0x00301: 0x000E9 + "\x00\x01\x94\x00`@\x00\xea" + // 0x00065 0x00302: 0x000EA + "\x00\x01\x94\x00a\x00\x00\xeb" + // 0x00065 0x00308: 0x000EB + "\x00\x01\xa4\x00`\x00\x00\xec" + // 0x00069 0x00300: 0x000EC + "\x00\x01\xa4\x00` \x00\xed" + // 0x00069 0x00301: 0x000ED + "\x00\x01\xa4\x00`@\x00\xee" + // 0x00069 0x00302: 0x000EE + "\x00\x01\xa4\x00a\x00\x00\xef" + // 0x00069 0x00308: 0x000EF + "\x00\x01\xb8\x00``\x00\xf1" + // 0x0006E 0x00303: 0x000F1 + "\x00\x01\xbc\x00`\x00\x00\xf2" + // 0x0006F 0x00300: 0x000F2 + "\x00\x01\xbc\x00` \x00\xf3" + // 0x0006F 0x00301: 0x000F3 + "\x00\x01\xbc\x00`@\x00\xf4" + // 0x0006F 0x00302: 0x000F4 + "\x00\x01\xbc\x00``\x00\xf5" + // 0x0006F 0x00303: 0x000F5 + "\x00\x01\xbc\x00a\x00\x00\xf6" + // 0x0006F 0x00308: 0x000F6 + "\x00\x01\xd4\x00`\x00\x00\xf9" + // 0x00075 0x00300: 0x000F9 + "\x00\x01\xd4\x00` \x00\xfa" + // 0x00075 0x00301: 0x000FA + "\x00\x01\xd4\x00`@\x00\xfb" + // 0x00075 0x00302: 0x000FB + "\x00\x01\xd4\x00a\x00\x00\xfc" + // 0x00075 0x00308: 0x000FC + "\x00\x01\xe4\x00` \x00\xfd" + // 0x00079 0x00301: 0x000FD + "\x00\x01\xe4\x00a\x00\x00\xff" + // 0x00079 0x00308: 0x000FF + "\x00\x01\x04\x00`\x80\x01\x00" + // 0x00041 0x00304: 0x00100 + "\x00\x01\x84\x00`\x80\x01\x01" + // 0x00061 0x00304: 0x00101 + "\x00\x01\x04\x00`\xc0\x01\x02" + // 0x00041 0x00306: 0x00102 + "\x00\x01\x84\x00`\xc0\x01\x03" + // 0x00061 0x00306: 0x00103 + "\x00\x01\x04\x00e\x00\x01\x04" + // 0x00041 0x00328: 0x00104 + "\x00\x01\x84\x00e\x00\x01\x05" + // 0x00061 0x00328: 0x00105 + "\x00\x01\f\x00` \x01\x06" + // 0x00043 0x00301: 0x00106 + "\x00\x01\x8c\x00` \x01\a" + // 0x00063 0x00301: 0x00107 + "\x00\x01\f\x00`@\x01\b" + // 0x00043 0x00302: 0x00108 + "\x00\x01\x8c\x00`@\x01\t" + // 0x00063 0x00302: 0x00109 + "\x00\x01\f\x00`\xe0\x01\n" + // 0x00043 0x00307: 0x0010A + "\x00\x01\x8c\x00`\xe0\x01\v" + // 0x00063 0x00307: 0x0010B + "\x00\x01\f\x00a\x80\x01\f" + // 0x00043 0x0030C: 0x0010C + "\x00\x01\x8c\x00a\x80\x01\r" + // 0x00063 0x0030C: 0x0010D + "\x00\x01\x10\x00a\x80\x01\x0e" + // 0x00044 0x0030C: 0x0010E + "\x00\x01\x90\x00a\x80\x01\x0f" + // 0x00064 0x0030C: 0x0010F + "\x00\x01\x14\x00`\x80\x01\x12" + // 0x00045 0x00304: 0x00112 + "\x00\x01\x94\x00`\x80\x01\x13" + // 0x00065 0x00304: 0x00113 + "\x00\x01\x14\x00`\xc0\x01\x14" + // 0x00045 0x00306: 0x00114 + "\x00\x01\x94\x00`\xc0\x01\x15" + // 0x00065 0x00306: 0x00115 + "\x00\x01\x14\x00`\xe0\x01\x16" + // 0x00045 0x00307: 0x00116 + "\x00\x01\x94\x00`\xe0\x01\x17" + // 0x00065 0x00307: 0x00117 + "\x00\x01\x14\x00e\x00\x01\x18" + // 0x00045 0x00328: 0x00118 + "\x00\x01\x94\x00e\x00\x01\x19" + // 0x00065 0x00328: 0x00119 + "\x00\x01\x14\x00a\x80\x01\x1a" + // 0x00045 0x0030C: 0x0011A + "\x00\x01\x94\x00a\x80\x01\x1b" + // 0x00065 0x0030C: 0x0011B + "\x00\x01\x1c\x00`@\x01\x1c" + // 0x00047 0x00302: 0x0011C + "\x00\x01\x9c\x00`@\x01\x1d" + // 0x00067 0x00302: 0x0011D + "\x00\x01\x1c\x00`\xc0\x01\x1e" + // 0x00047 0x00306: 0x0011E + "\x00\x01\x9c\x00`\xc0\x01\x1f" + // 0x00067 0x00306: 0x0011F + "\x00\x01\x1c\x00`\xe0\x01 " + // 0x00047 0x00307: 0x00120 + "\x00\x01\x9c\x00`\xe0\x01!" + // 0x00067 0x00307: 0x00121 + "\x00\x01\x1c\x00d\xe0\x01\"" + // 0x00047 0x00327: 0x00122 + "\x00\x01\x9c\x00d\xe0\x01#" + // 0x00067 0x00327: 0x00123 + "\x00\x01 \x00`@\x01$" + // 0x00048 0x00302: 0x00124 + "\x00\x01\xa0\x00`@\x01%" + // 0x00068 0x00302: 0x00125 + "\x00\x01$\x00``\x01(" + // 0x00049 0x00303: 0x00128 + "\x00\x01\xa4\x00``\x01)" + // 0x00069 0x00303: 0x00129 + "\x00\x01$\x00`\x80\x01*" + // 0x00049 0x00304: 0x0012A + "\x00\x01\xa4\x00`\x80\x01+" + // 0x00069 0x00304: 0x0012B + "\x00\x01$\x00`\xc0\x01," + // 0x00049 0x00306: 0x0012C + "\x00\x01\xa4\x00`\xc0\x01-" + // 0x00069 0x00306: 0x0012D + "\x00\x01$\x00e\x00\x01." + // 0x00049 0x00328: 0x0012E + "\x00\x01\xa4\x00e\x00\x01/" + // 0x00069 0x00328: 0x0012F + "\x00\x01$\x00`\xe0\x010" + // 0x00049 0x00307: 0x00130 + "\x00\x01(\x00`@\x014" + // 0x0004A 0x00302: 0x00134 + "\x00\x01\xa8\x00`@\x015" + // 0x0006A 0x00302: 0x00135 + "\x00\x01,\x00d\xe0\x016" + // 0x0004B 0x00327: 0x00136 + "\x00\x01\xac\x00d\xe0\x017" + // 0x0006B 0x00327: 0x00137 + "\x00\x010\x00` \x019" + // 0x0004C 0x00301: 0x00139 + "\x00\x01\xb0\x00` \x01:" + // 0x0006C 0x00301: 0x0013A + "\x00\x010\x00d\xe0\x01;" + // 0x0004C 0x00327: 0x0013B + "\x00\x01\xb0\x00d\xe0\x01<" + // 0x0006C 0x00327: 0x0013C + "\x00\x010\x00a\x80\x01=" + // 0x0004C 0x0030C: 0x0013D + "\x00\x01\xb0\x00a\x80\x01>" + // 0x0006C 0x0030C: 0x0013E + "\x00\x018\x00` \x01C" + // 0x0004E 0x00301: 0x00143 + "\x00\x01\xb8\x00` \x01D" + // 0x0006E 0x00301: 0x00144 + "\x00\x018\x00d\xe0\x01E" + // 0x0004E 0x00327: 0x00145 + "\x00\x01\xb8\x00d\xe0\x01F" + // 0x0006E 0x00327: 0x00146 + "\x00\x018\x00a\x80\x01G" + // 0x0004E 0x0030C: 0x00147 + "\x00\x01\xb8\x00a\x80\x01H" + // 0x0006E 0x0030C: 0x00148 + "\x00\x01<\x00`\x80\x01L" + // 0x0004F 0x00304: 0x0014C + "\x00\x01\xbc\x00`\x80\x01M" + // 0x0006F 0x00304: 0x0014D + "\x00\x01<\x00`\xc0\x01N" + // 0x0004F 0x00306: 0x0014E + "\x00\x01\xbc\x00`\xc0\x01O" + // 0x0006F 0x00306: 0x0014F + "\x00\x01<\x00a`\x01P" + // 0x0004F 0x0030B: 0x00150 + "\x00\x01\xbc\x00a`\x01Q" + // 0x0006F 0x0030B: 0x00151 + "\x00\x01H\x00` \x01T" + // 0x00052 0x00301: 0x00154 + "\x00\x01\xc8\x00` \x01U" + // 0x00072 0x00301: 0x00155 + "\x00\x01H\x00d\xe0\x01V" + // 0x00052 0x00327: 0x00156 + "\x00\x01\xc8\x00d\xe0\x01W" + // 0x00072 0x00327: 0x00157 + "\x00\x01H\x00a\x80\x01X" + // 0x00052 0x0030C: 0x00158 + "\x00\x01\xc8\x00a\x80\x01Y" + // 0x00072 0x0030C: 0x00159 + "\x00\x01L\x00` \x01Z" + // 0x00053 0x00301: 0x0015A + "\x00\x01\xcc\x00` \x01[" + // 0x00073 0x00301: 0x0015B + "\x00\x01L\x00`@\x01\\" + // 0x00053 0x00302: 0x0015C + "\x00\x01\xcc\x00`@\x01]" + // 0x00073 0x00302: 0x0015D + "\x00\x01L\x00d\xe0\x01^" + // 0x00053 0x00327: 0x0015E + "\x00\x01\xcc\x00d\xe0\x01_" + // 0x00073 0x00327: 0x0015F + "\x00\x01L\x00a\x80\x01`" + // 0x00053 0x0030C: 0x00160 + "\x00\x01\xcc\x00a\x80\x01a" + // 0x00073 0x0030C: 0x00161 + "\x00\x01P\x00d\xe0\x01b" + // 0x00054 0x00327: 0x00162 + "\x00\x01\xd0\x00d\xe0\x01c" + // 0x00074 0x00327: 0x00163 + "\x00\x01P\x00a\x80\x01d" + // 0x00054 0x0030C: 0x00164 + "\x00\x01\xd0\x00a\x80\x01e" + // 0x00074 0x0030C: 0x00165 + "\x00\x01T\x00``\x01h" + // 0x00055 0x00303: 0x00168 + "\x00\x01\xd4\x00``\x01i" + // 0x00075 0x00303: 0x00169 + "\x00\x01T\x00`\x80\x01j" + // 0x00055 0x00304: 0x0016A + "\x00\x01\xd4\x00`\x80\x01k" + // 0x00075 0x00304: 0x0016B + "\x00\x01T\x00`\xc0\x01l" + // 0x00055 0x00306: 0x0016C + "\x00\x01\xd4\x00`\xc0\x01m" + // 0x00075 0x00306: 0x0016D + "\x00\x01T\x00a@\x01n" + // 0x00055 0x0030A: 0x0016E + "\x00\x01\xd4\x00a@\x01o" + // 0x00075 0x0030A: 0x0016F + "\x00\x01T\x00a`\x01p" + // 0x00055 0x0030B: 0x00170 + "\x00\x01\xd4\x00a`\x01q" + // 0x00075 0x0030B: 0x00171 + "\x00\x01T\x00e\x00\x01r" + // 0x00055 0x00328: 0x00172 + "\x00\x01\xd4\x00e\x00\x01s" + // 0x00075 0x00328: 0x00173 + "\x00\x01\\\x00`@\x01t" + // 0x00057 0x00302: 0x00174 + "\x00\x01\xdc\x00`@\x01u" + // 0x00077 0x00302: 0x00175 + "\x00\x01d\x00`@\x01v" + // 0x00059 0x00302: 0x00176 + "\x00\x01\xe4\x00`@\x01w" + // 0x00079 0x00302: 0x00177 + "\x00\x01d\x00a\x00\x01x" + // 0x00059 0x00308: 0x00178 + "\x00\x01h\x00` \x01y" + // 0x0005A 0x00301: 0x00179 + "\x00\x01\xe8\x00` \x01z" + // 0x0007A 0x00301: 0x0017A + "\x00\x01h\x00`\xe0\x01{" + // 0x0005A 0x00307: 0x0017B + "\x00\x01\xe8\x00`\xe0\x01|" + // 0x0007A 0x00307: 0x0017C + "\x00\x01h\x00a\x80\x01}" + // 0x0005A 0x0030C: 0x0017D + "\x00\x01\xe8\x00a\x80\x01~" + // 0x0007A 0x0030C: 0x0017E + "\x00\x01<\x00c`\x01\xa0" + // 0x0004F 0x0031B: 0x001A0 + "\x00\x01\xbc\x00c`\x01\xa1" + // 0x0006F 0x0031B: 0x001A1 + "\x00\x01T\x00c`\x01\xaf" + // 0x00055 0x0031B: 0x001AF + "\x00\x01\xd4\x00c`\x01\xb0" + // 0x00075 0x0031B: 0x001B0 + "\x00\x01\x04\x00a\x80\x01\xcd" + // 0x00041 0x0030C: 0x001CD + "\x00\x01\x84\x00a\x80\x01\xce" + // 0x00061 0x0030C: 0x001CE + "\x00\x01$\x00a\x80\x01\xcf" + // 0x00049 0x0030C: 0x001CF + "\x00\x01\xa4\x00a\x80\x01\xd0" + // 0x00069 0x0030C: 0x001D0 + "\x00\x01<\x00a\x80\x01\xd1" + // 0x0004F 0x0030C: 0x001D1 + "\x00\x01\xbc\x00a\x80\x01\xd2" + // 0x0006F 0x0030C: 0x001D2 + "\x00\x01T\x00a\x80\x01\xd3" + // 0x00055 0x0030C: 0x001D3 + "\x00\x01\xd4\x00a\x80\x01\xd4" + // 0x00075 0x0030C: 0x001D4 + "\x00\x03p\x00`\x80\x01\xd5" + // 0x000DC 0x00304: 0x001D5 + "\x00\x03\xf0\x00`\x80\x01\xd6" + // 0x000FC 0x00304: 0x001D6 + "\x00\x03p\x00` \x01\xd7" + // 0x000DC 0x00301: 0x001D7 + "\x00\x03\xf0\x00` \x01\xd8" + // 0x000FC 0x00301: 0x001D8 + "\x00\x03p\x00a\x80\x01\xd9" + // 0x000DC 0x0030C: 0x001D9 + "\x00\x03\xf0\x00a\x80\x01\xda" + // 0x000FC 0x0030C: 0x001DA + "\x00\x03p\x00`\x00\x01\xdb" + // 0x000DC 0x00300: 0x001DB + "\x00\x03\xf0\x00`\x00\x01\xdc" + // 0x000FC 0x00300: 0x001DC + "\x00\x03\x10\x00`\x80\x01\xde" + // 0x000C4 0x00304: 0x001DE + "\x00\x03\x90\x00`\x80\x01\xdf" + // 0x000E4 0x00304: 0x001DF + "\x00\b\x98\x00`\x80\x01\xe0" + // 0x00226 0x00304: 0x001E0 + "\x00\b\x9c\x00`\x80\x01\xe1" + // 0x00227 0x00304: 0x001E1 + "\x00\x03\x18\x00`\x80\x01\xe2" + // 0x000C6 0x00304: 0x001E2 + "\x00\x03\x98\x00`\x80\x01\xe3" + // 0x000E6 0x00304: 0x001E3 + "\x00\x01\x1c\x00a\x80\x01\xe6" + // 0x00047 0x0030C: 0x001E6 + "\x00\x01\x9c\x00a\x80\x01\xe7" + // 0x00067 0x0030C: 0x001E7 + "\x00\x01,\x00a\x80\x01\xe8" + // 0x0004B 0x0030C: 0x001E8 + "\x00\x01\xac\x00a\x80\x01\xe9" + // 0x0006B 0x0030C: 0x001E9 + "\x00\x01<\x00e\x00\x01\xea" + // 0x0004F 0x00328: 0x001EA + "\x00\x01\xbc\x00e\x00\x01\xeb" + // 0x0006F 0x00328: 0x001EB + "\x00\a\xa8\x00`\x80\x01\xec" + // 0x001EA 0x00304: 0x001EC + "\x00\a\xac\x00`\x80\x01\xed" + // 0x001EB 0x00304: 0x001ED + "\x00\x06\xdc\x00a\x80\x01\xee" + // 0x001B7 0x0030C: 0x001EE + "\x00\nH\x00a\x80\x01\xef" + // 0x00292 0x0030C: 0x001EF + "\x00\x01\xa8\x00a\x80\x01\xf0" + // 0x0006A 0x0030C: 0x001F0 + "\x00\x01\x1c\x00` \x01\xf4" + // 0x00047 0x00301: 0x001F4 + "\x00\x01\x9c\x00` \x01\xf5" + // 0x00067 0x00301: 0x001F5 + "\x00\x018\x00`\x00\x01\xf8" + // 0x0004E 0x00300: 0x001F8 + "\x00\x01\xb8\x00`\x00\x01\xf9" + // 0x0006E 0x00300: 0x001F9 + "\x00\x03\x14\x00` \x01\xfa" + // 0x000C5 0x00301: 0x001FA + "\x00\x03\x94\x00` \x01\xfb" + // 0x000E5 0x00301: 0x001FB + "\x00\x03\x18\x00` \x01\xfc" + // 0x000C6 0x00301: 0x001FC + "\x00\x03\x98\x00` \x01\xfd" + // 0x000E6 0x00301: 0x001FD + "\x00\x03`\x00` \x01\xfe" + // 0x000D8 0x00301: 0x001FE + "\x00\x03\xe0\x00` \x01\xff" + // 0x000F8 0x00301: 0x001FF + "\x00\x01\x04\x00a\xe0\x02\x00" + // 0x00041 0x0030F: 0x00200 + "\x00\x01\x84\x00a\xe0\x02\x01" + // 0x00061 0x0030F: 0x00201 + "\x00\x01\x04\x00b \x02\x02" + // 0x00041 0x00311: 0x00202 + "\x00\x01\x84\x00b \x02\x03" + // 0x00061 0x00311: 0x00203 + "\x00\x01\x14\x00a\xe0\x02\x04" + // 0x00045 0x0030F: 0x00204 + "\x00\x01\x94\x00a\xe0\x02\x05" + // 0x00065 0x0030F: 0x00205 + "\x00\x01\x14\x00b \x02\x06" + // 0x00045 0x00311: 0x00206 + "\x00\x01\x94\x00b \x02\a" + // 0x00065 0x00311: 0x00207 + "\x00\x01$\x00a\xe0\x02\b" + // 0x00049 0x0030F: 0x00208 + "\x00\x01\xa4\x00a\xe0\x02\t" + // 0x00069 0x0030F: 0x00209 + "\x00\x01$\x00b \x02\n" + // 0x00049 0x00311: 0x0020A + "\x00\x01\xa4\x00b \x02\v" + // 0x00069 0x00311: 0x0020B + "\x00\x01<\x00a\xe0\x02\f" + // 0x0004F 0x0030F: 0x0020C + "\x00\x01\xbc\x00a\xe0\x02\r" + // 0x0006F 0x0030F: 0x0020D + "\x00\x01<\x00b \x02\x0e" + // 0x0004F 0x00311: 0x0020E + "\x00\x01\xbc\x00b \x02\x0f" + // 0x0006F 0x00311: 0x0020F + "\x00\x01H\x00a\xe0\x02\x10" + // 0x00052 0x0030F: 0x00210 + "\x00\x01\xc8\x00a\xe0\x02\x11" + // 0x00072 0x0030F: 0x00211 + "\x00\x01H\x00b \x02\x12" + // 0x00052 0x00311: 0x00212 + "\x00\x01\xc8\x00b \x02\x13" + // 0x00072 0x00311: 0x00213 + "\x00\x01T\x00a\xe0\x02\x14" + // 0x00055 0x0030F: 0x00214 + "\x00\x01\xd4\x00a\xe0\x02\x15" + // 0x00075 0x0030F: 0x00215 + "\x00\x01T\x00b \x02\x16" + // 0x00055 0x00311: 0x00216 + "\x00\x01\xd4\x00b \x02\x17" + // 0x00075 0x00311: 0x00217 + "\x00\x01L\x00d\xc0\x02\x18" + // 0x00053 0x00326: 0x00218 + "\x00\x01\xcc\x00d\xc0\x02\x19" + // 0x00073 0x00326: 0x00219 + "\x00\x01P\x00d\xc0\x02\x1a" + // 0x00054 0x00326: 0x0021A + "\x00\x01\xd0\x00d\xc0\x02\x1b" + // 0x00074 0x00326: 0x0021B + "\x00\x01 \x00a\x80\x02\x1e" + // 0x00048 0x0030C: 0x0021E + "\x00\x01\xa0\x00a\x80\x02\x1f" + // 0x00068 0x0030C: 0x0021F + "\x00\x01\x04\x00`\xe0\x02&" + // 0x00041 0x00307: 0x00226 + "\x00\x01\x84\x00`\xe0\x02'" + // 0x00061 0x00307: 0x00227 + "\x00\x01\x14\x00d\xe0\x02(" + // 0x00045 0x00327: 0x00228 + "\x00\x01\x94\x00d\xe0\x02)" + // 0x00065 0x00327: 0x00229 + "\x00\x03X\x00`\x80\x02*" + // 0x000D6 0x00304: 0x0022A + "\x00\x03\xd8\x00`\x80\x02+" + // 0x000F6 0x00304: 0x0022B + "\x00\x03T\x00`\x80\x02," + // 0x000D5 0x00304: 0x0022C + "\x00\x03\xd4\x00`\x80\x02-" + // 0x000F5 0x00304: 0x0022D + "\x00\x01<\x00`\xe0\x02." + // 0x0004F 0x00307: 0x0022E + "\x00\x01\xbc\x00`\xe0\x02/" + // 0x0006F 0x00307: 0x0022F + "\x00\b\xb8\x00`\x80\x020" + // 0x0022E 0x00304: 0x00230 + "\x00\b\xbc\x00`\x80\x021" + // 0x0022F 0x00304: 0x00231 + "\x00\x01d\x00`\x80\x022" + // 0x00059 0x00304: 0x00232 + "\x00\x01\xe4\x00`\x80\x023" + // 0x00079 0x00304: 0x00233 + "\x00\x02\xa0\x00` \x03\x85" + // 0x000A8 0x00301: 0x00385 + "\x00\x0eD\x00` \x03\x86" + // 0x00391 0x00301: 0x00386 + "\x00\x0eT\x00` \x03\x88" + // 0x00395 0x00301: 0x00388 + "\x00\x0e\\\x00` \x03\x89" + // 0x00397 0x00301: 0x00389 + "\x00\x0ed\x00` \x03\x8a" + // 0x00399 0x00301: 0x0038A + "\x00\x0e|\x00` \x03\x8c" + // 0x0039F 0x00301: 0x0038C + "\x00\x0e\x94\x00` \x03\x8e" + // 0x003A5 0x00301: 0x0038E + "\x00\x0e\xa4\x00` \x03\x8f" + // 0x003A9 0x00301: 0x0038F + "\x00\x0f(\x00` \x03\x90" + // 0x003CA 0x00301: 0x00390 + "\x00\x0ed\x00a\x00\x03\xaa" + // 0x00399 0x00308: 0x003AA + "\x00\x0e\x94\x00a\x00\x03\xab" + // 0x003A5 0x00308: 0x003AB + "\x00\x0e\xc4\x00` \x03\xac" + // 0x003B1 0x00301: 0x003AC + "\x00\x0e\xd4\x00` \x03\xad" + // 0x003B5 0x00301: 0x003AD + "\x00\x0e\xdc\x00` \x03\xae" + // 0x003B7 0x00301: 0x003AE + "\x00\x0e\xe4\x00` \x03\xaf" + // 0x003B9 0x00301: 0x003AF + "\x00\x0f,\x00` \x03\xb0" + // 0x003CB 0x00301: 0x003B0 + "\x00\x0e\xe4\x00a\x00\x03\xca" + // 0x003B9 0x00308: 0x003CA + "\x00\x0f\x14\x00a\x00\x03\xcb" + // 0x003C5 0x00308: 0x003CB + "\x00\x0e\xfc\x00` \x03\xcc" + // 0x003BF 0x00301: 0x003CC + "\x00\x0f\x14\x00` \x03\xcd" + // 0x003C5 0x00301: 0x003CD + "\x00\x0f$\x00` \x03\xce" + // 0x003C9 0x00301: 0x003CE + "\x00\x0fH\x00` \x03\xd3" + // 0x003D2 0x00301: 0x003D3 + "\x00\x0fH\x00a\x00\x03\xd4" + // 0x003D2 0x00308: 0x003D4 + "\x00\x10T\x00`\x00\x04\x00" + // 0x00415 0x00300: 0x00400 + "\x00\x10T\x00a\x00\x04\x01" + // 0x00415 0x00308: 0x00401 + "\x00\x10L\x00` \x04\x03" + // 0x00413 0x00301: 0x00403 + "\x00\x10\x18\x00a\x00\x04\a" + // 0x00406 0x00308: 0x00407 + "\x00\x10h\x00` \x04\f" + // 0x0041A 0x00301: 0x0040C + "\x00\x10`\x00`\x00\x04\r" + // 0x00418 0x00300: 0x0040D + "\x00\x10\x8c\x00`\xc0\x04\x0e" + // 0x00423 0x00306: 0x0040E + "\x00\x10`\x00`\xc0\x04\x19" + // 0x00418 0x00306: 0x00419 + "\x00\x10\xe0\x00`\xc0\x049" + // 0x00438 0x00306: 0x00439 + "\x00\x10\xd4\x00`\x00\x04P" + // 0x00435 0x00300: 0x00450 + "\x00\x10\xd4\x00a\x00\x04Q" + // 0x00435 0x00308: 0x00451 + "\x00\x10\xcc\x00` \x04S" + // 0x00433 0x00301: 0x00453 + "\x00\x11X\x00a\x00\x04W" + // 0x00456 0x00308: 0x00457 + "\x00\x10\xe8\x00` \x04\\" + // 0x0043A 0x00301: 0x0045C + "\x00\x10\xe0\x00`\x00\x04]" + // 0x00438 0x00300: 0x0045D + "\x00\x11\f\x00`\xc0\x04^" + // 0x00443 0x00306: 0x0045E + "\x00\x11\xd0\x00a\xe0\x04v" + // 0x00474 0x0030F: 0x00476 + "\x00\x11\xd4\x00a\xe0\x04w" + // 0x00475 0x0030F: 0x00477 + "\x00\x10X\x00`\xc0\x04\xc1" + // 0x00416 0x00306: 0x004C1 + "\x00\x10\xd8\x00`\xc0\x04\xc2" + // 0x00436 0x00306: 0x004C2 + "\x00\x10@\x00`\xc0\x04\xd0" + // 0x00410 0x00306: 0x004D0 + "\x00\x10\xc0\x00`\xc0\x04\xd1" + // 0x00430 0x00306: 0x004D1 + "\x00\x10@\x00a\x00\x04\xd2" + // 0x00410 0x00308: 0x004D2 + "\x00\x10\xc0\x00a\x00\x04\xd3" + // 0x00430 0x00308: 0x004D3 + "\x00\x10T\x00`\xc0\x04\xd6" + // 0x00415 0x00306: 0x004D6 + "\x00\x10\xd4\x00`\xc0\x04\xd7" + // 0x00435 0x00306: 0x004D7 + "\x00\x13`\x00a\x00\x04\xda" + // 0x004D8 0x00308: 0x004DA + "\x00\x13d\x00a\x00\x04\xdb" + // 0x004D9 0x00308: 0x004DB + "\x00\x10X\x00a\x00\x04\xdc" + // 0x00416 0x00308: 0x004DC + "\x00\x10\xd8\x00a\x00\x04\xdd" + // 0x00436 0x00308: 0x004DD + "\x00\x10\\\x00a\x00\x04\xde" + // 0x00417 0x00308: 0x004DE + "\x00\x10\xdc\x00a\x00\x04\xdf" + // 0x00437 0x00308: 0x004DF + "\x00\x10`\x00`\x80\x04\xe2" + // 0x00418 0x00304: 0x004E2 + "\x00\x10\xe0\x00`\x80\x04\xe3" + // 0x00438 0x00304: 0x004E3 + "\x00\x10`\x00a\x00\x04\xe4" + // 0x00418 0x00308: 0x004E4 + "\x00\x10\xe0\x00a\x00\x04\xe5" + // 0x00438 0x00308: 0x004E5 + "\x00\x10x\x00a\x00\x04\xe6" + // 0x0041E 0x00308: 0x004E6 + "\x00\x10\xf8\x00a\x00\x04\xe7" + // 0x0043E 0x00308: 0x004E7 + "\x00\x13\xa0\x00a\x00\x04\xea" + // 0x004E8 0x00308: 0x004EA + "\x00\x13\xa4\x00a\x00\x04\xeb" + // 0x004E9 0x00308: 0x004EB + "\x00\x10\xb4\x00a\x00\x04\xec" + // 0x0042D 0x00308: 0x004EC + "\x00\x114\x00a\x00\x04\xed" + // 0x0044D 0x00308: 0x004ED + "\x00\x10\x8c\x00`\x80\x04\xee" + // 0x00423 0x00304: 0x004EE + "\x00\x11\f\x00`\x80\x04\xef" + // 0x00443 0x00304: 0x004EF + "\x00\x10\x8c\x00a\x00\x04\xf0" + // 0x00423 0x00308: 0x004F0 + "\x00\x11\f\x00a\x00\x04\xf1" + // 0x00443 0x00308: 0x004F1 + "\x00\x10\x8c\x00a`\x04\xf2" + // 0x00423 0x0030B: 0x004F2 + "\x00\x11\f\x00a`\x04\xf3" + // 0x00443 0x0030B: 0x004F3 + "\x00\x10\x9c\x00a\x00\x04\xf4" + // 0x00427 0x00308: 0x004F4 + "\x00\x11\x1c\x00a\x00\x04\xf5" + // 0x00447 0x00308: 0x004F5 + "\x00\x10\xac\x00a\x00\x04\xf8" + // 0x0042B 0x00308: 0x004F8 + "\x00\x11,\x00a\x00\x04\xf9" + // 0x0044B 0x00308: 0x004F9 + "\x00\x18\x9c\x00\xca`\x06\"" + // 0x00627 0x00653: 0x00622 + "\x00\x18\x9c\x00ʀ\x06#" + // 0x00627 0x00654: 0x00623 + "\x00\x19 \x00ʀ\x06$" + // 0x00648 0x00654: 0x00624 + "\x00\x18\x9c\x00ʠ\x06%" + // 0x00627 0x00655: 0x00625 + "\x00\x19(\x00ʀ\x06&" + // 0x0064A 0x00654: 0x00626 + "\x00\x1bT\x00ʀ\x06\xc0" + // 0x006D5 0x00654: 0x006C0 + "\x00\x1b\x04\x00ʀ\x06\xc2" + // 0x006C1 0x00654: 0x006C2 + "\x00\x1bH\x00ʀ\x06\xd3" + // 0x006D2 0x00654: 0x006D3 + "\x00$\xa0\x01'\x80\t)" + // 0x00928 0x0093C: 0x00929 + "\x00$\xc0\x01'\x80\t1" + // 0x00930 0x0093C: 0x00931 + "\x00$\xcc\x01'\x80\t4" + // 0x00933 0x0093C: 0x00934 + "\x00'\x1c\x017\xc0\t\xcb" + // 0x009C7 0x009BE: 0x009CB + "\x00'\x1c\x01:\xe0\t\xcc" + // 0x009C7 0x009D7: 0x009CC + "\x00-\x1c\x01j\xc0\vH" + // 0x00B47 0x00B56: 0x00B48 + "\x00-\x1c\x01g\xc0\vK" + // 0x00B47 0x00B3E: 0x00B4B + "\x00-\x1c\x01j\xe0\vL" + // 0x00B47 0x00B57: 0x00B4C + "\x00.H\x01z\xe0\v\x94" + // 0x00B92 0x00BD7: 0x00B94 + "\x00/\x18\x01w\xc0\v\xca" + // 0x00BC6 0x00BBE: 0x00BCA + "\x00/\x1c\x01w\xc0\v\xcb" + // 0x00BC7 0x00BBE: 0x00BCB + "\x00/\x18\x01z\xe0\v\xcc" + // 0x00BC6 0x00BD7: 0x00BCC + "\x001\x18\x01\x8a\xc0\fH" + // 0x00C46 0x00C56: 0x00C48 + "\x002\xfc\x01\x9a\xa0\f\xc0" + // 0x00CBF 0x00CD5: 0x00CC0 + "\x003\x18\x01\x9a\xa0\f\xc7" + // 0x00CC6 0x00CD5: 0x00CC7 + "\x003\x18\x01\x9a\xc0\f\xc8" + // 0x00CC6 0x00CD6: 0x00CC8 + "\x003\x18\x01\x98@\f\xca" + // 0x00CC6 0x00CC2: 0x00CCA + "\x003(\x01\x9a\xa0\f\xcb" + // 0x00CCA 0x00CD5: 0x00CCB + "\x005\x18\x01\xa7\xc0\rJ" + // 0x00D46 0x00D3E: 0x00D4A + "\x005\x1c\x01\xa7\xc0\rK" + // 0x00D47 0x00D3E: 0x00D4B + "\x005\x18\x01\xaa\xe0\rL" + // 0x00D46 0x00D57: 0x00D4C + "\x007d\x01\xb9@\r\xda" + // 0x00DD9 0x00DCA: 0x00DDA + "\x007d\x01\xb9\xe0\r\xdc" + // 0x00DD9 0x00DCF: 0x00DDC + "\x007p\x01\xb9@\r\xdd" + // 0x00DDC 0x00DCA: 0x00DDD + "\x007d\x01\xbb\xe0\r\xde" + // 0x00DD9 0x00DDF: 0x00DDE + "\x00@\x94\x02\x05\xc0\x10&" + // 0x01025 0x0102E: 0x01026 + "\x00l\x14\x03f\xa0\x1b\x06" + // 0x01B05 0x01B35: 0x01B06 + "\x00l\x1c\x03f\xa0\x1b\b" + // 0x01B07 0x01B35: 0x01B08 + "\x00l$\x03f\xa0\x1b\n" + // 0x01B09 0x01B35: 0x01B0A + "\x00l,\x03f\xa0\x1b\f" + // 0x01B0B 0x01B35: 0x01B0C + "\x00l4\x03f\xa0\x1b\x0e" + // 0x01B0D 0x01B35: 0x01B0E + "\x00lD\x03f\xa0\x1b\x12" + // 0x01B11 0x01B35: 0x01B12 + "\x00l\xe8\x03f\xa0\x1b;" + // 0x01B3A 0x01B35: 0x01B3B + "\x00l\xf0\x03f\xa0\x1b=" + // 0x01B3C 0x01B35: 0x01B3D + "\x00l\xf8\x03f\xa0\x1b@" + // 0x01B3E 0x01B35: 0x01B40 + "\x00l\xfc\x03f\xa0\x1bA" + // 0x01B3F 0x01B35: 0x01B41 + "\x00m\b\x03f\xa0\x1bC" + // 0x01B42 0x01B35: 0x01B43 + "\x00\x01\x04\x00d\xa0\x1e\x00" + // 0x00041 0x00325: 0x01E00 + "\x00\x01\x84\x00d\xa0\x1e\x01" + // 0x00061 0x00325: 0x01E01 + "\x00\x01\b\x00`\xe0\x1e\x02" + // 0x00042 0x00307: 0x01E02 + "\x00\x01\x88\x00`\xe0\x1e\x03" + // 0x00062 0x00307: 0x01E03 + "\x00\x01\b\x00d`\x1e\x04" + // 0x00042 0x00323: 0x01E04 + "\x00\x01\x88\x00d`\x1e\x05" + // 0x00062 0x00323: 0x01E05 + "\x00\x01\b\x00f \x1e\x06" + // 0x00042 0x00331: 0x01E06 + "\x00\x01\x88\x00f \x1e\a" + // 0x00062 0x00331: 0x01E07 + "\x00\x03\x1c\x00` \x1e\b" + // 0x000C7 0x00301: 0x01E08 + "\x00\x03\x9c\x00` \x1e\t" + // 0x000E7 0x00301: 0x01E09 + "\x00\x01\x10\x00`\xe0\x1e\n" + // 0x00044 0x00307: 0x01E0A + "\x00\x01\x90\x00`\xe0\x1e\v" + // 0x00064 0x00307: 0x01E0B + "\x00\x01\x10\x00d`\x1e\f" + // 0x00044 0x00323: 0x01E0C + "\x00\x01\x90\x00d`\x1e\r" + // 0x00064 0x00323: 0x01E0D + "\x00\x01\x10\x00f \x1e\x0e" + // 0x00044 0x00331: 0x01E0E + "\x00\x01\x90\x00f \x1e\x0f" + // 0x00064 0x00331: 0x01E0F + "\x00\x01\x10\x00d\xe0\x1e\x10" + // 0x00044 0x00327: 0x01E10 + "\x00\x01\x90\x00d\xe0\x1e\x11" + // 0x00064 0x00327: 0x01E11 + "\x00\x01\x10\x00e\xa0\x1e\x12" + // 0x00044 0x0032D: 0x01E12 + "\x00\x01\x90\x00e\xa0\x1e\x13" + // 0x00064 0x0032D: 0x01E13 + "\x00\x04H\x00`\x00\x1e\x14" + // 0x00112 0x00300: 0x01E14 + "\x00\x04L\x00`\x00\x1e\x15" + // 0x00113 0x00300: 0x01E15 + "\x00\x04H\x00` \x1e\x16" + // 0x00112 0x00301: 0x01E16 + "\x00\x04L\x00` \x1e\x17" + // 0x00113 0x00301: 0x01E17 + "\x00\x01\x14\x00e\xa0\x1e\x18" + // 0x00045 0x0032D: 0x01E18 + "\x00\x01\x94\x00e\xa0\x1e\x19" + // 0x00065 0x0032D: 0x01E19 + "\x00\x01\x14\x00f\x00\x1e\x1a" + // 0x00045 0x00330: 0x01E1A + "\x00\x01\x94\x00f\x00\x1e\x1b" + // 0x00065 0x00330: 0x01E1B + "\x00\b\xa0\x00`\xc0\x1e\x1c" + // 0x00228 0x00306: 0x01E1C + "\x00\b\xa4\x00`\xc0\x1e\x1d" + // 0x00229 0x00306: 0x01E1D + "\x00\x01\x18\x00`\xe0\x1e\x1e" + // 0x00046 0x00307: 0x01E1E + "\x00\x01\x98\x00`\xe0\x1e\x1f" + // 0x00066 0x00307: 0x01E1F + "\x00\x01\x1c\x00`\x80\x1e " + // 0x00047 0x00304: 0x01E20 + "\x00\x01\x9c\x00`\x80\x1e!" + // 0x00067 0x00304: 0x01E21 + "\x00\x01 \x00`\xe0\x1e\"" + // 0x00048 0x00307: 0x01E22 + "\x00\x01\xa0\x00`\xe0\x1e#" + // 0x00068 0x00307: 0x01E23 + "\x00\x01 \x00d`\x1e$" + // 0x00048 0x00323: 0x01E24 + "\x00\x01\xa0\x00d`\x1e%" + // 0x00068 0x00323: 0x01E25 + "\x00\x01 \x00a\x00\x1e&" + // 0x00048 0x00308: 0x01E26 + "\x00\x01\xa0\x00a\x00\x1e'" + // 0x00068 0x00308: 0x01E27 + "\x00\x01 \x00d\xe0\x1e(" + // 0x00048 0x00327: 0x01E28 + "\x00\x01\xa0\x00d\xe0\x1e)" + // 0x00068 0x00327: 0x01E29 + "\x00\x01 \x00e\xc0\x1e*" + // 0x00048 0x0032E: 0x01E2A + "\x00\x01\xa0\x00e\xc0\x1e+" + // 0x00068 0x0032E: 0x01E2B + "\x00\x01$\x00f\x00\x1e," + // 0x00049 0x00330: 0x01E2C + "\x00\x01\xa4\x00f\x00\x1e-" + // 0x00069 0x00330: 0x01E2D + "\x00\x03<\x00` \x1e." + // 0x000CF 0x00301: 0x01E2E + "\x00\x03\xbc\x00` \x1e/" + // 0x000EF 0x00301: 0x01E2F + "\x00\x01,\x00` \x1e0" + // 0x0004B 0x00301: 0x01E30 + "\x00\x01\xac\x00` \x1e1" + // 0x0006B 0x00301: 0x01E31 + "\x00\x01,\x00d`\x1e2" + // 0x0004B 0x00323: 0x01E32 + "\x00\x01\xac\x00d`\x1e3" + // 0x0006B 0x00323: 0x01E33 + "\x00\x01,\x00f \x1e4" + // 0x0004B 0x00331: 0x01E34 + "\x00\x01\xac\x00f \x1e5" + // 0x0006B 0x00331: 0x01E35 + "\x00\x010\x00d`\x1e6" + // 0x0004C 0x00323: 0x01E36 + "\x00\x01\xb0\x00d`\x1e7" + // 0x0006C 0x00323: 0x01E37 + "\x00x\xd8\x00`\x80\x1e8" + // 0x01E36 0x00304: 0x01E38 + "\x00x\xdc\x00`\x80\x1e9" + // 0x01E37 0x00304: 0x01E39 + "\x00\x010\x00f \x1e:" + // 0x0004C 0x00331: 0x01E3A + "\x00\x01\xb0\x00f \x1e;" + // 0x0006C 0x00331: 0x01E3B + "\x00\x010\x00e\xa0\x1e<" + // 0x0004C 0x0032D: 0x01E3C + "\x00\x01\xb0\x00e\xa0\x1e=" + // 0x0006C 0x0032D: 0x01E3D + "\x00\x014\x00` \x1e>" + // 0x0004D 0x00301: 0x01E3E + "\x00\x01\xb4\x00` \x1e?" + // 0x0006D 0x00301: 0x01E3F + "\x00\x014\x00`\xe0\x1e@" + // 0x0004D 0x00307: 0x01E40 + "\x00\x01\xb4\x00`\xe0\x1eA" + // 0x0006D 0x00307: 0x01E41 + "\x00\x014\x00d`\x1eB" + // 0x0004D 0x00323: 0x01E42 + "\x00\x01\xb4\x00d`\x1eC" + // 0x0006D 0x00323: 0x01E43 + "\x00\x018\x00`\xe0\x1eD" + // 0x0004E 0x00307: 0x01E44 + "\x00\x01\xb8\x00`\xe0\x1eE" + // 0x0006E 0x00307: 0x01E45 + "\x00\x018\x00d`\x1eF" + // 0x0004E 0x00323: 0x01E46 + "\x00\x01\xb8\x00d`\x1eG" + // 0x0006E 0x00323: 0x01E47 + "\x00\x018\x00f \x1eH" + // 0x0004E 0x00331: 0x01E48 + "\x00\x01\xb8\x00f \x1eI" + // 0x0006E 0x00331: 0x01E49 + "\x00\x018\x00e\xa0\x1eJ" + // 0x0004E 0x0032D: 0x01E4A + "\x00\x01\xb8\x00e\xa0\x1eK" + // 0x0006E 0x0032D: 0x01E4B + "\x00\x03T\x00` \x1eL" + // 0x000D5 0x00301: 0x01E4C + "\x00\x03\xd4\x00` \x1eM" + // 0x000F5 0x00301: 0x01E4D + "\x00\x03T\x00a\x00\x1eN" + // 0x000D5 0x00308: 0x01E4E + "\x00\x03\xd4\x00a\x00\x1eO" + // 0x000F5 0x00308: 0x01E4F + "\x00\x050\x00`\x00\x1eP" + // 0x0014C 0x00300: 0x01E50 + "\x00\x054\x00`\x00\x1eQ" + // 0x0014D 0x00300: 0x01E51 + "\x00\x050\x00` \x1eR" + // 0x0014C 0x00301: 0x01E52 + "\x00\x054\x00` \x1eS" + // 0x0014D 0x00301: 0x01E53 + "\x00\x01@\x00` \x1eT" + // 0x00050 0x00301: 0x01E54 + "\x00\x01\xc0\x00` \x1eU" + // 0x00070 0x00301: 0x01E55 + "\x00\x01@\x00`\xe0\x1eV" + // 0x00050 0x00307: 0x01E56 + "\x00\x01\xc0\x00`\xe0\x1eW" + // 0x00070 0x00307: 0x01E57 + "\x00\x01H\x00`\xe0\x1eX" + // 0x00052 0x00307: 0x01E58 + "\x00\x01\xc8\x00`\xe0\x1eY" + // 0x00072 0x00307: 0x01E59 + "\x00\x01H\x00d`\x1eZ" + // 0x00052 0x00323: 0x01E5A + "\x00\x01\xc8\x00d`\x1e[" + // 0x00072 0x00323: 0x01E5B + "\x00yh\x00`\x80\x1e\\" + // 0x01E5A 0x00304: 0x01E5C + "\x00yl\x00`\x80\x1e]" + // 0x01E5B 0x00304: 0x01E5D + "\x00\x01H\x00f \x1e^" + // 0x00052 0x00331: 0x01E5E + "\x00\x01\xc8\x00f \x1e_" + // 0x00072 0x00331: 0x01E5F + "\x00\x01L\x00`\xe0\x1e`" + // 0x00053 0x00307: 0x01E60 + "\x00\x01\xcc\x00`\xe0\x1ea" + // 0x00073 0x00307: 0x01E61 + "\x00\x01L\x00d`\x1eb" + // 0x00053 0x00323: 0x01E62 + "\x00\x01\xcc\x00d`\x1ec" + // 0x00073 0x00323: 0x01E63 + "\x00\x05h\x00`\xe0\x1ed" + // 0x0015A 0x00307: 0x01E64 + "\x00\x05l\x00`\xe0\x1ee" + // 0x0015B 0x00307: 0x01E65 + "\x00\x05\x80\x00`\xe0\x1ef" + // 0x00160 0x00307: 0x01E66 + "\x00\x05\x84\x00`\xe0\x1eg" + // 0x00161 0x00307: 0x01E67 + "\x00y\x88\x00`\xe0\x1eh" + // 0x01E62 0x00307: 0x01E68 + "\x00y\x8c\x00`\xe0\x1ei" + // 0x01E63 0x00307: 0x01E69 + "\x00\x01P\x00`\xe0\x1ej" + // 0x00054 0x00307: 0x01E6A + "\x00\x01\xd0\x00`\xe0\x1ek" + // 0x00074 0x00307: 0x01E6B + "\x00\x01P\x00d`\x1el" + // 0x00054 0x00323: 0x01E6C + "\x00\x01\xd0\x00d`\x1em" + // 0x00074 0x00323: 0x01E6D + "\x00\x01P\x00f \x1en" + // 0x00054 0x00331: 0x01E6E + "\x00\x01\xd0\x00f \x1eo" + // 0x00074 0x00331: 0x01E6F + "\x00\x01P\x00e\xa0\x1ep" + // 0x00054 0x0032D: 0x01E70 + "\x00\x01\xd0\x00e\xa0\x1eq" + // 0x00074 0x0032D: 0x01E71 + "\x00\x01T\x00d\x80\x1er" + // 0x00055 0x00324: 0x01E72 + "\x00\x01\xd4\x00d\x80\x1es" + // 0x00075 0x00324: 0x01E73 + "\x00\x01T\x00f\x00\x1et" + // 0x00055 0x00330: 0x01E74 + "\x00\x01\xd4\x00f\x00\x1eu" + // 0x00075 0x00330: 0x01E75 + "\x00\x01T\x00e\xa0\x1ev" + // 0x00055 0x0032D: 0x01E76 + "\x00\x01\xd4\x00e\xa0\x1ew" + // 0x00075 0x0032D: 0x01E77 + "\x00\x05\xa0\x00` \x1ex" + // 0x00168 0x00301: 0x01E78 + "\x00\x05\xa4\x00` \x1ey" + // 0x00169 0x00301: 0x01E79 + "\x00\x05\xa8\x00a\x00\x1ez" + // 0x0016A 0x00308: 0x01E7A + "\x00\x05\xac\x00a\x00\x1e{" + // 0x0016B 0x00308: 0x01E7B + "\x00\x01X\x00``\x1e|" + // 0x00056 0x00303: 0x01E7C + "\x00\x01\xd8\x00``\x1e}" + // 0x00076 0x00303: 0x01E7D + "\x00\x01X\x00d`\x1e~" + // 0x00056 0x00323: 0x01E7E + "\x00\x01\xd8\x00d`\x1e\x7f" + // 0x00076 0x00323: 0x01E7F + "\x00\x01\\\x00`\x00\x1e\x80" + // 0x00057 0x00300: 0x01E80 + "\x00\x01\xdc\x00`\x00\x1e\x81" + // 0x00077 0x00300: 0x01E81 + "\x00\x01\\\x00` \x1e\x82" + // 0x00057 0x00301: 0x01E82 + "\x00\x01\xdc\x00` \x1e\x83" + // 0x00077 0x00301: 0x01E83 + "\x00\x01\\\x00a\x00\x1e\x84" + // 0x00057 0x00308: 0x01E84 + "\x00\x01\xdc\x00a\x00\x1e\x85" + // 0x00077 0x00308: 0x01E85 + "\x00\x01\\\x00`\xe0\x1e\x86" + // 0x00057 0x00307: 0x01E86 + "\x00\x01\xdc\x00`\xe0\x1e\x87" + // 0x00077 0x00307: 0x01E87 + "\x00\x01\\\x00d`\x1e\x88" + // 0x00057 0x00323: 0x01E88 + "\x00\x01\xdc\x00d`\x1e\x89" + // 0x00077 0x00323: 0x01E89 + "\x00\x01`\x00`\xe0\x1e\x8a" + // 0x00058 0x00307: 0x01E8A + "\x00\x01\xe0\x00`\xe0\x1e\x8b" + // 0x00078 0x00307: 0x01E8B + "\x00\x01`\x00a\x00\x1e\x8c" + // 0x00058 0x00308: 0x01E8C + "\x00\x01\xe0\x00a\x00\x1e\x8d" + // 0x00078 0x00308: 0x01E8D + "\x00\x01d\x00`\xe0\x1e\x8e" + // 0x00059 0x00307: 0x01E8E + "\x00\x01\xe4\x00`\xe0\x1e\x8f" + // 0x00079 0x00307: 0x01E8F + "\x00\x01h\x00`@\x1e\x90" + // 0x0005A 0x00302: 0x01E90 + "\x00\x01\xe8\x00`@\x1e\x91" + // 0x0007A 0x00302: 0x01E91 + "\x00\x01h\x00d`\x1e\x92" + // 0x0005A 0x00323: 0x01E92 + "\x00\x01\xe8\x00d`\x1e\x93" + // 0x0007A 0x00323: 0x01E93 + "\x00\x01h\x00f \x1e\x94" + // 0x0005A 0x00331: 0x01E94 + "\x00\x01\xe8\x00f \x1e\x95" + // 0x0007A 0x00331: 0x01E95 + "\x00\x01\xa0\x00f \x1e\x96" + // 0x00068 0x00331: 0x01E96 + "\x00\x01\xd0\x00a\x00\x1e\x97" + // 0x00074 0x00308: 0x01E97 + "\x00\x01\xdc\x00a@\x1e\x98" + // 0x00077 0x0030A: 0x01E98 + "\x00\x01\xe4\x00a@\x1e\x99" + // 0x00079 0x0030A: 0x01E99 + "\x00\x05\xfc\x00`\xe0\x1e\x9b" + // 0x0017F 0x00307: 0x01E9B + "\x00\x01\x04\x00d`\x1e\xa0" + // 0x00041 0x00323: 0x01EA0 + "\x00\x01\x84\x00d`\x1e\xa1" + // 0x00061 0x00323: 0x01EA1 + "\x00\x01\x04\x00a \x1e\xa2" + // 0x00041 0x00309: 0x01EA2 + "\x00\x01\x84\x00a \x1e\xa3" + // 0x00061 0x00309: 0x01EA3 + "\x00\x03\b\x00` \x1e\xa4" + // 0x000C2 0x00301: 0x01EA4 + "\x00\x03\x88\x00` \x1e\xa5" + // 0x000E2 0x00301: 0x01EA5 + "\x00\x03\b\x00`\x00\x1e\xa6" + // 0x000C2 0x00300: 0x01EA6 + "\x00\x03\x88\x00`\x00\x1e\xa7" + // 0x000E2 0x00300: 0x01EA7 + "\x00\x03\b\x00a \x1e\xa8" + // 0x000C2 0x00309: 0x01EA8 + "\x00\x03\x88\x00a \x1e\xa9" + // 0x000E2 0x00309: 0x01EA9 + "\x00\x03\b\x00``\x1e\xaa" + // 0x000C2 0x00303: 0x01EAA + "\x00\x03\x88\x00``\x1e\xab" + // 0x000E2 0x00303: 0x01EAB + "\x00z\x80\x00`@\x1e\xac" + // 0x01EA0 0x00302: 0x01EAC + "\x00z\x84\x00`@\x1e\xad" + // 0x01EA1 0x00302: 0x01EAD + "\x00\x04\b\x00` \x1e\xae" + // 0x00102 0x00301: 0x01EAE + "\x00\x04\f\x00` \x1e\xaf" + // 0x00103 0x00301: 0x01EAF + "\x00\x04\b\x00`\x00\x1e\xb0" + // 0x00102 0x00300: 0x01EB0 + "\x00\x04\f\x00`\x00\x1e\xb1" + // 0x00103 0x00300: 0x01EB1 + "\x00\x04\b\x00a \x1e\xb2" + // 0x00102 0x00309: 0x01EB2 + "\x00\x04\f\x00a \x1e\xb3" + // 0x00103 0x00309: 0x01EB3 + "\x00\x04\b\x00``\x1e\xb4" + // 0x00102 0x00303: 0x01EB4 + "\x00\x04\f\x00``\x1e\xb5" + // 0x00103 0x00303: 0x01EB5 + "\x00z\x80\x00`\xc0\x1e\xb6" + // 0x01EA0 0x00306: 0x01EB6 + "\x00z\x84\x00`\xc0\x1e\xb7" + // 0x01EA1 0x00306: 0x01EB7 + "\x00\x01\x14\x00d`\x1e\xb8" + // 0x00045 0x00323: 0x01EB8 + "\x00\x01\x94\x00d`\x1e\xb9" + // 0x00065 0x00323: 0x01EB9 + "\x00\x01\x14\x00a \x1e\xba" + // 0x00045 0x00309: 0x01EBA + "\x00\x01\x94\x00a \x1e\xbb" + // 0x00065 0x00309: 0x01EBB + "\x00\x01\x14\x00``\x1e\xbc" + // 0x00045 0x00303: 0x01EBC + "\x00\x01\x94\x00``\x1e\xbd" + // 0x00065 0x00303: 0x01EBD + "\x00\x03(\x00` \x1e\xbe" + // 0x000CA 0x00301: 0x01EBE + "\x00\x03\xa8\x00` \x1e\xbf" + // 0x000EA 0x00301: 0x01EBF + "\x00\x03(\x00`\x00\x1e\xc0" + // 0x000CA 0x00300: 0x01EC0 + "\x00\x03\xa8\x00`\x00\x1e\xc1" + // 0x000EA 0x00300: 0x01EC1 + "\x00\x03(\x00a \x1e\xc2" + // 0x000CA 0x00309: 0x01EC2 + "\x00\x03\xa8\x00a \x1e\xc3" + // 0x000EA 0x00309: 0x01EC3 + "\x00\x03(\x00``\x1e\xc4" + // 0x000CA 0x00303: 0x01EC4 + "\x00\x03\xa8\x00``\x1e\xc5" + // 0x000EA 0x00303: 0x01EC5 + "\x00z\xe0\x00`@\x1e\xc6" + // 0x01EB8 0x00302: 0x01EC6 + "\x00z\xe4\x00`@\x1e\xc7" + // 0x01EB9 0x00302: 0x01EC7 + "\x00\x01$\x00a \x1e\xc8" + // 0x00049 0x00309: 0x01EC8 + "\x00\x01\xa4\x00a \x1e\xc9" + // 0x00069 0x00309: 0x01EC9 + "\x00\x01$\x00d`\x1e\xca" + // 0x00049 0x00323: 0x01ECA + "\x00\x01\xa4\x00d`\x1e\xcb" + // 0x00069 0x00323: 0x01ECB + "\x00\x01<\x00d`\x1e\xcc" + // 0x0004F 0x00323: 0x01ECC + "\x00\x01\xbc\x00d`\x1e\xcd" + // 0x0006F 0x00323: 0x01ECD + "\x00\x01<\x00a \x1e\xce" + // 0x0004F 0x00309: 0x01ECE + "\x00\x01\xbc\x00a \x1e\xcf" + // 0x0006F 0x00309: 0x01ECF + "\x00\x03P\x00` \x1e\xd0" + // 0x000D4 0x00301: 0x01ED0 + "\x00\x03\xd0\x00` \x1e\xd1" + // 0x000F4 0x00301: 0x01ED1 + "\x00\x03P\x00`\x00\x1e\xd2" + // 0x000D4 0x00300: 0x01ED2 + "\x00\x03\xd0\x00`\x00\x1e\xd3" + // 0x000F4 0x00300: 0x01ED3 + "\x00\x03P\x00a \x1e\xd4" + // 0x000D4 0x00309: 0x01ED4 + "\x00\x03\xd0\x00a \x1e\xd5" + // 0x000F4 0x00309: 0x01ED5 + "\x00\x03P\x00``\x1e\xd6" + // 0x000D4 0x00303: 0x01ED6 + "\x00\x03\xd0\x00``\x1e\xd7" + // 0x000F4 0x00303: 0x01ED7 + "\x00{0\x00`@\x1e\xd8" + // 0x01ECC 0x00302: 0x01ED8 + "\x00{4\x00`@\x1e\xd9" + // 0x01ECD 0x00302: 0x01ED9 + "\x00\x06\x80\x00` \x1e\xda" + // 0x001A0 0x00301: 0x01EDA + "\x00\x06\x84\x00` \x1e\xdb" + // 0x001A1 0x00301: 0x01EDB + "\x00\x06\x80\x00`\x00\x1e\xdc" + // 0x001A0 0x00300: 0x01EDC + "\x00\x06\x84\x00`\x00\x1e\xdd" + // 0x001A1 0x00300: 0x01EDD + "\x00\x06\x80\x00a \x1e\xde" + // 0x001A0 0x00309: 0x01EDE + "\x00\x06\x84\x00a \x1e\xdf" + // 0x001A1 0x00309: 0x01EDF + "\x00\x06\x80\x00``\x1e\xe0" + // 0x001A0 0x00303: 0x01EE0 + "\x00\x06\x84\x00``\x1e\xe1" + // 0x001A1 0x00303: 0x01EE1 + "\x00\x06\x80\x00d`\x1e\xe2" + // 0x001A0 0x00323: 0x01EE2 + "\x00\x06\x84\x00d`\x1e\xe3" + // 0x001A1 0x00323: 0x01EE3 + "\x00\x01T\x00d`\x1e\xe4" + // 0x00055 0x00323: 0x01EE4 + "\x00\x01\xd4\x00d`\x1e\xe5" + // 0x00075 0x00323: 0x01EE5 + "\x00\x01T\x00a \x1e\xe6" + // 0x00055 0x00309: 0x01EE6 + "\x00\x01\xd4\x00a \x1e\xe7" + // 0x00075 0x00309: 0x01EE7 + "\x00\x06\xbc\x00` \x1e\xe8" + // 0x001AF 0x00301: 0x01EE8 + "\x00\x06\xc0\x00` \x1e\xe9" + // 0x001B0 0x00301: 0x01EE9 + "\x00\x06\xbc\x00`\x00\x1e\xea" + // 0x001AF 0x00300: 0x01EEA + "\x00\x06\xc0\x00`\x00\x1e\xeb" + // 0x001B0 0x00300: 0x01EEB + "\x00\x06\xbc\x00a \x1e\xec" + // 0x001AF 0x00309: 0x01EEC + "\x00\x06\xc0\x00a \x1e\xed" + // 0x001B0 0x00309: 0x01EED + "\x00\x06\xbc\x00``\x1e\xee" + // 0x001AF 0x00303: 0x01EEE + "\x00\x06\xc0\x00``\x1e\xef" + // 0x001B0 0x00303: 0x01EEF + "\x00\x06\xbc\x00d`\x1e\xf0" + // 0x001AF 0x00323: 0x01EF0 + "\x00\x06\xc0\x00d`\x1e\xf1" + // 0x001B0 0x00323: 0x01EF1 + "\x00\x01d\x00`\x00\x1e\xf2" + // 0x00059 0x00300: 0x01EF2 + "\x00\x01\xe4\x00`\x00\x1e\xf3" + // 0x00079 0x00300: 0x01EF3 + "\x00\x01d\x00d`\x1e\xf4" + // 0x00059 0x00323: 0x01EF4 + "\x00\x01\xe4\x00d`\x1e\xf5" + // 0x00079 0x00323: 0x01EF5 + "\x00\x01d\x00a \x1e\xf6" + // 0x00059 0x00309: 0x01EF6 + "\x00\x01\xe4\x00a \x1e\xf7" + // 0x00079 0x00309: 0x01EF7 + "\x00\x01d\x00``\x1e\xf8" + // 0x00059 0x00303: 0x01EF8 + "\x00\x01\xe4\x00``\x1e\xf9" + // 0x00079 0x00303: 0x01EF9 + "\x00\x0e\xc4\x00b`\x1f\x00" + // 0x003B1 0x00313: 0x01F00 + "\x00\x0e\xc4\x00b\x80\x1f\x01" + // 0x003B1 0x00314: 0x01F01 + "\x00|\x00\x00`\x00\x1f\x02" + // 0x01F00 0x00300: 0x01F02 + "\x00|\x04\x00`\x00\x1f\x03" + // 0x01F01 0x00300: 0x01F03 + "\x00|\x00\x00` \x1f\x04" + // 0x01F00 0x00301: 0x01F04 + "\x00|\x04\x00` \x1f\x05" + // 0x01F01 0x00301: 0x01F05 + "\x00|\x00\x00h@\x1f\x06" + // 0x01F00 0x00342: 0x01F06 + "\x00|\x04\x00h@\x1f\a" + // 0x01F01 0x00342: 0x01F07 + "\x00\x0eD\x00b`\x1f\b" + // 0x00391 0x00313: 0x01F08 + "\x00\x0eD\x00b\x80\x1f\t" + // 0x00391 0x00314: 0x01F09 + "\x00| \x00`\x00\x1f\n" + // 0x01F08 0x00300: 0x01F0A + "\x00|$\x00`\x00\x1f\v" + // 0x01F09 0x00300: 0x01F0B + "\x00| \x00` \x1f\f" + // 0x01F08 0x00301: 0x01F0C + "\x00|$\x00` \x1f\r" + // 0x01F09 0x00301: 0x01F0D + "\x00| \x00h@\x1f\x0e" + // 0x01F08 0x00342: 0x01F0E + "\x00|$\x00h@\x1f\x0f" + // 0x01F09 0x00342: 0x01F0F + "\x00\x0e\xd4\x00b`\x1f\x10" + // 0x003B5 0x00313: 0x01F10 + "\x00\x0e\xd4\x00b\x80\x1f\x11" + // 0x003B5 0x00314: 0x01F11 + "\x00|@\x00`\x00\x1f\x12" + // 0x01F10 0x00300: 0x01F12 + "\x00|D\x00`\x00\x1f\x13" + // 0x01F11 0x00300: 0x01F13 + "\x00|@\x00` \x1f\x14" + // 0x01F10 0x00301: 0x01F14 + "\x00|D\x00` \x1f\x15" + // 0x01F11 0x00301: 0x01F15 + "\x00\x0eT\x00b`\x1f\x18" + // 0x00395 0x00313: 0x01F18 + "\x00\x0eT\x00b\x80\x1f\x19" + // 0x00395 0x00314: 0x01F19 + "\x00|`\x00`\x00\x1f\x1a" + // 0x01F18 0x00300: 0x01F1A + "\x00|d\x00`\x00\x1f\x1b" + // 0x01F19 0x00300: 0x01F1B + "\x00|`\x00` \x1f\x1c" + // 0x01F18 0x00301: 0x01F1C + "\x00|d\x00` \x1f\x1d" + // 0x01F19 0x00301: 0x01F1D + "\x00\x0e\xdc\x00b`\x1f " + // 0x003B7 0x00313: 0x01F20 + "\x00\x0e\xdc\x00b\x80\x1f!" + // 0x003B7 0x00314: 0x01F21 + "\x00|\x80\x00`\x00\x1f\"" + // 0x01F20 0x00300: 0x01F22 + "\x00|\x84\x00`\x00\x1f#" + // 0x01F21 0x00300: 0x01F23 + "\x00|\x80\x00` \x1f$" + // 0x01F20 0x00301: 0x01F24 + "\x00|\x84\x00` \x1f%" + // 0x01F21 0x00301: 0x01F25 + "\x00|\x80\x00h@\x1f&" + // 0x01F20 0x00342: 0x01F26 + "\x00|\x84\x00h@\x1f'" + // 0x01F21 0x00342: 0x01F27 + "\x00\x0e\\\x00b`\x1f(" + // 0x00397 0x00313: 0x01F28 + "\x00\x0e\\\x00b\x80\x1f)" + // 0x00397 0x00314: 0x01F29 + "\x00|\xa0\x00`\x00\x1f*" + // 0x01F28 0x00300: 0x01F2A + "\x00|\xa4\x00`\x00\x1f+" + // 0x01F29 0x00300: 0x01F2B + "\x00|\xa0\x00` \x1f," + // 0x01F28 0x00301: 0x01F2C + "\x00|\xa4\x00` \x1f-" + // 0x01F29 0x00301: 0x01F2D + "\x00|\xa0\x00h@\x1f." + // 0x01F28 0x00342: 0x01F2E + "\x00|\xa4\x00h@\x1f/" + // 0x01F29 0x00342: 0x01F2F + "\x00\x0e\xe4\x00b`\x1f0" + // 0x003B9 0x00313: 0x01F30 + "\x00\x0e\xe4\x00b\x80\x1f1" + // 0x003B9 0x00314: 0x01F31 + "\x00|\xc0\x00`\x00\x1f2" + // 0x01F30 0x00300: 0x01F32 + "\x00|\xc4\x00`\x00\x1f3" + // 0x01F31 0x00300: 0x01F33 + "\x00|\xc0\x00` \x1f4" + // 0x01F30 0x00301: 0x01F34 + "\x00|\xc4\x00` \x1f5" + // 0x01F31 0x00301: 0x01F35 + "\x00|\xc0\x00h@\x1f6" + // 0x01F30 0x00342: 0x01F36 + "\x00|\xc4\x00h@\x1f7" + // 0x01F31 0x00342: 0x01F37 + "\x00\x0ed\x00b`\x1f8" + // 0x00399 0x00313: 0x01F38 + "\x00\x0ed\x00b\x80\x1f9" + // 0x00399 0x00314: 0x01F39 + "\x00|\xe0\x00`\x00\x1f:" + // 0x01F38 0x00300: 0x01F3A + "\x00|\xe4\x00`\x00\x1f;" + // 0x01F39 0x00300: 0x01F3B + "\x00|\xe0\x00` \x1f<" + // 0x01F38 0x00301: 0x01F3C + "\x00|\xe4\x00` \x1f=" + // 0x01F39 0x00301: 0x01F3D + "\x00|\xe0\x00h@\x1f>" + // 0x01F38 0x00342: 0x01F3E + "\x00|\xe4\x00h@\x1f?" + // 0x01F39 0x00342: 0x01F3F + "\x00\x0e\xfc\x00b`\x1f@" + // 0x003BF 0x00313: 0x01F40 + "\x00\x0e\xfc\x00b\x80\x1fA" + // 0x003BF 0x00314: 0x01F41 + "\x00}\x00\x00`\x00\x1fB" + // 0x01F40 0x00300: 0x01F42 + "\x00}\x04\x00`\x00\x1fC" + // 0x01F41 0x00300: 0x01F43 + "\x00}\x00\x00` \x1fD" + // 0x01F40 0x00301: 0x01F44 + "\x00}\x04\x00` \x1fE" + // 0x01F41 0x00301: 0x01F45 + "\x00\x0e|\x00b`\x1fH" + // 0x0039F 0x00313: 0x01F48 + "\x00\x0e|\x00b\x80\x1fI" + // 0x0039F 0x00314: 0x01F49 + "\x00} \x00`\x00\x1fJ" + // 0x01F48 0x00300: 0x01F4A + "\x00}$\x00`\x00\x1fK" + // 0x01F49 0x00300: 0x01F4B + "\x00} \x00` \x1fL" + // 0x01F48 0x00301: 0x01F4C + "\x00}$\x00` \x1fM" + // 0x01F49 0x00301: 0x01F4D + "\x00\x0f\x14\x00b`\x1fP" + // 0x003C5 0x00313: 0x01F50 + "\x00\x0f\x14\x00b\x80\x1fQ" + // 0x003C5 0x00314: 0x01F51 + "\x00}@\x00`\x00\x1fR" + // 0x01F50 0x00300: 0x01F52 + "\x00}D\x00`\x00\x1fS" + // 0x01F51 0x00300: 0x01F53 + "\x00}@\x00` \x1fT" + // 0x01F50 0x00301: 0x01F54 + "\x00}D\x00` \x1fU" + // 0x01F51 0x00301: 0x01F55 + "\x00}@\x00h@\x1fV" + // 0x01F50 0x00342: 0x01F56 + "\x00}D\x00h@\x1fW" + // 0x01F51 0x00342: 0x01F57 + "\x00\x0e\x94\x00b\x80\x1fY" + // 0x003A5 0x00314: 0x01F59 + "\x00}d\x00`\x00\x1f[" + // 0x01F59 0x00300: 0x01F5B + "\x00}d\x00` \x1f]" + // 0x01F59 0x00301: 0x01F5D + "\x00}d\x00h@\x1f_" + // 0x01F59 0x00342: 0x01F5F + "\x00\x0f$\x00b`\x1f`" + // 0x003C9 0x00313: 0x01F60 + "\x00\x0f$\x00b\x80\x1fa" + // 0x003C9 0x00314: 0x01F61 + "\x00}\x80\x00`\x00\x1fb" + // 0x01F60 0x00300: 0x01F62 + "\x00}\x84\x00`\x00\x1fc" + // 0x01F61 0x00300: 0x01F63 + "\x00}\x80\x00` \x1fd" + // 0x01F60 0x00301: 0x01F64 + "\x00}\x84\x00` \x1fe" + // 0x01F61 0x00301: 0x01F65 + "\x00}\x80\x00h@\x1ff" + // 0x01F60 0x00342: 0x01F66 + "\x00}\x84\x00h@\x1fg" + // 0x01F61 0x00342: 0x01F67 + "\x00\x0e\xa4\x00b`\x1fh" + // 0x003A9 0x00313: 0x01F68 + "\x00\x0e\xa4\x00b\x80\x1fi" + // 0x003A9 0x00314: 0x01F69 + "\x00}\xa0\x00`\x00\x1fj" + // 0x01F68 0x00300: 0x01F6A + "\x00}\xa4\x00`\x00\x1fk" + // 0x01F69 0x00300: 0x01F6B + "\x00}\xa0\x00` \x1fl" + // 0x01F68 0x00301: 0x01F6C + "\x00}\xa4\x00` \x1fm" + // 0x01F69 0x00301: 0x01F6D + "\x00}\xa0\x00h@\x1fn" + // 0x01F68 0x00342: 0x01F6E + "\x00}\xa4\x00h@\x1fo" + // 0x01F69 0x00342: 0x01F6F + "\x00\x0e\xc4\x00`\x00\x1fp" + // 0x003B1 0x00300: 0x01F70 + "\x00\x0e\xd4\x00`\x00\x1fr" + // 0x003B5 0x00300: 0x01F72 + "\x00\x0e\xdc\x00`\x00\x1ft" + // 0x003B7 0x00300: 0x01F74 + "\x00\x0e\xe4\x00`\x00\x1fv" + // 0x003B9 0x00300: 0x01F76 + "\x00\x0e\xfc\x00`\x00\x1fx" + // 0x003BF 0x00300: 0x01F78 + "\x00\x0f\x14\x00`\x00\x1fz" + // 0x003C5 0x00300: 0x01F7A + "\x00\x0f$\x00`\x00\x1f|" + // 0x003C9 0x00300: 0x01F7C + "\x00|\x00\x00h\xa0\x1f\x80" + // 0x01F00 0x00345: 0x01F80 + "\x00|\x04\x00h\xa0\x1f\x81" + // 0x01F01 0x00345: 0x01F81 + "\x00|\b\x00h\xa0\x1f\x82" + // 0x01F02 0x00345: 0x01F82 + "\x00|\f\x00h\xa0\x1f\x83" + // 0x01F03 0x00345: 0x01F83 + "\x00|\x10\x00h\xa0\x1f\x84" + // 0x01F04 0x00345: 0x01F84 + "\x00|\x14\x00h\xa0\x1f\x85" + // 0x01F05 0x00345: 0x01F85 + "\x00|\x18\x00h\xa0\x1f\x86" + // 0x01F06 0x00345: 0x01F86 + "\x00|\x1c\x00h\xa0\x1f\x87" + // 0x01F07 0x00345: 0x01F87 + "\x00| \x00h\xa0\x1f\x88" + // 0x01F08 0x00345: 0x01F88 + "\x00|$\x00h\xa0\x1f\x89" + // 0x01F09 0x00345: 0x01F89 + "\x00|(\x00h\xa0\x1f\x8a" + // 0x01F0A 0x00345: 0x01F8A + "\x00|,\x00h\xa0\x1f\x8b" + // 0x01F0B 0x00345: 0x01F8B + "\x00|0\x00h\xa0\x1f\x8c" + // 0x01F0C 0x00345: 0x01F8C + "\x00|4\x00h\xa0\x1f\x8d" + // 0x01F0D 0x00345: 0x01F8D + "\x00|8\x00h\xa0\x1f\x8e" + // 0x01F0E 0x00345: 0x01F8E + "\x00|<\x00h\xa0\x1f\x8f" + // 0x01F0F 0x00345: 0x01F8F + "\x00|\x80\x00h\xa0\x1f\x90" + // 0x01F20 0x00345: 0x01F90 + "\x00|\x84\x00h\xa0\x1f\x91" + // 0x01F21 0x00345: 0x01F91 + "\x00|\x88\x00h\xa0\x1f\x92" + // 0x01F22 0x00345: 0x01F92 + "\x00|\x8c\x00h\xa0\x1f\x93" + // 0x01F23 0x00345: 0x01F93 + "\x00|\x90\x00h\xa0\x1f\x94" + // 0x01F24 0x00345: 0x01F94 + "\x00|\x94\x00h\xa0\x1f\x95" + // 0x01F25 0x00345: 0x01F95 + "\x00|\x98\x00h\xa0\x1f\x96" + // 0x01F26 0x00345: 0x01F96 + "\x00|\x9c\x00h\xa0\x1f\x97" + // 0x01F27 0x00345: 0x01F97 + "\x00|\xa0\x00h\xa0\x1f\x98" + // 0x01F28 0x00345: 0x01F98 + "\x00|\xa4\x00h\xa0\x1f\x99" + // 0x01F29 0x00345: 0x01F99 + "\x00|\xa8\x00h\xa0\x1f\x9a" + // 0x01F2A 0x00345: 0x01F9A + "\x00|\xac\x00h\xa0\x1f\x9b" + // 0x01F2B 0x00345: 0x01F9B + "\x00|\xb0\x00h\xa0\x1f\x9c" + // 0x01F2C 0x00345: 0x01F9C + "\x00|\xb4\x00h\xa0\x1f\x9d" + // 0x01F2D 0x00345: 0x01F9D + "\x00|\xb8\x00h\xa0\x1f\x9e" + // 0x01F2E 0x00345: 0x01F9E + "\x00|\xbc\x00h\xa0\x1f\x9f" + // 0x01F2F 0x00345: 0x01F9F + "\x00}\x80\x00h\xa0\x1f\xa0" + // 0x01F60 0x00345: 0x01FA0 + "\x00}\x84\x00h\xa0\x1f\xa1" + // 0x01F61 0x00345: 0x01FA1 + "\x00}\x88\x00h\xa0\x1f\xa2" + // 0x01F62 0x00345: 0x01FA2 + "\x00}\x8c\x00h\xa0\x1f\xa3" + // 0x01F63 0x00345: 0x01FA3 + "\x00}\x90\x00h\xa0\x1f\xa4" + // 0x01F64 0x00345: 0x01FA4 + "\x00}\x94\x00h\xa0\x1f\xa5" + // 0x01F65 0x00345: 0x01FA5 + "\x00}\x98\x00h\xa0\x1f\xa6" + // 0x01F66 0x00345: 0x01FA6 + "\x00}\x9c\x00h\xa0\x1f\xa7" + // 0x01F67 0x00345: 0x01FA7 + "\x00}\xa0\x00h\xa0\x1f\xa8" + // 0x01F68 0x00345: 0x01FA8 + "\x00}\xa4\x00h\xa0\x1f\xa9" + // 0x01F69 0x00345: 0x01FA9 + "\x00}\xa8\x00h\xa0\x1f\xaa" + // 0x01F6A 0x00345: 0x01FAA + "\x00}\xac\x00h\xa0\x1f\xab" + // 0x01F6B 0x00345: 0x01FAB + "\x00}\xb0\x00h\xa0\x1f\xac" + // 0x01F6C 0x00345: 0x01FAC + "\x00}\xb4\x00h\xa0\x1f\xad" + // 0x01F6D 0x00345: 0x01FAD + "\x00}\xb8\x00h\xa0\x1f\xae" + // 0x01F6E 0x00345: 0x01FAE + "\x00}\xbc\x00h\xa0\x1f\xaf" + // 0x01F6F 0x00345: 0x01FAF + "\x00\x0e\xc4\x00`\xc0\x1f\xb0" + // 0x003B1 0x00306: 0x01FB0 + "\x00\x0e\xc4\x00`\x80\x1f\xb1" + // 0x003B1 0x00304: 0x01FB1 + "\x00}\xc0\x00h\xa0\x1f\xb2" + // 0x01F70 0x00345: 0x01FB2 + "\x00\x0e\xc4\x00h\xa0\x1f\xb3" + // 0x003B1 0x00345: 0x01FB3 + "\x00\x0e\xb0\x00h\xa0\x1f\xb4" + // 0x003AC 0x00345: 0x01FB4 + "\x00\x0e\xc4\x00h@\x1f\xb6" + // 0x003B1 0x00342: 0x01FB6 + "\x00~\xd8\x00h\xa0\x1f\xb7" + // 0x01FB6 0x00345: 0x01FB7 + "\x00\x0eD\x00`\xc0\x1f\xb8" + // 0x00391 0x00306: 0x01FB8 + "\x00\x0eD\x00`\x80\x1f\xb9" + // 0x00391 0x00304: 0x01FB9 + "\x00\x0eD\x00`\x00\x1f\xba" + // 0x00391 0x00300: 0x01FBA + "\x00\x0eD\x00h\xa0\x1f\xbc" + // 0x00391 0x00345: 0x01FBC + "\x00\x02\xa0\x00h@\x1f\xc1" + // 0x000A8 0x00342: 0x01FC1 + "\x00}\xd0\x00h\xa0\x1f\xc2" + // 0x01F74 0x00345: 0x01FC2 + "\x00\x0e\xdc\x00h\xa0\x1f\xc3" + // 0x003B7 0x00345: 0x01FC3 + "\x00\x0e\xb8\x00h\xa0\x1f\xc4" + // 0x003AE 0x00345: 0x01FC4 + "\x00\x0e\xdc\x00h@\x1f\xc6" + // 0x003B7 0x00342: 0x01FC6 + "\x00\x7f\x18\x00h\xa0\x1f\xc7" + // 0x01FC6 0x00345: 0x01FC7 + "\x00\x0eT\x00`\x00\x1f\xc8" + // 0x00395 0x00300: 0x01FC8 + "\x00\x0e\\\x00`\x00\x1f\xca" + // 0x00397 0x00300: 0x01FCA + "\x00\x0e\\\x00h\xa0\x1f\xcc" + // 0x00397 0x00345: 0x01FCC + "\x00~\xfc\x00`\x00\x1f\xcd" + // 0x01FBF 0x00300: 0x01FCD + "\x00~\xfc\x00` \x1f\xce" + // 0x01FBF 0x00301: 0x01FCE + "\x00~\xfc\x00h@\x1f\xcf" + // 0x01FBF 0x00342: 0x01FCF + "\x00\x0e\xe4\x00`\xc0\x1f\xd0" + // 0x003B9 0x00306: 0x01FD0 + "\x00\x0e\xe4\x00`\x80\x1f\xd1" + // 0x003B9 0x00304: 0x01FD1 + "\x00\x0f(\x00`\x00\x1f\xd2" + // 0x003CA 0x00300: 0x01FD2 + "\x00\x0e\xe4\x00h@\x1f\xd6" + // 0x003B9 0x00342: 0x01FD6 + "\x00\x0f(\x00h@\x1f\xd7" + // 0x003CA 0x00342: 0x01FD7 + "\x00\x0ed\x00`\xc0\x1f\xd8" + // 0x00399 0x00306: 0x01FD8 + "\x00\x0ed\x00`\x80\x1f\xd9" + // 0x00399 0x00304: 0x01FD9 + "\x00\x0ed\x00`\x00\x1f\xda" + // 0x00399 0x00300: 0x01FDA + "\x00\x7f\xf8\x00`\x00\x1f\xdd" + // 0x01FFE 0x00300: 0x01FDD + "\x00\x7f\xf8\x00` \x1f\xde" + // 0x01FFE 0x00301: 0x01FDE + "\x00\x7f\xf8\x00h@\x1f\xdf" + // 0x01FFE 0x00342: 0x01FDF + "\x00\x0f\x14\x00`\xc0\x1f\xe0" + // 0x003C5 0x00306: 0x01FE0 + "\x00\x0f\x14\x00`\x80\x1f\xe1" + // 0x003C5 0x00304: 0x01FE1 + "\x00\x0f,\x00`\x00\x1f\xe2" + // 0x003CB 0x00300: 0x01FE2 + "\x00\x0f\x04\x00b`\x1f\xe4" + // 0x003C1 0x00313: 0x01FE4 + "\x00\x0f\x04\x00b\x80\x1f\xe5" + // 0x003C1 0x00314: 0x01FE5 + "\x00\x0f\x14\x00h@\x1f\xe6" + // 0x003C5 0x00342: 0x01FE6 + "\x00\x0f,\x00h@\x1f\xe7" + // 0x003CB 0x00342: 0x01FE7 + "\x00\x0e\x94\x00`\xc0\x1f\xe8" + // 0x003A5 0x00306: 0x01FE8 + "\x00\x0e\x94\x00`\x80\x1f\xe9" + // 0x003A5 0x00304: 0x01FE9 + "\x00\x0e\x94\x00`\x00\x1f\xea" + // 0x003A5 0x00300: 0x01FEA + "\x00\x0e\x84\x00b\x80\x1f\xec" + // 0x003A1 0x00314: 0x01FEC + "\x00\x02\xa0\x00`\x00\x1f\xed" + // 0x000A8 0x00300: 0x01FED + "\x00}\xf0\x00h\xa0\x1f\xf2" + // 0x01F7C 0x00345: 0x01FF2 + "\x00\x0f$\x00h\xa0\x1f\xf3" + // 0x003C9 0x00345: 0x01FF3 + "\x00\x0f8\x00h\xa0\x1f\xf4" + // 0x003CE 0x00345: 0x01FF4 + "\x00\x0f$\x00h@\x1f\xf6" + // 0x003C9 0x00342: 0x01FF6 + "\x00\x7f\xd8\x00h\xa0\x1f\xf7" + // 0x01FF6 0x00345: 0x01FF7 + "\x00\x0e|\x00`\x00\x1f\xf8" + // 0x0039F 0x00300: 0x01FF8 + "\x00\x0e\xa4\x00`\x00\x1f\xfa" + // 0x003A9 0x00300: 0x01FFA + "\x00\x0e\xa4\x00h\xa0\x1f\xfc" + // 0x003A9 0x00345: 0x01FFC + "\x00\x86@\x00g\x00!\x9a" + // 0x02190 0x00338: 0x0219A + "\x00\x86H\x00g\x00!\x9b" + // 0x02192 0x00338: 0x0219B + "\x00\x86P\x00g\x00!\xae" + // 0x02194 0x00338: 0x021AE + "\x00\x87@\x00g\x00!\xcd" + // 0x021D0 0x00338: 0x021CD + "\x00\x87P\x00g\x00!\xce" + // 0x021D4 0x00338: 0x021CE + "\x00\x87H\x00g\x00!\xcf" + // 0x021D2 0x00338: 0x021CF + "\x00\x88\f\x00g\x00\"\x04" + // 0x02203 0x00338: 0x02204 + "\x00\x88 \x00g\x00\"\t" + // 0x02208 0x00338: 0x02209 + "\x00\x88,\x00g\x00\"\f" + // 0x0220B 0x00338: 0x0220C + "\x00\x88\x8c\x00g\x00\"$" + // 0x02223 0x00338: 0x02224 + "\x00\x88\x94\x00g\x00\"&" + // 0x02225 0x00338: 0x02226 + "\x00\x88\xf0\x00g\x00\"A" + // 0x0223C 0x00338: 0x02241 + "\x00\x89\f\x00g\x00\"D" + // 0x02243 0x00338: 0x02244 + "\x00\x89\x14\x00g\x00\"G" + // 0x02245 0x00338: 0x02247 + "\x00\x89 \x00g\x00\"I" + // 0x02248 0x00338: 0x02249 + "\x00\x00\xf4\x00g\x00\"`" + // 0x0003D 0x00338: 0x02260 + "\x00\x89\x84\x00g\x00\"b" + // 0x02261 0x00338: 0x02262 + "\x00\x894\x00g\x00\"m" + // 0x0224D 0x00338: 0x0226D + "\x00\x00\xf0\x00g\x00\"n" + // 0x0003C 0x00338: 0x0226E + "\x00\x00\xf8\x00g\x00\"o" + // 0x0003E 0x00338: 0x0226F + "\x00\x89\x90\x00g\x00\"p" + // 0x02264 0x00338: 0x02270 + "\x00\x89\x94\x00g\x00\"q" + // 0x02265 0x00338: 0x02271 + "\x00\x89\xc8\x00g\x00\"t" + // 0x02272 0x00338: 0x02274 + "\x00\x89\xcc\x00g\x00\"u" + // 0x02273 0x00338: 0x02275 + "\x00\x89\xd8\x00g\x00\"x" + // 0x02276 0x00338: 0x02278 + "\x00\x89\xdc\x00g\x00\"y" + // 0x02277 0x00338: 0x02279 + "\x00\x89\xe8\x00g\x00\"\x80" + // 0x0227A 0x00338: 0x02280 + "\x00\x89\xec\x00g\x00\"\x81" + // 0x0227B 0x00338: 0x02281 + "\x00\x8a\b\x00g\x00\"\x84" + // 0x02282 0x00338: 0x02284 + "\x00\x8a\f\x00g\x00\"\x85" + // 0x02283 0x00338: 0x02285 + "\x00\x8a\x18\x00g\x00\"\x88" + // 0x02286 0x00338: 0x02288 + "\x00\x8a\x1c\x00g\x00\"\x89" + // 0x02287 0x00338: 0x02289 + "\x00\x8a\x88\x00g\x00\"\xac" + // 0x022A2 0x00338: 0x022AC + "\x00\x8a\xa0\x00g\x00\"\xad" + // 0x022A8 0x00338: 0x022AD + "\x00\x8a\xa4\x00g\x00\"\xae" + // 0x022A9 0x00338: 0x022AE + "\x00\x8a\xac\x00g\x00\"\xaf" + // 0x022AB 0x00338: 0x022AF + "\x00\x89\xf0\x00g\x00\"\xe0" + // 0x0227C 0x00338: 0x022E0 + "\x00\x89\xf4\x00g\x00\"\xe1" + // 0x0227D 0x00338: 0x022E1 + "\x00\x8aD\x00g\x00\"\xe2" + // 0x02291 0x00338: 0x022E2 + "\x00\x8aH\x00g\x00\"\xe3" + // 0x02292 0x00338: 0x022E3 + "\x00\x8a\xc8\x00g\x00\"\xea" + // 0x022B2 0x00338: 0x022EA + "\x00\x8a\xcc\x00g\x00\"\xeb" + // 0x022B3 0x00338: 0x022EB + "\x00\x8a\xd0\x00g\x00\"\xec" + // 0x022B4 0x00338: 0x022EC + "\x00\x8a\xd4\x00g\x00\"\xed" + // 0x022B5 0x00338: 0x022ED + "\x00\xc1,\x06\x13 0L" + // 0x0304B 0x03099: 0x0304C + "\x00\xc14\x06\x13 0N" + // 0x0304D 0x03099: 0x0304E + "\x00\xc1<\x06\x13 0P" + // 0x0304F 0x03099: 0x03050 + "\x00\xc1D\x06\x13 0R" + // 0x03051 0x03099: 0x03052 + "\x00\xc1L\x06\x13 0T" + // 0x03053 0x03099: 0x03054 + "\x00\xc1T\x06\x13 0V" + // 0x03055 0x03099: 0x03056 + "\x00\xc1\\\x06\x13 0X" + // 0x03057 0x03099: 0x03058 + "\x00\xc1d\x06\x13 0Z" + // 0x03059 0x03099: 0x0305A + "\x00\xc1l\x06\x13 0\\" + // 0x0305B 0x03099: 0x0305C + "\x00\xc1t\x06\x13 0^" + // 0x0305D 0x03099: 0x0305E + "\x00\xc1|\x06\x13 0`" + // 0x0305F 0x03099: 0x03060 + "\x00\xc1\x84\x06\x13 0b" + // 0x03061 0x03099: 0x03062 + "\x00\xc1\x90\x06\x13 0e" + // 0x03064 0x03099: 0x03065 + "\x00\xc1\x98\x06\x13 0g" + // 0x03066 0x03099: 0x03067 + "\x00\xc1\xa0\x06\x13 0i" + // 0x03068 0x03099: 0x03069 + "\x00\xc1\xbc\x06\x13 0p" + // 0x0306F 0x03099: 0x03070 + "\x00\xc1\xbc\x06\x13@0q" + // 0x0306F 0x0309A: 0x03071 + "\x00\xc1\xc8\x06\x13 0s" + // 0x03072 0x03099: 0x03073 + "\x00\xc1\xc8\x06\x13@0t" + // 0x03072 0x0309A: 0x03074 + "\x00\xc1\xd4\x06\x13 0v" + // 0x03075 0x03099: 0x03076 + "\x00\xc1\xd4\x06\x13@0w" + // 0x03075 0x0309A: 0x03077 + "\x00\xc1\xe0\x06\x13 0y" + // 0x03078 0x03099: 0x03079 + "\x00\xc1\xe0\x06\x13@0z" + // 0x03078 0x0309A: 0x0307A + "\x00\xc1\xec\x06\x13 0|" + // 0x0307B 0x03099: 0x0307C + "\x00\xc1\xec\x06\x13@0}" + // 0x0307B 0x0309A: 0x0307D + "\x00\xc1\x18\x06\x13 0\x94" + // 0x03046 0x03099: 0x03094 + "\x00\xc2t\x06\x13 0\x9e" + // 0x0309D 0x03099: 0x0309E + "\x00¬\x06\x13 0\xac" + // 0x030AB 0x03099: 0x030AC + "\x00´\x06\x13 0\xae" + // 0x030AD 0x03099: 0x030AE + "\x00¼\x06\x13 0\xb0" + // 0x030AF 0x03099: 0x030B0 + "\x00\xc2\xc4\x06\x13 0\xb2" + // 0x030B1 0x03099: 0x030B2 + "\x00\xc2\xcc\x06\x13 0\xb4" + // 0x030B3 0x03099: 0x030B4 + "\x00\xc2\xd4\x06\x13 0\xb6" + // 0x030B5 0x03099: 0x030B6 + "\x00\xc2\xdc\x06\x13 0\xb8" + // 0x030B7 0x03099: 0x030B8 + "\x00\xc2\xe4\x06\x13 0\xba" + // 0x030B9 0x03099: 0x030BA + "\x00\xc2\xec\x06\x13 0\xbc" + // 0x030BB 0x03099: 0x030BC + "\x00\xc2\xf4\x06\x13 0\xbe" + // 0x030BD 0x03099: 0x030BE + "\x00\xc2\xfc\x06\x13 0\xc0" + // 0x030BF 0x03099: 0x030C0 + "\x00\xc3\x04\x06\x13 0\xc2" + // 0x030C1 0x03099: 0x030C2 + "\x00\xc3\x10\x06\x13 0\xc5" + // 0x030C4 0x03099: 0x030C5 + "\x00\xc3\x18\x06\x13 0\xc7" + // 0x030C6 0x03099: 0x030C7 + "\x00\xc3 \x06\x13 0\xc9" + // 0x030C8 0x03099: 0x030C9 + "\x00\xc3<\x06\x13 0\xd0" + // 0x030CF 0x03099: 0x030D0 + "\x00\xc3<\x06\x13@0\xd1" + // 0x030CF 0x0309A: 0x030D1 + "\x00\xc3H\x06\x13 0\xd3" + // 0x030D2 0x03099: 0x030D3 + "\x00\xc3H\x06\x13@0\xd4" + // 0x030D2 0x0309A: 0x030D4 + "\x00\xc3T\x06\x13 0\xd6" + // 0x030D5 0x03099: 0x030D6 + "\x00\xc3T\x06\x13@0\xd7" + // 0x030D5 0x0309A: 0x030D7 + "\x00\xc3`\x06\x13 0\xd9" + // 0x030D8 0x03099: 0x030D9 + "\x00\xc3`\x06\x13@0\xda" + // 0x030D8 0x0309A: 0x030DA + "\x00\xc3l\x06\x13 0\xdc" + // 0x030DB 0x03099: 0x030DC + "\x00\xc3l\x06\x13@0\xdd" + // 0x030DB 0x0309A: 0x030DD + "\x00\u0098\x06\x13 0\xf4" + // 0x030A6 0x03099: 0x030F4 + "\x00ü\x06\x13 0\xf7" + // 0x030EF 0x03099: 0x030F7 + "\x00\xc3\xc0\x06\x13 0\xf8" + // 0x030F0 0x03099: 0x030F8 + "\x00\xc3\xc4\x06\x13 0\xf9" + // 0x030F1 0x03099: 0x030F9 + "\x00\xc3\xc8\x06\x13 0\xfa" + // 0x030F2 0x03099: 0x030FA + "\x00\xc3\xf4\x06\x13 0\xfe" + // 0x030FD 0x03099: 0x030FE + "\x04\x17H\x00`\xe1\x05\xc9" + // 0x105D2 0x00307: 0x105C9 + "\x04\x17h\x00`\xe1\x05\xe4" + // 0x105DA 0x00307: 0x105E4 + "\x04Bd\"\x17A\x10\x9a" + // 0x11099 0x110BA: 0x1109A + "\x04Bl\"\x17A\x10\x9c" + // 0x1109B 0x110BA: 0x1109C + "\x04B\x94\"\x17A\x10\xab" + // 0x110A5 0x110BA: 0x110AB + "\x04D\xc4\"$\xe1\x11." + // 0x11131 0x11127: 0x1112E + "\x04D\xc8\"$\xe1\x11/" + // 0x11132 0x11127: 0x1112F + "\x04M\x1c\"g\xc1\x13K" + // 0x11347 0x1133E: 0x1134B + "\x04M\x1c\"j\xe1\x13L" + // 0x11347 0x11357: 0x1134C + "\x04N\b\"y!\x13\x83" + // 0x11382 0x113C9: 0x11383 + "\x04N\x10\"wa\x13\x85" + // 0x11384 0x113BB: 0x11385 + "\x04N,\"xA\x13\x8e" + // 0x1138B 0x113C2: 0x1138E + "\x04N@\"y!\x13\x91" + // 0x11390 0x113C9: 0x11391 + "\x04O\b\"xA\x13\xc5" + // 0x113C2 0x113C2: 0x113C5 + "\x04O\b\"w\x01\x13\xc7" + // 0x113C2 0x113B8: 0x113C7 + "\x04O\b\"y!\x13\xc8" + // 0x113C2 0x113C9: 0x113C8 + "\x04R\xe4\"\x97A\x14\xbb" + // 0x114B9 0x114BA: 0x114BB + "\x04R\xe4\"\x96\x01\x14\xbc" + // 0x114B9 0x114B0: 0x114BC + "\x04R\xe4\"\x97\xa1\x14\xbe" + // 0x114B9 0x114BD: 0x114BE + "\x04V\xe0\"\xb5\xe1\x15\xba" + // 0x115B8 0x115AF: 0x115BA + "\x04V\xe4\"\xb5\xe1\x15\xbb" + // 0x115B9 0x115AF: 0x115BB + "\x04d\xd4#&\x01\x198" + // 0x11935 0x11930: 0x11938 + "\x05\x84x,#\xc1a!" + // 0x1611E 0x1611E: 0x16121 + "\x05\x84x,%!a\"" + // 0x1611E 0x16129: 0x16122 + "\x05\x84x,#\xe1a#" + // 0x1611E 0x1611F: 0x16123 + "\x05\x84\xa4,#\xe1a$" + // 0x16129 0x1611F: 0x16124 + "\x05\x84x,$\x01a%" + // 0x1611E 0x16120: 0x16125 + "\x05\x84\x84,#\xe1a&" + // 0x16121 0x1611F: 0x16126 + "\x05\x84\x88,#\xe1a'" + // 0x16122 0x1611F: 0x16127 + "\x05\x84\x84,$\x01a(" + // 0x16121 0x16120: 0x16128 + "\x05\xb5\x9c-\xac\xe1mh" + // 0x16D67 0x16D67: 0x16D68 + "\x05\xb5\x8c-\xac\xe1mi" + // 0x16D63 0x16D67: 0x16D69 + "\x05\xb5\xa4-\xac\xe1mj" + // 0x16D69 0x16D67: 0x16D6A "" // Total size of tables: 57KB (58086 bytes) diff --git a/constraint/vendor/golang.org/x/text/unicode/norm/transform.go b/constraint/vendor/golang.org/x/text/unicode/norm/transform.go index a1d366ae4..583230d4d 100644 --- a/constraint/vendor/golang.org/x/text/unicode/norm/transform.go +++ b/constraint/vendor/golang.org/x/text/unicode/norm/transform.go @@ -33,7 +33,7 @@ func (f Form) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) return nDst + n, nSrc + n, err } - if err == nil && n < len(src) && !atEOF { + if err == nil && n < len(src) { err = transform.ErrShortSrc } return n, n, err @@ -67,6 +67,7 @@ func (f Form) transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) nSrc = end // Next quickSpan. + var err error end = rb.nsrc eof := atEOF if n := nSrc + len(dst) - nDst; n < end { @@ -79,7 +80,7 @@ func (f Form) transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) nSrc += n nDst += n if ok { - if err == nil && n < rb.nsrc && !atEOF { + if err == nil && nSrc < rb.nsrc { err = transform.ErrShortSrc } return nDst, nSrc, err diff --git a/constraint/vendor/modules.txt b/constraint/vendor/modules.txt index 59a15e8d4..1e87d5766 100644 --- a/constraint/vendor/modules.txt +++ b/constraint/vendor/modules.txt @@ -97,16 +97,11 @@ github.com/go-openapi/swag/typeutils # github.com/go-openapi/swag/yamlutils v0.28.0 ## explicit; go 1.25.0 github.com/go-openapi/swag/yamlutils -# github.com/gobwas/glob v0.2.3 -## explicit +# github.com/gobwas/glob v1.0.0 +## explicit; go 1.22.0 github.com/gobwas/glob -github.com/gobwas/glob/compiler -github.com/gobwas/glob/match +github.com/gobwas/glob/internal/debug github.com/gobwas/glob/syntax -github.com/gobwas/glob/syntax/ast -github.com/gobwas/glob/syntax/lexer -github.com/gobwas/glob/util/runes -github.com/gobwas/glob/util/strings # github.com/goccy/go-json v0.10.6 ## explicit; go 1.19 github.com/goccy/go-json @@ -180,8 +175,8 @@ github.com/json-iterator/go # github.com/lestrrat-go/blackmagic v1.0.4 ## explicit; go 1.23 github.com/lestrrat-go/blackmagic -# github.com/lestrrat-go/dsig v1.3.0 -## explicit; go 1.23.0 +# github.com/lestrrat-go/dsig v1.4.0 +## explicit; go 1.25.0 github.com/lestrrat-go/dsig github.com/lestrrat-go/dsig/internal/ecutil # github.com/lestrrat-go/dsig-secp256k1 v1.0.0 @@ -196,7 +191,7 @@ github.com/lestrrat-go/httprc/v3 github.com/lestrrat-go/httprc/v3/errsink github.com/lestrrat-go/httprc/v3/proxysink github.com/lestrrat-go/httprc/v3/tracesink -# github.com/lestrrat-go/jwx/v3 v3.2.0 +# github.com/lestrrat-go/jwx/v3 v3.3.0 ## explicit; go 1.25.0 github.com/lestrrat-go/jwx/v3 github.com/lestrrat-go/jwx/v3/cert @@ -219,6 +214,8 @@ github.com/lestrrat-go/jwx/v3/jwk/ecdsa github.com/lestrrat-go/jwx/v3/jwk/internal/registry github.com/lestrrat-go/jwx/v3/jwk/jwkbb github.com/lestrrat-go/jwx/v3/jws +github.com/lestrrat-go/jwx/v3/jws/internal/jwsbb +github.com/lestrrat-go/jwx/v3/jws/internal/keyalg github.com/lestrrat-go/jwx/v3/jws/internal/keytype github.com/lestrrat-go/jwx/v3/jws/jwsbb github.com/lestrrat-go/jwx/v3/jws/legacy @@ -251,7 +248,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.20.2 +# github.com/open-policy-agent/opa v1.21.0 ## explicit; go 1.26.0 github.com/open-policy-agent/opa/capabilities github.com/open-policy-agent/opa/internal/bundle @@ -291,6 +288,7 @@ github.com/open-policy-agent/opa/internal/wasm/opcode github.com/open-policy-agent/opa/internal/wasm/sdk/opa/capabilities github.com/open-policy-agent/opa/internal/wasm/types github.com/open-policy-agent/opa/internal/wasm/util +github.com/open-policy-agent/opa/internal/yaml github.com/open-policy-agent/opa/v1/ast github.com/open-policy-agent/opa/v1/ast/internal/scanner github.com/open-policy-agent/opa/v1/ast/internal/tokens @@ -339,8 +337,8 @@ github.com/prometheus/client_golang/prometheus/collectors github.com/prometheus/client_golang/prometheus/internal github.com/prometheus/client_golang/prometheus/promhttp github.com/prometheus/client_golang/prometheus/promhttp/internal -# github.com/prometheus/client_model v0.6.2 -## explicit; go 1.22.0 +# github.com/prometheus/client_model v0.6.3 +## explicit; go 1.23 github.com/prometheus/client_model/go # github.com/prometheus/common v0.70.1 ## explicit; go 1.25.0 @@ -379,7 +377,7 @@ github.com/tchap/go-patricia/v2/patricia ## explicit; go 1.24 github.com/valyala/fastjson github.com/valyala/fastjson/fastfloat -# github.com/vektah/gqlparser/v2 v2.5.36 +# github.com/vektah/gqlparser/v2 v2.5.37 ## explicit; go 1.22 github.com/vektah/gqlparser/v2/ast github.com/vektah/gqlparser/v2/gqlerror @@ -501,22 +499,22 @@ golang.org/x/net/trace ## explicit; go 1.25.0 golang.org/x/oauth2 golang.org/x/oauth2/internal -# golang.org/x/sync v0.22.0 -## explicit; go 1.25.0 +# golang.org/x/sync v0.23.0 +## explicit; go 1.26.0 golang.org/x/sync/errgroup golang.org/x/sync/singleflight -# golang.org/x/sys v0.47.0 -## explicit; go 1.25.0 +# golang.org/x/sys v0.48.0 +## explicit; go 1.26.0 golang.org/x/sys/cpu golang.org/x/sys/plan9 golang.org/x/sys/unix golang.org/x/sys/windows golang.org/x/sys/windows/registry -# golang.org/x/term v0.45.0 -## explicit; go 1.25.0 +# golang.org/x/term v0.46.0 +## explicit; go 1.26.0 golang.org/x/term -# golang.org/x/text v0.41.0 -## explicit; go 1.25.0 +# golang.org/x/text v0.42.0 +## explicit; go 1.26.0 golang.org/x/text/encoding golang.org/x/text/encoding/charmap golang.org/x/text/encoding/htmlindex @@ -545,8 +543,8 @@ golang.org/x/text/secure/bidirule golang.org/x/text/transform golang.org/x/text/unicode/bidi golang.org/x/text/unicode/norm -# golang.org/x/time v0.15.0 -## explicit; go 1.25.0 +# golang.org/x/time v0.16.0 +## explicit; go 1.26.0 golang.org/x/time/rate # google.golang.org/genproto/googleapis/api v0.0.0-20260819154853-08b0e4226688 ## explicit; go 1.25.0