Update dependencies

This commit is contained in:
Ingo Oppermann 2024-02-29 14:50:38 +01:00
parent 32a7916359
commit e8ca91d214
No known key found for this signature in database
GPG Key ID: 2AB32426E9DD229E
222 changed files with 14005 additions and 4625 deletions

55
go.mod
View File

@ -3,33 +3,33 @@ module github.com/datarhei/core/v16
go 1.18 go 1.18
require ( require (
github.com/99designs/gqlgen v0.17.42 github.com/99designs/gqlgen v0.17.44
github.com/Masterminds/semver/v3 v3.2.1 github.com/Masterminds/semver/v3 v3.2.1
github.com/atrox/haikunatorgo/v2 v2.0.1 github.com/atrox/haikunatorgo/v2 v2.0.1
github.com/caddyserver/certmagic v0.20.0 github.com/caddyserver/certmagic v0.20.0
github.com/datarhei/gosrt v0.5.5 github.com/datarhei/gosrt v0.5.7
github.com/datarhei/joy4 v0.0.0-20240103155326-704dff2c27fb github.com/datarhei/joy4 v0.0.0-20240229100136-43bcaf8ef5e7
github.com/go-playground/validator/v10 v10.16.0 github.com/go-playground/validator/v10 v10.18.0
github.com/gobwas/glob v0.2.3 github.com/gobwas/glob v0.2.3
github.com/golang-jwt/jwt/v5 v5.2.0 github.com/golang-jwt/jwt/v5 v5.2.0
github.com/google/uuid v1.5.0 github.com/google/uuid v1.6.0
github.com/invopop/jsonschema v0.4.0 github.com/invopop/jsonschema v0.4.0
github.com/joho/godotenv v1.5.1 github.com/joho/godotenv v1.5.1
github.com/labstack/echo-jwt v0.0.0-20221127215225-c84d41a71003 github.com/labstack/echo-jwt v0.0.0-20221127215225-c84d41a71003
github.com/labstack/echo/v4 v4.11.4 github.com/labstack/echo/v4 v4.11.4
github.com/lithammer/shortuuid/v4 v4.0.0 github.com/lithammer/shortuuid/v4 v4.0.0
github.com/mattn/go-isatty v0.0.20 github.com/mattn/go-isatty v0.0.20
github.com/minio/minio-go/v7 v7.0.66 github.com/minio/minio-go/v7 v7.0.67
github.com/prep/average v0.0.0-20200506183628-d26c465f48c3 github.com/prep/average v0.0.0-20200506183628-d26c465f48c3
github.com/prometheus/client_golang v1.18.0 github.com/prometheus/client_golang v1.19.0
github.com/shirou/gopsutil/v3 v3.23.12 github.com/shirou/gopsutil/v3 v3.24.1
github.com/stretchr/testify v1.8.4 github.com/stretchr/testify v1.8.4
github.com/swaggo/echo-swagger v1.4.1 github.com/swaggo/echo-swagger v1.4.1
github.com/swaggo/swag v1.16.2 github.com/swaggo/swag v1.16.3
github.com/vektah/gqlparser/v2 v2.5.10 github.com/vektah/gqlparser/v2 v2.5.11
github.com/xeipuuv/gojsonschema v1.2.0 github.com/xeipuuv/gojsonschema v1.2.0
go.uber.org/zap v1.26.0 go.uber.org/zap v1.27.0
golang.org/x/mod v0.14.0 golang.org/x/mod v0.15.0
) )
require ( require (
@ -47,7 +47,7 @@ require (
github.com/go-openapi/jsonpointer v0.20.2 // indirect github.com/go-openapi/jsonpointer v0.20.2 // indirect
github.com/go-openapi/jsonreference v0.20.4 // indirect github.com/go-openapi/jsonreference v0.20.4 // indirect
github.com/go-openapi/spec v0.20.14 // indirect github.com/go-openapi/spec v0.20.14 // indirect
github.com/go-openapi/swag v0.22.7 // indirect github.com/go-openapi/swag v0.22.9 // indirect
github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
@ -57,26 +57,25 @@ require (
github.com/iancoleman/orderedmap v0.2.0 // indirect github.com/iancoleman/orderedmap v0.2.0 // indirect
github.com/josharian/intern v1.0.0 // indirect github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.17.4 // indirect github.com/klauspost/compress v1.17.7 // indirect
github.com/klauspost/cpuid/v2 v2.2.6 // indirect github.com/klauspost/cpuid/v2 v2.2.7 // indirect
github.com/labstack/gommon v0.4.2 // indirect github.com/labstack/gommon v0.4.2 // indirect
github.com/leodido/go-urn v1.2.4 // indirect github.com/leodido/go-urn v1.4.0 // indirect
github.com/libdns/libdns v0.2.1 // indirect github.com/libdns/libdns v0.2.1 // indirect
github.com/lufia/plan9stats v0.0.0-20231016141302-07b5767bb0ed // indirect github.com/lufia/plan9stats v0.0.0-20240226150601-1dcf7310316a // indirect
github.com/mailru/easyjson v0.7.7 // indirect github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-colorable v0.1.13 // indirect
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect
github.com/mholt/acmez v1.2.0 // indirect github.com/mholt/acmez v1.2.0 // indirect
github.com/miekg/dns v1.1.57 // indirect github.com/miekg/dns v1.1.58 // indirect
github.com/minio/md5-simd v1.1.2 // indirect github.com/minio/md5-simd v1.1.2 // indirect
github.com/minio/sha256-simd v1.0.1 // indirect github.com/minio/sha256-simd v1.0.1 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
github.com/prometheus/client_model v0.5.0 // indirect github.com/prometheus/client_model v0.6.0 // indirect
github.com/prometheus/common v0.45.0 // indirect github.com/prometheus/common v0.48.0 // indirect
github.com/prometheus/procfs v0.12.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect
github.com/rs/xid v1.5.0 // indirect github.com/rs/xid v1.5.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect
@ -86,21 +85,21 @@ require (
github.com/swaggo/files/v2 v2.0.0 // indirect github.com/swaggo/files/v2 v2.0.0 // indirect
github.com/tklauser/go-sysconf v0.3.13 // indirect github.com/tklauser/go-sysconf v0.3.13 // indirect
github.com/tklauser/numcpus v0.7.0 // indirect github.com/tklauser/numcpus v0.7.0 // indirect
github.com/urfave/cli/v2 v2.25.5 // indirect github.com/urfave/cli/v2 v2.27.1 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.2 // indirect github.com/valyala/fasttemplate v1.2.2 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
github.com/yusufpapurcu/wmi v1.2.3 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect
github.com/zeebo/blake3 v0.2.3 // indirect github.com/zeebo/blake3 v0.2.3 // indirect
go.uber.org/multierr v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect
golang.org/x/crypto v0.18.0 // indirect golang.org/x/crypto v0.20.0 // indirect
golang.org/x/net v0.20.0 // indirect golang.org/x/net v0.21.0 // indirect
golang.org/x/sys v0.16.0 // indirect golang.org/x/sys v0.17.0 // indirect
golang.org/x/text v0.14.0 // indirect golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.5.0 // indirect golang.org/x/time v0.5.0 // indirect
golang.org/x/tools v0.17.0 // indirect golang.org/x/tools v0.18.0 // indirect
google.golang.org/protobuf v1.32.0 // indirect google.golang.org/protobuf v1.32.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect

112
go.sum
View File

@ -1,5 +1,5 @@
github.com/99designs/gqlgen v0.17.42 h1:BVWDOb2VVHQC5k3m6oa0XhDnxltLLrU4so7x/u39Zu4= github.com/99designs/gqlgen v0.17.44 h1:OS2wLk/67Y+vXM75XHbwRnNYJcbuJd4OBL76RX3NQQA=
github.com/99designs/gqlgen v0.17.42/go.mod h1:GQ6SyMhwFbgHR0a8r2Wn8fYgEwPxxmndLFPhU63+cJE= github.com/99designs/gqlgen v0.17.44/go.mod h1:UTCu3xpK2mLI5qcMNw+HKDiEL77it/1XtAjisC4sLwM=
github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0= github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0=
@ -23,10 +23,10 @@ github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/datarhei/gosrt v0.5.5 h1:4Xx4v7pn/rz6EaWhZRE37fROW+rry0y4yBHZBkq5d8g= github.com/datarhei/gosrt v0.5.7 h1:1COeDgF0D0v0poWu0yKDC72d29x16Ma6VFR1icx+3Xc=
github.com/datarhei/gosrt v0.5.5/go.mod h1:In1zba2/999S1d+ENIJ0h9s3alHO3FvCNrIpykxYbEE= github.com/datarhei/gosrt v0.5.7/go.mod h1:ZicbsY9T2rXtWgQVBTR9ilnEkSYVSIb36hG9Lj7XCKM=
github.com/datarhei/joy4 v0.0.0-20240103155326-704dff2c27fb h1:zzF0wtKJKMIDlqHfjBl5WgTFO3LeKBoJNInyOrkJZPc= github.com/datarhei/joy4 v0.0.0-20240229100136-43bcaf8ef5e7 h1:MG5XQMTTDPcuvvRzc1c37QbwgDbYPhKmPFo9gSaPdBE=
github.com/datarhei/joy4 v0.0.0-20240103155326-704dff2c27fb/go.mod h1:Jcw/6jZDQQmPx8A7INEkXmuEF7E9jjBbSTfVSLwmiQw= github.com/datarhei/joy4 v0.0.0-20240229100136-43bcaf8ef5e7/go.mod h1:Jcw/6jZDQQmPx8A7INEkXmuEF7E9jjBbSTfVSLwmiQw=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -47,15 +47,15 @@ github.com/go-openapi/jsonreference v0.20.4 h1:bKlDxQxQJgwpUSgOENiMPzCTBVuc7vTdX
github.com/go-openapi/jsonreference v0.20.4/go.mod h1:5pZJyJP2MnYCpoeoMAql78cCHauHj0V9Lhc506VOpw4= github.com/go-openapi/jsonreference v0.20.4/go.mod h1:5pZJyJP2MnYCpoeoMAql78cCHauHj0V9Lhc506VOpw4=
github.com/go-openapi/spec v0.20.14 h1:7CBlRnw+mtjFGlPDRZmAMnq35cRzI91xj03HVyUi/Do= github.com/go-openapi/spec v0.20.14 h1:7CBlRnw+mtjFGlPDRZmAMnq35cRzI91xj03HVyUi/Do=
github.com/go-openapi/spec v0.20.14/go.mod h1:8EOhTpBoFiask8rrgwbLC3zmJfz4zsCUueRuPM6GNkw= github.com/go-openapi/spec v0.20.14/go.mod h1:8EOhTpBoFiask8rrgwbLC3zmJfz4zsCUueRuPM6GNkw=
github.com/go-openapi/swag v0.22.7 h1:JWrc1uc/P9cSomxfnsFSVWoE1FW6bNbrVPmpQYpCcR8= github.com/go-openapi/swag v0.22.9 h1:XX2DssF+mQKM2DHsbgZK74y/zj4mo9I99+89xUmuZCE=
github.com/go-openapi/swag v0.22.7/go.mod h1:Gl91UqO+btAM0plGGxHqJcQZ1ZTy6jbmridBTsDy8A0= github.com/go-openapi/swag v0.22.9/go.mod h1:3/OXnFfnMAwBD099SwYRk7GD3xOrr1iL7d/XNLXVVwE=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.16.0 h1:x+plE831WK4vaKHO/jpgUGsvLKIqRRkz6M78GuJAfGE= github.com/go-playground/validator/v10 v10.18.0 h1:BvolUXjp4zuvkZ5YN5t7ebzbhlUtPsPm2S9NAZ5nl9U=
github.com/go-playground/validator/v10 v10.16.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= github.com/go-playground/validator/v10 v10.18.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= 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 v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
@ -70,8 +70,8 @@ github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
@ -87,12 +87,12 @@ github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8Hm
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= 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/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg=
github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc= github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/labstack/echo-jwt v0.0.0-20221127215225-c84d41a71003 h1:FyalHKl9hnJvhNbrABJXXjC2hG7gvIF0ioW9i0xHNQU= github.com/labstack/echo-jwt v0.0.0-20221127215225-c84d41a71003 h1:FyalHKl9hnJvhNbrABJXXjC2hG7gvIF0ioW9i0xHNQU=
@ -101,15 +101,15 @@ github.com/labstack/echo/v4 v4.11.4 h1:vDZmA+qNeh1pd/cCkEicDMrjtrnMGQ1QFI9gWN1zG
github.com/labstack/echo/v4 v4.11.4/go.mod h1:noh7EvLwqDsmh/X/HWKPUl1AjzJrhyptRyEbQJfxen8= github.com/labstack/echo/v4 v4.11.4/go.mod h1:noh7EvLwqDsmh/X/HWKPUl1AjzJrhyptRyEbQJfxen8=
github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0= github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=
github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU= github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU=
github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/libdns/libdns v0.2.1 h1:Wu59T7wSHRgtA0cfxC+n1c/e+O3upJGWytknkmFEDis= github.com/libdns/libdns v0.2.1 h1:Wu59T7wSHRgtA0cfxC+n1c/e+O3upJGWytknkmFEDis=
github.com/libdns/libdns v0.2.1/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40= github.com/libdns/libdns v0.2.1/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40=
github.com/lithammer/shortuuid/v4 v4.0.0 h1:QRbbVkfgNippHOS8PXDkti4NaWeyYfcBTHtw7k08o4c= github.com/lithammer/shortuuid/v4 v4.0.0 h1:QRbbVkfgNippHOS8PXDkti4NaWeyYfcBTHtw7k08o4c=
github.com/lithammer/shortuuid/v4 v4.0.0/go.mod h1:Zs8puNcrvf2rV9rTH51ZLLcj7ZXqQI3lv67aw4KiB1Y= github.com/lithammer/shortuuid/v4 v4.0.0/go.mod h1:Zs8puNcrvf2rV9rTH51ZLLcj7ZXqQI3lv67aw4KiB1Y=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
github.com/lufia/plan9stats v0.0.0-20231016141302-07b5767bb0ed h1:036IscGBfJsFIgJQzlui7nK1Ncm0tp2ktmPj8xO4N/0= github.com/lufia/plan9stats v0.0.0-20240226150601-1dcf7310316a h1:3Bm7EwfUQUvhNeKIkUct/gl9eod1TcXuj8stxvi/GoI=
github.com/lufia/plan9stats v0.0.0-20231016141302-07b5767bb0ed/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k= github.com/lufia/plan9stats v0.0.0-20240226150601-1dcf7310316a/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
@ -117,16 +117,14 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg=
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k=
github.com/mholt/acmez v1.2.0 h1:1hhLxSgY5FvH5HCnGUuwbKY2VQVo8IU7rxXKSnZ7F30= github.com/mholt/acmez v1.2.0 h1:1hhLxSgY5FvH5HCnGUuwbKY2VQVo8IU7rxXKSnZ7F30=
github.com/mholt/acmez v1.2.0/go.mod h1:VT9YwH1xgNX1kmYY89gY8xPJC84BFAisjo8Egigt4kE= github.com/mholt/acmez v1.2.0/go.mod h1:VT9YwH1xgNX1kmYY89gY8xPJC84BFAisjo8Egigt4kE=
github.com/miekg/dns v1.1.57 h1:Jzi7ApEIzwEPLHWRcafCN9LZSBbqQpxjt/wpgvg7wcM= github.com/miekg/dns v1.1.58 h1:ca2Hdkz+cDg/7eNF6V56jjzuZ4aCAE+DbVkILdQWG/4=
github.com/miekg/dns v1.1.57/go.mod h1:uqRjCRUuEAA6qsOiJvDd+CFo/vW+y5WR6SNmHE55hZk= github.com/miekg/dns v1.1.58/go.mod h1:Ypv+3b/KadlvW9vJfXOTf300O4UqaHFzFCuHz+rPkBY=
github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM= github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
github.com/minio/minio-go/v7 v7.0.66 h1:bnTOXOHjOqv/gcMuiVbN9o2ngRItvqE774dG9nq0Dzw= github.com/minio/minio-go/v7 v7.0.67 h1:BeBvZWAS+kRJm1vGTMJYVjKUNoo0FoEt/wUWdUtfmh8=
github.com/minio/minio-go/v7 v7.0.66/go.mod h1:DHAgmyQEGdW3Cif0UooKOyrT3Vxs82zNdV6tkKhRtbs= github.com/minio/minio-go/v7 v7.0.67/go.mod h1:+UXocnUeZ3wHvVh5s95gcrA4YjMIbccT6ubB+1m054A=
github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM=
github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
@ -140,16 +138,16 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= 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/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b h1:0LFwY6Q3gMACTjAbMZBjXAqTOzOwFaj2Ld6cjeQ7Rig= github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU=
github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/prep/average v0.0.0-20200506183628-d26c465f48c3 h1:Y7qCvg282QmlyrVQuL2fgGwebuw7zvfnRym09r+dUGc= github.com/prep/average v0.0.0-20200506183628-d26c465f48c3 h1:Y7qCvg282QmlyrVQuL2fgGwebuw7zvfnRym09r+dUGc=
github.com/prep/average v0.0.0-20200506183628-d26c465f48c3/go.mod h1:0ZE5gcyWKS151WBDIpmLshHY0l+3edpuKnBUWVVbWKk= github.com/prep/average v0.0.0-20200506183628-d26c465f48c3/go.mod h1:0ZE5gcyWKS151WBDIpmLshHY0l+3edpuKnBUWVVbWKk=
github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk= github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU=
github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA= github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k=
github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos=
github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8=
github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE=
github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc=
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
@ -158,8 +156,8 @@ github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4= github.com/shirou/gopsutil/v3 v3.24.1 h1:R3t6ondCEvmARp3wxODhXMTLC/klMa87h2PHUw5m7QI=
github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= github.com/shirou/gopsutil/v3 v3.24.1/go.mod h1:UU7a2MSBQa+kW1uuDq8DeEBS8kmrnQwsv2b5O513rwU=
github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
@ -176,29 +174,28 @@ github.com/stretchr/testify v1.3.1-0.20190311161405-34c6fa2dc709/go.mod h1:M5WIy
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/swaggo/echo-swagger v1.4.1 h1:Yf0uPaJWp1uRtDloZALyLnvdBeoEL5Kc7DtnjzO/TUk= github.com/swaggo/echo-swagger v1.4.1 h1:Yf0uPaJWp1uRtDloZALyLnvdBeoEL5Kc7DtnjzO/TUk=
github.com/swaggo/echo-swagger v1.4.1/go.mod h1:C8bSi+9yH2FLZsnhqMZLIZddpUxZdBYuNHbtaS1Hljc= github.com/swaggo/echo-swagger v1.4.1/go.mod h1:C8bSi+9yH2FLZsnhqMZLIZddpUxZdBYuNHbtaS1Hljc=
github.com/swaggo/files/v2 v2.0.0 h1:hmAt8Dkynw7Ssz46F6pn8ok6YmGZqHSVLZ+HQM7i0kw= github.com/swaggo/files/v2 v2.0.0 h1:hmAt8Dkynw7Ssz46F6pn8ok6YmGZqHSVLZ+HQM7i0kw=
github.com/swaggo/files/v2 v2.0.0/go.mod h1:24kk2Y9NYEJ5lHuCra6iVwkMjIekMCaFq/0JQj66kyM= github.com/swaggo/files/v2 v2.0.0/go.mod h1:24kk2Y9NYEJ5lHuCra6iVwkMjIekMCaFq/0JQj66kyM=
github.com/swaggo/swag v1.16.2 h1:28Pp+8DkQoV+HLzLx8RGJZXNGKbFqnuvSbAAtoxiY04= github.com/swaggo/swag v1.16.3 h1:PnCYjPCah8FK4I26l2F/KQ4yz3sILcVUN3cTlBFA9Pg=
github.com/swaggo/swag v1.16.2/go.mod h1:6YzXnDcpr0767iOejs318CwYkCQqyGer6BizOg03f+E= github.com/swaggo/swag v1.16.3/go.mod h1:DImHIuOFXKpMFAQjcC7FG4m3Dg4+QuUgUzJmKjI/gRk=
github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
github.com/tklauser/go-sysconf v0.3.13 h1:GBUpcahXSpR2xN01jhkNAbTLRk2Yzgggk8IM08lq3r4= github.com/tklauser/go-sysconf v0.3.13 h1:GBUpcahXSpR2xN01jhkNAbTLRk2Yzgggk8IM08lq3r4=
github.com/tklauser/go-sysconf v0.3.13/go.mod h1:zwleP4Q4OehZHGn4CYZDipCgg9usW5IJePewFCGVEa0= github.com/tklauser/go-sysconf v0.3.13/go.mod h1:zwleP4Q4OehZHGn4CYZDipCgg9usW5IJePewFCGVEa0=
github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
github.com/tklauser/numcpus v0.7.0 h1:yjuerZP127QG9m5Zh/mSO4wqurYil27tHrqwRoRjpr4= github.com/tklauser/numcpus v0.7.0 h1:yjuerZP127QG9m5Zh/mSO4wqurYil27tHrqwRoRjpr4=
github.com/tklauser/numcpus v0.7.0/go.mod h1:bb6dMVcj8A42tSE7i32fsIUCbQNllK5iDguyOZRUzAY= github.com/tklauser/numcpus v0.7.0/go.mod h1:bb6dMVcj8A42tSE7i32fsIUCbQNllK5iDguyOZRUzAY=
github.com/urfave/cli/v2 v2.25.5 h1:d0NIAyhh5shGscroL7ek/Ya9QYQE0KNabJgiUinIQkc= github.com/urfave/cli/v2 v2.27.1 h1:8xSQ6szndafKVRmfyeUMxkNUJQMjL1F2zmsZ+qHpfho=
github.com/urfave/cli/v2 v2.25.5/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc= github.com/urfave/cli/v2 v2.27.1/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
github.com/vektah/gqlparser/v2 v2.5.10 h1:6zSM4azXC9u4Nxy5YmdmGu4uKamfwsdKTwp5zsEealU= github.com/vektah/gqlparser/v2 v2.5.11 h1:JJxLtXIoN7+3x6MBdtIP59TP1RANnY7pXOaDnADQSf8=
github.com/vektah/gqlparser/v2 v2.5.10/go.mod h1:1rCcfwB2ekJofmluGWXMSEnPMZgbxzwj6FaZ/4OT8Cc= github.com/vektah/gqlparser/v2 v2.5.11/go.mod h1:1rCcfwB2ekJofmluGWXMSEnPMZgbxzwj6FaZ/4OT8Cc=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo=
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
@ -208,25 +205,26 @@ github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw=
github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
github.com/zeebo/assert v1.1.0 h1:hU1L1vLTHsnO8x8c9KAR5GmM5QscxHg5RNU5z5qbUWY= github.com/zeebo/assert v1.1.0 h1:hU1L1vLTHsnO8x8c9KAR5GmM5QscxHg5RNU5z5qbUWY=
github.com/zeebo/assert v1.1.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= github.com/zeebo/assert v1.1.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
github.com/zeebo/blake3 v0.2.3 h1:TFoLXsjeXqRNFxSbk35Dk4YtszE/MQQGK10BH4ptoTg= github.com/zeebo/blake3 v0.2.3 h1:TFoLXsjeXqRNFxSbk35Dk4YtszE/MQQGK10BH4ptoTg=
github.com/zeebo/blake3 v0.2.3/go.mod h1:mjJjZpnsyIVtVgTOSpJ9vmRE4wgDeyt2HU3qXvvKCaQ= github.com/zeebo/blake3 v0.2.3/go.mod h1:mjJjZpnsyIVtVgTOSpJ9vmRE4wgDeyt2HU3qXvvKCaQ=
github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo= github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo=
github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4= github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4=
go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= golang.org/x/crypto v0.20.0 h1:jmAMJJZXr5KiCw05dfYK9QnqaqKLYXijU23lsEdcQqg=
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/crypto v0.20.0/go.mod h1:Xwo95rrVNIoSMx9wa1JroENMToLWn3RNVrTBpLHgZPQ=
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8=
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -237,15 +235,15 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ=
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=

View File

@ -16,3 +16,5 @@
*.out *.out
gqlgen gqlgen
*.exe *.exe
node_modules

View File

@ -5,10 +5,81 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
<a name="unreleased"></a> <a name="unreleased"></a>
## [Unreleased](https://github.com/99designs/gqlgen/compare/v0.17.41...HEAD) ## [Unreleased](https://github.com/99designs/gqlgen/compare/v0.17.42...HEAD)
<!-- end of if --> <!-- end of if -->
<!-- end of CommitGroups --> <!-- end of CommitGroups -->
<a name="v0.17.42"></a>
## [v0.17.42](https://github.com/99designs/gqlgen/compare/v0.17.41...v0.17.42) - 2023-12-29
- <a href="https://github.com/99designs/gqlgen/commit/7bf0c223aec642d086793698bc2a0d1a6fdb09b4"><tt>7bf0c223</tt></a> release v0.17.42
<dl><dd><details><summary><a href="https://github.com/99designs/gqlgen/commit/c811d47ec498bdd50591f163e7d23a7524e98280"><tt>c811d47e</tt></a> fix: avoid panic from tracing on bad request (<a href="https://github.com/99designs/gqlgen/pull/2871">#2871</a>)</summary>
This fixes a panic which arises from the tracing components when a request has some defect which results in an error when creating the operation context. The transports consistently handle this by calling `DispatchError(graphql.WithOperationContext(ctx, rc), err)` where `rc` is the OperationContext which was not correctly constructed. This seems dangerous, because middleware may assume that if there in an `OperationContext` in the `context.Context` than they are being invoked on a normal codepath and can assume their other interceptors have been invoked in the normal order. Also, using a value returned by a function which also returned a non-nil error is very unusual. However, I have no idea what the impact of changing that dangerous behavior in the transports would be, so I opted to make the tracing component more resilient instead.
</details></dd></dl>
- <a href="https://github.com/99designs/gqlgen/commit/13bb415268dda837690835e65e331746c8df892b"><tt>13bb4152</tt></a> fix for entity interfce code gen with related test (<a href="https://github.com/99designs/gqlgen/pull/2868">#2868</a>)
- <a href="https://github.com/99designs/gqlgen/commit/0354649c0309af6acfe089d12d103060d55a5805"><tt>0354649c</tt></a> Remove archived dependency appdash (<a href="https://github.com/99designs/gqlgen/pull/2866">#2866</a>)
- <a href="https://github.com/99designs/gqlgen/commit/0d43599cdab22912d4ddd061c3b3ffd5d8da3845"><tt>0d43599c</tt></a> Update examples go.mod with appdash replacements (<a href="https://github.com/99designs/gqlgen/pull/2863">#2863</a>)
- <a href="https://github.com/99designs/gqlgen/commit/7dd971c871c0b0159ad26c9bf3095a8ba3780402"><tt>7dd971c8</tt></a> Use defer wg.Done() in FieldSet Dispatch (<a href="https://github.com/99designs/gqlgen/pull/2861">#2861</a>)
<dl><dd><details><summary><a href="https://github.com/99designs/gqlgen/commit/24ea195cebea095035caf4d23af7f3d75fd0a041"><tt>24ea195c</tt></a> vikstrous/dataloadgen replaces recommended dataloader package in example docs (<a href="https://github.com/99designs/gqlgen/pull/2770">#2770</a>)</summary>
* update example for dataloadgen
* improved example with link to example repo
* undo unnecessary changes
* fix wrong signature
* fix creation of loader
* Update docs/content/reference/dataloaders.md
</details></dd></dl>
<dl><dd><details><summary><a href="https://github.com/99designs/gqlgen/commit/42f6e39d48e3a301bf39cd4e8fd180250bc25f2c"><tt>42f6e39d</tt></a> Allow fields that return root level definitions (<a href="https://github.com/99designs/gqlgen/pull/2858">#2858</a>)</summary>
* generate structs for root level definitions to support fields that return Query, Mutation or Subscription
* removed unnecessary comment
* re-ran go generate
---------
</details></dd></dl>
- <a href="https://github.com/99designs/gqlgen/commit/682a58dd6af5fda53509fbf4cfa45d23b5bb1c86"><tt>682a58dd</tt></a> Add go generate for examples so contributors never forget (<a href="https://github.com/99designs/gqlgen/pull/2859">#2859</a>)
<dl><dd><details><summary><a href="https://github.com/99designs/gqlgen/commit/e080a96de178520fcfaf5a8d68836981ec4df9a9"><tt>e080a96d</tt></a> Modify to prevent unreachable code from occurring (<a href="https://github.com/99designs/gqlgen/pull/2846">#2846</a>)</summary>
* fix: 型の数でソートする処理を追加
* 戻し
* fix: case文の最初にスーパークラスが来ないようにする
* testdata追加
* fix: Added sorting by number of types.
* fix: Prevent superclass from appearing at the beginning of case statement
</details></dd></dl>
- <a href="https://github.com/99designs/gqlgen/commit/68744ad2a1e9d5869ab6a00b49814c6ae9583186"><tt>68744ad2</tt></a> Bump changelog
- <a href="https://github.com/99designs/gqlgen/commit/e4cf21d24518deb99af6d4c0ea86de11d6889349"><tt>e4cf21d2</tt></a> v0.17.41 postrelease bump
<!-- end of Commits -->
<!-- end of Else -->
<!-- end of If NoteGroups -->
<a name="v0.17.41"></a> <a name="v0.17.41"></a>
## [v0.17.41](https://github.com/99designs/gqlgen/compare/v0.17.40...v0.17.41) - 2023-12-03 ## [v0.17.41](https://github.com/99designs/gqlgen/compare/v0.17.40...v0.17.41) - 2023-12-03
- <a href="https://github.com/99designs/gqlgen/commit/fe60938c55308b1cd5562556cdb976771cfcc6cc"><tt>fe60938c</tt></a> release v0.17.41 - <a href="https://github.com/99designs/gqlgen/commit/fe60938c55308b1cd5562556cdb976771cfcc6cc"><tt>fe60938c</tt></a> release v0.17.41

View File

@ -27,14 +27,18 @@ func Generate(cfg *config.Config, option ...Option) error {
if cfg.Federation.IsDefined() { if cfg.Federation.IsDefined() {
if cfg.Federation.Version == 0 { // default to using the user's choice of version, but if unset, try to sort out which federation version to use if cfg.Federation.Version == 0 { // default to using the user's choice of version, but if unset, try to sort out which federation version to use
urlRegex := regexp.MustCompile(`(?s)@link.*\(.*url:.*?"(.*?)"[^)]+\)`) // regex to grab the url of a link directive, should it exist urlRegex := regexp.MustCompile(`(?s)@link.*\(.*url:.*?"(.*?)"[^)]+\)`) // regex to grab the url of a link directive, should it exist
versionRegex := regexp.MustCompile(`v(\d+).(\d+)$`) // regex to grab the version number from a url
// check the sources, and if one is marked as federation v2, we mark the entirety to be generated using that format // check the sources, and if one is marked as federation v2, we mark the entirety to be generated using that format
for _, v := range cfg.Sources { for _, v := range cfg.Sources {
cfg.Federation.Version = 1 cfg.Federation.Version = 1
urlString := urlRegex.FindStringSubmatch(v.Input) urlString := urlRegex.FindStringSubmatch(v.Input)
if urlString != nil && urlString[1] == "https://specs.apollo.dev/federation/v2.0" { // e.g. urlString[1] == "https://specs.apollo.dev/federation/v2.7"
cfg.Federation.Version = 2 if urlString != nil {
break matches := versionRegex.FindStringSubmatch(urlString[1])
if matches[1] == "2" {
cfg.Federation.Version = 2
break
}
} }
} }
} }

View File

@ -38,6 +38,7 @@ type Config struct {
OmitComplexity bool `yaml:"omit_complexity,omitempty"` OmitComplexity bool `yaml:"omit_complexity,omitempty"`
OmitGQLGenFileNotice bool `yaml:"omit_gqlgen_file_notice,omitempty"` OmitGQLGenFileNotice bool `yaml:"omit_gqlgen_file_notice,omitempty"`
OmitGQLGenVersionInFileNotice bool `yaml:"omit_gqlgen_version_in_file_notice,omitempty"` OmitGQLGenVersionInFileNotice bool `yaml:"omit_gqlgen_version_in_file_notice,omitempty"`
OmitRootModels bool `yaml:"omit_root_models,omitempty"`
StructFieldsAlwaysPointers bool `yaml:"struct_fields_always_pointers,omitempty"` StructFieldsAlwaysPointers bool `yaml:"struct_fields_always_pointers,omitempty"`
ReturnPointersInUmarshalInput bool `yaml:"return_pointers_in_unmarshalinput,omitempty"` ReturnPointersInUmarshalInput bool `yaml:"return_pointers_in_unmarshalinput,omitempty"`
ResolversAlwaysReturnPointers bool `yaml:"resolvers_always_return_pointers,omitempty"` ResolversAlwaysReturnPointers bool `yaml:"resolvers_always_return_pointers,omitempty"`

View File

@ -0,0 +1,3 @@
#!/usr/bin/env sh
cd ./_examples
go generate ./... || return 0

View File

@ -2,6 +2,7 @@ package graphql
import ( import (
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"io" "io"
"strconv" "strconv"
@ -19,8 +20,16 @@ func UnmarshalUint(v interface{}) (uint, error) {
u64, err := strconv.ParseUint(v, 10, 64) u64, err := strconv.ParseUint(v, 10, 64)
return uint(u64), err return uint(u64), err
case int: case int:
if v < 0 {
return 0, errors.New("cannot convert negative numbers to uint")
}
return uint(v), nil return uint(v), nil
case int64: case int64:
if v < 0 {
return 0, errors.New("cannot convert negative numbers to uint")
}
return uint(v), nil return uint(v), nil
case json.Number: case json.Number:
u64, err := strconv.ParseUint(string(v), 10, 64) u64, err := strconv.ParseUint(string(v), 10, 64)
@ -41,8 +50,16 @@ func UnmarshalUint64(v interface{}) (uint64, error) {
case string: case string:
return strconv.ParseUint(v, 10, 64) return strconv.ParseUint(v, 10, 64)
case int: case int:
if v < 0 {
return 0, errors.New("cannot convert negative numbers to uint64")
}
return uint64(v), nil return uint64(v), nil
case int64: case int64:
if v < 0 {
return 0, errors.New("cannot convert negative numbers to uint64")
}
return uint64(v), nil return uint64(v), nil
case json.Number: case json.Number:
return strconv.ParseUint(string(v), 10, 64) return strconv.ParseUint(string(v), 10, 64)
@ -66,8 +83,16 @@ func UnmarshalUint32(v interface{}) (uint32, error) {
} }
return uint32(iv), nil return uint32(iv), nil
case int: case int:
if v < 0 {
return 0, errors.New("cannot convert negative numbers to uint32")
}
return uint32(v), nil return uint32(v), nil
case int64: case int64:
if v < 0 {
return 0, errors.New("cannot convert negative numbers to uint32")
}
return uint32(v), nil return uint32(v), nil
case json.Number: case json.Number:
iv, err := strconv.ParseUint(string(v), 10, 32) iv, err := strconv.ParseUint(string(v), 10, 32)

View File

@ -1,3 +1,3 @@
package graphql package graphql
const Version = "v0.17.42" const Version = "v0.17.44"

View File

@ -1,6 +1,6 @@
package main package main
//go:generate go generate ./_examples/... //go:generate sh generate_examples.sh
import ( import (
"bytes" "bytes"

View File

@ -62,6 +62,9 @@ func (f *federation) MutateConfig(cfg *config.Config) error {
"federation__Scope": { "federation__Scope": {
Model: config.StringList{"github.com/99designs/gqlgen/graphql.String"}, Model: config.StringList{"github.com/99designs/gqlgen/graphql.String"},
}, },
"federation__Policy": {
Model: config.StringList{"github.com/99designs/gqlgen/graphql.String"},
},
} }
for typeName, entry := range builtins { for typeName, entry := range builtins {
@ -85,6 +88,7 @@ func (f *federation) MutateConfig(cfg *config.Config) error {
cfg.Directives["inaccessible"] = config.DirectiveConfig{SkipRuntime: true} cfg.Directives["inaccessible"] = config.DirectiveConfig{SkipRuntime: true}
cfg.Directives["authenticated"] = config.DirectiveConfig{SkipRuntime: true} cfg.Directives["authenticated"] = config.DirectiveConfig{SkipRuntime: true}
cfg.Directives["requiresScopes"] = config.DirectiveConfig{SkipRuntime: true} cfg.Directives["requiresScopes"] = config.DirectiveConfig{SkipRuntime: true}
cfg.Directives["policy"] = config.DirectiveConfig{SkipRuntime: true}
cfg.Directives["interfaceObject"] = config.DirectiveConfig{SkipRuntime: true} cfg.Directives["interfaceObject"] = config.DirectiveConfig{SkipRuntime: true}
cfg.Directives["composeDirective"] = config.DirectiveConfig{SkipRuntime: true} cfg.Directives["composeDirective"] = config.DirectiveConfig{SkipRuntime: true}
} }
@ -126,7 +130,13 @@ func (f *federation) InjectSourceEarly() *ast.Source {
| UNION | UNION
directive @interfaceObject on OBJECT directive @interfaceObject on OBJECT
directive @link(import: [String!], url: String!) repeatable on SCHEMA directive @link(import: [String!], url: String!) repeatable on SCHEMA
directive @override(from: String!) on FIELD_DEFINITION directive @override(from: String!, label: String) on FIELD_DEFINITION
directive @policy(policies: [[federation__Policy!]!]!) on
| FIELD_DEFINITION
| OBJECT
| INTERFACE
| SCALAR
| ENUM
directive @provides(fields: FieldSet!) on FIELD_DEFINITION directive @provides(fields: FieldSet!) on FIELD_DEFINITION
directive @requires(fields: FieldSet!) on FIELD_DEFINITION directive @requires(fields: FieldSet!) on FIELD_DEFINITION
directive @requiresScopes(scopes: [[federation__Scope!]!]!) on directive @requiresScopes(scopes: [[federation__Scope!]!]!) on
@ -149,6 +159,7 @@ func (f *federation) InjectSourceEarly() *ast.Source {
| UNION | UNION
scalar _Any scalar _Any
scalar FieldSet scalar FieldSet
scalar federation__Policy
scalar federation__Scope scalar federation__Scope
` `
} }

View File

@ -132,7 +132,13 @@ func (ec *executionContext) __resolve_entities(ctx context.Context, representati
{{ range $_, $entity := .Entities }} {{ range $_, $entity := .Entities }}
{{ if and .Resolvers .Multi -}} {{ if and .Resolvers .Multi -}}
case "{{.Def.Name}}": case "{{.Def.Name}}":
{{range $i, $_ := .Resolvers -}} resolverName, err := entityResolverNameFor{{.Def.Name}}(ctx, reps[0])
if err != nil {
return fmt.Errorf(`finding resolver for Entity "{{.Def.Name}}": %w`, err)
}
switch resolverName {
{{ range $i, $resolver := .Resolvers }}
case "{{.ResolverName}}":
_reps := make([]*{{.LookupInputType}}, len(reps)) _reps := make([]*{{.LookupInputType}}, len(reps))
for i, rep := range reps { for i, rep := range reps {
@ -166,6 +172,9 @@ func (ec *executionContext) __resolve_entities(ctx context.Context, representati
} }
return nil return nil
{{ end }} {{ end }}
default:
return fmt.Errorf("unknown resolver: %s", resolverName)
}
{{ end }} {{ end }}
{{- end }} {{- end }}
default: default:

View File

@ -139,10 +139,12 @@ func (m *Plugin) MutateConfig(cfg *config.Config) error {
b.Interfaces = append(b.Interfaces, it) b.Interfaces = append(b.Interfaces, it)
case ast.Object, ast.InputObject: case ast.Object, ast.InputObject:
if cfg.IsRoot(schemaType) { if cfg.IsRoot(schemaType) {
b.Models = append(b.Models, &Object{ if !cfg.OmitRootModels {
Description: schemaType.Description, b.Models = append(b.Models, &Object{
Name: schemaType.Name, Description: schemaType.Description,
}) Name: schemaType.Name,
})
}
continue continue
} }

View File

@ -281,9 +281,9 @@ func newSRTConn(config srtConnConfig) *srtConn {
c.ctx, c.cancelCtx = context.WithCancel(context.Background()) c.ctx, c.cancelCtx = context.WithCancel(context.Background())
go c.networkQueueReader() go c.networkQueueReader(c.ctx)
go c.writeQueueReader() go c.writeQueueReader(c.ctx)
go c.ticker() go c.ticker(c.ctx)
c.debug.expectedRcvPacketSequenceNumber = c.initialPacketSequenceNumber c.debug.expectedRcvPacketSequenceNumber = c.initialPacketSequenceNumber
c.debug.expectedReadPacketSequenceNumber = c.initialPacketSequenceNumber c.debug.expectedReadPacketSequenceNumber = c.initialPacketSequenceNumber
@ -311,11 +311,19 @@ func newSRTConn(config srtConnConfig) *srtConn {
} }
func (c *srtConn) LocalAddr() net.Addr { func (c *srtConn) LocalAddr() net.Addr {
if c.localAddr == nil {
return nil
}
addr, _ := net.ResolveUDPAddr("udp", c.localAddr.String()) addr, _ := net.ResolveUDPAddr("udp", c.localAddr.String())
return addr return addr
} }
func (c *srtConn) RemoteAddr() net.Addr { func (c *srtConn) RemoteAddr() net.Addr {
if c.remoteAddr == nil {
return nil
}
addr, _ := net.ResolveUDPAddr("udp", c.remoteAddr.String()) addr, _ := net.ResolveUDPAddr("udp", c.remoteAddr.String())
return addr return addr
} }
@ -338,7 +346,7 @@ func (c *srtConn) Version() uint32 {
// ticker invokes the congestion control in regular intervals with // ticker invokes the congestion control in regular intervals with
// the current connection time. // the current connection time.
func (c *srtConn) ticker() { func (c *srtConn) ticker(ctx context.Context) {
ticker := time.NewTicker(c.tick) ticker := time.NewTicker(c.tick)
defer ticker.Stop() defer ticker.Stop()
defer func() { defer func() {
@ -347,7 +355,7 @@ func (c *srtConn) ticker() {
for { for {
select { select {
case <-c.ctx.Done(): case <-ctx.Done():
return return
case t := <-ticker.C: case t := <-ticker.C:
tickTime := uint64(t.Sub(c.start).Microseconds()) tickTime := uint64(t.Sub(c.start).Microseconds())
@ -429,7 +437,7 @@ func (c *srtConn) Write(b []byte) (int, error) {
return 0, err return 0, err
} }
p := packet.NewPacket(nil, nil) p := packet.NewPacket(nil)
p.SetData(c.writeData[:n]) p.SetData(c.writeData[:n])
@ -526,14 +534,14 @@ func (c *srtConn) pop(p packet.Packet) {
} }
// networkQueueReader reads the packets from the network queue in order to process them. // networkQueueReader reads the packets from the network queue in order to process them.
func (c *srtConn) networkQueueReader() { func (c *srtConn) networkQueueReader(ctx context.Context) {
defer func() { defer func() {
c.log("connection:close", func() string { return "left network queue reader loop" }) c.log("connection:close", func() string { return "left network queue reader loop" })
}() }()
for { for {
select { select {
case <-c.ctx.Done(): case <-ctx.Done():
return return
case p := <-c.networkQueue: case p := <-c.networkQueue:
c.handlePacket(p) c.handlePacket(p)
@ -543,14 +551,14 @@ func (c *srtConn) networkQueueReader() {
// writeQueueReader reads the packets from the write queue and puts them into congestion // writeQueueReader reads the packets from the write queue and puts them into congestion
// control for sending. // control for sending.
func (c *srtConn) writeQueueReader() { func (c *srtConn) writeQueueReader(ctx context.Context) {
defer func() { defer func() {
c.log("connection:close", func() string { return "left write queue reader loop" }) c.log("connection:close", func() string { return "left write queue reader loop" })
}() }()
for { for {
select { select {
case <-c.ctx.Done(): case <-ctx.Done():
return return
case p := <-c.writeQueue: case p := <-c.writeQueue:
// Put the packet into the send congestion control // Put the packet into the send congestion control
@ -1133,7 +1141,7 @@ func (c *srtConn) handleKMResponse(p packet.Packet) {
// sendShutdown sends a shutdown packet to the peer. // sendShutdown sends a shutdown packet to the peer.
func (c *srtConn) sendShutdown() { func (c *srtConn) sendShutdown() {
p := packet.NewPacket(c.remoteAddr, nil) p := packet.NewPacket(c.remoteAddr)
p.Header().IsControlPacket = true p.Header().IsControlPacket = true
@ -1156,7 +1164,7 @@ func (c *srtConn) sendShutdown() {
// sendNAK sends a NAK to the peer with the given range of sequence numbers. // sendNAK sends a NAK to the peer with the given range of sequence numbers.
func (c *srtConn) sendNAK(from, to circular.Number) { func (c *srtConn) sendNAK(from, to circular.Number) {
p := packet.NewPacket(c.remoteAddr, nil) p := packet.NewPacket(c.remoteAddr)
p.Header().IsControlPacket = true p.Header().IsControlPacket = true
@ -1182,7 +1190,7 @@ func (c *srtConn) sendNAK(from, to circular.Number) {
// sendACK sends an ACK to the peer with the given sequence number. // sendACK sends an ACK to the peer with the given sequence number.
func (c *srtConn) sendACK(seq circular.Number, lite bool) { func (c *srtConn) sendACK(seq circular.Number, lite bool) {
p := packet.NewPacket(c.remoteAddr, nil) p := packet.NewPacket(c.remoteAddr)
p.Header().IsControlPacket = true p.Header().IsControlPacket = true
@ -1233,7 +1241,7 @@ func (c *srtConn) sendACK(seq circular.Number, lite bool) {
// sendACKACK sends an ACKACK to the peer with the given ACK sequence. // sendACKACK sends an ACKACK to the peer with the given ACK sequence.
func (c *srtConn) sendACKACK(ackSequence uint32) { func (c *srtConn) sendACKACK(ackSequence uint32) {
p := packet.NewPacket(c.remoteAddr, nil) p := packet.NewPacket(c.remoteAddr)
p.Header().IsControlPacket = true p.Header().IsControlPacket = true
@ -1280,7 +1288,7 @@ func (c *srtConn) sendHSRequest() {
SendTSBPDDelay: uint16(c.config.ReceiverLatency.Milliseconds()), SendTSBPDDelay: uint16(c.config.ReceiverLatency.Milliseconds()),
} }
p := packet.NewPacket(c.remoteAddr, nil) p := packet.NewPacket(c.remoteAddr)
p.Header().IsControlPacket = true p.Header().IsControlPacket = true
@ -1319,7 +1327,7 @@ func (c *srtConn) sendKMRequest(key packet.PacketEncryption) {
c.crypto.MarshalKM(cif, c.config.Passphrase, key) c.crypto.MarshalKM(cif, c.config.Passphrase, key)
p := packet.NewPacket(c.remoteAddr, nil) p := packet.NewPacket(c.remoteAddr)
p.Header().IsControlPacket = true p.Header().IsControlPacket = true

View File

@ -157,8 +157,8 @@ func Dial(network, address string, config Config) (Conn, error) {
return return
} }
p := packet.NewPacket(dl.remoteAddr, buffer[:n]) p, err := packet.NewPacketFromData(dl.remoteAddr, buffer[:n])
if p == nil { if err != nil {
continue continue
} }
@ -532,7 +532,7 @@ func (dl *dialer) handleHandshake(p packet.Packet) {
} }
func (dl *dialer) sendInduction() { func (dl *dialer) sendInduction() {
p := packet.NewPacket(dl.remoteAddr, nil) p := packet.NewPacket(dl.remoteAddr)
p.Header().IsControlPacket = true p.Header().IsControlPacket = true
@ -567,7 +567,7 @@ func (dl *dialer) sendInduction() {
} }
func (dl *dialer) sendShutdown(peerSocketId uint32) { func (dl *dialer) sendShutdown(peerSocketId uint32) {
p := packet.NewPacket(dl.remoteAddr, nil) p := packet.NewPacket(dl.remoteAddr)
data := [4]byte{} data := [4]byte{}
binary.BigEndian.PutUint32(data[0:], 0) binary.BigEndian.PutUint32(data[0:], 0)
@ -588,26 +588,68 @@ func (dl *dialer) sendShutdown(peerSocketId uint32) {
} }
func (dl *dialer) LocalAddr() net.Addr { func (dl *dialer) LocalAddr() net.Addr {
dl.connLock.RLock()
defer dl.connLock.RUnlock()
if dl.conn == nil {
return nil
}
return dl.conn.LocalAddr() return dl.conn.LocalAddr()
} }
func (dl *dialer) RemoteAddr() net.Addr { func (dl *dialer) RemoteAddr() net.Addr {
dl.connLock.RLock()
defer dl.connLock.RUnlock()
if dl.conn == nil {
return nil
}
return dl.conn.RemoteAddr() return dl.conn.RemoteAddr()
} }
func (dl *dialer) SocketId() uint32 { func (dl *dialer) SocketId() uint32 {
dl.connLock.RLock()
defer dl.connLock.RUnlock()
if dl.conn == nil {
return 0
}
return dl.conn.SocketId() return dl.conn.SocketId()
} }
func (dl *dialer) PeerSocketId() uint32 { func (dl *dialer) PeerSocketId() uint32 {
dl.connLock.RLock()
defer dl.connLock.RUnlock()
if dl.conn == nil {
return 0
}
return dl.conn.PeerSocketId() return dl.conn.PeerSocketId()
} }
func (dl *dialer) StreamId() string { func (dl *dialer) StreamId() string {
dl.connLock.RLock()
defer dl.connLock.RUnlock()
if dl.conn == nil {
return ""
}
return dl.conn.StreamId() return dl.conn.StreamId()
} }
func (dl *dialer) Version() uint32 { func (dl *dialer) Version() uint32 {
dl.connLock.RLock()
defer dl.connLock.RUnlock()
if dl.conn == nil {
return 0
}
return dl.conn.Version() return dl.conn.Version()
} }
@ -652,6 +694,10 @@ func (dl *dialer) Read(p []byte) (n int, err error) {
dl.connLock.RLock() dl.connLock.RLock()
defer dl.connLock.RUnlock() defer dl.connLock.RUnlock()
if dl.conn == nil {
return 0, fmt.Errorf("no connection")
}
return dl.conn.Read(p) return dl.conn.Read(p)
} }
@ -663,6 +709,10 @@ func (dl *dialer) readPacket() (packet.Packet, error) {
dl.connLock.RLock() dl.connLock.RLock()
defer dl.connLock.RUnlock() defer dl.connLock.RUnlock()
if dl.conn == nil {
return nil, fmt.Errorf("no connection")
}
return dl.conn.readPacket() return dl.conn.readPacket()
} }
@ -674,6 +724,10 @@ func (dl *dialer) Write(p []byte) (n int, err error) {
dl.connLock.RLock() dl.connLock.RLock()
defer dl.connLock.RUnlock() defer dl.connLock.RUnlock()
if dl.conn == nil {
return 0, fmt.Errorf("no connection")
}
return dl.conn.Write(p) return dl.conn.Write(p)
} }
@ -685,14 +739,32 @@ func (dl *dialer) writePacket(p packet.Packet) error {
dl.connLock.RLock() dl.connLock.RLock()
defer dl.connLock.RUnlock() defer dl.connLock.RUnlock()
if dl.conn == nil {
return fmt.Errorf("no connection")
}
return dl.conn.writePacket(p) return dl.conn.writePacket(p)
} }
func (dl *dialer) SetDeadline(t time.Time) error { return dl.conn.SetDeadline(t) } func (dl *dialer) SetDeadline(t time.Time) error { return dl.conn.SetDeadline(t) }
func (dl *dialer) SetReadDeadline(t time.Time) error { return dl.conn.SetReadDeadline(t) } func (dl *dialer) SetReadDeadline(t time.Time) error { return dl.conn.SetReadDeadline(t) }
func (dl *dialer) SetWriteDeadline(t time.Time) error { return dl.conn.SetWriteDeadline(t) } func (dl *dialer) SetWriteDeadline(t time.Time) error { return dl.conn.SetWriteDeadline(t) }
func (dl *dialer) Stats(s *Statistics) { dl.conn.Stats(s) }
func (dl *dialer) Stats(s *Statistics) {
dl.connLock.RLock()
defer dl.connLock.RUnlock()
if dl.conn == nil {
return
}
dl.conn.Stats(s)
}
func (dl *dialer) log(topic string, message func() string) { func (dl *dialer) log(topic string, message func() string) {
if dl.config.Logger == nil {
return
}
dl.config.Logger.Print(topic, dl.socketId, 2, message) dl.config.Logger.Print(topic, dl.socketId, 2, message)
} }

View File

@ -113,13 +113,24 @@ func (c *crypto) generateSEK(keyLength int) ([]byte, error) {
var ErrInvalidKey = errors.New("crypto: invalid key for encryption. Must be even, odd, or both") var ErrInvalidKey = errors.New("crypto: invalid key for encryption. Must be even, odd, or both")
// ErrInvalidWrap is returned when the packet encryption indicates a different length of the wrapped key // ErrInvalidWrap is returned when the packet encryption indicates a different length of the wrapped key
var ErrInvalidWrap = errors.New("crypto: the unwrapped key has the wrong length") var ErrInvalidWrap = errors.New("crypto: the un/wrapped key has the wrong length")
func (c *crypto) UnmarshalKM(km *packet.CIFKeyMaterialExtension, passphrase string) error { func (c *crypto) UnmarshalKM(km *packet.CIFKeyMaterialExtension, passphrase string) error {
if km.KeyBasedEncryption == packet.UnencryptedPacket || !km.KeyBasedEncryption.IsValid() { if km.KeyBasedEncryption == packet.UnencryptedPacket || !km.KeyBasedEncryption.IsValid() {
return ErrInvalidKey return ErrInvalidKey
} }
n := 1
if km.KeyBasedEncryption == packet.EvenAndOddKey {
n = 2
}
wrapLength := n * c.keyLength
if len(km.Wrap)-8 != wrapLength {
return ErrInvalidWrap
}
if len(km.Salt) != 0 { if len(km.Salt) != 0 {
copy(c.salt, km.Salt) copy(c.salt, km.Salt)
} }
@ -131,12 +142,7 @@ func (c *crypto) UnmarshalKM(km *packet.CIFKeyMaterialExtension, passphrase stri
return err return err
} }
n := 1 if len(unwrap) != wrapLength {
if km.KeyBasedEncryption == packet.EvenAndOddKey {
n = 2
}
if len(unwrap) != n*c.keyLength {
return ErrInvalidWrap return ErrInvalidWrap
} }
@ -223,6 +229,10 @@ func (c *crypto) EncryptOrDecryptPayload(data []byte, key packet.PacketEncryptio
// //
// CTR = (MSB(112, Salt) XOR psn) << 16 // CTR = (MSB(112, Salt) XOR psn) << 16
if len(c.salt) != 16 {
return fmt.Errorf("crypto: invalid salt. Must be of length 16 bytes")
}
ctr := make([]byte, 16) ctr := make([]byte, 16)
binary.BigEndian.PutUint32(ctr[10:], packetSequenceNumber) binary.BigEndian.PutUint32(ctr[10:], packetSequenceNumber)

View File

@ -12,11 +12,11 @@ type IP struct {
} }
func (i *IP) setDefault() { func (i *IP) setDefault() {
i.ip = net.ParseIP("127.0.0.1") i.ip = net.IPv4(127, 0, 0, 1)
} }
func (i *IP) isValid() bool { func (i *IP) isValid() bool {
if i.ip.String() == "<nil>" || i.ip.IsUnspecified() { if i.ip == nil || i.ip.String() == "<nil>" || i.ip.IsUnspecified() {
return false return false
} }
@ -24,11 +24,22 @@ func (i *IP) isValid() bool {
} }
func (i IP) String() string { func (i IP) String() string {
if i.ip == nil {
return ""
}
return i.ip.String() return i.ip.String()
} }
func (i *IP) Parse(ip string) { func (i *IP) Parse(ip string) {
i.ip = net.ParseIP(ip) i.setDefault()
iip := net.ParseIP(ip)
if iip == nil {
return
}
i.ip = iip
if !i.isValid() { if !i.isValid() {
i.setDefault() i.setDefault()
@ -36,7 +47,16 @@ func (i *IP) Parse(ip string) {
} }
func (i *IP) FromNetIP(ip net.IP) { func (i *IP) FromNetIP(ip net.IP) {
i.ip = net.ParseIP(ip.String()) if ip == nil {
return
}
iip := net.ParseIP(ip.String())
if iip == nil {
return
}
i.ip = iip
if !i.isValid() { if !i.isValid() {
i.setDefault() i.setDefault()
@ -44,12 +64,22 @@ func (i *IP) FromNetIP(ip net.IP) {
} }
func (i *IP) FromNetAddr(addr net.Addr) { func (i *IP) FromNetAddr(addr net.Addr) {
if addr == nil {
i.setDefault()
return
}
if addr.Network() != "udp" { if addr.Network() != "udp" {
i.setDefault() i.setDefault()
return
} }
if a, err := net.ResolveUDPAddr("udp", addr.String()); err == nil { if a, err := net.ResolveUDPAddr("udp", addr.String()); err == nil {
i.ip = a.IP if a == nil || a.IP == nil {
i.setDefault()
} else {
i.ip = a.IP
}
} else { } else {
i.setDefault() i.setDefault()
} }
@ -85,7 +115,12 @@ func (i *IP) Unmarshal(data []byte) error {
fmt.Fprintf(&b, "%04x:", (ip3&0xffff0000)>>16) fmt.Fprintf(&b, "%04x:", (ip3&0xffff0000)>>16)
fmt.Fprintf(&b, "%04x", ip3&0x0000ffff) fmt.Fprintf(&b, "%04x", ip3&0x0000ffff)
i.ip = net.ParseIP(b.String()) iip := net.ParseIP(b.String())
if iip == nil {
return fmt.Errorf("invalid ip")
}
i.ip = iip
} }
} }
@ -98,6 +133,14 @@ func (i *IP) Unmarshal(data []byte) error {
// Marshal converts an IP to 16 byte host byte order // Marshal converts an IP to 16 byte host byte order
func (i *IP) Marshal(data []byte) { func (i *IP) Marshal(data []byte) {
if i.ip == nil || !i.isValid() {
i.setDefault()
}
if len([]byte(i.ip)) == 4 {
i.ip = net.IPv4(i.ip[0], i.ip[1], i.ip[2], i.ip[3])
}
if len(data) < 16 { if len(data) < 16 {
return return
} }

View File

@ -9,6 +9,7 @@ import (
"io" "io"
"net" "net"
"sort" "sort"
"strconv"
"strings" "strings"
"sync" "sync"
@ -78,26 +79,6 @@ const (
HSTYPE_INDUCTION HandshakeType = 0x00000001 HSTYPE_INDUCTION HandshakeType = 0x00000001
) )
// Table 7: Handshake Rejection Reason Codes
const (
REJ_UNKNOWN HandshakeType = 1000
REJ_SYSTEM HandshakeType = 1001
REJ_PEER HandshakeType = 1002
REJ_RESOURCE HandshakeType = 1003
REJ_ROGUE HandshakeType = 1004
REJ_BACKLOG HandshakeType = 1005
REJ_IPE HandshakeType = 1006
REJ_CLOSE HandshakeType = 1007
REJ_VERSION HandshakeType = 1008
REJ_RDVCOOKIE HandshakeType = 1009
REJ_BADSECRET HandshakeType = 1010
REJ_UNSECURE HandshakeType = 1011
REJ_MESSAGEAPI HandshakeType = 1012
REJ_CONGESTION HandshakeType = 1013
REJ_FILTER HandshakeType = 1014
REJ_GROUP HandshakeType = 1015
)
func (h HandshakeType) String() string { func (h HandshakeType) String() string {
switch h { switch h {
case HSTYPE_DONE: case HSTYPE_DONE:
@ -110,45 +91,9 @@ func (h HandshakeType) String() string {
return "WAVEHAND" return "WAVEHAND"
case HSTYPE_INDUCTION: case HSTYPE_INDUCTION:
return "INDUCTION" return "INDUCTION"
case REJ_UNKNOWN:
return "REJ_UNKNOWN (unknown reason)"
case REJ_SYSTEM:
return "REJ_SYSTEM (system function error)"
case REJ_PEER:
return "REJ_PEER (rejected by peer)"
case REJ_RESOURCE:
return "REJ_RESOURCE (resource allocation problem)"
case REJ_ROGUE:
return "REJ_ROGUE (incorrect data in handshake)"
case REJ_BACKLOG:
return "REJ_BACKLOG (listener's backlog exceeded)"
case REJ_IPE:
return "REJ_IPE (internal program error)"
case REJ_CLOSE:
return "REJ_CLOSE (socket is closing)"
case REJ_VERSION:
return "REJ_VERSION (peer is older version than agent's min)"
case REJ_RDVCOOKIE:
return "REJ_RDVCOOKIE (rendezvous cookie collision)"
case REJ_BADSECRET:
return "REJ_BADSECRET (wrong password)"
case REJ_UNSECURE:
return "REJ_UNSECURE (password required or unexpected)"
case REJ_MESSAGEAPI:
return "REJ_MESSAGEAPI (stream flag collision)"
case REJ_CONGESTION:
return "REJ_CONGESTION (incompatible congestion-controller type)"
case REJ_FILTER:
return "REJ_FILTER (incompatible packet filter)"
case REJ_GROUP:
return "REJ_GROUP (incompatible group)"
} }
return "unknown" return "REJECT (" + strconv.FormatUint(uint64(h), 32) + ")"
}
func (h HandshakeType) IsUnknown() bool {
return h.String() == "unknown"
} }
func (h HandshakeType) IsHandshake() bool { func (h HandshakeType) IsHandshake() bool {
@ -166,13 +111,7 @@ func (h HandshakeType) IsHandshake() bool {
} }
func (h HandshakeType) IsRejection() bool { func (h HandshakeType) IsRejection() bool {
if h.IsUnknown() { return !h.IsHandshake()
return false
} else if h.IsHandshake() {
return false
}
return true
} }
func (h HandshakeType) Val() uint32 { func (h HandshakeType) Val() uint32 {
@ -311,7 +250,20 @@ func (p *pool) Put(b *bytes.Buffer) {
var payloadPool *pool = newPool() var payloadPool *pool = newPool()
func NewPacket(addr net.Addr, rawdata []byte) Packet { func NewPacketFromData(addr net.Addr, rawdata []byte) (Packet, error) {
p := NewPacket(addr)
if len(rawdata) != 0 {
if err := p.Unmarshal(rawdata); err != nil {
p.Decommission()
return nil, fmt.Errorf("invalid data: %w", err)
}
}
return p, nil
}
func NewPacket(addr net.Addr) Packet {
p := &pkt{ p := &pkt{
header: PacketHeader{ header: PacketHeader{
Addr: addr, Addr: addr,
@ -324,13 +276,6 @@ func NewPacket(addr net.Addr, rawdata []byte) Packet {
payload: payloadPool.Get(), payload: payloadPool.Get(),
} }
if len(rawdata) != 0 {
if err := p.Unmarshal(rawdata); err != nil {
p.Decommission()
return nil
}
}
return p return p
} }
@ -424,6 +369,10 @@ func (p *pkt) Unmarshal(data []byte) error {
} }
func (p *pkt) Marshal(w io.Writer) error { func (p *pkt) Marshal(w io.Writer) error {
if w == nil {
return fmt.Errorf("invalid writer")
}
var buffer [16]byte var buffer [16]byte
if p.payload == nil { if p.payload == nil {
@ -685,6 +634,10 @@ func (c *CIFHandshake) Unmarshal(data []byte) error {
} }
func (c *CIFHandshake) Marshal(w io.Writer) { func (c *CIFHandshake) Marshal(w io.Writer) {
if w == nil {
return
}
var buffer [128]byte var buffer [128]byte
if len(c.StreamId) == 0 { if len(c.StreamId) == 0 {
@ -856,6 +809,10 @@ func (c *CIFHandshakeExtension) Unmarshal(data []byte) error {
} }
func (c *CIFHandshakeExtension) Marshal(w io.Writer) { func (c *CIFHandshakeExtension) Marshal(w io.Writer) {
if w == nil {
return
}
var buffer [12]byte var buffer [12]byte
binary.BigEndian.PutUint32(buffer[0:], c.SRTVersion) binary.BigEndian.PutUint32(buffer[0:], c.SRTVersion)
@ -1050,6 +1007,10 @@ func (c *CIFKeyMaterialExtension) Unmarshal(data []byte) error {
} }
func (c *CIFKeyMaterialExtension) Marshal(w io.Writer) { func (c *CIFKeyMaterialExtension) Marshal(w io.Writer) {
if w == nil {
return
}
var buffer [128]byte var buffer [128]byte
b := byte(0) b := byte(0)
@ -1170,6 +1131,10 @@ func (c *CIFACK) Unmarshal(data []byte) error {
} }
func (c *CIFACK) Marshal(w io.Writer) { func (c *CIFACK) Marshal(w io.Writer) {
if w == nil {
return
}
var buffer [28]byte var buffer [28]byte
binary.BigEndian.PutUint32(buffer[0:], c.LastACKPacketSequenceNumber.Val()) binary.BigEndian.PutUint32(buffer[0:], c.LastACKPacketSequenceNumber.Val())
@ -1257,6 +1222,10 @@ func (c *CIFNAK) Unmarshal(data []byte) error {
} }
func (c *CIFNAK) Marshal(w io.Writer) { func (c *CIFNAK) Marshal(w io.Writer) {
if w == nil {
return
}
if len(c.LostPacketSequenceNumber)%2 != 0 { if len(c.LostPacketSequenceNumber)%2 != 0 {
return return
} }
@ -1294,6 +1263,10 @@ func (c *CIFShutdown) Unmarshal(data []byte) error {
} }
func (c *CIFShutdown) Marshal(w io.Writer) { func (c *CIFShutdown) Marshal(w io.Writer) {
if w == nil {
return
}
var buffer [4]byte var buffer [4]byte
binary.BigEndian.PutUint32(buffer[0:], 0) binary.BigEndian.PutUint32(buffer[0:], 0)

View File

@ -39,6 +39,52 @@ const (
SUBSCRIBE // This connection is meant to read data from a PUBLISHed stream SUBSCRIBE // This connection is meant to read data from a PUBLISHed stream
) )
// RejectionReason are the rejection reasons that can be returned from the AcceptFunc in order to send
// another reason than the default one (REJ_PEER) to the client.
type RejectionReason uint32
// Table 7: Handshake Rejection Reason Codes
const (
REJ_UNKNOWN RejectionReason = 1000 // unknown reason
REJ_SYSTEM RejectionReason = 1001 // system function error
REJ_PEER RejectionReason = 1002 // rejected by peer
REJ_RESOURCE RejectionReason = 1003 // resource allocation problem
REJ_ROGUE RejectionReason = 1004 // incorrect data in handshake
REJ_BACKLOG RejectionReason = 1005 // listener's backlog exceeded
REJ_IPE RejectionReason = 1006 // internal program error
REJ_CLOSE RejectionReason = 1007 // socket is closing
REJ_VERSION RejectionReason = 1008 // peer is older version than agent's min
REJ_RDVCOOKIE RejectionReason = 1009 // rendezvous cookie collision
REJ_BADSECRET RejectionReason = 1010 // wrong password
REJ_UNSECURE RejectionReason = 1011 // password required or unexpected
REJ_MESSAGEAPI RejectionReason = 1012 // stream flag collision
REJ_CONGESTION RejectionReason = 1013 // incompatible congestion-controller type
REJ_FILTER RejectionReason = 1014 // incompatible packet filter
REJ_GROUP RejectionReason = 1015 // incompatible group
)
// These are the extended rejection reasons that may be less well supported
// Codes & their meanings taken from https://github.com/Haivision/srt/blob/f477af533562505abf5295f059cf2156b17be740/srtcore/access_control.h
const (
REJX_BAD_REQUEST RejectionReason = 1400 // General syntax error in the SocketID specification (also a fallback code for undefined cases)
REJX_UNAUTHORIZED RejectionReason = 1401 // Authentication failed, provided that the user was correctly identified and access to the required resource would be granted
REJX_OVERLOAD RejectionReason = 1402 // The server is too heavily loaded, or you have exceeded credits for accessing the service and the resource.
REJX_FORBIDDEN RejectionReason = 1403 // Access denied to the resource by any kind of reason.
REJX_NOTFOUND RejectionReason = 1404 // Resource not found at this time.
REJX_BAD_MODE RejectionReason = 1405 // The mode specified in `m` key in StreamID is not supported for this request.
REJX_UNACCEPTABLE RejectionReason = 1406 // The requested parameters specified in SocketID cannot be satisfied for the requested resource. Also when m=publish and the data format is not acceptable.
REJX_CONFLICT RejectionReason = 1407 // The resource being accessed is already locked for modification. This is in case of m=publish and the specified resource is currently read-only.
REJX_NOTSUP_MEDIA RejectionReason = 1415 // The media type is not supported by the application. This is the `t` key that specifies the media type as stream, file and auth, possibly extended by the application.
REJX_LOCKED RejectionReason = 1423 // The resource being accessed is locked for any access.
REJX_FAILED_DEPEND RejectionReason = 1424 // The request failed because it specified a dependent session ID that has been disconnected.
REJX_ISE RejectionReason = 1500 // Unexpected internal server error
REJX_UNIMPLEMENTED RejectionReason = 1501 // The request was recognized, but the current version doesn't support it.
REJX_GW RejectionReason = 1502 // The server acts as a gateway and the target endpoint rejected the connection.
REJX_DOWN RejectionReason = 1503 // The service has been temporarily taken over by a stub reporting this error. The real service can be down for maintenance or crashed.
REJX_VERSION RejectionReason = 1505 // SRT version not supported. This might be either unsupported backward compatibility, or an upper value of a version.
REJX_NOROOM RejectionReason = 1507 // The data stream cannot be archived due to lacking storage space. This is in case when the request type was to send a file or the live stream to be archived.
)
// ConnRequest is an incoming connection request // ConnRequest is an incoming connection request
type ConnRequest interface { type ConnRequest interface {
// RemoteAddr returns the address of the peer. The returned net.Addr // RemoteAddr returns the address of the peer. The returned net.Addr
@ -63,6 +109,10 @@ type ConnRequest interface {
// data. Returns an error if the passphrase did not work or the connection // data. Returns an error if the passphrase did not work or the connection
// is not encrypted. // is not encrypted.
SetPassphrase(p string) error SetPassphrase(p string) error
// SetRejectionReason sets the rejection reason for the connection. If
// no set, REJ_PEER will be used.
SetRejectionReason(r RejectionReason)
} }
// connRequest implements the ConnRequest interface // connRequest implements the ConnRequest interface
@ -72,9 +122,11 @@ type connRequest struct {
socketId uint32 socketId uint32
timestamp uint32 timestamp uint32
handshake *packet.CIFHandshake config Config
crypto crypto.Crypto handshake *packet.CIFHandshake
passphrase string crypto crypto.Crypto
passphrase string
rejectionReason RejectionReason
} }
func (req *connRequest) RemoteAddr() net.Addr { func (req *connRequest) RemoteAddr() net.Addr {
@ -110,6 +162,10 @@ func (req *connRequest) SetPassphrase(passphrase string) error {
return nil return nil
} }
func (req *connRequest) SetRejectionReason(reason RejectionReason) {
req.rejectionReason = reason
}
// ErrListenerClosed is returned when the listener is about to shutdown. // ErrListenerClosed is returned when the listener is about to shutdown.
var ErrListenerClosed = errors.New("srt: listener closed") var ErrListenerClosed = errors.New("srt: listener closed")
@ -160,7 +216,9 @@ type listener struct {
stopReader context.CancelFunc stopReader context.CancelFunc
doneChan chan error doneChan chan struct{}
doneErr error
doneOnce sync.Once
} }
// Listen returns a new listener on the SRT protocol on the address with // Listen returns a new listener on the SRT protocol on the address with
@ -203,6 +261,9 @@ func Listen(network, address string, config Config) (Listener, error) {
ln.pc = pc ln.pc = pc
ln.addr = pc.LocalAddr() ln.addr = pc.LocalAddr()
if ln.addr == nil {
return nil, fmt.Errorf("listen: no local address")
}
ln.conns = make(map[uint32]*srtConn) ln.conns = make(map[uint32]*srtConn)
@ -210,13 +271,14 @@ func Listen(network, address string, config Config) (Listener, error) {
ln.rcvQueue = make(chan packet.Packet, 2048) ln.rcvQueue = make(chan packet.Packet, 2048)
ln.syncookie, err = srtnet.NewSYNCookie(ln.addr.String(), nil) syncookie, err := srtnet.NewSYNCookie(ln.addr.String(), nil)
if err != nil { if err != nil {
ln.Close() ln.Close()
return nil, err return nil, err
} }
ln.syncookie = syncookie
ln.doneChan = make(chan error) ln.doneChan = make(chan struct{})
ln.start = time.Now() ln.start = time.Now()
@ -229,7 +291,7 @@ func Listen(network, address string, config Config) (Listener, error) {
for { for {
if ln.isShutdown() { if ln.isShutdown() {
ln.doneChan <- ErrListenerClosed ln.markDone(ErrListenerClosed)
return return
} }
@ -241,16 +303,16 @@ func Listen(network, address string, config Config) (Listener, error) {
} }
if ln.isShutdown() { if ln.isShutdown() {
ln.doneChan <- ErrListenerClosed ln.markDone(ErrListenerClosed)
return return
} }
ln.doneChan <- err ln.markDone(err)
return return
} }
p := packet.NewPacket(addr, buffer[:n]) p, err := packet.NewPacketFromData(addr, buffer[:n])
if p == nil { if err != nil {
continue continue
} }
@ -272,22 +334,27 @@ func (ln *listener) Accept(acceptFn AcceptFunc) (Conn, ConnType, error) {
} }
select { select {
case err := <-ln.doneChan: case <-ln.doneChan:
return nil, REJECT, err return nil, REJECT, ln.error()
case request := <-ln.backlog: case request := <-ln.backlog:
if acceptFn == nil { if acceptFn == nil {
ln.reject(request, packet.REJ_PEER) ln.reject(request, REJ_PEER)
break break
} }
mode := acceptFn(&request) mode := acceptFn(&request)
if mode != PUBLISH && mode != SUBSCRIBE { if mode != PUBLISH && mode != SUBSCRIBE {
ln.reject(request, packet.REJ_PEER) // Figure out the reason
reason := REJ_PEER
if request.rejectionReason > 0 {
reason = request.rejectionReason
}
ln.reject(request, reason)
break break
} }
if request.crypto != nil && len(request.passphrase) == 0 { if request.crypto != nil && len(request.passphrase) == 0 {
ln.reject(request, packet.REJ_BADSECRET) ln.reject(request, REJ_BADSECRET)
break break
} }
@ -295,8 +362,8 @@ func (ln *listener) Accept(acceptFn AcceptFunc) (Conn, ConnType, error) {
socketId := uint32(time.Since(ln.start).Microseconds()) socketId := uint32(time.Since(ln.start).Microseconds())
// Select the largest TSBPD delay advertised by the caller, but at least 120ms // Select the largest TSBPD delay advertised by the caller, but at least 120ms
recvTsbpdDelay := uint16(ln.config.ReceiverLatency.Milliseconds()) recvTsbpdDelay := uint16(request.config.ReceiverLatency.Milliseconds())
sendTsbpdDelay := uint16(ln.config.PeerLatency.Milliseconds()) sendTsbpdDelay := uint16(request.config.PeerLatency.Milliseconds())
if request.handshake.Version == 5 { if request.handshake.Version == 5 {
if request.handshake.SRTHS.SendTSBPDDelay > recvTsbpdDelay { if request.handshake.SRTHS.SendTSBPDDelay > recvTsbpdDelay {
@ -307,17 +374,17 @@ func (ln *listener) Accept(acceptFn AcceptFunc) (Conn, ConnType, error) {
sendTsbpdDelay = request.handshake.SRTHS.RecvTSBPDDelay sendTsbpdDelay = request.handshake.SRTHS.RecvTSBPDDelay
} }
ln.config.StreamId = request.handshake.StreamId request.config.StreamId = request.handshake.StreamId
} }
ln.config.Passphrase = request.passphrase request.config.Passphrase = request.passphrase
// Create a new connection // Create a new connection
conn := newSRTConn(srtConnConfig{ conn := newSRTConn(srtConnConfig{
version: request.handshake.Version, version: request.handshake.Version,
localAddr: ln.addr, localAddr: ln.addr,
remoteAddr: request.addr, remoteAddr: request.addr,
config: ln.config, config: request.config,
start: request.start, start: request.start,
socketId: socketId, socketId: socketId,
peerSocketId: request.handshake.SRTSocketId, peerSocketId: request.handshake.SRTSocketId,
@ -329,7 +396,7 @@ func (ln *listener) Accept(acceptFn AcceptFunc) (Conn, ConnType, error) {
keyBaseEncryption: packet.EvenKeyEncrypted, keyBaseEncryption: packet.EvenKeyEncrypted,
onSend: ln.send, onSend: ln.send,
onShutdown: ln.handleShutdown, onShutdown: ln.handleShutdown,
logger: ln.config.Logger, logger: request.config.Logger,
}) })
ln.log("connection:new", func() string { return fmt.Sprintf("%#08x (%s) %s", conn.SocketId(), conn.StreamId(), mode) }) ln.log("connection:new", func() string { return fmt.Sprintf("%#08x (%s) %s", conn.SocketId(), conn.StreamId(), mode) })
@ -365,14 +432,33 @@ func (ln *listener) Accept(acceptFn AcceptFunc) (Conn, ConnType, error) {
return nil, REJECT, nil return nil, REJECT, nil
} }
// markDone marks the listener as done by closing
// the done channel & sets the error
func (ln *listener) markDone(err error) {
ln.doneOnce.Do(func() {
ln.lock.Lock()
defer ln.lock.Unlock()
ln.doneErr = err
close(ln.doneChan)
})
}
// error returns the error that caused the listener to be done
// if it's nil then the listener is not done
func (ln *listener) error() error {
ln.lock.Lock()
defer ln.lock.Unlock()
return ln.doneErr
}
func (ln *listener) handleShutdown(socketId uint32) { func (ln *listener) handleShutdown(socketId uint32) {
ln.lock.Lock() ln.lock.Lock()
delete(ln.conns, socketId) delete(ln.conns, socketId)
ln.lock.Unlock() ln.lock.Unlock()
} }
func (ln *listener) reject(request connRequest, reason packet.HandshakeType) { func (ln *listener) reject(request connRequest, reason RejectionReason) {
p := packet.NewPacket(request.addr, nil) p := packet.NewPacket(request.addr)
p.Header().IsControlPacket = true p.Header().IsControlPacket = true
p.Header().ControlType = packet.CTRLTYPE_HANDSHAKE p.Header().ControlType = packet.CTRLTYPE_HANDSHAKE
@ -382,7 +468,7 @@ func (ln *listener) reject(request connRequest, reason packet.HandshakeType) {
p.Header().Timestamp = uint32(time.Since(ln.start).Microseconds()) p.Header().Timestamp = uint32(time.Since(ln.start).Microseconds())
p.Header().DestinationSocketId = request.socketId p.Header().DestinationSocketId = request.socketId
request.handshake.HandshakeType = reason request.handshake.HandshakeType = packet.HandshakeType(reason)
p.MarshalCIF(request.handshake) p.MarshalCIF(request.handshake)
@ -393,7 +479,7 @@ func (ln *listener) reject(request connRequest, reason packet.HandshakeType) {
} }
func (ln *listener) accept(request connRequest) { func (ln *listener) accept(request connRequest) {
p := packet.NewPacket(request.addr, nil) p := packet.NewPacket(request.addr)
p.Header().IsControlPacket = true p.Header().IsControlPacket = true
@ -440,7 +526,12 @@ func (ln *listener) Close() {
} }
func (ln *listener) Addr() net.Addr { func (ln *listener) Addr() net.Addr {
addr, _ := net.ResolveUDPAddr("udp", ln.addr.String()) addrString := "0.0.0.0:0"
if ln.addr != nil {
addrString = ln.addr.String()
}
addr, _ := net.ResolveUDPAddr("udp", addrString)
return addr return addr
} }
@ -533,6 +624,9 @@ func (ln *listener) handleHandshake(p packet.Packet) {
cif.PeerIP.FromNetAddr(ln.addr) cif.PeerIP.FromNetAddr(ln.addr)
// Create a copy of the configuration for the connection
config := ln.config
if cif.HandshakeType == packet.HSTYPE_INDUCTION { if cif.HandshakeType == packet.HSTYPE_INDUCTION {
// cif // cif
cif.Version = 5 cif.Version = 5
@ -553,7 +647,7 @@ func (ln *listener) handleHandshake(p packet.Packet) {
} else if cif.HandshakeType == packet.HSTYPE_CONCLUSION { } else if cif.HandshakeType == packet.HSTYPE_CONCLUSION {
// Verify the SYN cookie // Verify the SYN cookie
if !ln.syncookie.Verify(cif.SynCookie, p.Header().Addr.String()) { if !ln.syncookie.Verify(cif.SynCookie, p.Header().Addr.String()) {
cif.HandshakeType = packet.REJ_ROGUE cif.HandshakeType = packet.HandshakeType(REJ_ROGUE)
ln.log("handshake:recv:error", func() string { return "invalid SYN cookie" }) ln.log("handshake:recv:error", func() string { return "invalid SYN cookie" })
p.MarshalCIF(cif) p.MarshalCIF(cif)
ln.log("handshake:send:dump", func() string { return p.Dump() }) ln.log("handshake:send:dump", func() string { return p.Dump() })
@ -565,7 +659,7 @@ func (ln *listener) handleHandshake(p packet.Packet) {
// Peer is advertising a too big MSS // Peer is advertising a too big MSS
if cif.MaxTransmissionUnitSize > MAX_MSS_SIZE { if cif.MaxTransmissionUnitSize > MAX_MSS_SIZE {
cif.HandshakeType = packet.REJ_ROGUE cif.HandshakeType = packet.HandshakeType(REJ_ROGUE)
ln.log("handshake:recv:error", func() string { return fmt.Sprintf("MTU is too big (%d bytes)", cif.MaxTransmissionUnitSize) }) ln.log("handshake:recv:error", func() string { return fmt.Sprintf("MTU is too big (%d bytes)", cif.MaxTransmissionUnitSize) })
p.MarshalCIF(cif) p.MarshalCIF(cif)
ln.log("handshake:send:dump", func() string { return p.Dump() }) ln.log("handshake:send:dump", func() string { return p.Dump() })
@ -576,13 +670,13 @@ func (ln *listener) handleHandshake(p packet.Packet) {
} }
// If the peer has a smaller MTU size, adjust to it // If the peer has a smaller MTU size, adjust to it
if cif.MaxTransmissionUnitSize < ln.config.MSS { if cif.MaxTransmissionUnitSize < config.MSS {
ln.config.MSS = cif.MaxTransmissionUnitSize config.MSS = cif.MaxTransmissionUnitSize
ln.config.PayloadSize = ln.config.MSS - SRT_HEADER_SIZE - UDP_HEADER_SIZE config.PayloadSize = config.MSS - SRT_HEADER_SIZE - UDP_HEADER_SIZE
if ln.config.PayloadSize < MIN_PAYLOAD_SIZE { if config.PayloadSize < MIN_PAYLOAD_SIZE {
cif.HandshakeType = packet.REJ_ROGUE cif.HandshakeType = packet.HandshakeType(REJ_ROGUE)
ln.log("handshake:recv:error", func() string { return fmt.Sprintf("payload size is too small (%d bytes)", ln.config.PayloadSize) }) ln.log("handshake:recv:error", func() string { return fmt.Sprintf("payload size is too small (%d bytes)", config.PayloadSize) })
p.MarshalCIF(cif) p.MarshalCIF(cif)
ln.log("handshake:send:dump", func() string { return p.Dump() }) ln.log("handshake:send:dump", func() string { return p.Dump() })
ln.log("handshake:send:cif", func() string { return cif.String() }) ln.log("handshake:send:cif", func() string { return cif.String() })
@ -594,7 +688,7 @@ func (ln *listener) handleHandshake(p packet.Packet) {
if cif.Version == 4 { if cif.Version == 4 {
// Check if the type (encryption field + extension field) has the value 2 // Check if the type (encryption field + extension field) has the value 2
if cif.EncryptionField != 0 || cif.ExtensionField != 2 { if cif.EncryptionField != 0 || cif.ExtensionField != 2 {
cif.HandshakeType = packet.REJ_ROGUE cif.HandshakeType = packet.HandshakeType(REJ_ROGUE)
ln.log("handshake:recv:error", func() string { return "invalid type, expecting a value of 2 (UDT_DGRAM)" }) ln.log("handshake:recv:error", func() string { return "invalid type, expecting a value of 2 (UDT_DGRAM)" })
p.MarshalCIF(cif) p.MarshalCIF(cif)
ln.log("handshake:send:dump", func() string { return p.Dump() }) ln.log("handshake:send:dump", func() string { return p.Dump() })
@ -605,10 +699,10 @@ func (ln *listener) handleHandshake(p packet.Packet) {
} }
} else if cif.Version == 5 { } else if cif.Version == 5 {
// Check if the peer version is sufficient // Check if the peer version is sufficient
if cif.SRTHS.SRTVersion < ln.config.MinVersion { if cif.SRTHS.SRTVersion < config.MinVersion {
cif.HandshakeType = packet.REJ_VERSION cif.HandshakeType = packet.HandshakeType(REJ_VERSION)
ln.log("handshake:recv:error", func() string { ln.log("handshake:recv:error", func() string {
return fmt.Sprintf("peer version insufficient (%#06x), expecting at least %#06x", cif.SRTHS.SRTVersion, ln.config.MinVersion) return fmt.Sprintf("peer version insufficient (%#06x), expecting at least %#06x", cif.SRTHS.SRTVersion, config.MinVersion)
}) })
p.MarshalCIF(cif) p.MarshalCIF(cif)
ln.log("handshake:send:dump", func() string { return p.Dump() }) ln.log("handshake:send:dump", func() string { return p.Dump() })
@ -620,7 +714,7 @@ func (ln *listener) handleHandshake(p packet.Packet) {
// Check the required SRT flags // Check the required SRT flags
if !cif.SRTHS.SRTFlags.TSBPDSND || !cif.SRTHS.SRTFlags.TSBPDRCV || !cif.SRTHS.SRTFlags.TLPKTDROP || !cif.SRTHS.SRTFlags.PERIODICNAK || !cif.SRTHS.SRTFlags.REXMITFLG { if !cif.SRTHS.SRTFlags.TSBPDSND || !cif.SRTHS.SRTFlags.TSBPDRCV || !cif.SRTHS.SRTFlags.TLPKTDROP || !cif.SRTHS.SRTFlags.PERIODICNAK || !cif.SRTHS.SRTFlags.REXMITFLG {
cif.HandshakeType = packet.REJ_ROGUE cif.HandshakeType = packet.HandshakeType(REJ_ROGUE)
ln.log("handshake:recv:error", func() string { return "not all required flags are set" }) ln.log("handshake:recv:error", func() string { return "not all required flags are set" })
p.MarshalCIF(cif) p.MarshalCIF(cif)
ln.log("handshake:send:dump", func() string { return p.Dump() }) ln.log("handshake:send:dump", func() string { return p.Dump() })
@ -632,7 +726,7 @@ func (ln *listener) handleHandshake(p packet.Packet) {
// We only support live streaming // We only support live streaming
if cif.SRTHS.SRTFlags.STREAM { if cif.SRTHS.SRTFlags.STREAM {
cif.HandshakeType = packet.REJ_MESSAGEAPI cif.HandshakeType = packet.HandshakeType(REJ_MESSAGEAPI)
ln.log("handshake:recv:error", func() string { return "only live streaming is supported" }) ln.log("handshake:recv:error", func() string { return "only live streaming is supported" })
p.MarshalCIF(cif) p.MarshalCIF(cif)
ln.log("handshake:send:dump", func() string { return p.Dump() }) ln.log("handshake:send:dump", func() string { return p.Dump() })
@ -642,7 +736,7 @@ func (ln *listener) handleHandshake(p packet.Packet) {
return return
} }
} else { } else {
cif.HandshakeType = packet.REJ_ROGUE cif.HandshakeType = packet.HandshakeType(REJ_ROGUE)
ln.log("handshake:recv:error", func() string { return fmt.Sprintf("only HSv4 and HSv5 are supported (got HSv%d)", cif.Version) }) ln.log("handshake:recv:error", func() string { return fmt.Sprintf("only HSv4 and HSv5 are supported (got HSv%d)", cif.Version) })
p.MarshalCIF(cif) p.MarshalCIF(cif)
ln.log("handshake:send:dump", func() string { return p.Dump() }) ln.log("handshake:send:dump", func() string { return p.Dump() })
@ -659,6 +753,7 @@ func (ln *listener) handleHandshake(p packet.Packet) {
start: time.Now(), start: time.Now(),
socketId: cif.SRTSocketId, socketId: cif.SRTSocketId,
timestamp: p.Header().Timestamp, timestamp: p.Header().Timestamp,
config: config,
handshake: cif, handshake: cif,
} }
@ -666,7 +761,7 @@ func (ln *listener) handleHandshake(p packet.Packet) {
if cif.SRTKM != nil { if cif.SRTKM != nil {
cr, err := crypto.New(int(cif.SRTKM.KLen)) cr, err := crypto.New(int(cif.SRTKM.KLen))
if err != nil { if err != nil {
cif.HandshakeType = packet.REJ_ROGUE cif.HandshakeType = packet.HandshakeType(REJ_ROGUE)
ln.log("handshake:recv:error", func() string { return fmt.Sprintf("crypto: %s", err) }) ln.log("handshake:recv:error", func() string { return fmt.Sprintf("crypto: %s", err) })
p.MarshalCIF(cif) p.MarshalCIF(cif)
ln.log("handshake:send:dump", func() string { return p.Dump() }) ln.log("handshake:send:dump", func() string { return p.Dump() })
@ -683,7 +778,7 @@ func (ln *listener) handleHandshake(p packet.Packet) {
select { select {
case ln.backlog <- c: case ln.backlog <- c:
default: default:
cif.HandshakeType = packet.REJ_BACKLOG cif.HandshakeType = packet.HandshakeType(REJ_BACKLOG)
ln.log("handshake:recv:error", func() string { return "backlog is full" }) ln.log("handshake:recv:error", func() string { return "backlog is full" })
p.MarshalCIF(cif) p.MarshalCIF(cif)
ln.log("handshake:send:dump", func() string { return p.Dump() }) ln.log("handshake:send:dump", func() string { return p.Dump() })
@ -700,5 +795,9 @@ func (ln *listener) handleHandshake(p packet.Packet) {
} }
func (ln *listener) log(topic string, message func() string) { func (ln *listener) log(topic string, message func() string) {
if ln.config.Logger == nil {
return
}
ln.config.Logger.Print(topic, 0, 2, message) ln.config.Logger.Print(topic, 0, 2, message)
} }

File diff suppressed because it is too large Load Diff

52
vendor/github.com/go-openapi/swag/BENCHMARK.md generated vendored Normal file
View File

@ -0,0 +1,52 @@
# Benchmarks
## Name mangling utilities
```bash
go test -bench XXX -run XXX -benchtime 30s
```
### Benchmarks at b3e7a5386f996177e4808f11acb2aa93a0f660df
```
goos: linux
goarch: amd64
pkg: github.com/go-openapi/swag
cpu: Intel(R) Core(TM) i5-6200U CPU @ 2.30GHz
BenchmarkToXXXName/ToGoName-4 862623 44101 ns/op 10450 B/op 732 allocs/op
BenchmarkToXXXName/ToVarName-4 853656 40728 ns/op 10468 B/op 734 allocs/op
BenchmarkToXXXName/ToFileName-4 1268312 27813 ns/op 9785 B/op 617 allocs/op
BenchmarkToXXXName/ToCommandName-4 1276322 27903 ns/op 9785 B/op 617 allocs/op
BenchmarkToXXXName/ToHumanNameLower-4 895334 40354 ns/op 10472 B/op 731 allocs/op
BenchmarkToXXXName/ToHumanNameTitle-4 882441 40678 ns/op 10566 B/op 749 allocs/op
```
### Benchmarks after PR #79
~ x10 performance improvement and ~ /100 memory allocations.
```
goos: linux
goarch: amd64
pkg: github.com/go-openapi/swag
cpu: Intel(R) Core(TM) i5-6200U CPU @ 2.30GHz
BenchmarkToXXXName/ToGoName-4 9595830 3991 ns/op 42 B/op 5 allocs/op
BenchmarkToXXXName/ToVarName-4 9194276 3984 ns/op 62 B/op 7 allocs/op
BenchmarkToXXXName/ToFileName-4 17002711 2123 ns/op 147 B/op 7 allocs/op
BenchmarkToXXXName/ToCommandName-4 16772926 2111 ns/op 147 B/op 7 allocs/op
BenchmarkToXXXName/ToHumanNameLower-4 9788331 3749 ns/op 92 B/op 6 allocs/op
BenchmarkToXXXName/ToHumanNameTitle-4 9188260 3941 ns/op 104 B/op 6 allocs/op
```
```
goos: linux
goarch: amd64
pkg: github.com/go-openapi/swag
cpu: AMD Ryzen 7 5800X 8-Core Processor
BenchmarkToXXXName/ToGoName-16 18527378 1972 ns/op 42 B/op 5 allocs/op
BenchmarkToXXXName/ToVarName-16 15552692 2093 ns/op 62 B/op 7 allocs/op
BenchmarkToXXXName/ToFileName-16 32161176 1117 ns/op 147 B/op 7 allocs/op
BenchmarkToXXXName/ToCommandName-16 32256634 1137 ns/op 147 B/op 7 allocs/op
BenchmarkToXXXName/ToHumanNameLower-16 18599661 1946 ns/op 92 B/op 6 allocs/op
BenchmarkToXXXName/ToHumanNameTitle-16 17581353 2054 ns/op 105 B/op 6 allocs/op
```

View File

@ -16,9 +16,130 @@ package swag
import ( import (
"sort" "sort"
"strings"
"sync" "sync"
) )
var (
// commonInitialisms are common acronyms that are kept as whole uppercased words.
commonInitialisms *indexOfInitialisms
// initialisms is a slice of sorted initialisms
initialisms []string
// a copy of initialisms pre-baked as []rune
initialismsRunes [][]rune
initialismsUpperCased [][]rune
isInitialism func(string) bool
maxAllocMatches int
)
func init() {
// Taken from https://github.com/golang/lint/blob/3390df4df2787994aea98de825b964ac7944b817/lint.go#L732-L769
configuredInitialisms := map[string]bool{
"ACL": true,
"API": true,
"ASCII": true,
"CPU": true,
"CSS": true,
"DNS": true,
"EOF": true,
"GUID": true,
"HTML": true,
"HTTPS": true,
"HTTP": true,
"ID": true,
"IP": true,
"IPv4": true,
"IPv6": true,
"JSON": true,
"LHS": true,
"OAI": true,
"QPS": true,
"RAM": true,
"RHS": true,
"RPC": true,
"SLA": true,
"SMTP": true,
"SQL": true,
"SSH": true,
"TCP": true,
"TLS": true,
"TTL": true,
"UDP": true,
"UI": true,
"UID": true,
"UUID": true,
"URI": true,
"URL": true,
"UTF8": true,
"VM": true,
"XML": true,
"XMPP": true,
"XSRF": true,
"XSS": true,
}
// a thread-safe index of initialisms
commonInitialisms = newIndexOfInitialisms().load(configuredInitialisms)
initialisms = commonInitialisms.sorted()
initialismsRunes = asRunes(initialisms)
initialismsUpperCased = asUpperCased(initialisms)
maxAllocMatches = maxAllocHeuristic(initialismsRunes)
// a test function
isInitialism = commonInitialisms.isInitialism
}
func asRunes(in []string) [][]rune {
out := make([][]rune, len(in))
for i, initialism := range in {
out[i] = []rune(initialism)
}
return out
}
func asUpperCased(in []string) [][]rune {
out := make([][]rune, len(in))
for i, initialism := range in {
out[i] = []rune(upper(trim(initialism)))
}
return out
}
func maxAllocHeuristic(in [][]rune) int {
heuristic := make(map[rune]int)
for _, initialism := range in {
heuristic[initialism[0]]++
}
var maxAlloc int
for _, val := range heuristic {
if val > maxAlloc {
maxAlloc = val
}
}
return maxAlloc
}
// AddInitialisms add additional initialisms
func AddInitialisms(words ...string) {
for _, word := range words {
// commonInitialisms[upper(word)] = true
commonInitialisms.add(upper(word))
}
// sort again
initialisms = commonInitialisms.sorted()
initialismsRunes = asRunes(initialisms)
initialismsUpperCased = asUpperCased(initialisms)
}
// indexOfInitialisms is a thread-safe implementation of the sorted index of initialisms. // indexOfInitialisms is a thread-safe implementation of the sorted index of initialisms.
// Since go1.9, this may be implemented with sync.Map. // Since go1.9, this may be implemented with sync.Map.
type indexOfInitialisms struct { type indexOfInitialisms struct {
@ -63,3 +184,19 @@ func (m *indexOfInitialisms) sorted() (result []string) {
sort.Sort(sort.Reverse(byInitialism(result))) sort.Sort(sort.Reverse(byInitialism(result)))
return return
} }
type byInitialism []string
func (s byInitialism) Len() int {
return len(s)
}
func (s byInitialism) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
func (s byInitialism) Less(i, j int) bool {
if len(s[i]) != len(s[j]) {
return len(s[i]) < len(s[j])
}
return strings.Compare(s[i], s[j]) > 0
}

View File

@ -14,74 +14,80 @@
package swag package swag
import "unicode" import (
"unicode"
"unicode/utf8"
)
type ( type (
nameLexem interface { lexemKind uint8
GetUnsafeGoName() string
GetOriginal() string
IsInitialism() bool
}
initialismNameLexem struct { nameLexem struct {
original string original string
matchedInitialism string matchedInitialism string
} kind lexemKind
casualNameLexem struct {
original string
} }
) )
func newInitialismNameLexem(original, matchedInitialism string) *initialismNameLexem { const (
return &initialismNameLexem{ lexemKindCasualName lexemKind = iota
lexemKindInitialismName
)
func newInitialismNameLexem(original, matchedInitialism string) nameLexem {
return nameLexem{
kind: lexemKindInitialismName,
original: original, original: original,
matchedInitialism: matchedInitialism, matchedInitialism: matchedInitialism,
} }
} }
func newCasualNameLexem(original string) *casualNameLexem { func newCasualNameLexem(original string) nameLexem {
return &casualNameLexem{ return nameLexem{
kind: lexemKindCasualName,
original: original, original: original,
} }
} }
func (l *initialismNameLexem) GetUnsafeGoName() string { func (l nameLexem) GetUnsafeGoName() string {
return l.matchedInitialism if l.kind == lexemKindInitialismName {
} return l.matchedInitialism
}
var (
first rune
rest string
)
func (l *casualNameLexem) GetUnsafeGoName() string {
var first rune
var rest string
for i, orig := range l.original { for i, orig := range l.original {
if i == 0 { if i == 0 {
first = orig first = orig
continue continue
} }
if i > 0 { if i > 0 {
rest = l.original[i:] rest = l.original[i:]
break break
} }
} }
if len(l.original) > 1 { if len(l.original) > 1 {
return string(unicode.ToUpper(first)) + lower(rest) b := poolOfBuffers.BorrowBuffer(utf8.UTFMax + len(rest))
defer func() {
poolOfBuffers.RedeemBuffer(b)
}()
b.WriteRune(unicode.ToUpper(first))
b.WriteString(lower(rest))
return b.String()
} }
return l.original return l.original
} }
func (l *initialismNameLexem) GetOriginal() string { func (l nameLexem) GetOriginal() string {
return l.original return l.original
} }
func (l *casualNameLexem) GetOriginal() string { func (l nameLexem) IsInitialism() bool {
return l.original return l.kind == lexemKindInitialismName
}
func (l *initialismNameLexem) IsInitialism() bool {
return true
}
func (l *casualNameLexem) IsInitialism() bool {
return false
} }

File diff suppressed because it is too large Load Diff

22
vendor/github.com/go-openapi/swag/string_bytes.go generated vendored Normal file
View File

@ -0,0 +1,22 @@
package swag
import "unsafe"
type internalString struct {
Data unsafe.Pointer
Len int
}
// hackStringBytes returns the (unsafe) underlying bytes slice of a string.
func hackStringBytes(str string) []byte {
p := (*internalString)(unsafe.Pointer(&str)).Data
return unsafe.Slice((*byte)(p), len(str))
}
/*
* go1.20 version (for when go mod moves to a go1.20 requirement):
func hackStringBytes(str string) []byte {
return unsafe.Slice(unsafe.StringData(str), len(str))
}
*/

View File

@ -18,76 +18,25 @@ import (
"reflect" "reflect"
"strings" "strings"
"unicode" "unicode"
"unicode/utf8"
) )
// commonInitialisms are common acronyms that are kept as whole uppercased words.
var commonInitialisms *indexOfInitialisms
// initialisms is a slice of sorted initialisms
var initialisms []string
var isInitialism func(string) bool
// GoNamePrefixFunc sets an optional rule to prefix go names // GoNamePrefixFunc sets an optional rule to prefix go names
// which do not start with a letter. // which do not start with a letter.
// //
// The prefix function is assumed to return a string that starts with an upper case letter.
//
// e.g. to help convert "123" into "{prefix}123" // e.g. to help convert "123" into "{prefix}123"
// //
// The default is to prefix with "X" // The default is to prefix with "X"
var GoNamePrefixFunc func(string) string var GoNamePrefixFunc func(string) string
func init() { func prefixFunc(name, in string) string {
// Taken from https://github.com/golang/lint/blob/3390df4df2787994aea98de825b964ac7944b817/lint.go#L732-L769 if GoNamePrefixFunc == nil {
var configuredInitialisms = map[string]bool{ return "X" + in
"ACL": true,
"API": true,
"ASCII": true,
"CPU": true,
"CSS": true,
"DNS": true,
"EOF": true,
"GUID": true,
"HTML": true,
"HTTPS": true,
"HTTP": true,
"ID": true,
"IP": true,
"IPv4": true,
"IPv6": true,
"JSON": true,
"LHS": true,
"OAI": true,
"QPS": true,
"RAM": true,
"RHS": true,
"RPC": true,
"SLA": true,
"SMTP": true,
"SQL": true,
"SSH": true,
"TCP": true,
"TLS": true,
"TTL": true,
"UDP": true,
"UI": true,
"UID": true,
"UUID": true,
"URI": true,
"URL": true,
"UTF8": true,
"VM": true,
"XML": true,
"XMPP": true,
"XSRF": true,
"XSS": true,
} }
// a thread-safe index of initialisms return GoNamePrefixFunc(name) + in
commonInitialisms = newIndexOfInitialisms().load(configuredInitialisms)
initialisms = commonInitialisms.sorted()
// a test function
isInitialism = commonInitialisms.isInitialism
} }
const ( const (
@ -156,22 +105,6 @@ func SplitByFormat(data, format string) []string {
return result return result
} }
type byInitialism []string
func (s byInitialism) Len() int {
return len(s)
}
func (s byInitialism) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
func (s byInitialism) Less(i, j int) bool {
if len(s[i]) != len(s[j]) {
return len(s[i]) < len(s[j])
}
return strings.Compare(s[i], s[j]) > 0
}
// Removes leading whitespaces // Removes leading whitespaces
func trim(str string) string { func trim(str string) string {
return strings.TrimSpace(str) return strings.TrimSpace(str)
@ -188,15 +121,20 @@ func lower(str string) string {
} }
// Camelize an uppercased word // Camelize an uppercased word
func Camelize(word string) (camelized string) { func Camelize(word string) string {
camelized := poolOfBuffers.BorrowBuffer(len(word))
defer func() {
poolOfBuffers.RedeemBuffer(camelized)
}()
for pos, ru := range []rune(word) { for pos, ru := range []rune(word) {
if pos > 0 { if pos > 0 {
camelized += string(unicode.ToLower(ru)) camelized.WriteRune(unicode.ToLower(ru))
} else { } else {
camelized += string(unicode.ToUpper(ru)) camelized.WriteRune(unicode.ToUpper(ru))
} }
} }
return return camelized.String()
} }
// ToFileName lowercases and underscores a go type name // ToFileName lowercases and underscores a go type name
@ -224,26 +162,31 @@ func ToCommandName(name string) string {
// ToHumanNameLower represents a code name as a human series of words // ToHumanNameLower represents a code name as a human series of words
func ToHumanNameLower(name string) string { func ToHumanNameLower(name string) string {
in := newSplitter(withPostSplitInitialismCheck).split(name) s := poolOfSplitters.BorrowSplitter(withPostSplitInitialismCheck)
out := make([]string, 0, len(in)) in := s.split(name)
poolOfSplitters.RedeemSplitter(s)
out := make([]string, 0, len(*in))
for _, w := range in { for _, w := range *in {
if !w.IsInitialism() { if !w.IsInitialism() {
out = append(out, lower(w.GetOriginal())) out = append(out, lower(w.GetOriginal()))
} else { } else {
out = append(out, trim(w.GetOriginal())) out = append(out, trim(w.GetOriginal()))
} }
} }
poolOfLexems.RedeemLexems(in)
return strings.Join(out, " ") return strings.Join(out, " ")
} }
// ToHumanNameTitle represents a code name as a human series of words with the first letters titleized // ToHumanNameTitle represents a code name as a human series of words with the first letters titleized
func ToHumanNameTitle(name string) string { func ToHumanNameTitle(name string) string {
in := newSplitter(withPostSplitInitialismCheck).split(name) s := poolOfSplitters.BorrowSplitter(withPostSplitInitialismCheck)
in := s.split(name)
poolOfSplitters.RedeemSplitter(s)
out := make([]string, 0, len(in)) out := make([]string, 0, len(*in))
for _, w := range in { for _, w := range *in {
original := trim(w.GetOriginal()) original := trim(w.GetOriginal())
if !w.IsInitialism() { if !w.IsInitialism() {
out = append(out, Camelize(original)) out = append(out, Camelize(original))
@ -251,6 +194,8 @@ func ToHumanNameTitle(name string) string {
out = append(out, original) out = append(out, original)
} }
} }
poolOfLexems.RedeemLexems(in)
return strings.Join(out, " ") return strings.Join(out, " ")
} }
@ -283,35 +228,70 @@ func ToVarName(name string) string {
// ToGoName translates a swagger name which can be underscored or camel cased to a name that golint likes // ToGoName translates a swagger name which can be underscored or camel cased to a name that golint likes
func ToGoName(name string) string { func ToGoName(name string) string {
lexems := newSplitter(withPostSplitInitialismCheck).split(name) s := poolOfSplitters.BorrowSplitter(withPostSplitInitialismCheck)
lexems := s.split(name)
poolOfSplitters.RedeemSplitter(s)
defer func() {
poolOfLexems.RedeemLexems(lexems)
}()
lexemes := *lexems
result := "" if len(lexemes) == 0 {
for _, lexem := range lexems { return ""
}
result := poolOfBuffers.BorrowBuffer(len(name))
defer func() {
poolOfBuffers.RedeemBuffer(result)
}()
// check if not starting with a letter, upper case
firstPart := lexemes[0].GetUnsafeGoName()
if lexemes[0].IsInitialism() {
firstPart = upper(firstPart)
}
if c := firstPart[0]; c < utf8.RuneSelf {
// ASCII
switch {
case 'A' <= c && c <= 'Z':
result.WriteString(firstPart)
case 'a' <= c && c <= 'z':
result.WriteByte(c - 'a' + 'A')
result.WriteString(firstPart[1:])
default:
result.WriteString(prefixFunc(name, firstPart))
// NOTE: no longer check if prefixFunc returns a string that starts with uppercase:
// assume this is always the case
}
} else {
// unicode
firstRune, _ := utf8.DecodeRuneInString(firstPart)
switch {
case !unicode.IsLetter(firstRune):
result.WriteString(prefixFunc(name, firstPart))
case !unicode.IsUpper(firstRune):
result.WriteString(prefixFunc(name, firstPart))
/*
result.WriteRune(unicode.ToUpper(firstRune))
result.WriteString(firstPart[offset:])
*/
default:
result.WriteString(firstPart)
}
}
for _, lexem := range lexemes[1:] {
goName := lexem.GetUnsafeGoName() goName := lexem.GetUnsafeGoName()
// to support old behavior // to support old behavior
if lexem.IsInitialism() { if lexem.IsInitialism() {
goName = upper(goName) goName = upper(goName)
} }
result += goName result.WriteString(goName)
} }
if len(result) > 0 { return result.String()
// Only prefix with X when the first character isn't an ascii letter
first := []rune(result)[0]
if !unicode.IsLetter(first) || (first > unicode.MaxASCII && !unicode.IsUpper(first)) {
if GoNamePrefixFunc == nil {
return "X" + result
}
result = GoNamePrefixFunc(name) + result
}
first = []rune(result)[0]
if unicode.IsLetter(first) && !unicode.IsUpper(first) {
result = string(append([]rune{unicode.ToUpper(first)}, []rune(result)[1:]...))
}
}
return result
} }
// ContainsStrings searches a slice of strings for a case-sensitive match // ContainsStrings searches a slice of strings for a case-sensitive match
@ -376,16 +356,6 @@ func IsZero(data interface{}) bool {
} }
} }
// AddInitialisms add additional initialisms
func AddInitialisms(words ...string) {
for _, word := range words {
// commonInitialisms[upper(word)] = true
commonInitialisms.add(upper(word))
}
// sort again
initialisms = commonInitialisms.sorted()
}
// CommandLineOptionsGroup represents a group of user-defined command line options // CommandLineOptionsGroup represents a group of user-defined command line options
type CommandLineOptionsGroup struct { type CommandLineOptionsGroup struct {
ShortDescription string ShortDescription string

View File

@ -1,4 +1,4 @@
GOCMD=GO111MODULE=on go GOCMD=go
linters-install: linters-install:
@golangci-lint --version >/dev/null 2>&1 || { \ @golangci-lint --version >/dev/null 2>&1 || { \

View File

@ -1,7 +1,7 @@
Package validator Package validator
================= =================
<img align="right" src="logo.png">[![Join the chat at https://gitter.im/go-playground/validator](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/go-playground/validator?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) <img align="right" src="logo.png">[![Join the chat at https://gitter.im/go-playground/validator](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/go-playground/validator?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
![Project status](https://img.shields.io/badge/version-10.16.0-green.svg) ![Project status](https://img.shields.io/badge/version-10.18.0-green.svg)
[![Build Status](https://travis-ci.org/go-playground/validator.svg?branch=master)](https://travis-ci.org/go-playground/validator) [![Build Status](https://travis-ci.org/go-playground/validator.svg?branch=master)](https://travis-ci.org/go-playground/validator)
[![Coverage Status](https://coveralls.io/repos/go-playground/validator/badge.svg?branch=master&service=github)](https://coveralls.io/github/go-playground/validator?branch=master) [![Coverage Status](https://coveralls.io/repos/go-playground/validator/badge.svg?branch=master&service=github)](https://coveralls.io/github/go-playground/validator?branch=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/go-playground/validator)](https://goreportcard.com/report/github.com/go-playground/validator) [![Go Report Card](https://goreportcard.com/badge/github.com/go-playground/validator)](https://goreportcard.com/report/github.com/go-playground/validator)

View File

@ -257,15 +257,19 @@ func (fe *fieldError) Error() string {
// NOTE: if no registered translation can be found, it returns the original // NOTE: if no registered translation can be found, it returns the original
// untranslated error message. // untranslated error message.
func (fe *fieldError) Translate(ut ut.Translator) string { func (fe *fieldError) Translate(ut ut.Translator) string {
var fn TranslationFunc
m, ok := fe.v.transTagFunc[ut] m, ok := fe.v.transTagFunc[ut]
if !ok { if !ok {
return fe.Error() return fe.Error()
} }
fn, ok := m[fe.tag] fn, ok = m[fe.tag]
if !ok { if !ok {
return fe.Error() fn, ok = m[fe.actualTag]
if !ok {
return fe.Error()
}
} }
return fn(ut, fe) return fn(ut, fe)

View File

@ -1,5 +1,18 @@
# Changelog # Changelog
## [1.6.0](https://github.com/google/uuid/compare/v1.5.0...v1.6.0) (2024-01-16)
### Features
* add Max UUID constant ([#149](https://github.com/google/uuid/issues/149)) ([c58770e](https://github.com/google/uuid/commit/c58770eb495f55fe2ced6284f93c5158a62e53e3))
### Bug Fixes
* fix typo in version 7 uuid documentation ([#153](https://github.com/google/uuid/issues/153)) ([016b199](https://github.com/google/uuid/commit/016b199544692f745ffc8867b914129ecb47ef06))
* Monotonicity in UUIDv7 ([#150](https://github.com/google/uuid/issues/150)) ([a2b2b32](https://github.com/google/uuid/commit/a2b2b32373ff0b1a312b7fdf6d38a977099698a6))
## [1.5.0](https://github.com/google/uuid/compare/v1.4.0...v1.5.0) (2023-12-12) ## [1.5.0](https://github.com/google/uuid/compare/v1.4.0...v1.5.0) (2023-12-12)

View File

@ -17,6 +17,12 @@ var (
NameSpaceOID = Must(Parse("6ba7b812-9dad-11d1-80b4-00c04fd430c8")) NameSpaceOID = Must(Parse("6ba7b812-9dad-11d1-80b4-00c04fd430c8"))
NameSpaceX500 = Must(Parse("6ba7b814-9dad-11d1-80b4-00c04fd430c8")) NameSpaceX500 = Must(Parse("6ba7b814-9dad-11d1-80b4-00c04fd430c8"))
Nil UUID // empty UUID, all zeros Nil UUID // empty UUID, all zeros
// The Max UUID is special form of UUID that is specified to have all 128 bits set to 1.
Max = UUID{
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
}
) )
// NewHash returns a new UUID derived from the hash of space concatenated with // NewHash returns a new UUID derived from the hash of space concatenated with

View File

@ -44,7 +44,7 @@ func NewV7FromReader(r io.Reader) (UUID, error) {
// makeV7 fill 48 bits time (uuid[0] - uuid[5]), set version b0111 (uuid[6]) // makeV7 fill 48 bits time (uuid[0] - uuid[5]), set version b0111 (uuid[6])
// uuid[8] already has the right version number (Variant is 10) // uuid[8] already has the right version number (Variant is 10)
// see function NewV7 and NewV7FromReader // see function NewV7 and NewV7FromReader
func makeV7(uuid []byte) { func makeV7(uuid []byte) {
/* /*
0 1 2 3 0 1 2 3
@ -52,7 +52,7 @@ func makeV7(uuid []byte) {
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| unix_ts_ms | | unix_ts_ms |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| unix_ts_ms | ver | rand_a | | unix_ts_ms | ver | rand_a (12 bit seq) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|var| rand_b | |var| rand_b |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@ -61,7 +61,7 @@ func makeV7(uuid []byte) {
*/ */
_ = uuid[15] // bounds check _ = uuid[15] // bounds check
t := timeNow().UnixMilli() t, s := getV7Time()
uuid[0] = byte(t >> 40) uuid[0] = byte(t >> 40)
uuid[1] = byte(t >> 32) uuid[1] = byte(t >> 32)
@ -70,6 +70,35 @@ func makeV7(uuid []byte) {
uuid[4] = byte(t >> 8) uuid[4] = byte(t >> 8)
uuid[5] = byte(t) uuid[5] = byte(t)
uuid[6] = 0x70 | (uuid[6] & 0x0F) uuid[6] = 0x70 | (0x0F & byte(s>>8))
// uuid[8] has already has right version uuid[7] = byte(s)
}
// lastV7time is the last time we returned stored as:
//
// 52 bits of time in milliseconds since epoch
// 12 bits of (fractional nanoseconds) >> 8
var lastV7time int64
const nanoPerMilli = 1000000
// getV7Time returns the time in milliseconds and nanoseconds / 256.
// The returned (milli << 12 + seq) is guarenteed to be greater than
// (milli << 12 + seq) returned by any previous call to getV7Time.
func getV7Time() (milli, seq int64) {
timeMu.Lock()
defer timeMu.Unlock()
nano := timeNow().UnixNano()
milli = nano / nanoPerMilli
// Sequence number is between 0 and 3906 (nanoPerMilli>>8)
seq = (nano - milli*nanoPerMilli) >> 8
now := milli<<12 + seq
if now <= lastV7time {
now = lastV7time + 1
milli = now >> 12
seq = now & 0xfff
}
lastV7time = now
return milli, seq
} }

View File

@ -0,0 +1,13 @@
// Copyright 2015 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 !race
package race
func ReadSlice[T any](s []T) {
}
func WriteSlice[T any](s []T) {
}

View File

@ -0,0 +1,26 @@
// Copyright 2015 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 race
package race
import (
"runtime"
"unsafe"
)
func ReadSlice[T any](s []T) {
if len(s) == 0 {
return
}
runtime.RaceReadRange(unsafe.Pointer(&s[0]), len(s)*int(unsafe.Sizeof(s[0])))
}
func WriteSlice[T any](s []T) {
if len(s) == 0 {
return
}
runtime.RaceWriteRange(unsafe.Pointer(&s[0]), len(s)*int(unsafe.Sizeof(s[0])))
}

View File

@ -10,6 +10,8 @@ import (
"errors" "errors"
"fmt" "fmt"
"strconv" "strconv"
"github.com/klauspost/compress/internal/race"
) )
var ( var (
@ -63,6 +65,10 @@ func Decode(dst, src []byte) ([]byte, error) {
} else { } else {
dst = make([]byte, dLen) dst = make([]byte, dLen)
} }
race.WriteSlice(dst)
race.ReadSlice(src[s:])
if s2Decode(dst, src[s:]) != 0 { if s2Decode(dst, src[s:]) != 0 {
return nil, ErrCorrupt return nil, ErrCorrupt
} }

View File

@ -117,6 +117,12 @@ func encodeBlockGo(dst, src []byte) (d int) {
i-- i--
base-- base--
} }
// Bail if we exceed the maximum size.
if d+(base-nextEmit) > dstLimit {
return 0
}
d += emitLiteral(dst[d:], src[nextEmit:base]) d += emitLiteral(dst[d:], src[nextEmit:base])
// Extend forward // Extend forward
@ -152,7 +158,6 @@ func encodeBlockGo(dst, src []byte) (d int) {
if s >= sLimit { if s >= sLimit {
goto emitRemainder goto emitRemainder
} }
cv = load64(src, s) cv = load64(src, s)
continue continue
} }
@ -325,6 +330,11 @@ func encodeBlockSnappyGo(dst, src []byte) (d int) {
i-- i--
base-- base--
} }
// Bail if we exceed the maximum size.
if d+(base-nextEmit) > dstLimit {
return 0
}
d += emitLiteral(dst[d:], src[nextEmit:base]) d += emitLiteral(dst[d:], src[nextEmit:base])
// Extend forward // Extend forward
@ -532,6 +542,11 @@ searchDict:
i-- i--
base-- base--
} }
// Bail if we exceed the maximum size.
if d+(base-nextEmit) > dstLimit {
return 0
}
d += emitLiteral(dst[d:], src[nextEmit:base]) d += emitLiteral(dst[d:], src[nextEmit:base])
if debug && nextEmit != base { if debug && nextEmit != base {
fmt.Println("emitted ", base-nextEmit, "literals") fmt.Println("emitted ", base-nextEmit, "literals")
@ -880,6 +895,11 @@ searchDict:
i-- i--
base-- base--
} }
// Bail if we exceed the maximum size.
if d+(base-nextEmit) > dstLimit {
return 0
}
d += emitLiteral(dst[d:], src[nextEmit:base]) d += emitLiteral(dst[d:], src[nextEmit:base])
if debug && nextEmit != base { if debug && nextEmit != base {
fmt.Println("emitted ", base-nextEmit, "literals") fmt.Println("emitted ", base-nextEmit, "literals")

View File

@ -3,6 +3,8 @@
package s2 package s2
import "github.com/klauspost/compress/internal/race"
const hasAmd64Asm = true const hasAmd64Asm = true
// encodeBlock encodes a non-empty src to a guaranteed-large-enough dst. It // encodeBlock encodes a non-empty src to a guaranteed-large-enough dst. It
@ -14,6 +16,9 @@ const hasAmd64Asm = true
// len(dst) >= MaxEncodedLen(len(src)) && // len(dst) >= MaxEncodedLen(len(src)) &&
// minNonLiteralBlockSize <= len(src) && len(src) <= maxBlockSize // minNonLiteralBlockSize <= len(src) && len(src) <= maxBlockSize
func encodeBlock(dst, src []byte) (d int) { func encodeBlock(dst, src []byte) (d int) {
race.ReadSlice(src)
race.WriteSlice(dst)
const ( const (
// Use 12 bit table when less than... // Use 12 bit table when less than...
limit12B = 16 << 10 limit12B = 16 << 10
@ -50,6 +55,9 @@ func encodeBlock(dst, src []byte) (d int) {
// len(dst) >= MaxEncodedLen(len(src)) && // len(dst) >= MaxEncodedLen(len(src)) &&
// minNonLiteralBlockSize <= len(src) && len(src) <= maxBlockSize // minNonLiteralBlockSize <= len(src) && len(src) <= maxBlockSize
func encodeBlockBetter(dst, src []byte) (d int) { func encodeBlockBetter(dst, src []byte) (d int) {
race.ReadSlice(src)
race.WriteSlice(dst)
const ( const (
// Use 12 bit table when less than... // Use 12 bit table when less than...
limit12B = 16 << 10 limit12B = 16 << 10
@ -86,6 +94,9 @@ func encodeBlockBetter(dst, src []byte) (d int) {
// len(dst) >= MaxEncodedLen(len(src)) && // len(dst) >= MaxEncodedLen(len(src)) &&
// minNonLiteralBlockSize <= len(src) && len(src) <= maxBlockSize // minNonLiteralBlockSize <= len(src) && len(src) <= maxBlockSize
func encodeBlockSnappy(dst, src []byte) (d int) { func encodeBlockSnappy(dst, src []byte) (d int) {
race.ReadSlice(src)
race.WriteSlice(dst)
const ( const (
// Use 12 bit table when less than... // Use 12 bit table when less than...
limit12B = 16 << 10 limit12B = 16 << 10
@ -121,6 +132,9 @@ func encodeBlockSnappy(dst, src []byte) (d int) {
// len(dst) >= MaxEncodedLen(len(src)) && // len(dst) >= MaxEncodedLen(len(src)) &&
// minNonLiteralBlockSize <= len(src) && len(src) <= maxBlockSize // minNonLiteralBlockSize <= len(src) && len(src) <= maxBlockSize
func encodeBlockBetterSnappy(dst, src []byte) (d int) { func encodeBlockBetterSnappy(dst, src []byte) (d int) {
race.ReadSlice(src)
race.WriteSlice(dst)
const ( const (
// Use 12 bit table when less than... // Use 12 bit table when less than...
limit12B = 16 << 10 limit12B = 16 << 10

View File

@ -100,6 +100,15 @@ repeat_extend_back_loop_encodeBlockAsm:
JNZ repeat_extend_back_loop_encodeBlockAsm JNZ repeat_extend_back_loop_encodeBlockAsm
repeat_extend_back_end_encodeBlockAsm: repeat_extend_back_end_encodeBlockAsm:
MOVL SI, BX
SUBL 12(SP), BX
LEAQ 5(AX)(BX*1), BX
CMPQ BX, (SP)
JB repeat_dst_size_check_encodeBlockAsm
MOVQ $0x00000000, ret+48(FP)
RET
repeat_dst_size_check_encodeBlockAsm:
MOVL 12(SP), BX MOVL 12(SP), BX
CMPL BX, SI CMPL BX, SI
JEQ emit_literal_done_repeat_emit_encodeBlockAsm JEQ emit_literal_done_repeat_emit_encodeBlockAsm
@ -1513,6 +1522,15 @@ repeat_extend_back_loop_encodeBlockAsm4MB:
JNZ repeat_extend_back_loop_encodeBlockAsm4MB JNZ repeat_extend_back_loop_encodeBlockAsm4MB
repeat_extend_back_end_encodeBlockAsm4MB: repeat_extend_back_end_encodeBlockAsm4MB:
MOVL SI, BX
SUBL 12(SP), BX
LEAQ 4(AX)(BX*1), BX
CMPQ BX, (SP)
JB repeat_dst_size_check_encodeBlockAsm4MB
MOVQ $0x00000000, ret+48(FP)
RET
repeat_dst_size_check_encodeBlockAsm4MB:
MOVL 12(SP), BX MOVL 12(SP), BX
CMPL BX, SI CMPL BX, SI
JEQ emit_literal_done_repeat_emit_encodeBlockAsm4MB JEQ emit_literal_done_repeat_emit_encodeBlockAsm4MB
@ -2828,6 +2846,15 @@ repeat_extend_back_loop_encodeBlockAsm12B:
JNZ repeat_extend_back_loop_encodeBlockAsm12B JNZ repeat_extend_back_loop_encodeBlockAsm12B
repeat_extend_back_end_encodeBlockAsm12B: repeat_extend_back_end_encodeBlockAsm12B:
MOVL SI, BX
SUBL 12(SP), BX
LEAQ 3(AX)(BX*1), BX
CMPQ BX, (SP)
JB repeat_dst_size_check_encodeBlockAsm12B
MOVQ $0x00000000, ret+48(FP)
RET
repeat_dst_size_check_encodeBlockAsm12B:
MOVL 12(SP), BX MOVL 12(SP), BX
CMPL BX, SI CMPL BX, SI
JEQ emit_literal_done_repeat_emit_encodeBlockAsm12B JEQ emit_literal_done_repeat_emit_encodeBlockAsm12B
@ -3903,6 +3930,15 @@ repeat_extend_back_loop_encodeBlockAsm10B:
JNZ repeat_extend_back_loop_encodeBlockAsm10B JNZ repeat_extend_back_loop_encodeBlockAsm10B
repeat_extend_back_end_encodeBlockAsm10B: repeat_extend_back_end_encodeBlockAsm10B:
MOVL SI, BX
SUBL 12(SP), BX
LEAQ 3(AX)(BX*1), BX
CMPQ BX, (SP)
JB repeat_dst_size_check_encodeBlockAsm10B
MOVQ $0x00000000, ret+48(FP)
RET
repeat_dst_size_check_encodeBlockAsm10B:
MOVL 12(SP), BX MOVL 12(SP), BX
CMPL BX, SI CMPL BX, SI
JEQ emit_literal_done_repeat_emit_encodeBlockAsm10B JEQ emit_literal_done_repeat_emit_encodeBlockAsm10B
@ -4978,6 +5014,15 @@ repeat_extend_back_loop_encodeBlockAsm8B:
JNZ repeat_extend_back_loop_encodeBlockAsm8B JNZ repeat_extend_back_loop_encodeBlockAsm8B
repeat_extend_back_end_encodeBlockAsm8B: repeat_extend_back_end_encodeBlockAsm8B:
MOVL SI, BX
SUBL 12(SP), BX
LEAQ 3(AX)(BX*1), BX
CMPQ BX, (SP)
JB repeat_dst_size_check_encodeBlockAsm8B
MOVQ $0x00000000, ret+48(FP)
RET
repeat_dst_size_check_encodeBlockAsm8B:
MOVL 12(SP), BX MOVL 12(SP), BX
CMPL BX, SI CMPL BX, SI
JEQ emit_literal_done_repeat_emit_encodeBlockAsm8B JEQ emit_literal_done_repeat_emit_encodeBlockAsm8B
@ -10756,6 +10801,15 @@ repeat_extend_back_loop_encodeSnappyBlockAsm:
JNZ repeat_extend_back_loop_encodeSnappyBlockAsm JNZ repeat_extend_back_loop_encodeSnappyBlockAsm
repeat_extend_back_end_encodeSnappyBlockAsm: repeat_extend_back_end_encodeSnappyBlockAsm:
MOVL SI, BX
SUBL 12(SP), BX
LEAQ 5(AX)(BX*1), BX
CMPQ BX, (SP)
JB repeat_dst_size_check_encodeSnappyBlockAsm
MOVQ $0x00000000, ret+48(FP)
RET
repeat_dst_size_check_encodeSnappyBlockAsm:
MOVL 12(SP), BX MOVL 12(SP), BX
CMPL BX, SI CMPL BX, SI
JEQ emit_literal_done_repeat_emit_encodeSnappyBlockAsm JEQ emit_literal_done_repeat_emit_encodeSnappyBlockAsm
@ -11678,6 +11732,15 @@ repeat_extend_back_loop_encodeSnappyBlockAsm64K:
JNZ repeat_extend_back_loop_encodeSnappyBlockAsm64K JNZ repeat_extend_back_loop_encodeSnappyBlockAsm64K
repeat_extend_back_end_encodeSnappyBlockAsm64K: repeat_extend_back_end_encodeSnappyBlockAsm64K:
MOVL SI, BX
SUBL 12(SP), BX
LEAQ 3(AX)(BX*1), BX
CMPQ BX, (SP)
JB repeat_dst_size_check_encodeSnappyBlockAsm64K
MOVQ $0x00000000, ret+48(FP)
RET
repeat_dst_size_check_encodeSnappyBlockAsm64K:
MOVL 12(SP), BX MOVL 12(SP), BX
CMPL BX, SI CMPL BX, SI
JEQ emit_literal_done_repeat_emit_encodeSnappyBlockAsm64K JEQ emit_literal_done_repeat_emit_encodeSnappyBlockAsm64K
@ -12504,6 +12567,15 @@ repeat_extend_back_loop_encodeSnappyBlockAsm12B:
JNZ repeat_extend_back_loop_encodeSnappyBlockAsm12B JNZ repeat_extend_back_loop_encodeSnappyBlockAsm12B
repeat_extend_back_end_encodeSnappyBlockAsm12B: repeat_extend_back_end_encodeSnappyBlockAsm12B:
MOVL SI, BX
SUBL 12(SP), BX
LEAQ 3(AX)(BX*1), BX
CMPQ BX, (SP)
JB repeat_dst_size_check_encodeSnappyBlockAsm12B
MOVQ $0x00000000, ret+48(FP)
RET
repeat_dst_size_check_encodeSnappyBlockAsm12B:
MOVL 12(SP), BX MOVL 12(SP), BX
CMPL BX, SI CMPL BX, SI
JEQ emit_literal_done_repeat_emit_encodeSnappyBlockAsm12B JEQ emit_literal_done_repeat_emit_encodeSnappyBlockAsm12B
@ -13330,6 +13402,15 @@ repeat_extend_back_loop_encodeSnappyBlockAsm10B:
JNZ repeat_extend_back_loop_encodeSnappyBlockAsm10B JNZ repeat_extend_back_loop_encodeSnappyBlockAsm10B
repeat_extend_back_end_encodeSnappyBlockAsm10B: repeat_extend_back_end_encodeSnappyBlockAsm10B:
MOVL SI, BX
SUBL 12(SP), BX
LEAQ 3(AX)(BX*1), BX
CMPQ BX, (SP)
JB repeat_dst_size_check_encodeSnappyBlockAsm10B
MOVQ $0x00000000, ret+48(FP)
RET
repeat_dst_size_check_encodeSnappyBlockAsm10B:
MOVL 12(SP), BX MOVL 12(SP), BX
CMPL BX, SI CMPL BX, SI
JEQ emit_literal_done_repeat_emit_encodeSnappyBlockAsm10B JEQ emit_literal_done_repeat_emit_encodeSnappyBlockAsm10B
@ -14156,6 +14237,15 @@ repeat_extend_back_loop_encodeSnappyBlockAsm8B:
JNZ repeat_extend_back_loop_encodeSnappyBlockAsm8B JNZ repeat_extend_back_loop_encodeSnappyBlockAsm8B
repeat_extend_back_end_encodeSnappyBlockAsm8B: repeat_extend_back_end_encodeSnappyBlockAsm8B:
MOVL SI, BX
SUBL 12(SP), BX
LEAQ 3(AX)(BX*1), BX
CMPQ BX, (SP)
JB repeat_dst_size_check_encodeSnappyBlockAsm8B
MOVQ $0x00000000, ret+48(FP)
RET
repeat_dst_size_check_encodeSnappyBlockAsm8B:
MOVL 12(SP), BX MOVL 12(SP), BX
CMPL BX, SI CMPL BX, SI
JEQ emit_literal_done_repeat_emit_encodeSnappyBlockAsm8B JEQ emit_literal_done_repeat_emit_encodeSnappyBlockAsm8B
@ -17949,6 +18039,15 @@ repeat_extend_back_loop_calcBlockSize:
JNZ repeat_extend_back_loop_calcBlockSize JNZ repeat_extend_back_loop_calcBlockSize
repeat_extend_back_end_calcBlockSize: repeat_extend_back_end_calcBlockSize:
MOVL SI, BX
SUBL 12(SP), BX
LEAQ 5(AX)(BX*1), BX
CMPQ BX, (SP)
JB repeat_dst_size_check_calcBlockSize
MOVQ $0x00000000, ret+24(FP)
RET
repeat_dst_size_check_calcBlockSize:
MOVL 12(SP), BX MOVL 12(SP), BX
CMPL BX, SI CMPL BX, SI
JEQ emit_literal_done_repeat_emit_calcBlockSize JEQ emit_literal_done_repeat_emit_calcBlockSize
@ -18531,6 +18630,15 @@ repeat_extend_back_loop_calcBlockSizeSmall:
JNZ repeat_extend_back_loop_calcBlockSizeSmall JNZ repeat_extend_back_loop_calcBlockSizeSmall
repeat_extend_back_end_calcBlockSizeSmall: repeat_extend_back_end_calcBlockSizeSmall:
MOVL SI, BX
SUBL 12(SP), BX
LEAQ 3(AX)(BX*1), BX
CMPQ BX, (SP)
JB repeat_dst_size_check_calcBlockSizeSmall
MOVQ $0x00000000, ret+24(FP)
RET
repeat_dst_size_check_calcBlockSizeSmall:
MOVL 12(SP), BX MOVL 12(SP), BX
CMPL BX, SI CMPL BX, SI
JEQ emit_literal_done_repeat_emit_calcBlockSizeSmall JEQ emit_literal_done_repeat_emit_calcBlockSizeSmall

View File

@ -104,12 +104,14 @@ func ReaderIgnoreStreamIdentifier() ReaderOption {
// For each chunk with the ID, the callback is called with the content. // For each chunk with the ID, the callback is called with the content.
// Any returned non-nil error will abort decompression. // Any returned non-nil error will abort decompression.
// Only one callback per ID is supported, latest sent will be used. // Only one callback per ID is supported, latest sent will be used.
// You can peek the stream, triggering the callback, by doing a Read with a 0
// byte buffer.
func ReaderSkippableCB(id uint8, fn func(r io.Reader) error) ReaderOption { func ReaderSkippableCB(id uint8, fn func(r io.Reader) error) ReaderOption {
return func(r *Reader) error { return func(r *Reader) error {
if id < 0x80 || id > 0xfd { if id < 0x80 || id > 0xfd {
return fmt.Errorf("ReaderSkippableCB: Invalid id provided, must be 0x80-0xfd (inclusive)") return fmt.Errorf("ReaderSkippableCB: Invalid id provided, must be 0x80-0xfd (inclusive)")
} }
r.skippableCB[id] = fn r.skippableCB[id-0x80] = fn
return nil return nil
} }
} }
@ -128,7 +130,7 @@ type Reader struct {
err error err error
decoded []byte decoded []byte
buf []byte buf []byte
skippableCB [0x80]func(r io.Reader) error skippableCB [0xff - 0x80]func(r io.Reader) error
blockStart int64 // Uncompressed offset at start of current. blockStart int64 // Uncompressed offset at start of current.
index *Index index *Index
@ -201,7 +203,7 @@ func (r *Reader) readFull(p []byte, allowEOF bool) (ok bool) {
// The supplied slice does not need to be the size of the read. // The supplied slice does not need to be the size of the read.
func (r *Reader) skippable(tmp []byte, n int, allowEOF bool, id uint8) (ok bool) { func (r *Reader) skippable(tmp []byte, n int, allowEOF bool, id uint8) (ok bool) {
if id < 0x80 { if id < 0x80 {
r.err = fmt.Errorf("interbal error: skippable id < 0x80") r.err = fmt.Errorf("internal error: skippable id < 0x80")
return false return false
} }
if fn := r.skippableCB[id-0x80]; fn != nil { if fn := r.skippableCB[id-0x80]; fn != nil {
@ -450,6 +452,12 @@ func (r *Reader) DecodeConcurrent(w io.Writer, concurrent int) (written int64, e
for toWrite := range queue { for toWrite := range queue {
entry := <-toWrite entry := <-toWrite
reUse <- toWrite reUse <- toWrite
if hasErr() || entry == nil {
if entry != nil {
writtenBlocks <- entry
}
continue
}
if hasErr() { if hasErr() {
writtenBlocks <- entry writtenBlocks <- entry
continue continue
@ -469,13 +477,13 @@ func (r *Reader) DecodeConcurrent(w io.Writer, concurrent int) (written int64, e
} }
}() }()
// Reader
defer func() { defer func() {
close(queue)
if r.err != nil { if r.err != nil {
err = r.err
setErr(r.err) setErr(r.err)
} else if err != nil {
setErr(err)
} }
close(queue)
wg.Wait() wg.Wait()
if err == nil { if err == nil {
err = aErr err = aErr
@ -483,6 +491,7 @@ func (r *Reader) DecodeConcurrent(w io.Writer, concurrent int) (written int64, e
written = aWritten written = aWritten
}() }()
// Reader
for !hasErr() { for !hasErr() {
if !r.readFull(r.buf[:4], true) { if !r.readFull(r.buf[:4], true) {
if r.err == io.EOF { if r.err == io.EOF {
@ -551,11 +560,13 @@ func (r *Reader) DecodeConcurrent(w io.Writer, concurrent int) (written int64, e
if err != nil { if err != nil {
writtenBlocks <- decoded writtenBlocks <- decoded
setErr(err) setErr(err)
entry <- nil
return return
} }
if !r.ignoreCRC && crc(decoded) != checksum { if !r.ignoreCRC && crc(decoded) != checksum {
writtenBlocks <- decoded writtenBlocks <- decoded
setErr(ErrCRC) setErr(ErrCRC)
entry <- nil
return return
} }
entry <- decoded entry <- decoded
@ -1048,15 +1059,17 @@ func (r *Reader) ReadByte() (byte, error) {
} }
// SkippableCB will register a callback for chunks with the specified ID. // SkippableCB will register a callback for chunks with the specified ID.
// ID must be a Reserved skippable chunks ID, 0x80-0xfe (inclusive). // ID must be a Reserved skippable chunks ID, 0x80-0xfd (inclusive).
// For each chunk with the ID, the callback is called with the content. // For each chunk with the ID, the callback is called with the content.
// Any returned non-nil error will abort decompression. // Any returned non-nil error will abort decompression.
// Only one callback per ID is supported, latest sent will be used. // Only one callback per ID is supported, latest sent will be used.
// Sending a nil function will disable previous callbacks. // Sending a nil function will disable previous callbacks.
// You can peek the stream, triggering the callback, by doing a Read with a 0
// byte buffer.
func (r *Reader) SkippableCB(id uint8, fn func(r io.Reader) error) error { func (r *Reader) SkippableCB(id uint8, fn func(r io.Reader) error) error {
if id < 0x80 || id > chunkTypePadding { if id < 0x80 || id >= chunkTypePadding {
return fmt.Errorf("ReaderSkippableCB: Invalid id provided, must be 0x80-0xfe (inclusive)") return fmt.Errorf("ReaderSkippableCB: Invalid id provided, must be 0x80-0xfe (inclusive)")
} }
r.skippableCB[id] = fn r.skippableCB[id-0x80] = fn
return nil return nil
} }

View File

@ -37,6 +37,8 @@ package s2
import ( import (
"bytes" "bytes"
"hash/crc32" "hash/crc32"
"github.com/klauspost/compress/internal/race"
) )
/* /*
@ -112,6 +114,8 @@ var crcTable = crc32.MakeTable(crc32.Castagnoli)
// crc implements the checksum specified in section 3 of // crc implements the checksum specified in section 3 of
// https://github.com/google/snappy/blob/master/framing_format.txt // https://github.com/google/snappy/blob/master/framing_format.txt
func crc(b []byte) uint32 { func crc(b []byte) uint32 {
race.ReadSlice(b)
c := crc32.Update(0, crcTable, b) c := crc32.Update(0, crcTable, b)
return c>>15 | c<<17 + 0xa282ead8 return c>>15 | c<<17 + 0xa282ead8
} }

View File

@ -13,6 +13,8 @@ import (
"io" "io"
"runtime" "runtime"
"sync" "sync"
"github.com/klauspost/compress/internal/race"
) )
const ( const (
@ -213,7 +215,7 @@ func (w *Writer) ReadFrom(r io.Reader) (n int64, err error) {
return 0, err return 0, err
} }
if len(w.ibuf) > 0 { if len(w.ibuf) > 0 {
err := w.Flush() err := w.AsyncFlush()
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -223,7 +225,7 @@ func (w *Writer) ReadFrom(r io.Reader) (n int64, err error) {
if err := w.EncodeBuffer(buf); err != nil { if err := w.EncodeBuffer(buf); err != nil {
return 0, err return 0, err
} }
return int64(len(buf)), w.Flush() return int64(len(buf)), w.AsyncFlush()
} }
for { for {
inbuf := w.buffers.Get().([]byte)[:w.blockSize+obufHeaderLen] inbuf := w.buffers.Get().([]byte)[:w.blockSize+obufHeaderLen]
@ -271,7 +273,7 @@ func (w *Writer) AddSkippableBlock(id uint8, data []byte) (err error) {
return fmt.Errorf("skippable block excessed maximum size") return fmt.Errorf("skippable block excessed maximum size")
} }
var header [4]byte var header [4]byte
chunkLen := 4 + len(data) chunkLen := len(data)
header[0] = id header[0] = id
header[1] = uint8(chunkLen >> 0) header[1] = uint8(chunkLen >> 0)
header[2] = uint8(chunkLen >> 8) header[2] = uint8(chunkLen >> 8)
@ -282,7 +284,7 @@ func (w *Writer) AddSkippableBlock(id uint8, data []byte) (err error) {
if err = w.err(err); err != nil { if err = w.err(err); err != nil {
return err return err
} }
if n != len(data) { if n != len(b) {
return w.err(io.ErrShortWrite) return w.err(io.ErrShortWrite)
} }
w.written += int64(n) w.written += int64(n)
@ -303,9 +305,7 @@ func (w *Writer) AddSkippableBlock(id uint8, data []byte) (err error) {
if err := write(header[:]); err != nil { if err := write(header[:]); err != nil {
return err return err
} }
if err := write(data); err != nil { return write(data)
return err
}
} }
// Create output... // Create output...
@ -354,7 +354,7 @@ func (w *Writer) EncodeBuffer(buf []byte) (err error) {
} }
// Flush queued data first. // Flush queued data first.
if len(w.ibuf) > 0 { if len(w.ibuf) > 0 {
err := w.Flush() err := w.AsyncFlush()
if err != nil { if err != nil {
return err return err
} }
@ -385,6 +385,8 @@ func (w *Writer) EncodeBuffer(buf []byte) (err error) {
buf = buf[len(uncompressed):] buf = buf[len(uncompressed):]
// Get an output buffer. // Get an output buffer.
obuf := w.buffers.Get().([]byte)[:len(uncompressed)+obufHeaderLen] obuf := w.buffers.Get().([]byte)[:len(uncompressed)+obufHeaderLen]
race.WriteSlice(obuf)
output := make(chan result) output := make(chan result)
// Queue output now, so we keep order. // Queue output now, so we keep order.
w.output <- output w.output <- output
@ -393,6 +395,8 @@ func (w *Writer) EncodeBuffer(buf []byte) (err error) {
} }
w.uncompWritten += int64(len(uncompressed)) w.uncompWritten += int64(len(uncompressed))
go func() { go func() {
race.ReadSlice(uncompressed)
checksum := crc(uncompressed) checksum := crc(uncompressed)
// Set to uncompressed. // Set to uncompressed.
@ -712,9 +716,9 @@ func (w *Writer) writeSync(p []byte) (nRet int, errRet error) {
return nRet, nil return nRet, nil
} }
// Flush flushes the Writer to its underlying io.Writer. // AsyncFlush writes any buffered bytes to a block and starts compressing it.
// This does not apply padding. // It does not wait for the output has been written as Flush() does.
func (w *Writer) Flush() error { func (w *Writer) AsyncFlush() error {
if err := w.err(nil); err != nil { if err := w.err(nil); err != nil {
return err return err
} }
@ -734,6 +738,15 @@ func (w *Writer) Flush() error {
} }
} }
} }
return w.err(nil)
}
// Flush flushes the Writer to its underlying io.Writer.
// This does not apply padding.
func (w *Writer) Flush() error {
if err := w.AsyncFlush(); err != nil {
return err
}
if w.output == nil { if w.output == nil {
return w.err(nil) return w.err(nil)
} }

View File

@ -67,195 +67,200 @@ const (
// Keep index -1 as unknown // Keep index -1 as unknown
UNKNOWN = -1 UNKNOWN = -1
// Add features // x86 features
ADX FeatureID = iota // Intel ADX (Multi-Precision Add-Carry Instruction Extensions) ADX FeatureID = iota // Intel ADX (Multi-Precision Add-Carry Instruction Extensions)
AESNI // Advanced Encryption Standard New Instructions AESNI // Advanced Encryption Standard New Instructions
AMD3DNOW // AMD 3DNOW AMD3DNOW // AMD 3DNOW
AMD3DNOWEXT // AMD 3DNowExt AMD3DNOWEXT // AMD 3DNowExt
AMXBF16 // Tile computational operations on BFLOAT16 numbers AMXBF16 // Tile computational operations on BFLOAT16 numbers
AMXFP16 // Tile computational operations on FP16 numbers AMXFP16 // Tile computational operations on FP16 numbers
AMXINT8 // Tile computational operations on 8-bit integers AMXINT8 // Tile computational operations on 8-bit integers
AMXTILE // Tile architecture AMXTILE // Tile architecture
APX_F // Intel APX APX_F // Intel APX
AVX // AVX functions AVX // AVX functions
AVX10 // If set the Intel AVX10 Converged Vector ISA is supported AVX10 // If set the Intel AVX10 Converged Vector ISA is supported
AVX10_128 // If set indicates that AVX10 128-bit vector support is present AVX10_128 // If set indicates that AVX10 128-bit vector support is present
AVX10_256 // If set indicates that AVX10 256-bit vector support is present AVX10_256 // If set indicates that AVX10 256-bit vector support is present
AVX10_512 // If set indicates that AVX10 512-bit vector support is present AVX10_512 // If set indicates that AVX10 512-bit vector support is present
AVX2 // AVX2 functions AVX2 // AVX2 functions
AVX512BF16 // AVX-512 BFLOAT16 Instructions AVX512BF16 // AVX-512 BFLOAT16 Instructions
AVX512BITALG // AVX-512 Bit Algorithms AVX512BITALG // AVX-512 Bit Algorithms
AVX512BW // AVX-512 Byte and Word Instructions AVX512BW // AVX-512 Byte and Word Instructions
AVX512CD // AVX-512 Conflict Detection Instructions AVX512CD // AVX-512 Conflict Detection Instructions
AVX512DQ // AVX-512 Doubleword and Quadword Instructions AVX512DQ // AVX-512 Doubleword and Quadword Instructions
AVX512ER // AVX-512 Exponential and Reciprocal Instructions AVX512ER // AVX-512 Exponential and Reciprocal Instructions
AVX512F // AVX-512 Foundation AVX512F // AVX-512 Foundation
AVX512FP16 // AVX-512 FP16 Instructions AVX512FP16 // AVX-512 FP16 Instructions
AVX512IFMA // AVX-512 Integer Fused Multiply-Add Instructions AVX512IFMA // AVX-512 Integer Fused Multiply-Add Instructions
AVX512PF // AVX-512 Prefetch Instructions AVX512PF // AVX-512 Prefetch Instructions
AVX512VBMI // AVX-512 Vector Bit Manipulation Instructions AVX512VBMI // AVX-512 Vector Bit Manipulation Instructions
AVX512VBMI2 // AVX-512 Vector Bit Manipulation Instructions, Version 2 AVX512VBMI2 // AVX-512 Vector Bit Manipulation Instructions, Version 2
AVX512VL // AVX-512 Vector Length Extensions AVX512VL // AVX-512 Vector Length Extensions
AVX512VNNI // AVX-512 Vector Neural Network Instructions AVX512VNNI // AVX-512 Vector Neural Network Instructions
AVX512VP2INTERSECT // AVX-512 Intersect for D/Q AVX512VP2INTERSECT // AVX-512 Intersect for D/Q
AVX512VPOPCNTDQ // AVX-512 Vector Population Count Doubleword and Quadword AVX512VPOPCNTDQ // AVX-512 Vector Population Count Doubleword and Quadword
AVXIFMA // AVX-IFMA instructions AVXIFMA // AVX-IFMA instructions
AVXNECONVERT // AVX-NE-CONVERT instructions AVXNECONVERT // AVX-NE-CONVERT instructions
AVXSLOW // Indicates the CPU performs 2 128 bit operations instead of one AVXSLOW // Indicates the CPU performs 2 128 bit operations instead of one
AVXVNNI // AVX (VEX encoded) VNNI neural network instructions AVXVNNI // AVX (VEX encoded) VNNI neural network instructions
AVXVNNIINT8 // AVX-VNNI-INT8 instructions AVXVNNIINT8 // AVX-VNNI-INT8 instructions
BHI_CTRL // Branch History Injection and Intra-mode Branch Target Injection / CVE-2022-0001, CVE-2022-0002 / INTEL-SA-00598 BHI_CTRL // Branch History Injection and Intra-mode Branch Target Injection / CVE-2022-0001, CVE-2022-0002 / INTEL-SA-00598
BMI1 // Bit Manipulation Instruction Set 1 BMI1 // Bit Manipulation Instruction Set 1
BMI2 // Bit Manipulation Instruction Set 2 BMI2 // Bit Manipulation Instruction Set 2
CETIBT // Intel CET Indirect Branch Tracking CETIBT // Intel CET Indirect Branch Tracking
CETSS // Intel CET Shadow Stack CETSS // Intel CET Shadow Stack
CLDEMOTE // Cache Line Demote CLDEMOTE // Cache Line Demote
CLMUL // Carry-less Multiplication CLMUL // Carry-less Multiplication
CLZERO // CLZERO instruction supported CLZERO // CLZERO instruction supported
CMOV // i686 CMOV CMOV // i686 CMOV
CMPCCXADD // CMPCCXADD instructions CMPCCXADD // CMPCCXADD instructions
CMPSB_SCADBS_SHORT // Fast short CMPSB and SCASB CMPSB_SCADBS_SHORT // Fast short CMPSB and SCASB
CMPXCHG8 // CMPXCHG8 instruction CMPXCHG8 // CMPXCHG8 instruction
CPBOOST // Core Performance Boost CPBOOST // Core Performance Boost
CPPC // AMD: Collaborative Processor Performance Control CPPC // AMD: Collaborative Processor Performance Control
CX16 // CMPXCHG16B Instruction CX16 // CMPXCHG16B Instruction
EFER_LMSLE_UNS // AMD: =Core::X86::Msr::EFER[LMSLE] is not supported, and MBZ EFER_LMSLE_UNS // AMD: =Core::X86::Msr::EFER[LMSLE] is not supported, and MBZ
ENQCMD // Enqueue Command ENQCMD // Enqueue Command
ERMS // Enhanced REP MOVSB/STOSB ERMS // Enhanced REP MOVSB/STOSB
F16C // Half-precision floating-point conversion F16C // Half-precision floating-point conversion
FLUSH_L1D // Flush L1D cache FLUSH_L1D // Flush L1D cache
FMA3 // Intel FMA 3. Does not imply AVX. FMA3 // Intel FMA 3. Does not imply AVX.
FMA4 // Bulldozer FMA4 functions FMA4 // Bulldozer FMA4 functions
FP128 // AMD: When set, the internal FP/SIMD execution datapath is no more than 128-bits wide FP128 // AMD: When set, the internal FP/SIMD execution datapath is no more than 128-bits wide
FP256 // AMD: When set, the internal FP/SIMD execution datapath is no more than 256-bits wide FP256 // AMD: When set, the internal FP/SIMD execution datapath is no more than 256-bits wide
FSRM // Fast Short Rep Mov FSRM // Fast Short Rep Mov
FXSR // FXSAVE, FXRESTOR instructions, CR4 bit 9 FXSR // FXSAVE, FXRESTOR instructions, CR4 bit 9
FXSROPT // FXSAVE/FXRSTOR optimizations FXSROPT // FXSAVE/FXRSTOR optimizations
GFNI // Galois Field New Instructions. May require other features (AVX, AVX512VL,AVX512F) based on usage. GFNI // Galois Field New Instructions. May require other features (AVX, AVX512VL,AVX512F) based on usage.
HLE // Hardware Lock Elision HLE // Hardware Lock Elision
HRESET // If set CPU supports history reset and the IA32_HRESET_ENABLE MSR HRESET // If set CPU supports history reset and the IA32_HRESET_ENABLE MSR
HTT // Hyperthreading (enabled) HTT // Hyperthreading (enabled)
HWA // Hardware assert supported. Indicates support for MSRC001_10 HWA // Hardware assert supported. Indicates support for MSRC001_10
HYBRID_CPU // This part has CPUs of more than one type. HYBRID_CPU // This part has CPUs of more than one type.
HYPERVISOR // This bit has been reserved by Intel & AMD for use by hypervisors HYPERVISOR // This bit has been reserved by Intel & AMD for use by hypervisors
IA32_ARCH_CAP // IA32_ARCH_CAPABILITIES MSR (Intel) IA32_ARCH_CAP // IA32_ARCH_CAPABILITIES MSR (Intel)
IA32_CORE_CAP // IA32_CORE_CAPABILITIES MSR IA32_CORE_CAP // IA32_CORE_CAPABILITIES MSR
IBPB // Indirect Branch Restricted Speculation (IBRS) and Indirect Branch Predictor Barrier (IBPB) IBPB // Indirect Branch Restricted Speculation (IBRS) and Indirect Branch Predictor Barrier (IBPB)
IBRS // AMD: Indirect Branch Restricted Speculation IBPB_BRTYPE // Indicates that MSR 49h (PRED_CMD) bit 0 (IBPB) flushes all branch type predictions from the CPU branch predictor
IBRS_PREFERRED // AMD: IBRS is preferred over software solution IBRS // AMD: Indirect Branch Restricted Speculation
IBRS_PROVIDES_SMP // AMD: IBRS provides Same Mode Protection IBRS_PREFERRED // AMD: IBRS is preferred over software solution
IBS // Instruction Based Sampling (AMD) IBRS_PROVIDES_SMP // AMD: IBRS provides Same Mode Protection
IBSBRNTRGT // Instruction Based Sampling Feature (AMD) IBS // Instruction Based Sampling (AMD)
IBSFETCHSAM // Instruction Based Sampling Feature (AMD) IBSBRNTRGT // Instruction Based Sampling Feature (AMD)
IBSFFV // Instruction Based Sampling Feature (AMD) IBSFETCHSAM // Instruction Based Sampling Feature (AMD)
IBSOPCNT // Instruction Based Sampling Feature (AMD) IBSFFV // Instruction Based Sampling Feature (AMD)
IBSOPCNTEXT // Instruction Based Sampling Feature (AMD) IBSOPCNT // Instruction Based Sampling Feature (AMD)
IBSOPSAM // Instruction Based Sampling Feature (AMD) IBSOPCNTEXT // Instruction Based Sampling Feature (AMD)
IBSRDWROPCNT // Instruction Based Sampling Feature (AMD) IBSOPSAM // Instruction Based Sampling Feature (AMD)
IBSRIPINVALIDCHK // Instruction Based Sampling Feature (AMD) IBSRDWROPCNT // Instruction Based Sampling Feature (AMD)
IBS_FETCH_CTLX // AMD: IBS fetch control extended MSR supported IBSRIPINVALIDCHK // Instruction Based Sampling Feature (AMD)
IBS_OPDATA4 // AMD: IBS op data 4 MSR supported IBS_FETCH_CTLX // AMD: IBS fetch control extended MSR supported
IBS_OPFUSE // AMD: Indicates support for IbsOpFuse IBS_OPDATA4 // AMD: IBS op data 4 MSR supported
IBS_PREVENTHOST // Disallowing IBS use by the host supported IBS_OPFUSE // AMD: Indicates support for IbsOpFuse
IBS_ZEN4 // AMD: Fetch and Op IBS support IBS extensions added with Zen4 IBS_PREVENTHOST // Disallowing IBS use by the host supported
IDPRED_CTRL // IPRED_DIS IBS_ZEN4 // AMD: Fetch and Op IBS support IBS extensions added with Zen4
INT_WBINVD // WBINVD/WBNOINVD are interruptible. IDPRED_CTRL // IPRED_DIS
INVLPGB // NVLPGB and TLBSYNC instruction supported INT_WBINVD // WBINVD/WBNOINVD are interruptible.
KEYLOCKER // Key locker INVLPGB // NVLPGB and TLBSYNC instruction supported
KEYLOCKERW // Key locker wide KEYLOCKER // Key locker
LAHF // LAHF/SAHF in long mode KEYLOCKERW // Key locker wide
LAM // If set, CPU supports Linear Address Masking LAHF // LAHF/SAHF in long mode
LBRVIRT // LBR virtualization LAM // If set, CPU supports Linear Address Masking
LZCNT // LZCNT instruction LBRVIRT // LBR virtualization
MCAOVERFLOW // MCA overflow recovery support. LZCNT // LZCNT instruction
MCDT_NO // Processor do not exhibit MXCSR Configuration Dependent Timing behavior and do not need to mitigate it. MCAOVERFLOW // MCA overflow recovery support.
MCOMMIT // MCOMMIT instruction supported MCDT_NO // Processor do not exhibit MXCSR Configuration Dependent Timing behavior and do not need to mitigate it.
MD_CLEAR // VERW clears CPU buffers MCOMMIT // MCOMMIT instruction supported
MMX // standard MMX MD_CLEAR // VERW clears CPU buffers
MMXEXT // SSE integer functions or AMD MMX ext MMX // standard MMX
MOVBE // MOVBE instruction (big-endian) MMXEXT // SSE integer functions or AMD MMX ext
MOVDIR64B // Move 64 Bytes as Direct Store MOVBE // MOVBE instruction (big-endian)
MOVDIRI // Move Doubleword as Direct Store MOVDIR64B // Move 64 Bytes as Direct Store
MOVSB_ZL // Fast Zero-Length MOVSB MOVDIRI // Move Doubleword as Direct Store
MOVU // AMD: MOVU SSE instructions are more efficient and should be preferred to SSE MOVL/MOVH. MOVUPS is more efficient than MOVLPS/MOVHPS. MOVUPD is more efficient than MOVLPD/MOVHPD MOVSB_ZL // Fast Zero-Length MOVSB
MPX // Intel MPX (Memory Protection Extensions) MOVU // AMD: MOVU SSE instructions are more efficient and should be preferred to SSE MOVL/MOVH. MOVUPS is more efficient than MOVLPS/MOVHPS. MOVUPD is more efficient than MOVLPD/MOVHPD
MSRIRC // Instruction Retired Counter MSR available MPX // Intel MPX (Memory Protection Extensions)
MSRLIST // Read/Write List of Model Specific Registers MSRIRC // Instruction Retired Counter MSR available
MSR_PAGEFLUSH // Page Flush MSR available MSRLIST // Read/Write List of Model Specific Registers
NRIPS // Indicates support for NRIP save on VMEXIT MSR_PAGEFLUSH // Page Flush MSR available
NX // NX (No-Execute) bit NRIPS // Indicates support for NRIP save on VMEXIT
OSXSAVE // XSAVE enabled by OS NX // NX (No-Execute) bit
PCONFIG // PCONFIG for Intel Multi-Key Total Memory Encryption OSXSAVE // XSAVE enabled by OS
POPCNT // POPCNT instruction PCONFIG // PCONFIG for Intel Multi-Key Total Memory Encryption
PPIN // AMD: Protected Processor Inventory Number support. Indicates that Protected Processor Inventory Number (PPIN) capability can be enabled POPCNT // POPCNT instruction
PREFETCHI // PREFETCHIT0/1 instructions PPIN // AMD: Protected Processor Inventory Number support. Indicates that Protected Processor Inventory Number (PPIN) capability can be enabled
PSFD // Predictive Store Forward Disable PREFETCHI // PREFETCHIT0/1 instructions
RDPRU // RDPRU instruction supported PSFD // Predictive Store Forward Disable
RDRAND // RDRAND instruction is available RDPRU // RDPRU instruction supported
RDSEED // RDSEED instruction is available RDRAND // RDRAND instruction is available
RDTSCP // RDTSCP Instruction RDSEED // RDSEED instruction is available
RRSBA_CTRL // Restricted RSB Alternate RDTSCP // RDTSCP Instruction
RTM // Restricted Transactional Memory RRSBA_CTRL // Restricted RSB Alternate
RTM_ALWAYS_ABORT // Indicates that the loaded microcode is forcing RTM abort. RTM // Restricted Transactional Memory
SERIALIZE // Serialize Instruction Execution RTM_ALWAYS_ABORT // Indicates that the loaded microcode is forcing RTM abort.
SEV // AMD Secure Encrypted Virtualization supported SBPB // Indicates support for the Selective Branch Predictor Barrier
SEV_64BIT // AMD SEV guest execution only allowed from a 64-bit host SERIALIZE // Serialize Instruction Execution
SEV_ALTERNATIVE // AMD SEV Alternate Injection supported SEV // AMD Secure Encrypted Virtualization supported
SEV_DEBUGSWAP // Full debug state swap supported for SEV-ES guests SEV_64BIT // AMD SEV guest execution only allowed from a 64-bit host
SEV_ES // AMD SEV Encrypted State supported SEV_ALTERNATIVE // AMD SEV Alternate Injection supported
SEV_RESTRICTED // AMD SEV Restricted Injection supported SEV_DEBUGSWAP // Full debug state swap supported for SEV-ES guests
SEV_SNP // AMD SEV Secure Nested Paging supported SEV_ES // AMD SEV Encrypted State supported
SGX // Software Guard Extensions SEV_RESTRICTED // AMD SEV Restricted Injection supported
SGXLC // Software Guard Extensions Launch Control SEV_SNP // AMD SEV Secure Nested Paging supported
SHA // Intel SHA Extensions SGX // Software Guard Extensions
SME // AMD Secure Memory Encryption supported SGXLC // Software Guard Extensions Launch Control
SME_COHERENT // AMD Hardware cache coherency across encryption domains enforced SHA // Intel SHA Extensions
SPEC_CTRL_SSBD // Speculative Store Bypass Disable SME // AMD Secure Memory Encryption supported
SRBDS_CTRL // SRBDS mitigation MSR available SME_COHERENT // AMD Hardware cache coherency across encryption domains enforced
SSE // SSE functions SPEC_CTRL_SSBD // Speculative Store Bypass Disable
SSE2 // P4 SSE functions SRBDS_CTRL // SRBDS mitigation MSR available
SSE3 // Prescott SSE3 functions SRSO_MSR_FIX // Indicates that software may use MSR BP_CFG[BpSpecReduce] to mitigate SRSO.
SSE4 // Penryn SSE4.1 functions SRSO_NO // Indicates the CPU is not subject to the SRSO vulnerability
SSE42 // Nehalem SSE4.2 functions SRSO_USER_KERNEL_NO // Indicates the CPU is not subject to the SRSO vulnerability across user/kernel boundaries
SSE4A // AMD Barcelona microarchitecture SSE4a instructions SSE // SSE functions
SSSE3 // Conroe SSSE3 functions SSE2 // P4 SSE functions
STIBP // Single Thread Indirect Branch Predictors SSE3 // Prescott SSE3 functions
STIBP_ALWAYSON // AMD: Single Thread Indirect Branch Prediction Mode has Enhanced Performance and may be left Always On SSE4 // Penryn SSE4.1 functions
STOSB_SHORT // Fast short STOSB SSE42 // Nehalem SSE4.2 functions
SUCCOR // Software uncorrectable error containment and recovery capability. SSE4A // AMD Barcelona microarchitecture SSE4a instructions
SVM // AMD Secure Virtual Machine SSSE3 // Conroe SSSE3 functions
SVMDA // Indicates support for the SVM decode assists. STIBP // Single Thread Indirect Branch Predictors
SVMFBASID // SVM, Indicates that TLB flush events, including CR3 writes and CR4.PGE toggles, flush only the current ASID's TLB entries. Also indicates support for the extended VMCBTLB_Control STIBP_ALWAYSON // AMD: Single Thread Indirect Branch Prediction Mode has Enhanced Performance and may be left Always On
SVML // AMD SVM lock. Indicates support for SVM-Lock. STOSB_SHORT // Fast short STOSB
SVMNP // AMD SVM nested paging SUCCOR // Software uncorrectable error containment and recovery capability.
SVMPF // SVM pause intercept filter. Indicates support for the pause intercept filter SVM // AMD Secure Virtual Machine
SVMPFT // SVM PAUSE filter threshold. Indicates support for the PAUSE filter cycle count threshold SVMDA // Indicates support for the SVM decode assists.
SYSCALL // System-Call Extension (SCE): SYSCALL and SYSRET instructions. SVMFBASID // SVM, Indicates that TLB flush events, including CR3 writes and CR4.PGE toggles, flush only the current ASID's TLB entries. Also indicates support for the extended VMCBTLB_Control
SYSEE // SYSENTER and SYSEXIT instructions SVML // AMD SVM lock. Indicates support for SVM-Lock.
TBM // AMD Trailing Bit Manipulation SVMNP // AMD SVM nested paging
TDX_GUEST // Intel Trust Domain Extensions Guest SVMPF // SVM pause intercept filter. Indicates support for the pause intercept filter
TLB_FLUSH_NESTED // AMD: Flushing includes all the nested translations for guest translations SVMPFT // SVM PAUSE filter threshold. Indicates support for the PAUSE filter cycle count threshold
TME // Intel Total Memory Encryption. The following MSRs are supported: IA32_TME_CAPABILITY, IA32_TME_ACTIVATE, IA32_TME_EXCLUDE_MASK, and IA32_TME_EXCLUDE_BASE. SYSCALL // System-Call Extension (SCE): SYSCALL and SYSRET instructions.
TOPEXT // TopologyExtensions: topology extensions support. Indicates support for CPUID Fn8000_001D_EAX_x[N:0]-CPUID Fn8000_001E_EDX. SYSEE // SYSENTER and SYSEXIT instructions
TSCRATEMSR // MSR based TSC rate control. Indicates support for MSR TSC ratio MSRC000_0104 TBM // AMD Trailing Bit Manipulation
TSXLDTRK // Intel TSX Suspend Load Address Tracking TDX_GUEST // Intel Trust Domain Extensions Guest
VAES // Vector AES. AVX(512) versions requires additional checks. TLB_FLUSH_NESTED // AMD: Flushing includes all the nested translations for guest translations
VMCBCLEAN // VMCB clean bits. Indicates support for VMCB clean bits. TME // Intel Total Memory Encryption. The following MSRs are supported: IA32_TME_CAPABILITY, IA32_TME_ACTIVATE, IA32_TME_EXCLUDE_MASK, and IA32_TME_EXCLUDE_BASE.
VMPL // AMD VM Permission Levels supported TOPEXT // TopologyExtensions: topology extensions support. Indicates support for CPUID Fn8000_001D_EAX_x[N:0]-CPUID Fn8000_001E_EDX.
VMSA_REGPROT // AMD VMSA Register Protection supported TSCRATEMSR // MSR based TSC rate control. Indicates support for MSR TSC ratio MSRC000_0104
VMX // Virtual Machine Extensions TSXLDTRK // Intel TSX Suspend Load Address Tracking
VPCLMULQDQ // Carry-Less Multiplication Quadword. Requires AVX for 3 register versions. VAES // Vector AES. AVX(512) versions requires additional checks.
VTE // AMD Virtual Transparent Encryption supported VMCBCLEAN // VMCB clean bits. Indicates support for VMCB clean bits.
WAITPKG // TPAUSE, UMONITOR, UMWAIT VMPL // AMD VM Permission Levels supported
WBNOINVD // Write Back and Do Not Invalidate Cache VMSA_REGPROT // AMD VMSA Register Protection supported
WRMSRNS // Non-Serializing Write to Model Specific Register VMX // Virtual Machine Extensions
X87 // FPU VPCLMULQDQ // Carry-Less Multiplication Quadword. Requires AVX for 3 register versions.
XGETBV1 // Supports XGETBV with ECX = 1 VTE // AMD Virtual Transparent Encryption supported
XOP // Bulldozer XOP functions WAITPKG // TPAUSE, UMONITOR, UMWAIT
XSAVE // XSAVE, XRESTOR, XSETBV, XGETBV WBNOINVD // Write Back and Do Not Invalidate Cache
XSAVEC // Supports XSAVEC and the compacted form of XRSTOR. WRMSRNS // Non-Serializing Write to Model Specific Register
XSAVEOPT // XSAVEOPT available X87 // FPU
XSAVES // Supports XSAVES/XRSTORS and IA32_XSS XGETBV1 // Supports XGETBV with ECX = 1
XOP // Bulldozer XOP functions
XSAVE // XSAVE, XRESTOR, XSETBV, XGETBV
XSAVEC // Supports XSAVEC and the compacted form of XRSTOR.
XSAVEOPT // XSAVEOPT available
XSAVES // Supports XSAVES/XRSTORS and IA32_XSS
// ARM features: // ARM features:
AESARM // AES instructions AESARM // AES instructions
@ -309,10 +314,11 @@ type CPUInfo struct {
L2 int // L2 Cache (per core or shared). Will be -1 if undetected L2 int // L2 Cache (per core or shared). Will be -1 if undetected
L3 int // L3 Cache (per core, per ccx or shared). Will be -1 if undetected L3 int // L3 Cache (per core, per ccx or shared). Will be -1 if undetected
} }
SGX SGXSupport SGX SGXSupport
AVX10Level uint8 AMDMemEncryption AMDMemEncryptionSupport
maxFunc uint32 AVX10Level uint8
maxExFunc uint32 maxFunc uint32
maxExFunc uint32
} }
var cpuid func(op uint32) (eax, ebx, ecx, edx uint32) var cpuid func(op uint32) (eax, ebx, ecx, edx uint32)
@ -1079,6 +1085,32 @@ func hasSGX(available, lc bool) (rval SGXSupport) {
return return
} }
type AMDMemEncryptionSupport struct {
Available bool
CBitPossition uint32
NumVMPL uint32
PhysAddrReduction uint32
NumEntryptedGuests uint32
MinSevNoEsAsid uint32
}
func hasAMDMemEncryption(available bool) (rval AMDMemEncryptionSupport) {
rval.Available = available
if !available {
return
}
_, b, c, d := cpuidex(0x8000001f, 0)
rval.CBitPossition = b & 0x3f
rval.PhysAddrReduction = (b >> 6) & 0x3F
rval.NumVMPL = (b >> 12) & 0xf
rval.NumEntryptedGuests = c
rval.MinSevNoEsAsid = d
return
}
func support() flagSet { func support() flagSet {
var fs flagSet var fs flagSet
mfi := maxFunctionID() mfi := maxFunctionID()
@ -1418,6 +1450,15 @@ func support() flagSet {
fs.setIf((a>>24)&1 == 1, VMSA_REGPROT) fs.setIf((a>>24)&1 == 1, VMSA_REGPROT)
} }
if maxExtendedFunction() >= 0x80000021 && vend == AMD {
a, _, _, _ := cpuid(0x80000021)
fs.setIf((a>>31)&1 == 1, SRSO_MSR_FIX)
fs.setIf((a>>30)&1 == 1, SRSO_USER_KERNEL_NO)
fs.setIf((a>>29)&1 == 1, SRSO_NO)
fs.setIf((a>>28)&1 == 1, IBPB_BRTYPE)
fs.setIf((a>>27)&1 == 1, SBPB)
}
if mfi >= 0x20 { if mfi >= 0x20 {
// Microsoft has decided to purposefully hide the information // Microsoft has decided to purposefully hide the information
// of the guest TEE when VMs are being created using Hyper-V. // of the guest TEE when VMs are being created using Hyper-V.

View File

@ -27,6 +27,7 @@ func addInfo(c *CPUInfo, safe bool) {
c.Family, c.Model, c.Stepping = familyModel() c.Family, c.Model, c.Stepping = familyModel()
c.featureSet = support() c.featureSet = support()
c.SGX = hasSGX(c.featureSet.inSet(SGX), c.featureSet.inSet(SGXLC)) c.SGX = hasSGX(c.featureSet.inSet(SGX), c.featureSet.inSet(SGXLC))
c.AMDMemEncryption = hasAMDMemEncryption(c.featureSet.inSet(SME) || c.featureSet.inSet(SEV))
c.ThreadsPerCore = threadsPerCore() c.ThreadsPerCore = threadsPerCore()
c.LogicalCores = logicalCores() c.LogicalCores = logicalCores()
c.PhysicalCores = physicalCores() c.PhysicalCores = physicalCores()

View File

@ -81,152 +81,157 @@ func _() {
_ = x[IA32_ARCH_CAP-71] _ = x[IA32_ARCH_CAP-71]
_ = x[IA32_CORE_CAP-72] _ = x[IA32_CORE_CAP-72]
_ = x[IBPB-73] _ = x[IBPB-73]
_ = x[IBRS-74] _ = x[IBPB_BRTYPE-74]
_ = x[IBRS_PREFERRED-75] _ = x[IBRS-75]
_ = x[IBRS_PROVIDES_SMP-76] _ = x[IBRS_PREFERRED-76]
_ = x[IBS-77] _ = x[IBRS_PROVIDES_SMP-77]
_ = x[IBSBRNTRGT-78] _ = x[IBS-78]
_ = x[IBSFETCHSAM-79] _ = x[IBSBRNTRGT-79]
_ = x[IBSFFV-80] _ = x[IBSFETCHSAM-80]
_ = x[IBSOPCNT-81] _ = x[IBSFFV-81]
_ = x[IBSOPCNTEXT-82] _ = x[IBSOPCNT-82]
_ = x[IBSOPSAM-83] _ = x[IBSOPCNTEXT-83]
_ = x[IBSRDWROPCNT-84] _ = x[IBSOPSAM-84]
_ = x[IBSRIPINVALIDCHK-85] _ = x[IBSRDWROPCNT-85]
_ = x[IBS_FETCH_CTLX-86] _ = x[IBSRIPINVALIDCHK-86]
_ = x[IBS_OPDATA4-87] _ = x[IBS_FETCH_CTLX-87]
_ = x[IBS_OPFUSE-88] _ = x[IBS_OPDATA4-88]
_ = x[IBS_PREVENTHOST-89] _ = x[IBS_OPFUSE-89]
_ = x[IBS_ZEN4-90] _ = x[IBS_PREVENTHOST-90]
_ = x[IDPRED_CTRL-91] _ = x[IBS_ZEN4-91]
_ = x[INT_WBINVD-92] _ = x[IDPRED_CTRL-92]
_ = x[INVLPGB-93] _ = x[INT_WBINVD-93]
_ = x[KEYLOCKER-94] _ = x[INVLPGB-94]
_ = x[KEYLOCKERW-95] _ = x[KEYLOCKER-95]
_ = x[LAHF-96] _ = x[KEYLOCKERW-96]
_ = x[LAM-97] _ = x[LAHF-97]
_ = x[LBRVIRT-98] _ = x[LAM-98]
_ = x[LZCNT-99] _ = x[LBRVIRT-99]
_ = x[MCAOVERFLOW-100] _ = x[LZCNT-100]
_ = x[MCDT_NO-101] _ = x[MCAOVERFLOW-101]
_ = x[MCOMMIT-102] _ = x[MCDT_NO-102]
_ = x[MD_CLEAR-103] _ = x[MCOMMIT-103]
_ = x[MMX-104] _ = x[MD_CLEAR-104]
_ = x[MMXEXT-105] _ = x[MMX-105]
_ = x[MOVBE-106] _ = x[MMXEXT-106]
_ = x[MOVDIR64B-107] _ = x[MOVBE-107]
_ = x[MOVDIRI-108] _ = x[MOVDIR64B-108]
_ = x[MOVSB_ZL-109] _ = x[MOVDIRI-109]
_ = x[MOVU-110] _ = x[MOVSB_ZL-110]
_ = x[MPX-111] _ = x[MOVU-111]
_ = x[MSRIRC-112] _ = x[MPX-112]
_ = x[MSRLIST-113] _ = x[MSRIRC-113]
_ = x[MSR_PAGEFLUSH-114] _ = x[MSRLIST-114]
_ = x[NRIPS-115] _ = x[MSR_PAGEFLUSH-115]
_ = x[NX-116] _ = x[NRIPS-116]
_ = x[OSXSAVE-117] _ = x[NX-117]
_ = x[PCONFIG-118] _ = x[OSXSAVE-118]
_ = x[POPCNT-119] _ = x[PCONFIG-119]
_ = x[PPIN-120] _ = x[POPCNT-120]
_ = x[PREFETCHI-121] _ = x[PPIN-121]
_ = x[PSFD-122] _ = x[PREFETCHI-122]
_ = x[RDPRU-123] _ = x[PSFD-123]
_ = x[RDRAND-124] _ = x[RDPRU-124]
_ = x[RDSEED-125] _ = x[RDRAND-125]
_ = x[RDTSCP-126] _ = x[RDSEED-126]
_ = x[RRSBA_CTRL-127] _ = x[RDTSCP-127]
_ = x[RTM-128] _ = x[RRSBA_CTRL-128]
_ = x[RTM_ALWAYS_ABORT-129] _ = x[RTM-129]
_ = x[SERIALIZE-130] _ = x[RTM_ALWAYS_ABORT-130]
_ = x[SEV-131] _ = x[SBPB-131]
_ = x[SEV_64BIT-132] _ = x[SERIALIZE-132]
_ = x[SEV_ALTERNATIVE-133] _ = x[SEV-133]
_ = x[SEV_DEBUGSWAP-134] _ = x[SEV_64BIT-134]
_ = x[SEV_ES-135] _ = x[SEV_ALTERNATIVE-135]
_ = x[SEV_RESTRICTED-136] _ = x[SEV_DEBUGSWAP-136]
_ = x[SEV_SNP-137] _ = x[SEV_ES-137]
_ = x[SGX-138] _ = x[SEV_RESTRICTED-138]
_ = x[SGXLC-139] _ = x[SEV_SNP-139]
_ = x[SHA-140] _ = x[SGX-140]
_ = x[SME-141] _ = x[SGXLC-141]
_ = x[SME_COHERENT-142] _ = x[SHA-142]
_ = x[SPEC_CTRL_SSBD-143] _ = x[SME-143]
_ = x[SRBDS_CTRL-144] _ = x[SME_COHERENT-144]
_ = x[SSE-145] _ = x[SPEC_CTRL_SSBD-145]
_ = x[SSE2-146] _ = x[SRBDS_CTRL-146]
_ = x[SSE3-147] _ = x[SRSO_MSR_FIX-147]
_ = x[SSE4-148] _ = x[SRSO_NO-148]
_ = x[SSE42-149] _ = x[SRSO_USER_KERNEL_NO-149]
_ = x[SSE4A-150] _ = x[SSE-150]
_ = x[SSSE3-151] _ = x[SSE2-151]
_ = x[STIBP-152] _ = x[SSE3-152]
_ = x[STIBP_ALWAYSON-153] _ = x[SSE4-153]
_ = x[STOSB_SHORT-154] _ = x[SSE42-154]
_ = x[SUCCOR-155] _ = x[SSE4A-155]
_ = x[SVM-156] _ = x[SSSE3-156]
_ = x[SVMDA-157] _ = x[STIBP-157]
_ = x[SVMFBASID-158] _ = x[STIBP_ALWAYSON-158]
_ = x[SVML-159] _ = x[STOSB_SHORT-159]
_ = x[SVMNP-160] _ = x[SUCCOR-160]
_ = x[SVMPF-161] _ = x[SVM-161]
_ = x[SVMPFT-162] _ = x[SVMDA-162]
_ = x[SYSCALL-163] _ = x[SVMFBASID-163]
_ = x[SYSEE-164] _ = x[SVML-164]
_ = x[TBM-165] _ = x[SVMNP-165]
_ = x[TDX_GUEST-166] _ = x[SVMPF-166]
_ = x[TLB_FLUSH_NESTED-167] _ = x[SVMPFT-167]
_ = x[TME-168] _ = x[SYSCALL-168]
_ = x[TOPEXT-169] _ = x[SYSEE-169]
_ = x[TSCRATEMSR-170] _ = x[TBM-170]
_ = x[TSXLDTRK-171] _ = x[TDX_GUEST-171]
_ = x[VAES-172] _ = x[TLB_FLUSH_NESTED-172]
_ = x[VMCBCLEAN-173] _ = x[TME-173]
_ = x[VMPL-174] _ = x[TOPEXT-174]
_ = x[VMSA_REGPROT-175] _ = x[TSCRATEMSR-175]
_ = x[VMX-176] _ = x[TSXLDTRK-176]
_ = x[VPCLMULQDQ-177] _ = x[VAES-177]
_ = x[VTE-178] _ = x[VMCBCLEAN-178]
_ = x[WAITPKG-179] _ = x[VMPL-179]
_ = x[WBNOINVD-180] _ = x[VMSA_REGPROT-180]
_ = x[WRMSRNS-181] _ = x[VMX-181]
_ = x[X87-182] _ = x[VPCLMULQDQ-182]
_ = x[XGETBV1-183] _ = x[VTE-183]
_ = x[XOP-184] _ = x[WAITPKG-184]
_ = x[XSAVE-185] _ = x[WBNOINVD-185]
_ = x[XSAVEC-186] _ = x[WRMSRNS-186]
_ = x[XSAVEOPT-187] _ = x[X87-187]
_ = x[XSAVES-188] _ = x[XGETBV1-188]
_ = x[AESARM-189] _ = x[XOP-189]
_ = x[ARMCPUID-190] _ = x[XSAVE-190]
_ = x[ASIMD-191] _ = x[XSAVEC-191]
_ = x[ASIMDDP-192] _ = x[XSAVEOPT-192]
_ = x[ASIMDHP-193] _ = x[XSAVES-193]
_ = x[ASIMDRDM-194] _ = x[AESARM-194]
_ = x[ATOMICS-195] _ = x[ARMCPUID-195]
_ = x[CRC32-196] _ = x[ASIMD-196]
_ = x[DCPOP-197] _ = x[ASIMDDP-197]
_ = x[EVTSTRM-198] _ = x[ASIMDHP-198]
_ = x[FCMA-199] _ = x[ASIMDRDM-199]
_ = x[FP-200] _ = x[ATOMICS-200]
_ = x[FPHP-201] _ = x[CRC32-201]
_ = x[GPA-202] _ = x[DCPOP-202]
_ = x[JSCVT-203] _ = x[EVTSTRM-203]
_ = x[LRCPC-204] _ = x[FCMA-204]
_ = x[PMULL-205] _ = x[FP-205]
_ = x[SHA1-206] _ = x[FPHP-206]
_ = x[SHA2-207] _ = x[GPA-207]
_ = x[SHA3-208] _ = x[JSCVT-208]
_ = x[SHA512-209] _ = x[LRCPC-209]
_ = x[SM3-210] _ = x[PMULL-210]
_ = x[SM4-211] _ = x[SHA1-211]
_ = x[SVE-212] _ = x[SHA2-212]
_ = x[lastID-213] _ = x[SHA3-213]
_ = x[SHA512-214]
_ = x[SM3-215]
_ = x[SM4-216]
_ = x[SVE-217]
_ = x[lastID-218]
_ = x[firstID-0] _ = x[firstID-0]
} }
const _FeatureID_name = "firstIDADXAESNIAMD3DNOWAMD3DNOWEXTAMXBF16AMXFP16AMXINT8AMXTILEAPX_FAVXAVX10AVX10_128AVX10_256AVX10_512AVX2AVX512BF16AVX512BITALGAVX512BWAVX512CDAVX512DQAVX512ERAVX512FAVX512FP16AVX512IFMAAVX512PFAVX512VBMIAVX512VBMI2AVX512VLAVX512VNNIAVX512VP2INTERSECTAVX512VPOPCNTDQAVXIFMAAVXNECONVERTAVXSLOWAVXVNNIAVXVNNIINT8BHI_CTRLBMI1BMI2CETIBTCETSSCLDEMOTECLMULCLZEROCMOVCMPCCXADDCMPSB_SCADBS_SHORTCMPXCHG8CPBOOSTCPPCCX16EFER_LMSLE_UNSENQCMDERMSF16CFLUSH_L1DFMA3FMA4FP128FP256FSRMFXSRFXSROPTGFNIHLEHRESETHTTHWAHYBRID_CPUHYPERVISORIA32_ARCH_CAPIA32_CORE_CAPIBPBIBRSIBRS_PREFERREDIBRS_PROVIDES_SMPIBSIBSBRNTRGTIBSFETCHSAMIBSFFVIBSOPCNTIBSOPCNTEXTIBSOPSAMIBSRDWROPCNTIBSRIPINVALIDCHKIBS_FETCH_CTLXIBS_OPDATA4IBS_OPFUSEIBS_PREVENTHOSTIBS_ZEN4IDPRED_CTRLINT_WBINVDINVLPGBKEYLOCKERKEYLOCKERWLAHFLAMLBRVIRTLZCNTMCAOVERFLOWMCDT_NOMCOMMITMD_CLEARMMXMMXEXTMOVBEMOVDIR64BMOVDIRIMOVSB_ZLMOVUMPXMSRIRCMSRLISTMSR_PAGEFLUSHNRIPSNXOSXSAVEPCONFIGPOPCNTPPINPREFETCHIPSFDRDPRURDRANDRDSEEDRDTSCPRRSBA_CTRLRTMRTM_ALWAYS_ABORTSERIALIZESEVSEV_64BITSEV_ALTERNATIVESEV_DEBUGSWAPSEV_ESSEV_RESTRICTEDSEV_SNPSGXSGXLCSHASMESME_COHERENTSPEC_CTRL_SSBDSRBDS_CTRLSSESSE2SSE3SSE4SSE42SSE4ASSSE3STIBPSTIBP_ALWAYSONSTOSB_SHORTSUCCORSVMSVMDASVMFBASIDSVMLSVMNPSVMPFSVMPFTSYSCALLSYSEETBMTDX_GUESTTLB_FLUSH_NESTEDTMETOPEXTTSCRATEMSRTSXLDTRKVAESVMCBCLEANVMPLVMSA_REGPROTVMXVPCLMULQDQVTEWAITPKGWBNOINVDWRMSRNSX87XGETBV1XOPXSAVEXSAVECXSAVEOPTXSAVESAESARMARMCPUIDASIMDASIMDDPASIMDHPASIMDRDMATOMICSCRC32DCPOPEVTSTRMFCMAFPFPHPGPAJSCVTLRCPCPMULLSHA1SHA2SHA3SHA512SM3SM4SVElastID" const _FeatureID_name = "firstIDADXAESNIAMD3DNOWAMD3DNOWEXTAMXBF16AMXFP16AMXINT8AMXTILEAPX_FAVXAVX10AVX10_128AVX10_256AVX10_512AVX2AVX512BF16AVX512BITALGAVX512BWAVX512CDAVX512DQAVX512ERAVX512FAVX512FP16AVX512IFMAAVX512PFAVX512VBMIAVX512VBMI2AVX512VLAVX512VNNIAVX512VP2INTERSECTAVX512VPOPCNTDQAVXIFMAAVXNECONVERTAVXSLOWAVXVNNIAVXVNNIINT8BHI_CTRLBMI1BMI2CETIBTCETSSCLDEMOTECLMULCLZEROCMOVCMPCCXADDCMPSB_SCADBS_SHORTCMPXCHG8CPBOOSTCPPCCX16EFER_LMSLE_UNSENQCMDERMSF16CFLUSH_L1DFMA3FMA4FP128FP256FSRMFXSRFXSROPTGFNIHLEHRESETHTTHWAHYBRID_CPUHYPERVISORIA32_ARCH_CAPIA32_CORE_CAPIBPBIBPB_BRTYPEIBRSIBRS_PREFERREDIBRS_PROVIDES_SMPIBSIBSBRNTRGTIBSFETCHSAMIBSFFVIBSOPCNTIBSOPCNTEXTIBSOPSAMIBSRDWROPCNTIBSRIPINVALIDCHKIBS_FETCH_CTLXIBS_OPDATA4IBS_OPFUSEIBS_PREVENTHOSTIBS_ZEN4IDPRED_CTRLINT_WBINVDINVLPGBKEYLOCKERKEYLOCKERWLAHFLAMLBRVIRTLZCNTMCAOVERFLOWMCDT_NOMCOMMITMD_CLEARMMXMMXEXTMOVBEMOVDIR64BMOVDIRIMOVSB_ZLMOVUMPXMSRIRCMSRLISTMSR_PAGEFLUSHNRIPSNXOSXSAVEPCONFIGPOPCNTPPINPREFETCHIPSFDRDPRURDRANDRDSEEDRDTSCPRRSBA_CTRLRTMRTM_ALWAYS_ABORTSBPBSERIALIZESEVSEV_64BITSEV_ALTERNATIVESEV_DEBUGSWAPSEV_ESSEV_RESTRICTEDSEV_SNPSGXSGXLCSHASMESME_COHERENTSPEC_CTRL_SSBDSRBDS_CTRLSRSO_MSR_FIXSRSO_NOSRSO_USER_KERNEL_NOSSESSE2SSE3SSE4SSE42SSE4ASSSE3STIBPSTIBP_ALWAYSONSTOSB_SHORTSUCCORSVMSVMDASVMFBASIDSVMLSVMNPSVMPFSVMPFTSYSCALLSYSEETBMTDX_GUESTTLB_FLUSH_NESTEDTMETOPEXTTSCRATEMSRTSXLDTRKVAESVMCBCLEANVMPLVMSA_REGPROTVMXVPCLMULQDQVTEWAITPKGWBNOINVDWRMSRNSX87XGETBV1XOPXSAVEXSAVECXSAVEOPTXSAVESAESARMARMCPUIDASIMDASIMDDPASIMDHPASIMDRDMATOMICSCRC32DCPOPEVTSTRMFCMAFPFPHPGPAJSCVTLRCPCPMULLSHA1SHA2SHA3SHA512SM3SM4SVElastID"
var _FeatureID_index = [...]uint16{0, 7, 10, 15, 23, 34, 41, 48, 55, 62, 67, 70, 75, 84, 93, 102, 106, 116, 128, 136, 144, 152, 160, 167, 177, 187, 195, 205, 216, 224, 234, 252, 267, 274, 286, 293, 300, 311, 319, 323, 327, 333, 338, 346, 351, 357, 361, 370, 388, 396, 403, 407, 411, 425, 431, 435, 439, 448, 452, 456, 461, 466, 470, 474, 481, 485, 488, 494, 497, 500, 510, 520, 533, 546, 550, 554, 568, 585, 588, 598, 609, 615, 623, 634, 642, 654, 670, 684, 695, 705, 720, 728, 739, 749, 756, 765, 775, 779, 782, 789, 794, 805, 812, 819, 827, 830, 836, 841, 850, 857, 865, 869, 872, 878, 885, 898, 903, 905, 912, 919, 925, 929, 938, 942, 947, 953, 959, 965, 975, 978, 994, 1003, 1006, 1015, 1030, 1043, 1049, 1063, 1070, 1073, 1078, 1081, 1084, 1096, 1110, 1120, 1123, 1127, 1131, 1135, 1140, 1145, 1150, 1155, 1169, 1180, 1186, 1189, 1194, 1203, 1207, 1212, 1217, 1223, 1230, 1235, 1238, 1247, 1263, 1266, 1272, 1282, 1290, 1294, 1303, 1307, 1319, 1322, 1332, 1335, 1342, 1350, 1357, 1360, 1367, 1370, 1375, 1381, 1389, 1395, 1401, 1409, 1414, 1421, 1428, 1436, 1443, 1448, 1453, 1460, 1464, 1466, 1470, 1473, 1478, 1483, 1488, 1492, 1496, 1500, 1506, 1509, 1512, 1515, 1521} var _FeatureID_index = [...]uint16{0, 7, 10, 15, 23, 34, 41, 48, 55, 62, 67, 70, 75, 84, 93, 102, 106, 116, 128, 136, 144, 152, 160, 167, 177, 187, 195, 205, 216, 224, 234, 252, 267, 274, 286, 293, 300, 311, 319, 323, 327, 333, 338, 346, 351, 357, 361, 370, 388, 396, 403, 407, 411, 425, 431, 435, 439, 448, 452, 456, 461, 466, 470, 474, 481, 485, 488, 494, 497, 500, 510, 520, 533, 546, 550, 561, 565, 579, 596, 599, 609, 620, 626, 634, 645, 653, 665, 681, 695, 706, 716, 731, 739, 750, 760, 767, 776, 786, 790, 793, 800, 805, 816, 823, 830, 838, 841, 847, 852, 861, 868, 876, 880, 883, 889, 896, 909, 914, 916, 923, 930, 936, 940, 949, 953, 958, 964, 970, 976, 986, 989, 1005, 1009, 1018, 1021, 1030, 1045, 1058, 1064, 1078, 1085, 1088, 1093, 1096, 1099, 1111, 1125, 1135, 1147, 1154, 1173, 1176, 1180, 1184, 1188, 1193, 1198, 1203, 1208, 1222, 1233, 1239, 1242, 1247, 1256, 1260, 1265, 1270, 1276, 1283, 1288, 1291, 1300, 1316, 1319, 1325, 1335, 1343, 1347, 1356, 1360, 1372, 1375, 1385, 1388, 1395, 1403, 1410, 1413, 1420, 1423, 1428, 1434, 1442, 1448, 1454, 1462, 1467, 1474, 1481, 1489, 1496, 1501, 1506, 1513, 1517, 1519, 1523, 1526, 1531, 1536, 1541, 1545, 1549, 1553, 1559, 1562, 1565, 1568, 1574}
func (i FeatureID) String() string { func (i FeatureID) String() string {
if i < 0 || i >= FeatureID(len(_FeatureID_index)-1) { if i < 0 || i >= FeatureID(len(_FeatureID_index)-1) {

View File

@ -10,3 +10,4 @@
vendor/ vendor/
/removecomments /removecomments
/snake2camel

View File

@ -2,21 +2,34 @@
**A parser for URNs**. **A parser for URNs**.
> As seen on [RFC 2141](https://tools.ietf.org/html/rfc2141#ref-1). > As seen on [RFC 2141](https://datatracker.ietf.org/doc/html/rfc2141), [RFC 7643](https://datatracker.ietf.org/doc/html/rfc7643#section-10), and on [RFC 8141](https://datatracker.ietf.org/doc/html/rfc8141).
[API documentation](https://godoc.org/github.com/leodido/go-urn). [API documentation](https://godoc.org/github.com/leodido/go-urn).
Starting with version 1.3 this library also supports [RFC 7643 SCIM URNs](https://datatracker.ietf.org/doc/html/rfc7643#section-10).
Starting with version 1.4 this library also supports [RFC 8141 URNs (2017)](https://datatracker.ietf.org/doc/html/rfc8141).
## Installation ## Installation
``` ```
go get github.com/leodido/go-urn go get github.com/leodido/go-urn
``` ```
## Features
1. RFC 2141 URNs parsing (default)
2. RFC 8141 URNs parsing (supersedes RFC 2141)
3. RFC 7643 SCIM URNs parsing
4. Normalization as per RFCs
5. Lexical equivalence as per RFCs
6. Precise, fine-grained errors
## Performances ## Performances
This implementation results to be really fast. This implementation results to be really fast.
Usually below ½ microsecond on my machine<sup>[1](#mymachine)</sup>. Usually below 400 ns on my machine<sup>[1](#mymachine)</sup>.
Notice it also performs, while parsing: Notice it also performs, while parsing:
@ -24,35 +37,36 @@ Notice it also performs, while parsing:
2. specific-string normalization 2. specific-string normalization
``` ```
ok/00/urn:a:b______________________________________/-4 20000000 265 ns/op 182 B/op 6 allocs/op ok/00/urn:a:b______________________________________/-10 51372006 109.0 ns/op 275 B/op 3 allocs/op
ok/01/URN:foo:a123,456_____________________________/-4 30000000 296 ns/op 200 B/op 6 allocs/op ok/01/URN:foo:a123,456_____________________________/-10 36024072 160.8 ns/op 296 B/op 6 allocs/op
ok/02/urn:foo:a123%2c456___________________________/-4 20000000 331 ns/op 208 B/op 6 allocs/op ok/02/urn:foo:a123%2C456___________________________/-10 31901007 188.4 ns/op 320 B/op 7 allocs/op
ok/03/urn:ietf:params:scim:schemas:core:2.0:User___/-4 20000000 430 ns/op 280 B/op 6 allocs/op ok/03/urn:ietf:params:scim:schemas:core:2.0:User___/-10 22736756 266.6 ns/op 376 B/op 6 allocs/op
ok/04/urn:ietf:params:scim:schemas:extension:enterp/-4 20000000 411 ns/op 312 B/op 6 allocs/op ok/04/urn:ietf:params:scim:schemas:extension:enterp/-10 18291859 335.2 ns/op 408 B/op 6 allocs/op
ok/05/urn:ietf:params:scim:schemas:extension:enterp/-4 20000000 472 ns/op 344 B/op 6 allocs/op ok/05/urn:ietf:params:scim:schemas:extension:enterp/-10 15283087 379.4 ns/op 440 B/op 6 allocs/op
ok/06/urn:burnout:nss______________________________/-4 30000000 257 ns/op 192 B/op 6 allocs/op ok/06/urn:burnout:nss______________________________/-10 39407593 155.1 ns/op 288 B/op 6 allocs/op
ok/07/urn:abcdefghilmnopqrstuvzabcdefghilm:x_______/-4 20000000 375 ns/op 213 B/op 6 allocs/op ok/07/urn:abcdefghilmnopqrstuvzabcdefghilm:x_______/-10 27832718 211.4 ns/op 307 B/op 4 allocs/op
ok/08/urn:urnurnurn:urn____________________________/-4 30000000 265 ns/op 197 B/op 6 allocs/op ok/08/urn:urnurnurn:urn____________________________/-10 33269596 168.1 ns/op 293 B/op 6 allocs/op
ok/09/urn:ciao:@!=%2c(xyz)+a,b.*@g=$_'_____________/-4 20000000 307 ns/op 248 B/op 6 allocs/op ok/09/urn:ciao:!!*_________________________________/-10 41100675 148.8 ns/op 288 B/op 6 allocs/op
ok/10/URN:x:abc%1dz%2f%3az_________________________/-4 30000000 259 ns/op 212 B/op 6 allocs/op ok/10/urn:ciao:=@__________________________________/-10 37214253 149.7 ns/op 284 B/op 6 allocs/op
no/11/URN:-xxx:x___________________________________/-4 20000000 445 ns/op 320 B/op 6 allocs/op ok/11/urn:ciao:@!=%2C(xyz)+a,b.*@g=$_'_____________/-10 26534240 229.8 ns/op 336 B/op 7 allocs/op
no/12/urn::colon:nss_______________________________/-4 20000000 461 ns/op 320 B/op 6 allocs/op ok/12/URN:x:abc%1Dz%2F%3az_________________________/-10 28166396 211.8 ns/op 336 B/op 7 allocs/op
no/13/urn:abcdefghilmnopqrstuvzabcdefghilmn:specifi/-4 10000000 660 ns/op 320 B/op 6 allocs/op no/13/URN:---xxx:x_________________________________/-10 23635159 255.6 ns/op 419 B/op 5 allocs/op
no/14/URN:a!?:x____________________________________/-4 20000000 507 ns/op 320 B/op 6 allocs/op no/14/urn::colon:nss_______________________________/-10 23594779 258.4 ns/op 419 B/op 5 allocs/op
no/15/urn:urn:NSS__________________________________/-4 20000000 429 ns/op 288 B/op 6 allocs/op no/15/URN:@,:x_____________________________________/-10 23742535 261.5 ns/op 419 B/op 5 allocs/op
no/16/urn:white_space:NSS__________________________/-4 20000000 482 ns/op 320 B/op 6 allocs/op no/16/URN:URN:NSS__________________________________/-10 27432714 223.3 ns/op 371 B/op 5 allocs/op
no/17/urn:concat:no_spaces_________________________/-4 20000000 539 ns/op 328 B/op 7 allocs/op no/17/urn:UrN:NSS__________________________________/-10 26922117 224.9 ns/op 371 B/op 5 allocs/op
no/18/urn:a:/______________________________________/-4 20000000 470 ns/op 320 B/op 7 allocs/op no/18/urn:a:%______________________________________/-10 24926733 224.6 ns/op 371 B/op 5 allocs/op
no/19/urn:UrN:NSS__________________________________/-4 20000000 399 ns/op 288 B/op 6 allocs/op no/19/urn:urn:NSS__________________________________/-10 27652641 220.7 ns/op 371 B/op 5 allocs/op
``` ```
--- * <a name="mymachine">[1]</a>: Apple M1 Pro
* <a name="mymachine">[1]</a>: Intel Core i7-7600U CPU @ 2.80GHz
---
## Example ## Example
For more examples take a look at the [examples file](examples_test.go).
```go ```go
package main package main
@ -64,6 +78,35 @@ import (
func main() { func main() {
var uid = "URN:foo:a123,456" var uid = "URN:foo:a123,456"
// Parse the input string as a RFC 2141 URN only
u, e := urn.NewMachine().Parse(uid)
if e != nil {
fmt.Errorf(err)
return
}
fmt.Println(u.ID)
fmt.Println(u.SS)
// Output:
// foo
// a123,456
}
```
```go
package main
import (
"fmt"
"github.com/leodido/go-urn"
)
func main() {
var uid = "URN:foo:a123,456"
// Parse the input string as a RFC 2141 URN only
u, ok := urn.Parse([]byte(uid)) u, ok := urn.Parse([]byte(uid))
if !ok { if !ok {
panic("error parsing urn") panic("error parsing urn")
@ -78,4 +121,33 @@ func main() {
} }
``` ```
[![Analytics](https://ga-beacon.appspot.com/UA-49657176-1/go-urn?flat)](https://github.com/igrigorik/ga-beacon) ```go
package main
import (
"fmt"
"github.com/leodido/go-urn"
)
func main() {
input := "urn:ietf:params:scim:api:messages:2.0:ListResponse"
// Parsing the input string as a RFC 7643 SCIM URN
u, ok := urn.Parse([]byte(input), urn.WithParsingMode(urn.RFC7643Only))
if !ok {
panic("error parsing urn")
}
fmt.Println(u.IsSCIM())
scim := u.SCIM()
fmt.Println(scim.Type.String())
fmt.Println(scim.Name)
fmt.Println(scim.Other)
// Output:
// true
// api
// messages
// 2.0:ListResponse
}
```

10
vendor/github.com/leodido/go-urn/kind.go generated vendored Normal file
View File

@ -0,0 +1,10 @@
package urn
type Kind int
const (
NONE Kind = iota
RFC2141
RFC7643
RFC8141
)

File diff suppressed because it is too large Load Diff

View File

@ -2,15 +2,28 @@ package urn
import ( import (
"fmt" "fmt"
scimschema "github.com/leodido/go-urn/scim/schema"
) )
var ( var (
errPrefix = "expecting the prefix to be the \"urn\" string (whatever case) [col %d]" errPrefix = "expecting the prefix to be the \"urn\" string (whatever case) [col %d]"
errIdentifier = "expecting the identifier to be string (1..31 alnum chars, also containing dashes but not at its start) [col %d]" errIdentifier = "expecting the identifier to be string (1..31 alnum chars, also containing dashes but not at its beginning) [col %d]"
errSpecificString = "expecting the specific string to be a string containing alnum, hex, or others ([()+,-.:=@;$_!*']) chars [col %d]" errSpecificString = "expecting the specific string to be a string containing alnum, hex, or others ([()+,-.:=@;$_!*']) chars [col %d]"
errNoUrnWithinID = "expecting the identifier to not contain the \"urn\" reserved string [col %d]" errNoUrnWithinID = "expecting the identifier to not contain the \"urn\" reserved string [col %d]"
errHex = "expecting the specific string hex chars to be well-formed (%%alnum{2}) [col %d]" errHex = "expecting the percent encoded chars to be well-formed (%%alnum{2}) [col %d]"
errParse = "parsing error [col %d]" errSCIMNamespace = "expecing the SCIM namespace identifier (ietf:params:scim) [col %d]"
errSCIMType = "expecting a correct SCIM type (schemas, api, param) [col %d]"
errSCIMName = "expecting one or more alnum char in the SCIM name part [col %d]"
errSCIMOther = "expecting a well-formed other SCIM part [col %d]"
errSCIMOtherIncomplete = "expecting a not empty SCIM other part after colon [col %d]"
err8141InformalID = "informal URN namespace must be in the form urn-[1-9][0-9] [col %d]"
err8141SpecificString = "expecting the specific string to contain alnum, hex, or others ([~&()+,-.:=@;$_!*'] or [/?] not in first position) chars [col %d]"
err8141Identifier = "expecting the indentifier to be a string with (length 2 to 32 chars) containing alnum (or dashes) not starting or ending with a dash [col %d]"
err8141RComponentStart = "expecting only one r-component (starting with the ?+ sequence) [col %d]"
err8141QComponentStart = "expecting only one q-component (starting with the ?= sequence) [col %d]"
err8141MalformedRComp = "expecting a non-empty r-component containing alnum, hex, or others ([~&()+,-.:=@;$_!*'] or [/?] but not at its beginning) [col %d]"
err8141MalformedQComp = "expecting a non-empty q-component containing alnum, hex, or others ([~&()+,-.:=@;$_!*'] or [/?] but not at its beginning) [col %d]"
) )
%%{ %%{
@ -24,25 +37,42 @@ action mark {
} }
action tolower { action tolower {
m.tolower = append(m.tolower, m.p - m.pb) // List of positions in the buffer to later lowercase
output.tolower = append(output.tolower, m.p - m.pb)
} }
action set_pre { action set_pre {
output.prefix = string(m.text()) output.prefix = string(m.text())
} }
action throw_pre_urn_err {
if m.parsingMode != RFC8141Only {
// Throw an error when:
// - we are entering here matching the the prefix in the namespace identifier part
// - looking ahead (3 chars) we find a colon
if pos := m.p + 3; pos < m.pe && m.data[pos] == 58 && output.prefix != "" {
m.err = fmt.Errorf(errNoUrnWithinID, pos)
fhold;
fgoto fail;
}
}
}
action set_nid { action set_nid {
output.ID = string(m.text()) output.ID = string(m.text())
} }
action set_nss { action set_nss {
raw := m.text() output.SS = string(m.text())
output.SS = string(raw)
// Iterate upper letters lowering them // Iterate upper letters lowering them
for _, i := range m.tolower { for _, i := range output.tolower {
raw[i] = raw[i] + 32 m.data[m.pb+i] = m.data[m.pb+i] + 32
}
output.norm = string(m.text())
// Revert the buffer to the original
for _, i := range output.tolower {
m.data[m.pb+i] = m.data[m.pb+i] - 32
} }
output.norm = string(raw)
} }
action err_pre { action err_pre {
@ -70,20 +100,20 @@ action err_urn {
} }
action err_hex { action err_hex {
m.err = fmt.Errorf(errHex, m.p) if m.parsingMode == RFC2141Only || m.parsingMode == RFC8141Only {
fhold; m.err = fmt.Errorf(errHex, m.p)
fgoto fail; fhold;
fgoto fail;
}
} }
action err_parse { action base_type {
m.err = fmt.Errorf(errParse, m.p) output.kind = RFC2141;
fhold;
fgoto fail;
} }
pre = ([uU][rR][nN] @err(err_pre)) >mark %set_pre; pre = ([uU] @err(err_pre) [rR] @err(err_pre) [nN] @err(err_pre)) >mark >throw_pre_urn_err %set_pre;
nid = (alnum >mark (alnum | '-'){0,31}) %set_nid; nid = (alnum >mark (alnum | '-'){0,31}) $err(err_nid) %set_nid;
hex = '%' (digit | lower | upper >tolower){2} $err(err_hex); hex = '%' (digit | lower | upper >tolower){2} $err(err_hex);
@ -91,9 +121,179 @@ sss = (alnum | [()+,\-.:=@;$_!*']);
nss = (sss | hex)+ $err(err_nss); nss = (sss | hex)+ $err(err_nss);
nid_not_urn = (nid - pre %err(err_urn));
urn = pre ':' @err(err_pre) (nid_not_urn ':' nss >mark %set_nss) %eof(base_type);
### SCIM BEG
action err_scim_nid {
m.err = fmt.Errorf(errSCIMNamespace, m.p)
fhold;
fgoto fail;
}
action err_scim_type {
m.err = fmt.Errorf(errSCIMType, m.p)
fhold;
fgoto fail;
}
action err_scim_name {
m.err = fmt.Errorf(errSCIMName, m.p)
fhold;
fgoto fail;
}
action err_scim_other {
if m.p == m.pe {
m.err = fmt.Errorf(errSCIMOtherIncomplete, m.p-1)
} else {
m.err = fmt.Errorf(errSCIMOther, m.p)
}
fhold;
fgoto fail;
}
action scim_type {
output.kind = RFC7643;
}
action create_scim {
output.scim = &SCIM{};
}
action set_scim_type {
output.scim.Type = scimschema.TypeFromString(string(m.text()))
}
action mark_scim_name {
output.scim.pos = m.p
}
action set_scim_name {
output.scim.Name = string(m.data[output.scim.pos:m.p])
}
action mark_scim_other {
output.scim.pos = m.p
}
action set_scim_other {
output.scim.Other = string(m.data[output.scim.pos:m.p])
}
scim_nid = 'ietf:params:scim' >mark %set_nid %create_scim $err(err_scim_nid);
scim_other = ':' (sss | hex)+ >mark_scim_other %set_scim_other $err(err_scim_other);
scim_name = (alnum)+ >mark_scim_name %set_scim_name $err(err_scim_name);
scim_type = ('schemas' | 'api' | 'param') >mark %set_scim_type $err(err_scim_type);
scim_only := pre ':' @err(err_pre) (scim_nid ':' scim_type ':' scim_name scim_other? %set_nss) %eof(scim_type);
### SCIM END
### 8141 BEG
action err_nss_8141 {
m.err = fmt.Errorf(err8141SpecificString, m.p)
fhold;
fgoto fail;
}
action err_nid_8141 {
m.err = fmt.Errorf(err8141Identifier, m.p)
fhold;
fgoto fail;
}
action rfc8141_type {
output.kind = RFC8141;
}
action set_r_component {
output.rComponent = string(m.text())
}
action set_q_component {
output.qComponent = string(m.text())
}
action set_f_component {
output.fComponent = string(m.text())
}
action informal_nid_match {
fhold;
m.err = fmt.Errorf(err8141InformalID, m.p);
fgoto fail;
}
action mark_r_start {
if output.rStart {
m.err = fmt.Errorf(err8141RComponentStart, m.p)
fhold;
fgoto fail;
}
output.rStart = true
}
action mark_q_start {
if output.qStart {
m.err = fmt.Errorf(err8141QComponentStart, m.p)
fhold;
fgoto fail;
}
output.qStart = true
}
action err_malformed_r_component {
m.err = fmt.Errorf(err8141MalformedRComp, m.p)
fhold;
fgoto fail;
}
action err_malformed_q_component {
m.err = fmt.Errorf(err8141MalformedQComp, m.p)
fhold;
fgoto fail;
}
pchar = (sss | '~' | '&' | hex);
component = pchar (pchar | '/' | '?')*;
r_start = ('?+') %mark_r_start;
r_component = r_start <: (r_start | component)+ $err(err_malformed_r_component) >mark %set_r_component;
q_start = ('?=') %mark_q_start;
q_component = q_start <: (q_start | component)+ $err(err_malformed_q_component) >mark %set_q_component;
rq_components = (r_component :>> q_component? | q_component);
fragment = (pchar | '/' | '?')*;
f_component = '#' fragment >mark %set_f_component;
nss_rfc8141 = (pchar >mark (pchar | '/')*) $err(err_nss_8141) %set_nss;
nid_rfc8141 = (alnum >mark (alnum | '-'){0,30} alnum) $err(err_nid_8141) %set_nid;
informal_id = pre ('-' [a-zA-z0] %to(informal_nid_match));
nid_rfc8141_not_urn = (nid_rfc8141 - informal_id?);
rfc8141_only := pre ':' @err(err_pre) nid_rfc8141_not_urn ':' nss_rfc8141 rq_components? f_component? %eof(rfc8141_type);
### 8141 END
fail := (any - [\n\r])* @err{ fgoto main; }; fail := (any - [\n\r])* @err{ fgoto main; };
main := (pre ':' (nid - pre %err(err_urn)) $err(err_nid) ':' nss >mark %set_nss) $err(err_parse); main := urn;
}%% }%%
@ -103,6 +303,7 @@ main := (pre ':' (nid - pre %err(err_urn)) $err(err_nid) ':' nss >mark %set_nss)
type Machine interface { type Machine interface {
Error() error Error() error
Parse(input []byte) (*URN, error) Parse(input []byte) (*URN, error)
WithParsingMode(ParsingMode)
} }
type machine struct { type machine struct {
@ -110,12 +311,24 @@ type machine struct {
cs int cs int
p, pe, eof, pb int p, pe, eof, pb int
err error err error
tolower []int startParsingAt int
parsingMode ParsingMode
parsingModeSet bool
} }
// NewMachine creates a new FSM able to parse RFC 2141 strings. // NewMachine creates a new FSM able to parse RFC 2141 strings.
func NewMachine() Machine { func NewMachine(options ...Option) Machine {
m := &machine{} m := &machine{
parsingModeSet: false,
}
for _, o := range options {
o(m)
}
// Set default parsing mode
if !m.parsingModeSet {
m.WithParsingMode(DefaultParsingMode)
}
%% access m.; %% access m.;
%% variable p m.p; %% variable p m.p;
@ -137,7 +350,7 @@ func (m *machine) text() []byte {
return m.data[m.pb:m.p] return m.data[m.pb:m.p]
} }
// Parse parses the input byte array as a RFC 2141 string. // Parse parses the input byte array as a RFC 2141 or RFC7643 string.
func (m *machine) Parse(input []byte) (*URN, error) { func (m *machine) Parse(input []byte) (*URN, error) {
m.data = input m.data = input
m.p = 0 m.p = 0
@ -145,10 +358,11 @@ func (m *machine) Parse(input []byte) (*URN, error) {
m.pe = len(input) m.pe = len(input)
m.eof = len(input) m.eof = len(input)
m.err = nil m.err = nil
m.tolower = []int{} m.cs = m.startParsingAt
output := &URN{} output := &URN{
tolower: []int{},
}
%% write init;
%% write exec; %% write exec;
if m.cs < first_final || m.cs == en_fail { if m.cs < first_final || m.cs == en_fail {
@ -157,3 +371,16 @@ func (m *machine) Parse(input []byte) (*URN, error) {
return output, nil return output, nil
} }
func (m *machine) WithParsingMode(x ParsingMode) {
m.parsingMode = x
switch m.parsingMode {
case RFC2141Only:
m.startParsingAt = en_main
case RFC8141Only:
m.startParsingAt = en_rfc8141_only
case RFC7643Only:
m.startParsingAt = en_scim_only
}
m.parsingModeSet = true
}

View File

@ -15,18 +15,24 @@ clean:
.PHONY: images .PHONY: images
images: docs/urn.png images: docs/urn.png
.PHONY: snake2camel
snake2camel:
@cd ./tools/snake2camel; go build -o ../../snake2camel .
.PHONY: removecomments .PHONY: removecomments
removecomments: removecomments:
@cd ./tools/removecomments; go build -o ../../removecomments . @cd ./tools/removecomments; go build -o ../../removecomments .
machine.go: machine.go.rl machine.go: machine.go.rl
machine.go: snake2camel
machine.go: removecomments machine.go: removecomments
machine.go: machine.go:
$(RAGEL) -Z -G2 -e -o $@ $< $(RAGEL) -Z -G1 -e -o $@ $<
@./removecomments $@ @./removecomments $@
$(MAKE) -s file=$@ snake2camel @./snake2camel $@
$(GOFMT) $@ $(GOFMT) $@
docs/urn.dot: machine.go.rl docs/urn.dot: machine.go.rl
@ -43,11 +49,3 @@ bench: *_test.go machine.go
.PHONY: tests .PHONY: tests
tests: *_test.go tests: *_test.go
$(GO_TEST) ./... $(GO_TEST) ./...
.PHONY: snake2camel
snake2camel:
@awk -i inplace '{ \
while ( match($$0, /(.*)([a-z]+[0-9]*)_([a-zA-Z0-9])(.*)/, cap) ) \
$$0 = cap[1] cap[2] toupper(cap[3]) cap[4]; \
print \
}' $(file)

9
vendor/github.com/leodido/go-urn/options.go generated vendored Normal file
View File

@ -0,0 +1,9 @@
package urn
type Option func(Machine)
func WithParsingMode(mode ParsingMode) Option {
return func(m Machine) {
m.WithParsingMode(mode)
}
}

12
vendor/github.com/leodido/go-urn/parsing_mode.go generated vendored Normal file
View File

@ -0,0 +1,12 @@
package urn
type ParsingMode int
const (
Default ParsingMode = iota
RFC2141Only
RFC7643Only
RFC8141Only
)
const DefaultParsingMode = RFC2141Only

48
vendor/github.com/leodido/go-urn/scim.go generated vendored Normal file
View File

@ -0,0 +1,48 @@
package urn
import (
"encoding/json"
"fmt"
scimschema "github.com/leodido/go-urn/scim/schema"
)
const errInvalidSCIMURN = "invalid SCIM URN: %s"
type SCIM struct {
Type scimschema.Type
Name string
Other string
pos int
}
func (s SCIM) MarshalJSON() ([]byte, error) {
return json.Marshal(s.String())
}
func (s *SCIM) UnmarshalJSON(bytes []byte) error {
var str string
if err := json.Unmarshal(bytes, &str); err != nil {
return err
}
// Parse as SCIM
value, ok := Parse([]byte(str), WithParsingMode(RFC7643Only))
if !ok {
return fmt.Errorf(errInvalidSCIMURN, str)
}
if value.RFC() != RFC7643 {
return fmt.Errorf(errInvalidSCIMURN, str)
}
*s = *value.SCIM()
return nil
}
func (s *SCIM) String() string {
ret := fmt.Sprintf("urn:ietf:params:scim:%s:%s", s.Type.String(), s.Name)
if s.Other != "" {
ret += fmt.Sprintf(":%s", s.Other)
}
return ret
}

36
vendor/github.com/leodido/go-urn/scim/schema/type.go generated vendored Normal file
View File

@ -0,0 +1,36 @@
package scimschema
type Type int
const (
Unsupported Type = iota
Schemas
API
Param
)
func (t Type) String() string {
switch t {
case Schemas:
return "schemas"
case API:
return "api"
case Param:
return "param"
}
return ""
}
func TypeFromString(input string) Type {
switch input {
case "schemas":
return Schemas
case "api":
return API
case "param":
return Param
}
return Unsupported
}

View File

@ -16,10 +16,18 @@ const errInvalidURN = "invalid URN: %s"
// //
// Details at https://tools.ietf.org/html/rfc2141. // Details at https://tools.ietf.org/html/rfc2141.
type URN struct { type URN struct {
prefix string // Static prefix. Equal to "urn" when empty. prefix string // Static prefix. Equal to "urn" when empty.
ID string // Namespace identifier ID string // Namespace identifier (NID)
SS string // Namespace specific string SS string // Namespace specific string (NSS)
norm string // Normalized namespace specific string norm string // Normalized namespace specific string
kind Kind
scim *SCIM
rComponent string // RFC8141
qComponent string // RFC8141
fComponent string // RFC8141
rStart bool // RFC8141
qStart bool // RFC8141
tolower []int
} }
// Normalize turns the receiving URN into its norm version. // Normalize turns the receiving URN into its norm version.
@ -30,12 +38,21 @@ func (u *URN) Normalize() *URN {
prefix: "urn", prefix: "urn",
ID: strings.ToLower(u.ID), ID: strings.ToLower(u.ID),
SS: u.norm, SS: u.norm,
// rComponent: u.rComponent,
// qComponent: u.qComponent,
// fComponent: u.fComponent,
} }
} }
// Equal checks the lexical equivalence of the current URN with another one. // Equal checks the lexical equivalence of the current URN with another one.
func (u *URN) Equal(x *URN) bool { func (u *URN) Equal(x *URN) bool {
return *u.Normalize() == *x.Normalize() if x == nil {
return false
}
nu := u.Normalize()
nx := x.Normalize()
return nu.prefix == nx.prefix && nu.ID == nx.ID && nu.SS == nx.SS
} }
// String reassembles the URN into a valid URN string. // String reassembles the URN into a valid URN string.
@ -51,14 +68,23 @@ func (u *URN) String() string {
res += "urn" res += "urn"
} }
res += u.prefix + ":" + u.ID + ":" + u.SS res += u.prefix + ":" + u.ID + ":" + u.SS
if u.rComponent != "" {
res += "?+" + u.rComponent
}
if u.qComponent != "" {
res += "?=" + u.qComponent
}
if u.fComponent != "" {
res += "#" + u.fComponent
}
} }
return res return res
} }
// Parse is responsible to create an URN instance from a byte array matching the correct URN syntax. // Parse is responsible to create an URN instance from a byte array matching the correct URN syntax (RFC 2141).
func Parse(u []byte) (*URN, bool) { func Parse(u []byte, options ...Option) (*URN, bool) {
urn, err := NewMachine().Parse(u) urn, err := NewMachine(options...).Parse(u)
if err != nil { if err != nil {
return nil, false return nil, false
} }
@ -71,7 +97,7 @@ func (u URN) MarshalJSON() ([]byte, error) {
return json.Marshal(u.String()) return json.Marshal(u.String())
} }
// MarshalJSON unmarshals a URN from JSON string form (e.g. `"urn:oid:1.2.3.4"`). // UnmarshalJSON unmarshals a URN from JSON string form (e.g. `"urn:oid:1.2.3.4"`).
func (u *URN) UnmarshalJSON(bytes []byte) error { func (u *URN) UnmarshalJSON(bytes []byte) error {
var str string var str string
if err := json.Unmarshal(bytes, &str); err != nil { if err := json.Unmarshal(bytes, &str); err != nil {
@ -82,5 +108,34 @@ func (u *URN) UnmarshalJSON(bytes []byte) error {
} else { } else {
*u = *value *u = *value
} }
return nil return nil
} }
func (u *URN) IsSCIM() bool {
return u.kind == RFC7643
}
func (u *URN) SCIM() *SCIM {
if u.kind != RFC7643 {
return nil
}
return u.scim
}
func (u *URN) RFC() Kind {
return u.kind
}
func (u *URN) FComponent() string {
return u.fComponent
}
func (u *URN) QComponent() string {
return u.qComponent
}
func (u *URN) RComponent() string {
return u.rComponent
}

30
vendor/github.com/leodido/go-urn/urn8141.go generated vendored Normal file
View File

@ -0,0 +1,30 @@
package urn
import (
"encoding/json"
"fmt"
)
const errInvalidURN8141 = "invalid URN per RFC 8141: %s"
type URN8141 struct {
*URN
}
func (u URN8141) MarshalJSON() ([]byte, error) {
return json.Marshal(u.String())
}
func (u *URN8141) UnmarshalJSON(bytes []byte) error {
var str string
if err := json.Unmarshal(bytes, &str); err != nil {
return err
}
if value, ok := Parse([]byte(str), WithParsingMode(RFC8141Only)); !ok {
return fmt.Errorf(errInvalidURN8141, str)
} else {
*u = URN8141{value}
}
return nil
}

View File

@ -1,201 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -1 +0,0 @@
Copyright 2012 Matt T. Proud (matt.proud@gmail.com)

View File

@ -1 +0,0 @@
cover.dat

View File

@ -1,7 +0,0 @@
all:
cover:
go test -cover -v -coverprofile=cover.dat ./...
go tool cover -func cover.dat
.PHONY: cover

View File

@ -1,81 +0,0 @@
// Copyright 2013 Matt T. Proud
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package pbutil
import (
"encoding/binary"
"errors"
"io"
"google.golang.org/protobuf/proto"
)
// TODO: Give error package name prefix in next minor release.
var errInvalidVarint = errors.New("invalid varint32 encountered")
// ReadDelimited decodes a message from the provided length-delimited stream,
// where the length is encoded as 32-bit varint prefix to the message body.
// It returns the total number of bytes read and any applicable error. This is
// roughly equivalent to the companion Java API's
// MessageLite#parseDelimitedFrom. As per the reader contract, this function
// calls r.Read repeatedly as required until exactly one message including its
// prefix is read and decoded (or an error has occurred). The function never
// reads more bytes from the stream than required. The function never returns
// an error if a message has been read and decoded correctly, even if the end
// of the stream has been reached in doing so. In that case, any subsequent
// calls return (0, io.EOF).
func ReadDelimited(r io.Reader, m proto.Message) (n int, err error) {
// TODO: Consider allowing the caller to specify a decode buffer in the
// next major version.
// TODO: Consider using error wrapping to annotate error state in pass-
// through cases in the next minor version.
// Per AbstractParser#parsePartialDelimitedFrom with
// CodedInputStream#readRawVarint32.
var headerBuf [binary.MaxVarintLen32]byte
var bytesRead, varIntBytes int
var messageLength uint64
for varIntBytes == 0 { // i.e. no varint has been decoded yet.
if bytesRead >= len(headerBuf) {
return bytesRead, errInvalidVarint
}
// We have to read byte by byte here to avoid reading more bytes
// than required. Each read byte is appended to what we have
// read before.
newBytesRead, err := r.Read(headerBuf[bytesRead : bytesRead+1])
if newBytesRead == 0 {
if err != nil {
return bytesRead, err
}
// A Reader should not return (0, nil); but if it does, it should
// be treated as no-op according to the Reader contract.
continue
}
bytesRead += newBytesRead
// Now present everything read so far to the varint decoder and
// see if a varint can be decoded already.
messageLength, varIntBytes = binary.Uvarint(headerBuf[:bytesRead])
}
messageBuf := make([]byte, messageLength)
newBytesRead, err := io.ReadFull(r, messageBuf)
bytesRead += newBytesRead
if err != nil {
return bytesRead, err
}
return bytesRead, proto.Unmarshal(messageBuf, m)
}

View File

@ -1,16 +0,0 @@
// Copyright 2013 Matt T. Proud
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package pbutil provides record length-delimited Protocol Buffer streaming.
package pbutil

View File

@ -1,49 +0,0 @@
// Copyright 2013 Matt T. Proud
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package pbutil
import (
"encoding/binary"
"io"
"google.golang.org/protobuf/proto"
)
// WriteDelimited encodes and dumps a message to the provided writer prefixed
// with a 32-bit varint indicating the length of the encoded message, producing
// a length-delimited record stream, which can be used to chain together
// encoded messages of the same type together in a file. It returns the total
// number of bytes written and any applicable error. This is roughly
// equivalent to the companion Java API's MessageLite#writeDelimitedTo.
func WriteDelimited(w io.Writer, m proto.Message) (n int, err error) {
// TODO: Consider allowing the caller to specify an encode buffer in the
// next major version.
buffer, err := proto.Marshal(m)
if err != nil {
return 0, err
}
var buf [binary.MaxVarintLen32]byte
encodedLength := binary.PutUvarint(buf[:], uint64(len(buffer)))
sync, err := w.Write(buf[:encodedLength])
if err != nil {
return sync, err
}
n, err = w.Write(buffer)
return n + sync, err
}

View File

@ -82,6 +82,7 @@ A not-so-up-to-date-list-that-may-be-actually-current:
* https://dnscheck.tools/ * https://dnscheck.tools/
* https://github.com/egbakou/domainverifier * https://github.com/egbakou/domainverifier
* https://github.com/semihalev/sdns * https://github.com/semihalev/sdns
* https://github.com/wintbiit/NineDNS
Send pull request if you want to be listed here. Send pull request if you want to be listed here.
@ -125,6 +126,7 @@ Example programs can be found in the `github.com/miekg/exdns` repository.
*all of them* *all of them*
* 103{4,5} - DNS standard * 103{4,5} - DNS standard
* 1183 - ISDN, X25 and other deprecated records
* 1348 - NSAP record (removed the record) * 1348 - NSAP record (removed the record)
* 1982 - Serial Arithmetic * 1982 - Serial Arithmetic
* 1876 - LOC record * 1876 - LOC record

View File

@ -160,7 +160,7 @@ func parseKey(r io.Reader, file string) (map[string]string, error) {
k = l.token k = l.token
case zValue: case zValue:
if k == "" { if k == "" {
return nil, &ParseError{file, "no private key seen", l} return nil, &ParseError{file: file, err: "no private key seen", lex: l}
} }
m[strings.ToLower(k)] = l.token m[strings.ToLower(k)] = l.token

View File

@ -116,7 +116,7 @@ func (r *generateReader) parseError(msg string, end int) *ParseError {
l.token = r.s[r.si-1 : end] l.token = r.s[r.si-1 : end]
l.column += r.si // l.column starts one zBLANK before r.s l.column += r.si // l.column starts one zBLANK before r.s
return &ParseError{r.file, msg, l} return &ParseError{file: r.file, err: msg, lex: l}
} }
func (r *generateReader) Read(p []byte) (int, error) { func (r *generateReader) Read(p []byte) (int, error) {

View File

@ -84,7 +84,7 @@ Fetch:
err := r.Data.Parse(text) err := r.Data.Parse(text)
if err != nil { if err != nil {
return &ParseError{"", err.Error(), l} return &ParseError{wrappedErr: err, lex: l}
} }
return nil return nil

103
vendor/github.com/miekg/dns/scan.go generated vendored
View File

@ -4,7 +4,9 @@ import (
"bufio" "bufio"
"fmt" "fmt"
"io" "io"
"io/fs"
"os" "os"
"path"
"path/filepath" "path/filepath"
"strconv" "strconv"
"strings" "strings"
@ -64,20 +66,26 @@ const (
// ParseError is a parsing error. It contains the parse error and the location in the io.Reader // ParseError is a parsing error. It contains the parse error and the location in the io.Reader
// where the error occurred. // where the error occurred.
type ParseError struct { type ParseError struct {
file string file string
err string err string
lex lex wrappedErr error
lex lex
} }
func (e *ParseError) Error() (s string) { func (e *ParseError) Error() (s string) {
if e.file != "" { if e.file != "" {
s = e.file + ": " s = e.file + ": "
} }
if e.err == "" && e.wrappedErr != nil {
e.err = e.wrappedErr.Error()
}
s += "dns: " + e.err + ": " + strconv.QuoteToASCII(e.lex.token) + " at line: " + s += "dns: " + e.err + ": " + strconv.QuoteToASCII(e.lex.token) + " at line: " +
strconv.Itoa(e.lex.line) + ":" + strconv.Itoa(e.lex.column) strconv.Itoa(e.lex.line) + ":" + strconv.Itoa(e.lex.column)
return return
} }
func (e *ParseError) Unwrap() error { return e.wrappedErr }
type lex struct { type lex struct {
token string // text of the token token string // text of the token
err bool // when true, token text has lexer error err bool // when true, token text has lexer error
@ -168,8 +176,9 @@ type ZoneParser struct {
// sub is used to parse $INCLUDE files and $GENERATE directives. // sub is used to parse $INCLUDE files and $GENERATE directives.
// Next, by calling subNext, forwards the resulting RRs from this // Next, by calling subNext, forwards the resulting RRs from this
// sub parser to the calling code. // sub parser to the calling code.
sub *ZoneParser sub *ZoneParser
osFile *os.File r io.Reader
fsys fs.FS
includeDepth uint8 includeDepth uint8
@ -188,7 +197,7 @@ func NewZoneParser(r io.Reader, origin, file string) *ZoneParser {
if origin != "" { if origin != "" {
origin = Fqdn(origin) origin = Fqdn(origin)
if _, ok := IsDomainName(origin); !ok { if _, ok := IsDomainName(origin); !ok {
pe = &ParseError{file, "bad initial origin name", lex{}} pe = &ParseError{file: file, err: "bad initial origin name"}
} }
} }
@ -220,6 +229,24 @@ func (zp *ZoneParser) SetIncludeAllowed(v bool) {
zp.includeAllowed = v zp.includeAllowed = v
} }
// SetIncludeFS provides an [fs.FS] to use when looking for the target of
// $INCLUDE directives. ($INCLUDE must still be enabled separately by calling
// [ZoneParser.SetIncludeAllowed].) If fsys is nil, [os.Open] will be used.
//
// When fsys is an on-disk FS, the ability of $INCLUDE to reach files from
// outside its root directory depends upon the FS implementation. For
// instance, [os.DirFS] will refuse to open paths like "../../etc/passwd",
// however it will still follow links which may point anywhere on the system.
//
// FS paths are slash-separated on all systems, even Windows. $INCLUDE paths
// containing other characters such as backslash and colon may be accepted as
// valid, but those characters will never be interpreted by an FS
// implementation as path element separators. See [fs.ValidPath] for more
// details.
func (zp *ZoneParser) SetIncludeFS(fsys fs.FS) {
zp.fsys = fsys
}
// Err returns the first non-EOF error that was encountered by the // Err returns the first non-EOF error that was encountered by the
// ZoneParser. // ZoneParser.
func (zp *ZoneParser) Err() error { func (zp *ZoneParser) Err() error {
@ -237,7 +264,7 @@ func (zp *ZoneParser) Err() error {
} }
func (zp *ZoneParser) setParseError(err string, l lex) (RR, bool) { func (zp *ZoneParser) setParseError(err string, l lex) (RR, bool) {
zp.parseErr = &ParseError{zp.file, err, l} zp.parseErr = &ParseError{file: zp.file, err: err, lex: l}
return nil, false return nil, false
} }
@ -260,9 +287,11 @@ func (zp *ZoneParser) subNext() (RR, bool) {
return rr, true return rr, true
} }
if zp.sub.osFile != nil { if zp.sub.r != nil {
zp.sub.osFile.Close() if c, ok := zp.sub.r.(io.Closer); ok {
zp.sub.osFile = nil c.Close()
}
zp.sub.r = nil
} }
if zp.sub.Err() != nil { if zp.sub.Err() != nil {
@ -402,24 +431,44 @@ func (zp *ZoneParser) Next() (RR, bool) {
// Start with the new file // Start with the new file
includePath := l.token includePath := l.token
if !filepath.IsAbs(includePath) { var r1 io.Reader
includePath = filepath.Join(filepath.Dir(zp.file), includePath) var e1 error
} if zp.fsys != nil {
// fs.FS always uses / as separator, even on Windows, so use
r1, e1 := os.Open(includePath) // path instead of filepath here:
if e1 != nil { if !path.IsAbs(includePath) {
var as string includePath = path.Join(path.Dir(zp.file), includePath)
if !filepath.IsAbs(l.token) {
as = fmt.Sprintf(" as `%s'", includePath)
} }
msg := fmt.Sprintf("failed to open `%s'%s: %v", l.token, as, e1) // os.DirFS, and probably others, expect all paths to be
return zp.setParseError(msg, l) // relative, so clean the path and remove leading / if
// present:
includePath = strings.TrimLeft(path.Clean(includePath), "/")
r1, e1 = zp.fsys.Open(includePath)
} else {
if !filepath.IsAbs(includePath) {
includePath = filepath.Join(filepath.Dir(zp.file), includePath)
}
r1, e1 = os.Open(includePath)
}
if e1 != nil {
var as string
if includePath != l.token {
as = fmt.Sprintf(" as `%s'", includePath)
}
zp.parseErr = &ParseError{
file: zp.file,
wrappedErr: fmt.Errorf("failed to open `%s'%s: %w", l.token, as, e1),
lex: l,
}
return nil, false
} }
zp.sub = NewZoneParser(r1, neworigin, includePath) zp.sub = NewZoneParser(r1, neworigin, includePath)
zp.sub.defttl, zp.sub.includeDepth, zp.sub.osFile = zp.defttl, zp.includeDepth+1, r1 zp.sub.defttl, zp.sub.includeDepth, zp.sub.r = zp.defttl, zp.includeDepth+1, r1
zp.sub.SetIncludeAllowed(true) zp.sub.SetIncludeAllowed(true)
zp.sub.SetIncludeFS(zp.fsys)
return zp.subNext() return zp.subNext()
case zExpectDirTTLBl: case zExpectDirTTLBl:
if l.value != zBlank { if l.value != zBlank {
@ -1326,12 +1375,12 @@ func slurpRemainder(c *zlexer) *ParseError {
case zBlank: case zBlank:
l, _ = c.Next() l, _ = c.Next()
if l.value != zNewline && l.value != zEOF { if l.value != zNewline && l.value != zEOF {
return &ParseError{"", "garbage after rdata", l} return &ParseError{err: "garbage after rdata", lex: l}
} }
case zNewline: case zNewline:
case zEOF: case zEOF:
default: default:
return &ParseError{"", "garbage after rdata", l} return &ParseError{err: "garbage after rdata", lex: l}
} }
return nil return nil
} }
@ -1340,16 +1389,16 @@ func slurpRemainder(c *zlexer) *ParseError {
// Used for NID and L64 record. // Used for NID and L64 record.
func stringToNodeID(l lex) (uint64, *ParseError) { func stringToNodeID(l lex) (uint64, *ParseError) {
if len(l.token) < 19 { if len(l.token) < 19 {
return 0, &ParseError{l.token, "bad NID/L64 NodeID/Locator64", l} return 0, &ParseError{file: l.token, err: "bad NID/L64 NodeID/Locator64", lex: l}
} }
// There must be three colons at fixes positions, if not its a parse error // There must be three colons at fixes positions, if not its a parse error
if l.token[4] != ':' && l.token[9] != ':' && l.token[14] != ':' { if l.token[4] != ':' && l.token[9] != ':' && l.token[14] != ':' {
return 0, &ParseError{l.token, "bad NID/L64 NodeID/Locator64", l} return 0, &ParseError{file: l.token, err: "bad NID/L64 NodeID/Locator64", lex: l}
} }
s := l.token[0:4] + l.token[5:9] + l.token[10:14] + l.token[15:19] s := l.token[0:4] + l.token[5:9] + l.token[10:14] + l.token[15:19]
u, err := strconv.ParseUint(s, 16, 64) u, err := strconv.ParseUint(s, 16, 64)
if err != nil { if err != nil {
return 0, &ParseError{l.token, "bad NID/L64 NodeID/Locator64", l} return 0, &ParseError{file: l.token, err: "bad NID/L64 NodeID/Locator64", lex: l}
} }
return u, nil return u, nil
} }

File diff suppressed because it is too large Load Diff

20
vendor/github.com/miekg/dns/svcb.go generated vendored
View File

@ -85,7 +85,7 @@ func (rr *SVCB) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next() l, _ := c.Next()
i, e := strconv.ParseUint(l.token, 10, 16) i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err { if e != nil || l.err {
return &ParseError{l.token, "bad SVCB priority", l} return &ParseError{file: l.token, err: "bad SVCB priority", lex: l}
} }
rr.Priority = uint16(i) rr.Priority = uint16(i)
@ -95,7 +95,7 @@ func (rr *SVCB) parse(c *zlexer, o string) *ParseError {
name, nameOk := toAbsoluteName(l.token, o) name, nameOk := toAbsoluteName(l.token, o)
if l.err || !nameOk { if l.err || !nameOk {
return &ParseError{l.token, "bad SVCB Target", l} return &ParseError{file: l.token, err: "bad SVCB Target", lex: l}
} }
rr.Target = name rr.Target = name
@ -111,7 +111,7 @@ func (rr *SVCB) parse(c *zlexer, o string) *ParseError {
if !canHaveNextKey { if !canHaveNextKey {
// The key we can now read was probably meant to be // The key we can now read was probably meant to be
// a part of the last value. // a part of the last value.
return &ParseError{l.token, "bad SVCB value quotation", l} return &ParseError{file: l.token, err: "bad SVCB value quotation", lex: l}
} }
// In key=value pairs, value does not have to be quoted unless value // In key=value pairs, value does not have to be quoted unless value
@ -124,7 +124,7 @@ func (rr *SVCB) parse(c *zlexer, o string) *ParseError {
// Key with no value and no equality sign // Key with no value and no equality sign
key = l.token key = l.token
} else if idx == 0 { } else if idx == 0 {
return &ParseError{l.token, "bad SVCB key", l} return &ParseError{file: l.token, err: "bad SVCB key", lex: l}
} else { } else {
key, value = l.token[:idx], l.token[idx+1:] key, value = l.token[:idx], l.token[idx+1:]
@ -144,30 +144,30 @@ func (rr *SVCB) parse(c *zlexer, o string) *ParseError {
value = l.token value = l.token
l, _ = c.Next() l, _ = c.Next()
if l.value != zQuote { if l.value != zQuote {
return &ParseError{l.token, "SVCB unterminated value", l} return &ParseError{file: l.token, err: "SVCB unterminated value", lex: l}
} }
case zQuote: case zQuote:
// There's nothing in double quotes. // There's nothing in double quotes.
default: default:
return &ParseError{l.token, "bad SVCB value", l} return &ParseError{file: l.token, err: "bad SVCB value", lex: l}
} }
} }
} }
} }
kv := makeSVCBKeyValue(svcbStringToKey(key)) kv := makeSVCBKeyValue(svcbStringToKey(key))
if kv == nil { if kv == nil {
return &ParseError{l.token, "bad SVCB key", l} return &ParseError{file: l.token, err: "bad SVCB key", lex: l}
} }
if err := kv.parse(value); err != nil { if err := kv.parse(value); err != nil {
return &ParseError{l.token, err.Error(), l} return &ParseError{file: l.token, wrappedErr: err, lex: l}
} }
xs = append(xs, kv) xs = append(xs, kv)
case zQuote: case zQuote:
return &ParseError{l.token, "SVCB key can't contain double quotes", l} return &ParseError{file: l.token, err: "SVCB key can't contain double quotes", lex: l}
case zBlank: case zBlank:
canHaveNextKey = true canHaveNextKey = true
default: default:
return &ParseError{l.token, "bad SVCB values", l} return &ParseError{file: l.token, err: "bad SVCB values", lex: l}
} }
l, _ = c.Next() l, _ = c.Next()
} }

28
vendor/github.com/miekg/dns/types.go generated vendored
View File

@ -135,8 +135,8 @@ const (
RcodeNXRrset = 8 // NXRRSet - RR Set that should exist does not [DNS Update] RcodeNXRrset = 8 // NXRRSet - RR Set that should exist does not [DNS Update]
RcodeNotAuth = 9 // NotAuth - Server Not Authoritative for zone [DNS Update] RcodeNotAuth = 9 // NotAuth - Server Not Authoritative for zone [DNS Update]
RcodeNotZone = 10 // NotZone - Name not contained in zone [DNS Update/TSIG] RcodeNotZone = 10 // NotZone - Name not contained in zone [DNS Update/TSIG]
RcodeBadSig = 16 // BADSIG - TSIG Signature Failure [TSIG] RcodeBadSig = 16 // BADSIG - TSIG Signature Failure [TSIG] https://www.rfc-editor.org/rfc/rfc6895.html#section-2.3
RcodeBadVers = 16 // BADVERS - Bad OPT Version [EDNS0] RcodeBadVers = 16 // BADVERS - Bad OPT Version [EDNS0] https://www.rfc-editor.org/rfc/rfc6895.html#section-2.3
RcodeBadKey = 17 // BADKEY - Key not recognized [TSIG] RcodeBadKey = 17 // BADKEY - Key not recognized [TSIG]
RcodeBadTime = 18 // BADTIME - Signature out of time window [TSIG] RcodeBadTime = 18 // BADTIME - Signature out of time window [TSIG]
RcodeBadMode = 19 // BADMODE - Bad TKEY Mode [TKEY] RcodeBadMode = 19 // BADMODE - Bad TKEY Mode [TKEY]
@ -402,6 +402,17 @@ func (rr *X25) String() string {
return rr.Hdr.String() + rr.PSDNAddress return rr.Hdr.String() + rr.PSDNAddress
} }
// ISDN RR. See RFC 1183, Section 3.2.
type ISDN struct {
Hdr RR_Header
Address string
SubAddress string
}
func (rr *ISDN) String() string {
return rr.Hdr.String() + sprintTxt([]string{rr.Address, rr.SubAddress})
}
// RT RR. See RFC 1183, Section 3.3. // RT RR. See RFC 1183, Section 3.3.
type RT struct { type RT struct {
Hdr RR_Header Hdr RR_Header
@ -786,7 +797,7 @@ func (rr *GPOS) String() string {
return rr.Hdr.String() + rr.Longitude + " " + rr.Latitude + " " + rr.Altitude return rr.Hdr.String() + rr.Longitude + " " + rr.Latitude + " " + rr.Altitude
} }
// LOC RR. See RFC RFC 1876. // LOC RR. See RFC 1876.
type LOC struct { type LOC struct {
Hdr RR_Header Hdr RR_Header
Version uint8 Version uint8
@ -898,6 +909,11 @@ func (rr *RRSIG) String() string {
return s return s
} }
// NXT RR. See RFC 2535.
type NXT struct {
NSEC
}
// NSEC RR. See RFC 4034 and RFC 3755. // NSEC RR. See RFC 4034 and RFC 3755.
type NSEC struct { type NSEC struct {
Hdr RR_Header Hdr RR_Header
@ -982,7 +998,7 @@ func (rr *TALINK) String() string {
sprintName(rr.PreviousName) + " " + sprintName(rr.NextName) sprintName(rr.PreviousName) + " " + sprintName(rr.NextName)
} }
// SSHFP RR. See RFC RFC 4255. // SSHFP RR. See RFC 4255.
type SSHFP struct { type SSHFP struct {
Hdr RR_Header Hdr RR_Header
Algorithm uint8 Algorithm uint8
@ -996,7 +1012,7 @@ func (rr *SSHFP) String() string {
" " + strings.ToUpper(rr.FingerPrint) " " + strings.ToUpper(rr.FingerPrint)
} }
// KEY RR. See RFC RFC 2535. // KEY RR. See RFC 2535.
type KEY struct { type KEY struct {
DNSKEY DNSKEY
} }
@ -1306,7 +1322,7 @@ type NINFO struct {
func (rr *NINFO) String() string { return rr.Hdr.String() + sprintTxt(rr.ZSData) } func (rr *NINFO) String() string { return rr.Hdr.String() + sprintTxt(rr.ZSData) }
// NID RR. See RFC RFC 6742. // NID RR. See RFC 6742.
type NID struct { type NID struct {
Hdr RR_Header Hdr RR_Header
Preference uint16 Preference uint16

View File

@ -3,7 +3,7 @@ package dns
import "fmt" import "fmt"
// Version is current version of this library. // Version is current version of this library.
var Version = v{1, 1, 57} var Version = v{1, 1, 58}
// v holds the version of this library. // v holds the version of this library.
type v struct { type v struct {

View File

@ -481,6 +481,21 @@ func (r1 *IPSECKEY) isDuplicate(_r2 RR) bool {
return true return true
} }
func (r1 *ISDN) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*ISDN)
if !ok {
return false
}
_ = r2
if r1.Address != r2.Address {
return false
}
if r1.SubAddress != r2.SubAddress {
return false
}
return true
}
func (r1 *KEY) isDuplicate(_r2 RR) bool { func (r1 *KEY) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*KEY) r2, ok := _r2.(*KEY)
if !ok { if !ok {
@ -871,6 +886,26 @@ func (r1 *NULL) isDuplicate(_r2 RR) bool {
return true return true
} }
func (r1 *NXT) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*NXT)
if !ok {
return false
}
_ = r2
if !isDuplicateName(r1.NextDomain, r2.NextDomain) {
return false
}
if len(r1.TypeBitMap) != len(r2.TypeBitMap) {
return false
}
for i := 0; i < len(r1.TypeBitMap); i++ {
if r1.TypeBitMap[i] != r2.TypeBitMap[i] {
return false
}
}
return true
}
func (r1 *OPENPGPKEY) isDuplicate(_r2 RR) bool { func (r1 *OPENPGPKEY) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*OPENPGPKEY) r2, ok := _r2.(*OPENPGPKEY)
if !ok { if !ok {

60
vendor/github.com/miekg/dns/zmsg.go generated vendored
View File

@ -372,6 +372,18 @@ func (rr *IPSECKEY) pack(msg []byte, off int, compression compressionMap, compre
return off, nil return off, nil
} }
func (rr *ISDN) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packString(rr.Address, msg, off)
if err != nil {
return off, err
}
off, err = packString(rr.SubAddress, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *KEY) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) { func (rr *KEY) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint16(rr.Flags, msg, off) off, err = packUint16(rr.Flags, msg, off)
if err != nil { if err != nil {
@ -694,6 +706,18 @@ func (rr *NULL) pack(msg []byte, off int, compression compressionMap, compress b
return off, nil return off, nil
} }
func (rr *NXT) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packDomainName(rr.NextDomain, msg, off, compression, false)
if err != nil {
return off, err
}
off, err = packDataNsec(rr.TypeBitMap, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *OPENPGPKEY) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) { func (rr *OPENPGPKEY) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packStringBase64(rr.PublicKey, msg, off) off, err = packStringBase64(rr.PublicKey, msg, off)
if err != nil { if err != nil {
@ -1746,6 +1770,24 @@ func (rr *IPSECKEY) unpack(msg []byte, off int) (off1 int, err error) {
return off, nil return off, nil
} }
func (rr *ISDN) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Address, off, err = unpackString(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.SubAddress, off, err = unpackString(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *KEY) unpack(msg []byte, off int) (off1 int, err error) { func (rr *KEY) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off rdStart := off
_ = rdStart _ = rdStart
@ -2224,6 +2266,24 @@ func (rr *NULL) unpack(msg []byte, off int) (off1 int, err error) {
return off, nil return off, nil
} }
func (rr *NXT) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.NextDomain, off, err = UnpackDomainName(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.TypeBitMap, off, err = unpackDataNsec(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *OPENPGPKEY) unpack(msg []byte, off int) (off1 int, err error) { func (rr *OPENPGPKEY) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off rdStart := off
_ = rdStart _ = rdStart

View File

@ -36,6 +36,7 @@ var TypeToRR = map[uint16]func() RR{
TypeHIP: func() RR { return new(HIP) }, TypeHIP: func() RR { return new(HIP) },
TypeHTTPS: func() RR { return new(HTTPS) }, TypeHTTPS: func() RR { return new(HTTPS) },
TypeIPSECKEY: func() RR { return new(IPSECKEY) }, TypeIPSECKEY: func() RR { return new(IPSECKEY) },
TypeISDN: func() RR { return new(ISDN) },
TypeKEY: func() RR { return new(KEY) }, TypeKEY: func() RR { return new(KEY) },
TypeKX: func() RR { return new(KX) }, TypeKX: func() RR { return new(KX) },
TypeL32: func() RR { return new(L32) }, TypeL32: func() RR { return new(L32) },
@ -59,6 +60,7 @@ var TypeToRR = map[uint16]func() RR{
TypeNSEC3: func() RR { return new(NSEC3) }, TypeNSEC3: func() RR { return new(NSEC3) },
TypeNSEC3PARAM: func() RR { return new(NSEC3PARAM) }, TypeNSEC3PARAM: func() RR { return new(NSEC3PARAM) },
TypeNULL: func() RR { return new(NULL) }, TypeNULL: func() RR { return new(NULL) },
TypeNXT: func() RR { return new(NXT) },
TypeOPENPGPKEY: func() RR { return new(OPENPGPKEY) }, TypeOPENPGPKEY: func() RR { return new(OPENPGPKEY) },
TypeOPT: func() RR { return new(OPT) }, TypeOPT: func() RR { return new(OPT) },
TypePTR: func() RR { return new(PTR) }, TypePTR: func() RR { return new(PTR) },
@ -204,6 +206,7 @@ func (rr *HINFO) Header() *RR_Header { return &rr.Hdr }
func (rr *HIP) Header() *RR_Header { return &rr.Hdr } func (rr *HIP) Header() *RR_Header { return &rr.Hdr }
func (rr *HTTPS) Header() *RR_Header { return &rr.Hdr } func (rr *HTTPS) Header() *RR_Header { return &rr.Hdr }
func (rr *IPSECKEY) Header() *RR_Header { return &rr.Hdr } func (rr *IPSECKEY) Header() *RR_Header { return &rr.Hdr }
func (rr *ISDN) Header() *RR_Header { return &rr.Hdr }
func (rr *KEY) Header() *RR_Header { return &rr.Hdr } func (rr *KEY) Header() *RR_Header { return &rr.Hdr }
func (rr *KX) Header() *RR_Header { return &rr.Hdr } func (rr *KX) Header() *RR_Header { return &rr.Hdr }
func (rr *L32) Header() *RR_Header { return &rr.Hdr } func (rr *L32) Header() *RR_Header { return &rr.Hdr }
@ -227,6 +230,7 @@ func (rr *NSEC) Header() *RR_Header { return &rr.Hdr }
func (rr *NSEC3) Header() *RR_Header { return &rr.Hdr } func (rr *NSEC3) Header() *RR_Header { return &rr.Hdr }
func (rr *NSEC3PARAM) Header() *RR_Header { return &rr.Hdr } func (rr *NSEC3PARAM) Header() *RR_Header { return &rr.Hdr }
func (rr *NULL) Header() *RR_Header { return &rr.Hdr } func (rr *NULL) Header() *RR_Header { return &rr.Hdr }
func (rr *NXT) Header() *RR_Header { return &rr.Hdr }
func (rr *OPENPGPKEY) Header() *RR_Header { return &rr.Hdr } func (rr *OPENPGPKEY) Header() *RR_Header { return &rr.Hdr }
func (rr *OPT) Header() *RR_Header { return &rr.Hdr } func (rr *OPT) Header() *RR_Header { return &rr.Hdr }
func (rr *PTR) Header() *RR_Header { return &rr.Hdr } func (rr *PTR) Header() *RR_Header { return &rr.Hdr }
@ -437,6 +441,13 @@ func (rr *IPSECKEY) len(off int, compression map[string]struct{}) int {
return l return l
} }
func (rr *ISDN) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += len(rr.Address) + 1
l += len(rr.SubAddress) + 1
return l
}
func (rr *KX) len(off int, compression map[string]struct{}) int { func (rr *KX) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len(off, compression)
l += 2 // Preference l += 2 // Preference
@ -966,6 +977,10 @@ func (rr *IPSECKEY) copy() RR {
} }
} }
func (rr *ISDN) copy() RR {
return &ISDN{rr.Hdr, rr.Address, rr.SubAddress}
}
func (rr *KEY) copy() RR { func (rr *KEY) copy() RR {
return &KEY{*rr.DNSKEY.copy().(*DNSKEY)} return &KEY{*rr.DNSKEY.copy().(*DNSKEY)}
} }
@ -1092,6 +1107,10 @@ func (rr *NULL) copy() RR {
return &NULL{rr.Hdr, rr.Data} return &NULL{rr.Hdr, rr.Data}
} }
func (rr *NXT) copy() RR {
return &NXT{*rr.NSEC.copy().(*NSEC)}
}
func (rr *OPENPGPKEY) copy() RR { func (rr *OPENPGPKEY) copy() RR {
return &OPENPGPKEY{rr.Hdr, rr.PublicKey} return &OPENPGPKEY{rr.Hdr, rr.PublicKey}
} }

1806
vendor/github.com/minio/minio-go/v7/CREDITS generated vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,201 @@
/*
* MinIO Go Library for Amazon S3 Compatible Cloud Storage
* Copyright 2020 MinIO, Inc.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package minio
import (
"context"
"encoding/xml"
"errors"
"net/http"
"net/url"
"strconv"
"time"
"github.com/minio/minio-go/v7/pkg/encrypt"
"github.com/minio/minio-go/v7/pkg/s3utils"
)
// ObjectAttributesOptions are options used for the GetObjectAttributes API
//
// - MaxParts
// How many parts the caller wants to be returned (default: 1000)
//
// - VersionID
// The object version you want to attributes for
//
// - PartNumberMarker
// the listing will start AFTER the part matching PartNumberMarker
//
// - ServerSideEncryption
// The server-side encryption algorithm used when storing this object in Minio
type ObjectAttributesOptions struct {
MaxParts int
VersionID string
PartNumberMarker int
ServerSideEncryption encrypt.ServerSide
}
// ObjectAttributes is the response object returned by the GetObjectAttributes API
//
// - VersionID
// The object version
//
// - LastModified
// The last time the object was modified
//
// - ObjectAttributesResponse
// Contains more information about the object
type ObjectAttributes struct {
VersionID string
LastModified time.Time
ObjectAttributesResponse
}
// ObjectAttributesResponse contains details returned by the GetObjectAttributes API
//
// Noteworthy fields:
//
// - ObjectParts.PartsCount
// Contains the total part count for the object (not the current response)
//
// - ObjectParts.PartNumberMarker
// Pagination of parts will begin at (but not include) PartNumberMarker
//
// - ObjectParts.NextPartNumberMarket
// The next PartNumberMarker to be used in order to continue pagination
//
// - ObjectParts.IsTruncated
// Indicates if the last part is included in the request (does not check if parts are missing from the start of the list, ONLY the end)
//
// - ObjectParts.MaxParts
// Reflects the MaxParts used by the caller or the default MaxParts value of the API
type ObjectAttributesResponse struct {
ETag string `xml:",omitempty"`
StorageClass string
ObjectSize int
Checksum struct {
ChecksumCRC32 string `xml:",omitempty"`
ChecksumCRC32C string `xml:",omitempty"`
ChecksumSHA1 string `xml:",omitempty"`
ChecksumSHA256 string `xml:",omitempty"`
}
ObjectParts struct {
PartsCount int
PartNumberMarker int
NextPartNumberMarker int
MaxParts int
IsTruncated bool
Parts []*ObjectAttributePart `xml:"Part"`
}
}
// ObjectAttributePart is used by ObjectAttributesResponse to describe an object part
type ObjectAttributePart struct {
ChecksumCRC32 string `xml:",omitempty"`
ChecksumCRC32C string `xml:",omitempty"`
ChecksumSHA1 string `xml:",omitempty"`
ChecksumSHA256 string `xml:",omitempty"`
PartNumber int
Size int
}
func (o *ObjectAttributes) parseResponse(resp *http.Response) (err error) {
mod, err := parseRFC7231Time(resp.Header.Get("Last-Modified"))
if err != nil {
return err
}
o.LastModified = mod
o.VersionID = resp.Header.Get(amzVersionID)
response := new(ObjectAttributesResponse)
if err := xml.NewDecoder(resp.Body).Decode(response); err != nil {
return err
}
o.ObjectAttributesResponse = *response
return
}
// GetObjectAttributes API combines HeadObject and ListParts.
// More details on usage can be found in the documentation for ObjectAttributesOptions{}
func (c *Client) GetObjectAttributes(ctx context.Context, bucketName, objectName string, opts ObjectAttributesOptions) (*ObjectAttributes, error) {
if err := s3utils.CheckValidBucketName(bucketName); err != nil {
return nil, err
}
if err := s3utils.CheckValidObjectName(objectName); err != nil {
return nil, err
}
urlValues := make(url.Values)
urlValues.Add("attributes", "")
if opts.VersionID != "" {
urlValues.Add("versionId", opts.VersionID)
}
headers := make(http.Header)
headers.Set(amzObjectAttributes, GetObjectAttributesTags)
if opts.PartNumberMarker > 0 {
headers.Set(amzPartNumberMarker, strconv.Itoa(opts.PartNumberMarker))
}
if opts.MaxParts > 0 {
headers.Set(amzMaxParts, strconv.Itoa(opts.MaxParts))
} else {
headers.Set(amzMaxParts, strconv.Itoa(GetObjectAttributesMaxParts))
}
if opts.ServerSideEncryption != nil {
opts.ServerSideEncryption.Marshal(headers)
}
resp, err := c.executeMethod(ctx, http.MethodGet, requestMetadata{
bucketName: bucketName,
objectName: objectName,
queryValues: urlValues,
contentSHA256Hex: emptySHA256Hex,
customHeader: headers,
})
if err != nil {
return nil, err
}
defer closeResponse(resp)
hasEtag := resp.Header.Get(ETag)
if hasEtag != "" {
return nil, errors.New("getObjectAttributes is not supported by the current endpoint version")
}
if resp.StatusCode != http.StatusOK {
ER := new(ErrorResponse)
if err := xml.NewDecoder(resp.Body).Decode(ER); err != nil {
return nil, err
}
return nil, *ER
}
OA := new(ObjectAttributes)
err = OA.parseResponse(resp)
if err != nil {
return nil, err
}
return OA, nil
}

View File

@ -435,7 +435,7 @@ func (c *Client) removeObjects(ctx context.Context, bucketName string, objectsCh
// Generate remove multi objects XML request // Generate remove multi objects XML request
removeBytes := generateRemoveMultiObjectsRequest(batch) removeBytes := generateRemoveMultiObjectsRequest(batch)
// Execute GET on bucket to list objects. // Execute POST on bucket to remove objects.
resp, err := c.executeMethod(ctx, http.MethodPost, requestMetadata{ resp, err := c.executeMethod(ctx, http.MethodPost, requestMetadata{
bucketName: bucketName, bucketName: bucketName,
queryValues: urlValues, queryValues: urlValues,

View File

@ -127,7 +127,7 @@ type Options struct {
// Global constants. // Global constants.
const ( const (
libraryName = "minio-go" libraryName = "minio-go"
libraryVersion = "v7.0.66" libraryVersion = "v7.0.67"
) )
// User Agent should always following the below style. // User Agent should always following the below style.
@ -234,7 +234,7 @@ func privateNew(endpoint string, opts *Options) (*Client, error) {
clnt.httpClient = &http.Client{ clnt.httpClient = &http.Client{
Jar: jar, Jar: jar,
Transport: transport, Transport: transport,
CheckRedirect: func(req *http.Request, via []*http.Request) error { CheckRedirect: func(_ *http.Request, _ []*http.Request) error {
return http.ErrUseLastResponse return http.ErrUseLastResponse
}, },
} }

View File

@ -60,12 +60,32 @@ const (
) )
const ( const (
// GetObjectAttributesTags are tags used to defined
// return values for the GetObjectAttributes API
GetObjectAttributesTags = "ETag,Checksum,StorageClass,ObjectSize,ObjectParts"
// GetObjectAttributesMaxParts defined the default maximum
// number of parts returned by GetObjectAttributes
GetObjectAttributesMaxParts = 1000
)
const (
// Response Headers
// ETag is a common response header
ETag = "ETag"
// Storage class header. // Storage class header.
amzStorageClass = "X-Amz-Storage-Class" amzStorageClass = "X-Amz-Storage-Class"
// Website redirect location header // Website redirect location header
amzWebsiteRedirectLocation = "X-Amz-Website-Redirect-Location" amzWebsiteRedirectLocation = "X-Amz-Website-Redirect-Location"
// GetObjectAttributes headers
amzPartNumberMarker = "X-Amz-Part-Number-Marker"
amzExpectedBucketOnwer = "X-Amz-Expected-Bucket-Owner"
amzMaxParts = "X-Amz-Max-Parts"
amzObjectAttributes = "X-Amz-Object-Attributes"
// Object Tagging headers // Object Tagging headers
amzTaggingHeader = "X-Amz-Tagging" amzTaggingHeader = "X-Amz-Tagging"
amzTaggingHeaderDirective = "X-Amz-Tagging-Directive" amzTaggingHeaderDirective = "X-Amz-Tagging-Directive"

File diff suppressed because it is too large Load Diff

View File

@ -402,7 +402,7 @@ func (e Expiration) IsDeleteMarkerExpirationEnabled() bool {
// IsNull returns true if both date and days fields are null // IsNull returns true if both date and days fields are null
func (e Expiration) IsNull() bool { func (e Expiration) IsNull() bool {
return e.IsDaysNull() && e.IsDateNull() && !e.IsDeleteMarkerExpirationEnabled() return e.IsDaysNull() && e.IsDateNull() && !e.IsDeleteMarkerExpirationEnabled() && !e.DeleteAll.IsEnabled()
} }
// MarshalXML is expiration is non null // MarshalXML is expiration is non null

View File

@ -149,22 +149,19 @@ func (set StringSet) MarshalJSON() ([]byte, error) {
} }
// UnmarshalJSON - parses JSON data and creates new set with it. // UnmarshalJSON - parses JSON data and creates new set with it.
// If 'data' contains JSON string array, the set contains each string.
// If 'data' contains JSON string, the set contains the string as one element.
// If 'data' contains Other JSON types, JSON parse error is returned.
func (set *StringSet) UnmarshalJSON(data []byte) error { func (set *StringSet) UnmarshalJSON(data []byte) error {
sl := []string{} sl := []interface{}{}
var err error var err error
if err = json.Unmarshal(data, &sl); err == nil { if err = json.Unmarshal(data, &sl); err == nil {
*set = make(StringSet) *set = make(StringSet)
for _, s := range sl { for _, s := range sl {
set.Add(s) set.Add(fmt.Sprintf("%v", s))
} }
} else { } else {
var s string var s interface{}
if err = json.Unmarshal(data, &s); err == nil { if err = json.Unmarshal(data, &s); err == nil {
*set = make(StringSet) *set = make(StringSet)
set.Add(s) set.Add(fmt.Sprintf("%v", s))
} }
} }

View File

@ -21,6 +21,7 @@ import (
"context" "context"
"crypto/md5" "crypto/md5"
fipssha256 "crypto/sha256" fipssha256 "crypto/sha256"
"crypto/tls"
"encoding/base64" "encoding/base64"
"encoding/hex" "encoding/hex"
"encoding/xml" "encoding/xml"
@ -513,6 +514,7 @@ func isAmzHeader(headerKey string) bool {
// supportedQueryValues is a list of query strings that can be passed in when using GetObject. // supportedQueryValues is a list of query strings that can be passed in when using GetObject.
var supportedQueryValues = map[string]bool{ var supportedQueryValues = map[string]bool{
"attributes": true,
"partNumber": true, "partNumber": true,
"versionId": true, "versionId": true,
"response-cache-control": true, "response-cache-control": true,
@ -622,7 +624,7 @@ func IsNetworkOrHostDown(err error, expectTimeouts bool) bool {
urlErr := &url.Error{} urlErr := &url.Error{}
if errors.As(err, &urlErr) { if errors.As(err, &urlErr) {
switch urlErr.Err.(type) { switch urlErr.Err.(type) {
case *net.DNSError, *net.OpError, net.UnknownNetworkError: case *net.DNSError, *net.OpError, net.UnknownNetworkError, *tls.CertificateVerificationError:
return true return true
} }
} }
@ -649,7 +651,12 @@ func IsNetworkOrHostDown(err error, expectTimeouts bool) bool {
case strings.Contains(err.Error(), "connection refused"): case strings.Contains(err.Error(), "connection refused"):
// If err is connection refused // If err is connection refused
return true return true
case strings.Contains(err.Error(), "server gave HTTP response to HTTPS client"):
// If err is TLS client is used with HTTP server
return true
case strings.Contains(err.Error(), "Client sent an HTTP request to an HTTPS server"):
// If err is plain-text Client is used with a HTTPS server
return true
case strings.Contains(strings.ToLower(err.Error()), "503 service unavailable"): case strings.Contains(strings.ToLower(err.Error()), "503 service unavailable"):
// Denial errors // Denial errors
return true return true

View File

@ -136,4 +136,3 @@ func CpuUtilTotalStat() (*CPUUtil, error) {
u := perfstatcpuutil2cpuutil(cpuutil) u := perfstatcpuutil2cpuutil(cpuutil)
return &u, nil return &u, nil
} }

View File

@ -37,24 +37,24 @@ func DisableLVMStat() {}
// CpuStat() returns array of CPU structures with information about // CpuStat() returns array of CPU structures with information about
// logical CPUs on the system. // logical CPUs on the system.
// IBM documentation: // IBM documentation:
// * https://www.ibm.com/support/knowledgecenter/ssw_aix_72/performancetools/idprftools_perfstat_int_cpu.html // - https://www.ibm.com/support/knowledgecenter/ssw_aix_72/performancetools/idprftools_perfstat_int_cpu.html
// * https://www.ibm.com/support/knowledgecenter/en/ssw_aix_72/p_bostechref/perfstat_cpu.html // - https://www.ibm.com/support/knowledgecenter/en/ssw_aix_72/p_bostechref/perfstat_cpu.html
func CpuStat() ([]CPU, error) { func CpuStat() ([]CPU, error) {
return nil, fmt.Errorf("not implemented") return nil, fmt.Errorf("not implemented")
} }
// CpuTotalStat() returns general information about CPUs on the system. // CpuTotalStat() returns general information about CPUs on the system.
// IBM documentation: // IBM documentation:
// * https://www.ibm.com/support/knowledgecenter/ssw_aix_72/performancetools/idprftools_perfstat_glob_cpu.html // - https://www.ibm.com/support/knowledgecenter/ssw_aix_72/performancetools/idprftools_perfstat_glob_cpu.html
// * https://www.ibm.com/support/knowledgecenter/en/ssw_aix_72/p_bostechref/perfstat_cputot.html // - https://www.ibm.com/support/knowledgecenter/en/ssw_aix_72/p_bostechref/perfstat_cputot.html
func CpuTotalStat() (*CPUTotal, error) { func CpuTotalStat() (*CPUTotal, error) {
return nil, fmt.Errorf("not implemented") return nil, fmt.Errorf("not implemented")
} }
// CpuUtilStat() calculates CPU utilization. // CpuUtilStat() calculates CPU utilization.
// IBM documentation: // IBM documentation:
// * https://www.ibm.com/support/knowledgecenter/ssw_aix_72/performancetools/idprftools_perfstat_cpu_util.html // - https://www.ibm.com/support/knowledgecenter/ssw_aix_72/performancetools/idprftools_perfstat_cpu_util.html
// * https://www.ibm.com/support/knowledgecenter/en/ssw_aix_72/p_bostechref/perfstat_cpu_util.html // - https://www.ibm.com/support/knowledgecenter/en/ssw_aix_72/p_bostechref/perfstat_cpu_util.html
func CpuUtilStat(intvl time.Duration) (*CPUUtil, error) { func CpuUtilStat(intvl time.Duration) (*CPUUtil, error) {
return nil, fmt.Errorf("not implemented") return nil, fmt.Errorf("not implemented")
} }

View File

@ -8,6 +8,7 @@ package perfstat
#include <libperfstat.h> #include <libperfstat.h>
#include <sys/proc.h> #include <sys/proc.h>
#include <sys/dr.h>
#include "c_helpers.h" #include "c_helpers.h"
*/ */
@ -763,3 +764,56 @@ func fsinfo2filesystem(n *C.struct_fsinfo) FileSystem {
return i return i
} }
func lparinfo2partinfo(n C.lpar_info_format2_t) PartitionInfo {
var i PartitionInfo
i.Version = int(n.version)
i.OnlineMemory = uint64(n.online_memory)
i.TotalDispatchTime = uint64(n.tot_dispatch_time)
i.PoolIdleTime = uint64(n.pool_idle_time)
i.DispatchLatency = uint64(n.dispatch_latency)
i.LparFlags = uint(n.lpar_flags)
i.PCpusInSys = uint(n.pcpus_in_sys)
i.OnlineVCpus = uint(n.online_vcpus)
i.OnlineLCpus = uint(n.online_lcpus)
i.PCpusInPool = uint(n.pcpus_in_pool)
i.UnallocCapacity = uint(n.unalloc_capacity)
i.EntitledCapacity = uint(n.entitled_capacity)
i.VariableWeight = uint(n.variable_weight)
i.UnallocWeight = uint(n.unalloc_weight)
i.MinReqVCpuCapacity = uint(n.min_req_vcpu_capacity)
i.GroupId = uint8(n.group_id)
i.PoolId = uint8(n.pool_id)
i.ShCpusInSys = uint(n.shcpus_in_sys)
i.MaxPoolCapacity = uint(n.max_pool_capacity)
i.EntitledPoolCapacity = uint(n.entitled_pool_capacity)
i.PoolMaxTime = uint64(n.pool_max_time)
i.PoolBusyTime = uint64(n.pool_busy_time)
i.PoolScaledBusyTime = uint64(n.pool_scaled_busy_time)
i.ShCpuTotalTime = uint64(n.shcpu_tot_time)
i.ShCpuBusyTime = uint64(n.shcpu_busy_time)
i.ShCpuScaledBusyTime = uint64(n.shcpu_scaled_busy_time)
i.EntMemCapacity = uint64(n.ent_mem_capacity)
i.PhysMem = uint64(n.phys_mem)
i.VrmPoolPhysMem = uint64(n.vrm_pool_physmem)
i.HypPageSize = uint(n.hyp_pagesize)
i.VrmPoolId = int(n.vrm_pool_id)
i.VrmGroupId = int(n.vrm_group_id)
i.VarMemWeight = int(n.var_mem_weight)
i.UnallocVarMemWeight = int(n.unalloc_var_mem_weight)
i.UnallocEntMemCapacity = uint64(n.unalloc_ent_mem_capacity)
i.TrueOnlineMemory = uint64(n.true_online_memory)
i.AmeOnlineMemory = uint64(n.ame_online_memory)
i.AmeType = uint8(n.ame_type)
i.SpecExecMode = uint8(n.spec_exec_mode)
i.AmeFactor = uint(n.ame_factor)
i.EmPartMajorCode = uint(n.em_part_major_code)
i.EmPartMinorCode = uint(n.em_part_minor_code)
i.BytesCoalesced = uint64(n.bytes_coalesced)
i.BytesCoalescedMemPool = uint64(n.bytes_coalesced_mempool)
i.PurrCoalescing = uint64(n.purr_coalescing)
i.SpurrCoalescing = uint64(n.spurr_coalescing)
return i
}

View File

@ -7,11 +7,13 @@ package perfstat
#cgo LDFLAGS: -lperfstat #cgo LDFLAGS: -lperfstat
#include <libperfstat.h> #include <libperfstat.h>
#include <sys/dr.h>
*/ */
import "C" import "C"
import ( import (
"fmt" "fmt"
"unsafe"
) )
func PartitionStat() (*PartitionConfig, error) { func PartitionStat() (*PartitionConfig, error) {
@ -25,3 +27,14 @@ func PartitionStat() (*PartitionConfig, error) {
return &p, nil return &p, nil
} }
func LparInfo() (*PartitionInfo, error) {
var pinfo C.lpar_info_format2_t
rc := C.lpar_get_info(C.LPAR_INFO_FORMAT2, unsafe.Pointer(&pinfo), C.sizeof_lpar_info_format2_t)
if rc != 0 {
return nil, fmt.Errorf("lpar_get_info() error")
}
p := lparinfo2partinfo(pinfo)
return &p, nil
}

View File

@ -71,6 +71,7 @@ const (
SC_TM_VER = 59 /* Transaction Memory version, 0 - not capable */ SC_TM_VER = 59 /* Transaction Memory version, 0 - not capable */
SC_NX_CAP = 60 /* NX GZIP capable */ SC_NX_CAP = 60 /* NX GZIP capable */
SC_PKS_STATE = 61 /* Platform KeyStore */ SC_PKS_STATE = 61 /* Platform KeyStore */
SC_MMA_VER = 62
) )
/* kernel attributes */ /* kernel attributes */
@ -120,6 +121,7 @@ const (
IMPL_POWER7 = 0x8000 /* 7 class CPU */ IMPL_POWER7 = 0x8000 /* 7 class CPU */
IMPL_POWER8 = 0x10000 /* 8 class CPU */ IMPL_POWER8 = 0x10000 /* 8 class CPU */
IMPL_POWER9 = 0x20000 /* 9 class CPU */ IMPL_POWER9 = 0x20000 /* 9 class CPU */
IMPL_POWER10 = 0x20000 /* 10 class CPU */
) )
// Values for implementation field for IA64 Architectures // Values for implementation field for IA64 Architectures
@ -152,11 +154,13 @@ const (
PV_7 = 0x200000 /* Power PC 7 */ PV_7 = 0x200000 /* Power PC 7 */
PV_8 = 0x300000 /* Power PC 8 */ PV_8 = 0x300000 /* Power PC 8 */
PV_9 = 0x400000 /* Power PC 9 */ PV_9 = 0x400000 /* Power PC 9 */
PV_10 = 0x500000 /* Power PC 10 */
PV_5_Compat = 0x0F8000 /* Power PC 5 */ PV_5_Compat = 0x0F8000 /* Power PC 5 */
PV_6_Compat = 0x108000 /* Power PC 6 */ PV_6_Compat = 0x108000 /* Power PC 6 */
PV_7_Compat = 0x208000 /* Power PC 7 */ PV_7_Compat = 0x208000 /* Power PC 7 */
PV_8_Compat = 0x308000 /* Power PC 8 */ PV_8_Compat = 0x308000 /* Power PC 8 */
PV_9_Compat = 0x408000 /* Power PC 9 */ PV_9_Compat = 0x408000 /* Power PC 9 */
PV_10_Compat = 0x508000 /* Power PC 10 */
PV_RESERVED_2 = 0x0A0000 /* source compatability */ PV_RESERVED_2 = 0x0A0000 /* source compatability */
PV_RESERVED_3 = 0x0B0000 /* source compatability */ PV_RESERVED_3 = 0x0B0000 /* source compatability */
PV_RS2 = 0x040000 /* Power RS2 */ PV_RS2 = 0x040000 /* Power RS2 */
@ -182,19 +186,21 @@ const (
// Macros for identifying physical processor // Macros for identifying physical processor
const ( const (
PPI4_1 = 0x35 PPI4_1 = 0x35
PPI4_2 = 0x38 PPI4_2 = 0x38
PPI4_3 = 0x39 PPI4_3 = 0x39
PPI4_4 = 0x3C PPI4_4 = 0x3C
PPI4_5 = 0x44 PPI4_5 = 0x44
PPI5_1 = 0x3A PPI5_1 = 0x3A
PPI5_2 = 0x3B PPI5_2 = 0x3B
PPI6_1 = 0x3E PPI6_1 = 0x3E
PPI7_1 = 0x3F PPI7_1 = 0x3F
PPI7_2 = 0x4A PPI7_2 = 0x4A
PPI8_1 = 0x4B PPI8_1 = 0x4B
PPI8_2 = 0x4D PPI8_2 = 0x4D
PPI9 = 0x4E PPI9 = 0x4E
PPI9_1 = 0x4E
PPI10_1 = 0x80
) )
// Macros for kernel attributes // Macros for kernel attributes
@ -292,14 +298,32 @@ func GetCPUImplementation() string {
return "POWER8" return "POWER8"
case impl&IMPL_POWER9 != 0: case impl&IMPL_POWER9 != 0:
return "POWER9" return "POWER9"
case impl&IMPL_POWER10 != 0:
return "Power10"
default: default:
return "Unknown" return "Unknown"
} }
} }
func POWER10OrNewer() bool {
impl := unix.Getsystemcfg(SC_IMPL)
if impl&IMPL_POWER10 != 0 {
return true
}
return false
}
func POWER10() bool {
impl := unix.Getsystemcfg(SC_IMPL)
if impl&IMPL_POWER10 != 0 {
return true
}
return false
}
func POWER9OrNewer() bool { func POWER9OrNewer() bool {
impl := unix.Getsystemcfg(SC_IMPL) impl := unix.Getsystemcfg(SC_IMPL)
if impl&IMPL_POWER9 != 0 { if impl&IMPL_POWER10 != 0 || impl&IMPL_POWER9 != 0 {
return true return true
} }
return false return false
@ -315,7 +339,7 @@ func POWER9() bool {
func POWER8OrNewer() bool { func POWER8OrNewer() bool {
impl := unix.Getsystemcfg(SC_IMPL) impl := unix.Getsystemcfg(SC_IMPL)
if impl&IMPL_POWER9 != 0 || impl&IMPL_POWER8 != 0 { if impl&IMPL_POWER10 != 0 || impl&IMPL_POWER9 != 0 || impl&IMPL_POWER8 != 0 {
return true return true
} }
return false return false
@ -331,7 +355,7 @@ func POWER8() bool {
func POWER7OrNewer() bool { func POWER7OrNewer() bool {
impl := unix.Getsystemcfg(SC_IMPL) impl := unix.Getsystemcfg(SC_IMPL)
if impl&IMPL_POWER9 != 0 || impl&IMPL_POWER8 != 0 || impl&IMPL_POWER7 != 0 { if impl&IMPL_POWER10 != 0 || impl&IMPL_POWER9 != 0 || impl&IMPL_POWER8 != 0 || impl&IMPL_POWER7 != 0 {
return true return true
} }
return false return false
@ -420,6 +444,8 @@ func PksEnabled() bool {
func CPUMode() string { func CPUMode() string {
impl := unix.Getsystemcfg(SC_VERS) impl := unix.Getsystemcfg(SC_VERS)
switch impl { switch impl {
case PV_10, PV_10_Compat:
return "Power10"
case PV_9, PV_9_Compat: case PV_9, PV_9_Compat:
return "POWER9" return "POWER9"
case PV_8, PV_8_Compat: case PV_8, PV_8_Compat:

View File

@ -29,8 +29,8 @@ type DiskTotal struct {
// Disk Adapter Types // Disk Adapter Types
const ( const (
DA_SCSI = 0 /* 0 ==> SCSI, SAS, other legacy adapter types */ DA_SCSI = 0 /* 0 ==> SCSI, SAS, other legacy adapter types */
DA_VSCSI /* 1 ==> Virtual SCSI/SAS Adapter */ DA_VSCSI = 1 /* 1 ==> Virtual SCSI/SAS Adapter */
DA_FCA /* 2 ==> Fiber Channel Adapter */ DA_FCA = 2 /* 2 ==> Fiber Channel Adapter */
) )
type DiskAdapter struct { type DiskAdapter struct {

View File

@ -66,3 +66,64 @@ type PartitionConfig struct {
TargetMemExpSize int64 /* Expanded Memory Size in MB */ TargetMemExpSize int64 /* Expanded Memory Size in MB */
SubProcessorMode int32 /* Split core mode, its value can be 0,1,2 or 4. 0 for unsupported, 1 for capable but not enabled, 2 or 4 for enabled*/ SubProcessorMode int32 /* Split core mode, its value can be 0,1,2 or 4. 0 for unsupported, 1 for capable but not enabled, 2 or 4 for enabled*/
} }
const (
AME_TYPE_V1 = 0x1
AME_TYPE_V2 = 0x2
LPAR_INFO_CAPPED = 0x01 /* Parition Capped */
LPAR_INFO_AUTH_PIC = 0x02 /* Authority granted for poolidle*/
LPAR_INFO_SMT_ENABLED = 0x04 /* SMT Enabled */
LPAR_INFO_WPAR_ACTIVE = 0x08 /* Process Running Within a WPAR */
LPAR_INFO_EXTENDED = 0x10 /* Extended shared processor pool information */
LPAR_INFO_AME_ENABLED = 0x20 /* Active Mem. Expansion (AME) enabled*/
LPAR_INFO_SEM_ENABLED = 0x40 /* Speculative Execution Mode enabled */
)
type PartitionInfo struct {
Version int /* version for this structure */
OnlineMemory uint64 /* MB of currently online memory */
TotalDispatchTime uint64 /* Total lpar dispatch time in nsecs */
PoolIdleTime uint64 /* Idle time of shared CPU pool nsecs*/
DispatchLatency uint64 /* Max latency inbetween dispatches of this LPAR on physCPUS in nsecs */
LparFlags uint /* LPAR flags */
PCpusInSys uint /* # of active licensed physical CPUs in system */
OnlineVCpus uint /* # of current online virtual CPUs */
OnlineLCpus uint /* # of current online logical CPUs */
PCpusInPool uint /* # physical CPUs in shared pool */
UnallocCapacity uint /* Unallocated Capacity available in shared pool */
EntitledCapacity uint /* Entitled Processor Capacity for this partition */
VariableWeight uint /* Variable Processor Capacity Weight */
UnallocWeight uint /* Unallocated Variable Weight available for this partition */
MinReqVCpuCapacity uint /* OS minimum required virtual processor capacity. */
GroupId uint8 /* ID of a LPAR group/aggregation */
PoolId uint8 /* ID of a shared pool */
ShCpusInSys uint /* # of physical processors allocated for shared processor use */
MaxPoolCapacity uint /* Maximum processor capacity of partition's pool */
EntitledPoolCapacity uint /* Entitled processor capacity of partition's pool */
PoolMaxTime uint64 /* Summation of maximum time that could be consumed by the pool, in nanoseconds */
PoolBusyTime uint64 /* Summation of busy time accumulated across all partitions in the pool, in nanoseconds */
PoolScaledBusyTime uint64 /* Scaled summation of busy time accumulated across all partitions in the pool, in nanoseconds */
ShCpuTotalTime uint64 /* Summation of total time across all physical processors allocated for shared processor use, in nanoseconds */
ShCpuBusyTime uint64 /* Summation of busy time accumulated across all shared processor partitions, in nanoseconds */
ShCpuScaledBusyTime uint64 /* Scaled summation of busy time accumulated across all shared processor partitions, in nanoseconds */
EntMemCapacity uint64 /* Partition's current entitlement memory capacity setting */
PhysMem uint64 /* Amount of physical memory, in bytes, currently backing the partition's logical memory */
VrmPoolPhysMem uint64 /* Total amount of physical memory in the VRM pool */
HypPageSize uint /* Page size hypervisor is using to virtualize partition's memory */
VrmPoolId int /* ID of VRM pool */
VrmGroupId int /* eWLM VRM group to which partition belongs */
VarMemWeight int /* Partition's current variable memory capacity weighting setting */
UnallocVarMemWeight int /* Amount of unallocated variable memory capacity weight available to LPAR's group */
UnallocEntMemCapacity uint64 /* Amount of unallocated I/O memory entitlement available to LPAR's group */
TrueOnlineMemory uint64 /* true MB of currently online memory */
AmeOnlineMemory uint64 /* AME MB of currently online memory */
AmeType uint8
SpecExecMode uint8 /* Speculative Execution Mode */
AmeFactor uint /* memory expansion factor for LPAR */
EmPartMajorCode uint /* Major and minor codes for our */
EmPartMinorCode uint /* current energy management mode */
BytesCoalesced uint64 /* The number of bytes of the calling partition.s logical real memory coalesced because they contained duplicated data */
BytesCoalescedMemPool uint64 /* If the calling partition is authorized to see pool wide statistics then the number of bytes of logical real memory coalesced because they contained duplicated data in the calling partition.s memory pool else set to zero.*/
PurrCoalescing uint64 /* If the calling partition is authorized to see pool wide statistics then PURR cycles consumed to coalesce data else set to zero.*/
SpurrCoalescing uint64 /* If the calling partition is authorized to see pool wide statistics then SPURR cycles consumed to coalesce data else set to zero.*/
}

View File

@ -483,6 +483,8 @@ type Histogram struct {
// histograms. // histograms.
PositiveDelta []int64 `protobuf:"zigzag64,13,rep,name=positive_delta,json=positiveDelta" json:"positive_delta,omitempty"` // Count delta of each bucket compared to previous one (or to zero for 1st bucket). PositiveDelta []int64 `protobuf:"zigzag64,13,rep,name=positive_delta,json=positiveDelta" json:"positive_delta,omitempty"` // Count delta of each bucket compared to previous one (or to zero for 1st bucket).
PositiveCount []float64 `protobuf:"fixed64,14,rep,name=positive_count,json=positiveCount" json:"positive_count,omitempty"` // Absolute count of each bucket. PositiveCount []float64 `protobuf:"fixed64,14,rep,name=positive_count,json=positiveCount" json:"positive_count,omitempty"` // Absolute count of each bucket.
// Only used for native histograms. These exemplars MUST have a timestamp.
Exemplars []*Exemplar `protobuf:"bytes,16,rep,name=exemplars" json:"exemplars,omitempty"`
} }
func (x *Histogram) Reset() { func (x *Histogram) Reset() {
@ -622,6 +624,13 @@ func (x *Histogram) GetPositiveCount() []float64 {
return nil return nil
} }
func (x *Histogram) GetExemplars() []*Exemplar {
if x != nil {
return x.Exemplars
}
return nil
}
// A Bucket of a conventional histogram, each of which is treated as // A Bucket of a conventional histogram, each of which is treated as
// an individual counter-like time series by Prometheus. // an individual counter-like time series by Prometheus.
type Bucket struct { type Bucket struct {
@ -923,6 +932,7 @@ type MetricFamily struct {
Help *string `protobuf:"bytes,2,opt,name=help" json:"help,omitempty"` Help *string `protobuf:"bytes,2,opt,name=help" json:"help,omitempty"`
Type *MetricType `protobuf:"varint,3,opt,name=type,enum=io.prometheus.client.MetricType" json:"type,omitempty"` Type *MetricType `protobuf:"varint,3,opt,name=type,enum=io.prometheus.client.MetricType" json:"type,omitempty"`
Metric []*Metric `protobuf:"bytes,4,rep,name=metric" json:"metric,omitempty"` Metric []*Metric `protobuf:"bytes,4,rep,name=metric" json:"metric,omitempty"`
Unit *string `protobuf:"bytes,5,opt,name=unit" json:"unit,omitempty"`
} }
func (x *MetricFamily) Reset() { func (x *MetricFamily) Reset() {
@ -985,6 +995,13 @@ func (x *MetricFamily) GetMetric() []*Metric {
return nil return nil
} }
func (x *MetricFamily) GetUnit() string {
if x != nil && x.Unit != nil {
return *x.Unit
}
return ""
}
var File_io_prometheus_client_metrics_proto protoreflect.FileDescriptor var File_io_prometheus_client_metrics_proto protoreflect.FileDescriptor
var file_io_prometheus_client_metrics_proto_rawDesc = []byte{ var file_io_prometheus_client_metrics_proto_rawDesc = []byte{
@ -1028,7 +1045,7 @@ var file_io_prometheus_client_metrics_proto_rawDesc = []byte{
0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x10, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x10, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64,
0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x1f, 0x0a, 0x07, 0x55, 0x6e, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x1f, 0x0a, 0x07, 0x55, 0x6e, 0x74,
0x79, 0x70, 0x65, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x79, 0x70, 0x65, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20,
0x01, 0x28, 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xac, 0x05, 0x0a, 0x09, 0x48, 0x01, 0x28, 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xea, 0x05, 0x0a, 0x09, 0x48,
0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x61, 0x6d, 0x70, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x61, 0x6d, 0x70,
0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b,
0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2c, 0x0a, 0x12, 0x73, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2c, 0x0a, 0x12, 0x73,
@ -1071,79 +1088,84 @@ var file_io_prometheus_client_metrics_proto_rawDesc = []byte{
0x03, 0x28, 0x12, 0x52, 0x0d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x44, 0x65, 0x6c, 0x03, 0x28, 0x12, 0x52, 0x0d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x44, 0x65, 0x6c,
0x74, 0x61, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x63, 0x74, 0x61, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x63,
0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x01, 0x52, 0x0d, 0x70, 0x6f, 0x73, 0x69, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x01, 0x52, 0x0d, 0x70, 0x6f, 0x73, 0x69,
0x74, 0x69, 0x76, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0xc6, 0x01, 0x0a, 0x06, 0x42, 0x75, 0x74, 0x69, 0x76, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x3c, 0x0a, 0x09, 0x65, 0x78, 0x65,
0x63, 0x6b, 0x65, 0x74, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6d, 0x70, 0x6c, 0x61, 0x72, 0x73, 0x18, 0x10, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x69,
0x76, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69,
0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x78, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x72, 0x52, 0x09, 0x65, 0x78,
0x34, 0x0a, 0x16, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x63, 0x6f, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x72, 0x73, 0x22, 0xc6, 0x01, 0x0a, 0x06, 0x42, 0x75, 0x63, 0x6b,
0x75, 0x6e, 0x74, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x52, 0x65, 0x74, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65,
0x14, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x63, 0x75,
0x46, 0x6c, 0x6f, 0x61, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x75, 0x70, 0x70, 0x65, 0x72, 0x5f, 0x62, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x34, 0x0a,
0x6f, 0x75, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0a, 0x75, 0x70, 0x70, 0x65, 0x16, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e,
0x72, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x3a, 0x0a, 0x08, 0x65, 0x78, 0x65, 0x6d, 0x70, 0x6c, 0x74, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x52, 0x14, 0x63,
0x61, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x46, 0x6c,
0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x6f, 0x61, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x75, 0x70, 0x70, 0x65, 0x72, 0x5f, 0x62, 0x6f, 0x75,
0x45, 0x78, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x72, 0x52, 0x08, 0x65, 0x78, 0x65, 0x6d, 0x70, 0x6c, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0a, 0x75, 0x70, 0x70, 0x65, 0x72, 0x42,
0x61, 0x72, 0x22, 0x3c, 0x0a, 0x0a, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x70, 0x61, 0x6e, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x3a, 0x0a, 0x08, 0x65, 0x78, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x72,
0x12, 0x16, 0x0a, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x11, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d,
0x52, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x78,
0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x72, 0x52, 0x08, 0x65, 0x78, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x72,
0x22, 0x91, 0x01, 0x0a, 0x08, 0x45, 0x78, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x72, 0x12, 0x35, 0x0a, 0x22, 0x3c, 0x0a, 0x0a, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x70, 0x61, 0x6e, 0x12, 0x16,
0x0a, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x11, 0x52, 0x06,
0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68,
0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x91,
0x01, 0x0a, 0x08, 0x45, 0x78, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x72, 0x12, 0x35, 0x0a, 0x05, 0x6c,
0x61, 0x62, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x69, 0x6f, 0x2e,
0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e,
0x74, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x50, 0x61, 0x69, 0x72, 0x52, 0x05, 0x6c, 0x61, 0x62,
0x65, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65,
0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f,
0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69,
0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61,
0x6d, 0x70, 0x22, 0xff, 0x02, 0x0a, 0x06, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x35, 0x0a,
0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x69, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x69,
0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69,
0x65, 0x6e, 0x74, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x50, 0x61, 0x69, 0x72, 0x52, 0x05, 0x6c, 0x65, 0x6e, 0x74, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x50, 0x61, 0x69, 0x72, 0x52, 0x05, 0x6c,
0x61, 0x62, 0x65, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x31, 0x0a, 0x05, 0x67, 0x61, 0x75, 0x67, 0x65, 0x18, 0x02, 0x20,
0x01, 0x28, 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68,
0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x47, 0x61, 0x75, 0x67, 0x65,
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x52, 0x05, 0x67, 0x61, 0x75, 0x67, 0x65, 0x12, 0x37, 0x0a, 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74,
0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72,
0x74, 0x61, 0x6d, 0x70, 0x22, 0xff, 0x02, 0x0a, 0x06, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e,
0x35, 0x0a, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x52, 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72,
0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x12, 0x37, 0x0a, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28,
0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x50, 0x61, 0x69, 0x72, 0x52, 0x0b, 0x32, 0x1d, 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75,
0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x31, 0x0a, 0x05, 0x67, 0x61, 0x75, 0x67, 0x65, 0x18, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79,
0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x52, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x37, 0x0a, 0x07, 0x75, 0x6e, 0x74,
0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x47, 0x61, 0x75, 0x79, 0x70, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x69, 0x6f, 0x2e,
0x67, 0x65, 0x52, 0x05, 0x67, 0x61, 0x75, 0x67, 0x65, 0x12, 0x37, 0x0a, 0x07, 0x63, 0x6f, 0x75,
0x6e, 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x69, 0x6f, 0x2e,
0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e,
0x74, 0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x52, 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x74, 0x2e, 0x55, 0x6e, 0x74, 0x79, 0x70, 0x65, 0x64, 0x52, 0x07, 0x75, 0x6e, 0x74, 0x79, 0x70,
0x65, 0x72, 0x12, 0x37, 0x0a, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x04, 0x20, 0x65, 0x64, 0x12, 0x3d, 0x0a, 0x09, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x18,
0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65,
0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x48, 0x69, 0x73,
0x72, 0x79, 0x52, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x37, 0x0a, 0x07, 0x75, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x52, 0x09, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61,
0x6e, 0x74, 0x79, 0x70, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x69, 0x6d, 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x5f, 0x6d,
0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61,
0x65, 0x6e, 0x74, 0x2e, 0x55, 0x6e, 0x74, 0x79, 0x70, 0x65, 0x64, 0x52, 0x07, 0x75, 0x6e, 0x74, 0x6d, 0x70, 0x4d, 0x73, 0x22, 0xb6, 0x01, 0x0a, 0x0c, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x46,
0x79, 0x70, 0x65, 0x64, 0x12, 0x3d, 0x0a, 0x09, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20,
0x6d, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x65, 0x6c,
0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x48, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x65, 0x6c, 0x70, 0x12, 0x34, 0x0a,
0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x52, 0x09, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x69, 0x6f,
0x72, 0x61, 0x6d, 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65,
0x5f, 0x6d, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x6e, 0x74, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74,
0x74, 0x61, 0x6d, 0x70, 0x4d, 0x73, 0x22, 0xa2, 0x01, 0x0a, 0x0c, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x79, 0x70, 0x65, 0x12, 0x34, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x18, 0x04, 0x20,
0x63, 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68,
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69,
0x65, 0x6c, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x65, 0x6c, 0x70, 0x12, 0x63, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x6e, 0x69,
0x34, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x6e, 0x69, 0x74, 0x2a, 0x62, 0x0a,
0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x0a, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x43,
0x69, 0x65, 0x6e, 0x74, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x54, 0x79, 0x70, 0x65, 0x52, 0x4f, 0x55, 0x4e, 0x54, 0x45, 0x52, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x47, 0x41, 0x55, 0x47,
0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x34, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x18, 0x45, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x55, 0x4d, 0x4d, 0x41, 0x52, 0x59, 0x10, 0x02,
0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x54, 0x59, 0x50, 0x45, 0x44, 0x10, 0x03, 0x12, 0x0d, 0x0a,
0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x4d, 0x65, 0x74, 0x09, 0x48, 0x49, 0x53, 0x54, 0x4f, 0x47, 0x52, 0x41, 0x4d, 0x10, 0x04, 0x12, 0x13, 0x0a, 0x0f,
0x72, 0x69, 0x63, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2a, 0x62, 0x0a, 0x0a, 0x4d, 0x47, 0x41, 0x55, 0x47, 0x45, 0x5f, 0x48, 0x49, 0x53, 0x54, 0x4f, 0x47, 0x52, 0x41, 0x4d, 0x10,
0x65, 0x74, 0x72, 0x69, 0x63, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x43, 0x4f, 0x55, 0x05, 0x42, 0x52, 0x0a, 0x14, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65,
0x4e, 0x54, 0x45, 0x52, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x47, 0x41, 0x55, 0x47, 0x45, 0x10, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75,
0x01, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x55, 0x4d, 0x4d, 0x41, 0x52, 0x59, 0x10, 0x02, 0x12, 0x0b, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73,
0x0a, 0x07, 0x55, 0x4e, 0x54, 0x59, 0x50, 0x45, 0x44, 0x10, 0x03, 0x12, 0x0d, 0x0a, 0x09, 0x48, 0x2f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x67, 0x6f,
0x49, 0x53, 0x54, 0x4f, 0x47, 0x52, 0x41, 0x4d, 0x10, 0x04, 0x12, 0x13, 0x0a, 0x0f, 0x47, 0x41, 0x3b, 0x69, 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x5f, 0x63,
0x55, 0x47, 0x45, 0x5f, 0x48, 0x49, 0x53, 0x54, 0x4f, 0x47, 0x52, 0x41, 0x4d, 0x10, 0x05, 0x42, 0x6c, 0x69, 0x65, 0x6e, 0x74,
0x52, 0x0a, 0x14, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73,
0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e,
0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2f, 0x63,
0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x67, 0x6f, 0x3b, 0x69,
0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x5f, 0x63, 0x6c, 0x69,
0x65, 0x6e, 0x74,
} }
var ( var (
@ -1185,22 +1207,23 @@ var file_io_prometheus_client_metrics_proto_depIdxs = []int32{
13, // 5: io.prometheus.client.Histogram.created_timestamp:type_name -> google.protobuf.Timestamp 13, // 5: io.prometheus.client.Histogram.created_timestamp:type_name -> google.protobuf.Timestamp
9, // 6: io.prometheus.client.Histogram.negative_span:type_name -> io.prometheus.client.BucketSpan 9, // 6: io.prometheus.client.Histogram.negative_span:type_name -> io.prometheus.client.BucketSpan
9, // 7: io.prometheus.client.Histogram.positive_span:type_name -> io.prometheus.client.BucketSpan 9, // 7: io.prometheus.client.Histogram.positive_span:type_name -> io.prometheus.client.BucketSpan
10, // 8: io.prometheus.client.Bucket.exemplar:type_name -> io.prometheus.client.Exemplar 10, // 8: io.prometheus.client.Histogram.exemplars:type_name -> io.prometheus.client.Exemplar
1, // 9: io.prometheus.client.Exemplar.label:type_name -> io.prometheus.client.LabelPair 10, // 9: io.prometheus.client.Bucket.exemplar:type_name -> io.prometheus.client.Exemplar
13, // 10: io.prometheus.client.Exemplar.timestamp:type_name -> google.protobuf.Timestamp 1, // 10: io.prometheus.client.Exemplar.label:type_name -> io.prometheus.client.LabelPair
1, // 11: io.prometheus.client.Metric.label:type_name -> io.prometheus.client.LabelPair 13, // 11: io.prometheus.client.Exemplar.timestamp:type_name -> google.protobuf.Timestamp
2, // 12: io.prometheus.client.Metric.gauge:type_name -> io.prometheus.client.Gauge 1, // 12: io.prometheus.client.Metric.label:type_name -> io.prometheus.client.LabelPair
3, // 13: io.prometheus.client.Metric.counter:type_name -> io.prometheus.client.Counter 2, // 13: io.prometheus.client.Metric.gauge:type_name -> io.prometheus.client.Gauge
5, // 14: io.prometheus.client.Metric.summary:type_name -> io.prometheus.client.Summary 3, // 14: io.prometheus.client.Metric.counter:type_name -> io.prometheus.client.Counter
6, // 15: io.prometheus.client.Metric.untyped:type_name -> io.prometheus.client.Untyped 5, // 15: io.prometheus.client.Metric.summary:type_name -> io.prometheus.client.Summary
7, // 16: io.prometheus.client.Metric.histogram:type_name -> io.prometheus.client.Histogram 6, // 16: io.prometheus.client.Metric.untyped:type_name -> io.prometheus.client.Untyped
0, // 17: io.prometheus.client.MetricFamily.type:type_name -> io.prometheus.client.MetricType 7, // 17: io.prometheus.client.Metric.histogram:type_name -> io.prometheus.client.Histogram
11, // 18: io.prometheus.client.MetricFamily.metric:type_name -> io.prometheus.client.Metric 0, // 18: io.prometheus.client.MetricFamily.type:type_name -> io.prometheus.client.MetricType
19, // [19:19] is the sub-list for method output_type 11, // 19: io.prometheus.client.MetricFamily.metric:type_name -> io.prometheus.client.Metric
19, // [19:19] is the sub-list for method input_type 20, // [20:20] is the sub-list for method output_type
19, // [19:19] is the sub-list for extension type_name 20, // [20:20] is the sub-list for method input_type
19, // [19:19] is the sub-list for extension extendee 20, // [20:20] is the sub-list for extension type_name
0, // [0:19] is the sub-list for field type_name 20, // [20:20] is the sub-list for extension extendee
0, // [0:20] is the sub-list for field type_name
} }
func init() { file_io_prometheus_client_metrics_proto_init() } func init() { file_io_prometheus_client_metrics_proto_init() }

View File

@ -14,6 +14,7 @@
package expfmt package expfmt
import ( import (
"bufio"
"fmt" "fmt"
"io" "io"
"math" "math"
@ -21,8 +22,8 @@ import (
"net/http" "net/http"
dto "github.com/prometheus/client_model/go" dto "github.com/prometheus/client_model/go"
"google.golang.org/protobuf/encoding/protodelim"
"github.com/matttproud/golang_protobuf_extensions/v2/pbutil"
"github.com/prometheus/common/model" "github.com/prometheus/common/model"
) )
@ -44,7 +45,7 @@ func ResponseFormat(h http.Header) Format {
mediatype, params, err := mime.ParseMediaType(ct) mediatype, params, err := mime.ParseMediaType(ct)
if err != nil { if err != nil {
return FmtUnknown return fmtUnknown
} }
const textType = "text/plain" const textType = "text/plain"
@ -52,28 +53,28 @@ func ResponseFormat(h http.Header) Format {
switch mediatype { switch mediatype {
case ProtoType: case ProtoType:
if p, ok := params["proto"]; ok && p != ProtoProtocol { if p, ok := params["proto"]; ok && p != ProtoProtocol {
return FmtUnknown return fmtUnknown
} }
if e, ok := params["encoding"]; ok && e != "delimited" { if e, ok := params["encoding"]; ok && e != "delimited" {
return FmtUnknown return fmtUnknown
} }
return FmtProtoDelim return fmtProtoDelim
case textType: case textType:
if v, ok := params["version"]; ok && v != TextVersion { if v, ok := params["version"]; ok && v != TextVersion {
return FmtUnknown return fmtUnknown
} }
return FmtText return fmtText
} }
return FmtUnknown return fmtUnknown
} }
// NewDecoder returns a new decoder based on the given input format. // NewDecoder returns a new decoder based on the given input format.
// If the input format does not imply otherwise, a text format decoder is returned. // If the input format does not imply otherwise, a text format decoder is returned.
func NewDecoder(r io.Reader, format Format) Decoder { func NewDecoder(r io.Reader, format Format) Decoder {
switch format { switch format.FormatType() {
case FmtProtoDelim: case TypeProtoDelim:
return &protoDecoder{r: r} return &protoDecoder{r: r}
} }
return &textDecoder{r: r} return &textDecoder{r: r}
@ -86,8 +87,10 @@ type protoDecoder struct {
// Decode implements the Decoder interface. // Decode implements the Decoder interface.
func (d *protoDecoder) Decode(v *dto.MetricFamily) error { func (d *protoDecoder) Decode(v *dto.MetricFamily) error {
_, err := pbutil.ReadDelimited(d.r, v) opts := protodelim.UnmarshalOptions{
if err != nil { MaxSize: -1,
}
if err := opts.UnmarshalFrom(bufio.NewReader(d.r), v); err != nil {
return err return err
} }
if !model.IsValidMetricName(model.LabelValue(v.GetName())) { if !model.IsValidMetricName(model.LabelValue(v.GetName())) {

View File

@ -18,10 +18,12 @@ import (
"io" "io"
"net/http" "net/http"
"github.com/matttproud/golang_protobuf_extensions/v2/pbutil" "google.golang.org/protobuf/encoding/protodelim"
"github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg"
"google.golang.org/protobuf/encoding/prototext" "google.golang.org/protobuf/encoding/prototext"
"github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg"
"github.com/prometheus/common/model"
dto "github.com/prometheus/client_model/go" dto "github.com/prometheus/client_model/go"
) )
@ -60,23 +62,32 @@ func (ec encoderCloser) Close() error {
// as the support is still experimental. To include the option to negotiate // as the support is still experimental. To include the option to negotiate
// FmtOpenMetrics, use NegotiateOpenMetrics. // FmtOpenMetrics, use NegotiateOpenMetrics.
func Negotiate(h http.Header) Format { func Negotiate(h http.Header) Format {
escapingScheme := Format(fmt.Sprintf("; escaping=%s", Format(model.NameEscapingScheme.String())))
for _, ac := range goautoneg.ParseAccept(h.Get(hdrAccept)) { for _, ac := range goautoneg.ParseAccept(h.Get(hdrAccept)) {
if escapeParam := ac.Params[model.EscapingKey]; escapeParam != "" {
switch Format(escapeParam) {
case model.AllowUTF8, model.EscapeUnderscores, model.EscapeDots, model.EscapeValues:
escapingScheme = Format(fmt.Sprintf("; escaping=%s", escapeParam))
default:
// If the escaping parameter is unknown, ignore it.
}
}
ver := ac.Params["version"] ver := ac.Params["version"]
if ac.Type+"/"+ac.SubType == ProtoType && ac.Params["proto"] == ProtoProtocol { if ac.Type+"/"+ac.SubType == ProtoType && ac.Params["proto"] == ProtoProtocol {
switch ac.Params["encoding"] { switch ac.Params["encoding"] {
case "delimited": case "delimited":
return FmtProtoDelim return fmtProtoDelim + escapingScheme
case "text": case "text":
return FmtProtoText return fmtProtoText + escapingScheme
case "compact-text": case "compact-text":
return FmtProtoCompact return fmtProtoCompact + escapingScheme
} }
} }
if ac.Type == "text" && ac.SubType == "plain" && (ver == TextVersion || ver == "") { if ac.Type == "text" && ac.SubType == "plain" && (ver == TextVersion || ver == "") {
return FmtText return fmtText + escapingScheme
} }
} }
return FmtText return fmtText + escapingScheme
} }
// NegotiateIncludingOpenMetrics works like Negotiate but includes // NegotiateIncludingOpenMetrics works like Negotiate but includes
@ -84,29 +95,40 @@ func Negotiate(h http.Header) Format {
// temporary and will disappear once FmtOpenMetrics is fully supported and as // temporary and will disappear once FmtOpenMetrics is fully supported and as
// such may be negotiated by the normal Negotiate function. // such may be negotiated by the normal Negotiate function.
func NegotiateIncludingOpenMetrics(h http.Header) Format { func NegotiateIncludingOpenMetrics(h http.Header) Format {
escapingScheme := Format(fmt.Sprintf("; escaping=%s", Format(model.NameEscapingScheme.String())))
for _, ac := range goautoneg.ParseAccept(h.Get(hdrAccept)) { for _, ac := range goautoneg.ParseAccept(h.Get(hdrAccept)) {
if escapeParam := ac.Params[model.EscapingKey]; escapeParam != "" {
switch Format(escapeParam) {
case model.AllowUTF8, model.EscapeUnderscores, model.EscapeDots, model.EscapeValues:
escapingScheme = Format(fmt.Sprintf("; escaping=%s", escapeParam))
default:
// If the escaping parameter is unknown, ignore it.
}
}
ver := ac.Params["version"] ver := ac.Params["version"]
if ac.Type+"/"+ac.SubType == ProtoType && ac.Params["proto"] == ProtoProtocol { if ac.Type+"/"+ac.SubType == ProtoType && ac.Params["proto"] == ProtoProtocol {
switch ac.Params["encoding"] { switch ac.Params["encoding"] {
case "delimited": case "delimited":
return FmtProtoDelim return fmtProtoDelim + escapingScheme
case "text": case "text":
return FmtProtoText return fmtProtoText + escapingScheme
case "compact-text": case "compact-text":
return FmtProtoCompact return fmtProtoCompact + escapingScheme
} }
} }
if ac.Type == "text" && ac.SubType == "plain" && (ver == TextVersion || ver == "") { if ac.Type == "text" && ac.SubType == "plain" && (ver == TextVersion || ver == "") {
return FmtText return fmtText + escapingScheme
} }
if ac.Type+"/"+ac.SubType == OpenMetricsType && (ver == OpenMetricsVersion_0_0_1 || ver == OpenMetricsVersion_1_0_0 || ver == "") { if ac.Type+"/"+ac.SubType == OpenMetricsType && (ver == OpenMetricsVersion_0_0_1 || ver == OpenMetricsVersion_1_0_0 || ver == "") {
if ver == OpenMetricsVersion_1_0_0 { switch ver {
return FmtOpenMetrics_1_0_0 case OpenMetricsVersion_1_0_0:
return fmtOpenMetrics_1_0_0 + escapingScheme
default:
return fmtOpenMetrics_0_0_1 + escapingScheme
} }
return FmtOpenMetrics_0_0_1
} }
} }
return FmtText return fmtText + escapingScheme
} }
// NewEncoder returns a new encoder based on content type negotiation. All // NewEncoder returns a new encoder based on content type negotiation. All
@ -115,44 +137,48 @@ func NegotiateIncludingOpenMetrics(h http.Header) Format {
// for FmtOpenMetrics, but a future (breaking) release will add the Close method // for FmtOpenMetrics, but a future (breaking) release will add the Close method
// to the Encoder interface directly. The current version of the Encoder // to the Encoder interface directly. The current version of the Encoder
// interface is kept for backwards compatibility. // interface is kept for backwards compatibility.
// In cases where the Format does not allow for UTF-8 names, the global
// NameEscapingScheme will be applied.
func NewEncoder(w io.Writer, format Format) Encoder { func NewEncoder(w io.Writer, format Format) Encoder {
switch format { escapingScheme := format.ToEscapingScheme()
case FmtProtoDelim:
switch format.FormatType() {
case TypeProtoDelim:
return encoderCloser{ return encoderCloser{
encode: func(v *dto.MetricFamily) error { encode: func(v *dto.MetricFamily) error {
_, err := pbutil.WriteDelimited(w, v) _, err := protodelim.MarshalTo(w, v)
return err return err
}, },
close: func() error { return nil }, close: func() error { return nil },
} }
case FmtProtoCompact: case TypeProtoCompact:
return encoderCloser{ return encoderCloser{
encode: func(v *dto.MetricFamily) error { encode: func(v *dto.MetricFamily) error {
_, err := fmt.Fprintln(w, v.String()) _, err := fmt.Fprintln(w, model.EscapeMetricFamily(v, escapingScheme).String())
return err return err
}, },
close: func() error { return nil }, close: func() error { return nil },
} }
case FmtProtoText: case TypeProtoText:
return encoderCloser{ return encoderCloser{
encode: func(v *dto.MetricFamily) error { encode: func(v *dto.MetricFamily) error {
_, err := fmt.Fprintln(w, prototext.Format(v)) _, err := fmt.Fprintln(w, prototext.Format(model.EscapeMetricFamily(v, escapingScheme)))
return err return err
}, },
close: func() error { return nil }, close: func() error { return nil },
} }
case FmtText: case TypeTextPlain:
return encoderCloser{ return encoderCloser{
encode: func(v *dto.MetricFamily) error { encode: func(v *dto.MetricFamily) error {
_, err := MetricFamilyToText(w, v) _, err := MetricFamilyToText(w, model.EscapeMetricFamily(v, escapingScheme))
return err return err
}, },
close: func() error { return nil }, close: func() error { return nil },
} }
case FmtOpenMetrics_0_0_1, FmtOpenMetrics_1_0_0: case TypeOpenMetrics:
return encoderCloser{ return encoderCloser{
encode: func(v *dto.MetricFamily) error { encode: func(v *dto.MetricFamily) error {
_, err := MetricFamilyToOpenMetrics(w, v) _, err := MetricFamilyToOpenMetrics(w, model.EscapeMetricFamily(v, escapingScheme))
return err return err
}, },
close: func() error { close: func() error {

View File

@ -14,30 +14,154 @@
// Package expfmt contains tools for reading and writing Prometheus metrics. // Package expfmt contains tools for reading and writing Prometheus metrics.
package expfmt package expfmt
import (
"strings"
"github.com/prometheus/common/model"
)
// Format specifies the HTTP content type of the different wire protocols. // Format specifies the HTTP content type of the different wire protocols.
type Format string type Format string
// Constants to assemble the Content-Type values for the different wire protocols. // Constants to assemble the Content-Type values for the different wire
// protocols. The Content-Type strings here are all for the legacy exposition
// formats, where valid characters for metric names and label names are limited.
// Support for arbitrary UTF-8 characters in those names is already partially
// implemented in this module (see model.ValidationScheme), but to actually use
// it on the wire, new content-type strings will have to be agreed upon and
// added here.
const ( const (
TextVersion = "0.0.4" TextVersion = "0.0.4"
ProtoType = `application/vnd.google.protobuf` ProtoType = `application/vnd.google.protobuf`
ProtoProtocol = `io.prometheus.client.MetricFamily` ProtoProtocol = `io.prometheus.client.MetricFamily`
ProtoFmt = ProtoType + "; proto=" + ProtoProtocol + ";" protoFmt = ProtoType + "; proto=" + ProtoProtocol + ";"
OpenMetricsType = `application/openmetrics-text` OpenMetricsType = `application/openmetrics-text`
OpenMetricsVersion_0_0_1 = "0.0.1" OpenMetricsVersion_0_0_1 = "0.0.1"
OpenMetricsVersion_1_0_0 = "1.0.0" OpenMetricsVersion_1_0_0 = "1.0.0"
// The Content-Type values for the different wire protocols. // The Content-Type values for the different wire protocols. Note that these
FmtUnknown Format = `<unknown>` // values are now unexported. If code was relying on comparisons to these
FmtText Format = `text/plain; version=` + TextVersion + `; charset=utf-8` // constants, instead use FormatType().
FmtProtoDelim Format = ProtoFmt + ` encoding=delimited` fmtUnknown Format = `<unknown>`
FmtProtoText Format = ProtoFmt + ` encoding=text` fmtText Format = `text/plain; version=` + TextVersion + `; charset=utf-8`
FmtProtoCompact Format = ProtoFmt + ` encoding=compact-text` fmtProtoDelim Format = protoFmt + ` encoding=delimited`
FmtOpenMetrics_1_0_0 Format = OpenMetricsType + `; version=` + OpenMetricsVersion_1_0_0 + `; charset=utf-8` fmtProtoText Format = protoFmt + ` encoding=text`
FmtOpenMetrics_0_0_1 Format = OpenMetricsType + `; version=` + OpenMetricsVersion_0_0_1 + `; charset=utf-8` fmtProtoCompact Format = protoFmt + ` encoding=compact-text`
fmtOpenMetrics_1_0_0 Format = OpenMetricsType + `; version=` + OpenMetricsVersion_1_0_0 + `; charset=utf-8`
fmtOpenMetrics_0_0_1 Format = OpenMetricsType + `; version=` + OpenMetricsVersion_0_0_1 + `; charset=utf-8`
) )
const ( const (
hdrContentType = "Content-Type" hdrContentType = "Content-Type"
hdrAccept = "Accept" hdrAccept = "Accept"
) )
// FormatType is a Go enum representing the overall category for the given
// Format. As the number of Format permutations increases, doing basic string
// comparisons are not feasible, so this enum captures the most useful
// high-level attribute of the Format string.
type FormatType int
const (
TypeUnknown = iota
TypeProtoCompact
TypeProtoDelim
TypeProtoText
TypeTextPlain
TypeOpenMetrics
)
// NewFormat generates a new Format from the type provided. Mostly used for
// tests, most Formats should be generated as part of content negotiation in
// encode.go.
func NewFormat(t FormatType) Format {
switch t {
case TypeProtoCompact:
return fmtProtoCompact
case TypeProtoDelim:
return fmtProtoDelim
case TypeProtoText:
return fmtProtoText
case TypeTextPlain:
return fmtText
case TypeOpenMetrics:
return fmtOpenMetrics_1_0_0
default:
return fmtUnknown
}
}
// FormatType deduces an overall FormatType for the given format.
func (f Format) FormatType() FormatType {
toks := strings.Split(string(f), ";")
if len(toks) < 2 {
return TypeUnknown
}
params := make(map[string]string)
for i, t := range toks {
if i == 0 {
continue
}
args := strings.Split(t, "=")
if len(args) != 2 {
continue
}
params[strings.TrimSpace(args[0])] = strings.TrimSpace(args[1])
}
switch strings.TrimSpace(toks[0]) {
case ProtoType:
if params["proto"] != ProtoProtocol {
return TypeUnknown
}
switch params["encoding"] {
case "delimited":
return TypeProtoDelim
case "text":
return TypeProtoText
case "compact-text":
return TypeProtoCompact
default:
return TypeUnknown
}
case OpenMetricsType:
if params["charset"] != "utf-8" {
return TypeUnknown
}
return TypeOpenMetrics
case "text/plain":
v, ok := params["version"]
if !ok {
return TypeTextPlain
}
if v == TextVersion {
return TypeTextPlain
}
return TypeUnknown
default:
return TypeUnknown
}
}
// ToEscapingScheme returns an EscapingScheme depending on the Format. Iff the
// Format contains a escaping=allow-utf-8 term, it will select NoEscaping. If a valid
// "escaping" term exists, that will be used. Otherwise, the global default will
// be returned.
func (format Format) ToEscapingScheme() model.EscapingScheme {
for _, p := range strings.Split(string(format), ";") {
toks := strings.Split(p, "=")
if len(toks) != 2 {
continue
}
key, value := strings.TrimSpace(toks[0]), strings.TrimSpace(toks[1])
if key == model.EscapingKey {
scheme, err := model.ToEscapingScheme(value)
if err != nil {
return model.NameEscapingScheme
}
return scheme
}
}
return model.NameEscapingScheme
}

View File

@ -35,6 +35,18 @@ import (
// sanity checks. If the input contains duplicate metrics or invalid metric or // sanity checks. If the input contains duplicate metrics or invalid metric or
// label names, the conversion will result in invalid text format output. // label names, the conversion will result in invalid text format output.
// //
// If metric names conform to the legacy validation pattern, they will be placed
// outside the brackets in the traditional way, like `foo{}`. If the metric name
// fails the legacy validation check, it will be placed quoted inside the
// brackets: `{"foo"}`. As stated above, the input is assumed to be santized and
// no error will be thrown in this case.
//
// Similar to metric names, if label names conform to the legacy validation
// pattern, they will be unquoted as normal, like `foo{bar="baz"}`. If the label
// name fails the legacy validation check, it will be quoted:
// `foo{"bar"="baz"}`. As stated above, the input is assumed to be santized and
// no error will be thrown in this case.
//
// This function fulfills the type 'expfmt.encoder'. // This function fulfills the type 'expfmt.encoder'.
// //
// Note that OpenMetrics requires a final `# EOF` line. Since this function acts // Note that OpenMetrics requires a final `# EOF` line. Since this function acts
@ -98,7 +110,7 @@ func MetricFamilyToOpenMetrics(out io.Writer, in *dto.MetricFamily) (written int
if err != nil { if err != nil {
return return
} }
n, err = w.WriteString(shortName) n, err = writeName(w, shortName)
written += n written += n
if err != nil { if err != nil {
return return
@ -124,7 +136,7 @@ func MetricFamilyToOpenMetrics(out io.Writer, in *dto.MetricFamily) (written int
if err != nil { if err != nil {
return return
} }
n, err = w.WriteString(shortName) n, err = writeName(w, shortName)
written += n written += n
if err != nil { if err != nil {
return return
@ -303,21 +315,9 @@ func writeOpenMetricsSample(
floatValue float64, intValue uint64, useIntValue bool, floatValue float64, intValue uint64, useIntValue bool,
exemplar *dto.Exemplar, exemplar *dto.Exemplar,
) (int, error) { ) (int, error) {
var written int written := 0
n, err := w.WriteString(name) n, err := writeOpenMetricsNameAndLabelPairs(
written += n w, name+suffix, metric.Label, additionalLabelName, additionalLabelValue,
if err != nil {
return written, err
}
if suffix != "" {
n, err = w.WriteString(suffix)
written += n
if err != nil {
return written, err
}
}
n, err = writeOpenMetricsLabelPairs(
w, metric.Label, additionalLabelName, additionalLabelValue,
) )
written += n written += n
if err != nil { if err != nil {
@ -365,27 +365,58 @@ func writeOpenMetricsSample(
return written, nil return written, nil
} }
// writeOpenMetricsLabelPairs works like writeOpenMetrics but formats the float // writeOpenMetricsNameAndLabelPairs works like writeOpenMetricsSample but
// in OpenMetrics style. // formats the float in OpenMetrics style.
func writeOpenMetricsLabelPairs( func writeOpenMetricsNameAndLabelPairs(
w enhancedWriter, w enhancedWriter,
name string,
in []*dto.LabelPair, in []*dto.LabelPair,
additionalLabelName string, additionalLabelValue float64, additionalLabelName string, additionalLabelValue float64,
) (int, error) { ) (int, error) {
if len(in) == 0 && additionalLabelName == "" {
return 0, nil
}
var ( var (
written int written int
separator byte = '{' separator byte = '{'
metricInsideBraces = false
) )
if name != "" {
// If the name does not pass the legacy validity check, we must put the
// metric name inside the braces, quoted.
if !model.IsValidLegacyMetricName(model.LabelValue(name)) {
metricInsideBraces = true
err := w.WriteByte(separator)
written++
if err != nil {
return written, err
}
separator = ','
}
n, err := writeName(w, name)
written += n
if err != nil {
return written, err
}
}
if len(in) == 0 && additionalLabelName == "" {
if metricInsideBraces {
err := w.WriteByte('}')
written++
if err != nil {
return written, err
}
}
return written, nil
}
for _, lp := range in { for _, lp := range in {
err := w.WriteByte(separator) err := w.WriteByte(separator)
written++ written++
if err != nil { if err != nil {
return written, err return written, err
} }
n, err := w.WriteString(lp.GetName()) n, err := writeName(w, lp.GetName())
written += n written += n
if err != nil { if err != nil {
return written, err return written, err
@ -451,7 +482,7 @@ func writeExemplar(w enhancedWriter, e *dto.Exemplar) (int, error) {
if err != nil { if err != nil {
return written, err return written, err
} }
n, err = writeOpenMetricsLabelPairs(w, e.Label, "", 0) n, err = writeOpenMetricsNameAndLabelPairs(w, "", e.Label, "", 0)
written += n written += n
if err != nil { if err != nil {
return written, err return written, err

View File

@ -62,6 +62,18 @@ var (
// contains duplicate metrics or invalid metric or label names, the conversion // contains duplicate metrics or invalid metric or label names, the conversion
// will result in invalid text format output. // will result in invalid text format output.
// //
// If metric names conform to the legacy validation pattern, they will be placed
// outside the brackets in the traditional way, like `foo{}`. If the metric name
// fails the legacy validation check, it will be placed quoted inside the
// brackets: `{"foo"}`. As stated above, the input is assumed to be santized and
// no error will be thrown in this case.
//
// Similar to metric names, if label names conform to the legacy validation
// pattern, they will be unquoted as normal, like `foo{bar="baz"}`. If the label
// name fails the legacy validation check, it will be quoted:
// `foo{"bar"="baz"}`. As stated above, the input is assumed to be santized and
// no error will be thrown in this case.
//
// This method fulfills the type 'prometheus.encoder'. // This method fulfills the type 'prometheus.encoder'.
func MetricFamilyToText(out io.Writer, in *dto.MetricFamily) (written int, err error) { func MetricFamilyToText(out io.Writer, in *dto.MetricFamily) (written int, err error) {
// Fail-fast checks. // Fail-fast checks.
@ -98,7 +110,7 @@ func MetricFamilyToText(out io.Writer, in *dto.MetricFamily) (written int, err e
if err != nil { if err != nil {
return return
} }
n, err = w.WriteString(name) n, err = writeName(w, name)
written += n written += n
if err != nil { if err != nil {
return return
@ -124,7 +136,7 @@ func MetricFamilyToText(out io.Writer, in *dto.MetricFamily) (written int, err e
if err != nil { if err != nil {
return return
} }
n, err = w.WriteString(name) n, err = writeName(w, name)
written += n written += n
if err != nil { if err != nil {
return return
@ -280,21 +292,9 @@ func writeSample(
additionalLabelName string, additionalLabelValue float64, additionalLabelName string, additionalLabelValue float64,
value float64, value float64,
) (int, error) { ) (int, error) {
var written int written := 0
n, err := w.WriteString(name) n, err := writeNameAndLabelPairs(
written += n w, name+suffix, metric.Label, additionalLabelName, additionalLabelValue,
if err != nil {
return written, err
}
if suffix != "" {
n, err = w.WriteString(suffix)
written += n
if err != nil {
return written, err
}
}
n, err = writeLabelPairs(
w, metric.Label, additionalLabelName, additionalLabelValue,
) )
written += n written += n
if err != nil { if err != nil {
@ -330,32 +330,64 @@ func writeSample(
return written, nil return written, nil
} }
// writeLabelPairs converts a slice of LabelPair proto messages plus the // writeNameAndLabelPairs converts a slice of LabelPair proto messages plus the
// explicitly given additional label pair into text formatted as required by the // explicitly given metric name and additional label pair into text formatted as
// text format and writes it to 'w'. An empty slice in combination with an empty // required by the text format and writes it to 'w'. An empty slice in
// string 'additionalLabelName' results in nothing being written. Otherwise, the // combination with an empty string 'additionalLabelName' results in nothing
// label pairs are written, escaped as required by the text format, and enclosed // being written. Otherwise, the label pairs are written, escaped as required by
// in '{...}'. The function returns the number of bytes written and any error // the text format, and enclosed in '{...}'. The function returns the number of
// encountered. // bytes written and any error encountered. If the metric name is not
func writeLabelPairs( // legacy-valid, it will be put inside the brackets as well. Legacy-invalid
// label names will also be quoted.
func writeNameAndLabelPairs(
w enhancedWriter, w enhancedWriter,
name string,
in []*dto.LabelPair, in []*dto.LabelPair,
additionalLabelName string, additionalLabelValue float64, additionalLabelName string, additionalLabelValue float64,
) (int, error) { ) (int, error) {
if len(in) == 0 && additionalLabelName == "" {
return 0, nil
}
var ( var (
written int written int
separator byte = '{' separator byte = '{'
metricInsideBraces = false
) )
if name != "" {
// If the name does not pass the legacy validity check, we must put the
// metric name inside the braces.
if !model.IsValidLegacyMetricName(model.LabelValue(name)) {
metricInsideBraces = true
err := w.WriteByte(separator)
written++
if err != nil {
return written, err
}
separator = ','
}
n, err := writeName(w, name)
written += n
if err != nil {
return written, err
}
}
if len(in) == 0 && additionalLabelName == "" {
if metricInsideBraces {
err := w.WriteByte('}')
written++
if err != nil {
return written, err
}
}
return written, nil
}
for _, lp := range in { for _, lp := range in {
err := w.WriteByte(separator) err := w.WriteByte(separator)
written++ written++
if err != nil { if err != nil {
return written, err return written, err
} }
n, err := w.WriteString(lp.GetName()) n, err := writeName(w, lp.GetName())
written += n written += n
if err != nil { if err != nil {
return written, err return written, err
@ -462,3 +494,27 @@ func writeInt(w enhancedWriter, i int64) (int, error) {
numBufPool.Put(bp) numBufPool.Put(bp)
return written, err return written, err
} }
// writeName writes a string as-is if it complies with the legacy naming
// scheme, or escapes it in double quotes if not.
func writeName(w enhancedWriter, name string) (int, error) {
if model.IsValidLegacyMetricName(model.LabelValue(name)) {
return w.WriteString(name)
}
var written int
var err error
err = w.WriteByte('"')
written++
if err != nil {
return written, err
}
var n int
n, err = writeEscapedString(w, name, true)
written += n
if err != nil {
return written, err
}
err = w.WriteByte('"')
written++
return written, err
}

View File

@ -16,6 +16,7 @@ package expfmt
import ( import (
"bufio" "bufio"
"bytes" "bytes"
"errors"
"fmt" "fmt"
"io" "io"
"math" "math"
@ -24,8 +25,9 @@ import (
dto "github.com/prometheus/client_model/go" dto "github.com/prometheus/client_model/go"
"github.com/prometheus/common/model"
"google.golang.org/protobuf/proto" "google.golang.org/protobuf/proto"
"github.com/prometheus/common/model"
) )
// A stateFn is a function that represents a state in a state machine. By // A stateFn is a function that represents a state in a state machine. By
@ -112,7 +114,7 @@ func (p *TextParser) TextToMetricFamilies(in io.Reader) (map[string]*dto.MetricF
// stream. Turn this error into something nicer and more // stream. Turn this error into something nicer and more
// meaningful. (io.EOF is often used as a signal for the legitimate end // meaningful. (io.EOF is often used as a signal for the legitimate end
// of an input stream.) // of an input stream.)
if p.err == io.EOF { if p.err != nil && errors.Is(p.err, io.EOF) {
p.parseError("unexpected end of input stream") p.parseError("unexpected end of input stream")
} }
return p.metricFamiliesByName, p.err return p.metricFamiliesByName, p.err
@ -146,7 +148,7 @@ func (p *TextParser) startOfLine() stateFn {
// which is not an error but the signal that we are done. // which is not an error but the signal that we are done.
// Any other error that happens to align with the start of // Any other error that happens to align with the start of
// a line is still an error. // a line is still an error.
if p.err == io.EOF { if errors.Is(p.err, io.EOF) {
p.err = nil p.err = nil
} }
return nil return nil

View File

@ -90,13 +90,13 @@ func (a *Alert) Validate() error {
return fmt.Errorf("start time must be before end time") return fmt.Errorf("start time must be before end time")
} }
if err := a.Labels.Validate(); err != nil { if err := a.Labels.Validate(); err != nil {
return fmt.Errorf("invalid label set: %s", err) return fmt.Errorf("invalid label set: %w", err)
} }
if len(a.Labels) == 0 { if len(a.Labels) == 0 {
return fmt.Errorf("at least one label pair required") return fmt.Errorf("at least one label pair required")
} }
if err := a.Annotations.Validate(); err != nil { if err := a.Annotations.Validate(); err != nil {
return fmt.Errorf("invalid annotations: %s", err) return fmt.Errorf("invalid annotations: %w", err)
} }
return nil return nil
} }

View File

@ -97,17 +97,25 @@ var LabelNameRE = regexp.MustCompile("^[a-zA-Z_][a-zA-Z0-9_]*$")
// therewith. // therewith.
type LabelName string type LabelName string
// IsValid is true iff the label name matches the pattern of LabelNameRE. This // IsValid returns true iff name matches the pattern of LabelNameRE for legacy
// method, however, does not use LabelNameRE for the check but a much faster // names, and iff it's valid UTF-8 if NameValidationScheme is set to
// hardcoded implementation. // UTF8Validation. For the legacy matching, it does not use LabelNameRE for the
// check but a much faster hardcoded implementation.
func (ln LabelName) IsValid() bool { func (ln LabelName) IsValid() bool {
if len(ln) == 0 { if len(ln) == 0 {
return false return false
} }
for i, b := range ln { switch NameValidationScheme {
if !((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || b == '_' || (b >= '0' && b <= '9' && i > 0)) { case LegacyValidation:
return false for i, b := range ln {
if !((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || b == '_' || (b >= '0' && b <= '9' && i > 0)) {
return false
}
} }
case UTF8Validation:
return utf8.ValidString(string(ln))
default:
panic(fmt.Sprintf("Invalid name validation scheme requested: %d", NameValidationScheme))
} }
return true return true
} }
@ -164,7 +172,7 @@ func (l LabelNames) String() string {
// A LabelValue is an associated value for a LabelName. // A LabelValue is an associated value for a LabelName.
type LabelValue string type LabelValue string
// IsValid returns true iff the string is a valid UTF8. // IsValid returns true iff the string is a valid UTF-8.
func (lv LabelValue) IsValid() bool { func (lv LabelValue) IsValid() bool {
return utf8.ValidString(string(lv)) return utf8.ValidString(string(lv))
} }

Some files were not shown because too many files have changed in this diff Show More