mirror of
https://github.com/kubernetes-sigs/descheduler.git
synced 2026-08-19 04:26:25 +00:00
[v0.36.0] release prep: bump k8s/go deps, manifests, docs, and CI matrix
This commit is contained in:
@@ -7,8 +7,8 @@ jobs:
|
||||
deploy:
|
||||
strategy:
|
||||
matrix:
|
||||
k8s-version: ["v1.35.1"]
|
||||
descheduler-version: ["v0.35.0"]
|
||||
k8s-version: ["v1.36.1"]
|
||||
descheduler-version: ["v0.36.0"]
|
||||
descheduler-api: ["v1alpha2"]
|
||||
manifest: ["deployment"]
|
||||
kind-version: ["v0.31.0"] # keep in sync with test/run-e2e-tests.sh
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@
|
||||
# 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.
|
||||
FROM golang:1.25.1
|
||||
FROM golang:1.26.0
|
||||
|
||||
WORKDIR /go/src/sigs.k8s.io/descheduler
|
||||
COPY . .
|
||||
|
||||
@@ -33,11 +33,12 @@ but relies on the default scheduler for that.
|
||||
## ⚠️ Documentation Versions by Release
|
||||
|
||||
If you are using a published release of Descheduler (such as
|
||||
`registry.k8s.io/descheduler/descheduler:v0.35.0`), follow the documentation in
|
||||
`registry.k8s.io/descheduler/descheduler:v0.36.0`), follow the documentation in
|
||||
that version's release branch, as listed below:
|
||||
|
||||
|Descheduler Version|Docs link|
|
||||
|---|---|
|
||||
|v0.36.x|[`release-1.36`](https://github.com/kubernetes-sigs/descheduler/blob/release-1.36/README.md)|
|
||||
|v0.35.x|[`release-1.35`](https://github.com/kubernetes-sigs/descheduler/blob/release-1.35/README.md)|
|
||||
|v0.34.x|[`release-1.34`](https://github.com/kubernetes-sigs/descheduler/blob/release-1.34/README.md)|
|
||||
|v0.33.x|[`release-1.33`](https://github.com/kubernetes-sigs/descheduler/blob/release-1.33/README.md)|
|
||||
@@ -1159,6 +1160,7 @@ packages that it is compiled with.
|
||||
|
||||
| Descheduler | Supported Kubernetes Version |
|
||||
|-------------|------------------------------|
|
||||
| v0.36 | v1.36 |
|
||||
| v0.35 | v1.35 |
|
||||
| v0.34 | v1.34 |
|
||||
| v0.33 | v1.33 |
|
||||
|
||||
@@ -57,6 +57,7 @@ descheduler [flags]
|
||||
--tls-cipher-suites strings Comma-separated list of cipher suites for the server. If omitted, the default Go cipher suites will be used.
|
||||
Preferred values: TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384, TLS_CHACHA20_POLY1305_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256.
|
||||
Insecure values: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_3DES_EDE_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_256_GCM_SHA384, TLS_RSA_WITH_RC4_128_SHA.
|
||||
--tls-curve-preferences int32Slice Comma-separated list of numeric Go crypto/tls CurveID values, as the allowed key exchange mechanisms for the server. The supported values depend on the Go version used. See https://pkg.go.dev/crypto/tls#CurveID for values supported for each Go version. The order of the list is ignored, and key exchange mechanisms are chosen by Go from this list using an internal preference order. If omitted, the default Go curves will be used. (default [])
|
||||
--tls-min-version string Minimum TLS version supported. Possible values: VersionTLS10, VersionTLS11, VersionTLS12, VersionTLS13
|
||||
--tls-private-key-file string File containing the default x509 private key matching --tls-cert-file.
|
||||
--tls-sni-cert-key namedCertKey A pair of x509 certificate and private key file paths, optionally suffixed with a list of domain patterns which are fully qualified domain names, possibly with prefixed wildcard segments. The domain patterns also allow IP addresses, but IPs should only be used if the apiserver has visibility to the IP address requested by a client. If no domain patterns are provided, the names of the certificate are extracted. Non-wildcard matches trump over wildcard matches, explicit domain patterns trump over extracted names. For multiple key/certificate pairs, use the --tls-sni-cert-key multiple times. Examples: "example.crt,example.key" or "foo.crt,foo.key:*.foo.com,foo.com". (default [])
|
||||
|
||||
@@ -4,6 +4,7 @@ Starting with descheduler release v0.10.0 container images are available in the
|
||||
|
||||
Descheduler Version | Container Image | Architectures |
|
||||
------------------- |-------------------------------------------------|-------------------------|
|
||||
v0.36.0 | registry.k8s.io/descheduler/descheduler:v0.36.0 | AMD64<br>ARM64<br>ARMv7 |
|
||||
v0.35.0 | registry.k8s.io/descheduler/descheduler:v0.35.0 | AMD64<br>ARM64<br>ARMv7 |
|
||||
v0.34.0 | registry.k8s.io/descheduler/descheduler:v0.34.0 | AMD64<br>ARM64<br>ARMv7 |
|
||||
v0.33.0 | registry.k8s.io/descheduler/descheduler:v0.33.0 | AMD64<br>ARM64<br>ARMv7 |
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
module sigs.k8s.io/descheduler
|
||||
|
||||
go 1.25.0
|
||||
go 1.26.0
|
||||
|
||||
toolchain go1.25.1
|
||||
|
||||
godebug default=go1.25
|
||||
godebug default=go1.26
|
||||
|
||||
require (
|
||||
github.com/client9/misspell v0.3.4
|
||||
@@ -18,18 +16,18 @@ require (
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0
|
||||
go.opentelemetry.io/otel/sdk v1.43.0
|
||||
go.opentelemetry.io/otel/trace v1.43.0
|
||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56
|
||||
google.golang.org/grpc v1.80.0
|
||||
k8s.io/api v0.35.1
|
||||
k8s.io/apimachinery v0.35.1
|
||||
k8s.io/apiserver v0.35.1
|
||||
k8s.io/client-go v0.35.1
|
||||
k8s.io/code-generator v0.35.1
|
||||
k8s.io/component-base v0.35.1
|
||||
k8s.io/component-helpers v0.35.1
|
||||
k8s.io/klog/v2 v2.130.1
|
||||
k8s.io/metrics v0.35.1
|
||||
k8s.io/utils v0.0.0-20260108192941-914a6e750570
|
||||
golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93
|
||||
google.golang.org/grpc v1.81.1
|
||||
k8s.io/api v0.36.1
|
||||
k8s.io/apimachinery v0.36.1
|
||||
k8s.io/apiserver v0.36.1
|
||||
k8s.io/client-go v0.36.1
|
||||
k8s.io/code-generator v0.36.1
|
||||
k8s.io/component-base v0.36.1
|
||||
k8s.io/component-helpers v0.36.1
|
||||
k8s.io/klog/v2 v2.140.0
|
||||
k8s.io/metrics v0.36.1
|
||||
k8s.io/utils v0.0.0-20260507154919-ff6756f316d2
|
||||
kubevirt.io/api v1.3.0
|
||||
kubevirt.io/client-go v1.3.0
|
||||
sigs.k8s.io/mdtoc v1.4.0
|
||||
@@ -47,10 +45,10 @@ require (
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be // indirect
|
||||
github.com/coreos/go-semver v0.3.1 // indirect
|
||||
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
|
||||
github.com/coreos/go-systemd/v22 v22.7.0 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/emicklei/go-restful/v3 v3.12.2 // indirect
|
||||
github.com/emicklei/go-restful/v3 v3.13.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/fsnotify/fsnotify v1.9.0 // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
|
||||
@@ -62,25 +60,34 @@ require (
|
||||
github.com/go-logr/zapr v1.3.0 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.21.0 // indirect
|
||||
github.com/go-openapi/jsonreference v0.20.2 // indirect
|
||||
github.com/go-openapi/swag v0.23.0 // indirect
|
||||
github.com/go-openapi/swag v0.25.4 // indirect
|
||||
github.com/go-openapi/swag/cmdutils v0.25.4 // indirect
|
||||
github.com/go-openapi/swag/conv v0.25.4 // indirect
|
||||
github.com/go-openapi/swag/fileutils v0.25.4 // indirect
|
||||
github.com/go-openapi/swag/jsonname v0.25.4 // indirect
|
||||
github.com/go-openapi/swag/jsonutils v0.25.4 // indirect
|
||||
github.com/go-openapi/swag/loading v0.25.4 // indirect
|
||||
github.com/go-openapi/swag/mangling v0.25.4 // indirect
|
||||
github.com/go-openapi/swag/netutils v0.25.4 // indirect
|
||||
github.com/go-openapi/swag/stringutils v0.25.4 // indirect
|
||||
github.com/go-openapi/swag/typeutils v0.25.4 // indirect
|
||||
github.com/go-openapi/swag/yamlutils v0.25.4 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang-jwt/jwt/v5 v5.3.0 // indirect
|
||||
github.com/golang/glog v1.2.5 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/gomarkdown/markdown v0.0.0-20260217112301-37c66b85d6ab // indirect
|
||||
github.com/google/btree v1.1.3 // indirect
|
||||
github.com/google/cel-go v0.26.0 // indirect
|
||||
github.com/google/gnostic-models v0.7.0 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/jpillora/backoff v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/kylelemons/godebug v1.1.0 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/mmarkdown/mmark v2.0.40+incompatible // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
|
||||
@@ -90,50 +97,50 @@ require (
|
||||
github.com/openshift/custom-resource-status v1.1.2 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/prometheus/client_model v0.6.2 // indirect
|
||||
github.com/prometheus/procfs v0.16.1 // indirect
|
||||
github.com/prometheus/procfs v0.19.2 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/stoewer/go-strcase v1.3.0 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
go.etcd.io/etcd/api/v3 v3.6.5 // indirect
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.6.5 // indirect
|
||||
go.etcd.io/etcd/client/v3 v3.6.5 // indirect
|
||||
go.etcd.io/etcd/api/v3 v3.6.8 // indirect
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.6.8 // indirect
|
||||
go.etcd.io/etcd/client/v3 v3.6.8 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.66.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.66.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.65.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.65.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.43.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.10.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.27.0 // indirect
|
||||
go.uber.org/zap v1.27.1 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
golang.org/x/crypto v0.49.0 // indirect
|
||||
golang.org/x/mod v0.33.0 // indirect
|
||||
golang.org/x/net v0.52.0 // indirect
|
||||
golang.org/x/oauth2 v0.35.0 // indirect
|
||||
golang.org/x/oauth2 v0.36.0 // indirect
|
||||
golang.org/x/sync v0.20.0 // indirect
|
||||
golang.org/x/sys v0.42.0 // indirect
|
||||
golang.org/x/term v0.41.0 // indirect
|
||||
golang.org/x/text v0.35.0 // indirect
|
||||
golang.org/x/time v0.9.0 // indirect
|
||||
golang.org/x/time v0.14.0 // indirect
|
||||
golang.org/x/tools v0.42.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9 // indirect
|
||||
google.golang.org/protobuf v1.36.11 // indirect
|
||||
google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af // indirect
|
||||
gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
k8s.io/apiextensions-apiserver v0.30.0 // indirect
|
||||
k8s.io/gengo/v2 v2.0.0-20250922181213-ec3ebc5fd46b // indirect
|
||||
k8s.io/kms v0.35.1 // indirect
|
||||
k8s.io/kms v0.36.1 // indirect
|
||||
k8s.io/kube-openapi v0.30.0 // indirect
|
||||
k8s.io/streaming v0.36.1 // indirect
|
||||
kubevirt.io/containerized-data-importer-api v1.57.0-alpha1 // indirect
|
||||
kubevirt.io/controller-lifecycle-operator-sdk/api v0.0.0-20220329064328-f3cc58c6ed90 // indirect
|
||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 // indirect
|
||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.34.0 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect
|
||||
sigs.k8s.io/randfill v1.0.0 // indirect
|
||||
sigs.k8s.io/release-utils v0.8.3 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v6 v6.3.2 // indirect
|
||||
)
|
||||
|
||||
replace k8s.io/kube-openapi => k8s.io/kube-openapi v0.0.0-20260127142750-a19766b6e2d4
|
||||
replace k8s.io/kube-openapi => k8s.io/kube-openapi v0.0.0-20260512234627-ef417d054102
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
cel.dev/expr v0.24.0 h1:56OvJKSH3hDGL0ml5uSxZmz3/3Pq4tJ+fb1unVLAFcY=
|
||||
cel.dev/expr v0.24.0/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw=
|
||||
cel.dev/expr v0.25.1 h1:1KrZg61W6TWSxuNZ37Xy49ps13NUovb66QLprthtwi4=
|
||||
cel.dev/expr v0.25.1/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4=
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0=
|
||||
github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
|
||||
github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I=
|
||||
github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c=
|
||||
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
@@ -22,23 +18,17 @@ github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F9
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/chromedp/cdproto v0.0.0-20230802225258-3cf4e6d46a89/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs=
|
||||
github.com/chromedp/chromedp v0.9.2/go.mod h1:LkSXJKONWTCHAfQasKFUZI+mxqS4tZqhmtGzzhLsnLs=
|
||||
github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8=
|
||||
github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be h1:J5BL2kskAlV9ckgEsNQXscjIaLiOYiZ75d4e94E6dcQ=
|
||||
github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be/go.mod h1:mk5IQ+Y0ZeO87b858TlA645sVcEcbiX6YqP98kt+7+w=
|
||||
github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4=
|
||||
github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/coreos/go-systemd/v22 v22.7.0 h1:LAEzFkke61DFROc7zNLX/WA2i5J8gYqe0rSj9KI28KA=
|
||||
github.com/coreos/go-systemd/v22 v22.7.0/go.mod h1:xNUYtjHu2EDXbsxz1i41wouACIwT7Ybq9o0BQhMwD0w=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6 h1:XJtiaUW6dEEqVuZiMTn1ldk455QWwEIsMIJlo5vtkx0=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
@@ -52,9 +42,8 @@ github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+m
|
||||
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
|
||||
github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
||||
github.com/emicklei/go-restful v2.15.0+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
||||
github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
|
||||
github.com/emicklei/go-restful/v3 v3.12.2 h1:DhwDP0vY3k8ZzE0RunuJy8GhNpPL6zqLkDf9B/a0/xU=
|
||||
github.com/emicklei/go-restful/v3 v3.12.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
|
||||
github.com/emicklei/go-restful/v3 v3.13.0 h1:C4Bl2xDndpU6nJ4bc1jXd+uTmYPVUwkD6bFY/oTyCes=
|
||||
github.com/emicklei/go-restful/v3 v3.13.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||
@@ -76,8 +65,6 @@ github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7
|
||||
github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
|
||||
github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||
@@ -92,24 +79,47 @@ github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1
|
||||
github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
|
||||
github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg=
|
||||
github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns=
|
||||
github.com/go-openapi/jsonreference v0.20.1/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
|
||||
github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=
|
||||
github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
|
||||
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||
github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
|
||||
github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
|
||||
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
|
||||
github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
|
||||
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
|
||||
github.com/go-openapi/swag v0.25.4 h1:OyUPUFYDPDBMkqyxOTkqDYFnrhuhi9NR6QVUvIochMU=
|
||||
github.com/go-openapi/swag v0.25.4/go.mod h1:zNfJ9WZABGHCFg2RnY0S4IOkAcVTzJ6z2Bi+Q4i6qFQ=
|
||||
github.com/go-openapi/swag/cmdutils v0.25.4 h1:8rYhB5n6WawR192/BfUu2iVlxqVR9aRgGJP6WaBoW+4=
|
||||
github.com/go-openapi/swag/cmdutils v0.25.4/go.mod h1:pdae/AFo6WxLl5L0rq87eRzVPm/XRHM3MoYgRMvG4A0=
|
||||
github.com/go-openapi/swag/conv v0.25.4 h1:/Dd7p0LZXczgUcC/Ikm1+YqVzkEeCc9LnOWjfkpkfe4=
|
||||
github.com/go-openapi/swag/conv v0.25.4/go.mod h1:3LXfie/lwoAv0NHoEuY1hjoFAYkvlqI/Bn5EQDD3PPU=
|
||||
github.com/go-openapi/swag/fileutils v0.25.4 h1:2oI0XNW5y6UWZTC7vAxC8hmsK/tOkWXHJQH4lKjqw+Y=
|
||||
github.com/go-openapi/swag/fileutils v0.25.4/go.mod h1:cdOT/PKbwcysVQ9Tpr0q20lQKH7MGhOEb6EwmHOirUk=
|
||||
github.com/go-openapi/swag/jsonname v0.25.4 h1:bZH0+MsS03MbnwBXYhuTttMOqk+5KcQ9869Vye1bNHI=
|
||||
github.com/go-openapi/swag/jsonname v0.25.4/go.mod h1:GPVEk9CWVhNvWhZgrnvRA6utbAltopbKwDu8mXNUMag=
|
||||
github.com/go-openapi/swag/jsonutils v0.25.4 h1:VSchfbGhD4UTf4vCdR2F4TLBdLwHyUDTd1/q4i+jGZA=
|
||||
github.com/go-openapi/swag/jsonutils v0.25.4/go.mod h1:7OYGXpvVFPn4PpaSdPHJBtF0iGnbEaTk8AvBkoWnaAY=
|
||||
github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.4 h1:IACsSvBhiNJwlDix7wq39SS2Fh7lUOCJRmx/4SN4sVo=
|
||||
github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.4/go.mod h1:Mt0Ost9l3cUzVv4OEZG+WSeoHwjWLnarzMePNDAOBiM=
|
||||
github.com/go-openapi/swag/loading v0.25.4 h1:jN4MvLj0X6yhCDduRsxDDw1aHe+ZWoLjW+9ZQWIKn2s=
|
||||
github.com/go-openapi/swag/loading v0.25.4/go.mod h1:rpUM1ZiyEP9+mNLIQUdMiD7dCETXvkkC30z53i+ftTE=
|
||||
github.com/go-openapi/swag/mangling v0.25.4 h1:2b9kBJk9JvPgxr36V23FxJLdwBrpijI26Bx5JH4Hp48=
|
||||
github.com/go-openapi/swag/mangling v0.25.4/go.mod h1:6dxwu6QyORHpIIApsdZgb6wBk/DPU15MdyYj/ikn0Hg=
|
||||
github.com/go-openapi/swag/netutils v0.25.4 h1:Gqe6K71bGRb3ZQLusdI8p/y1KLgV4M/k+/HzVSqT8H0=
|
||||
github.com/go-openapi/swag/netutils v0.25.4/go.mod h1:m2W8dtdaoX7oj9rEttLyTeEFFEBvnAx9qHd5nJEBzYg=
|
||||
github.com/go-openapi/swag/stringutils v0.25.4 h1:O6dU1Rd8bej4HPA3/CLPciNBBDwZj9HiEpdVsb8B5A8=
|
||||
github.com/go-openapi/swag/stringutils v0.25.4/go.mod h1:GTsRvhJW5xM5gkgiFe0fV3PUlFm0dr8vki6/VSRaZK0=
|
||||
github.com/go-openapi/swag/typeutils v0.25.4 h1:1/fbZOUN472NTc39zpa+YGHn3jzHWhv42wAJSN91wRw=
|
||||
github.com/go-openapi/swag/typeutils v0.25.4/go.mod h1:Ou7g//Wx8tTLS9vG0UmzfCsjZjKhpjxayRKTHXf2pTE=
|
||||
github.com/go-openapi/swag/yamlutils v0.25.4 h1:6jdaeSItEUb7ioS9lFoCZ65Cne1/RZtPBZ9A56h92Sw=
|
||||
github.com/go-openapi/swag/yamlutils v0.25.4/go.mod h1:MNzq1ulQu+yd8Kl7wPOut/YHAAU/H6hL91fF+E2RFwc=
|
||||
github.com/go-openapi/testify/enable/yaml/v2 v2.0.2 h1:0+Y41Pz1NkbTHz8NngxTuAXxEodtNSI1WG1c/m5Akw4=
|
||||
github.com/go-openapi/testify/enable/yaml/v2 v2.0.2/go.mod h1:kme83333GCtJQHXQ8UKX3IBZu6z8T5Dvy5+CW3NLUUg=
|
||||
github.com/go-openapi/testify/v2 v2.0.2 h1:X999g3jeLcoY8qctY/c/Z8iBHTbwLz7R2WXd6Ub6wls=
|
||||
github.com/go-openapi/testify/v2 v2.0.2/go.mod h1:HCPmvFFnheKK2BuwSA0TbbdxJ3I16pjwMkYkP4Ywn54=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
|
||||
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
|
||||
github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
|
||||
github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo=
|
||||
@@ -129,7 +139,6 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/gomarkdown/markdown v0.0.0-20260217112301-37c66b85d6ab h1:VYNivV7P8IRHUam2swVUNkhIdp0LRRFKe4hXNnoZKTc=
|
||||
@@ -145,7 +154,6 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
@@ -153,10 +161,8 @@ github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 h1:k7nVchz72niMH6YLQNvHSdIE7iqsQxK1P41mySCvssg=
|
||||
github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw=
|
||||
github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo=
|
||||
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8=
|
||||
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
@@ -164,25 +170,18 @@ github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97Dwqy
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo=
|
||||
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 h1:qnpSQwGEnkcRpTqNOIR6bJbR0gAorgP9CSALpRcKoAA=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1/go.mod h1:lXGCsh6c22WGtjr+qGHj1otzZpV/1kwTMAqkwZsnWRU=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.0 h1:FbSCl+KggFl+Ocym490i/EyXF4lPgLoUtcSWquBM0Rs=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.0/go.mod h1:qOchhhIlmRcqk/O9uCo/puJlyo07YINaIqdZfZG3Jkc=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.7 h1:X+2YciYSxvMQK0UZ7sg45ZVabVZBeBuvMkmuI2V3Fak=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.7/go.mod h1:lW34nIZuQ8UDPdkon5fmfp2l3+ZkQ2me/+oecHYLOII=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 h1:QGLs/O40yoNK9vmy4rhUGBVyMf1lISBGtXRpsu/Qu/o=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0/go.mod h1:hM2alZsMUni80N33RBe6J0e423LB+odMj7d3EMP9l20=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3 h1:B+8ClL/kCQkRiU82d9xajRPKYMrB7E0MbtzWVi1K4ns=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3/go.mod h1:NbCUVmiS4foBGBHOYlCT25+YmGpJ32dZPi75pGEUpj4=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 h1:HWRh5R2+9EifMyIHV7ZV+MIZqgz+PMpZ14Jynv3O2Zs=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0/go.mod h1:JfhWUomR1baixubs02l85lZYYOm7LV6om4ceouMv45c=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20240312041847-bd984b5ce465/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/jonboulle/clockwork v0.5.0 h1:Hyh9A8u51kptdkR+cqRpT1EebBwTn1oK9YfGYbdFz6I=
|
||||
github.com/jonboulle/clockwork v0.5.0/go.mod h1:3mZlmanh0g2NDKO5TWZVJAfofYk64M7XN3SzBPjZF60=
|
||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA=
|
||||
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
|
||||
@@ -204,11 +203,9 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||
github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs=
|
||||
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/mmarkdown/mmark v2.0.40+incompatible h1:vMeUeDzBK3H+/mU0oMVfMuhSXJlIA+DE/DMPQNAj5C4=
|
||||
github.com/mmarkdown/mmark v2.0.40+incompatible/go.mod h1:Uvmoz7tvsWpr7bMVxIpqZPyN3FbOtzDmnsJDFp7ltJs=
|
||||
@@ -234,54 +231,18 @@ github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9k
|
||||
github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
|
||||
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
|
||||
github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
|
||||
github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
|
||||
github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU=
|
||||
github.com/onsi/ginkgo/v2 v2.1.6/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk=
|
||||
github.com/onsi/ginkgo/v2 v2.3.0/go.mod h1:Eew0uilEqZmIEZr8JrvYlvOM7Rr6xzTmMV8AyFNU9d0=
|
||||
github.com/onsi/ginkgo/v2 v2.4.0/go.mod h1:iHkDK1fKGcBoEHT5W7YBq4RFWaQulw+caOMkAt4OrFo=
|
||||
github.com/onsi/ginkgo/v2 v2.5.0/go.mod h1:Luc4sArBICYCS8THh8v3i3i5CuSZO+RaQRaJoeNwomw=
|
||||
github.com/onsi/ginkgo/v2 v2.7.0/go.mod h1:yjiuMwPokqY1XauOgju45q3sJt6VzQ/Fict1LFVcsAo=
|
||||
github.com/onsi/ginkgo/v2 v2.8.1/go.mod h1:N1/NbDngAFcSLdyZ+/aYTYGSlq9qMCS/cNKGJjy+csc=
|
||||
github.com/onsi/ginkgo/v2 v2.9.0/go.mod h1:4xkjoL/tZv4SMWeww56BU5kAt19mVB47gTWxmrTcxyk=
|
||||
github.com/onsi/ginkgo/v2 v2.9.1/go.mod h1:FEcmzVcCHl+4o9bQZVab+4dC9+j+91t2FHSzmGAPfuo=
|
||||
github.com/onsi/ginkgo/v2 v2.9.2/go.mod h1:WHcJJG2dIlcCqVfBAwUCrJxSPFb6v4azBwgxeMeDuts=
|
||||
github.com/onsi/ginkgo/v2 v2.9.5/go.mod h1:tvAoo1QUJwNEU2ITftXTpR7R1RbCzoZUOs3RonqW57k=
|
||||
github.com/onsi/ginkgo/v2 v2.9.7/go.mod h1:cxrmXWykAwTwhQsJOPfdIDiJ+l2RYq7U8hFU+M/1uw0=
|
||||
github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM=
|
||||
github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o=
|
||||
github.com/onsi/ginkgo/v2 v2.17.1/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs=
|
||||
github.com/onsi/ginkgo/v2 v2.17.2 h1:7eMhcy3GimbsA3hEnVKdw/PQM9XN9krpKVXsZdph0/g=
|
||||
github.com/onsi/ginkgo/v2 v2.17.2/go.mod h1:nP2DPOQoNsQmsVyv5rDA8JkXQoCs6goXIvr/PRJ1eCc=
|
||||
github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To=
|
||||
github.com/onsi/ginkgo/v2 v2.27.2 h1:LzwLj0b89qtIy6SSASkzlNvX6WktqurSHwkk2ipF/Ns=
|
||||
github.com/onsi/ginkgo/v2 v2.27.2/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
|
||||
github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
|
||||
github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro=
|
||||
github.com/onsi/gomega v1.20.1/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo=
|
||||
github.com/onsi/gomega v1.21.1/go.mod h1:iYAIXgPSaDHak0LCMA+AWBpIKBr8WZicMxnE8luStNc=
|
||||
github.com/onsi/gomega v1.22.1/go.mod h1:x6n7VNe4hw0vkyYUM4mjIXx3JbLiPaBPNgB7PRQ1tuM=
|
||||
github.com/onsi/gomega v1.24.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg=
|
||||
github.com/onsi/gomega v1.24.1/go.mod h1:3AOiACssS3/MajrniINInwbfOOtfZvplPzuRSmvt1jM=
|
||||
github.com/onsi/gomega v1.26.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM=
|
||||
github.com/onsi/gomega v1.27.1/go.mod h1:aHX5xOykVYzWOV4WqQy0sy8BQptgukenXpCXfadcIAw=
|
||||
github.com/onsi/gomega v1.27.3/go.mod h1:5vG284IBtfDAmDyrK+eGyZmUgUlmi+Wngqo557cZ6Gw=
|
||||
github.com/onsi/gomega v1.27.4/go.mod h1:riYq/GJKh8hhoM01HN6Vmuy93AarCXCBGpvFDK3q3fQ=
|
||||
github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg=
|
||||
github.com/onsi/gomega v1.27.7/go.mod h1:1p8OOlwo2iUUDsHnOrjE5UKYJ+e3W8eQ3qSlRahPmr4=
|
||||
github.com/onsi/gomega v1.27.8/go.mod h1:2J8vzI/s+2shY9XHRApDkdgPo1TKT7P2u6fXeJKFnNQ=
|
||||
github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M=
|
||||
github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ=
|
||||
github.com/onsi/gomega v1.33.0/go.mod h1:+925n5YtiFsLzzafLUHzVMBpvvRAzrydIBiSIxjX3wY=
|
||||
github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk=
|
||||
github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0=
|
||||
github.com/onsi/gomega v1.38.2 h1:eZCjf2xjZAqe+LeWvKb5weQ+NcPwX84kqJ0cZNxok2A=
|
||||
github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k=
|
||||
github.com/openshift/api v0.0.0-20230503133300-8bbcb7ca7183 h1:t/CahSnpqY46sQR01SoS+Jt0jtjgmhgE6lFmRnO4q70=
|
||||
github.com/openshift/api v0.0.0-20230503133300-8bbcb7ca7183/go.mod h1:4VWG+W22wrB4HfBL88P40DxLEpSOaiBVxUnfalfJo9k=
|
||||
github.com/openshift/custom-resource-status v1.1.2 h1:C3DL44LEbvlbItfd8mT5jWrqPfHnSOQoQf/sypqA6A4=
|
||||
github.com/openshift/custom-resource-status v1.1.2/go.mod h1:DB/Mf2oTeiAmVVX1gN+NEqweonAPY0TKUwADizj8+ZA=
|
||||
github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
@@ -294,10 +255,9 @@ github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNw
|
||||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||
github.com/prometheus/common v0.67.5 h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTUGI4=
|
||||
github.com/prometheus/common v0.67.5/go.mod h1:SjE/0MzDEEAyrdr5Gqc6G+sXI67maCxzaT3A2+HqjUw=
|
||||
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
|
||||
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
|
||||
github.com/prometheus/procfs v0.19.2 h1:zUMhqEW66Ex7OXIiDkll3tl9a1ZdilUOd/F6ZXw4Vws=
|
||||
github.com/prometheus/procfs v0.19.2/go.mod h1:M0aotyiemPhBCM0z5w87kL22CxfcH05ZpYlu+b4J7mw=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
||||
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
||||
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||
@@ -345,78 +305,46 @@ github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
go.etcd.io/bbolt v1.4.3 h1:dEadXpI6G79deX5prL3QRNP6JB8UxVkqo4UPnHaNXJo=
|
||||
go.etcd.io/bbolt v1.4.3/go.mod h1:tKQlpPaYCVFctUIgFKFnAlvbmB3tpy1vkTnDWohtc0E=
|
||||
go.etcd.io/etcd/api/v3 v3.6.5 h1:pMMc42276sgR1j1raO/Qv3QI9Af/AuyQUW6CBAWuntA=
|
||||
go.etcd.io/etcd/api/v3 v3.6.5/go.mod h1:ob0/oWA/UQQlT1BmaEkWQzI0sJ1M0Et0mMpaABxguOQ=
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.6.5 h1:Duz9fAzIZFhYWgRjp/FgNq2gO1jId9Yae/rLn3RrBP8=
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.6.5/go.mod h1:8Wx3eGRPiy0qOFMZT/hfvdos+DjEaPxdIDiCDUv/FQk=
|
||||
go.etcd.io/etcd/client/v3 v3.6.5 h1:yRwZNFBx/35VKHTcLDeO7XVLbCBFbPi+XV4OC3QJf2U=
|
||||
go.etcd.io/etcd/client/v3 v3.6.5/go.mod h1:ZqwG/7TAFZ0BJ0jXRPoJjKQJtbFo/9NIY8uoFFKcCyo=
|
||||
go.etcd.io/etcd/pkg/v3 v3.6.5 h1:byxWB4AqIKI4SBmquZUG1WGtvMfMaorXFoCcFbVeoxM=
|
||||
go.etcd.io/etcd/pkg/v3 v3.6.5/go.mod h1:uqrXrzmMIJDEy5j00bCqhVLzR5jEJIwDp5wTlLwPGOU=
|
||||
go.etcd.io/etcd/server/v3 v3.6.5 h1:4RbUb1Bd4y1WkBHmuF+cZII83JNQMuNXzyjwigQ06y0=
|
||||
go.etcd.io/etcd/server/v3 v3.6.5/go.mod h1:PLuhyVXz8WWRhzXDsl3A3zv/+aK9e4A9lpQkqawIaH0=
|
||||
go.etcd.io/etcd/api/v3 v3.6.8 h1:gqb1VN92TAI6G2FiBvWcqKtHiIjr4SU2GdXxTwyexbM=
|
||||
go.etcd.io/etcd/api/v3 v3.6.8/go.mod h1:qyQj1HZPUV3B5cbAL8scG62+fyz5dSxxu0w8pn28N6Q=
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.6.8 h1:Qs/5C0LNFiqXxYf2GU8MVjYUEXJ6sZaYOz0zEqQgy50=
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.6.8/go.mod h1:GsiTRUZE2318PggZkAo6sWb6l8JLVrnckTNfbG8PWtw=
|
||||
go.etcd.io/etcd/client/v3 v3.6.8 h1:B3G76t1UykqAOrbio7s/EPatixQDkQBevN8/mwiplrY=
|
||||
go.etcd.io/etcd/client/v3 v3.6.8/go.mod h1:MVG4BpSIuumPi+ELF7wYtySETmoTWBHVcDoHdVupwt8=
|
||||
go.etcd.io/etcd/pkg/v3 v3.6.8 h1:Xe+LIL974spy8b4nEx3H0KMr1ofq3r0kh6FbU3aw4es=
|
||||
go.etcd.io/etcd/pkg/v3 v3.6.8/go.mod h1:TRibVNe+FqJIe1abOAA1PsuQ4wqO87ZaOoprg09Tn8c=
|
||||
go.etcd.io/etcd/server/v3 v3.6.8 h1:U2strdSEy1U8qcSzRIdkYpvOPtBy/9i/IfaaCI9flZ4=
|
||||
go.etcd.io/etcd/server/v3 v3.6.8/go.mod h1:88dCtwUnSirkUoJbflQxxWXqtBSZa6lSG0Kuej+dois=
|
||||
go.etcd.io/raft/v3 v3.6.0 h1:5NtvbDVYpnfZWcIHgGRk9DyzkBIXOi8j+DDp1IcnUWQ=
|
||||
go.etcd.io/raft/v3 v3.6.0/go.mod h1:nLvLevg6+xrVtHUmVaTcTz603gQPHfh7kUAwV6YpfGo=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 h1:x7wzEgXfnzJcHDwStJT+mxOz4etr2EcexjqhBvmoakw=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0/go.mod h1:rg+RlpR5dKwaS95IyyZqj5Wd4E13lk/msnTS0Xl9lJM=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.66.0 h1:w/o339tDd6Qtu3+ytwt+/jon2yjAs3Ot8Xq8pelfhSo=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.66.0/go.mod h1:pdhNtM9C4H5fRdrnwO7NjxzQWhKSSxCHk/KluVqDVC0=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.66.0 h1:PnV4kVnw0zOmwwFkAzCN5O07fw1YOIQor120zrh0AVo=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.66.0/go.mod h1:ofAwF4uinaf8SXdVzzbL4OsxJ3VfeEg3f/F6CeF49/Y=
|
||||
go.opentelemetry.io/otel v1.40.0 h1:oA5YeOcpRTXq6NN7frwmwFR0Cn3RhTVZvXsP4duvCms=
|
||||
go.opentelemetry.io/otel v1.40.0/go.mod h1:IMb+uXZUKkMXdPddhwAHm6UfOwJyh4ct1ybIlV14J0g=
|
||||
go.opentelemetry.io/otel v1.41.0 h1:YlEwVsGAlCvczDILpUXpIpPSL/VPugt7zHThEMLce1c=
|
||||
go.opentelemetry.io/otel v1.41.0/go.mod h1:Yt4UwgEKeT05QbLwbyHXEwhnjxNO6D8L5PQP51/46dE=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.65.0 h1:XmiuHzgJt067+a6kwyAzkhXooYVv3/TOw9cM2VfJgUM=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.65.0/go.mod h1:KDgtbWKTQs4bM+VPUr6WlL9m/WXcmkCcBlIzqxPGzmI=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.65.0 h1:7iP2uCb7sGddAr30RRS6xjKy7AZ2JtTOPA3oolgVSw8=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.65.0/go.mod h1:c7hN3ddxs/z6q9xwvfLPk+UHlWRQyaeR1LdgfL/66l0=
|
||||
go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I=
|
||||
go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0 h1:dNzwXjZKpMpE2JhmO+9HsPl42NIXFIFSUSSs0fiqra0=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0/go.mod h1:90PoxvaEB5n6AOdZvi+yWJQoE95U8Dhhw2bSyRqnTD0=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.41.0 h1:ao6Oe+wSebTlQ1OEht7jlYTzQKE+pnx/iNywFvTbuuI=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.41.0/go.mod h1:u3T6vz0gh/NVzgDgiwkgLxpsSF6PaPmo2il0apGJbls=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0 h1:88Y4s2C8oTui1LGM6bTWkw0ICGcOLCAI5l6zsD1j20k=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0/go.mod h1:Vl1/iaggsuRlrHf/hfPJPvVag77kKyvrLeD10kpMl+A=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.36.0 h1:JgtbA0xkWHnTmYk7YusopJFX6uleBmAuZ8n05NEh8nQ=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.36.0/go.mod h1:179AK5aar5R3eS9FucPy6rggvU0g52cvKId8pv4+v0c=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.41.0 h1:mq/Qcf28TWz719lE3/hMB4KkyDuLJIvgJnFGcd0kEUI=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.41.0/go.mod h1:yk5LXEYhsL2htyDNJbEq7fWzNEigeEdV5xBF/Y+kAv0=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0 h1:RAE+JPfvEmvy+0LzyUA25/SGawPwIUbZ6u0Wug54sLc=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0/go.mod h1:AGmbycVGEsRx9mXMZ75CsOyhSP6MFIcj/6dnG+vhVjk=
|
||||
go.opentelemetry.io/otel/metric v1.40.0 h1:rcZe317KPftE2rstWIBitCdVp89A2HqjkxR3c11+p9g=
|
||||
go.opentelemetry.io/otel/metric v1.40.0/go.mod h1:ib/crwQH7N3r5kfiBZQbwrTge743UDc7DTFVZrrXnqc=
|
||||
go.opentelemetry.io/otel/metric v1.41.0 h1:rFnDcs4gRzBcsO9tS8LCpgR0dxg4aaxWlJxCno7JlTQ=
|
||||
go.opentelemetry.io/otel/metric v1.41.0/go.mod h1:xPvCwd9pU0VN8tPZYzDZV/BMj9CM9vs00GuBjeKhJps=
|
||||
go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM=
|
||||
go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY=
|
||||
go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E=
|
||||
go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg=
|
||||
go.opentelemetry.io/otel/sdk v1.41.0 h1:YPIEXKmiAwkGl3Gu1huk1aYWwtpRLeskpV+wPisxBp8=
|
||||
go.opentelemetry.io/otel/sdk v1.41.0/go.mod h1:ahFdU0G5y8IxglBf0QBJXgSe7agzjE4GiTJ6HT9ud90=
|
||||
go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg=
|
||||
go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.41.0 h1:siZQIYBAUd1rlIWQT2uCxWJxcCO7q3TriaMlf08rXw8=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw=
|
||||
go.opentelemetry.io/otel/trace v1.40.0 h1:WA4etStDttCSYuhwvEa8OP8I5EWu24lkOzp+ZYblVjw=
|
||||
go.opentelemetry.io/otel/trace v1.40.0/go.mod h1:zeAhriXecNGP/s2SEG3+Y8X9ujcJOTqQ5RgdEJcawiA=
|
||||
go.opentelemetry.io/otel/trace v1.41.0 h1:Vbk2co6bhj8L59ZJ6/xFTskY+tGAbOnCtQGVVa9TIN0=
|
||||
go.opentelemetry.io/otel/trace v1.41.0/go.mod h1:U1NU4ULCoxeDKc09yCWdWe+3QoyweJcISEVa1RBzOis=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A=
|
||||
go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A=
|
||||
go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0=
|
||||
go.opentelemetry.io/proto/otlp v1.9.0 h1:l706jCMITVouPOqEnii2fIAuO3IVGBRPV5ICjceRb/A=
|
||||
go.opentelemetry.io/proto/otlp v1.9.0/go.mod h1:xE+Cx5E/eEHw+ISFkwPLwCZefwVjY+pqKg1qcK03+/4=
|
||||
go.opentelemetry.io/proto/otlp v1.10.0 h1:IQRWgT5srOCYfiWnpqUYz9CVmbO8bFmKcwYxpuCSL2g=
|
||||
go.opentelemetry.io/proto/otlp v1.10.0/go.mod h1:/CV4QoCR/S9yaPj8utp3lvQPoqMtxXdzn7ozvvozVqk=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
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/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
||||
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||
go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc=
|
||||
go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||
go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
|
||||
go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
|
||||
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
|
||||
@@ -427,30 +355,26 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
|
||||
golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
|
||||
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
|
||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
||||
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
||||
golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
||||
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
|
||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
|
||||
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
|
||||
golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U=
|
||||
golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY=
|
||||
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
|
||||
golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8=
|
||||
golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8=
|
||||
golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0=
|
||||
golang.org/x/crypto v0.44.0/go.mod h1:013i+Nw79BMiQiMsOPcVCB5ZIJbYkerPrGnOa00tvmc=
|
||||
golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0=
|
||||
golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A=
|
||||
golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
|
||||
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
|
||||
golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4=
|
||||
golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
|
||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
|
||||
golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93 h1:fQsdNF2N+/YewlRZiricy4P1iimyPKZ/xwniHj8Q2a0=
|
||||
golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93/go.mod h1:EPRbTFwzwjXj9NpYyyrvenVh9Y+GFeEvMNh7Xuz7xgU=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
@@ -458,24 +382,21 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
|
||||
golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
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/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
||||
golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
|
||||
golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
|
||||
golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ=
|
||||
golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
|
||||
golang.org/x/mod v0.31.0 h1:HaW9xtz0+kOcWKwli0ZXy79Ix+UW/vOfmWI5QVd2tgI=
|
||||
golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI=
|
||||
golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w=
|
||||
golang.org/x/mod v0.30.0/go.mod h1:lAsf5O2EvJeSFMiBxXDki7sCgAxEUcZHXoXMKT4GJKc=
|
||||
golang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg=
|
||||
golang.org/x/mod v0.32.0 h1:9F4d3PHLljb6x//jOyokMv3eX+YDeepZSEo3mFJy93c=
|
||||
golang.org/x/mod v0.32.0/go.mod h1:SgipZ/3h2Ci89DlEtEXWUk/HteuRin+HHhN+WbNhguU=
|
||||
golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8=
|
||||
golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w=
|
||||
@@ -497,42 +418,30 @@ golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qx
|
||||
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
|
||||
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||
golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
|
||||
golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
|
||||
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
|
||||
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
||||
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
|
||||
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/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
||||
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
|
||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
|
||||
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
|
||||
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
|
||||
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
|
||||
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
|
||||
golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o=
|
||||
golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
|
||||
golang.org/x/net v0.45.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
|
||||
golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210=
|
||||
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
|
||||
golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
|
||||
golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8=
|
||||
golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60=
|
||||
golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM=
|
||||
golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=
|
||||
golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.34.0 h1:hqK/t4AKgbqWkdkcAeI8XLmbK+4m4G5YeQRrmiotGlw=
|
||||
golang.org/x/oauth2 v0.34.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/oauth2 v0.35.0 h1:Mv2mzuHuZuY2+bkyWXIHMfhNdJAdwW3FuWeCPYN5GVQ=
|
||||
golang.org/x/oauth2 v0.35.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs=
|
||||
golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -541,15 +450,16 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
||||
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||
golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
|
||||
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
||||
@@ -574,35 +484,23 @@ golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
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.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.13.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/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
|
||||
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
|
||||
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
|
||||
golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
@@ -610,31 +508,29 @@ golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXct
|
||||
golang.org/x/telemetry v0.0.0-20240521205824-bda55230c457/go.mod h1:pRgIJT+bRLFKnoM1ldnzKoxTIn14Yxz928LQRYYgIN0=
|
||||
golang.org/x/telemetry v0.0.0-20250710130107-8d8967aff50b/go.mod h1:4ZwOYna0/zsOKwuR5X/m0QFOJpSZvAxFfkQT+Erd9D4=
|
||||
golang.org/x/telemetry v0.0.0-20250807160809-1a19826ec488/go.mod h1:fGb/2+tgXXjhjHsTNdVEEMZNWA0quBnfrO+AfoDSAKw=
|
||||
golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053/go.mod h1:+nZKN+XVh4LCiA9DV3ywrzN4gumyCnKjau3NGb9SGoE=
|
||||
golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8/go.mod h1:Pi4ztBfryZoJEkyFTI5/Ocsu2jXyDr6iSdgJiYE/uwE=
|
||||
golang.org/x/telemetry v0.0.0-20251111182119-bc8e575c7b54/go.mod h1:hKdjCMrbv9skySur+Nek8Hd0uJ0GuxJIoIX2payrIdQ=
|
||||
golang.org/x/telemetry v0.0.0-20251203150158-8fff8a5912fc/go.mod h1:hKdjCMrbv9skySur+Nek8Hd0uJ0GuxJIoIX2payrIdQ=
|
||||
golang.org/x/telemetry v0.0.0-20260109210033-bd525da824e2/go.mod h1:b7fPSJ0pKZ3ccUh8gnTONJxhn3c/PS6tyzQvyqw4iA8=
|
||||
golang.org/x/telemetry v0.0.0-20260209163413-e7419c687ee4/go.mod h1:g5NllXBEermZrmR51cJDQxmJUHUOfRAaNyWBM+R+548=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
|
||||
golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o=
|
||||
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
|
||||
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
||||
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
|
||||
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
|
||||
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
|
||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
|
||||
golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk=
|
||||
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
||||
golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M=
|
||||
golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ=
|
||||
golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0=
|
||||
golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw=
|
||||
golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY=
|
||||
golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA=
|
||||
golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss=
|
||||
golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254=
|
||||
golang.org/x/term v0.38.0/go.mod h1:bSEAKrOT1W+VSu9TSCMtoGEOUcKxOKgl3LE5QEF/xVg=
|
||||
golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww=
|
||||
golang.org/x/term v0.40.0 h1:36e4zGLqU4yhjlmxEaagx2KuYbJq3EwY8K943ZsHcvg=
|
||||
golang.org/x/term v0.40.0/go.mod h1:w2P8uVp06p2iyKKuvXIm7N/y0UCRt3UfJTfZ7oOpglM=
|
||||
golang.org/x/term v0.41.0 h1:QCgPso/Q3RTJx2Th4bDLqML4W6iJiaXFq2/ftQF13YU=
|
||||
golang.org/x/term v0.41.0/go.mod h1:3pfBgksrReYfZ5lvYM0kSO0LIkAl4Yl2bXOkKP7Ec2A=
|
||||
@@ -643,29 +539,26 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
|
||||
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
|
||||
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
|
||||
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
|
||||
golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
|
||||
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
|
||||
golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
|
||||
golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
|
||||
golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=
|
||||
golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
|
||||
golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
|
||||
golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
|
||||
golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8=
|
||||
golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA=
|
||||
golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
|
||||
golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
|
||||
golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
@@ -678,29 +571,21 @@ golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4f
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.6-0.20210820212750-d4cc65f0b2ff/go.mod h1:YD9qOF0M9xpSpdWTBbzEl5e/RnCefISl8E5Noe10jFM=
|
||||
golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
|
||||
golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
|
||||
golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
|
||||
golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
|
||||
golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
|
||||
golang.org/x/tools v0.12.0/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM=
|
||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
||||
golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0=
|
||||
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
|
||||
golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg=
|
||||
golang.org/x/tools v0.21.0/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
||||
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
|
||||
golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI=
|
||||
golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg=
|
||||
golang.org/x/tools v0.34.1-0.20250613162507-3f93fece84c7/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg=
|
||||
golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw=
|
||||
golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
|
||||
golang.org/x/tools v0.40.0 h1:yLkxfA+Qnul4cs9QA3KnlFu0lVmd8JJfoq+E41uSutA=
|
||||
golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w=
|
||||
golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs=
|
||||
golang.org/x/tools v0.39.0/go.mod h1:JnefbkDPyD8UU2kI5fuf8ZX4/yUeh9W877ZeBONxUqQ=
|
||||
golang.org/x/tools v0.40.0/go.mod h1:Ik/tzLRlbscWpqqMRjyWYDisX8bG13FrdXp3o4Sr9lc=
|
||||
golang.org/x/tools v0.41.0 h1:a9b8iMweWG+S0OBnlU36rzLp20z1Rp10w+IY2czHTQc=
|
||||
golang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg=
|
||||
golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k=
|
||||
golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0=
|
||||
@@ -713,36 +598,23 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
|
||||
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
|
||||
gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4=
|
||||
gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260128011058-8636f8732409 h1:merA0rdPeUV3YIIfHHcH4qBkiQAc1nfCKSI7lB4cV2M=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260128011058-8636f8732409/go.mod h1:fl8J1IvUjCilwZzQowmw2b7HQB2eAuYBabMXzWurF+I=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260209200024-4cfbd4190f57 h1:JLQynH/LBHfCTSbDWl+py8C+Rg/k1OVH3xfcaiANuF0=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260209200024-4cfbd4190f57/go.mod h1:kSJwQxqmFXeo79zOmbrALdflXQeAYcUbgS7PbpMknCY=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 h1:VPWxll4HlMw1Vs/qXtN7BvhZqsS9cdAittCNvVENElA=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9/go.mod h1:7QBABkRtR8z+TEnmXTqIqwJLlzrZKVfAUm7tY3yGv0M=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409 h1:H86B94AW+VfJWDqFeEbBPhEtHzJwJfTbgE2lZa54ZAQ=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57 h1:mWPCjDEyshlQYzBpMNHaEof6UX1PmHcaUODUywQ0uac=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9 h1:m8qni9SQFH0tJc1X0vmnpw/0t+AImlSvp30sEupozUg=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc=
|
||||
google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U=
|
||||
google.golang.org/grpc v1.79.1 h1:zGhSi45ODB9/p3VAawt9a+O/MULLl9dpizzNNpq7flY=
|
||||
google.golang.org/grpc v1.79.1/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ=
|
||||
google.golang.org/grpc v1.80.0 h1:Xr6m2WmWZLETvUNvIUmeD5OAagMw3FiKmMlTdViWsHM=
|
||||
google.golang.org/grpc v1.80.0/go.mod h1:ho/dLnxwi3EDJA4Zghp7k2Ec1+c2jqup0bFkw07bwF4=
|
||||
google.golang.org/grpc v1.81.1 h1:VnnIIZ88UzOOKLukQi+ImGz8O1Wdp8nAGGnvOfEIWQQ=
|
||||
google.golang.org/grpc v1.81.1/go.mod h1:xGH9GfzOyMTGIOXBJmXt+BX/V0kcdQbdcuwQ/zNw42I=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
@@ -754,11 +626,9 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD
|
||||
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
||||
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||
google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af h1:+5/Sw3GsDNlEmu7TfklWKPdQ0Ykja5VEmq2i817+jbI=
|
||||
google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
@@ -785,27 +655,26 @@ gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
k8s.io/api v0.23.3/go.mod h1:w258XdGyvCmnBj/vGzQMj6kzdufJZVUwEM1U2fRJwSQ=
|
||||
k8s.io/api v0.35.1 h1:0PO/1FhlK/EQNVK5+txc4FuhQibV25VLSdLMmGpDE/Q=
|
||||
k8s.io/api v0.35.1/go.mod h1:28uR9xlXWml9eT0uaGo6y71xK86JBELShLy4wR1XtxM=
|
||||
k8s.io/api v0.36.1 h1:XbL/EMj8K2aJpJtePmqUyQMsM0D4QI2pvl7YKJ20FTY=
|
||||
k8s.io/api v0.36.1/go.mod h1:KOWo4ey3TINlXjeHVuwB3i+tXXnu+UcwFBHlI/9dvEo=
|
||||
k8s.io/apiextensions-apiserver v0.30.0 h1:jcZFKMqnICJfRxTgnC4E+Hpcq8UEhT8B2lhBcQ+6uAs=
|
||||
k8s.io/apiextensions-apiserver v0.30.0/go.mod h1:N9ogQFGcrbWqAY9p2mUAL5mGxsLqwgtUce127VtRX5Y=
|
||||
k8s.io/apimachinery v0.23.3/go.mod h1:BEuFMMBaIbcOqVIJqNZJXGFTP4W6AycEpb5+m/97hrM=
|
||||
k8s.io/apimachinery v0.35.1 h1:yxO6gV555P1YV0SANtnTjXYfiivaTPvCTKX6w6qdDsU=
|
||||
k8s.io/apimachinery v0.35.1/go.mod h1:jQCgFZFR1F4Ik7hvr2g84RTJSZegBc8yHgFWKn//hns=
|
||||
k8s.io/apiserver v0.35.1 h1:potxdhhTL4i6AYAa2QCwtlhtB1eCdWQFvJV6fXgJzxs=
|
||||
k8s.io/apiserver v0.35.1/go.mod h1:BiL6Dd3A2I/0lBnteXfWmCFobHM39vt5+hJQd7Lbpi4=
|
||||
k8s.io/client-go v0.35.1 h1:+eSfZHwuo/I19PaSxqumjqZ9l5XiTEKbIaJ+j1wLcLM=
|
||||
k8s.io/client-go v0.35.1/go.mod h1:1p1KxDt3a0ruRfc/pG4qT/3oHmUj1AhSHEcxNSGg+OA=
|
||||
k8s.io/apimachinery v0.36.1 h1:G63Gjx2W+q0YD+72Vo8oY0nDnePVwnuzTmmy5ENrVSA=
|
||||
k8s.io/apimachinery v0.36.1/go.mod h1:ibYOR00vW/I1kzvi5SF0dRuJ52BvKtfvRdOn35GPQ+8=
|
||||
k8s.io/apiserver v0.36.1 h1:iMS5V+rPUertv5P9RaqJgmHHTuh4quWpoxchvMUY+JY=
|
||||
k8s.io/apiserver v0.36.1/go.mod h1:Cby1PbLWztu0GDOxoO6iFOyyqIsziHNEW+w9zVQ22Kw=
|
||||
k8s.io/client-go v0.36.1 h1:FN/K8QIT2CEDt+2WB2HnWrUANZ50AP5GII43/SP2JR0=
|
||||
k8s.io/client-go v0.36.1/go.mod h1:s6rAnCtTGYDQnpNjEhSaISV+2O8jwruZ6m3QOYBFbtU=
|
||||
k8s.io/code-generator v0.23.3/go.mod h1:S0Q1JVA+kSzTI1oUvbKAxZY/DYbA/ZUb4Uknog12ETk=
|
||||
k8s.io/code-generator v0.35.1 h1:yLKR2la7Z9cWT5qmk67ayx8xXLM4RRKQMnC8YPvTWRI=
|
||||
k8s.io/code-generator v0.35.1/go.mod h1:F2Fhm7aA69tC/VkMXLDokdovltXEF026Tb9yfQXQWKg=
|
||||
k8s.io/component-base v0.35.1 h1:XgvpRf4srp037QWfGBLFsYMUQJkE5yMa94UsJU7pmcE=
|
||||
k8s.io/component-base v0.35.1/go.mod h1:HI/6jXlwkiOL5zL9bqA3en1Ygv60F03oEpnuU1G56Bs=
|
||||
k8s.io/component-helpers v0.35.1 h1:vwQ/cAfnVwaPeSXTu4DdK3d3n11Lugc5vMb6EV809ZY=
|
||||
k8s.io/component-helpers v0.35.1/go.mod h1:HQqMwUk68Yyxgj92dJ+J1w/qbx9M0QR0eZ680m/o+Rk=
|
||||
k8s.io/code-generator v0.36.1 h1:5bHQ7NbBcFFLHcoyo/hgU3m2tQV5RLz2nv4QNDlsbXc=
|
||||
k8s.io/code-generator v0.36.1/go.mod h1:oCv8WmrW2RGdcMyvSk1aYbBfSs51ggtSFQr1YNeuAuo=
|
||||
k8s.io/component-base v0.36.1 h1:iG6GsELftXqTNG9HG6kiVjatSgAw1sf5pJ6R5a6N0kA=
|
||||
k8s.io/component-base v0.36.1/go.mod h1:nf9XPlntRdqO6WMeEWAA5F93Y4ICZQdeT9GeqLDB3JI=
|
||||
k8s.io/component-helpers v0.36.1 h1:BTrr5fzNSm8TkQfXrKT3N9ioWwiC4n2FTIwGTUo/ccg=
|
||||
k8s.io/component-helpers v0.36.1/go.mod h1:s38HnzKQRurbUnhI5IV8GwyL/a3lVuNCYZMTd+rITMM=
|
||||
k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
|
||||
k8s.io/gengo v0.0.0-20211129171323-c02415ce4185/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
|
||||
k8s.io/gengo/v2 v2.0.0-20250604051438-85fd79dbfd9f/go.mod h1:EJykeLsmFC60UQbYJezXkEsG2FLrt0GPNkU5iK5GWxU=
|
||||
k8s.io/gengo/v2 v2.0.0-20250922181213-ec3ebc5fd46b h1:gMplByicHV/TJBizHd9aVEsTYoJBnnUAT5MHlTkbjhQ=
|
||||
k8s.io/gengo/v2 v2.0.0-20250922181213-ec3ebc5fd46b/go.mod h1:CgujABENc3KuTrcsdpGmrrASjtQsWCT7R99mEV4U/fM=
|
||||
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
|
||||
@@ -813,18 +682,20 @@ k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
|
||||
k8s.io/klog/v2 v2.30.0/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
|
||||
k8s.io/klog/v2 v2.40.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
|
||||
k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
|
||||
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
|
||||
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
||||
k8s.io/kms v0.35.1 h1:kjv2r9g1mY7uL+l1RhyAZvWVZIA/4qIfBHXyjFGLRhU=
|
||||
k8s.io/kms v0.35.1/go.mod h1:VT+4ekZAdrZDMgShK37vvlyHUVhwI9t/9tvh0AyCWmQ=
|
||||
k8s.io/kube-openapi v0.0.0-20260127142750-a19766b6e2d4 h1:HhDfevmPS+OalTjQRKbTHppRIz01AWi8s45TMXStgYY=
|
||||
k8s.io/kube-openapi v0.0.0-20260127142750-a19766b6e2d4/go.mod h1:kdmbQkyfwUagLfXIad1y2TdrjPFWp2Q89B3qkRwf/pQ=
|
||||
k8s.io/metrics v0.35.1 h1:MUcrUcWlq81XiripkydzCGsY9zQawDXfP9IICNNcVVw=
|
||||
k8s.io/metrics v0.35.1/go.mod h1:9x7xWOAOiWzHA0vaqLgSE4PXF3vyT5ts5XIbx8OSjiI=
|
||||
k8s.io/klog/v2 v2.140.0 h1:Tf+J3AH7xnUzZyVVXhTgGhEKnFqye14aadWv7bzXdzc=
|
||||
k8s.io/klog/v2 v2.140.0/go.mod h1:o+/RWfJ6PwpnFn7OyAG3QnO47BFsymfEfrz6XyYSSp0=
|
||||
k8s.io/kms v0.36.1 h1:XdvKpywoW4k7YUHDh5uYP4mahJXECswHGfCddBBYLZs=
|
||||
k8s.io/kms v0.36.1/go.mod h1:g91diTD9h0oJCCHkTb00krlF+Qm5HTnkWLi9Q/TpRoc=
|
||||
k8s.io/kube-openapi v0.0.0-20260512234627-ef417d054102 h1:xs2ux1MvyrOdfKwS3vuFWrGuLgDOHk6id975Twx2Jss=
|
||||
k8s.io/kube-openapi v0.0.0-20260512234627-ef417d054102/go.mod h1:V/QaCUYDa+0QpcHhVVc5l99Uz56wEMEXBSj9oCDkNDY=
|
||||
k8s.io/metrics v0.36.1 h1:MQPb+G4RhrKEpt8NETPssbW8QgGUc4Jbqu1jx+kPqGk=
|
||||
k8s.io/metrics v0.36.1/go.mod h1:xqS8XcWLjDzo6E7DJm/GfjKpRKdN5/MtJAQFuV6nLUc=
|
||||
k8s.io/streaming v0.36.1 h1:L+K68n4Gg940BGNNYtUBvL1WTLL0YnKT3s+P1MNAmR4=
|
||||
k8s.io/streaming v0.36.1/go.mod h1:z6fV3D+NVkoeqRMtWwlUZK6U17SY/LqNzOxWL6GyR/s=
|
||||
k8s.io/utils v0.0.0-20211116205334-6203023598ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
k8s.io/utils v0.0.0-20260108192941-914a6e750570 h1:JT4W8lsdrGENg9W+YwwdLJxklIuKWdRm+BC+xt33FOY=
|
||||
k8s.io/utils v0.0.0-20260108192941-914a6e750570/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk=
|
||||
k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk=
|
||||
k8s.io/utils v0.0.0-20260507154919-ff6756f316d2 h1:wU4tMEhLGgIbLvXQb1cfN+EcM0wf7zC6CPF+C79jroc=
|
||||
k8s.io/utils v0.0.0-20260507154919-ff6756f316d2/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk=
|
||||
kubevirt.io/api v1.3.0 h1:9sGElMmnRU50pGED+MPPD2OwQl4S5lvjCUjm+t0mI90=
|
||||
kubevirt.io/api v1.3.0/go.mod h1:e6LkElYZZm8NcP2gKlFVHZS9pgNhIARHIjSBSfeiP1s=
|
||||
kubevirt.io/client-go v1.3.0 h1:/HKn4exzwsctEVTwVtEFaeT9D2v4TgWr2SmxITVEZ/4=
|
||||
@@ -833,10 +704,9 @@ kubevirt.io/containerized-data-importer-api v1.57.0-alpha1 h1:IWo12+ei3jltSN5jQN
|
||||
kubevirt.io/containerized-data-importer-api v1.57.0-alpha1/go.mod h1:Y/8ETgHS1GjO89bl682DPtQOYEU/1ctPFBz6Sjxm4DM=
|
||||
kubevirt.io/controller-lifecycle-operator-sdk/api v0.0.0-20220329064328-f3cc58c6ed90 h1:QMrd0nKP0BGbnxTqakhDZAUhGKxPiPiN5gSDqKUmGGc=
|
||||
kubevirt.io/controller-lifecycle-operator-sdk/api v0.0.0-20220329064328-f3cc58c6ed90/go.mod h1:018lASpFYBsYN6XwmA2TIrPCx6e0gviTd/ZNtSitKgc=
|
||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 h1:jpcvIRr3GLoUoEKRkHKSmGjxb6lWwrBlJsXc+eUYQHM=
|
||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw=
|
||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.34.0 h1:hSfpvjjTQXQY2Fol2CS0QHMNs/WI1MOSGzCm1KhM5ec=
|
||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.34.0/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw=
|
||||
sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6/go.mod h1:p4QtZmO4uMYipTQNzagwnNoseA6OxSUutVw05NhYDRs=
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
|
||||
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg=
|
||||
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
|
||||
sigs.k8s.io/mdtoc v1.4.0 h1:2pDEwJSjoVrGr5BPkG+LoLkYLKvgtGYurrBY8ul3SxQ=
|
||||
@@ -847,11 +717,9 @@ sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxO
|
||||
sigs.k8s.io/release-utils v0.8.3 h1:KtOtA4qDmzJyeQ2zkDsFVI25+NViwms/o5eL2NftFdA=
|
||||
sigs.k8s.io/release-utils v0.8.3/go.mod h1:fp82Fma06OXBhEJ+GUJKqvcplDBomruK1R/1fWJnsrQ=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.2.1/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4=
|
||||
sigs.k8s.io/structured-merge-diff/v6 v6.2.0/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE=
|
||||
sigs.k8s.io/structured-merge-diff/v6 v6.3.0 h1:jTijUJbW353oVOd9oTlifJqOGEkUw2jB/fXCbTiQEco=
|
||||
sigs.k8s.io/structured-merge-diff/v6 v6.3.0/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE=
|
||||
sigs.k8s.io/structured-merge-diff/v6 v6.3.2 h1:kwVWMx5yS1CrnFWA/2QHyRVJ8jM6dBA80uLmm0wJkk8=
|
||||
sigs.k8s.io/structured-merge-diff/v6 v6.3.2/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE=
|
||||
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
|
||||
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
|
||||
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
|
||||
sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs=
|
||||
sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4=
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@
|
||||
go::verify_version() {
|
||||
GO_VERSION=($(go version))
|
||||
|
||||
if [[ -z $(echo "${GO_VERSION[2]}" | grep -E 'go1.23|go1.24|go1.25') ]]; then
|
||||
if [[ -z $(echo "${GO_VERSION[2]}" | grep -E 'go1.24|go1.25|go1.26') ]]; then
|
||||
echo "Unknown go version '${GO_VERSION[2]}', skipping gofmt."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -16,7 +16,7 @@ spec:
|
||||
priorityClassName: system-cluster-critical
|
||||
containers:
|
||||
- name: descheduler
|
||||
image: registry.k8s.io/descheduler/descheduler:v0.35.0
|
||||
image: registry.k8s.io/descheduler/descheduler:v0.36.0
|
||||
volumeMounts:
|
||||
- mountPath: /policy-dir
|
||||
name: policy-volume
|
||||
|
||||
@@ -19,7 +19,7 @@ spec:
|
||||
serviceAccountName: descheduler-sa
|
||||
containers:
|
||||
- name: descheduler
|
||||
image: registry.k8s.io/descheduler/descheduler:v0.35.0
|
||||
image: registry.k8s.io/descheduler/descheduler:v0.36.0
|
||||
imagePullPolicy: IfNotPresent
|
||||
command:
|
||||
- "/bin/descheduler"
|
||||
|
||||
@@ -14,7 +14,7 @@ spec:
|
||||
priorityClassName: system-cluster-critical
|
||||
containers:
|
||||
- name: descheduler
|
||||
image: registry.k8s.io/descheduler/descheduler:v0.35.0
|
||||
image: registry.k8s.io/descheduler/descheduler:v0.36.0
|
||||
volumeMounts:
|
||||
- mountPath: /policy-dir
|
||||
name: policy-volume
|
||||
|
||||
@@ -39,7 +39,7 @@ echo "DESCHEDULER_IMAGE: ${DESCHEDULER_IMAGE}"
|
||||
|
||||
# This just runs e2e tests.
|
||||
if [ -n "$KIND_E2E" ]; then
|
||||
K8S_VERSION=${KUBERNETES_VERSION:-v1.35.1}
|
||||
K8S_VERSION=${KUBERNETES_VERSION:-v1.36.1}
|
||||
if [ -z "${SKIP_KUBECTL_INSTALL}" ]; then
|
||||
curl -Lo kubectl https://dl.k8s.io/release/${K8S_VERSION}/bin/linux/amd64/kubectl && chmod +x kubectl && mv kubectl /usr/local/bin/
|
||||
fi
|
||||
|
||||
Generated
Vendored
+6
-17
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
// Copyright 2025
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -12,22 +12,11 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package swag
|
||||
//go:build !unix
|
||||
|
||||
import "mime/multipart"
|
||||
package daemon
|
||||
|
||||
// File represents an uploaded file.
|
||||
type File struct {
|
||||
Data multipart.File
|
||||
Header *multipart.FileHeader
|
||||
}
|
||||
|
||||
// Read bytes from the file
|
||||
func (f *File) Read(p []byte) (n int, err error) {
|
||||
return f.Data.Read(p)
|
||||
}
|
||||
|
||||
// Close the file
|
||||
func (f *File) Close() error {
|
||||
return f.Data.Close()
|
||||
// SdNotifyMonotonicUsec returns the empty string on unsupported platforms.
|
||||
func SdNotifyMonotonicUsec() string {
|
||||
return ""
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
// Copyright 2025
|
||||
//
|
||||
// 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.
|
||||
|
||||
//go:build unix
|
||||
|
||||
package daemon
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// SdNotifyMonotonicUsec returns a MONOTONIC_USEC=... assignment for the current time
|
||||
// with a trailing newline included. This is typically used with [SdNotifyReloading].
|
||||
//
|
||||
// If the monotonic clock is not available on the system, the empty string is returned.
|
||||
func SdNotifyMonotonicUsec() string {
|
||||
var ts unix.Timespec
|
||||
if err := unix.ClockGettime(unix.CLOCK_MONOTONIC, &ts); err != nil {
|
||||
// Monotonic clock is not available on this system.
|
||||
return ""
|
||||
}
|
||||
return "MONOTONIC_USEC=" + strconv.FormatInt(ts.Nano()/1000, 10) + "\n"
|
||||
}
|
||||
+4
-3
@@ -15,6 +15,7 @@
|
||||
package daemon
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
@@ -51,10 +52,10 @@ func SdWatchdogEnabled(unsetEnvironment bool) (time.Duration, error) {
|
||||
}
|
||||
s, err := strconv.Atoi(wusec)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("error converting WATCHDOG_USEC: %s", err)
|
||||
return 0, fmt.Errorf("error converting WATCHDOG_USEC: %w", err)
|
||||
}
|
||||
if s <= 0 {
|
||||
return 0, fmt.Errorf("error WATCHDOG_USEC must be a positive number")
|
||||
return 0, errors.New("error WATCHDOG_USEC must be a positive number")
|
||||
}
|
||||
interval := time.Duration(s) * time.Microsecond
|
||||
|
||||
@@ -63,7 +64,7 @@ func SdWatchdogEnabled(unsetEnvironment bool) (time.Duration, error) {
|
||||
}
|
||||
p, err := strconv.Atoi(wpid)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("error converting WATCHDOG_PID: %s", err)
|
||||
return 0, fmt.Errorf("error converting WATCHDOG_PID: %w", err)
|
||||
}
|
||||
if os.Getpid() != p {
|
||||
return 0, nil
|
||||
|
||||
+1
-1
@@ -41,6 +41,6 @@ const (
|
||||
)
|
||||
|
||||
// Print prints a message to the local systemd journal using Send().
|
||||
func Print(priority Priority, format string, a ...interface{}) error {
|
||||
func Print(priority Priority, format string, a ...any) error {
|
||||
return Send(fmt.Sprintf(format, a...), priority, nil)
|
||||
}
|
||||
|
||||
+4
-6
@@ -13,7 +13,6 @@
|
||||
// limitations under the License.
|
||||
|
||||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
// Package journal provides write bindings to the local systemd journal.
|
||||
// It is implemented in pure Go and connects to the journal directly over its
|
||||
@@ -31,7 +30,6 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"strconv"
|
||||
@@ -108,7 +106,7 @@ func fdIsJournalStream(fd int) (bool, error) {
|
||||
var expectedStat syscall.Stat_t
|
||||
_, err := fmt.Sscanf(journalStream, "%d:%d", &expectedStat.Dev, &expectedStat.Ino)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to parse JOURNAL_STREAM=%q: %v", journalStream, err)
|
||||
return false, fmt.Errorf("failed to parse JOURNAL_STREAM=%q: %w", journalStream, err)
|
||||
}
|
||||
|
||||
var stat syscall.Stat_t
|
||||
@@ -194,7 +192,7 @@ func appendVariable(w io.Writer, name, value string) {
|
||||
* - the data, followed by a newline
|
||||
*/
|
||||
fmt.Fprintln(w, name)
|
||||
binary.Write(w, binary.LittleEndian, uint64(len(value)))
|
||||
_ = binary.Write(w, binary.LittleEndian, uint64(len(value)))
|
||||
fmt.Fprintln(w, value)
|
||||
} else {
|
||||
/* just write the variable and value all on one line */
|
||||
@@ -214,7 +212,7 @@ func validVarName(name string) error {
|
||||
}
|
||||
|
||||
for _, c := range name {
|
||||
if !(('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') || c == '_') {
|
||||
if ('A' > c || c > 'Z') && ('0' > c || c > '9') && c != '_' {
|
||||
return errors.New("Variable name contains invalid characters")
|
||||
}
|
||||
}
|
||||
@@ -239,7 +237,7 @@ func isSocketSpaceError(err error) bool {
|
||||
|
||||
// tempFd creates a temporary, unlinked file under `/dev/shm`.
|
||||
func tempFd() (*os.File, error) {
|
||||
file, err := ioutil.TempFile("/dev/shm/", "journal.XXXXX")
|
||||
file, err := os.CreateTemp("/dev/shm/", "journal.XXXXX")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
-13
@@ -1,13 +0,0 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.x
|
||||
|
||||
before_install:
|
||||
- go test -v
|
||||
|
||||
script:
|
||||
- go test -race -coverprofile=coverage.txt -covermode=atomic
|
||||
|
||||
after_success:
|
||||
- bash <(curl -s https://codecov.io/bash)
|
||||
+4
@@ -1,5 +1,9 @@
|
||||
# Change history of go-restful
|
||||
|
||||
## [v3.13.0] - 2025-08-14
|
||||
|
||||
- optimize performance of path matching in CurlyRouter ( thanks @wenhuang, Wen Huang)
|
||||
|
||||
## [v3.12.2] - 2025-02-21
|
||||
|
||||
- allow empty payloads in post,put,patch, issue #580 ( thanks @liggitt, Jordan Liggitt)
|
||||
|
||||
+1
@@ -84,6 +84,7 @@ func (u UserResource) findUser(request *restful.Request, response *restful.Respo
|
||||
- Configurable (trace) logging
|
||||
- Customizable gzip/deflate readers and writers using CompressorProvider registration
|
||||
- Inject your own http.Handler using the `HttpMiddlewareHandlerToFilter` function
|
||||
- Added `SetPathTokenCacheEnabled` and `SetCustomVerbCacheEnabled` to disable regexp caching (default=true)
|
||||
|
||||
## How to customize
|
||||
There are several hooks to customize the behavior of the go-restful package.
|
||||
|
||||
+47
-3
@@ -9,11 +9,35 @@ import (
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// CurlyRouter expects Routes with paths that contain zero or more parameters in curly brackets.
|
||||
type CurlyRouter struct{}
|
||||
|
||||
var (
|
||||
regexCache sync.Map // Cache for compiled regex patterns
|
||||
pathTokenCacheEnabled = true // Enable/disable path token regex caching
|
||||
)
|
||||
|
||||
// SetPathTokenCacheEnabled enables or disables path token regex caching for CurlyRouter.
|
||||
// When disabled, regex patterns will be compiled on every request.
|
||||
// When enabled (default), compiled regex patterns are cached for better performance.
|
||||
func SetPathTokenCacheEnabled(enabled bool) {
|
||||
pathTokenCacheEnabled = enabled
|
||||
}
|
||||
|
||||
// getCachedRegexp retrieves a compiled regex from the cache if found and valid.
|
||||
// Returns the regex and true if found and valid, nil and false otherwise.
|
||||
func getCachedRegexp(cache *sync.Map, pattern string) (*regexp.Regexp, bool) {
|
||||
if cached, found := cache.Load(pattern); found {
|
||||
if regex, ok := cached.(*regexp.Regexp); ok {
|
||||
return regex, true
|
||||
}
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// SelectRoute is part of the Router interface and returns the best match
|
||||
// for the WebService and its Route for the given Request.
|
||||
func (c CurlyRouter) SelectRoute(
|
||||
@@ -113,8 +137,28 @@ func (c CurlyRouter) regularMatchesPathToken(routeToken string, colon int, reque
|
||||
}
|
||||
return true, true
|
||||
}
|
||||
matched, err := regexp.MatchString(regPart, requestToken)
|
||||
return (matched && err == nil), false
|
||||
|
||||
// Check cache first (if enabled)
|
||||
if pathTokenCacheEnabled {
|
||||
if regex, found := getCachedRegexp(®exCache, regPart); found {
|
||||
matched := regex.MatchString(requestToken)
|
||||
return matched, false
|
||||
}
|
||||
}
|
||||
|
||||
// Compile the regex
|
||||
regex, err := regexp.Compile(regPart)
|
||||
if err != nil {
|
||||
return false, false
|
||||
}
|
||||
|
||||
// Cache the regex (if enabled)
|
||||
if pathTokenCacheEnabled {
|
||||
regexCache.Store(regPart, regex)
|
||||
}
|
||||
|
||||
matched := regex.MatchString(requestToken)
|
||||
return matched, false
|
||||
}
|
||||
|
||||
var jsr311Router = RouterJSR311{}
|
||||
@@ -168,7 +212,7 @@ func (c CurlyRouter) computeWebserviceScore(requestTokens []string, routeTokens
|
||||
if matchesToken {
|
||||
score++ // extra score for regex match
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// not a parameter
|
||||
if eachRequestToken != eachRouteToken {
|
||||
|
||||
+32
-2
@@ -1,14 +1,28 @@
|
||||
package restful
|
||||
|
||||
// Copyright 2025 Ernest Micklei. All rights reserved.
|
||||
// Use of this source code is governed by a license
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
customVerbReg = regexp.MustCompile(":([A-Za-z]+)$")
|
||||
customVerbReg = regexp.MustCompile(":([A-Za-z]+)$")
|
||||
customVerbCache sync.Map // Cache for compiled custom verb regexes
|
||||
customVerbCacheEnabled = true // Enable/disable custom verb regex caching
|
||||
)
|
||||
|
||||
// SetCustomVerbCacheEnabled enables or disables custom verb regex caching.
|
||||
// When disabled, custom verb regex patterns will be compiled on every request.
|
||||
// When enabled (default), compiled custom verb regex patterns are cached for better performance.
|
||||
func SetCustomVerbCacheEnabled(enabled bool) {
|
||||
customVerbCacheEnabled = enabled
|
||||
}
|
||||
|
||||
func hasCustomVerb(routeToken string) bool {
|
||||
return customVerbReg.MatchString(routeToken)
|
||||
}
|
||||
@@ -20,7 +34,23 @@ func isMatchCustomVerb(routeToken string, pathToken string) bool {
|
||||
}
|
||||
|
||||
customVerb := rs[1]
|
||||
specificVerbReg := regexp.MustCompile(fmt.Sprintf(":%s$", customVerb))
|
||||
regexPattern := fmt.Sprintf(":%s$", customVerb)
|
||||
|
||||
// Check cache first (if enabled)
|
||||
if customVerbCacheEnabled {
|
||||
if specificVerbReg, found := getCachedRegexp(&customVerbCache, regexPattern); found {
|
||||
return specificVerbReg.MatchString(pathToken)
|
||||
}
|
||||
}
|
||||
|
||||
// Compile the regex
|
||||
specificVerbReg := regexp.MustCompile(regexPattern)
|
||||
|
||||
// Cache the regex (if enabled)
|
||||
if customVerbCacheEnabled {
|
||||
customVerbCache.Store(regexPattern, specificVerbReg)
|
||||
}
|
||||
|
||||
return specificVerbReg.MatchString(pathToken)
|
||||
}
|
||||
|
||||
|
||||
+19
-23
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Package restful , a lean package for creating REST-style WebServices without magic.
|
||||
|
||||
WebServices and Routes
|
||||
### WebServices and Routes
|
||||
|
||||
A WebService has a collection of Route objects that dispatch incoming Http Requests to a function calls.
|
||||
Typically, a WebService has a root path (e.g. /users) and defines common MIME types for its routes.
|
||||
@@ -30,14 +30,14 @@ The (*Request, *Response) arguments provide functions for reading information fr
|
||||
|
||||
See the example https://github.com/emicklei/go-restful/blob/v3/examples/user-resource/restful-user-resource.go with a full implementation.
|
||||
|
||||
Regular expression matching Routes
|
||||
### Regular expression matching Routes
|
||||
|
||||
A Route parameter can be specified using the format "uri/{var[:regexp]}" or the special version "uri/{var:*}" for matching the tail of the path.
|
||||
For example, /persons/{name:[A-Z][A-Z]} can be used to restrict values for the parameter "name" to only contain capital alphabetic characters.
|
||||
Regular expressions must use the standard Go syntax as described in the regexp package. (https://code.google.com/p/re2/wiki/Syntax)
|
||||
This feature requires the use of a CurlyRouter.
|
||||
|
||||
Containers
|
||||
### Containers
|
||||
|
||||
A Container holds a collection of WebServices, Filters and a http.ServeMux for multiplexing http requests.
|
||||
Using the statements "restful.Add(...) and restful.Filter(...)" will register WebServices and Filters to the Default Container.
|
||||
@@ -47,7 +47,7 @@ You can create your own Container and create a new http.Server for that particul
|
||||
container := restful.NewContainer()
|
||||
server := &http.Server{Addr: ":8081", Handler: container}
|
||||
|
||||
Filters
|
||||
### Filters
|
||||
|
||||
A filter dynamically intercepts requests and responses to transform or use the information contained in the requests or responses.
|
||||
You can use filters to perform generic logging, measurement, authentication, redirect, set response headers etc.
|
||||
@@ -60,22 +60,21 @@ Use the following statement to pass the request,response pair to the next filter
|
||||
|
||||
chain.ProcessFilter(req, resp)
|
||||
|
||||
Container Filters
|
||||
### Container Filters
|
||||
|
||||
These are processed before any registered WebService.
|
||||
|
||||
// install a (global) filter for the default container (processed before any webservice)
|
||||
restful.Filter(globalLogging)
|
||||
|
||||
WebService Filters
|
||||
### WebService Filters
|
||||
|
||||
These are processed before any Route of a WebService.
|
||||
|
||||
// install a webservice filter (processed before any route)
|
||||
ws.Filter(webserviceLogging).Filter(measureTime)
|
||||
|
||||
|
||||
Route Filters
|
||||
### Route Filters
|
||||
|
||||
These are processed before calling the function associated with the Route.
|
||||
|
||||
@@ -84,7 +83,7 @@ These are processed before calling the function associated with the Route.
|
||||
|
||||
See the example https://github.com/emicklei/go-restful/blob/v3/examples/filters/restful-filters.go with full implementations.
|
||||
|
||||
Response Encoding
|
||||
### Response Encoding
|
||||
|
||||
Two encodings are supported: gzip and deflate. To enable this for all responses:
|
||||
|
||||
@@ -95,20 +94,20 @@ Alternatively, you can create a Filter that performs the encoding and install it
|
||||
|
||||
See the example https://github.com/emicklei/go-restful/blob/v3/examples/encoding/restful-encoding-filter.go
|
||||
|
||||
OPTIONS support
|
||||
### OPTIONS support
|
||||
|
||||
By installing a pre-defined container filter, your Webservice(s) can respond to the OPTIONS Http request.
|
||||
|
||||
Filter(OPTIONSFilter())
|
||||
|
||||
CORS
|
||||
### CORS
|
||||
|
||||
By installing the filter of a CrossOriginResourceSharing (CORS), your WebService(s) can handle CORS requests.
|
||||
|
||||
cors := CrossOriginResourceSharing{ExposeHeaders: []string{"X-My-Header"}, CookiesAllowed: false, Container: DefaultContainer}
|
||||
Filter(cors.Filter)
|
||||
|
||||
Error Handling
|
||||
### Error Handling
|
||||
|
||||
Unexpected things happen. If a request cannot be processed because of a failure, your service needs to tell via the response what happened and why.
|
||||
For this reason HTTP status codes exist and it is important to use the correct code in every exceptional situation.
|
||||
@@ -137,11 +136,11 @@ The request does not have or has an unknown Accept Header set for this operation
|
||||
|
||||
The request does not have or has an unknown Content-Type Header set for this operation.
|
||||
|
||||
ServiceError
|
||||
### ServiceError
|
||||
|
||||
In addition to setting the correct (error) Http status code, you can choose to write a ServiceError message on the response.
|
||||
|
||||
Performance options
|
||||
### Performance options
|
||||
|
||||
This package has several options that affect the performance of your service. It is important to understand them and how you can change it.
|
||||
|
||||
@@ -156,30 +155,27 @@ Default value is true
|
||||
If content encoding is enabled then the default strategy for getting new gzip/zlib writers and readers is to use a sync.Pool.
|
||||
Because writers are expensive structures, performance is even more improved when using a preloaded cache. You can also inject your own implementation.
|
||||
|
||||
Trouble shooting
|
||||
### Trouble shooting
|
||||
|
||||
This package has the means to produce detail logging of the complete Http request matching process and filter invocation.
|
||||
Enabling this feature requires you to set an implementation of restful.StdLogger (e.g. log.Logger) instance such as:
|
||||
|
||||
restful.TraceLogger(log.New(os.Stdout, "[restful] ", log.LstdFlags|log.Lshortfile))
|
||||
|
||||
Logging
|
||||
### Logging
|
||||
|
||||
The restful.SetLogger() method allows you to override the logger used by the package. By default restful
|
||||
uses the standard library `log` package and logs to stdout. Different logging packages are supported as
|
||||
long as they conform to `StdLogger` interface defined in the `log` sub-package, writing an adapter for your
|
||||
preferred package is simple.
|
||||
|
||||
Resources
|
||||
### Resources
|
||||
|
||||
(c) 2012-2025, http://ernestmicklei.com. MIT License
|
||||
|
||||
[project]: https://github.com/emicklei/go-restful
|
||||
|
||||
[examples]: https://github.com/emicklei/go-restful/blob/master/examples
|
||||
|
||||
[design]: http://ernestmicklei.com/2012/11/11/go-restful-api-design/
|
||||
|
||||
[design]: http://ernestmicklei.com/2012/11/11/go-restful-api-design/
|
||||
[showcases]: https://github.com/emicklei/mora, https://github.com/emicklei/landskape
|
||||
|
||||
(c) 2012-2015, http://ernestmicklei.com. MIT License
|
||||
*/
|
||||
package restful
|
||||
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
ignore:
|
||||
- jsonutils/fixtures_test
|
||||
- jsonutils/adapters/ifaces/mocks
|
||||
- jsonutils/adapters/testintegration/benchmarks
|
||||
+73
-55
@@ -1,60 +1,78 @@
|
||||
linters-settings:
|
||||
govet:
|
||||
check-shadowing: true
|
||||
golint:
|
||||
min-confidence: 0
|
||||
gocyclo:
|
||||
min-complexity: 45
|
||||
maligned:
|
||||
suggest-new: true
|
||||
dupl:
|
||||
threshold: 200
|
||||
goconst:
|
||||
min-len: 3
|
||||
min-occurrences: 3
|
||||
|
||||
version: "2"
|
||||
linters:
|
||||
enable-all: true
|
||||
default: all
|
||||
disable:
|
||||
- maligned
|
||||
- lll
|
||||
- gochecknoinits
|
||||
- gochecknoglobals
|
||||
- funlen
|
||||
- godox
|
||||
- gocognit
|
||||
- whitespace
|
||||
- wsl
|
||||
- wrapcheck
|
||||
- testpackage
|
||||
- nlreturn
|
||||
- gomnd
|
||||
- exhaustivestruct
|
||||
- goerr113
|
||||
- errorlint
|
||||
- nestif
|
||||
- godot
|
||||
- gofumpt
|
||||
- paralleltest
|
||||
- tparallel
|
||||
- thelper
|
||||
- ifshort
|
||||
- exhaustruct
|
||||
- varnamelen
|
||||
- gci
|
||||
- cyclop
|
||||
- depguard
|
||||
- errchkjson
|
||||
- inamedparam
|
||||
- nonamedreturns
|
||||
- musttag
|
||||
- ireturn
|
||||
- errorlint
|
||||
- exhaustruct
|
||||
- forcetypeassert
|
||||
- cyclop
|
||||
# deprecated linters
|
||||
- deadcode
|
||||
- interfacer
|
||||
- scopelint
|
||||
- varcheck
|
||||
- structcheck
|
||||
- golint
|
||||
- nosnakecase
|
||||
- funlen
|
||||
- gochecknoglobals
|
||||
- gochecknoinits
|
||||
- gocognit
|
||||
- godot
|
||||
- godox
|
||||
- gomoddirectives
|
||||
- gosmopolitan
|
||||
- inamedparam
|
||||
- intrange
|
||||
- ireturn
|
||||
- lll
|
||||
- musttag
|
||||
- modernize
|
||||
- nestif
|
||||
- nlreturn
|
||||
- nonamedreturns
|
||||
- noinlineerr
|
||||
- paralleltest
|
||||
- recvcheck
|
||||
- testpackage
|
||||
- thelper
|
||||
- tagliatelle
|
||||
- tparallel
|
||||
- unparam
|
||||
- varnamelen
|
||||
- whitespace
|
||||
- wrapcheck
|
||||
- wsl
|
||||
- wsl_v5
|
||||
settings:
|
||||
dupl:
|
||||
threshold: 200
|
||||
goconst:
|
||||
min-len: 2
|
||||
min-occurrences: 3
|
||||
gocyclo:
|
||||
min-complexity: 45
|
||||
exclusions:
|
||||
generated: lax
|
||||
presets:
|
||||
- comments
|
||||
- common-false-positives
|
||||
- legacy
|
||||
- std-error-handling
|
||||
paths:
|
||||
- third_party$
|
||||
- builtin$
|
||||
- examples$
|
||||
formatters:
|
||||
enable:
|
||||
- gofmt
|
||||
- goimports
|
||||
exclusions:
|
||||
generated: lax
|
||||
paths:
|
||||
- third_party$
|
||||
- builtin$
|
||||
- examples$
|
||||
issues:
|
||||
# Maximum issues count per one linter.
|
||||
# Set to 0 to disable.
|
||||
# Default: 50
|
||||
max-issues-per-linter: 0
|
||||
# Maximum count of issues with the same text.
|
||||
# Set to 0 to disable.
|
||||
# Default: 3
|
||||
max-same-issues: 0
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
all: false
|
||||
dir: '{{.InterfaceDir}}'
|
||||
filename: mocks_test.go
|
||||
force-file-write: true
|
||||
formatter: goimports
|
||||
include-auto-generated: false
|
||||
log-level: info
|
||||
structname: '{{.Mock}}{{.InterfaceName}}'
|
||||
pkgname: '{{.SrcPackageName}}'
|
||||
recursive: false
|
||||
require-template-schema-exists: true
|
||||
template: matryer
|
||||
template-schema: '{{.Template}}.schema.json'
|
||||
packages:
|
||||
github.com/go-openapi/swag/jsonutils/adapters/ifaces:
|
||||
config:
|
||||
dir: jsonutils/adapters/ifaces/mocks
|
||||
filename: mocks.go
|
||||
pkgname: 'mocks'
|
||||
force-file-write: true
|
||||
all: true
|
||||
github.com/go-openapi/swag/jsonutils/adapters/testintegration:
|
||||
config:
|
||||
inpackage: true
|
||||
dir: jsonutils/adapters/testintegration
|
||||
force-file-write: true
|
||||
all: true
|
||||
interfaces:
|
||||
EJMarshaler:
|
||||
EJUnmarshaler:
|
||||
+227
-11
@@ -1,23 +1,239 @@
|
||||
# Swag [](https://github.com/go-openapi/swag/actions?query=workflow%3A"go+test") [](https://codecov.io/gh/go-openapi/swag)
|
||||
|
||||
[](https://slackin.goswagger.io)
|
||||
[](https://raw.githubusercontent.com/go-openapi/swag/master/LICENSE)
|
||||
[](https://raw.githubusercontent.com/go-openapi/swag/master/LICENSE)
|
||||
[](https://pkg.go.dev/github.com/go-openapi/swag)
|
||||
[](https://goreportcard.com/report/github.com/go-openapi/swag)
|
||||
|
||||
Contains a bunch of helper functions for go-openapi and go-swagger projects.
|
||||
Package `swag` contains a bunch of helper functions for go-openapi and go-swagger projects.
|
||||
|
||||
You may also use it standalone for your projects.
|
||||
|
||||
* convert between value and pointers for builtin types
|
||||
* convert from string to builtin types (wraps strconv)
|
||||
* fast json concatenation
|
||||
* search in path
|
||||
* load from file or http
|
||||
* name mangling
|
||||
> **NOTE**
|
||||
> `swag` is one of the foundational building blocks of the go-openapi initiative.
|
||||
> Most repositories in `github.com/go-openapi/...` depend on it in some way.
|
||||
> And so does our CLI tool `github.com/go-swagger/go-swagger`,
|
||||
> as well as the code generated by this tool.
|
||||
|
||||
* [Contents](#contents)
|
||||
* [Dependencies](#dependencies)
|
||||
* [Release Notes](#release-notes)
|
||||
* [Licensing](#licensing)
|
||||
* [Note to contributors](#note-to-contributors)
|
||||
* [TODOs, suggestions and plans](#todos-suggestions-and-plans)
|
||||
|
||||
## Contents
|
||||
|
||||
`go-openapi/swag` exposes a collection of relatively independent modules.
|
||||
|
||||
Moving forward, no additional feature will be added to the `swag` API directly at the root package level,
|
||||
which remains there for backward-compatibility purposes. All exported top-level features are now deprecated.
|
||||
|
||||
Child modules will continue to evolve and some new ones may be added in the future.
|
||||
|
||||
| Module | Content | Main features |
|
||||
|---------------|---------|---------------|
|
||||
| `cmdutils` | utilities to work with CLIs ||
|
||||
| `conv` | type conversion utilities | convert between values and pointers for any types<br />convert from string to builtin types (wraps `strconv`)<br />require `./typeutils` (test dependency)<br /> |
|
||||
| `fileutils` | file utilities | |
|
||||
| `jsonname` | JSON utilities | infer JSON names from `go` properties<br /> |
|
||||
| `jsonutils` | JSON utilities | fast json concatenation<br />read and write JSON from and to dynamic `go` data structures<br />~require `github.com/mailru/easyjson`~<br /> |
|
||||
| `loading` | file loading | load from file or http<br />require `./yamlutils`<br /> |
|
||||
| `mangling` | safe name generation | name mangling for `go`<br /> |
|
||||
| `netutils` | networking utilities | host, port from address<br /> |
|
||||
| `stringutils` | `string` utilities | search in slice (with case-insensitive)<br />split/join query parameters as arrays<br /> |
|
||||
| `typeutils` | `go` types utilities | check the zero value for any type<br />safe check for a nil value<br /> |
|
||||
| `yamlutils` | YAML utilities | converting YAML to JSON<br />loading YAML into a dynamic YAML document<br />maintaining the original order of keys in YAML objects<br />require `./jsonutils`<br />~require `github.com/mailru/easyjson`~<br />require `go.yaml.in/yaml/v3`<br /> |
|
||||
|
||||
---
|
||||
|
||||
## Dependencies
|
||||
|
||||
The root module `github.com/go-openapi/swag` at the repo level maintains a few
|
||||
dependencies outside of the standard library.
|
||||
|
||||
* YAML utilities depend on `go.yaml.in/yaml/v3`
|
||||
* JSON utilities depend on their registered adapter module:
|
||||
* by default, only the standard library is used
|
||||
* `github.com/mailru/easyjson` is now only a dependency for module
|
||||
`github.com/go-openapi/swag/jsonutils/adapters/easyjson/json`,
|
||||
for users willing to import that module.
|
||||
* integration tests and benchmarks use all the dependencies are published as their own module
|
||||
* other dependencies are test dependencies drawn from `github.com/stretchr/testify`
|
||||
|
||||
## Release notes
|
||||
|
||||
### v0.25.4
|
||||
|
||||
** mangling**
|
||||
|
||||
Bug fix
|
||||
|
||||
* [x] mangler may panic with pluralized overlapping initialisms
|
||||
|
||||
Tests
|
||||
|
||||
* [x] introduced fuzz tests
|
||||
|
||||
### v0.25.3
|
||||
|
||||
** mangling**
|
||||
|
||||
Bug fix
|
||||
|
||||
* [x] mangler may panic with pluralized initialisms
|
||||
|
||||
### v0.25.2
|
||||
|
||||
Minor changes due to internal maintenance that don't affect the behavior of the library.
|
||||
|
||||
* [x] removed indirect test dependencies by switching all tests to `go-openapi/testify`,
|
||||
a fork of `stretch/testify` with zero-dependencies.
|
||||
* [x] improvements to CI to catch test reports.
|
||||
* [x] modernized licensing annotations in source code, using the more compact SPDX annotations
|
||||
rather than the full license terms.
|
||||
* [x] simplified a bit JSON & YAML testing by using newly available assertions
|
||||
* started the journey to an OpenSSF score card badge:
|
||||
* [x] explicited permissions in CI workflows
|
||||
* [x] published security policy
|
||||
* pinned dependencies to github actions
|
||||
* introduced fuzzing in tests
|
||||
|
||||
### v0.25.1
|
||||
|
||||
* fixes a data race that could occur when using the standard library implementation of a JSON ordered map
|
||||
|
||||
### v0.25.0
|
||||
|
||||
**New with this release**:
|
||||
|
||||
* requires `go1.24`, as iterators are being introduced
|
||||
* removes the dependency to `mailru/easyjson` by default (#68)
|
||||
* functionality remains the same, but performance may somewhat degrade for applications
|
||||
that relied on `easyjson`
|
||||
* users of the JSON or YAML utilities who want to use `easyjson` as their preferred JSON serializer library
|
||||
will be able to do so by registering this the corresponding JSON adapter at runtime. See below.
|
||||
* ordered keys in JSON and YAML objects: this feature used to rely solely on `easyjson`.
|
||||
With this release, an implementation relying on the standard `encoding/json` is provided.
|
||||
* an independent [benchmark](./jsonutils/adapters/testintegration/benchmarks/README.md) to compare the different adapters
|
||||
* improves the "float is integer" check (`conv.IsFloat64AJSONInteger`) (#59)
|
||||
* removes the _direct_ dependency to `gopkg.in/yaml.v3` (indirect dependency is still incurred through `stretchr/testify`) (#127)
|
||||
* exposed `conv.IsNil()` (previously kept private): a safe nil check (accounting for the "non-nil interface with nil value" nonsensical go trick)
|
||||
|
||||
**What coming next?**
|
||||
|
||||
Moving forward, we want to :
|
||||
* provide an implementation of the JSON adapter based on `encoding/json/v2`, for `go1.25` builds.
|
||||
* provide similar implementations for `goccy/go-json` and `jsoniterator/go`, and perhaps some other
|
||||
similar libraries may be interesting too.
|
||||
|
||||
|
||||
This repo has only few dependencies outside of the standard library:
|
||||
**How to explicitly register a dependency at runtime**?
|
||||
|
||||
* YAML utilities depend on `gopkg.in/yaml.v3`
|
||||
* `github.com/mailru/easyjson v0.7.7`
|
||||
The following would maintain how JSON utilities proposed by `swag` used work, up to `v0.24.1`.
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/go-openapi/swag/jsonutils/adapters"
|
||||
easyjson "github.com/go-openapi/swag/jsonutils/adapters/easyjson/json"
|
||||
)
|
||||
|
||||
func init() {
|
||||
easyjson.Register(adapters.Registry)
|
||||
}
|
||||
```
|
||||
|
||||
Subsequent calls to `jsonutils.ReadJSON()` or `jsonutils.WriteJSON()` will switch to `easyjson`
|
||||
whenever the passed data structures implement the `easyjson.Unmarshaler` or `easyjson.Marshaler` respectively,
|
||||
or fallback to the standard library.
|
||||
|
||||
For more details, you may also look at our
|
||||
[integration tests](jsonutils/adapters/testintegration/integration_suite_test.go#29).
|
||||
|
||||
### v0.24.0
|
||||
|
||||
With this release, we have largely modernized the API of `swag`:
|
||||
|
||||
* The traditional `swag` API is still supported: code that imports `swag` will still
|
||||
compile and work the same.
|
||||
* A deprecation notice is published to encourage consumers of this library to adopt
|
||||
the newer API
|
||||
* **Deprecation notice**
|
||||
* configuration through global variables is now deprecated, in favor of options passed as parameters
|
||||
* all helper functions are moved to more specialized packages, which are exposed as
|
||||
go modules. Importing such a module would reduce the footprint of dependencies.
|
||||
* _all_ functions, variables, constants exposed by the deprecated API have now moved, so
|
||||
that consumers of the new API no longer need to import github.com/go-openapi/swag, but
|
||||
should import the desired sub-module(s).
|
||||
|
||||
**New with this release**:
|
||||
|
||||
* [x] type converters and pointer to value helpers now support generic types
|
||||
* [x] name mangling now support pluralized initialisms (issue #46)
|
||||
Strings like "contact IDs" are now recognized as such a plural form and mangled as a linter would expect.
|
||||
* [x] performance: small improvements to reduce the overhead of convert/format wrappers (see issues #110, or PR #108)
|
||||
* [x] performance: name mangling utilities run ~ 10% faster (PR #115)
|
||||
|
||||
---
|
||||
|
||||
## Licensing
|
||||
|
||||
This library ships under the [SPDX-License-Identifier: Apache-2.0](./LICENSE).
|
||||
|
||||
## Note to contributors
|
||||
|
||||
A mono-repo structure comes with some unavoidable extra pains...
|
||||
|
||||
* Testing
|
||||
|
||||
> The usual `go test ./...` command, run from the root of this repo won't work any longer to test all submodules.
|
||||
>
|
||||
> Each module constitutes an independant unit of test. So you have to run `go test` inside each module.
|
||||
> Or you may take a look at how this is achieved by CI
|
||||
> [here] https://github.com/go-openapi/swag/blob/master/.github/workflows/go-test.yml).
|
||||
>
|
||||
> There are also some alternative tricks using `go work`, for local development, if you feel comfortable with
|
||||
> go workspaces. Perhaps some day, we'll have a `go work test` to run all tests without any hack.
|
||||
|
||||
* Releasing
|
||||
|
||||
> Each module follows its own independant module versioning.
|
||||
>
|
||||
> So you have tags like `mangling/v0.24.0`, `fileutils/v0.24.0` etc that are used by `go mod` and `go get`
|
||||
> to refer to the tagged version of each module specifically.
|
||||
>
|
||||
> This means we may release patches etc to each module independently.
|
||||
>
|
||||
> We'd like to adopt the rule that modules in this repo would only differ by a patch version
|
||||
> (e.g. `v0.24.5` vs `v0.24.3`), and we'll level all modules whenever a minor version is introduced.
|
||||
>
|
||||
> A script in `./hack` is provided to tag all modules with the same version in one go.
|
||||
|
||||
* Continuous integration
|
||||
|
||||
> At this moment, all tests in all modules are systematically run over the full test matrix (3 platform x 2 go releases).
|
||||
> This generates quite a lot of jobs.
|
||||
>
|
||||
> We ought to reduce the number of jobs required to test a PR focused on only a few modules.
|
||||
|
||||
## Todos, suggestions and plans
|
||||
|
||||
All kinds of contributions are welcome.
|
||||
|
||||
A few ideas:
|
||||
|
||||
* [x] Complete the split of dependencies to isolate easyjson from the rest
|
||||
* [x] Improve CI to reduce needed tests
|
||||
* [x] Replace dependency to `gopkg.in/yaml.v3` (`yamlutil`)
|
||||
* [ ] Improve mangling utilities (improve readability, support for capitalized words,
|
||||
better word substitution for non-letter symbols...)
|
||||
* [ ] Move back to this common shared pot a few of the technical features introduced by go-swagger independently
|
||||
(e.g. mangle go package names, search package with go modules support, ...)
|
||||
* [ ] Apply a similar mono-repo approach to go-openapi/strfmt which suffer from similar woes: bloated API,
|
||||
imposed dependency to some database driver.
|
||||
* [ ] Adapt `go-swagger` (incl. generated code) to the new `swag` API.
|
||||
* [ ] Factorize some tests, as there is a lot of redundant testing code in `jsonutils`
|
||||
* [ ] Benchmark & profiling: publish independently the tool built to analyze and chart benchmarks (e.g. similar to `benchvisual`)
|
||||
* [ ] more thorough testing for nil / null case
|
||||
* [ ] ci pipeline to manage releases
|
||||
* [ ] cleaner mockery generation (doesn't work out of the box for all sub-modules)
|
||||
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
# Security Policy
|
||||
|
||||
This policy outlines the commitment and practices of the go-openapi maintainers regarding security.
|
||||
|
||||
## Supported Versions
|
||||
|
||||
| Version | Supported |
|
||||
| ------- | ------------------ |
|
||||
| 0.25.x | :white_check_mark: |
|
||||
|
||||
## Reporting a vulnerability
|
||||
|
||||
If you become aware of a security vulnerability that affects the current repository,
|
||||
please report it privately to the maintainers.
|
||||
|
||||
Please follow the instructions provided by github to
|
||||
[Privately report a security vulnerability](https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing-information-about-vulnerabilities/privately-reporting-a-security-vulnerability#privately-reporting-a-security-vulnerability).
|
||||
|
||||
TL;DR: on Github, navigate to the project's "Security" tab then click on "Report a vulnerability".
|
||||
Generated
Vendored
+13
@@ -0,0 +1,13 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package cmdutils
|
||||
|
||||
// CommandLineOptionsGroup represents a group of user-defined command line options.
|
||||
//
|
||||
// This is for instance used to configure command line arguments in API servers generated by go-swagger.
|
||||
type CommandLineOptionsGroup struct {
|
||||
ShortDescription string
|
||||
LongDescription string
|
||||
Options any
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Package cmdutils brings helpers for CLIs produced by go-openapi
|
||||
package cmdutils
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package swag
|
||||
|
||||
import "github.com/go-openapi/swag/cmdutils"
|
||||
|
||||
// CommandLineOptionsGroup represents a group of user-defined command line options.
|
||||
//
|
||||
// Deprecated: use [cmdutils.CommandLineOptionsGroup] instead.
|
||||
type CommandLineOptionsGroup = cmdutils.CommandLineOptionsGroup
|
||||
+202
@@ -0,0 +1,202 @@
|
||||
|
||||
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.
|
||||
+161
@@ -0,0 +1,161 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package conv
|
||||
|
||||
import (
|
||||
"math"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// same as ECMA Number.MAX_SAFE_INTEGER and Number.MIN_SAFE_INTEGER
|
||||
const (
|
||||
maxJSONFloat = float64(1<<53 - 1) // 9007199254740991.0 2^53 - 1
|
||||
minJSONFloat = -float64(1<<53 - 1) //-9007199254740991.0 -2^53 - 1
|
||||
epsilon float64 = 1e-9
|
||||
)
|
||||
|
||||
// IsFloat64AJSONInteger allows for integers [-2^53, 2^53-1] inclusive.
|
||||
func IsFloat64AJSONInteger(f float64) bool {
|
||||
if math.IsNaN(f) || math.IsInf(f, 0) || f < minJSONFloat || f > maxJSONFloat {
|
||||
return false
|
||||
}
|
||||
rounded := math.Round(f)
|
||||
if f == rounded {
|
||||
return true
|
||||
}
|
||||
if rounded == 0 { // f = 0.0 exited above
|
||||
return false
|
||||
}
|
||||
|
||||
diff := math.Abs(f - rounded)
|
||||
if diff == 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
// relative error Abs{f - Round(f)) / Round(f)} < ε ; Round(f)
|
||||
return diff < epsilon*math.Abs(rounded)
|
||||
}
|
||||
|
||||
// ConvertFloat turns a string into a float numerical value.
|
||||
func ConvertFloat[T Float](str string) (T, error) {
|
||||
var v T
|
||||
f, err := strconv.ParseFloat(str, bitsize(v))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return T(f), nil
|
||||
}
|
||||
|
||||
// ConvertInteger turns a string into a signed integer.
|
||||
func ConvertInteger[T Signed](str string) (T, error) {
|
||||
var v T
|
||||
f, err := strconv.ParseInt(str, 10, bitsize(v))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return T(f), nil
|
||||
}
|
||||
|
||||
// ConvertUinteger turns a string into an unsigned integer.
|
||||
func ConvertUinteger[T Unsigned](str string) (T, error) {
|
||||
var v T
|
||||
f, err := strconv.ParseUint(str, 10, bitsize(v))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return T(f), nil
|
||||
}
|
||||
|
||||
// ConvertBool turns a string into a boolean.
|
||||
//
|
||||
// It supports a few more "true" strings than [strconv.ParseBool]:
|
||||
//
|
||||
// - it is not case sensitive ("trUe" or "FalsE" work)
|
||||
// - "ok", "yes", "y", "on", "selected", "checked", "enabled" are all true
|
||||
// - everything that is not true is false: there is never an actual error returned
|
||||
func ConvertBool(str string) (bool, error) {
|
||||
switch strings.ToLower(str) {
|
||||
case "true",
|
||||
"1",
|
||||
"yes",
|
||||
"ok",
|
||||
"y",
|
||||
"on",
|
||||
"selected",
|
||||
"checked",
|
||||
"t",
|
||||
"enabled":
|
||||
return true, nil
|
||||
default:
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
|
||||
// ConvertFloat32 turns a string into a float32.
|
||||
func ConvertFloat32(str string) (float32, error) { return ConvertFloat[float32](str) }
|
||||
|
||||
// ConvertFloat64 turns a string into a float64
|
||||
func ConvertFloat64(str string) (float64, error) { return ConvertFloat[float64](str) }
|
||||
|
||||
// ConvertInt8 turns a string into an int8
|
||||
func ConvertInt8(str string) (int8, error) { return ConvertInteger[int8](str) }
|
||||
|
||||
// ConvertInt16 turns a string into an int16
|
||||
func ConvertInt16(str string) (int16, error) {
|
||||
i, err := strconv.ParseInt(str, 10, 16)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return int16(i), nil
|
||||
}
|
||||
|
||||
// ConvertInt32 turns a string into an int32
|
||||
func ConvertInt32(str string) (int32, error) {
|
||||
i, err := strconv.ParseInt(str, 10, 32)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return int32(i), nil
|
||||
}
|
||||
|
||||
// ConvertInt64 turns a string into an int64
|
||||
func ConvertInt64(str string) (int64, error) {
|
||||
return strconv.ParseInt(str, 10, 64)
|
||||
}
|
||||
|
||||
// ConvertUint8 turns a string into an uint8
|
||||
func ConvertUint8(str string) (uint8, error) {
|
||||
i, err := strconv.ParseUint(str, 10, 8)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return uint8(i), nil
|
||||
}
|
||||
|
||||
// ConvertUint16 turns a string into an uint16
|
||||
func ConvertUint16(str string) (uint16, error) {
|
||||
i, err := strconv.ParseUint(str, 10, 16)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return uint16(i), nil
|
||||
}
|
||||
|
||||
// ConvertUint32 turns a string into an uint32
|
||||
func ConvertUint32(str string) (uint32, error) {
|
||||
i, err := strconv.ParseUint(str, 10, 32)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return uint32(i), nil
|
||||
}
|
||||
|
||||
// ConvertUint64 turns a string into an uint64
|
||||
func ConvertUint64(str string) (uint64, error) {
|
||||
return strconv.ParseUint(str, 10, 64)
|
||||
}
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package conv
|
||||
|
||||
// Unlicensed credits (idea, concept)
|
||||
//
|
||||
// The idea to convert values to pointers and the other way around, was inspired, eons ago, by the aws go sdk.
|
||||
//
|
||||
// Nowadays, all sensible API sdk's expose a similar functionality.
|
||||
|
||||
// Pointer returns a pointer to the value passed in.
|
||||
func Pointer[T any](v T) *T {
|
||||
return &v
|
||||
}
|
||||
|
||||
// Value returns a shallow copy of the value of the pointer passed in.
|
||||
//
|
||||
// If the pointer is nil, the returned value is the zero value.
|
||||
func Value[T any](v *T) T {
|
||||
if v != nil {
|
||||
return *v
|
||||
}
|
||||
|
||||
var zero T
|
||||
return zero
|
||||
}
|
||||
|
||||
// PointerSlice converts a slice of values into a slice of pointers.
|
||||
func PointerSlice[T any](src []T) []*T {
|
||||
dst := make([]*T, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
dst[i] = &(src[i])
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// ValueSlice converts a slice of pointers into a slice of values.
|
||||
//
|
||||
// nil elements are zero values.
|
||||
func ValueSlice[T any](src []*T) []T {
|
||||
dst := make([]T, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
if src[i] != nil {
|
||||
dst[i] = *(src[i])
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// PointerMap converts a map of values into a map of pointers.
|
||||
func PointerMap[K comparable, T any](src map[K]T) map[K]*T {
|
||||
dst := make(map[K]*T)
|
||||
for k, val := range src {
|
||||
v := val
|
||||
dst[k] = &v
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// ValueMap converts a map of pointers into a map of values.
|
||||
//
|
||||
// nil elements are skipped.
|
||||
func ValueMap[K comparable, T any](src map[K]*T) map[K]T {
|
||||
dst := make(map[K]T)
|
||||
for k, val := range src {
|
||||
if val != nil {
|
||||
dst[k] = *val
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Package conv exposes utilities to convert types.
|
||||
//
|
||||
// The Convert and Format families of functions are essentially a shorthand to [strconv] functions,
|
||||
// using the decimal representation of numbers.
|
||||
//
|
||||
// Features:
|
||||
//
|
||||
// - from string representation to value ("Convert*") and reciprocally ("Format*")
|
||||
// - from pointer to value ([Value]) and reciprocally ([Pointer])
|
||||
// - from slice of values to slice of pointers ([PointerSlice]) and reciprocally ([ValueSlice])
|
||||
// - from map of values to map of pointers ([PointerMap]) and reciprocally ([ValueMap])
|
||||
package conv
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package conv
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// FormatInteger turns an integer type into a string.
|
||||
func FormatInteger[T Signed](value T) string {
|
||||
return strconv.FormatInt(int64(value), 10)
|
||||
}
|
||||
|
||||
// FormatUinteger turns an unsigned integer type into a string.
|
||||
func FormatUinteger[T Unsigned](value T) string {
|
||||
return strconv.FormatUint(uint64(value), 10)
|
||||
}
|
||||
|
||||
// FormatFloat turns a floating point numerical value into a string.
|
||||
func FormatFloat[T Float](value T) string {
|
||||
return strconv.FormatFloat(float64(value), 'f', -1, bitsize(value))
|
||||
}
|
||||
|
||||
// FormatBool turns a boolean into a string.
|
||||
func FormatBool(value bool) string {
|
||||
return strconv.FormatBool(value)
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package conv
|
||||
|
||||
import "unsafe"
|
||||
|
||||
// bitsize returns the size in bits of a type.
|
||||
//
|
||||
// NOTE: [unsafe.SizeOf] simply returns the size in bytes of the value.
|
||||
// For primitive types T, the generic stencil is precompiled and this value
|
||||
// is resolved at compile time, resulting in an immediate call to [strconv.ParseFloat].
|
||||
//
|
||||
// We may leave up to the go compiler to simplify this function into a
|
||||
// constant value, which happens in practice at least for primitive types
|
||||
// (e.g. numerical types).
|
||||
func bitsize[T Numerical](value T) int {
|
||||
const bitsPerByte = 8
|
||||
return int(unsafe.Sizeof(value)) * bitsPerByte
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package conv
|
||||
|
||||
type (
|
||||
// these type constraints are redefined after golang.org/x/exp/constraints,
|
||||
// because importing that package causes an undesired go upgrade.
|
||||
|
||||
// Signed integer types, cf. [golang.org/x/exp/constraints.Signed]
|
||||
Signed interface {
|
||||
~int | ~int8 | ~int16 | ~int32 | ~int64
|
||||
}
|
||||
|
||||
// Unsigned integer types, cf. [golang.org/x/exp/constraints.Unsigned]
|
||||
Unsigned interface {
|
||||
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr
|
||||
}
|
||||
|
||||
// Float numerical types, cf. [golang.org/x/exp/constraints.Float]
|
||||
Float interface {
|
||||
~float32 | ~float64
|
||||
}
|
||||
|
||||
// Numerical types
|
||||
Numerical interface {
|
||||
Signed | Unsigned | Float
|
||||
}
|
||||
)
|
||||
+486
@@ -0,0 +1,486 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package swag
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/go-openapi/swag/conv"
|
||||
)
|
||||
|
||||
// IsFloat64AJSONInteger allows for integers [-2^53, 2^53-1] inclusive.
|
||||
//
|
||||
// Deprecated: use [conv.IsFloat64AJSONInteger] instead.
|
||||
func IsFloat64AJSONInteger(f float64) bool { return conv.IsFloat64AJSONInteger(f) }
|
||||
|
||||
// ConvertBool turns a string into a boolean.
|
||||
//
|
||||
// Deprecated: use [conv.ConvertBool] instead.
|
||||
func ConvertBool(str string) (bool, error) { return conv.ConvertBool(str) }
|
||||
|
||||
// ConvertFloat32 turns a string into a float32.
|
||||
//
|
||||
// Deprecated: use [conv.ConvertFloat32] instead. Alternatively, you may use the generic version [conv.ConvertFloat].
|
||||
func ConvertFloat32(str string) (float32, error) { return conv.ConvertFloat[float32](str) }
|
||||
|
||||
// ConvertFloat64 turns a string into a float64.
|
||||
//
|
||||
// Deprecated: use [conv.ConvertFloat64] instead. Alternatively, you may use the generic version [conv.ConvertFloat].
|
||||
func ConvertFloat64(str string) (float64, error) { return conv.ConvertFloat[float64](str) }
|
||||
|
||||
// ConvertInt8 turns a string into an int8.
|
||||
//
|
||||
// Deprecated: use [conv.ConvertInt8] instead. Alternatively, you may use the generic version [conv.ConvertInteger].
|
||||
func ConvertInt8(str string) (int8, error) { return conv.ConvertInteger[int8](str) }
|
||||
|
||||
// ConvertInt16 turns a string into an int16.
|
||||
//
|
||||
// Deprecated: use [conv.ConvertInt16] instead. Alternatively, you may use the generic version [conv.ConvertInteger].
|
||||
func ConvertInt16(str string) (int16, error) { return conv.ConvertInteger[int16](str) }
|
||||
|
||||
// ConvertInt32 turns a string into an int32.
|
||||
//
|
||||
// Deprecated: use [conv.ConvertInt32] instead. Alternatively, you may use the generic version [conv.ConvertInteger].
|
||||
func ConvertInt32(str string) (int32, error) { return conv.ConvertInteger[int32](str) }
|
||||
|
||||
// ConvertInt64 turns a string into an int64.
|
||||
//
|
||||
// Deprecated: use [conv.ConvertInt64] instead. Alternatively, you may use the generic version [conv.ConvertInteger].
|
||||
func ConvertInt64(str string) (int64, error) { return conv.ConvertInteger[int64](str) }
|
||||
|
||||
// ConvertUint8 turns a string into an uint8.
|
||||
//
|
||||
// Deprecated: use [conv.ConvertUint8] instead. Alternatively, you may use the generic version [conv.ConvertUinteger].
|
||||
func ConvertUint8(str string) (uint8, error) { return conv.ConvertUinteger[uint8](str) }
|
||||
|
||||
// ConvertUint16 turns a string into an uint16.
|
||||
//
|
||||
// Deprecated: use [conv.ConvertUint16] instead. Alternatively, you may use the generic version [conv.ConvertUinteger].
|
||||
func ConvertUint16(str string) (uint16, error) { return conv.ConvertUinteger[uint16](str) }
|
||||
|
||||
// ConvertUint32 turns a string into an uint32.
|
||||
//
|
||||
// Deprecated: use [conv.ConvertUint32] instead. Alternatively, you may use the generic version [conv.ConvertUinteger].
|
||||
func ConvertUint32(str string) (uint32, error) { return conv.ConvertUinteger[uint32](str) }
|
||||
|
||||
// ConvertUint64 turns a string into an uint64.
|
||||
//
|
||||
// Deprecated: use [conv.ConvertUint64] instead. Alternatively, you may use the generic version [conv.ConvertUinteger].
|
||||
func ConvertUint64(str string) (uint64, error) { return conv.ConvertUinteger[uint64](str) }
|
||||
|
||||
// FormatBool turns a boolean into a string.
|
||||
//
|
||||
// Deprecated: use [conv.FormatBool] instead.
|
||||
func FormatBool(value bool) string { return conv.FormatBool(value) }
|
||||
|
||||
// FormatFloat32 turns a float32 into a string.
|
||||
//
|
||||
// Deprecated: use [conv.FormatFloat] instead.
|
||||
func FormatFloat32(value float32) string { return conv.FormatFloat(value) }
|
||||
|
||||
// FormatFloat64 turns a float64 into a string.
|
||||
//
|
||||
// Deprecated: use [conv.FormatFloat] instead.
|
||||
func FormatFloat64(value float64) string { return conv.FormatFloat(value) }
|
||||
|
||||
// FormatInt8 turns an int8 into a string.
|
||||
//
|
||||
// Deprecated: use [conv.FormatInteger] instead.
|
||||
func FormatInt8(value int8) string { return conv.FormatInteger(value) }
|
||||
|
||||
// FormatInt16 turns an int16 into a string.
|
||||
//
|
||||
// Deprecated: use [conv.FormatInteger] instead.
|
||||
func FormatInt16(value int16) string { return conv.FormatInteger(value) }
|
||||
|
||||
// FormatInt32 turns an int32 into a string
|
||||
//
|
||||
// Deprecated: use [conv.FormatInteger] instead.
|
||||
func FormatInt32(value int32) string { return conv.FormatInteger(value) }
|
||||
|
||||
// FormatInt64 turns an int64 into a string.
|
||||
//
|
||||
// Deprecated: use [conv.FormatInteger] instead.
|
||||
func FormatInt64(value int64) string { return conv.FormatInteger(value) }
|
||||
|
||||
// FormatUint8 turns an uint8 into a string.
|
||||
//
|
||||
// Deprecated: use [conv.FormatUinteger] instead.
|
||||
func FormatUint8(value uint8) string { return conv.FormatUinteger(value) }
|
||||
|
||||
// FormatUint16 turns an uint16 into a string.
|
||||
//
|
||||
// Deprecated: use [conv.FormatUinteger] instead.
|
||||
func FormatUint16(value uint16) string { return conv.FormatUinteger(value) }
|
||||
|
||||
// FormatUint32 turns an uint32 into a string.
|
||||
//
|
||||
// Deprecated: use [conv.FormatUinteger] instead.
|
||||
func FormatUint32(value uint32) string { return conv.FormatUinteger(value) }
|
||||
|
||||
// FormatUint64 turns an uint64 into a string.
|
||||
//
|
||||
// Deprecated: use [conv.FormatUinteger] instead.
|
||||
func FormatUint64(value uint64) string { return conv.FormatUinteger(value) }
|
||||
|
||||
// String turn a pointer to of the string value passed in.
|
||||
//
|
||||
// Deprecated: use [conv.Pointer] instead.
|
||||
func String(v string) *string { return conv.Pointer(v) }
|
||||
|
||||
// StringValue turn the value of the string pointer passed in or
|
||||
// "" if the pointer is nil.
|
||||
//
|
||||
// Deprecated: use [conv.Value] instead.
|
||||
func StringValue(v *string) string { return conv.Value(v) }
|
||||
|
||||
// StringSlice converts a slice of string values into a slice of string pointers.
|
||||
//
|
||||
// Deprecated: use [conv.PointerSlice] instead.
|
||||
func StringSlice(src []string) []*string { return conv.PointerSlice(src) }
|
||||
|
||||
// StringValueSlice converts a slice of string pointers into a slice of string values.
|
||||
//
|
||||
// Deprecated: use [conv.ValueSlice] instead.
|
||||
func StringValueSlice(src []*string) []string { return conv.ValueSlice(src) }
|
||||
|
||||
// StringMap converts a string map of string values into a string map of string pointers.
|
||||
//
|
||||
// Deprecated: use [conv.PointerMap] instead.
|
||||
func StringMap(src map[string]string) map[string]*string { return conv.PointerMap(src) }
|
||||
|
||||
// StringValueMap converts a string map of string pointers into a string map of string values.
|
||||
//
|
||||
// Deprecated: use [conv.ValueMap] instead.
|
||||
func StringValueMap(src map[string]*string) map[string]string { return conv.ValueMap(src) }
|
||||
|
||||
// Bool turn a pointer to of the bool value passed in.
|
||||
//
|
||||
// Deprecated: use [conv.Pointer] instead.
|
||||
func Bool(v bool) *bool { return conv.Pointer(v) }
|
||||
|
||||
// BoolValue turn the value of the bool pointer passed in or false if the pointer is nil.
|
||||
//
|
||||
// Deprecated: use [conv.Value] instead.
|
||||
func BoolValue(v *bool) bool { return conv.Value(v) }
|
||||
|
||||
// BoolSlice converts a slice of bool values into a slice of bool pointers.
|
||||
//
|
||||
// Deprecated: use [conv.PointerSlice] instead.
|
||||
func BoolSlice(src []bool) []*bool { return conv.PointerSlice(src) }
|
||||
|
||||
// BoolValueSlice converts a slice of bool pointers into a slice of bool values.
|
||||
//
|
||||
// Deprecated: use [conv.ValueSlice] instead.
|
||||
func BoolValueSlice(src []*bool) []bool { return conv.ValueSlice(src) }
|
||||
|
||||
// BoolMap converts a string map of bool values into a string map of bool pointers.
|
||||
//
|
||||
// Deprecated: use [conv.PointerMap] instead.
|
||||
func BoolMap(src map[string]bool) map[string]*bool { return conv.PointerMap(src) }
|
||||
|
||||
// BoolValueMap converts a string map of bool pointers into a string map of bool values.
|
||||
//
|
||||
// Deprecated: use [conv.ValueMap] instead.
|
||||
func BoolValueMap(src map[string]*bool) map[string]bool { return conv.ValueMap(src) }
|
||||
|
||||
// Int turn a pointer to of the int value passed in.
|
||||
//
|
||||
// Deprecated: use [conv.Pointer] instead.
|
||||
func Int(v int) *int { return conv.Pointer(v) }
|
||||
|
||||
// IntValue turn the value of the int pointer passed in or 0 if the pointer is nil.
|
||||
//
|
||||
// Deprecated: use [conv.Value] instead.
|
||||
func IntValue(v *int) int { return conv.Value(v) }
|
||||
|
||||
// IntSlice converts a slice of int values into a slice of int pointers.
|
||||
//
|
||||
// Deprecated: use [conv.PointerSlice] instead.
|
||||
func IntSlice(src []int) []*int { return conv.PointerSlice(src) }
|
||||
|
||||
// IntValueSlice converts a slice of int pointers into a slice of int values.
|
||||
//
|
||||
// Deprecated: use [conv.ValueSlice] instead.
|
||||
func IntValueSlice(src []*int) []int { return conv.ValueSlice(src) }
|
||||
|
||||
// IntMap converts a string map of int values into a string map of int pointers.
|
||||
//
|
||||
// Deprecated: use [conv.PointerMap] instead.
|
||||
func IntMap(src map[string]int) map[string]*int { return conv.PointerMap(src) }
|
||||
|
||||
// IntValueMap converts a string map of int pointers into a string map of int values.
|
||||
//
|
||||
// Deprecated: use [conv.ValueMap] instead.
|
||||
func IntValueMap(src map[string]*int) map[string]int { return conv.ValueMap(src) }
|
||||
|
||||
// Int32 turn a pointer to of the int32 value passed in.
|
||||
//
|
||||
// Deprecated: use [conv.Pointer] instead.
|
||||
func Int32(v int32) *int32 { return conv.Pointer(v) }
|
||||
|
||||
// Int32Value turn the value of the int32 pointer passed in or 0 if the pointer is nil.
|
||||
//
|
||||
// Deprecated: use [conv.Value] instead.
|
||||
func Int32Value(v *int32) int32 { return conv.Value(v) }
|
||||
|
||||
// Int32Slice converts a slice of int32 values into a slice of int32 pointers.
|
||||
//
|
||||
// Deprecated: use [conv.PointerSlice] instead.
|
||||
func Int32Slice(src []int32) []*int32 { return conv.PointerSlice(src) }
|
||||
|
||||
// Int32ValueSlice converts a slice of int32 pointers into a slice of int32 values.
|
||||
//
|
||||
// Deprecated: use [conv.ValueSlice] instead.
|
||||
func Int32ValueSlice(src []*int32) []int32 { return conv.ValueSlice(src) }
|
||||
|
||||
// Int32Map converts a string map of int32 values into a string map of int32 pointers.
|
||||
//
|
||||
// Deprecated: use [conv.PointerMap] instead.
|
||||
func Int32Map(src map[string]int32) map[string]*int32 { return conv.PointerMap(src) }
|
||||
|
||||
// Int32ValueMap converts a string map of int32 pointers into a string map of int32 values.
|
||||
//
|
||||
// Deprecated: use [conv.ValueMap] instead.
|
||||
func Int32ValueMap(src map[string]*int32) map[string]int32 { return conv.ValueMap(src) }
|
||||
|
||||
// Int64 turn a pointer to of the int64 value passed in.
|
||||
//
|
||||
// Deprecated: use [conv.Pointer] instead.
|
||||
func Int64(v int64) *int64 { return conv.Pointer(v) }
|
||||
|
||||
// Int64Value turn the value of the int64 pointer passed in or 0 if the pointer is nil.
|
||||
//
|
||||
// Deprecated: use [conv.Value] instead.
|
||||
func Int64Value(v *int64) int64 { return conv.Value(v) }
|
||||
|
||||
// Int64Slice converts a slice of int64 values into a slice of int64 pointers.
|
||||
//
|
||||
// Deprecated: use [conv.PointerSlice] instead.
|
||||
func Int64Slice(src []int64) []*int64 { return conv.PointerSlice(src) }
|
||||
|
||||
// Int64ValueSlice converts a slice of int64 pointers into a slice of int64 values.
|
||||
//
|
||||
// Deprecated: use [conv.ValueSlice] instead.
|
||||
func Int64ValueSlice(src []*int64) []int64 { return conv.ValueSlice(src) }
|
||||
|
||||
// Int64Map converts a string map of int64 values into a string map of int64 pointers.
|
||||
//
|
||||
// Deprecated: use [conv.PointerMap] instead.
|
||||
func Int64Map(src map[string]int64) map[string]*int64 { return conv.PointerMap(src) }
|
||||
|
||||
// Int64ValueMap converts a string map of int64 pointers into a string map of int64 values.
|
||||
//
|
||||
// Deprecated: use [conv.ValueMap] instead.
|
||||
func Int64ValueMap(src map[string]*int64) map[string]int64 { return conv.ValueMap(src) }
|
||||
|
||||
// Uint16 turn a pointer to of the uint16 value passed in.
|
||||
//
|
||||
// Deprecated: use [conv.Pointer] instead.
|
||||
func Uint16(v uint16) *uint16 { return conv.Pointer(v) }
|
||||
|
||||
// Uint16Value turn the value of the uint16 pointer passed in or 0 if the pointer is nil.
|
||||
//
|
||||
// Deprecated: use [conv.Value] instead.
|
||||
func Uint16Value(v *uint16) uint16 { return conv.Value(v) }
|
||||
|
||||
// Uint16Slice converts a slice of uint16 values into a slice of uint16 pointers.
|
||||
//
|
||||
// Deprecated: use [conv.PointerSlice] instead.
|
||||
func Uint16Slice(src []uint16) []*uint16 { return conv.PointerSlice(src) }
|
||||
|
||||
// Uint16ValueSlice converts a slice of uint16 pointers into a slice of uint16 values.
|
||||
//
|
||||
// Deprecated: use [conv.ValueSlice] instead.
|
||||
func Uint16ValueSlice(src []*uint16) []uint16 { return conv.ValueSlice(src) }
|
||||
|
||||
// Uint16Map converts a string map of uint16 values into a string map of uint16 pointers.
|
||||
//
|
||||
// Deprecated: use [conv.PointerMap] instead.
|
||||
func Uint16Map(src map[string]uint16) map[string]*uint16 { return conv.PointerMap(src) }
|
||||
|
||||
// Uint16ValueMap converts a string map of uint16 pointers into a string map of uint16 values.
|
||||
//
|
||||
// Deprecated: use [conv.ValueMap] instead.
|
||||
func Uint16ValueMap(src map[string]*uint16) map[string]uint16 { return conv.ValueMap(src) }
|
||||
|
||||
// Uint turn a pointer to of the uint value passed in.
|
||||
//
|
||||
// Deprecated: use [conv.Pointer] instead.
|
||||
func Uint(v uint) *uint { return conv.Pointer(v) }
|
||||
|
||||
// UintValue turn the value of the uint pointer passed in or 0 if the pointer is nil.
|
||||
//
|
||||
// Deprecated: use [conv.Value] instead.
|
||||
func UintValue(v *uint) uint { return conv.Value(v) }
|
||||
|
||||
// UintSlice converts a slice of uint values into a slice of uint pointers.
|
||||
//
|
||||
// Deprecated: use [conv.PointerSlice] instead.
|
||||
func UintSlice(src []uint) []*uint { return conv.PointerSlice(src) }
|
||||
|
||||
// UintValueSlice converts a slice of uint pointers into a slice of uint values.
|
||||
//
|
||||
// Deprecated: use [conv.ValueSlice] instead.
|
||||
func UintValueSlice(src []*uint) []uint { return conv.ValueSlice(src) }
|
||||
|
||||
// UintMap converts a string map of uint values into a string map of uint pointers.
|
||||
//
|
||||
// Deprecated: use [conv.PointerMap] instead.
|
||||
func UintMap(src map[string]uint) map[string]*uint { return conv.PointerMap(src) }
|
||||
|
||||
// UintValueMap converts a string map of uint pointers into a string map of uint values.
|
||||
//
|
||||
// Deprecated: use [conv.ValueMap] instead.
|
||||
func UintValueMap(src map[string]*uint) map[string]uint { return conv.ValueMap(src) }
|
||||
|
||||
// Uint32 turn a pointer to of the uint32 value passed in.
|
||||
//
|
||||
// Deprecated: use [conv.Pointer] instead.
|
||||
func Uint32(v uint32) *uint32 { return conv.Pointer(v) }
|
||||
|
||||
// Uint32Value turn the value of the uint32 pointer passed in or 0 if the pointer is nil.
|
||||
//
|
||||
// Deprecated: use [conv.Value] instead.
|
||||
func Uint32Value(v *uint32) uint32 { return conv.Value(v) }
|
||||
|
||||
// Uint32Slice converts a slice of uint32 values into a slice of uint32 pointers.
|
||||
//
|
||||
// Deprecated: use [conv.PointerSlice] instead.
|
||||
func Uint32Slice(src []uint32) []*uint32 { return conv.PointerSlice(src) }
|
||||
|
||||
// Uint32ValueSlice converts a slice of uint32 pointers into a slice of uint32 values.
|
||||
//
|
||||
// Deprecated: use [conv.ValueSlice] instead.
|
||||
func Uint32ValueSlice(src []*uint32) []uint32 { return conv.ValueSlice(src) }
|
||||
|
||||
// Uint32Map converts a string map of uint32 values into a string map of uint32 pointers.
|
||||
//
|
||||
// Deprecated: use [conv.PointerMap] instead.
|
||||
func Uint32Map(src map[string]uint32) map[string]*uint32 { return conv.PointerMap(src) }
|
||||
|
||||
// Uint32ValueMap converts a string map of uint32 pointers into a string map of uint32 values.
|
||||
//
|
||||
// Deprecated: use [conv.ValueMap] instead.
|
||||
func Uint32ValueMap(src map[string]*uint32) map[string]uint32 { return conv.ValueMap(src) }
|
||||
|
||||
// Uint64 turn a pointer to of the uint64 value passed in.
|
||||
//
|
||||
// Deprecated: use [conv.Pointer] instead.
|
||||
func Uint64(v uint64) *uint64 { return conv.Pointer(v) }
|
||||
|
||||
// Uint64Value turn the value of the uint64 pointer passed in or 0 if the pointer is nil.
|
||||
//
|
||||
// Deprecated: use [conv.Value] instead.
|
||||
func Uint64Value(v *uint64) uint64 { return conv.Value(v) }
|
||||
|
||||
// Uint64Slice converts a slice of uint64 values into a slice of uint64 pointers.
|
||||
//
|
||||
// Deprecated: use [conv.PointerSlice] instead.
|
||||
func Uint64Slice(src []uint64) []*uint64 { return conv.PointerSlice(src) }
|
||||
|
||||
// Uint64ValueSlice converts a slice of uint64 pointers into a slice of uint64 values.
|
||||
//
|
||||
// Deprecated: use [conv.ValueSlice] instead.
|
||||
func Uint64ValueSlice(src []*uint64) []uint64 { return conv.ValueSlice(src) }
|
||||
|
||||
// Uint64Map converts a string map of uint64 values into a string map of uint64 pointers.
|
||||
//
|
||||
// Deprecated: use [conv.PointerMap] instead.
|
||||
func Uint64Map(src map[string]uint64) map[string]*uint64 { return conv.PointerMap(src) }
|
||||
|
||||
// Uint64ValueMap converts a string map of uint64 pointers into a string map of uint64 values.
|
||||
//
|
||||
// Deprecated: use [conv.ValueMap] instead.
|
||||
func Uint64ValueMap(src map[string]*uint64) map[string]uint64 { return conv.ValueMap(src) }
|
||||
|
||||
// Float32 turn a pointer to of the float32 value passed in.
|
||||
//
|
||||
// Deprecated: use [conv.Pointer] instead.
|
||||
func Float32(v float32) *float32 { return conv.Pointer(v) }
|
||||
|
||||
// Float32Value turn the value of the float32 pointer passed in or 0 if the pointer is nil.
|
||||
//
|
||||
// Deprecated: use [conv.Value] instead.
|
||||
func Float32Value(v *float32) float32 { return conv.Value(v) }
|
||||
|
||||
// Float32Slice converts a slice of float32 values into a slice of float32 pointers.
|
||||
//
|
||||
// Deprecated: use [conv.PointerSlice] instead.
|
||||
func Float32Slice(src []float32) []*float32 { return conv.PointerSlice(src) }
|
||||
|
||||
// Float32ValueSlice converts a slice of float32 pointers into a slice of float32 values.
|
||||
//
|
||||
// Deprecated: use [conv.ValueSlice] instead.
|
||||
func Float32ValueSlice(src []*float32) []float32 { return conv.ValueSlice(src) }
|
||||
|
||||
// Float32Map converts a string map of float32 values into a string map of float32 pointers.
|
||||
//
|
||||
// Deprecated: use [conv.PointerMap] instead.
|
||||
func Float32Map(src map[string]float32) map[string]*float32 { return conv.PointerMap(src) }
|
||||
|
||||
// Float32ValueMap converts a string map of float32 pointers into a string map of float32 values.
|
||||
//
|
||||
// Deprecated: use [conv.ValueMap] instead.
|
||||
func Float32ValueMap(src map[string]*float32) map[string]float32 { return conv.ValueMap(src) }
|
||||
|
||||
// Float64 turn a pointer to of the float64 value passed in.
|
||||
//
|
||||
// Deprecated: use [conv.Pointer] instead.
|
||||
func Float64(v float64) *float64 { return conv.Pointer(v) }
|
||||
|
||||
// Float64Value turn the value of the float64 pointer passed in or 0 if the pointer is nil.
|
||||
//
|
||||
// Deprecated: use [conv.Value] instead.
|
||||
func Float64Value(v *float64) float64 { return conv.Value(v) }
|
||||
|
||||
// Float64Slice converts a slice of float64 values into a slice of float64 pointers.
|
||||
//
|
||||
// Deprecated: use [conv.PointerSlice] instead.
|
||||
func Float64Slice(src []float64) []*float64 { return conv.PointerSlice(src) }
|
||||
|
||||
// Float64ValueSlice converts a slice of float64 pointers into a slice of float64 values.
|
||||
//
|
||||
// Deprecated: use [conv.ValueSlice] instead.
|
||||
func Float64ValueSlice(src []*float64) []float64 { return conv.ValueSlice(src) }
|
||||
|
||||
// Float64Map converts a string map of float64 values into a string map of float64 pointers.
|
||||
//
|
||||
// Deprecated: use [conv.PointerMap] instead.
|
||||
func Float64Map(src map[string]float64) map[string]*float64 { return conv.PointerMap(src) }
|
||||
|
||||
// Float64ValueMap converts a string map of float64 pointers into a string map of float64 values.
|
||||
//
|
||||
// Deprecated: use [conv.ValueMap] instead.
|
||||
func Float64ValueMap(src map[string]*float64) map[string]float64 { return conv.ValueMap(src) }
|
||||
|
||||
// Time turn a pointer to of the time.Time value passed in.
|
||||
//
|
||||
// Deprecated: use [conv.Pointer] instead.
|
||||
func Time(v time.Time) *time.Time { return conv.Pointer(v) }
|
||||
|
||||
// TimeValue turn the value of the time.Time pointer passed in or time.Time{} if the pointer is nil.
|
||||
//
|
||||
// Deprecated: use [conv.Value] instead.
|
||||
func TimeValue(v *time.Time) time.Time { return conv.Value(v) }
|
||||
|
||||
// TimeSlice converts a slice of time.Time values into a slice of time.Time pointers.
|
||||
//
|
||||
// Deprecated: use [conv.PointerSlice] instead.
|
||||
func TimeSlice(src []time.Time) []*time.Time { return conv.PointerSlice(src) }
|
||||
|
||||
// TimeValueSlice converts a slice of time.Time pointers into a slice of time.Time values
|
||||
//
|
||||
// Deprecated: use [conv.ValueSlice] instead.
|
||||
func TimeValueSlice(src []*time.Time) []time.Time { return conv.ValueSlice(src) }
|
||||
|
||||
// TimeMap converts a string map of time.Time values into a string map of time.Time pointers.
|
||||
//
|
||||
// Deprecated: use [conv.PointerMap] instead.
|
||||
func TimeMap(src map[string]time.Time) map[string]*time.Time { return conv.PointerMap(src) }
|
||||
|
||||
// TimeValueMap converts a string map of time.Time pointers into a string map of time.Time values.
|
||||
//
|
||||
// Deprecated: use [conv.ValueMap] instead.
|
||||
func TimeValueMap(src map[string]*time.Time) map[string]time.Time { return conv.ValueMap(src) }
|
||||
-208
@@ -1,208 +0,0 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// 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 swag
|
||||
|
||||
import (
|
||||
"math"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// same as ECMA Number.MAX_SAFE_INTEGER and Number.MIN_SAFE_INTEGER
|
||||
const (
|
||||
maxJSONFloat = float64(1<<53 - 1) // 9007199254740991.0 2^53 - 1
|
||||
minJSONFloat = -float64(1<<53 - 1) //-9007199254740991.0 -2^53 - 1
|
||||
epsilon float64 = 1e-9
|
||||
)
|
||||
|
||||
// IsFloat64AJSONInteger allow for integers [-2^53, 2^53-1] inclusive
|
||||
func IsFloat64AJSONInteger(f float64) bool {
|
||||
if math.IsNaN(f) || math.IsInf(f, 0) || f < minJSONFloat || f > maxJSONFloat {
|
||||
return false
|
||||
}
|
||||
fa := math.Abs(f)
|
||||
g := float64(uint64(f))
|
||||
ga := math.Abs(g)
|
||||
|
||||
diff := math.Abs(f - g)
|
||||
|
||||
// more info: https://floating-point-gui.de/errors/comparison/#look-out-for-edge-cases
|
||||
switch {
|
||||
case f == g: // best case
|
||||
return true
|
||||
case f == float64(int64(f)) || f == float64(uint64(f)): // optimistic case
|
||||
return true
|
||||
case f == 0 || g == 0 || diff < math.SmallestNonzeroFloat64: // very close to 0 values
|
||||
return diff < (epsilon * math.SmallestNonzeroFloat64)
|
||||
}
|
||||
// check the relative error
|
||||
return diff/math.Min(fa+ga, math.MaxFloat64) < epsilon
|
||||
}
|
||||
|
||||
var evaluatesAsTrue map[string]struct{}
|
||||
|
||||
func init() {
|
||||
evaluatesAsTrue = map[string]struct{}{
|
||||
"true": {},
|
||||
"1": {},
|
||||
"yes": {},
|
||||
"ok": {},
|
||||
"y": {},
|
||||
"on": {},
|
||||
"selected": {},
|
||||
"checked": {},
|
||||
"t": {},
|
||||
"enabled": {},
|
||||
}
|
||||
}
|
||||
|
||||
// ConvertBool turn a string into a boolean
|
||||
func ConvertBool(str string) (bool, error) {
|
||||
_, ok := evaluatesAsTrue[strings.ToLower(str)]
|
||||
return ok, nil
|
||||
}
|
||||
|
||||
// ConvertFloat32 turn a string into a float32
|
||||
func ConvertFloat32(str string) (float32, error) {
|
||||
f, err := strconv.ParseFloat(str, 32)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return float32(f), nil
|
||||
}
|
||||
|
||||
// ConvertFloat64 turn a string into a float64
|
||||
func ConvertFloat64(str string) (float64, error) {
|
||||
return strconv.ParseFloat(str, 64)
|
||||
}
|
||||
|
||||
// ConvertInt8 turn a string into an int8
|
||||
func ConvertInt8(str string) (int8, error) {
|
||||
i, err := strconv.ParseInt(str, 10, 8)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return int8(i), nil
|
||||
}
|
||||
|
||||
// ConvertInt16 turn a string into an int16
|
||||
func ConvertInt16(str string) (int16, error) {
|
||||
i, err := strconv.ParseInt(str, 10, 16)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return int16(i), nil
|
||||
}
|
||||
|
||||
// ConvertInt32 turn a string into an int32
|
||||
func ConvertInt32(str string) (int32, error) {
|
||||
i, err := strconv.ParseInt(str, 10, 32)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return int32(i), nil
|
||||
}
|
||||
|
||||
// ConvertInt64 turn a string into an int64
|
||||
func ConvertInt64(str string) (int64, error) {
|
||||
return strconv.ParseInt(str, 10, 64)
|
||||
}
|
||||
|
||||
// ConvertUint8 turn a string into an uint8
|
||||
func ConvertUint8(str string) (uint8, error) {
|
||||
i, err := strconv.ParseUint(str, 10, 8)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return uint8(i), nil
|
||||
}
|
||||
|
||||
// ConvertUint16 turn a string into an uint16
|
||||
func ConvertUint16(str string) (uint16, error) {
|
||||
i, err := strconv.ParseUint(str, 10, 16)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return uint16(i), nil
|
||||
}
|
||||
|
||||
// ConvertUint32 turn a string into an uint32
|
||||
func ConvertUint32(str string) (uint32, error) {
|
||||
i, err := strconv.ParseUint(str, 10, 32)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return uint32(i), nil
|
||||
}
|
||||
|
||||
// ConvertUint64 turn a string into an uint64
|
||||
func ConvertUint64(str string) (uint64, error) {
|
||||
return strconv.ParseUint(str, 10, 64)
|
||||
}
|
||||
|
||||
// FormatBool turns a boolean into a string
|
||||
func FormatBool(value bool) string {
|
||||
return strconv.FormatBool(value)
|
||||
}
|
||||
|
||||
// FormatFloat32 turns a float32 into a string
|
||||
func FormatFloat32(value float32) string {
|
||||
return strconv.FormatFloat(float64(value), 'f', -1, 32)
|
||||
}
|
||||
|
||||
// FormatFloat64 turns a float64 into a string
|
||||
func FormatFloat64(value float64) string {
|
||||
return strconv.FormatFloat(value, 'f', -1, 64)
|
||||
}
|
||||
|
||||
// FormatInt8 turns an int8 into a string
|
||||
func FormatInt8(value int8) string {
|
||||
return strconv.FormatInt(int64(value), 10)
|
||||
}
|
||||
|
||||
// FormatInt16 turns an int16 into a string
|
||||
func FormatInt16(value int16) string {
|
||||
return strconv.FormatInt(int64(value), 10)
|
||||
}
|
||||
|
||||
// FormatInt32 turns an int32 into a string
|
||||
func FormatInt32(value int32) string {
|
||||
return strconv.Itoa(int(value))
|
||||
}
|
||||
|
||||
// FormatInt64 turns an int64 into a string
|
||||
func FormatInt64(value int64) string {
|
||||
return strconv.FormatInt(value, 10)
|
||||
}
|
||||
|
||||
// FormatUint8 turns an uint8 into a string
|
||||
func FormatUint8(value uint8) string {
|
||||
return strconv.FormatUint(uint64(value), 10)
|
||||
}
|
||||
|
||||
// FormatUint16 turns an uint16 into a string
|
||||
func FormatUint16(value uint16) string {
|
||||
return strconv.FormatUint(uint64(value), 10)
|
||||
}
|
||||
|
||||
// FormatUint32 turns an uint32 into a string
|
||||
func FormatUint32(value uint32) string {
|
||||
return strconv.FormatUint(uint64(value), 10)
|
||||
}
|
||||
|
||||
// FormatUint64 turns an uint64 into a string
|
||||
func FormatUint64(value uint64) string {
|
||||
return strconv.FormatUint(value, 10)
|
||||
}
|
||||
-730
@@ -1,730 +0,0 @@
|
||||
package swag
|
||||
|
||||
import "time"
|
||||
|
||||
// This file was taken from the aws go sdk
|
||||
|
||||
// String returns a pointer to of the string value passed in.
|
||||
func String(v string) *string {
|
||||
return &v
|
||||
}
|
||||
|
||||
// StringValue returns the value of the string pointer passed in or
|
||||
// "" if the pointer is nil.
|
||||
func StringValue(v *string) string {
|
||||
if v != nil {
|
||||
return *v
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// StringSlice converts a slice of string values into a slice of
|
||||
// string pointers
|
||||
func StringSlice(src []string) []*string {
|
||||
dst := make([]*string, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
dst[i] = &(src[i])
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// StringValueSlice converts a slice of string pointers into a slice of
|
||||
// string values
|
||||
func StringValueSlice(src []*string) []string {
|
||||
dst := make([]string, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
if src[i] != nil {
|
||||
dst[i] = *(src[i])
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// StringMap converts a string map of string values into a string
|
||||
// map of string pointers
|
||||
func StringMap(src map[string]string) map[string]*string {
|
||||
dst := make(map[string]*string)
|
||||
for k, val := range src {
|
||||
v := val
|
||||
dst[k] = &v
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// StringValueMap converts a string map of string pointers into a string
|
||||
// map of string values
|
||||
func StringValueMap(src map[string]*string) map[string]string {
|
||||
dst := make(map[string]string)
|
||||
for k, val := range src {
|
||||
if val != nil {
|
||||
dst[k] = *val
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Bool returns a pointer to of the bool value passed in.
|
||||
func Bool(v bool) *bool {
|
||||
return &v
|
||||
}
|
||||
|
||||
// BoolValue returns the value of the bool pointer passed in or
|
||||
// false if the pointer is nil.
|
||||
func BoolValue(v *bool) bool {
|
||||
if v != nil {
|
||||
return *v
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// BoolSlice converts a slice of bool values into a slice of
|
||||
// bool pointers
|
||||
func BoolSlice(src []bool) []*bool {
|
||||
dst := make([]*bool, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
dst[i] = &(src[i])
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// BoolValueSlice converts a slice of bool pointers into a slice of
|
||||
// bool values
|
||||
func BoolValueSlice(src []*bool) []bool {
|
||||
dst := make([]bool, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
if src[i] != nil {
|
||||
dst[i] = *(src[i])
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// BoolMap converts a string map of bool values into a string
|
||||
// map of bool pointers
|
||||
func BoolMap(src map[string]bool) map[string]*bool {
|
||||
dst := make(map[string]*bool)
|
||||
for k, val := range src {
|
||||
v := val
|
||||
dst[k] = &v
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// BoolValueMap converts a string map of bool pointers into a string
|
||||
// map of bool values
|
||||
func BoolValueMap(src map[string]*bool) map[string]bool {
|
||||
dst := make(map[string]bool)
|
||||
for k, val := range src {
|
||||
if val != nil {
|
||||
dst[k] = *val
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Int returns a pointer to of the int value passed in.
|
||||
func Int(v int) *int {
|
||||
return &v
|
||||
}
|
||||
|
||||
// IntValue returns the value of the int pointer passed in or
|
||||
// 0 if the pointer is nil.
|
||||
func IntValue(v *int) int {
|
||||
if v != nil {
|
||||
return *v
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// IntSlice converts a slice of int values into a slice of
|
||||
// int pointers
|
||||
func IntSlice(src []int) []*int {
|
||||
dst := make([]*int, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
dst[i] = &(src[i])
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// IntValueSlice converts a slice of int pointers into a slice of
|
||||
// int values
|
||||
func IntValueSlice(src []*int) []int {
|
||||
dst := make([]int, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
if src[i] != nil {
|
||||
dst[i] = *(src[i])
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// IntMap converts a string map of int values into a string
|
||||
// map of int pointers
|
||||
func IntMap(src map[string]int) map[string]*int {
|
||||
dst := make(map[string]*int)
|
||||
for k, val := range src {
|
||||
v := val
|
||||
dst[k] = &v
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// IntValueMap converts a string map of int pointers into a string
|
||||
// map of int values
|
||||
func IntValueMap(src map[string]*int) map[string]int {
|
||||
dst := make(map[string]int)
|
||||
for k, val := range src {
|
||||
if val != nil {
|
||||
dst[k] = *val
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Int32 returns a pointer to of the int32 value passed in.
|
||||
func Int32(v int32) *int32 {
|
||||
return &v
|
||||
}
|
||||
|
||||
// Int32Value returns the value of the int32 pointer passed in or
|
||||
// 0 if the pointer is nil.
|
||||
func Int32Value(v *int32) int32 {
|
||||
if v != nil {
|
||||
return *v
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Int32Slice converts a slice of int32 values into a slice of
|
||||
// int32 pointers
|
||||
func Int32Slice(src []int32) []*int32 {
|
||||
dst := make([]*int32, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
dst[i] = &(src[i])
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Int32ValueSlice converts a slice of int32 pointers into a slice of
|
||||
// int32 values
|
||||
func Int32ValueSlice(src []*int32) []int32 {
|
||||
dst := make([]int32, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
if src[i] != nil {
|
||||
dst[i] = *(src[i])
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Int32Map converts a string map of int32 values into a string
|
||||
// map of int32 pointers
|
||||
func Int32Map(src map[string]int32) map[string]*int32 {
|
||||
dst := make(map[string]*int32)
|
||||
for k, val := range src {
|
||||
v := val
|
||||
dst[k] = &v
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Int32ValueMap converts a string map of int32 pointers into a string
|
||||
// map of int32 values
|
||||
func Int32ValueMap(src map[string]*int32) map[string]int32 {
|
||||
dst := make(map[string]int32)
|
||||
for k, val := range src {
|
||||
if val != nil {
|
||||
dst[k] = *val
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Int64 returns a pointer to of the int64 value passed in.
|
||||
func Int64(v int64) *int64 {
|
||||
return &v
|
||||
}
|
||||
|
||||
// Int64Value returns the value of the int64 pointer passed in or
|
||||
// 0 if the pointer is nil.
|
||||
func Int64Value(v *int64) int64 {
|
||||
if v != nil {
|
||||
return *v
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Int64Slice converts a slice of int64 values into a slice of
|
||||
// int64 pointers
|
||||
func Int64Slice(src []int64) []*int64 {
|
||||
dst := make([]*int64, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
dst[i] = &(src[i])
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Int64ValueSlice converts a slice of int64 pointers into a slice of
|
||||
// int64 values
|
||||
func Int64ValueSlice(src []*int64) []int64 {
|
||||
dst := make([]int64, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
if src[i] != nil {
|
||||
dst[i] = *(src[i])
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Int64Map converts a string map of int64 values into a string
|
||||
// map of int64 pointers
|
||||
func Int64Map(src map[string]int64) map[string]*int64 {
|
||||
dst := make(map[string]*int64)
|
||||
for k, val := range src {
|
||||
v := val
|
||||
dst[k] = &v
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Int64ValueMap converts a string map of int64 pointers into a string
|
||||
// map of int64 values
|
||||
func Int64ValueMap(src map[string]*int64) map[string]int64 {
|
||||
dst := make(map[string]int64)
|
||||
for k, val := range src {
|
||||
if val != nil {
|
||||
dst[k] = *val
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Uint16 returns a pointer to of the uint16 value passed in.
|
||||
func Uint16(v uint16) *uint16 {
|
||||
return &v
|
||||
}
|
||||
|
||||
// Uint16Value returns the value of the uint16 pointer passed in or
|
||||
// 0 if the pointer is nil.
|
||||
func Uint16Value(v *uint16) uint16 {
|
||||
if v != nil {
|
||||
return *v
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
// Uint16Slice converts a slice of uint16 values into a slice of
|
||||
// uint16 pointers
|
||||
func Uint16Slice(src []uint16) []*uint16 {
|
||||
dst := make([]*uint16, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
dst[i] = &(src[i])
|
||||
}
|
||||
|
||||
return dst
|
||||
}
|
||||
|
||||
// Uint16ValueSlice converts a slice of uint16 pointers into a slice of
|
||||
// uint16 values
|
||||
func Uint16ValueSlice(src []*uint16) []uint16 {
|
||||
dst := make([]uint16, len(src))
|
||||
|
||||
for i := 0; i < len(src); i++ {
|
||||
if src[i] != nil {
|
||||
dst[i] = *(src[i])
|
||||
}
|
||||
}
|
||||
|
||||
return dst
|
||||
}
|
||||
|
||||
// Uint16Map converts a string map of uint16 values into a string
|
||||
// map of uint16 pointers
|
||||
func Uint16Map(src map[string]uint16) map[string]*uint16 {
|
||||
dst := make(map[string]*uint16)
|
||||
|
||||
for k, val := range src {
|
||||
v := val
|
||||
dst[k] = &v
|
||||
}
|
||||
|
||||
return dst
|
||||
}
|
||||
|
||||
// Uint16ValueMap converts a string map of uint16 pointers into a string
|
||||
// map of uint16 values
|
||||
func Uint16ValueMap(src map[string]*uint16) map[string]uint16 {
|
||||
dst := make(map[string]uint16)
|
||||
|
||||
for k, val := range src {
|
||||
if val != nil {
|
||||
dst[k] = *val
|
||||
}
|
||||
}
|
||||
|
||||
return dst
|
||||
}
|
||||
|
||||
// Uint returns a pointer to of the uint value passed in.
|
||||
func Uint(v uint) *uint {
|
||||
return &v
|
||||
}
|
||||
|
||||
// UintValue returns the value of the uint pointer passed in or
|
||||
// 0 if the pointer is nil.
|
||||
func UintValue(v *uint) uint {
|
||||
if v != nil {
|
||||
return *v
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// UintSlice converts a slice of uint values into a slice of
|
||||
// uint pointers
|
||||
func UintSlice(src []uint) []*uint {
|
||||
dst := make([]*uint, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
dst[i] = &(src[i])
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// UintValueSlice converts a slice of uint pointers into a slice of
|
||||
// uint values
|
||||
func UintValueSlice(src []*uint) []uint {
|
||||
dst := make([]uint, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
if src[i] != nil {
|
||||
dst[i] = *(src[i])
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// UintMap converts a string map of uint values into a string
|
||||
// map of uint pointers
|
||||
func UintMap(src map[string]uint) map[string]*uint {
|
||||
dst := make(map[string]*uint)
|
||||
for k, val := range src {
|
||||
v := val
|
||||
dst[k] = &v
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// UintValueMap converts a string map of uint pointers into a string
|
||||
// map of uint values
|
||||
func UintValueMap(src map[string]*uint) map[string]uint {
|
||||
dst := make(map[string]uint)
|
||||
for k, val := range src {
|
||||
if val != nil {
|
||||
dst[k] = *val
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Uint32 returns a pointer to of the uint32 value passed in.
|
||||
func Uint32(v uint32) *uint32 {
|
||||
return &v
|
||||
}
|
||||
|
||||
// Uint32Value returns the value of the uint32 pointer passed in or
|
||||
// 0 if the pointer is nil.
|
||||
func Uint32Value(v *uint32) uint32 {
|
||||
if v != nil {
|
||||
return *v
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Uint32Slice converts a slice of uint32 values into a slice of
|
||||
// uint32 pointers
|
||||
func Uint32Slice(src []uint32) []*uint32 {
|
||||
dst := make([]*uint32, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
dst[i] = &(src[i])
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Uint32ValueSlice converts a slice of uint32 pointers into a slice of
|
||||
// uint32 values
|
||||
func Uint32ValueSlice(src []*uint32) []uint32 {
|
||||
dst := make([]uint32, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
if src[i] != nil {
|
||||
dst[i] = *(src[i])
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Uint32Map converts a string map of uint32 values into a string
|
||||
// map of uint32 pointers
|
||||
func Uint32Map(src map[string]uint32) map[string]*uint32 {
|
||||
dst := make(map[string]*uint32)
|
||||
for k, val := range src {
|
||||
v := val
|
||||
dst[k] = &v
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Uint32ValueMap converts a string map of uint32 pointers into a string
|
||||
// map of uint32 values
|
||||
func Uint32ValueMap(src map[string]*uint32) map[string]uint32 {
|
||||
dst := make(map[string]uint32)
|
||||
for k, val := range src {
|
||||
if val != nil {
|
||||
dst[k] = *val
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Uint64 returns a pointer to of the uint64 value passed in.
|
||||
func Uint64(v uint64) *uint64 {
|
||||
return &v
|
||||
}
|
||||
|
||||
// Uint64Value returns the value of the uint64 pointer passed in or
|
||||
// 0 if the pointer is nil.
|
||||
func Uint64Value(v *uint64) uint64 {
|
||||
if v != nil {
|
||||
return *v
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Uint64Slice converts a slice of uint64 values into a slice of
|
||||
// uint64 pointers
|
||||
func Uint64Slice(src []uint64) []*uint64 {
|
||||
dst := make([]*uint64, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
dst[i] = &(src[i])
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Uint64ValueSlice converts a slice of uint64 pointers into a slice of
|
||||
// uint64 values
|
||||
func Uint64ValueSlice(src []*uint64) []uint64 {
|
||||
dst := make([]uint64, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
if src[i] != nil {
|
||||
dst[i] = *(src[i])
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Uint64Map converts a string map of uint64 values into a string
|
||||
// map of uint64 pointers
|
||||
func Uint64Map(src map[string]uint64) map[string]*uint64 {
|
||||
dst := make(map[string]*uint64)
|
||||
for k, val := range src {
|
||||
v := val
|
||||
dst[k] = &v
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Uint64ValueMap converts a string map of uint64 pointers into a string
|
||||
// map of uint64 values
|
||||
func Uint64ValueMap(src map[string]*uint64) map[string]uint64 {
|
||||
dst := make(map[string]uint64)
|
||||
for k, val := range src {
|
||||
if val != nil {
|
||||
dst[k] = *val
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Float32 returns a pointer to of the float32 value passed in.
|
||||
func Float32(v float32) *float32 {
|
||||
return &v
|
||||
}
|
||||
|
||||
// Float32Value returns the value of the float32 pointer passed in or
|
||||
// 0 if the pointer is nil.
|
||||
func Float32Value(v *float32) float32 {
|
||||
if v != nil {
|
||||
return *v
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
// Float32Slice converts a slice of float32 values into a slice of
|
||||
// float32 pointers
|
||||
func Float32Slice(src []float32) []*float32 {
|
||||
dst := make([]*float32, len(src))
|
||||
|
||||
for i := 0; i < len(src); i++ {
|
||||
dst[i] = &(src[i])
|
||||
}
|
||||
|
||||
return dst
|
||||
}
|
||||
|
||||
// Float32ValueSlice converts a slice of float32 pointers into a slice of
|
||||
// float32 values
|
||||
func Float32ValueSlice(src []*float32) []float32 {
|
||||
dst := make([]float32, len(src))
|
||||
|
||||
for i := 0; i < len(src); i++ {
|
||||
if src[i] != nil {
|
||||
dst[i] = *(src[i])
|
||||
}
|
||||
}
|
||||
|
||||
return dst
|
||||
}
|
||||
|
||||
// Float32Map converts a string map of float32 values into a string
|
||||
// map of float32 pointers
|
||||
func Float32Map(src map[string]float32) map[string]*float32 {
|
||||
dst := make(map[string]*float32)
|
||||
|
||||
for k, val := range src {
|
||||
v := val
|
||||
dst[k] = &v
|
||||
}
|
||||
|
||||
return dst
|
||||
}
|
||||
|
||||
// Float32ValueMap converts a string map of float32 pointers into a string
|
||||
// map of float32 values
|
||||
func Float32ValueMap(src map[string]*float32) map[string]float32 {
|
||||
dst := make(map[string]float32)
|
||||
|
||||
for k, val := range src {
|
||||
if val != nil {
|
||||
dst[k] = *val
|
||||
}
|
||||
}
|
||||
|
||||
return dst
|
||||
}
|
||||
|
||||
// Float64 returns a pointer to of the float64 value passed in.
|
||||
func Float64(v float64) *float64 {
|
||||
return &v
|
||||
}
|
||||
|
||||
// Float64Value returns the value of the float64 pointer passed in or
|
||||
// 0 if the pointer is nil.
|
||||
func Float64Value(v *float64) float64 {
|
||||
if v != nil {
|
||||
return *v
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Float64Slice converts a slice of float64 values into a slice of
|
||||
// float64 pointers
|
||||
func Float64Slice(src []float64) []*float64 {
|
||||
dst := make([]*float64, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
dst[i] = &(src[i])
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Float64ValueSlice converts a slice of float64 pointers into a slice of
|
||||
// float64 values
|
||||
func Float64ValueSlice(src []*float64) []float64 {
|
||||
dst := make([]float64, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
if src[i] != nil {
|
||||
dst[i] = *(src[i])
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Float64Map converts a string map of float64 values into a string
|
||||
// map of float64 pointers
|
||||
func Float64Map(src map[string]float64) map[string]*float64 {
|
||||
dst := make(map[string]*float64)
|
||||
for k, val := range src {
|
||||
v := val
|
||||
dst[k] = &v
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Float64ValueMap converts a string map of float64 pointers into a string
|
||||
// map of float64 values
|
||||
func Float64ValueMap(src map[string]*float64) map[string]float64 {
|
||||
dst := make(map[string]float64)
|
||||
for k, val := range src {
|
||||
if val != nil {
|
||||
dst[k] = *val
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Time returns a pointer to of the time.Time value passed in.
|
||||
func Time(v time.Time) *time.Time {
|
||||
return &v
|
||||
}
|
||||
|
||||
// TimeValue returns the value of the time.Time pointer passed in or
|
||||
// time.Time{} if the pointer is nil.
|
||||
func TimeValue(v *time.Time) time.Time {
|
||||
if v != nil {
|
||||
return *v
|
||||
}
|
||||
return time.Time{}
|
||||
}
|
||||
|
||||
// TimeSlice converts a slice of time.Time values into a slice of
|
||||
// time.Time pointers
|
||||
func TimeSlice(src []time.Time) []*time.Time {
|
||||
dst := make([]*time.Time, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
dst[i] = &(src[i])
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// TimeValueSlice converts a slice of time.Time pointers into a slice of
|
||||
// time.Time values
|
||||
func TimeValueSlice(src []*time.Time) []time.Time {
|
||||
dst := make([]time.Time, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
if src[i] != nil {
|
||||
dst[i] = *(src[i])
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// TimeMap converts a string map of time.Time values into a string
|
||||
// map of time.Time pointers
|
||||
func TimeMap(src map[string]time.Time) map[string]*time.Time {
|
||||
dst := make(map[string]*time.Time)
|
||||
for k, val := range src {
|
||||
v := val
|
||||
dst[k] = &v
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// TimeValueMap converts a string map of time.Time pointers into a string
|
||||
// map of time.Time values
|
||||
func TimeValueMap(src map[string]*time.Time) map[string]time.Time {
|
||||
dst := make(map[string]time.Time)
|
||||
for k, val := range src {
|
||||
if val != nil {
|
||||
dst[k] = *val
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
+43
-27
@@ -1,31 +1,47 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Package swag contains a bunch of helper functions for go-openapi and go-swagger projects.
|
||||
//
|
||||
// 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
|
||||
// You may also use it standalone for your projects.
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
// NOTE: all features that used to be exposed as package-level members (constants, variables,
|
||||
// functions and types) are now deprecated and are superseded by equivalent features in
|
||||
// more specialized sub-packages.
|
||||
// Moving forward, no additional feature will be added to the [swag] API directly at the root package level,
|
||||
// which remains there for backward-compatibility purposes.
|
||||
//
|
||||
// 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 swag contains a bunch of helper functions for go-openapi and go-swagger projects.
|
||||
|
||||
You may also use it standalone for your projects.
|
||||
|
||||
- convert between value and pointers for builtin types
|
||||
- convert from string to builtin types (wraps strconv)
|
||||
- fast json concatenation
|
||||
- search in path
|
||||
- load from file or http
|
||||
- name mangling
|
||||
|
||||
This repo has only few dependencies outside of the standard library:
|
||||
|
||||
- YAML utilities depend on gopkg.in/yaml.v2
|
||||
*/
|
||||
// Child modules will continue to evolve or some new ones may be added in the future.
|
||||
//
|
||||
// # Modules
|
||||
//
|
||||
// - [cmdutils] utilities to work with CLIs
|
||||
//
|
||||
// - [conv] type conversion utilities
|
||||
//
|
||||
// - [fileutils] file utilities
|
||||
//
|
||||
// - [jsonname] JSON utilities
|
||||
//
|
||||
// - [jsonutils] JSON utilities
|
||||
//
|
||||
// - [loading] file loading
|
||||
//
|
||||
// - [mangling] safe name generation
|
||||
//
|
||||
// - [netutils] networking utilities
|
||||
//
|
||||
// - [stringutils] `string` utilities
|
||||
//
|
||||
// - [typeutils] `go` types utilities
|
||||
//
|
||||
// - [yamlutils] YAML utilities
|
||||
//
|
||||
// # Dependencies
|
||||
//
|
||||
// This repo has a few dependencies outside of the standard library:
|
||||
//
|
||||
// - YAML utilities depend on [go.yaml.in/yaml/v3]
|
||||
package swag
|
||||
|
||||
//go:generate mockery
|
||||
|
||||
+202
@@ -0,0 +1,202 @@
|
||||
|
||||
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.
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Package fileutils exposes utilities to deal with files and paths.
|
||||
//
|
||||
// Currently, there is:
|
||||
// - [File] to represent an abstraction of an uploaded file.
|
||||
// For instance, this is used by [github.com/go-openapi/runtime.File].
|
||||
// - path search utilities (e.g. finding packages in the GO search path)
|
||||
package fileutils
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package fileutils
|
||||
|
||||
import "mime/multipart"
|
||||
|
||||
// File represents an uploaded file.
|
||||
type File struct {
|
||||
Data multipart.File
|
||||
Header *multipart.FileHeader
|
||||
}
|
||||
|
||||
// Read bytes from the file
|
||||
func (f *File) Read(p []byte) (n int, err error) {
|
||||
return f.Data.Read(p)
|
||||
}
|
||||
|
||||
// Close the file
|
||||
func (f *File) Close() error {
|
||||
return f.Data.Close()
|
||||
}
|
||||
Generated
Vendored
+11
-18
@@ -1,18 +1,7 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// 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.
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package swag
|
||||
package fileutils
|
||||
|
||||
import (
|
||||
"os"
|
||||
@@ -21,10 +10,8 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
// GOPATHKey represents the env key for gopath
|
||||
GOPATHKey = "GOPATH"
|
||||
)
|
||||
// GOPATHKey represents the env key for gopath
|
||||
const GOPATHKey = "GOPATH"
|
||||
|
||||
// FindInSearchPath finds a package in a provided lists of paths
|
||||
func FindInSearchPath(searchPath, pkg string) string {
|
||||
@@ -40,11 +27,17 @@ func FindInSearchPath(searchPath, pkg string) string {
|
||||
}
|
||||
|
||||
// FindInGoSearchPath finds a package in the $GOPATH:$GOROOT
|
||||
//
|
||||
// Deprecated: this function is no longer relevant with modern go.
|
||||
// It uses [runtime.GOROOT] under the hood, which is deprecated as of go1.24.
|
||||
func FindInGoSearchPath(pkg string) string {
|
||||
return FindInSearchPath(FullGoSearchPath(), pkg)
|
||||
}
|
||||
|
||||
// FullGoSearchPath gets the search paths for finding packages
|
||||
//
|
||||
// Deprecated: this function is no longer relevant with modern go.
|
||||
// It uses [runtime.GOROOT] under the hood, which is deprecated as of go1.24.
|
||||
func FullGoSearchPath() string {
|
||||
allPaths := os.Getenv(GOPATHKey)
|
||||
if allPaths == "" {
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package swag
|
||||
|
||||
import "github.com/go-openapi/swag/fileutils"
|
||||
|
||||
// GOPATHKey represents the env key for gopath
|
||||
//
|
||||
// Deprecated: use [fileutils.GOPATHKey] instead.
|
||||
const GOPATHKey = fileutils.GOPATHKey
|
||||
|
||||
// File represents an uploaded file.
|
||||
//
|
||||
// Deprecated: use [fileutils.File] instead.
|
||||
type File = fileutils.File
|
||||
|
||||
// FindInSearchPath finds a package in a provided lists of paths.
|
||||
//
|
||||
// Deprecated: use [fileutils.FindInSearchPath] instead.
|
||||
func FindInSearchPath(searchPath, pkg string) string {
|
||||
return fileutils.FindInSearchPath(searchPath, pkg)
|
||||
}
|
||||
|
||||
// FindInGoSearchPath finds a package in the $GOPATH:$GOROOT
|
||||
//
|
||||
// Deprecated: use [fileutils.FindInGoSearchPath] instead.
|
||||
func FindInGoSearchPath(pkg string) string { return fileutils.FindInGoSearchPath(pkg) }
|
||||
|
||||
// FullGoSearchPath gets the search paths for finding packages
|
||||
//
|
||||
// Deprecated: use [fileutils.FullGoSearchPath] instead.
|
||||
func FullGoSearchPath() string { return fileutils.FullGoSearchPath() }
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
use (
|
||||
.
|
||||
./cmdutils
|
||||
./conv
|
||||
./fileutils
|
||||
./jsonname
|
||||
./jsonutils
|
||||
./jsonutils/adapters/easyjson
|
||||
./jsonutils/adapters/testintegration
|
||||
./jsonutils/adapters/testintegration/benchmarks
|
||||
./jsonutils/fixtures_test
|
||||
./loading
|
||||
./mangling
|
||||
./netutils
|
||||
./stringutils
|
||||
./typeutils
|
||||
./yamlutils
|
||||
)
|
||||
|
||||
go 1.24.0
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
github.com/go-openapi/testify/v2 v2.0.1/go.mod h1:HCPmvFFnheKK2BuwSA0TbbdxJ3I16pjwMkYkP4Ywn54=
|
||||
golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
|
||||
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
||||
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
|
||||
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
|
||||
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
|
||||
-202
@@ -1,202 +0,0 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// 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 swag
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"strings"
|
||||
"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.
|
||||
// Since go1.9, this may be implemented with sync.Map.
|
||||
type indexOfInitialisms struct {
|
||||
sortMutex *sync.Mutex
|
||||
index *sync.Map
|
||||
}
|
||||
|
||||
func newIndexOfInitialisms() *indexOfInitialisms {
|
||||
return &indexOfInitialisms{
|
||||
sortMutex: new(sync.Mutex),
|
||||
index: new(sync.Map),
|
||||
}
|
||||
}
|
||||
|
||||
func (m *indexOfInitialisms) load(initial map[string]bool) *indexOfInitialisms {
|
||||
m.sortMutex.Lock()
|
||||
defer m.sortMutex.Unlock()
|
||||
for k, v := range initial {
|
||||
m.index.Store(k, v)
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *indexOfInitialisms) isInitialism(key string) bool {
|
||||
_, ok := m.index.Load(key)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (m *indexOfInitialisms) add(key string) *indexOfInitialisms {
|
||||
m.index.Store(key, true)
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *indexOfInitialisms) sorted() (result []string) {
|
||||
m.sortMutex.Lock()
|
||||
defer m.sortMutex.Unlock()
|
||||
m.index.Range(func(key, _ interface{}) bool {
|
||||
k := key.(string)
|
||||
result = append(result, k)
|
||||
return true
|
||||
})
|
||||
sort.Sort(sort.Reverse(byInitialism(result)))
|
||||
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
|
||||
}
|
||||
-312
@@ -1,312 +0,0 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// 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 swag
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"log"
|
||||
"reflect"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/mailru/easyjson/jlexer"
|
||||
"github.com/mailru/easyjson/jwriter"
|
||||
)
|
||||
|
||||
// nullJSON represents a JSON object with null type
|
||||
var nullJSON = []byte("null")
|
||||
|
||||
// DefaultJSONNameProvider the default cache for types
|
||||
var DefaultJSONNameProvider = NewNameProvider()
|
||||
|
||||
const comma = byte(',')
|
||||
|
||||
var closers map[byte]byte
|
||||
|
||||
func init() {
|
||||
closers = map[byte]byte{
|
||||
'{': '}',
|
||||
'[': ']',
|
||||
}
|
||||
}
|
||||
|
||||
type ejMarshaler interface {
|
||||
MarshalEasyJSON(w *jwriter.Writer)
|
||||
}
|
||||
|
||||
type ejUnmarshaler interface {
|
||||
UnmarshalEasyJSON(w *jlexer.Lexer)
|
||||
}
|
||||
|
||||
// WriteJSON writes json data, prefers finding an appropriate interface to short-circuit the marshaler
|
||||
// so it takes the fastest option available.
|
||||
func WriteJSON(data interface{}) ([]byte, error) {
|
||||
if d, ok := data.(ejMarshaler); ok {
|
||||
jw := new(jwriter.Writer)
|
||||
d.MarshalEasyJSON(jw)
|
||||
return jw.BuildBytes()
|
||||
}
|
||||
if d, ok := data.(json.Marshaler); ok {
|
||||
return d.MarshalJSON()
|
||||
}
|
||||
return json.Marshal(data)
|
||||
}
|
||||
|
||||
// ReadJSON reads json data, prefers finding an appropriate interface to short-circuit the unmarshaler
|
||||
// so it takes the fastest option available
|
||||
func ReadJSON(data []byte, value interface{}) error {
|
||||
trimmedData := bytes.Trim(data, "\x00")
|
||||
if d, ok := value.(ejUnmarshaler); ok {
|
||||
jl := &jlexer.Lexer{Data: trimmedData}
|
||||
d.UnmarshalEasyJSON(jl)
|
||||
return jl.Error()
|
||||
}
|
||||
if d, ok := value.(json.Unmarshaler); ok {
|
||||
return d.UnmarshalJSON(trimmedData)
|
||||
}
|
||||
return json.Unmarshal(trimmedData, value)
|
||||
}
|
||||
|
||||
// DynamicJSONToStruct converts an untyped json structure into a struct
|
||||
func DynamicJSONToStruct(data interface{}, target interface{}) error {
|
||||
// TODO: convert straight to a json typed map (mergo + iterate?)
|
||||
b, err := WriteJSON(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return ReadJSON(b, target)
|
||||
}
|
||||
|
||||
// ConcatJSON concatenates multiple json objects efficiently
|
||||
func ConcatJSON(blobs ...[]byte) []byte {
|
||||
if len(blobs) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
last := len(blobs) - 1
|
||||
for blobs[last] == nil || bytes.Equal(blobs[last], nullJSON) {
|
||||
// strips trailing null objects
|
||||
last--
|
||||
if last < 0 {
|
||||
// there was nothing but "null"s or nil...
|
||||
return nil
|
||||
}
|
||||
}
|
||||
if last == 0 {
|
||||
return blobs[0]
|
||||
}
|
||||
|
||||
var opening, closing byte
|
||||
var idx, a int
|
||||
buf := bytes.NewBuffer(nil)
|
||||
|
||||
for i, b := range blobs[:last+1] {
|
||||
if b == nil || bytes.Equal(b, nullJSON) {
|
||||
// a null object is in the list: skip it
|
||||
continue
|
||||
}
|
||||
if len(b) > 0 && opening == 0 { // is this an array or an object?
|
||||
opening, closing = b[0], closers[b[0]]
|
||||
}
|
||||
|
||||
if opening != '{' && opening != '[' {
|
||||
continue // don't know how to concatenate non container objects
|
||||
}
|
||||
|
||||
if len(b) < 3 { // yep empty but also the last one, so closing this thing
|
||||
if i == last && a > 0 {
|
||||
if err := buf.WriteByte(closing); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
idx = 0
|
||||
if a > 0 { // we need to join with a comma for everything beyond the first non-empty item
|
||||
if err := buf.WriteByte(comma); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
idx = 1 // this is not the first or the last so we want to drop the leading bracket
|
||||
}
|
||||
|
||||
if i != last { // not the last one, strip brackets
|
||||
if _, err := buf.Write(b[idx : len(b)-1]); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
} else { // last one, strip only the leading bracket
|
||||
if _, err := buf.Write(b[idx:]); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
||||
a++
|
||||
}
|
||||
// somehow it ended up being empty, so provide a default value
|
||||
if buf.Len() == 0 {
|
||||
if err := buf.WriteByte(opening); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
if err := buf.WriteByte(closing); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
// ToDynamicJSON turns an object into a properly JSON typed structure
|
||||
func ToDynamicJSON(data interface{}) interface{} {
|
||||
// TODO: convert straight to a json typed map (mergo + iterate?)
|
||||
b, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
var res interface{}
|
||||
if err := json.Unmarshal(b, &res); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// FromDynamicJSON turns an object into a properly JSON typed structure
|
||||
func FromDynamicJSON(data, target interface{}) error {
|
||||
b, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
return json.Unmarshal(b, target)
|
||||
}
|
||||
|
||||
// NameProvider represents an object capable of translating from go property names
|
||||
// to json property names
|
||||
// This type is thread-safe.
|
||||
type NameProvider struct {
|
||||
lock *sync.Mutex
|
||||
index map[reflect.Type]nameIndex
|
||||
}
|
||||
|
||||
type nameIndex struct {
|
||||
jsonNames map[string]string
|
||||
goNames map[string]string
|
||||
}
|
||||
|
||||
// NewNameProvider creates a new name provider
|
||||
func NewNameProvider() *NameProvider {
|
||||
return &NameProvider{
|
||||
lock: &sync.Mutex{},
|
||||
index: make(map[reflect.Type]nameIndex),
|
||||
}
|
||||
}
|
||||
|
||||
func buildnameIndex(tpe reflect.Type, idx, reverseIdx map[string]string) {
|
||||
for i := 0; i < tpe.NumField(); i++ {
|
||||
targetDes := tpe.Field(i)
|
||||
|
||||
if targetDes.PkgPath != "" { // unexported
|
||||
continue
|
||||
}
|
||||
|
||||
if targetDes.Anonymous { // walk embedded structures tree down first
|
||||
buildnameIndex(targetDes.Type, idx, reverseIdx)
|
||||
continue
|
||||
}
|
||||
|
||||
if tag := targetDes.Tag.Get("json"); tag != "" {
|
||||
|
||||
parts := strings.Split(tag, ",")
|
||||
if len(parts) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
nm := parts[0]
|
||||
if nm == "-" {
|
||||
continue
|
||||
}
|
||||
if nm == "" { // empty string means we want to use the Go name
|
||||
nm = targetDes.Name
|
||||
}
|
||||
|
||||
idx[nm] = targetDes.Name
|
||||
reverseIdx[targetDes.Name] = nm
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func newNameIndex(tpe reflect.Type) nameIndex {
|
||||
var idx = make(map[string]string, tpe.NumField())
|
||||
var reverseIdx = make(map[string]string, tpe.NumField())
|
||||
|
||||
buildnameIndex(tpe, idx, reverseIdx)
|
||||
return nameIndex{jsonNames: idx, goNames: reverseIdx}
|
||||
}
|
||||
|
||||
// GetJSONNames gets all the json property names for a type
|
||||
func (n *NameProvider) GetJSONNames(subject interface{}) []string {
|
||||
n.lock.Lock()
|
||||
defer n.lock.Unlock()
|
||||
tpe := reflect.Indirect(reflect.ValueOf(subject)).Type()
|
||||
names, ok := n.index[tpe]
|
||||
if !ok {
|
||||
names = n.makeNameIndex(tpe)
|
||||
}
|
||||
|
||||
res := make([]string, 0, len(names.jsonNames))
|
||||
for k := range names.jsonNames {
|
||||
res = append(res, k)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// GetJSONName gets the json name for a go property name
|
||||
func (n *NameProvider) GetJSONName(subject interface{}, name string) (string, bool) {
|
||||
tpe := reflect.Indirect(reflect.ValueOf(subject)).Type()
|
||||
return n.GetJSONNameForType(tpe, name)
|
||||
}
|
||||
|
||||
// GetJSONNameForType gets the json name for a go property name on a given type
|
||||
func (n *NameProvider) GetJSONNameForType(tpe reflect.Type, name string) (string, bool) {
|
||||
n.lock.Lock()
|
||||
defer n.lock.Unlock()
|
||||
names, ok := n.index[tpe]
|
||||
if !ok {
|
||||
names = n.makeNameIndex(tpe)
|
||||
}
|
||||
nme, ok := names.goNames[name]
|
||||
return nme, ok
|
||||
}
|
||||
|
||||
func (n *NameProvider) makeNameIndex(tpe reflect.Type) nameIndex {
|
||||
names := newNameIndex(tpe)
|
||||
n.index[tpe] = names
|
||||
return names
|
||||
}
|
||||
|
||||
// GetGoName gets the go name for a json property name
|
||||
func (n *NameProvider) GetGoName(subject interface{}, name string) (string, bool) {
|
||||
tpe := reflect.Indirect(reflect.ValueOf(subject)).Type()
|
||||
return n.GetGoNameForType(tpe, name)
|
||||
}
|
||||
|
||||
// GetGoNameForType gets the go name for a given type for a json property name
|
||||
func (n *NameProvider) GetGoNameForType(tpe reflect.Type, name string) (string, bool) {
|
||||
n.lock.Lock()
|
||||
defer n.lock.Unlock()
|
||||
names, ok := n.index[tpe]
|
||||
if !ok {
|
||||
names = n.makeNameIndex(tpe)
|
||||
}
|
||||
nme, ok := names.jsonNames[name]
|
||||
return nme, ok
|
||||
}
|
||||
+202
@@ -0,0 +1,202 @@
|
||||
|
||||
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.
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Package jsonname is a provider of json property names from go properties.
|
||||
package jsonname
|
||||
+138
@@ -0,0 +1,138 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package jsonname
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// DefaultJSONNameProvider is the default cache for types.
|
||||
var DefaultJSONNameProvider = NewNameProvider()
|
||||
|
||||
// NameProvider represents an object capable of translating from go property names
|
||||
// to json property names.
|
||||
//
|
||||
// This type is thread-safe.
|
||||
//
|
||||
// See [github.com/go-openapi/jsonpointer.Pointer] for an example.
|
||||
type NameProvider struct {
|
||||
lock *sync.Mutex
|
||||
index map[reflect.Type]nameIndex
|
||||
}
|
||||
|
||||
type nameIndex struct {
|
||||
jsonNames map[string]string
|
||||
goNames map[string]string
|
||||
}
|
||||
|
||||
// NewNameProvider creates a new name provider
|
||||
func NewNameProvider() *NameProvider {
|
||||
return &NameProvider{
|
||||
lock: &sync.Mutex{},
|
||||
index: make(map[reflect.Type]nameIndex),
|
||||
}
|
||||
}
|
||||
|
||||
func buildnameIndex(tpe reflect.Type, idx, reverseIdx map[string]string) {
|
||||
for i := 0; i < tpe.NumField(); i++ {
|
||||
targetDes := tpe.Field(i)
|
||||
|
||||
if targetDes.PkgPath != "" { // unexported
|
||||
continue
|
||||
}
|
||||
|
||||
if targetDes.Anonymous { // walk embedded structures tree down first
|
||||
buildnameIndex(targetDes.Type, idx, reverseIdx)
|
||||
continue
|
||||
}
|
||||
|
||||
if tag := targetDes.Tag.Get("json"); tag != "" {
|
||||
|
||||
parts := strings.Split(tag, ",")
|
||||
if len(parts) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
nm := parts[0]
|
||||
if nm == "-" {
|
||||
continue
|
||||
}
|
||||
if nm == "" { // empty string means we want to use the Go name
|
||||
nm = targetDes.Name
|
||||
}
|
||||
|
||||
idx[nm] = targetDes.Name
|
||||
reverseIdx[targetDes.Name] = nm
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func newNameIndex(tpe reflect.Type) nameIndex {
|
||||
var idx = make(map[string]string, tpe.NumField())
|
||||
var reverseIdx = make(map[string]string, tpe.NumField())
|
||||
|
||||
buildnameIndex(tpe, idx, reverseIdx)
|
||||
return nameIndex{jsonNames: idx, goNames: reverseIdx}
|
||||
}
|
||||
|
||||
// GetJSONNames gets all the json property names for a type
|
||||
func (n *NameProvider) GetJSONNames(subject any) []string {
|
||||
n.lock.Lock()
|
||||
defer n.lock.Unlock()
|
||||
tpe := reflect.Indirect(reflect.ValueOf(subject)).Type()
|
||||
names, ok := n.index[tpe]
|
||||
if !ok {
|
||||
names = n.makeNameIndex(tpe)
|
||||
}
|
||||
|
||||
res := make([]string, 0, len(names.jsonNames))
|
||||
for k := range names.jsonNames {
|
||||
res = append(res, k)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// GetJSONName gets the json name for a go property name
|
||||
func (n *NameProvider) GetJSONName(subject any, name string) (string, bool) {
|
||||
tpe := reflect.Indirect(reflect.ValueOf(subject)).Type()
|
||||
return n.GetJSONNameForType(tpe, name)
|
||||
}
|
||||
|
||||
// GetJSONNameForType gets the json name for a go property name on a given type
|
||||
func (n *NameProvider) GetJSONNameForType(tpe reflect.Type, name string) (string, bool) {
|
||||
n.lock.Lock()
|
||||
defer n.lock.Unlock()
|
||||
names, ok := n.index[tpe]
|
||||
if !ok {
|
||||
names = n.makeNameIndex(tpe)
|
||||
}
|
||||
nme, ok := names.goNames[name]
|
||||
return nme, ok
|
||||
}
|
||||
|
||||
// GetGoName gets the go name for a json property name
|
||||
func (n *NameProvider) GetGoName(subject any, name string) (string, bool) {
|
||||
tpe := reflect.Indirect(reflect.ValueOf(subject)).Type()
|
||||
return n.GetGoNameForType(tpe, name)
|
||||
}
|
||||
|
||||
// GetGoNameForType gets the go name for a given type for a json property name
|
||||
func (n *NameProvider) GetGoNameForType(tpe reflect.Type, name string) (string, bool) {
|
||||
n.lock.Lock()
|
||||
defer n.lock.Unlock()
|
||||
names, ok := n.index[tpe]
|
||||
if !ok {
|
||||
names = n.makeNameIndex(tpe)
|
||||
}
|
||||
nme, ok := names.jsonNames[name]
|
||||
return nme, ok
|
||||
}
|
||||
|
||||
func (n *NameProvider) makeNameIndex(tpe reflect.Type) nameIndex {
|
||||
names := newNameIndex(tpe)
|
||||
n.index[tpe] = names
|
||||
return names
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package swag
|
||||
|
||||
import (
|
||||
"github.com/go-openapi/swag/jsonname"
|
||||
)
|
||||
|
||||
// DefaultJSONNameProvider is the default cache for types
|
||||
//
|
||||
// Deprecated: use [jsonname.DefaultJSONNameProvider] instead.
|
||||
var DefaultJSONNameProvider = jsonname.DefaultJSONNameProvider
|
||||
|
||||
// NameProvider represents an object capable of translating from go property names
|
||||
// to json property names.
|
||||
//
|
||||
// Deprecated: use [jsonname.NameProvider] instead.
|
||||
type NameProvider = jsonname.NameProvider
|
||||
|
||||
// NewNameProvider creates a new name provider
|
||||
//
|
||||
// Deprecated: use [jsonname.NewNameProvider] instead.
|
||||
func NewNameProvider() *NameProvider { return jsonname.NewNameProvider() }
|
||||
+202
@@ -0,0 +1,202 @@
|
||||
|
||||
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.
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
# jsonutils
|
||||
|
||||
`jsonutils` exposes a few tools to work with JSON:
|
||||
|
||||
- a fast, simple `Concat` to concatenate (not merge) JSON objects and arrays
|
||||
- `FromDynamicJSON` to convert a data structure into a "dynamic JSON" data structure
|
||||
- `ReadJSON` and `WriteJSON` behave like `json.Unmarshal` and `json.Marshal`,
|
||||
with the ability to use another underlying serialization library through an `Adapter`
|
||||
configured at runtime
|
||||
- a `JSONMapSlice` structure that may be used to store JSON objects with the order of keys maintained
|
||||
|
||||
## Dynamic JSON
|
||||
|
||||
We call "dynamic JSON" the go data structure that results from unmarshaling JSON like this:
|
||||
|
||||
```go
|
||||
var value any
|
||||
jsonBytes := `{"a": 1, ... }`
|
||||
_ = json.Unmarshal(jsonBytes, &value)
|
||||
```
|
||||
|
||||
In this configuration, the standard library mappings are as follows:
|
||||
|
||||
| JSON | go |
|
||||
|-----------|------------------|
|
||||
| `number` | `float64` |
|
||||
| `string` | `string` |
|
||||
| `boolean` | `bool` |
|
||||
| `null` | `nil` |
|
||||
| `object` | `map[string]any` |
|
||||
| `array` | `[]any` |
|
||||
|
||||
## Map slices
|
||||
|
||||
When using `JSONMapSlice`, the ordering of keys is ensured by replacing
|
||||
mappings to `map[string]any` by a `JSONMapSlice` which is an (ordered)
|
||||
slice of `JSONMapItem`s.
|
||||
|
||||
Notice that a similar feature is available for YAML (see [`yamlutils`](../yamlutils)),
|
||||
with a `YAMLMapSlice` type based on the `JSONMapSlice`.
|
||||
|
||||
`JSONMapSlice` is similar to an ordered map, but the keys are not retrieved
|
||||
in constant time.
|
||||
|
||||
Another difference with the the above standard mappings is that numbers don't always map
|
||||
to a `float64`: if the value is a JSON integer, it unmarshals to `int64`.
|
||||
|
||||
See also [some examples](https://pkg.go.dev/github.com/go-openapi/swag/jsonutils#pkg-examples)
|
||||
|
||||
## Adapters
|
||||
|
||||
`ReadJSON`, `WriteJSON` and `FromDynamicJSON` (which is a combination of the latter two)
|
||||
are wrappers on top of `json.Unmarshal` and `json.Marshal`.
|
||||
|
||||
By default, the adapter merely wraps the standard library.
|
||||
|
||||
The adapter may be used to register other JSON serialization libraries,
|
||||
possibly several ones at the same time.
|
||||
|
||||
If the value passed is identified as an "ordered map" (i.e. implements `ifaces.Ordered`
|
||||
or `ifaces.SetOrdered`, the adapter favors the "ordered" JSON behavior and tries to
|
||||
find a registered implementation that support ordered keys in objects.
|
||||
|
||||
Our standard library implementation supports this.
|
||||
|
||||
As of `v0.25.0`, we support through such an adapter the popular `mailru/easyjson`
|
||||
library, which kicks in when the passed values support the `easyjson.Unmarshaler`
|
||||
or `easyjson.Marshaler` interfaces.
|
||||
|
||||
In the future, we plan to add more similar libraries that compete on the go JSON
|
||||
serializers scene.
|
||||
|
||||
## Registering an adapter
|
||||
|
||||
In package `github.com/go-openapi/swag/easyjson/adapters`, several adapters are available.
|
||||
|
||||
Each adapter is an independent go module. Hence you'll pick its dependencies only if you import it.
|
||||
|
||||
At this moment we provide:
|
||||
* `stdlib`: JSON adapter based on the standard library
|
||||
* `easyjson`: JSON adapter based on the `github.com/mailru/easyjson`
|
||||
|
||||
The adapters provide the basic `Marshal` and `Unmarshal` capabilities, plus an implementation
|
||||
of the `MapSlice` pattern.
|
||||
|
||||
You may also build your own adapter based on your specific use-case. An adapter is not required to implement
|
||||
all capabilities.
|
||||
|
||||
Every adapter comes with a `Register` function, possibly with some options, to register the adapter
|
||||
to a global registry.
|
||||
|
||||
For example, to enable `easyjson` to be used in `ReadJSON` and `WriteJSON`, you would write something like:
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/go-openapi/swag/jsonutils/adapters"
|
||||
easyjson "github.com/go-openapi/swag/jsonutils/adapters/easyjson/json"
|
||||
)
|
||||
|
||||
func init() {
|
||||
easyjson.Register(adapters.Registry)
|
||||
}
|
||||
```
|
||||
|
||||
You may register several adapters. In this case, capability matching is evaluated from the last registered
|
||||
adapters (LIFO).
|
||||
|
||||
## [Benchmarks](./adapters/testintegration/benchmarks/README.md)
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Package adapters exposes a registry of adapters to multiple
|
||||
// JSON serialization libraries.
|
||||
//
|
||||
// All interfaces are defined in package [ifaces.Adapter].
|
||||
package adapters
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Package ifaces exposes all interfaces to work with adapters.
|
||||
package ifaces
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package ifaces
|
||||
|
||||
import (
|
||||
_ "encoding/json" // for documentation purpose
|
||||
"iter"
|
||||
)
|
||||
|
||||
// Ordered knows how to iterate over the (key,value) pairs of a JSON object.
|
||||
type Ordered interface {
|
||||
OrderedItems() iter.Seq2[string, any]
|
||||
}
|
||||
|
||||
// SetOrdered knows how to append or update the keys of a JSON object,
|
||||
// given an iterator over (key,value) pairs.
|
||||
//
|
||||
// If the provided iterator is nil then the receiver should be set to nil.
|
||||
type SetOrdered interface {
|
||||
SetOrderedItems(iter.Seq2[string, any])
|
||||
}
|
||||
|
||||
// OrderedMap represent a JSON object (i.e. like a map[string,any]),
|
||||
// and knows how to serialize and deserialize JSON with the order of keys maintained.
|
||||
type OrderedMap interface {
|
||||
Ordered
|
||||
SetOrdered
|
||||
|
||||
OrderedMarshalJSON() ([]byte, error)
|
||||
OrderedUnmarshalJSON([]byte) error
|
||||
}
|
||||
|
||||
// MarshalAdapter behaves likes the standard library [json.Marshal].
|
||||
type MarshalAdapter interface {
|
||||
Poolable
|
||||
|
||||
Marshal(any) ([]byte, error)
|
||||
}
|
||||
|
||||
// OrderedMarshalAdapter behaves likes the standard library [json.Marshal], preserving the order of keys in objects.
|
||||
type OrderedMarshalAdapter interface {
|
||||
Poolable
|
||||
|
||||
OrderedMarshal(Ordered) ([]byte, error)
|
||||
}
|
||||
|
||||
// UnmarshalAdapter behaves likes the standard library [json.Unmarshal].
|
||||
type UnmarshalAdapter interface {
|
||||
Poolable
|
||||
|
||||
Unmarshal([]byte, any) error
|
||||
}
|
||||
|
||||
// OrderedUnmarshalAdapter behaves likes the standard library [json.Unmarshal], preserving the order of keys in objects.
|
||||
type OrderedUnmarshalAdapter interface {
|
||||
Poolable
|
||||
|
||||
OrderedUnmarshal([]byte, SetOrdered) error
|
||||
}
|
||||
|
||||
// Adapter exposes an interface like the standard [json] library.
|
||||
type Adapter interface {
|
||||
MarshalAdapter
|
||||
UnmarshalAdapter
|
||||
|
||||
OrderedAdapter
|
||||
}
|
||||
|
||||
// OrderedAdapter exposes interfaces to process JSON and keep the order of object keys.
|
||||
type OrderedAdapter interface {
|
||||
OrderedMarshalAdapter
|
||||
OrderedUnmarshalAdapter
|
||||
NewOrderedMap(capacity int) OrderedMap
|
||||
}
|
||||
|
||||
type Poolable interface {
|
||||
// Self-redeem: for [Adapter] s that are allocated from a pool.
|
||||
// The [Adapter] must not be used after calling [Redeem].
|
||||
Redeem()
|
||||
|
||||
// Reset the state of the [Adapter], if any.
|
||||
Reset()
|
||||
}
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package ifaces
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Capability indicates what a JSON adapter is capable of.
|
||||
type Capability uint8
|
||||
|
||||
const (
|
||||
CapabilityMarshalJSON Capability = 1 << iota
|
||||
CapabilityUnmarshalJSON
|
||||
CapabilityOrderedMarshalJSON
|
||||
CapabilityOrderedUnmarshalJSON
|
||||
CapabilityOrderedMap
|
||||
)
|
||||
|
||||
func (c Capability) String() string {
|
||||
switch c {
|
||||
case CapabilityMarshalJSON:
|
||||
return "MarshalJSON"
|
||||
case CapabilityUnmarshalJSON:
|
||||
return "UnmarshalJSON"
|
||||
case CapabilityOrderedMarshalJSON:
|
||||
return "OrderedMarshalJSON"
|
||||
case CapabilityOrderedUnmarshalJSON:
|
||||
return "OrderedUnmarshalJSON"
|
||||
case CapabilityOrderedMap:
|
||||
return "OrderedMap"
|
||||
default:
|
||||
return "<unknown>"
|
||||
}
|
||||
}
|
||||
|
||||
// Capabilities holds several unitary capability flags
|
||||
type Capabilities uint8
|
||||
|
||||
// Has some capability flag enabled.
|
||||
func (c Capabilities) Has(capability Capability) bool {
|
||||
return Capability(c)&capability > 0
|
||||
}
|
||||
|
||||
func (c Capabilities) String() string {
|
||||
var w strings.Builder
|
||||
|
||||
first := true
|
||||
for _, capability := range []Capability{
|
||||
CapabilityMarshalJSON,
|
||||
CapabilityUnmarshalJSON,
|
||||
CapabilityOrderedMarshalJSON,
|
||||
CapabilityOrderedUnmarshalJSON,
|
||||
CapabilityOrderedMap,
|
||||
} {
|
||||
if c.Has(capability) {
|
||||
if !first {
|
||||
w.WriteByte('|')
|
||||
} else {
|
||||
first = false
|
||||
}
|
||||
w.WriteString(capability.String())
|
||||
}
|
||||
}
|
||||
|
||||
return w.String()
|
||||
}
|
||||
|
||||
const (
|
||||
AllCapabilities Capabilities = Capabilities(uint8(CapabilityMarshalJSON) |
|
||||
uint8(CapabilityUnmarshalJSON) |
|
||||
uint8(CapabilityOrderedMarshalJSON) |
|
||||
uint8(CapabilityOrderedUnmarshalJSON) |
|
||||
uint8(CapabilityOrderedMap))
|
||||
|
||||
AllUnorderedCapabilities Capabilities = Capabilities(uint8(CapabilityMarshalJSON) | uint8(CapabilityUnmarshalJSON))
|
||||
)
|
||||
|
||||
// RegistryEntry describes how any given adapter registers its capabilities to the [Registrar].
|
||||
type RegistryEntry struct {
|
||||
Who string
|
||||
What Capabilities
|
||||
Constructor func() Adapter
|
||||
Support func(what Capability, value any) bool
|
||||
}
|
||||
|
||||
// Registrar is a type that knows how to keep registration calls from adapters.
|
||||
type Registrar interface {
|
||||
RegisterFor(RegistryEntry)
|
||||
}
|
||||
+229
@@ -0,0 +1,229 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package adapters
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"slices"
|
||||
"sync"
|
||||
|
||||
"github.com/go-openapi/swag/jsonutils/adapters/ifaces"
|
||||
stdlib "github.com/go-openapi/swag/jsonutils/adapters/stdlib/json"
|
||||
)
|
||||
|
||||
// Registry holds the global registry for registered adapters.
|
||||
var Registry = NewRegistrar()
|
||||
|
||||
var (
|
||||
defaultRegistered = stdlib.Register
|
||||
|
||||
_ ifaces.Registrar = &Registrar{}
|
||||
)
|
||||
|
||||
type registryError string
|
||||
|
||||
func (e registryError) Error() string {
|
||||
return string(e)
|
||||
}
|
||||
|
||||
// ErrRegistry indicates an error returned by the [Registrar].
|
||||
var ErrRegistry registryError = "JSON adapters registry error"
|
||||
|
||||
type registry []*ifaces.RegistryEntry
|
||||
|
||||
// Registrar holds registered [ifaces.Adapters] for different serialization capabilities.
|
||||
//
|
||||
// Internally, it maintains a cache for data types that favor a given adapter.
|
||||
type Registrar struct {
|
||||
marshalerRegistry registry
|
||||
unmarshalerRegistry registry
|
||||
orderedMarshalerRegistry registry
|
||||
orderedUnmarshalerRegistry registry
|
||||
orderedMapRegistry registry
|
||||
|
||||
gmx sync.RWMutex
|
||||
|
||||
// cache indexed by value type, so we don't have to lookup
|
||||
marshalerCache map[reflect.Type]*ifaces.RegistryEntry
|
||||
unmarshalerCache map[reflect.Type]*ifaces.RegistryEntry
|
||||
orderedMarshalerCache map[reflect.Type]*ifaces.RegistryEntry
|
||||
orderedUnmarshalerCache map[reflect.Type]*ifaces.RegistryEntry
|
||||
orderedMapCache map[reflect.Type]*ifaces.RegistryEntry
|
||||
}
|
||||
|
||||
func NewRegistrar() *Registrar {
|
||||
r := &Registrar{}
|
||||
|
||||
r.marshalerRegistry = make(registry, 0, 1)
|
||||
r.unmarshalerRegistry = make(registry, 0, 1)
|
||||
r.orderedMarshalerRegistry = make(registry, 0, 1)
|
||||
r.orderedUnmarshalerRegistry = make(registry, 0, 1)
|
||||
r.orderedMapRegistry = make(registry, 0, 1)
|
||||
|
||||
r.marshalerCache = make(map[reflect.Type]*ifaces.RegistryEntry)
|
||||
r.unmarshalerCache = make(map[reflect.Type]*ifaces.RegistryEntry)
|
||||
r.orderedMarshalerCache = make(map[reflect.Type]*ifaces.RegistryEntry)
|
||||
r.orderedUnmarshalerCache = make(map[reflect.Type]*ifaces.RegistryEntry)
|
||||
r.orderedMapCache = make(map[reflect.Type]*ifaces.RegistryEntry)
|
||||
|
||||
defaultRegistered(r)
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
// ClearCache resets the internal type cache.
|
||||
func (r *Registrar) ClearCache() {
|
||||
r.gmx.Lock()
|
||||
r.clearCache()
|
||||
r.gmx.Unlock()
|
||||
}
|
||||
|
||||
// Reset the [Registrar] to its defaults.
|
||||
func (r *Registrar) Reset() {
|
||||
r.gmx.Lock()
|
||||
r.clearCache()
|
||||
r.marshalerRegistry = r.marshalerRegistry[:0]
|
||||
r.unmarshalerRegistry = r.unmarshalerRegistry[:0]
|
||||
r.orderedMarshalerRegistry = r.orderedMarshalerRegistry[:0]
|
||||
r.orderedUnmarshalerRegistry = r.orderedUnmarshalerRegistry[:0]
|
||||
r.orderedMapRegistry = r.orderedMapRegistry[:0]
|
||||
r.gmx.Unlock()
|
||||
|
||||
defaultRegistered(r)
|
||||
}
|
||||
|
||||
// RegisterFor registers an adapter for some JSON capabilities.
|
||||
func (r *Registrar) RegisterFor(entry ifaces.RegistryEntry) {
|
||||
r.gmx.Lock()
|
||||
if entry.What.Has(ifaces.CapabilityMarshalJSON) {
|
||||
e := entry
|
||||
e.What &= ifaces.Capabilities(ifaces.CapabilityMarshalJSON)
|
||||
r.marshalerRegistry = slices.Insert(r.marshalerRegistry, 0, &e)
|
||||
}
|
||||
if entry.What.Has(ifaces.CapabilityUnmarshalJSON) {
|
||||
e := entry
|
||||
e.What &= ifaces.Capabilities(ifaces.CapabilityUnmarshalJSON)
|
||||
r.unmarshalerRegistry = slices.Insert(r.unmarshalerRegistry, 0, &e)
|
||||
}
|
||||
if entry.What.Has(ifaces.CapabilityOrderedMarshalJSON) {
|
||||
e := entry
|
||||
e.What &= ifaces.Capabilities(ifaces.CapabilityOrderedMarshalJSON)
|
||||
r.orderedMarshalerRegistry = slices.Insert(r.orderedMarshalerRegistry, 0, &e)
|
||||
}
|
||||
if entry.What.Has(ifaces.CapabilityOrderedUnmarshalJSON) {
|
||||
e := entry
|
||||
e.What &= ifaces.Capabilities(ifaces.CapabilityOrderedUnmarshalJSON)
|
||||
r.orderedUnmarshalerRegistry = slices.Insert(r.orderedUnmarshalerRegistry, 0, &e)
|
||||
}
|
||||
if entry.What.Has(ifaces.CapabilityOrderedMap) {
|
||||
e := entry
|
||||
e.What &= ifaces.Capabilities(ifaces.CapabilityOrderedMap)
|
||||
r.orderedMapRegistry = slices.Insert(r.orderedMapRegistry, 0, &e)
|
||||
}
|
||||
r.gmx.Unlock()
|
||||
}
|
||||
|
||||
// AdapterFor returns an [ifaces.Adapter] that supports this capability for this type of value.
|
||||
//
|
||||
// The [ifaces.Adapter] may be redeemed to its pool using its Redeem() method, for adapters that support global
|
||||
// pooling. When this is not the case, the redeem function is just a no-operation.
|
||||
func (r *Registrar) AdapterFor(capability ifaces.Capability, value any) ifaces.Adapter {
|
||||
entry := r.findFirstFor(capability, value)
|
||||
if entry == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return entry.Constructor()
|
||||
}
|
||||
|
||||
func (r *Registrar) clearCache() {
|
||||
clear(r.marshalerCache)
|
||||
clear(r.unmarshalerCache)
|
||||
clear(r.orderedMarshalerCache)
|
||||
clear(r.orderedUnmarshalerCache)
|
||||
clear(r.orderedMapCache)
|
||||
}
|
||||
|
||||
func (r *Registrar) findFirstFor(capability ifaces.Capability, value any) *ifaces.RegistryEntry {
|
||||
switch capability {
|
||||
case ifaces.CapabilityMarshalJSON:
|
||||
return r.findFirstInRegistryFor(r.marshalerRegistry, r.marshalerCache, capability, value)
|
||||
case ifaces.CapabilityUnmarshalJSON:
|
||||
return r.findFirstInRegistryFor(r.unmarshalerRegistry, r.unmarshalerCache, capability, value)
|
||||
case ifaces.CapabilityOrderedMarshalJSON:
|
||||
return r.findFirstInRegistryFor(r.orderedMarshalerRegistry, r.orderedMarshalerCache, capability, value)
|
||||
case ifaces.CapabilityOrderedUnmarshalJSON:
|
||||
return r.findFirstInRegistryFor(r.orderedUnmarshalerRegistry, r.orderedUnmarshalerCache, capability, value)
|
||||
case ifaces.CapabilityOrderedMap:
|
||||
return r.findFirstInRegistryFor(r.orderedMapRegistry, r.orderedMapCache, capability, value)
|
||||
default:
|
||||
panic(fmt.Errorf("unsupported capability %d: %w", capability, ErrRegistry))
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Registrar) findFirstInRegistryFor(reg registry, cache map[reflect.Type]*ifaces.RegistryEntry, capability ifaces.Capability, value any) *ifaces.RegistryEntry {
|
||||
r.gmx.RLock()
|
||||
if len(reg) > 1 {
|
||||
if entry, ok := cache[reflect.TypeOf(value)]; ok {
|
||||
// cache hit
|
||||
r.gmx.RUnlock()
|
||||
return entry
|
||||
}
|
||||
}
|
||||
|
||||
for _, entry := range reg {
|
||||
if !entry.Support(capability, value) {
|
||||
continue
|
||||
}
|
||||
|
||||
r.gmx.RUnlock()
|
||||
|
||||
// update the internal cache
|
||||
r.gmx.Lock()
|
||||
cache[reflect.TypeOf(value)] = entry
|
||||
r.gmx.Unlock()
|
||||
|
||||
return entry
|
||||
}
|
||||
|
||||
// no adapter found
|
||||
r.gmx.RUnlock()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalAdapterFor returns the first adapter that knows how to Marshal this type of value.
|
||||
func MarshalAdapterFor(value any) ifaces.MarshalAdapter {
|
||||
return Registry.AdapterFor(ifaces.CapabilityMarshalJSON, value)
|
||||
}
|
||||
|
||||
// OrderedMarshalAdapterFor returns the first adapter that knows how to OrderedMarshal this type of value.
|
||||
func OrderedMarshalAdapterFor(value ifaces.Ordered) ifaces.OrderedMarshalAdapter {
|
||||
return Registry.AdapterFor(ifaces.CapabilityOrderedMarshalJSON, value)
|
||||
}
|
||||
|
||||
// UnmarshalAdapterFor returns the first adapter that knows how to Unmarshal this type of value.
|
||||
func UnmarshalAdapterFor(value any) ifaces.UnmarshalAdapter {
|
||||
return Registry.AdapterFor(ifaces.CapabilityUnmarshalJSON, value)
|
||||
}
|
||||
|
||||
// OrderedUnmarshalAdapterFor provides the first adapter that knows how to OrderedUnmarshal this type of value.
|
||||
func OrderedUnmarshalAdapterFor(value ifaces.SetOrdered) ifaces.OrderedUnmarshalAdapter {
|
||||
return Registry.AdapterFor(ifaces.CapabilityOrderedUnmarshalJSON, value)
|
||||
}
|
||||
|
||||
// NewOrderedMap provides the "ordered map" implementation provided by the registry.
|
||||
func NewOrderedMap(capacity int) ifaces.OrderedMap {
|
||||
var v any
|
||||
adapter := Registry.AdapterFor(ifaces.CapabilityOrderedUnmarshalJSON, v)
|
||||
if adapter == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
defer adapter.Redeem()
|
||||
return adapter.NewOrderedMap(capacity)
|
||||
}
|
||||
|
||||
func noopRedeemer() {}
|
||||
+115
@@ -0,0 +1,115 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package json
|
||||
|
||||
import (
|
||||
stdjson "encoding/json"
|
||||
|
||||
"github.com/go-openapi/swag/jsonutils/adapters/ifaces"
|
||||
"github.com/go-openapi/swag/typeutils"
|
||||
)
|
||||
|
||||
const sensibleBufferSize = 8192
|
||||
|
||||
type jsonError string
|
||||
|
||||
func (e jsonError) Error() string {
|
||||
return string(e)
|
||||
}
|
||||
|
||||
// ErrStdlib indicates that an error comes from the stdlib JSON adapter
|
||||
var ErrStdlib jsonError = "error from the JSON adapter stdlib"
|
||||
|
||||
var _ ifaces.Adapter = &Adapter{}
|
||||
|
||||
type Adapter struct {
|
||||
}
|
||||
|
||||
// NewAdapter yields an [ifaces.Adapter] using the standard library.
|
||||
func NewAdapter() *Adapter {
|
||||
return &Adapter{}
|
||||
}
|
||||
|
||||
func (a *Adapter) Marshal(value any) ([]byte, error) {
|
||||
return stdjson.Marshal(value)
|
||||
}
|
||||
|
||||
func (a *Adapter) Unmarshal(data []byte, value any) error {
|
||||
return stdjson.Unmarshal(data, value)
|
||||
}
|
||||
|
||||
func (a *Adapter) OrderedMarshal(value ifaces.Ordered) ([]byte, error) {
|
||||
w := poolOfWriters.Borrow()
|
||||
defer func() {
|
||||
poolOfWriters.Redeem(w)
|
||||
}()
|
||||
|
||||
if typeutils.IsNil(value) {
|
||||
w.RawString("null")
|
||||
|
||||
return w.BuildBytes()
|
||||
}
|
||||
|
||||
w.RawByte('{')
|
||||
first := true
|
||||
for k, v := range value.OrderedItems() {
|
||||
if first {
|
||||
first = false
|
||||
} else {
|
||||
w.RawByte(',')
|
||||
}
|
||||
|
||||
w.String(k)
|
||||
w.RawByte(':')
|
||||
|
||||
switch val := v.(type) {
|
||||
case ifaces.Ordered:
|
||||
w.Raw(a.OrderedMarshal(val))
|
||||
default:
|
||||
w.Raw(stdjson.Marshal(v))
|
||||
}
|
||||
}
|
||||
|
||||
w.RawByte('}')
|
||||
|
||||
return w.BuildBytes()
|
||||
}
|
||||
|
||||
func (a *Adapter) OrderedUnmarshal(data []byte, value ifaces.SetOrdered) error {
|
||||
var m MapSlice
|
||||
if err := m.OrderedUnmarshalJSON(data); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if typeutils.IsNil(m) {
|
||||
// force input value to nil
|
||||
value.SetOrderedItems(nil)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
value.SetOrderedItems(m.OrderedItems())
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *Adapter) NewOrderedMap(capacity int) ifaces.OrderedMap {
|
||||
m := make(MapSlice, 0, capacity)
|
||||
|
||||
return &m
|
||||
}
|
||||
|
||||
// Redeem the [Adapter] when it comes from a pool.
|
||||
//
|
||||
// The adapter becomes immediately unusable once redeemed.
|
||||
func (a *Adapter) Redeem() {
|
||||
if a == nil {
|
||||
return
|
||||
}
|
||||
|
||||
RedeemAdapter(a)
|
||||
}
|
||||
|
||||
func (a *Adapter) Reset() {
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Package json implements an [ifaces.Adapter] using the standard library.
|
||||
package json
|
||||
+320
@@ -0,0 +1,320 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package json
|
||||
|
||||
import (
|
||||
stdjson "encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"strconv"
|
||||
|
||||
"github.com/go-openapi/swag/conv"
|
||||
)
|
||||
|
||||
type token struct {
|
||||
stdjson.Token
|
||||
}
|
||||
|
||||
func (t token) String() string {
|
||||
if t == invalidToken {
|
||||
return "invalid token"
|
||||
}
|
||||
if t == eofToken {
|
||||
return "EOF"
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%v", t.Token)
|
||||
}
|
||||
|
||||
func (t token) Kind() tokenKind {
|
||||
switch t.Token.(type) {
|
||||
case nil:
|
||||
return tokenNull
|
||||
case stdjson.Delim:
|
||||
return tokenDelim
|
||||
case bool:
|
||||
return tokenBool
|
||||
case float64:
|
||||
return tokenFloat
|
||||
case stdjson.Number:
|
||||
return tokenNumber
|
||||
case string:
|
||||
return tokenString
|
||||
default:
|
||||
return tokenUndef
|
||||
}
|
||||
}
|
||||
|
||||
func (t token) Delim() byte {
|
||||
r, ok := t.Token.(stdjson.Delim)
|
||||
if !ok {
|
||||
return 0
|
||||
}
|
||||
|
||||
return byte(r)
|
||||
}
|
||||
|
||||
type tokenKind uint8
|
||||
|
||||
const (
|
||||
tokenUndef tokenKind = iota
|
||||
tokenString
|
||||
tokenNumber
|
||||
tokenFloat
|
||||
tokenBool
|
||||
tokenNull
|
||||
tokenDelim
|
||||
)
|
||||
|
||||
var (
|
||||
invalidToken = token{
|
||||
Token: stdjson.Token(struct{}{}),
|
||||
}
|
||||
|
||||
eofToken = token{
|
||||
Token: stdjson.Token(&struct{}{}),
|
||||
}
|
||||
|
||||
undefToken = token{
|
||||
Token: stdjson.Token(uint8(0)),
|
||||
}
|
||||
)
|
||||
|
||||
// jlexer apes easyjson's jlexer, but uses the standard library decoder under the hood.
|
||||
type jlexer struct {
|
||||
buf *bytesReader
|
||||
dec *stdjson.Decoder
|
||||
err error
|
||||
// current token
|
||||
next token
|
||||
// started bool
|
||||
}
|
||||
|
||||
type bytesReader struct {
|
||||
buf []byte
|
||||
offset int
|
||||
}
|
||||
|
||||
func (b *bytesReader) Reset() {
|
||||
b.buf = nil
|
||||
b.offset = 0
|
||||
}
|
||||
|
||||
func (b *bytesReader) Read(p []byte) (int, error) {
|
||||
if b.offset >= len(b.buf) {
|
||||
return 0, io.EOF
|
||||
}
|
||||
|
||||
n := len(p)
|
||||
buf := b.buf[b.offset:]
|
||||
m := len(buf)
|
||||
|
||||
if n >= m {
|
||||
copy(p, buf)
|
||||
b.offset += m
|
||||
|
||||
return m, nil
|
||||
}
|
||||
|
||||
copy(p, buf[:n])
|
||||
b.offset += n
|
||||
|
||||
return n, nil
|
||||
}
|
||||
|
||||
var _ io.Reader = &bytesReader{}
|
||||
|
||||
func newLexer(data []byte) *jlexer {
|
||||
l := &jlexer{
|
||||
// current: undefToken,
|
||||
next: undefToken,
|
||||
}
|
||||
l.buf = &bytesReader{
|
||||
buf: data,
|
||||
}
|
||||
l.dec = stdjson.NewDecoder(l.buf) // unfortunately, cannot pool this
|
||||
|
||||
return l
|
||||
}
|
||||
|
||||
func (l *jlexer) Reset() {
|
||||
l.err = nil
|
||||
l.next = undefToken
|
||||
// leave l.dec and l.buf alone, since they are replaced at every Borrow
|
||||
}
|
||||
|
||||
func (l *jlexer) Error() error {
|
||||
return l.err
|
||||
}
|
||||
|
||||
func (l *jlexer) SetErr(err error) {
|
||||
l.err = err
|
||||
}
|
||||
|
||||
func (l *jlexer) Ok() bool {
|
||||
return l.err == nil
|
||||
}
|
||||
|
||||
// NextToken consumes a token
|
||||
func (l *jlexer) NextToken() token {
|
||||
if !l.Ok() {
|
||||
return invalidToken
|
||||
}
|
||||
|
||||
if l.next != undefToken {
|
||||
next := l.next
|
||||
l.next = undefToken
|
||||
|
||||
return next
|
||||
}
|
||||
|
||||
return l.fetchToken()
|
||||
}
|
||||
|
||||
// PeekToken returns the next token without consuming it
|
||||
func (l *jlexer) PeekToken() token {
|
||||
if l.next == undefToken {
|
||||
l.next = l.fetchToken()
|
||||
}
|
||||
|
||||
return l.next
|
||||
}
|
||||
|
||||
func (l *jlexer) Skip() {
|
||||
_ = l.NextToken()
|
||||
}
|
||||
|
||||
func (l *jlexer) IsDelim(c byte) bool {
|
||||
if !l.Ok() {
|
||||
return false
|
||||
}
|
||||
|
||||
next := l.PeekToken()
|
||||
if next.Kind() != tokenDelim {
|
||||
return false
|
||||
}
|
||||
|
||||
if next.Delim() != c {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (l *jlexer) IsNull() bool {
|
||||
if !l.Ok() {
|
||||
return false
|
||||
}
|
||||
|
||||
next := l.PeekToken()
|
||||
|
||||
return next.Kind() == tokenNull
|
||||
}
|
||||
|
||||
func (l *jlexer) Delim(c byte) {
|
||||
if !l.Ok() {
|
||||
return
|
||||
}
|
||||
|
||||
tok := l.NextToken()
|
||||
if tok.Kind() != tokenDelim {
|
||||
l.err = fmt.Errorf("expected a delimiter token but got '%v': %w", tok, ErrStdlib)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if tok.Delim() != c {
|
||||
l.err = fmt.Errorf("expected delimiter '%q' but got '%q': %w", c, tok.Delim(), ErrStdlib)
|
||||
}
|
||||
}
|
||||
|
||||
func (l *jlexer) Null() {
|
||||
if !l.Ok() {
|
||||
return
|
||||
}
|
||||
|
||||
tok := l.NextToken()
|
||||
if tok.Kind() != tokenNull {
|
||||
l.err = fmt.Errorf("expected a null token but got '%v': %w", tok, ErrStdlib)
|
||||
}
|
||||
}
|
||||
|
||||
func (l *jlexer) Number() any {
|
||||
if !l.Ok() {
|
||||
return 0
|
||||
}
|
||||
|
||||
tok := l.NextToken()
|
||||
|
||||
switch tok.Kind() { //nolint:exhaustive
|
||||
case tokenNumber:
|
||||
n := tok.Token.(stdjson.Number).String()
|
||||
f, _ := strconv.ParseFloat(n, 64)
|
||||
if conv.IsFloat64AJSONInteger(f) {
|
||||
return int64(math.Trunc(f))
|
||||
}
|
||||
|
||||
return f
|
||||
|
||||
case tokenFloat:
|
||||
f := tok.Token.(float64)
|
||||
if conv.IsFloat64AJSONInteger(f) {
|
||||
return int64(math.Trunc(f))
|
||||
}
|
||||
|
||||
return f
|
||||
|
||||
default:
|
||||
l.err = fmt.Errorf("expected a number token but got '%v': %w", tok, ErrStdlib)
|
||||
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
func (l *jlexer) Bool() bool {
|
||||
if !l.Ok() {
|
||||
return false
|
||||
}
|
||||
|
||||
tok := l.NextToken()
|
||||
if tok.Kind() != tokenBool {
|
||||
l.err = fmt.Errorf("expected a bool token but got '%v': %w", tok, ErrStdlib)
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
return tok.Token.(bool)
|
||||
}
|
||||
|
||||
func (l *jlexer) String() string {
|
||||
if !l.Ok() {
|
||||
return ""
|
||||
}
|
||||
|
||||
tok := l.NextToken()
|
||||
if tok.Kind() != tokenString {
|
||||
l.err = fmt.Errorf("expected a string token but got '%v': %w", tok, ErrStdlib)
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
return tok.Token.(string)
|
||||
}
|
||||
|
||||
// Commas and colons are elided.
|
||||
func (l *jlexer) fetchToken() token {
|
||||
jtok, err := l.dec.Token()
|
||||
if err != nil {
|
||||
if errors.Is(err, io.EOF) {
|
||||
return eofToken
|
||||
}
|
||||
|
||||
l.err = errors.Join(err, ErrStdlib)
|
||||
return invalidToken
|
||||
}
|
||||
|
||||
return token{Token: jtok}
|
||||
}
|
||||
+266
@@ -0,0 +1,266 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package json
|
||||
|
||||
import (
|
||||
stdjson "encoding/json"
|
||||
"fmt"
|
||||
"iter"
|
||||
|
||||
"github.com/go-openapi/swag/jsonutils/adapters/ifaces"
|
||||
)
|
||||
|
||||
var _ ifaces.OrderedMap = &MapSlice{}
|
||||
|
||||
// MapSlice represents a JSON object, with the order of keys maintained.
|
||||
type MapSlice []MapItem
|
||||
|
||||
func (s MapSlice) OrderedItems() iter.Seq2[string, any] {
|
||||
return func(yield func(string, any) bool) {
|
||||
for _, item := range s {
|
||||
if !yield(item.Key, item.Value) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *MapSlice) SetOrderedItems(items iter.Seq2[string, any]) {
|
||||
if items == nil {
|
||||
*s = nil
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
m := *s
|
||||
if len(m) > 0 {
|
||||
// update mode
|
||||
idx := make(map[string]int, len(m))
|
||||
|
||||
for i, item := range m {
|
||||
idx[item.Key] = i
|
||||
}
|
||||
|
||||
for k, v := range items {
|
||||
idx, ok := idx[k]
|
||||
if ok {
|
||||
m[idx].Value = v
|
||||
|
||||
continue
|
||||
}
|
||||
m = append(m, MapItem{Key: k, Value: v})
|
||||
}
|
||||
|
||||
*s = m
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
for k, v := range items {
|
||||
m = append(m, MapItem{Key: k, Value: v})
|
||||
}
|
||||
|
||||
*s = m
|
||||
}
|
||||
|
||||
// MarshalJSON renders a [MapSlice] as JSON bytes, preserving the order of keys.
|
||||
func (s MapSlice) MarshalJSON() ([]byte, error) {
|
||||
return s.OrderedMarshalJSON()
|
||||
}
|
||||
|
||||
func (s MapSlice) OrderedMarshalJSON() ([]byte, error) {
|
||||
w := poolOfWriters.Borrow()
|
||||
defer func() {
|
||||
poolOfWriters.Redeem(w)
|
||||
}()
|
||||
|
||||
s.marshalObject(w)
|
||||
|
||||
return w.BuildBytes() // this clones data, so it's okay to redeem the writer and its buffer
|
||||
}
|
||||
|
||||
// UnmarshalJSON builds a [MapSlice] from JSON bytes, preserving the order of keys.
|
||||
//
|
||||
// Inner objects are unmarshaled as [MapSlice] slices and not map[string]any.
|
||||
func (s *MapSlice) UnmarshalJSON(data []byte) error {
|
||||
return s.OrderedUnmarshalJSON(data)
|
||||
}
|
||||
|
||||
func (s *MapSlice) OrderedUnmarshalJSON(data []byte) error {
|
||||
l := poolOfLexers.Borrow(data)
|
||||
defer func() {
|
||||
poolOfLexers.Redeem(l)
|
||||
}()
|
||||
|
||||
s.unmarshalObject(l)
|
||||
|
||||
return l.Error()
|
||||
}
|
||||
|
||||
func (s MapSlice) marshalObject(w *jwriter) {
|
||||
if s == nil {
|
||||
w.RawString("null")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
w.RawByte('{')
|
||||
|
||||
if len(s) == 0 {
|
||||
w.RawByte('}')
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
s[0].marshalJSON(w)
|
||||
|
||||
for i := 1; i < len(s); i++ {
|
||||
w.RawByte(',')
|
||||
s[i].marshalJSON(w)
|
||||
}
|
||||
|
||||
w.RawByte('}')
|
||||
}
|
||||
|
||||
func (s *MapSlice) unmarshalObject(in *jlexer) {
|
||||
if in.IsNull() {
|
||||
in.Skip()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
in.Delim('{') // consume token
|
||||
if !in.Ok() {
|
||||
return
|
||||
}
|
||||
|
||||
result := make(MapSlice, 0)
|
||||
|
||||
for in.Ok() && !in.IsDelim('}') {
|
||||
var mi MapItem
|
||||
|
||||
mi.unmarshalKeyValue(in)
|
||||
result = append(result, mi)
|
||||
}
|
||||
|
||||
in.Delim('}')
|
||||
|
||||
if !in.Ok() {
|
||||
return
|
||||
}
|
||||
|
||||
*s = result
|
||||
}
|
||||
|
||||
// MapItem represents the value of a key in a JSON object held by [MapSlice].
|
||||
//
|
||||
// Notice that [MapItem] should not be marshaled to or unmarshaled from JSON directly,
|
||||
// use this type as part of a [MapSlice] when dealing with JSON bytes.
|
||||
type MapItem struct {
|
||||
Key string
|
||||
Value any
|
||||
}
|
||||
|
||||
func (s MapItem) marshalJSON(w *jwriter) {
|
||||
w.String(s.Key)
|
||||
w.RawByte(':')
|
||||
w.Raw(stdjson.Marshal(s.Value))
|
||||
}
|
||||
|
||||
func (s *MapItem) unmarshalKeyValue(in *jlexer) {
|
||||
key := in.String() // consume string
|
||||
value := s.asInterface(in) // consume any value, including termination tokens '}' or ']'
|
||||
|
||||
if !in.Ok() {
|
||||
return
|
||||
}
|
||||
|
||||
s.Key = key
|
||||
s.Value = value
|
||||
}
|
||||
|
||||
func (s *MapItem) unmarshalArray(in *jlexer) []any {
|
||||
if in.IsNull() {
|
||||
in.Skip()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
in.Delim('[') // consume token
|
||||
if !in.Ok() {
|
||||
return nil
|
||||
}
|
||||
|
||||
ret := make([]any, 0)
|
||||
|
||||
for in.Ok() && !in.IsDelim(']') {
|
||||
ret = append(ret, s.asInterface(in))
|
||||
}
|
||||
|
||||
in.Delim(']')
|
||||
if !in.Ok() {
|
||||
return nil
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// asInterface is very much like [jlexer.Lexer.Interface], but unmarshals an object
|
||||
// into a [MapSlice], not a map[string]any.
|
||||
//
|
||||
// We have to force parsing errors somehow, since [jlexer.Lexer] doesn't let us
|
||||
// set a parsing error directly.
|
||||
func (s *MapItem) asInterface(in *jlexer) any {
|
||||
if !in.Ok() {
|
||||
return nil
|
||||
}
|
||||
|
||||
tok := in.PeekToken() // look-ahead what the next token looks like
|
||||
kind := tok.Kind()
|
||||
|
||||
switch kind {
|
||||
case tokenString:
|
||||
return in.String() // consume string
|
||||
|
||||
case tokenNumber, tokenFloat:
|
||||
return in.Number()
|
||||
|
||||
case tokenBool:
|
||||
return in.Bool()
|
||||
|
||||
case tokenNull:
|
||||
in.Null()
|
||||
|
||||
return nil
|
||||
|
||||
case tokenDelim:
|
||||
switch tok.Delim() {
|
||||
case '{': // not consumed yet
|
||||
ret := make(MapSlice, 0)
|
||||
ret.unmarshalObject(in) // consumes the terminating '}'
|
||||
|
||||
if in.Ok() {
|
||||
return ret
|
||||
}
|
||||
|
||||
// lexer is in an error state: will exhaust
|
||||
return nil
|
||||
|
||||
case '[': // not consumed yet
|
||||
return s.unmarshalArray(in) // consumes the terminating ']'
|
||||
default:
|
||||
in.SetErr(fmt.Errorf("unexpected delimiter: %v: %w", tok, ErrStdlib)) // force error
|
||||
return nil
|
||||
}
|
||||
|
||||
case tokenUndef:
|
||||
fallthrough
|
||||
default:
|
||||
if in.Ok() {
|
||||
in.SetErr(fmt.Errorf("unexpected token: %v: %w", tok, ErrStdlib)) // force error
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
+143
@@ -0,0 +1,143 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package json
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"sync"
|
||||
|
||||
"github.com/go-openapi/swag/jsonutils/adapters/ifaces"
|
||||
)
|
||||
|
||||
type adaptersPool struct {
|
||||
sync.Pool
|
||||
}
|
||||
|
||||
func (p *adaptersPool) Borrow() *Adapter {
|
||||
return p.Get().(*Adapter)
|
||||
}
|
||||
|
||||
func (p *adaptersPool) BorrowIface() ifaces.Adapter {
|
||||
return p.Get().(*Adapter)
|
||||
}
|
||||
|
||||
func (p *adaptersPool) Redeem(a *Adapter) {
|
||||
p.Put(a)
|
||||
}
|
||||
|
||||
type writersPool struct {
|
||||
sync.Pool
|
||||
}
|
||||
|
||||
func (p *writersPool) Borrow() *jwriter {
|
||||
ptr := p.Get()
|
||||
|
||||
jw := ptr.(*jwriter)
|
||||
jw.Reset()
|
||||
|
||||
return jw
|
||||
}
|
||||
|
||||
func (p *writersPool) Redeem(w *jwriter) {
|
||||
p.Put(w)
|
||||
}
|
||||
|
||||
type lexersPool struct {
|
||||
sync.Pool
|
||||
}
|
||||
|
||||
func (p *lexersPool) Borrow(data []byte) *jlexer {
|
||||
ptr := p.Get()
|
||||
|
||||
l := ptr.(*jlexer)
|
||||
l.buf = poolOfReaders.Borrow(data)
|
||||
l.dec = json.NewDecoder(l.buf) // cannot pool, not exposed by the encoding/json API
|
||||
l.Reset()
|
||||
|
||||
return l
|
||||
}
|
||||
|
||||
func (p *lexersPool) Redeem(l *jlexer) {
|
||||
l.dec = nil
|
||||
discard := l.buf
|
||||
l.buf = nil
|
||||
poolOfReaders.Redeem(discard)
|
||||
p.Put(l)
|
||||
}
|
||||
|
||||
type readersPool struct {
|
||||
sync.Pool
|
||||
}
|
||||
|
||||
func (p *readersPool) Borrow(data []byte) *bytesReader {
|
||||
ptr := p.Get()
|
||||
|
||||
b := ptr.(*bytesReader)
|
||||
b.Reset()
|
||||
b.buf = data
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
func (p *readersPool) Redeem(b *bytesReader) {
|
||||
p.Put(b)
|
||||
}
|
||||
|
||||
var (
|
||||
poolOfAdapters = &adaptersPool{
|
||||
Pool: sync.Pool{
|
||||
New: func() any {
|
||||
return NewAdapter()
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
poolOfWriters = &writersPool{
|
||||
Pool: sync.Pool{
|
||||
New: func() any {
|
||||
return newJWriter()
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
poolOfLexers = &lexersPool{
|
||||
Pool: sync.Pool{
|
||||
New: func() any {
|
||||
return newLexer(nil)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
poolOfReaders = &readersPool{
|
||||
Pool: sync.Pool{
|
||||
New: func() any {
|
||||
return &bytesReader{}
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
// BorrowAdapter borrows an [Adapter] from the pool, recycling already allocated instances.
|
||||
func BorrowAdapter() *Adapter {
|
||||
return poolOfAdapters.Borrow()
|
||||
}
|
||||
|
||||
// BorrowAdapterIface borrows a stdlib [Adapter] and converts it directly
|
||||
// to [ifaces.Adapter]. This is useful to avoid further allocations when
|
||||
// translating the concrete type into an interface.
|
||||
func BorrowAdapterIface() ifaces.Adapter {
|
||||
return poolOfAdapters.BorrowIface()
|
||||
}
|
||||
|
||||
// RedeemAdapter redeems an [Adapter] to the pool, so it may be recycled.
|
||||
func RedeemAdapter(a *Adapter) {
|
||||
poolOfAdapters.Redeem(a)
|
||||
}
|
||||
|
||||
func RedeemAdapterIface(a ifaces.Adapter) {
|
||||
concrete, ok := a.(*Adapter)
|
||||
if ok {
|
||||
poolOfAdapters.Redeem(concrete)
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package json
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/go-openapi/swag/jsonutils/adapters/ifaces"
|
||||
)
|
||||
|
||||
func Register(dispatcher ifaces.Registrar) {
|
||||
t := reflect.TypeOf(Adapter{})
|
||||
dispatcher.RegisterFor(
|
||||
ifaces.RegistryEntry{
|
||||
Who: fmt.Sprintf("%s.%s", t.PkgPath(), t.Name()),
|
||||
What: ifaces.AllCapabilities,
|
||||
Constructor: BorrowAdapterIface,
|
||||
Support: support,
|
||||
})
|
||||
}
|
||||
|
||||
func support(_ ifaces.Capability, _ any) bool {
|
||||
return true
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package json
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type jwriter struct {
|
||||
buf *bytes.Buffer
|
||||
err error
|
||||
}
|
||||
|
||||
func newJWriter() *jwriter {
|
||||
buf := make([]byte, 0, sensibleBufferSize)
|
||||
|
||||
return &jwriter{buf: bytes.NewBuffer(buf)}
|
||||
}
|
||||
|
||||
func (w *jwriter) Reset() {
|
||||
w.buf.Reset()
|
||||
w.err = nil
|
||||
}
|
||||
|
||||
func (w *jwriter) RawString(s string) {
|
||||
if w.err != nil {
|
||||
return
|
||||
}
|
||||
w.buf.WriteString(s)
|
||||
}
|
||||
|
||||
func (w *jwriter) Raw(b []byte, err error) {
|
||||
if w.err != nil {
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
w.err = err
|
||||
return
|
||||
}
|
||||
|
||||
_, _ = w.buf.Write(b)
|
||||
}
|
||||
|
||||
func (w *jwriter) RawByte(c byte) {
|
||||
if w.err != nil {
|
||||
return
|
||||
}
|
||||
w.buf.WriteByte(c)
|
||||
}
|
||||
|
||||
var quoteReplacer = strings.NewReplacer(`"`, `\"`, `\`, `\\`)
|
||||
|
||||
func (w *jwriter) String(s string) {
|
||||
if w.err != nil {
|
||||
return
|
||||
}
|
||||
// escape quotes and \
|
||||
s = quoteReplacer.Replace(s)
|
||||
|
||||
_ = w.buf.WriteByte('"')
|
||||
json.HTMLEscape(w.buf, []byte(s))
|
||||
_ = w.buf.WriteByte('"')
|
||||
}
|
||||
|
||||
// BuildBytes returns a clone of the internal buffer.
|
||||
func (w *jwriter) BuildBytes() ([]byte, error) {
|
||||
if w.err != nil {
|
||||
return nil, w.err
|
||||
}
|
||||
|
||||
return bytes.Clone(w.buf.Bytes()), nil
|
||||
}
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package jsonutils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
)
|
||||
|
||||
// nullJSON represents a JSON object with null type
|
||||
var nullJSON = []byte("null")
|
||||
|
||||
const comma = byte(',')
|
||||
|
||||
var closers map[byte]byte
|
||||
|
||||
func init() {
|
||||
closers = map[byte]byte{
|
||||
'{': '}',
|
||||
'[': ']',
|
||||
}
|
||||
}
|
||||
|
||||
// ConcatJSON concatenates multiple json objects or arrays efficiently.
|
||||
//
|
||||
// Note that [ConcatJSON] performs a very simple (and fast) concatenation
|
||||
// operation: it does not attempt to merge objects.
|
||||
func ConcatJSON(blobs ...[]byte) []byte {
|
||||
if len(blobs) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
last := len(blobs) - 1
|
||||
for blobs[last] == nil || bytes.Equal(blobs[last], nullJSON) {
|
||||
// strips trailing null objects
|
||||
last--
|
||||
if last < 0 {
|
||||
// there was nothing but "null"s or nil...
|
||||
return nil
|
||||
}
|
||||
}
|
||||
if last == 0 {
|
||||
return blobs[0]
|
||||
}
|
||||
|
||||
var opening, closing byte
|
||||
var idx, a int
|
||||
buf := bytes.NewBuffer(nil)
|
||||
|
||||
for i, b := range blobs[:last+1] {
|
||||
if b == nil || bytes.Equal(b, nullJSON) {
|
||||
// a null object is in the list: skip it
|
||||
continue
|
||||
}
|
||||
if len(b) > 0 && opening == 0 { // is this an array or an object?
|
||||
opening, closing = b[0], closers[b[0]]
|
||||
}
|
||||
|
||||
if opening != '{' && opening != '[' {
|
||||
continue // don't know how to concatenate non container objects
|
||||
}
|
||||
|
||||
const minLengthIfNotEmpty = 3
|
||||
if len(b) < minLengthIfNotEmpty { // yep empty but also the last one, so closing this thing
|
||||
if i == last && a > 0 {
|
||||
_ = buf.WriteByte(closing) // never returns err != nil
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
idx = 0
|
||||
if a > 0 { // we need to join with a comma for everything beyond the first non-empty item
|
||||
_ = buf.WriteByte(comma) // never returns err != nil
|
||||
idx = 1 // this is not the first or the last so we want to drop the leading bracket
|
||||
}
|
||||
|
||||
if i != last { // not the last one, strip brackets
|
||||
_, _ = buf.Write(b[idx : len(b)-1]) // never returns err != nil
|
||||
} else { // last one, strip only the leading bracket
|
||||
_, _ = buf.Write(b[idx:])
|
||||
}
|
||||
a++
|
||||
}
|
||||
|
||||
// somehow it ended up being empty, so provide a default value
|
||||
if buf.Len() == 0 && (opening == '{' || opening == '[') {
|
||||
_ = buf.WriteByte(opening) // never returns err != nil
|
||||
_ = buf.WriteByte(closing)
|
||||
}
|
||||
|
||||
return buf.Bytes()
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Package jsonutils provides helpers to work with JSON.
|
||||
//
|
||||
// These utilities work with dynamic go structures to and from JSON.
|
||||
package jsonutils
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package jsonutils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/go-openapi/swag/jsonutils/adapters"
|
||||
"github.com/go-openapi/swag/jsonutils/adapters/ifaces"
|
||||
)
|
||||
|
||||
// WriteJSON marshals a data structure as JSON.
|
||||
//
|
||||
// The difference with [json.Marshal] is that it may check among several alternatives
|
||||
// to do so.
|
||||
//
|
||||
// See [adapters.Registrar] for more details about how to configure
|
||||
// multiple serialization alternatives.
|
||||
//
|
||||
// NOTE: to allow types that are [easyjson.Marshaler] s to use that route to process JSON,
|
||||
// you now need to register the adapter for easyjson at runtime.
|
||||
func WriteJSON(value any) ([]byte, error) {
|
||||
if orderedMap, isOrdered := value.(ifaces.Ordered); isOrdered {
|
||||
orderedMarshaler := adapters.OrderedMarshalAdapterFor(orderedMap)
|
||||
|
||||
if orderedMarshaler != nil {
|
||||
defer orderedMarshaler.Redeem()
|
||||
|
||||
return orderedMarshaler.OrderedMarshal(orderedMap)
|
||||
}
|
||||
|
||||
// no support found in registered adapters, fallback to the default (unordered) case
|
||||
}
|
||||
|
||||
marshaler := adapters.MarshalAdapterFor(value)
|
||||
if marshaler != nil {
|
||||
defer marshaler.Redeem()
|
||||
|
||||
return marshaler.Marshal(value)
|
||||
}
|
||||
|
||||
// no support found in registered adapters, fallback to the default standard library.
|
||||
//
|
||||
// This only happens when tinkering with the global registry of adapters, since the default handles all the above cases.
|
||||
return json.Marshal(value) // Codecov ignore // this is a safeguard not easily simulated in tests
|
||||
}
|
||||
|
||||
// ReadJSON unmarshals JSON data into a data structure.
|
||||
//
|
||||
// The difference with [json.Unmarshal] is that it may check among several alternatives
|
||||
// to do so.
|
||||
//
|
||||
// See [adapters.Registrar] for more details about how to configure
|
||||
// multiple serialization alternatives.
|
||||
//
|
||||
// NOTE: value must be a pointer.
|
||||
//
|
||||
// If the provided value implements [ifaces.SetOrdered], it is a considered an "ordered map" and [ReadJSON]
|
||||
// will favor an adapter that supports the [ifaces.OrderedUnmarshal] feature, or fallback to
|
||||
// an unordered behavior if none is found.
|
||||
//
|
||||
// NOTE: to allow types that are [easyjson.Unmarshaler] s to use that route to process JSON,
|
||||
// you now need to register the adapter for easyjson at runtime.
|
||||
func ReadJSON(data []byte, value any) error {
|
||||
trimmedData := bytes.Trim(data, "\x00")
|
||||
|
||||
if orderedMap, isOrdered := value.(ifaces.SetOrdered); isOrdered {
|
||||
// if the value is an ordered map, favors support for OrderedUnmarshal.
|
||||
|
||||
orderedUnmarshaler := adapters.OrderedUnmarshalAdapterFor(orderedMap)
|
||||
|
||||
if orderedUnmarshaler != nil {
|
||||
defer orderedUnmarshaler.Redeem()
|
||||
|
||||
return orderedUnmarshaler.OrderedUnmarshal(trimmedData, orderedMap)
|
||||
}
|
||||
|
||||
// no support found in registered adapters, fallback to the default (unordered) case
|
||||
}
|
||||
|
||||
unmarshaler := adapters.UnmarshalAdapterFor(value)
|
||||
if unmarshaler != nil {
|
||||
defer unmarshaler.Redeem()
|
||||
|
||||
return unmarshaler.Unmarshal(trimmedData, value)
|
||||
}
|
||||
|
||||
// no support found in registered adapters, fallback to the default standard library.
|
||||
//
|
||||
// This only happens when tinkering with the global registry of adapters, since the default handles all the above cases.
|
||||
return json.Unmarshal(trimmedData, value) // Codecov ignore // this is a safeguard not easily simulated in tests
|
||||
}
|
||||
|
||||
// FromDynamicJSON turns a go value into a properly JSON typed structure.
|
||||
//
|
||||
// "Dynamic JSON" refers to what you get when unmarshaling JSON into an untyped any,
|
||||
// i.e. objects are represented by map[string]any, arrays by []any, and
|
||||
// all numbers are represented as float64.
|
||||
//
|
||||
// NOTE: target must be a pointer.
|
||||
//
|
||||
// # Maintaining the order of keys in objects
|
||||
//
|
||||
// If source and target implement [ifaces.Ordered] and [ifaces.SetOrdered] respectively,
|
||||
// they are considered "ordered maps" and the order of keys is maintained in the
|
||||
// "jsonification" process. In that case, map[string]any values are replaced by (ordered) [JSONMapSlice] ones.
|
||||
func FromDynamicJSON(source, target any) error {
|
||||
b, err := WriteJSON(source)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return ReadJSON(b, target)
|
||||
}
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package jsonutils
|
||||
|
||||
import (
|
||||
"iter"
|
||||
|
||||
"github.com/go-openapi/swag/jsonutils/adapters"
|
||||
"github.com/go-openapi/swag/typeutils"
|
||||
)
|
||||
|
||||
// JSONMapSlice represents a JSON object, with the order of keys maintained.
|
||||
//
|
||||
// It behaves like an ordered map, but keys can't be accessed in constant time.
|
||||
type JSONMapSlice []JSONMapItem
|
||||
|
||||
// OrderedItems iterates over all (key,value) pairs with the order of keys maintained.
|
||||
//
|
||||
// This implements the [ifaces.Ordered] interface, so that [ifaces.Adapter] s know how to marshal
|
||||
// keys in the desired order.
|
||||
func (s JSONMapSlice) OrderedItems() iter.Seq2[string, any] {
|
||||
return func(yield func(string, any) bool) {
|
||||
for _, item := range s {
|
||||
if !yield(item.Key, item.Value) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SetOrderedItems sets keys in the [JSONMapSlice] objects, as presented by
|
||||
// the provided iterator.
|
||||
//
|
||||
// As a special case, if items is nil, this sets to receiver to a nil slice.
|
||||
//
|
||||
// This implements the [ifaces.SetOrdered] interface, so that [ifaces.Adapter] s know how to unmarshal
|
||||
// keys in the desired order.
|
||||
func (s *JSONMapSlice) SetOrderedItems(items iter.Seq2[string, any]) {
|
||||
if items == nil {
|
||||
// force receiver to be a nil slice
|
||||
*s = nil
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
m := *s
|
||||
if len(m) > 0 {
|
||||
// update mode: short-circuited when unmarshaling fresh data structures
|
||||
idx := make(map[string]int, len(m))
|
||||
|
||||
for i, item := range m {
|
||||
idx[item.Key] = i
|
||||
}
|
||||
|
||||
for k, v := range items {
|
||||
idx, ok := idx[k]
|
||||
if ok {
|
||||
m[idx].Value = v
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
m = append(m, JSONMapItem{Key: k, Value: v})
|
||||
}
|
||||
|
||||
*s = m
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
for k, v := range items {
|
||||
m = append(m, JSONMapItem{Key: k, Value: v})
|
||||
}
|
||||
|
||||
*s = m
|
||||
}
|
||||
|
||||
// MarshalJSON renders a [JSONMapSlice] as JSON bytes, preserving the order of keys.
|
||||
//
|
||||
// It will pick the JSON library currently configured by the [adapters.Registry] (defaults to the standard library).
|
||||
func (s JSONMapSlice) MarshalJSON() ([]byte, error) {
|
||||
orderedMarshaler := adapters.OrderedMarshalAdapterFor(s)
|
||||
defer orderedMarshaler.Redeem()
|
||||
|
||||
return orderedMarshaler.OrderedMarshal(s)
|
||||
}
|
||||
|
||||
// UnmarshalJSON builds a [JSONMapSlice] from JSON bytes, preserving the order of keys.
|
||||
//
|
||||
// Inner objects are unmarshaled as ordered [JSONMapSlice] slices and not map[string]any.
|
||||
//
|
||||
// It will pick the JSON library currently configured by the [adapters.Registry] (defaults to the standard library).
|
||||
func (s *JSONMapSlice) UnmarshalJSON(data []byte) error {
|
||||
if typeutils.IsNil(*s) {
|
||||
// allow to unmarshal with a simple var declaration (nil slice)
|
||||
*s = JSONMapSlice{}
|
||||
}
|
||||
|
||||
orderedUnmarshaler := adapters.OrderedUnmarshalAdapterFor(s)
|
||||
defer orderedUnmarshaler.Redeem()
|
||||
|
||||
return orderedUnmarshaler.OrderedUnmarshal(data, s)
|
||||
}
|
||||
|
||||
// JSONMapItem represents the value of a key in a JSON object held by [JSONMapSlice].
|
||||
//
|
||||
// Notice that JSONMapItem should not be marshaled to or unmarshaled from JSON directly.
|
||||
//
|
||||
// Use this type as part of a [JSONMapSlice] when dealing with JSON bytes.
|
||||
type JSONMapItem struct {
|
||||
Key string
|
||||
Value any
|
||||
}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package swag
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/go-openapi/swag/jsonutils"
|
||||
)
|
||||
|
||||
// JSONMapSlice represents a JSON object, with the order of keys maintained
|
||||
//
|
||||
// Deprecated: use [jsonutils.JSONMapSlice] instead, or [yamlutils.YAMLMapSlice] if you marshal YAML.
|
||||
type JSONMapSlice = jsonutils.JSONMapSlice
|
||||
|
||||
// JSONMapItem represents a JSON object, with the order of keys maintained
|
||||
//
|
||||
// Deprecated: use [jsonutils.JSONMapItem] instead.
|
||||
type JSONMapItem = jsonutils.JSONMapItem
|
||||
|
||||
// WriteJSON writes json data.
|
||||
//
|
||||
// Deprecated: use [jsonutils.WriteJSON] instead.
|
||||
func WriteJSON(data any) ([]byte, error) { return jsonutils.WriteJSON(data) }
|
||||
|
||||
// ReadJSON reads json data.
|
||||
//
|
||||
// Deprecated: use [jsonutils.ReadJSON] instead.
|
||||
func ReadJSON(data []byte, value any) error { return jsonutils.ReadJSON(data, value) }
|
||||
|
||||
// DynamicJSONToStruct converts an untyped JSON structure into a target data type.
|
||||
//
|
||||
// Deprecated: use [jsonutils.FromDynamicJSON] instead.
|
||||
func DynamicJSONToStruct(data any, target any) error {
|
||||
return jsonutils.FromDynamicJSON(data, target)
|
||||
}
|
||||
|
||||
// ConcatJSON concatenates multiple JSON objects efficiently.
|
||||
//
|
||||
// Deprecated: use [jsonutils.ConcatJSON] instead.
|
||||
func ConcatJSON(blobs ...[]byte) []byte { return jsonutils.ConcatJSON(blobs...) }
|
||||
|
||||
// ToDynamicJSON turns a go value into a properly JSON untyped structure.
|
||||
//
|
||||
// It is the same as [FromDynamicJSON], but doesn't check for errors.
|
||||
//
|
||||
// Deprecated: this function is a misnomer and is unsafe. Use [jsonutils.FromDynamicJSON] instead.
|
||||
func ToDynamicJSON(value any) any {
|
||||
var res any
|
||||
if err := FromDynamicJSON(value, &res); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
// FromDynamicJSON turns a go value into a properly JSON typed structure.
|
||||
//
|
||||
// "Dynamic JSON" refers to what you get when unmarshaling JSON into an untyped any,
|
||||
// i.e. objects are represented by map[string]any, arrays by []any, and all
|
||||
// scalar values are any.
|
||||
//
|
||||
// Deprecated: use [jsonutils.FromDynamicJSON] instead.
|
||||
func FromDynamicJSON(data, target any) error { return jsonutils.FromDynamicJSON(data, target) }
|
||||
+202
@@ -0,0 +1,202 @@
|
||||
|
||||
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.
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Package loading provides tools to load a file from http or from a local file system.
|
||||
package loading
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package loading
|
||||
|
||||
type loadingError string
|
||||
|
||||
const (
|
||||
// ErrLoader is an error raised by the file loader utility
|
||||
ErrLoader loadingError = "loader error"
|
||||
)
|
||||
|
||||
func (e loadingError) Error() string {
|
||||
return string(e)
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package loading
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// JSONMatcher matches json for a file loader.
|
||||
func JSONMatcher(path string) bool {
|
||||
ext := filepath.Ext(path)
|
||||
return ext == ".json" || ext == ".jsn" || ext == ".jso"
|
||||
}
|
||||
|
||||
// JSONDoc loads a json document from either a file or a remote url.
|
||||
func JSONDoc(path string, opts ...Option) (json.RawMessage, error) {
|
||||
data, err := LoadFromFileOrHTTP(path, opts...)
|
||||
if err != nil {
|
||||
return nil, errors.Join(err, ErrLoader)
|
||||
}
|
||||
return json.RawMessage(data), nil
|
||||
}
|
||||
Generated
Vendored
+38
-54
@@ -1,54 +1,26 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// 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.
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package swag
|
||||
package loading
|
||||
|
||||
import (
|
||||
"context"
|
||||
"embed"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// LoadHTTPTimeout the default timeout for load requests
|
||||
var LoadHTTPTimeout = 30 * time.Second
|
||||
|
||||
// LoadHTTPBasicAuthUsername the username to use when load requests require basic auth
|
||||
var LoadHTTPBasicAuthUsername = ""
|
||||
|
||||
// LoadHTTPBasicAuthPassword the password to use when load requests require basic auth
|
||||
var LoadHTTPBasicAuthPassword = ""
|
||||
|
||||
// LoadHTTPCustomHeaders an optional collection of custom HTTP headers for load requests
|
||||
var LoadHTTPCustomHeaders = map[string]string{}
|
||||
|
||||
// LoadFromFileOrHTTP loads the bytes from a file or a remote http server based on the path passed in
|
||||
func LoadFromFileOrHTTP(pth string) ([]byte, error) {
|
||||
return LoadStrategy(pth, os.ReadFile, loadHTTPBytes(LoadHTTPTimeout))(pth)
|
||||
}
|
||||
|
||||
// LoadFromFileOrHTTPWithTimeout loads the bytes from a file or a remote http server based on the path passed in
|
||||
// timeout arg allows for per request overriding of the request timeout
|
||||
func LoadFromFileOrHTTPWithTimeout(pth string, timeout time.Duration) ([]byte, error) {
|
||||
return LoadStrategy(pth, os.ReadFile, loadHTTPBytes(timeout))(pth)
|
||||
func LoadFromFileOrHTTP(pth string, opts ...Option) ([]byte, error) {
|
||||
o := optionsWithDefaults(opts)
|
||||
return LoadStrategy(pth, o.ReadFileFunc(), loadHTTPBytes(opts...), opts...)(pth)
|
||||
}
|
||||
|
||||
// LoadStrategy returns a loader function for a given path or URI.
|
||||
@@ -81,10 +53,12 @@ func LoadFromFileOrHTTPWithTimeout(pth string, timeout time.Duration) ([]byte, e
|
||||
// - `file://host/folder/file` becomes an UNC path like `\\host\folder\file` (no port specification is supported)
|
||||
// - `file:///c:/folder/file` becomes `C:\folder\file`
|
||||
// - `file://c:/folder/file` is tolerated (without leading `/`) and becomes `c:\folder\file`
|
||||
func LoadStrategy(pth string, local, remote func(string) ([]byte, error)) func(string) ([]byte, error) {
|
||||
func LoadStrategy(pth string, local, remote func(string) ([]byte, error), opts ...Option) func(string) ([]byte, error) {
|
||||
if strings.HasPrefix(pth, "http") {
|
||||
return remote
|
||||
}
|
||||
o := optionsWithDefaults(opts)
|
||||
_, isEmbedFS := o.fs.(embed.FS)
|
||||
|
||||
return func(p string) ([]byte, error) {
|
||||
upth, err := url.PathUnescape(p)
|
||||
@@ -92,19 +66,19 @@ func LoadStrategy(pth string, local, remote func(string) ([]byte, error)) func(s
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(p, `file://`) {
|
||||
cpth, hasPrefix := strings.CutPrefix(upth, "file://")
|
||||
if !hasPrefix || isEmbedFS || runtime.GOOS != "windows" {
|
||||
// crude processing: trim the file:// prefix. This leaves full URIs with a host with a (mostly) unexpected result
|
||||
// regular file path provided: just normalize slashes
|
||||
return local(filepath.FromSlash(upth))
|
||||
if isEmbedFS {
|
||||
// on windows, we need to slash the path if FS is an embed FS.
|
||||
return local(strings.TrimLeft(filepath.ToSlash(cpth), "./")) // remove invalid leading characters for embed FS
|
||||
}
|
||||
|
||||
return local(filepath.FromSlash(cpth))
|
||||
}
|
||||
|
||||
if runtime.GOOS != "windows" {
|
||||
// crude processing: this leaves full URIs with a host with a (mostly) unexpected result
|
||||
upth = strings.TrimPrefix(upth, `file://`)
|
||||
|
||||
return local(filepath.FromSlash(upth))
|
||||
}
|
||||
|
||||
// windows-only pre-processing of file://... URIs
|
||||
// windows-only pre-processing of file://... URIs, excluding embed.FS
|
||||
|
||||
// support for canonical file URIs on windows.
|
||||
u, err := url.Parse(filepath.ToSlash(upth))
|
||||
@@ -139,19 +113,29 @@ func LoadStrategy(pth string, local, remote func(string) ([]byte, error)) func(s
|
||||
}
|
||||
}
|
||||
|
||||
func loadHTTPBytes(timeout time.Duration) func(path string) ([]byte, error) {
|
||||
func loadHTTPBytes(opts ...Option) func(path string) ([]byte, error) {
|
||||
o := optionsWithDefaults(opts)
|
||||
|
||||
return func(path string) ([]byte, error) {
|
||||
client := &http.Client{Timeout: timeout}
|
||||
req, err := http.NewRequest(http.MethodGet, path, nil) //nolint:noctx
|
||||
client := o.client
|
||||
timeoutCtx := context.Background()
|
||||
var cancel func()
|
||||
|
||||
if o.httpTimeout > 0 {
|
||||
timeoutCtx, cancel = context.WithTimeout(timeoutCtx, o.httpTimeout)
|
||||
defer cancel()
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(timeoutCtx, http.MethodGet, path, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if LoadHTTPBasicAuthUsername != "" && LoadHTTPBasicAuthPassword != "" {
|
||||
req.SetBasicAuth(LoadHTTPBasicAuthUsername, LoadHTTPBasicAuthPassword)
|
||||
if o.basicAuthUsername != "" && o.basicAuthPassword != "" {
|
||||
req.SetBasicAuth(o.basicAuthUsername, o.basicAuthPassword)
|
||||
}
|
||||
|
||||
for key, val := range LoadHTTPCustomHeaders {
|
||||
for key, val := range o.customHeaders {
|
||||
req.Header.Set(key, val)
|
||||
}
|
||||
|
||||
@@ -168,7 +152,7 @@ func loadHTTPBytes(timeout time.Duration) func(path string) ([]byte, error) {
|
||||
}
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("could not access document at %q [%s] ", path, resp.Status)
|
||||
return nil, fmt.Errorf("could not access document at %q [%s]: %w", path, resp.Status, ErrLoader)
|
||||
}
|
||||
|
||||
return io.ReadAll(resp.Body)
|
||||
+125
@@ -0,0 +1,125 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package loading
|
||||
|
||||
import (
|
||||
"io/fs"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
type (
|
||||
// Option provides options for loading a file over HTTP or from a file.
|
||||
Option func(*options)
|
||||
|
||||
httpOptions struct {
|
||||
httpTimeout time.Duration
|
||||
basicAuthUsername string
|
||||
basicAuthPassword string
|
||||
customHeaders map[string]string
|
||||
client *http.Client
|
||||
}
|
||||
|
||||
fileOptions struct {
|
||||
fs fs.ReadFileFS
|
||||
}
|
||||
|
||||
options struct {
|
||||
httpOptions
|
||||
fileOptions
|
||||
}
|
||||
)
|
||||
|
||||
func (fo fileOptions) ReadFileFunc() func(string) ([]byte, error) {
|
||||
if fo.fs == nil {
|
||||
return os.ReadFile
|
||||
}
|
||||
|
||||
return fo.fs.ReadFile
|
||||
}
|
||||
|
||||
// WithTimeout sets a timeout for the remote file loader.
|
||||
//
|
||||
// The default timeout is 30s.
|
||||
func WithTimeout(timeout time.Duration) Option {
|
||||
return func(o *options) {
|
||||
o.httpTimeout = timeout
|
||||
}
|
||||
}
|
||||
|
||||
// WithBasicAuth sets a basic authentication scheme for the remote file loader.
|
||||
func WithBasicAuth(username, password string) Option {
|
||||
return func(o *options) {
|
||||
o.basicAuthUsername = username
|
||||
o.basicAuthPassword = password
|
||||
}
|
||||
}
|
||||
|
||||
// WithCustomHeaders sets custom headers for the remote file loader.
|
||||
func WithCustomHeaders(headers map[string]string) Option {
|
||||
return func(o *options) {
|
||||
if o.customHeaders == nil {
|
||||
o.customHeaders = make(map[string]string, len(headers))
|
||||
}
|
||||
|
||||
for header, value := range headers {
|
||||
o.customHeaders[header] = value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WithHTTPClient overrides the default HTTP client used to fetch a remote file.
|
||||
//
|
||||
// By default, [http.DefaultClient] is used.
|
||||
func WithHTTPClient(client *http.Client) Option {
|
||||
return func(o *options) {
|
||||
o.client = client
|
||||
}
|
||||
}
|
||||
|
||||
// WithFS sets a file system for the local file loader.
|
||||
//
|
||||
// If the provided file system is a [fs.ReadFileFS], the ReadFile function is used.
|
||||
// Otherwise, ReadFile is wrapped using [fs.ReadFile].
|
||||
//
|
||||
// By default, the file system is the one provided by the os package.
|
||||
//
|
||||
// For example, this may be set to consume from an embedded file system, or a rooted FS.
|
||||
func WithFS(filesystem fs.FS) Option {
|
||||
return func(o *options) {
|
||||
if rfs, ok := filesystem.(fs.ReadFileFS); ok {
|
||||
o.fs = rfs
|
||||
|
||||
return
|
||||
}
|
||||
o.fs = readFileFS{FS: filesystem}
|
||||
}
|
||||
}
|
||||
|
||||
type readFileFS struct {
|
||||
fs.FS
|
||||
}
|
||||
|
||||
func (r readFileFS) ReadFile(name string) ([]byte, error) {
|
||||
return fs.ReadFile(r.FS, name)
|
||||
}
|
||||
|
||||
func optionsWithDefaults(opts []Option) options {
|
||||
const defaultTimeout = 30 * time.Second
|
||||
|
||||
o := options{
|
||||
// package level defaults
|
||||
httpOptions: httpOptions{
|
||||
httpTimeout: defaultTimeout,
|
||||
client: http.DefaultClient,
|
||||
},
|
||||
}
|
||||
|
||||
for _, apply := range opts {
|
||||
apply(&o)
|
||||
}
|
||||
|
||||
return o
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package loading
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/go-openapi/swag/yamlutils"
|
||||
)
|
||||
|
||||
// YAMLMatcher matches yaml for a file loader.
|
||||
func YAMLMatcher(path string) bool {
|
||||
ext := filepath.Ext(path)
|
||||
return ext == ".yaml" || ext == ".yml"
|
||||
}
|
||||
|
||||
// YAMLDoc loads a yaml document from either http or a file and converts it to json.
|
||||
func YAMLDoc(path string, opts ...Option) (json.RawMessage, error) {
|
||||
yamlDoc, err := YAMLData(path, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return yamlutils.YAMLToJSON(yamlDoc)
|
||||
}
|
||||
|
||||
// YAMLData loads a yaml document from either http or a file.
|
||||
func YAMLData(path string, opts ...Option) (any, error) {
|
||||
data, err := LoadFromFileOrHTTP(path, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return yamlutils.BytesToYAMLDoc(data)
|
||||
}
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package swag
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/go-openapi/swag/loading"
|
||||
)
|
||||
|
||||
var (
|
||||
// Package-level defaults for the file loading utilities (deprecated).
|
||||
|
||||
// LoadHTTPTimeout the default timeout for load requests.
|
||||
//
|
||||
// Deprecated: use [loading.WithTimeout] instead.
|
||||
LoadHTTPTimeout = 30 * time.Second
|
||||
|
||||
// LoadHTTPBasicAuthUsername the username to use when load requests require basic auth.
|
||||
//
|
||||
// Deprecated: use [loading.WithBasicAuth] instead.
|
||||
LoadHTTPBasicAuthUsername = ""
|
||||
|
||||
// LoadHTTPBasicAuthPassword the password to use when load requests require basic auth.
|
||||
//
|
||||
// Deprecated: use [loading.WithBasicAuth] instead.
|
||||
LoadHTTPBasicAuthPassword = ""
|
||||
|
||||
// LoadHTTPCustomHeaders an optional collection of custom HTTP headers for load requests.
|
||||
//
|
||||
// Deprecated: use [loading.WithCustomHeaders] instead.
|
||||
LoadHTTPCustomHeaders = map[string]string{}
|
||||
)
|
||||
|
||||
// LoadFromFileOrHTTP loads the bytes from a file or a remote http server based on the provided path.
|
||||
//
|
||||
// Deprecated: use [loading.LoadFromFileOrHTTP] instead.
|
||||
func LoadFromFileOrHTTP(pth string, opts ...loading.Option) ([]byte, error) {
|
||||
return loading.LoadFromFileOrHTTP(pth, loadingOptionsWithDefaults(opts)...)
|
||||
}
|
||||
|
||||
// LoadFromFileOrHTTPWithTimeout loads the bytes from a file or a remote http server based on the path passed in
|
||||
// timeout arg allows for per request overriding of the request timeout.
|
||||
//
|
||||
// Deprecated: use [loading.LoadFileOrHTTP] with the [loading.WithTimeout] option instead.
|
||||
func LoadFromFileOrHTTPWithTimeout(pth string, timeout time.Duration, opts ...loading.Option) ([]byte, error) {
|
||||
opts = append(opts, loading.WithTimeout(timeout))
|
||||
|
||||
return LoadFromFileOrHTTP(pth, opts...)
|
||||
}
|
||||
|
||||
// LoadStrategy returns a loader function for a given path or URL.
|
||||
//
|
||||
// Deprecated: use [loading.LoadStrategy] instead.
|
||||
func LoadStrategy(pth string, local, remote func(string) ([]byte, error), opts ...loading.Option) func(string) ([]byte, error) {
|
||||
return loading.LoadStrategy(pth, local, remote, loadingOptionsWithDefaults(opts)...)
|
||||
}
|
||||
|
||||
// YAMLMatcher matches yaml for a file loader.
|
||||
//
|
||||
// Deprecated: use [loading.YAMLMatcher] instead.
|
||||
func YAMLMatcher(path string) bool { return loading.YAMLMatcher(path) }
|
||||
|
||||
// YAMLDoc loads a yaml document from either http or a file and converts it to json.
|
||||
//
|
||||
// Deprecated: use [loading.YAMLDoc] instead.
|
||||
func YAMLDoc(path string) (json.RawMessage, error) {
|
||||
return loading.YAMLDoc(path)
|
||||
}
|
||||
|
||||
// YAMLData loads a yaml document from either http or a file.
|
||||
//
|
||||
// Deprecated: use [loading.YAMLData] instead.
|
||||
func YAMLData(path string) (any, error) {
|
||||
return loading.YAMLData(path)
|
||||
}
|
||||
|
||||
// loadingOptionsWithDefaults bridges deprecated default settings that use package-level variables,
|
||||
// with the recommended use of loading.Option.
|
||||
func loadingOptionsWithDefaults(opts []loading.Option) []loading.Option {
|
||||
o := []loading.Option{
|
||||
loading.WithTimeout(LoadHTTPTimeout),
|
||||
loading.WithBasicAuth(LoadHTTPBasicAuthUsername, LoadHTTPBasicAuthPassword),
|
||||
loading.WithCustomHeaders(LoadHTTPCustomHeaders),
|
||||
}
|
||||
o = append(o, opts...)
|
||||
|
||||
return o
|
||||
}
|
||||
Generated
Vendored
+43
-5
@@ -1,12 +1,10 @@
|
||||
# Benchmarks
|
||||
|
||||
## Name mangling utilities
|
||||
# Benchmarking name mangling utilities
|
||||
|
||||
```bash
|
||||
go test -bench XXX -run XXX -benchtime 30s
|
||||
```
|
||||
|
||||
### Benchmarks at b3e7a5386f996177e4808f11acb2aa93a0f660df
|
||||
## Benchmarks at b3e7a5386f996177e4808f11acb2aa93a0f660df
|
||||
|
||||
```
|
||||
goos: linux
|
||||
@@ -21,7 +19,7 @@ BenchmarkToXXXName/ToHumanNameLower-4 895334 40354 ns/op 10472 B/op
|
||||
BenchmarkToXXXName/ToHumanNameTitle-4 882441 40678 ns/op 10566 B/op 749 allocs/op
|
||||
```
|
||||
|
||||
### Benchmarks after PR #79
|
||||
## Benchmarks after PR #79
|
||||
|
||||
~ x10 performance improvement and ~ /100 memory allocations.
|
||||
|
||||
@@ -50,3 +48,43 @@ BenchmarkToXXXName/ToCommandName-16 32256634 1137 ns/op 147 B/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
|
||||
```
|
||||
|
||||
## Benchmarks at d7d2d1b895f5b6747afaff312dd2a402e69e818b
|
||||
|
||||
go1.24
|
||||
|
||||
```
|
||||
goos: linux
|
||||
goarch: amd64
|
||||
pkg: github.com/go-openapi/swag
|
||||
cpu: AMD Ryzen 7 5800X 8-Core Processor
|
||||
BenchmarkToXXXName/ToGoName-16 19757858 1881 ns/op 42 B/op 5 allocs/op
|
||||
BenchmarkToXXXName/ToVarName-16 17494111 2094 ns/op 74 B/op 7 allocs/op
|
||||
BenchmarkToXXXName/ToFileName-16 28161226 1492 ns/op 158 B/op 7 allocs/op
|
||||
BenchmarkToXXXName/ToCommandName-16 23787333 1489 ns/op 158 B/op 7 allocs/op
|
||||
BenchmarkToXXXName/ToHumanNameLower-16 17537257 2030 ns/op 103 B/op 6 allocs/op
|
||||
BenchmarkToXXXName/ToHumanNameTitle-16 16977453 2156 ns/op 105 B/op 6 allocs/op
|
||||
```
|
||||
|
||||
## Benchmarks after PR #106
|
||||
|
||||
Moving the scope of everything down to a struct allowed to reduce a bit garbage and pooling.
|
||||
|
||||
On top of that, ToGoName (and thus ToVarName) have been subject to a minor optimization, removing a few allocations.
|
||||
|
||||
Overall timings improve by ~ -10%.
|
||||
|
||||
go1.24
|
||||
|
||||
```
|
||||
goos: linux
|
||||
goarch: amd64
|
||||
pkg: github.com/go-openapi/swag/mangling
|
||||
cpu: AMD Ryzen 7 5800X 8-Core Processor
|
||||
BenchmarkToXXXName/ToGoName-16 22496130 1618 ns/op 31 B/op 3 allocs/op
|
||||
BenchmarkToXXXName/ToVarName-16 22538068 1618 ns/op 33 B/op 3 allocs/op
|
||||
BenchmarkToXXXName/ToFileName-16 27722977 1236 ns/op 105 B/op 6 allocs/op
|
||||
BenchmarkToXXXName/ToCommandName-16 27967395 1258 ns/op 105 B/op 6 allocs/op
|
||||
BenchmarkToXXXName/ToHumanNameLower-16 18587901 1917 ns/op 103 B/op 6 allocs/op
|
||||
BenchmarkToXXXName/ToHumanNameTitle-16 17193208 2019 ns/op 108 B/op 7 allocs/op
|
||||
```
|
||||
+202
@@ -0,0 +1,202 @@
|
||||
|
||||
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.
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Package mangling provides name mangling capabilities.
|
||||
//
|
||||
// Name mangling is an important stage when generating code:
|
||||
// it helps construct safe program identifiers that abide by the language rules
|
||||
// and play along with linters.
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
// Suppose we get an object name taken from an API spec: "json_object",
|
||||
//
|
||||
// We may generate a legit go type name using [NameMangler.ToGoName]: "JsonObject".
|
||||
//
|
||||
// We may then locate this type in a source file named using [NameMangler.ToFileName]: "json_object.go".
|
||||
//
|
||||
// The methods exposed by the NameMangler are used to generate code in many different contexts, such as:
|
||||
//
|
||||
// - generating exported or unexported go identifiers from a JSON schema or an API spec
|
||||
// - generating file names
|
||||
// - generating human-readable comments for types and variables
|
||||
// - generating JSON-like API identifiers from go code
|
||||
// - ...
|
||||
package mangling
|
||||
+270
@@ -0,0 +1,270 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package mangling
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"strings"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// DefaultInitialisms returns all the initialisms configured by default for this package.
|
||||
//
|
||||
// # Motivation
|
||||
//
|
||||
// Common initialisms are acronyms for which the ordinary camel-casing rules are altered and
|
||||
// for which we retain the original case.
|
||||
//
|
||||
// This is largely specific to the go naming conventions enforced by golint (now revive).
|
||||
//
|
||||
// # Example
|
||||
//
|
||||
// In go, "id" is a good-looking identifier, but "Id" is not and "ID" is preferred
|
||||
// (notice that this stems only from conventions: the go compiler accepts all of these).
|
||||
//
|
||||
// Similarly, we may use "http", but not "Http". In this case, "HTTP" is preferred.
|
||||
//
|
||||
// # Reference and customization
|
||||
//
|
||||
// The default list of these casing-style exceptions is taken from the [github.com/mgechev/revive] linter for go:
|
||||
// https://github.com/mgechev/revive/blob/master/lint/name.go#L93
|
||||
//
|
||||
// There are a few additions to the original list, such as IPv4, IPv6 and OAI ("OpenAPI").
|
||||
//
|
||||
// For these additions, "IPv4" would be preferred to "Ipv4" or "IPV4", and "OAI" to "Oai"
|
||||
//
|
||||
// You may redefine this list entirely using the mangler option [WithInitialisms], or simply add extra definitions
|
||||
// using [WithAdditionalInitialisms].
|
||||
//
|
||||
// # Mixed-case and plurals
|
||||
//
|
||||
// Notice that initialisms are not necessarily fully upper-cased: a mixed-case initialism indicates the preferred casing.
|
||||
//
|
||||
// Obviously, lower-case only initialisms do not make a lot of sense: if lower-case only initialisms are added,
|
||||
// they will be considered fully capitalized.
|
||||
//
|
||||
// Plural forms use mixed case like "IDs". And so do values like "IPv4" or "IPv6".
|
||||
//
|
||||
// The [NameMangler] automatically detects simple plurals for words such as "IDs" or "APIs",
|
||||
// so you don't need to configure these variants.
|
||||
//
|
||||
// At this moment, it doesn't support pluralization of terms that ends with an 's' (or 'S'), since there is
|
||||
// no clear consensus on whether a word like DNS should be pluralized as DNSes or remain invariant.
|
||||
// The [NameMangler] consider those invariant. Therefore DNSs or DNSes are not recognized as plurals for DNS.
|
||||
//
|
||||
// Besids, we don't want to support pluralization of terms which would otherwise conflict with another one,
|
||||
// like "HTTPs" vs "HTTPS". All these should be considered invariant. Hence: "Https" matches "HTTPS" and
|
||||
// "HTTPSS" is "HTTPS" followed by "S".
|
||||
func DefaultInitialisms() []string {
|
||||
return []string{
|
||||
"ACL",
|
||||
"API",
|
||||
"ASCII",
|
||||
"CPU",
|
||||
"CSS",
|
||||
"DNS",
|
||||
"EOF",
|
||||
"GUID",
|
||||
"HTML",
|
||||
"HTTPS",
|
||||
"HTTP",
|
||||
"ID",
|
||||
"IP",
|
||||
"IPv4", // prefer the mixed case outcome IPv4 over the capitalized IPV4
|
||||
"IPv6", // prefer the mixed case outcome IPv6 over the capitalized IPV6
|
||||
"JSON",
|
||||
"LHS",
|
||||
"OAI",
|
||||
"QPS",
|
||||
"RAM",
|
||||
"RHS",
|
||||
"RPC",
|
||||
"SLA",
|
||||
"SMTP",
|
||||
"SQL",
|
||||
"SSH",
|
||||
"TCP",
|
||||
"TLS",
|
||||
"TTL",
|
||||
"UDP",
|
||||
"UI",
|
||||
"UID",
|
||||
"UUID",
|
||||
"URI",
|
||||
"URL",
|
||||
"UTF8",
|
||||
"VM",
|
||||
"XML",
|
||||
"XMPP",
|
||||
"XSRF",
|
||||
"XSS",
|
||||
}
|
||||
}
|
||||
|
||||
type indexOfInitialisms struct {
|
||||
initialismsCache
|
||||
|
||||
index map[string]struct{}
|
||||
}
|
||||
|
||||
func newIndexOfInitialisms() *indexOfInitialisms {
|
||||
return &indexOfInitialisms{
|
||||
index: make(map[string]struct{}),
|
||||
}
|
||||
}
|
||||
|
||||
func (m *indexOfInitialisms) add(words ...string) *indexOfInitialisms {
|
||||
for _, word := range words {
|
||||
// sanitization of injected words: trimmed from blanks, and must start with a letter
|
||||
trimmed := strings.TrimSpace(word)
|
||||
|
||||
firstRune, _ := utf8.DecodeRuneInString(trimmed)
|
||||
if !unicode.IsLetter(firstRune) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Initialisms are case-sensitive. This means that we support mixed-case words.
|
||||
// However, if specified as a lower-case string, the initialism should be fully capitalized.
|
||||
if trimmed == strings.ToLower(trimmed) {
|
||||
m.index[strings.ToUpper(trimmed)] = struct{}{}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
m.index[trimmed] = struct{}{}
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *indexOfInitialisms) sorted() []string {
|
||||
result := make([]string, 0, len(m.index))
|
||||
for k := range m.index {
|
||||
result = append(result, k)
|
||||
}
|
||||
sort.Sort(sort.Reverse(byInitialism(result)))
|
||||
return result
|
||||
}
|
||||
|
||||
func (m *indexOfInitialisms) buildCache() {
|
||||
m.build(m.sorted(), m.pluralForm)
|
||||
}
|
||||
|
||||
// initialismsCache caches all needed pre-computed and converted initialism entries,
|
||||
// in the desired resolution order.
|
||||
type initialismsCache struct {
|
||||
initialisms []string
|
||||
initialismsRunes [][]rune
|
||||
initialismsUpperCased [][]rune // initialisms cached in their trimmed, upper-cased version
|
||||
initialismsPluralForm []pluralForm
|
||||
}
|
||||
|
||||
func (c *initialismsCache) build(in []string, pluralfunc func(string) pluralForm) {
|
||||
c.initialisms = in
|
||||
c.initialismsRunes = asRunes(c.initialisms)
|
||||
c.initialismsUpperCased = asUpperCased(c.initialisms)
|
||||
c.initialismsPluralForm = asPluralForms(c.initialisms, pluralfunc)
|
||||
}
|
||||
|
||||
// pluralForm denotes the kind of pluralization to be used for initialisms.
|
||||
//
|
||||
// At this moment, initialisms are either invariant or follow a simple plural form with an
|
||||
// extra (lower case) "s".
|
||||
type pluralForm uint8
|
||||
|
||||
const (
|
||||
notPlural pluralForm = iota
|
||||
invariantPlural
|
||||
simplePlural
|
||||
)
|
||||
|
||||
func (f pluralForm) String() string {
|
||||
switch f {
|
||||
case notPlural:
|
||||
return "notPlural"
|
||||
case invariantPlural:
|
||||
return "invariantPlural"
|
||||
case simplePlural:
|
||||
return "simplePlural"
|
||||
default:
|
||||
return "<unknown>"
|
||||
}
|
||||
}
|
||||
|
||||
// pluralForm indicates how we want to pluralize a given initialism.
|
||||
//
|
||||
// Besides configured invariant forms (like HTTP and HTTPS),
|
||||
// an initialism is normally pluralized by adding a single 's', like in IDs.
|
||||
//
|
||||
// Initialisms ending with an 'S' or an 's' are configured as invariant (we don't
|
||||
// support plural forms like CSSes or DNSes, however the mechanism could be extended to
|
||||
// do just that).
|
||||
func (m *indexOfInitialisms) pluralForm(key string) pluralForm {
|
||||
if _, ok := m.index[key]; !ok {
|
||||
return notPlural
|
||||
}
|
||||
|
||||
if strings.HasSuffix(strings.ToUpper(key), "S") {
|
||||
return invariantPlural
|
||||
}
|
||||
|
||||
if _, ok := m.index[key+"s"]; ok {
|
||||
return invariantPlural
|
||||
}
|
||||
|
||||
if _, ok := m.index[key+"S"]; ok {
|
||||
return invariantPlural
|
||||
}
|
||||
|
||||
return simplePlural
|
||||
}
|
||||
|
||||
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]
|
||||
}
|
||||
|
||||
// Less specifies the order in which initialisms are prioritized:
|
||||
// 1. match longest first
|
||||
// 2. when equal length, match in reverse lexicographical order, lower case match comes first
|
||||
func (s byInitialism) Less(i, j int) bool {
|
||||
if len(s[i]) != len(s[j]) {
|
||||
return len(s[i]) < len(s[j])
|
||||
}
|
||||
|
||||
return s[i] < s[j]
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
// asPluralForms bakes an index of pluralization support.
|
||||
func asPluralForms(in []string, pluralFunc func(string) pluralForm) []pluralForm {
|
||||
out := make([]pluralForm, len(in))
|
||||
for i, initialism := range in {
|
||||
out[i] = pluralFunc(initialism)
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
+186
@@ -0,0 +1,186 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package mangling
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
type (
|
||||
lexemKind uint8
|
||||
|
||||
nameLexem struct {
|
||||
original string
|
||||
matchedInitialism string
|
||||
kind lexemKind
|
||||
}
|
||||
)
|
||||
|
||||
const (
|
||||
lexemKindCasualName lexemKind = iota
|
||||
lexemKindInitialismName
|
||||
)
|
||||
|
||||
func newInitialismNameLexem(original, matchedInitialism string) nameLexem {
|
||||
return nameLexem{
|
||||
kind: lexemKindInitialismName,
|
||||
original: original,
|
||||
matchedInitialism: matchedInitialism,
|
||||
}
|
||||
}
|
||||
|
||||
func newCasualNameLexem(original string) nameLexem {
|
||||
return nameLexem{
|
||||
kind: lexemKindCasualName,
|
||||
original: trim(original), // TODO: save on calls to trim
|
||||
}
|
||||
}
|
||||
|
||||
// WriteTitleized writes the titleized lexeme to a bytes.Buffer.
|
||||
//
|
||||
// If the first letter cannot be capitalized, it doesn't write anything and return false,
|
||||
// so the caller may attempt some workaround strategy.
|
||||
func (l nameLexem) WriteTitleized(w *bytes.Buffer, alwaysUpper bool) bool {
|
||||
if l.kind == lexemKindInitialismName {
|
||||
w.WriteString(l.matchedInitialism)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
if len(l.original) == 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
if len(l.original) == 1 {
|
||||
// identifier is too short: casing will depend on the context
|
||||
firstByte := l.original[0]
|
||||
switch {
|
||||
case 'A' <= firstByte && firstByte <= 'Z':
|
||||
// safe
|
||||
w.WriteByte(firstByte)
|
||||
|
||||
return true
|
||||
case alwaysUpper && 'a' <= firstByte && firstByte <= 'z':
|
||||
w.WriteByte(firstByte - 'a' + 'A')
|
||||
|
||||
return true
|
||||
default:
|
||||
|
||||
// not a letter: skip and let the caller decide
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
if firstByte := l.original[0]; firstByte < utf8.RuneSelf {
|
||||
// ASCII
|
||||
switch {
|
||||
case 'A' <= firstByte && firstByte <= 'Z':
|
||||
// already an upper case letter
|
||||
w.WriteString(l.original)
|
||||
|
||||
return true
|
||||
case 'a' <= firstByte && firstByte <= 'z':
|
||||
w.WriteByte(firstByte - 'a' + 'A')
|
||||
w.WriteString(l.original[1:])
|
||||
|
||||
return true
|
||||
default:
|
||||
// not a good candidate: doesn't start with a letter
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// unicode
|
||||
firstRune, idx := utf8.DecodeRuneInString(l.original)
|
||||
if !unicode.IsLetter(firstRune) || !unicode.IsUpper(unicode.ToUpper(firstRune)) {
|
||||
// not a good candidate: doesn't start with a letter
|
||||
// or a rune for which case doesn't make sense (e.g. East-Asian runes etc)
|
||||
return false
|
||||
}
|
||||
|
||||
rest := l.original[idx:]
|
||||
w.WriteRune(unicode.ToUpper(firstRune))
|
||||
w.WriteString(strings.ToLower(rest))
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// WriteLower is like write titleized but it writes a lower-case version of the lexeme.
|
||||
//
|
||||
// Similarly, there is no writing if the casing of the first rune doesn't make sense.
|
||||
func (l nameLexem) WriteLower(w *bytes.Buffer, alwaysLower bool) bool {
|
||||
if l.kind == lexemKindInitialismName {
|
||||
w.WriteString(lower(l.matchedInitialism))
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
if len(l.original) == 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
if len(l.original) == 1 {
|
||||
// identifier is too short: casing will depend on the context
|
||||
firstByte := l.original[0]
|
||||
switch {
|
||||
case 'a' <= firstByte && firstByte <= 'z':
|
||||
// safe
|
||||
w.WriteByte(firstByte)
|
||||
|
||||
return true
|
||||
case alwaysLower && 'A' <= firstByte && firstByte <= 'Z':
|
||||
w.WriteByte(firstByte - 'A' + 'a')
|
||||
|
||||
return true
|
||||
default:
|
||||
|
||||
// not a letter: skip and let the caller decide
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
if firstByte := l.original[0]; firstByte < utf8.RuneSelf {
|
||||
// ASCII
|
||||
switch {
|
||||
case 'a' <= firstByte && firstByte <= 'z':
|
||||
// already a lower case letter
|
||||
w.WriteString(l.original)
|
||||
|
||||
return true
|
||||
case 'A' <= firstByte && firstByte <= 'Z':
|
||||
w.WriteByte(firstByte - 'A' + 'a')
|
||||
w.WriteString(l.original[1:])
|
||||
|
||||
return true
|
||||
default:
|
||||
// not a good candidate: doesn't start with a letter
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// unicode
|
||||
firstRune, idx := utf8.DecodeRuneInString(l.original)
|
||||
if !unicode.IsLetter(firstRune) || !unicode.IsLower(unicode.ToLower(firstRune)) {
|
||||
// not a good candidate: doesn't start with a letter
|
||||
// or a rune for which case doesn't make sense (e.g. East-Asian runes etc)
|
||||
return false
|
||||
}
|
||||
|
||||
rest := l.original[idx:]
|
||||
w.WriteRune(unicode.ToLower(firstRune))
|
||||
w.WriteString(rest)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (l nameLexem) GetOriginal() string {
|
||||
return l.original
|
||||
}
|
||||
|
||||
func (l nameLexem) IsInitialism() bool {
|
||||
return l.kind == lexemKindInitialismName
|
||||
}
|
||||
+370
@@ -0,0 +1,370 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package mangling
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
// NameMangler knows how to transform sentences or words into
|
||||
// identifiers that are a better fit in contexts such as:
|
||||
//
|
||||
// - unexported or exported go variable identifiers
|
||||
// - file names
|
||||
// - camel cased identifiers
|
||||
// - ...
|
||||
//
|
||||
// The [NameMangler] is safe for concurrent use, save for its [NameMangler.AddInitialisms] method,
|
||||
// which is not.
|
||||
//
|
||||
// # Known limitations
|
||||
//
|
||||
// At this moment, the [NameMangler] doesn't play well with "all caps" text:
|
||||
//
|
||||
// unless every single upper-cased word is declared as an initialism, capitalized words would generally
|
||||
// not be transformed with the expected result, e.g.
|
||||
//
|
||||
// ToFileName("THIS_IS_ALL_CAPS")
|
||||
//
|
||||
// yields the weird outcome
|
||||
//
|
||||
// "t_h_i_s_i_s_a_l_l_c_a_p_s"
|
||||
type NameMangler struct {
|
||||
options
|
||||
|
||||
index *indexOfInitialisms
|
||||
|
||||
splitter splitter
|
||||
splitterWithPostSplit splitter
|
||||
|
||||
_ struct{}
|
||||
}
|
||||
|
||||
// NewNameMangler builds a name mangler ready to convert strings.
|
||||
//
|
||||
// The default name mangler is configured with default common initialisms and all default options.
|
||||
func NewNameMangler(opts ...Option) NameMangler {
|
||||
m := NameMangler{
|
||||
options: optionsWithDefaults(opts),
|
||||
index: newIndexOfInitialisms(),
|
||||
}
|
||||
m.addInitialisms(m.commonInitialisms...)
|
||||
|
||||
// a splitter that returns matches lexemes as ready-to-assemble strings:
|
||||
// details of the lexemes are redeemed.
|
||||
m.splitter = newSplitter(
|
||||
withInitialismsCache(&m.index.initialismsCache),
|
||||
withReplaceFunc(m.replaceFunc),
|
||||
)
|
||||
|
||||
// a splitter that returns matches lexemes ready for post-processing
|
||||
m.splitterWithPostSplit = newSplitter(
|
||||
withInitialismsCache(&m.index.initialismsCache),
|
||||
withReplaceFunc(m.replaceFunc),
|
||||
withPostSplitInitialismCheck,
|
||||
)
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// AddInitialisms declares extra initialisms to the mangler.
|
||||
//
|
||||
// It declares extra words as "initialisms" (i.e. words that won't be camel cased or titled cased),
|
||||
// on top of the existing list of common initialisms (such as ID, HTTP...).
|
||||
//
|
||||
// Added words must start with a (unicode) letter. If some don't, they are ignored.
|
||||
// Added words are either fully capitalized or mixed-cased. Lower-case only words are considered capitalized.
|
||||
//
|
||||
// It is typically used just after initializing the [NameMangler].
|
||||
//
|
||||
// When all initialisms are known at the time the mangler is initialized, it is preferable to
|
||||
// use [NewNameMangler] with the option [WithAdditionalInitialisms].
|
||||
//
|
||||
// Adding initialisms mutates the mangler and should not be carried out concurrently with other calls to the mangler.
|
||||
func (m *NameMangler) AddInitialisms(words ...string) {
|
||||
m.addInitialisms(words...)
|
||||
}
|
||||
|
||||
// Initialisms renders the list of initialisms supported by this mangler.
|
||||
func (m *NameMangler) Initialisms() []string {
|
||||
return m.index.initialisms
|
||||
}
|
||||
|
||||
// Camelize a single word.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// - "HELLO" and "hello" become "Hello".
|
||||
func (m NameMangler) Camelize(word string) string {
|
||||
ru := []rune(word)
|
||||
|
||||
switch len(ru) {
|
||||
case 0:
|
||||
return ""
|
||||
case 1:
|
||||
return string(unicode.ToUpper(ru[0]))
|
||||
default:
|
||||
camelized := poolOfBuffers.BorrowBuffer(len(word))
|
||||
camelized.Grow(len(word))
|
||||
defer func() {
|
||||
poolOfBuffers.RedeemBuffer(camelized)
|
||||
}()
|
||||
|
||||
camelized.WriteRune(unicode.ToUpper(ru[0]))
|
||||
for _, ru := range ru[1:] {
|
||||
camelized.WriteRune(unicode.ToLower(ru))
|
||||
}
|
||||
|
||||
return camelized.String()
|
||||
}
|
||||
}
|
||||
|
||||
// ToFileName generates a suitable snake-case file name from a sentence.
|
||||
//
|
||||
// It lower-cases everything with underscore (_) as a word separator.
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
// - "Hello, Swagger" becomes "hello_swagger"
|
||||
// - "HelloSwagger" becomes "hello_swagger"
|
||||
func (m NameMangler) ToFileName(name string) string {
|
||||
inptr := m.split(name)
|
||||
in := *inptr
|
||||
out := make([]string, 0, len(in))
|
||||
|
||||
for _, w := range in {
|
||||
out = append(out, lower(w))
|
||||
}
|
||||
poolOfStrings.RedeemStrings(inptr)
|
||||
|
||||
return strings.Join(out, "_")
|
||||
}
|
||||
|
||||
// ToCommandName generates a suitable CLI command name from a sentence.
|
||||
//
|
||||
// It lower-cases everything with dash (-) as a word separator.
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
// - "Hello, Swagger" becomes "hello-swagger"
|
||||
// - "HelloSwagger" becomes "hello-swagger"
|
||||
func (m NameMangler) ToCommandName(name string) string {
|
||||
inptr := m.split(name)
|
||||
in := *inptr
|
||||
out := make([]string, 0, len(in))
|
||||
|
||||
for _, w := range in {
|
||||
out = append(out, lower(w))
|
||||
}
|
||||
poolOfStrings.RedeemStrings(inptr)
|
||||
|
||||
return strings.Join(out, "-")
|
||||
}
|
||||
|
||||
// ToHumanNameLower represents a code name as a human-readable series of words.
|
||||
//
|
||||
// It lower-cases everything with blank space as a word separator.
|
||||
//
|
||||
// NOTE: parts recognized as initialisms just keep their original casing.
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
// - "Hello, Swagger" becomes "hello swagger"
|
||||
// - "HelloSwagger" or "Hello-Swagger" become "hello swagger"
|
||||
func (m NameMangler) ToHumanNameLower(name string) string {
|
||||
s := m.splitterWithPostSplit
|
||||
in := s.split(name)
|
||||
out := make([]string, 0, len(*in))
|
||||
|
||||
for _, w := range *in {
|
||||
if !w.IsInitialism() {
|
||||
out = append(out, lower(w.GetOriginal()))
|
||||
} else {
|
||||
out = append(out, trim(w.GetOriginal()))
|
||||
}
|
||||
}
|
||||
|
||||
poolOfLexems.RedeemLexems(in)
|
||||
|
||||
return strings.Join(out, " ")
|
||||
}
|
||||
|
||||
// ToHumanNameTitle represents a code name as a human-readable series of titleized words.
|
||||
//
|
||||
// It titleizes every word with blank space as a word separator.
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
// - "hello, Swagger" becomes "Hello Swagger"
|
||||
// - "helloSwagger" becomes "Hello Swagger"
|
||||
func (m NameMangler) ToHumanNameTitle(name string) string {
|
||||
s := m.splitterWithPostSplit
|
||||
in := s.split(name)
|
||||
|
||||
out := make([]string, 0, len(*in))
|
||||
for _, w := range *in {
|
||||
original := trim(w.GetOriginal())
|
||||
if !w.IsInitialism() {
|
||||
out = append(out, m.Camelize(original))
|
||||
} else {
|
||||
out = append(out, original)
|
||||
}
|
||||
}
|
||||
poolOfLexems.RedeemLexems(in)
|
||||
|
||||
return strings.Join(out, " ")
|
||||
}
|
||||
|
||||
// ToJSONName generates a camelized single-word version of a sentence.
|
||||
//
|
||||
// The output assembles every camelized word, but for the first word, which
|
||||
// is lower-cased.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// - "Hello_swagger" becomes "helloSwagger"
|
||||
func (m NameMangler) ToJSONName(name string) string {
|
||||
inptr := m.split(name)
|
||||
in := *inptr
|
||||
out := make([]string, 0, len(in))
|
||||
|
||||
for i, w := range in {
|
||||
if i == 0 {
|
||||
out = append(out, lower(w))
|
||||
continue
|
||||
}
|
||||
out = append(out, m.Camelize(trim(w)))
|
||||
}
|
||||
|
||||
poolOfStrings.RedeemStrings(inptr)
|
||||
|
||||
return strings.Join(out, "")
|
||||
}
|
||||
|
||||
// ToVarName generates a legit unexported go variable name from a sentence.
|
||||
//
|
||||
// The generated name plays well with linters (see also [NameMangler.ToGoName]).
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
// - "Hello_swagger" becomes "helloSwagger"
|
||||
// - "Http_server" becomes "httpServer"
|
||||
//
|
||||
// This name applies the same rules as [NameMangler.ToGoName] (legit exported variable), save the
|
||||
// capitalization of the initial rune.
|
||||
//
|
||||
// Special case: when the initial part is a recognized as an initialism (like in the example above),
|
||||
// the full part is lower-cased.
|
||||
func (m NameMangler) ToVarName(name string) string {
|
||||
return m.goIdentifier(name, false)
|
||||
}
|
||||
|
||||
// ToGoName generates a legit exported go variable name from a sentence.
|
||||
//
|
||||
// The generated name plays well with most linters.
|
||||
//
|
||||
// ToGoName abides by the go "exported" symbol rule starting with an upper-case letter.
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
// - "hello_swagger" becomes "HelloSwagger"
|
||||
// - "Http_server" becomes "HTTPServer"
|
||||
//
|
||||
// # Edge cases
|
||||
//
|
||||
// Whenever the first rune is not eligible to upper case, a special prefix is prepended to the resulting name.
|
||||
// By default this is simply "X" and you may customize this behavior using the [WithGoNamePrefixFunc] option.
|
||||
//
|
||||
// This happens when the first rune is not a letter, e.g. a digit, or a symbol that has no word transliteration
|
||||
// (see also [WithReplaceFunc] about symbol transliterations),
|
||||
// as well as for most East Asian or Devanagari runes, for which there is no such concept as upper-case.
|
||||
//
|
||||
// # Linting
|
||||
//
|
||||
// [revive], the successor of golint is the reference linter.
|
||||
//
|
||||
// This means that [NameMangler.ToGoName] supports the initialisms that revive checks (see also [DefaultInitialisms]).
|
||||
//
|
||||
// At this moment, there is no attempt to transliterate unicode into ascii, meaning that some linters
|
||||
// (e.g. asciicheck, gosmopolitan) may croak on go identifiers generated from unicode input.
|
||||
//
|
||||
// [revive]: https://github.com/mgechev/revive
|
||||
func (m NameMangler) ToGoName(name string) string {
|
||||
return m.goIdentifier(name, true)
|
||||
}
|
||||
|
||||
func (m NameMangler) goIdentifier(name string, exported bool) string {
|
||||
s := m.splitterWithPostSplit
|
||||
lexems := s.split(name)
|
||||
defer func() {
|
||||
poolOfLexems.RedeemLexems(lexems)
|
||||
}()
|
||||
lexemes := *lexems
|
||||
|
||||
if len(lexemes) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
result := poolOfBuffers.BorrowBuffer(len(name))
|
||||
defer func() {
|
||||
poolOfBuffers.RedeemBuffer(result)
|
||||
}()
|
||||
|
||||
firstPart := lexemes[0]
|
||||
if !exported {
|
||||
if ok := firstPart.WriteLower(result, true); !ok {
|
||||
// NOTE: an initialism as the first part is lower-cased: no longer generates stuff like hTTPxyz.
|
||||
//
|
||||
// same prefixing rule applied to unexported variable as to an exported one, so that we have consistent
|
||||
// names, whether the generated identifier is exported or not.
|
||||
result.WriteString(strings.ToLower(m.prefixFunc()(name)))
|
||||
result.WriteString(lexemes[0].GetOriginal())
|
||||
}
|
||||
} else {
|
||||
if ok := firstPart.WriteTitleized(result, true); !ok {
|
||||
// "repairs" a lexeme that doesn't start with a letter to become
|
||||
// the start a legit go name. The current strategy is very crude and simply adds a fixed prefix,
|
||||
// e.g. "X".
|
||||
// For instance "1_sesame_street" would be split into lexemes ["1", "sesame", "street"] and
|
||||
// the first one ("1") would result in something like "X1" (with the default prefix function).
|
||||
//
|
||||
// NOTE: no longer forcing the first part to be fully upper-cased
|
||||
result.WriteString(m.prefixFunc()(name))
|
||||
result.WriteString(lexemes[0].GetOriginal())
|
||||
}
|
||||
}
|
||||
|
||||
for _, lexem := range lexemes[1:] {
|
||||
// NOTE: no longer forcing initialism parts to be fully upper-cased:
|
||||
// * pluralized initialism preserve their trailing "s"
|
||||
// * mixed-cased initialisms, such as IPv4, are preserved
|
||||
if ok := lexem.WriteTitleized(result, false); !ok {
|
||||
// it's not titleized: perhaps it's too short, perhaps the first rune is not a letter.
|
||||
// write anyway
|
||||
result.WriteString(lexem.GetOriginal())
|
||||
}
|
||||
}
|
||||
|
||||
return result.String()
|
||||
}
|
||||
|
||||
func (m *NameMangler) addInitialisms(words ...string) {
|
||||
m.index.add(words...)
|
||||
m.index.buildCache()
|
||||
}
|
||||
|
||||
// split calls the inner splitter.
|
||||
func (m NameMangler) split(str string) *[]string {
|
||||
s := m.splitter
|
||||
lexems := s.split(str)
|
||||
result := poolOfStrings.BorrowStrings()
|
||||
|
||||
for _, lexem := range *lexems {
|
||||
*result = append(*result, lexem.GetOriginal())
|
||||
}
|
||||
poolOfLexems.RedeemLexems(lexems)
|
||||
|
||||
return result
|
||||
}
|
||||
+150
@@ -0,0 +1,150 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package mangling
|
||||
|
||||
type (
|
||||
// PrefixFunc defines a safeguard rule (that may depend on the input string), to prefix
|
||||
// a generated go name (in [NameMangler.ToGoName] and [NameMangler.ToVarName]).
|
||||
//
|
||||
// See [NameMangler.ToGoName] for more about which edge cases the prefix function covers.
|
||||
PrefixFunc func(string) string
|
||||
|
||||
// ReplaceFunc is a transliteration function to replace special runes by a word.
|
||||
ReplaceFunc func(r rune) (string, bool)
|
||||
|
||||
// Option to configure a [NameMangler].
|
||||
Option func(*options)
|
||||
|
||||
options struct {
|
||||
commonInitialisms []string
|
||||
|
||||
goNamePrefixFunc PrefixFunc
|
||||
goNamePrefixFuncPtr *PrefixFunc
|
||||
replaceFunc func(r rune) (string, bool)
|
||||
}
|
||||
)
|
||||
|
||||
func (o *options) prefixFunc() PrefixFunc {
|
||||
if o.goNamePrefixFuncPtr != nil && *o.goNamePrefixFuncPtr != nil {
|
||||
return *o.goNamePrefixFuncPtr
|
||||
}
|
||||
|
||||
return o.goNamePrefixFunc
|
||||
}
|
||||
|
||||
// WithGoNamePrefixFunc overrides the default prefix rule to safeguard generated go names.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// This helps convert "123" into "{prefix}123" (a very crude strategy indeed, but it works).
|
||||
//
|
||||
// See [github.com/go-swagger/go-swagger/generator.DefaultFuncMap] for an example.
|
||||
//
|
||||
// The prefix function is assumed to return a string that starts with an upper case letter.
|
||||
//
|
||||
// The default is to prefix with "X".
|
||||
//
|
||||
// See [NameMangler.ToGoName] for more about which edge cases the prefix function covers.
|
||||
func WithGoNamePrefixFunc(fn PrefixFunc) Option {
|
||||
return func(o *options) {
|
||||
o.goNamePrefixFunc = fn
|
||||
}
|
||||
}
|
||||
|
||||
// WithGoNamePrefixFuncPtr is like [WithGoNamePrefixFunc] but it specifies a pointer to a function.
|
||||
//
|
||||
// [WithGoNamePrefixFunc] should be preferred in most situations. This option should only serve the
|
||||
// purpose of handling special situations where the prefix function is not an internal variable
|
||||
// (e.g. an exported package global).
|
||||
//
|
||||
// [WithGoNamePrefixFuncPtr] supersedes [WithGoNamePrefixFunc] if it also specified.
|
||||
//
|
||||
// If the provided pointer is nil or points to a nil value, this option has no effect.
|
||||
//
|
||||
// The caller should ensure that no undesirable concurrent changes are applied to the function pointed to.
|
||||
func WithGoNamePrefixFuncPtr(ptr *PrefixFunc) Option {
|
||||
return func(o *options) {
|
||||
o.goNamePrefixFuncPtr = ptr
|
||||
}
|
||||
}
|
||||
|
||||
// WithInitialisms declares the initialisms this mangler supports.
|
||||
//
|
||||
// This supersedes any pre-loaded defaults (see [DefaultInitialisms] for more about what initialisms are).
|
||||
//
|
||||
// It declares words to be recognized as "initialisms" (i.e. words that won't be camel cased or titled cased).
|
||||
//
|
||||
// Words must start with a (unicode) letter. If some don't, they are ignored.
|
||||
// Words are either fully capitalized or mixed-cased. Lower-case only words are considered capitalized.
|
||||
func WithInitialisms(words ...string) Option {
|
||||
return func(o *options) {
|
||||
o.commonInitialisms = words
|
||||
}
|
||||
}
|
||||
|
||||
// WithAdditionalInitialisms adds new initialisms to the currently supported list (see [DefaultInitialisms]).
|
||||
//
|
||||
// The same sanitization rules apply as those described for [WithInitialisms].
|
||||
func WithAdditionalInitialisms(words ...string) Option {
|
||||
return func(o *options) {
|
||||
o.commonInitialisms = append(o.commonInitialisms, words...)
|
||||
}
|
||||
}
|
||||
|
||||
// WithReplaceFunc specifies a custom transliteration function instead of the default.
|
||||
//
|
||||
// The default translates the following characters into words as follows:
|
||||
//
|
||||
// - '@' -> 'At'
|
||||
// - '&' -> 'And'
|
||||
// - '|' -> 'Pipe'
|
||||
// - '$' -> 'Dollar'
|
||||
// - '!' -> 'Bang'
|
||||
//
|
||||
// Notice that the outcome of a transliteration should always be titleized.
|
||||
func WithReplaceFunc(fn ReplaceFunc) Option {
|
||||
return func(o *options) {
|
||||
o.replaceFunc = fn
|
||||
}
|
||||
}
|
||||
|
||||
func defaultPrefixFunc(_ string) string {
|
||||
return "X"
|
||||
}
|
||||
|
||||
// defaultReplaceTable finds a word representation for special characters.
|
||||
func defaultReplaceTable(r rune) (string, bool) {
|
||||
switch r {
|
||||
case '@':
|
||||
return "At ", true
|
||||
case '&':
|
||||
return "And ", true
|
||||
case '|':
|
||||
return "Pipe ", true
|
||||
case '$':
|
||||
return "Dollar ", true
|
||||
case '!':
|
||||
return "Bang ", true
|
||||
case '-':
|
||||
return "", true
|
||||
case '_':
|
||||
return "", true
|
||||
default:
|
||||
return "", false
|
||||
}
|
||||
}
|
||||
|
||||
func optionsWithDefaults(opts []Option) options {
|
||||
o := options{
|
||||
commonInitialisms: DefaultInitialisms(),
|
||||
goNamePrefixFunc: defaultPrefixFunc,
|
||||
replaceFunc: defaultReplaceTable,
|
||||
}
|
||||
|
||||
for _, apply := range opts {
|
||||
apply(&o)
|
||||
}
|
||||
|
||||
return o
|
||||
}
|
||||
+123
@@ -0,0 +1,123 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package mangling
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"sync"
|
||||
)
|
||||
|
||||
const maxAllocMatches = 8
|
||||
|
||||
type (
|
||||
// memory pools of temporary objects.
|
||||
//
|
||||
// These are used to recycle temporarily allocated objects
|
||||
// and relieve the GC from undue pressure.
|
||||
|
||||
matchesPool struct {
|
||||
*sync.Pool
|
||||
}
|
||||
|
||||
buffersPool struct {
|
||||
*sync.Pool
|
||||
}
|
||||
|
||||
lexemsPool struct {
|
||||
*sync.Pool
|
||||
}
|
||||
|
||||
stringsPool struct {
|
||||
*sync.Pool
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
// poolOfMatches holds temporary slices for recycling during the initialism match process
|
||||
poolOfMatches = matchesPool{
|
||||
Pool: &sync.Pool{
|
||||
New: func() any {
|
||||
s := make(initialismMatches, 0, maxAllocMatches)
|
||||
|
||||
return &s
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
poolOfBuffers = buffersPool{
|
||||
Pool: &sync.Pool{
|
||||
New: func() any {
|
||||
return new(bytes.Buffer)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
poolOfLexems = lexemsPool{
|
||||
Pool: &sync.Pool{
|
||||
New: func() any {
|
||||
s := make([]nameLexem, 0, maxAllocMatches)
|
||||
|
||||
return &s
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
poolOfStrings = stringsPool{
|
||||
Pool: &sync.Pool{
|
||||
New: func() any {
|
||||
s := make([]string, 0, maxAllocMatches)
|
||||
|
||||
return &s
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func (p matchesPool) BorrowMatches() *initialismMatches {
|
||||
s := p.Get().(*initialismMatches)
|
||||
*s = (*s)[:0] // reset slice, keep allocated capacity
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
func (p buffersPool) BorrowBuffer(size int) *bytes.Buffer {
|
||||
s := p.Get().(*bytes.Buffer)
|
||||
s.Reset()
|
||||
|
||||
if s.Cap() < size {
|
||||
s.Grow(size)
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
func (p lexemsPool) BorrowLexems() *[]nameLexem {
|
||||
s := p.Get().(*[]nameLexem)
|
||||
*s = (*s)[:0] // reset slice, keep allocated capacity
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
func (p stringsPool) BorrowStrings() *[]string {
|
||||
s := p.Get().(*[]string)
|
||||
*s = (*s)[:0] // reset slice, keep allocated capacity
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
func (p matchesPool) RedeemMatches(s *initialismMatches) {
|
||||
p.Put(s)
|
||||
}
|
||||
|
||||
func (p buffersPool) RedeemBuffer(s *bytes.Buffer) {
|
||||
p.Put(s)
|
||||
}
|
||||
|
||||
func (p lexemsPool) RedeemLexems(s *[]nameLexem) {
|
||||
p.Put(s)
|
||||
}
|
||||
|
||||
func (p stringsPool) RedeemStrings(s *[]string) {
|
||||
p.Put(s)
|
||||
}
|
||||
+341
@@ -0,0 +1,341 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package mangling
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
type splitterOption func(*splitter)
|
||||
|
||||
// withPostSplitInitialismCheck allows to catch initialisms after main split process
|
||||
func withPostSplitInitialismCheck(s *splitter) {
|
||||
s.postSplitInitialismCheck = true
|
||||
}
|
||||
|
||||
func withReplaceFunc(fn ReplaceFunc) func(*splitter) {
|
||||
return func(s *splitter) {
|
||||
s.replaceFunc = fn
|
||||
}
|
||||
}
|
||||
|
||||
func withInitialismsCache(c *initialismsCache) splitterOption {
|
||||
return func(s *splitter) {
|
||||
s.initialismsCache = c
|
||||
}
|
||||
}
|
||||
|
||||
type (
|
||||
initialismMatch struct {
|
||||
body []rune
|
||||
start, end int
|
||||
complete bool
|
||||
hasPlural pluralForm
|
||||
}
|
||||
initialismMatches []initialismMatch
|
||||
)
|
||||
|
||||
// String representation of a match, e.g. for debugging.
|
||||
func (m initialismMatch) String() string {
|
||||
return fmt.Sprintf("{body: %s (%d), start: %d, end; %d, complete: %t, hasPlural: %v}",
|
||||
string(m.body), len(m.body), m.start, m.end, m.complete, m.hasPlural,
|
||||
)
|
||||
}
|
||||
|
||||
func (m initialismMatch) isZero() bool {
|
||||
return m.start == 0 && m.end == 0
|
||||
}
|
||||
|
||||
type splitter struct {
|
||||
*initialismsCache
|
||||
|
||||
postSplitInitialismCheck bool
|
||||
replaceFunc ReplaceFunc
|
||||
}
|
||||
|
||||
func newSplitter(options ...splitterOption) splitter {
|
||||
var s splitter
|
||||
|
||||
for _, option := range options {
|
||||
option(&s)
|
||||
}
|
||||
|
||||
if s.replaceFunc == nil {
|
||||
s.replaceFunc = defaultReplaceTable
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
func (s splitter) split(name string) *[]nameLexem {
|
||||
nameRunes := []rune(name)
|
||||
matches := s.gatherInitialismMatches(nameRunes)
|
||||
if matches == nil {
|
||||
return poolOfLexems.BorrowLexems()
|
||||
}
|
||||
|
||||
return s.mapMatchesToNameLexems(nameRunes, matches)
|
||||
}
|
||||
|
||||
func (s splitter) gatherInitialismMatches(nameRunes []rune) *initialismMatches {
|
||||
matches := poolOfMatches.BorrowMatches()
|
||||
const minLenInitialism = 1
|
||||
if len(nameRunes) < minLenInitialism+1 {
|
||||
// can't match initialism with 0 or 1 rune
|
||||
return matches
|
||||
}
|
||||
|
||||
// first iteration
|
||||
s.findMatches(matches, nameRunes, nameRunes[0], 0)
|
||||
|
||||
for i, currentRune := range nameRunes[1:] {
|
||||
currentRunePosition := i + 1
|
||||
// recycle allocations as we loop over runes
|
||||
// with such recycling, only 2 slices should be allocated per call
|
||||
// instead of o(n).
|
||||
//
|
||||
// BorrowMatches always yields slices with zero length (with some capacity)
|
||||
newMatches := poolOfMatches.BorrowMatches()
|
||||
|
||||
// check current initialism matches
|
||||
for _, match := range *matches {
|
||||
if keepCompleteMatch := match.complete; keepCompleteMatch {
|
||||
// the match is already complete: keep it then move on to the next match
|
||||
*newMatches = append(*newMatches, match)
|
||||
continue
|
||||
}
|
||||
|
||||
if currentRunePosition-match.start == len(match.body) {
|
||||
// unmatched: skip
|
||||
continue
|
||||
}
|
||||
|
||||
// 1. by construction of the matches, we can't have currentRunePosition - match.start < 0
|
||||
// because matches have been computed with their start <= currentRunePosition in the previous
|
||||
// iterations.
|
||||
// 2. by construction of the matches, we can't have currentRunePosition - match.start >= len(match.body)
|
||||
|
||||
currentMatchRune := match.body[currentRunePosition-match.start]
|
||||
if currentMatchRune != currentRune {
|
||||
// failed match, discard it then move on to the next match
|
||||
continue
|
||||
}
|
||||
|
||||
// try to complete the current match
|
||||
if currentRunePosition-match.start == len(match.body)-1 {
|
||||
// we are close: the next step is to check the symbol ahead
|
||||
// if it is a lowercase letter, then it is not the end of match
|
||||
// but the beginning of the next word.
|
||||
//
|
||||
// NOTE(fredbi): this heuristic sometimes leads to counterintuitive splits and
|
||||
// perhaps (not sure yet) we should check against case _alternance_.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// In the current version, in the sentence "IDS initialism", "ID" is recognized as an initialism,
|
||||
// leading to a split like "id_s_initialism" (or IDSInitialism),
|
||||
// whereas in the sentence "IDx initialism", it is not and produces something like
|
||||
// "i_d_x_initialism" (or IDxInitialism). The generated file name is not great.
|
||||
//
|
||||
// Both go identifiers are tolerated by linters.
|
||||
//
|
||||
// Notice that the slightly different input "IDs initialism" is correctly detected
|
||||
// as a pluralized initialism and produces something like "ids_initialism" (or IDsInitialism).
|
||||
|
||||
if currentRunePosition < len(nameRunes)-1 { // when before the last rune
|
||||
nextRune := nameRunes[currentRunePosition+1]
|
||||
|
||||
// recognize a plural form for this initialism (only simple english pluralization is supported).
|
||||
if nextRune == 's' && match.hasPlural == simplePlural {
|
||||
// detected a pluralized initialism
|
||||
match.body = append(match.body, nextRune)
|
||||
lookAhead := currentRunePosition + 1
|
||||
if lookAhead < len(nameRunes)-1 {
|
||||
nextRune = nameRunes[lookAhead+1]
|
||||
if newWord := unicode.IsLower(nextRune); newWord {
|
||||
// it is the start of a new word.
|
||||
// Match is only partial and the initialism is not recognized:
|
||||
// move on to the next match, but do not advance the rune position
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// this is a pluralized match: keep it
|
||||
currentRunePosition++
|
||||
match.complete = true
|
||||
match.hasPlural = simplePlural
|
||||
match.end = currentRunePosition
|
||||
*newMatches = append(*newMatches, match)
|
||||
|
||||
// match is complete: keep it then move on to the next match
|
||||
continue
|
||||
}
|
||||
|
||||
// other cases
|
||||
// example: invariant plural such as "TLS"
|
||||
if newWord := unicode.IsLower(nextRune); newWord {
|
||||
// it is the start of a new word
|
||||
// Match is only partial and the initialism is not recognized : move on
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
match.complete = true
|
||||
match.end = currentRunePosition
|
||||
}
|
||||
|
||||
// append the ongoing matching attempt: it is not necessarily complete, but was successful so far.
|
||||
// Let's see if it still matches on the next rune.
|
||||
*newMatches = append(*newMatches, match)
|
||||
}
|
||||
|
||||
s.findMatches(newMatches, nameRunes, currentRune, currentRunePosition)
|
||||
|
||||
poolOfMatches.RedeemMatches(matches)
|
||||
matches = newMatches
|
||||
}
|
||||
|
||||
// it is up to the caller to redeem this last slice
|
||||
return matches
|
||||
}
|
||||
|
||||
func (s splitter) findMatches(newMatches *initialismMatches, nameRunes []rune, currentRune rune, currentRunePosition int) {
|
||||
// check for new initialism matches, based on the first character
|
||||
for i, r := range s.initialismsRunes {
|
||||
if r[0] != currentRune {
|
||||
continue
|
||||
}
|
||||
|
||||
if currentRunePosition+len(r) > len(nameRunes) {
|
||||
continue // not eligible: would spilll over the initial string
|
||||
}
|
||||
|
||||
// possible matches: all initialisms starting with the current rune and that can fit the given string (nameRunes)
|
||||
*newMatches = append(*newMatches, initialismMatch{
|
||||
start: currentRunePosition,
|
||||
body: r,
|
||||
complete: false,
|
||||
hasPlural: s.initialismsPluralForm[i],
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (s splitter) mapMatchesToNameLexems(nameRunes []rune, matches *initialismMatches) *[]nameLexem {
|
||||
nameLexems := poolOfLexems.BorrowLexems()
|
||||
|
||||
var lastAcceptedMatch initialismMatch
|
||||
for _, match := range *matches {
|
||||
if !match.complete {
|
||||
continue
|
||||
}
|
||||
|
||||
if firstMatch := lastAcceptedMatch.isZero(); firstMatch {
|
||||
s.appendBrokenDownCasualString(nameLexems, nameRunes[:match.start])
|
||||
*nameLexems = append(*nameLexems, s.breakInitialism(string(match.body)))
|
||||
|
||||
lastAcceptedMatch = match
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
if overlappedMatch := match.start <= lastAcceptedMatch.end; overlappedMatch {
|
||||
continue
|
||||
}
|
||||
|
||||
middle := nameRunes[lastAcceptedMatch.end+1 : match.start]
|
||||
s.appendBrokenDownCasualString(nameLexems, middle)
|
||||
*nameLexems = append(*nameLexems, s.breakInitialism(string(match.body)))
|
||||
|
||||
lastAcceptedMatch = match
|
||||
}
|
||||
|
||||
// we have not found any accepted matches
|
||||
if lastAcceptedMatch.isZero() {
|
||||
*nameLexems = (*nameLexems)[:0]
|
||||
s.appendBrokenDownCasualString(nameLexems, nameRunes)
|
||||
} else if lastAcceptedMatch.end+1 != len(nameRunes) {
|
||||
rest := nameRunes[lastAcceptedMatch.end+1:]
|
||||
s.appendBrokenDownCasualString(nameLexems, rest)
|
||||
}
|
||||
|
||||
poolOfMatches.RedeemMatches(matches)
|
||||
|
||||
return nameLexems
|
||||
}
|
||||
|
||||
func (s splitter) breakInitialism(original string) nameLexem {
|
||||
return newInitialismNameLexem(original, original)
|
||||
}
|
||||
|
||||
func (s splitter) appendBrokenDownCasualString(segments *[]nameLexem, str []rune) {
|
||||
currentSegment := poolOfBuffers.BorrowBuffer(len(str)) // unlike strings.Builder, bytes.Buffer initial storage can reused
|
||||
defer func() {
|
||||
poolOfBuffers.RedeemBuffer(currentSegment)
|
||||
}()
|
||||
|
||||
addCasualNameLexem := func(original string) {
|
||||
*segments = append(*segments, newCasualNameLexem(original))
|
||||
}
|
||||
|
||||
addInitialismNameLexem := func(original, match string) {
|
||||
*segments = append(*segments, newInitialismNameLexem(original, match))
|
||||
}
|
||||
|
||||
var addNameLexem func(string)
|
||||
if s.postSplitInitialismCheck {
|
||||
addNameLexem = func(original string) {
|
||||
for i := range s.initialisms {
|
||||
if isEqualFoldIgnoreSpace(s.initialismsUpperCased[i], original) {
|
||||
addInitialismNameLexem(original, s.initialisms[i])
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
addCasualNameLexem(original)
|
||||
}
|
||||
} else {
|
||||
addNameLexem = addCasualNameLexem
|
||||
}
|
||||
|
||||
// NOTE: (performance). The few remaining non-amortized allocations
|
||||
// lay in the code below: using String() forces
|
||||
for _, rn := range str {
|
||||
if replace, found := s.replaceFunc(rn); found {
|
||||
if currentSegment.Len() > 0 {
|
||||
addNameLexem(currentSegment.String())
|
||||
currentSegment.Reset()
|
||||
}
|
||||
|
||||
if replace != "" {
|
||||
addNameLexem(replace)
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
if !unicode.In(rn, unicode.L, unicode.M, unicode.N, unicode.Pc) {
|
||||
if currentSegment.Len() > 0 {
|
||||
addNameLexem(currentSegment.String())
|
||||
currentSegment.Reset()
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
if unicode.IsUpper(rn) {
|
||||
if currentSegment.Len() > 0 {
|
||||
addNameLexem(currentSegment.String())
|
||||
}
|
||||
currentSegment.Reset()
|
||||
}
|
||||
|
||||
currentSegment.WriteRune(rn)
|
||||
}
|
||||
|
||||
if currentSegment.Len() > 0 {
|
||||
addNameLexem(currentSegment.String())
|
||||
}
|
||||
}
|
||||
Generated
Vendored
+4
-1
@@ -1,4 +1,7 @@
|
||||
package swag
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package mangling
|
||||
|
||||
import "unsafe"
|
||||
|
||||
+118
@@ -0,0 +1,118 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package mangling
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// Removes leading whitespaces
|
||||
func trim(str string) string { return strings.TrimSpace(str) }
|
||||
|
||||
// upper is strings.ToUpper() combined with trim
|
||||
func upper(str string) string {
|
||||
return strings.ToUpper(trim(str))
|
||||
}
|
||||
|
||||
// lower is strings.ToLower() combined with trim
|
||||
func lower(str string) string {
|
||||
return strings.ToLower(trim(str))
|
||||
}
|
||||
|
||||
// isEqualFoldIgnoreSpace is the same as strings.EqualFold, but
|
||||
// it ignores leading and trailing blank spaces in the compared
|
||||
// string.
|
||||
//
|
||||
// base is assumed to be composed of upper-cased runes, and be already
|
||||
// trimmed.
|
||||
//
|
||||
// This code is heavily inspired from strings.EqualFold.
|
||||
func isEqualFoldIgnoreSpace(base []rune, str string) bool {
|
||||
var i, baseIndex int
|
||||
// equivalent to b := []byte(str), but without data copy
|
||||
b := hackStringBytes(str)
|
||||
|
||||
for i < len(b) {
|
||||
if c := b[i]; c < utf8.RuneSelf {
|
||||
// fast path for ASCII
|
||||
if c != ' ' && c != '\t' {
|
||||
break
|
||||
}
|
||||
i++
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
// unicode case
|
||||
r, size := utf8.DecodeRune(b[i:])
|
||||
if !unicode.IsSpace(r) {
|
||||
break
|
||||
}
|
||||
i += size
|
||||
}
|
||||
|
||||
if i >= len(b) {
|
||||
return len(base) == 0
|
||||
}
|
||||
|
||||
for _, baseRune := range base {
|
||||
if i >= len(b) {
|
||||
break
|
||||
}
|
||||
|
||||
if c := b[i]; c < utf8.RuneSelf {
|
||||
// single byte rune case (ASCII)
|
||||
if baseRune >= utf8.RuneSelf {
|
||||
return false
|
||||
}
|
||||
|
||||
baseChar := byte(baseRune)
|
||||
if c != baseChar && ((c < 'a') || (c > 'z') || (c-'a'+'A' != baseChar)) {
|
||||
return false
|
||||
}
|
||||
|
||||
baseIndex++
|
||||
i++
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
// unicode case
|
||||
r, size := utf8.DecodeRune(b[i:])
|
||||
if unicode.ToUpper(r) != baseRune {
|
||||
return false
|
||||
}
|
||||
baseIndex++
|
||||
i += size
|
||||
}
|
||||
|
||||
if baseIndex != len(base) {
|
||||
return false
|
||||
}
|
||||
|
||||
// all passed: now we should only have blanks
|
||||
for i < len(b) {
|
||||
if c := b[i]; c < utf8.RuneSelf {
|
||||
// fast path for ASCII
|
||||
if c != ' ' && c != '\t' {
|
||||
return false
|
||||
}
|
||||
i++
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
// unicode case
|
||||
r, size := utf8.DecodeRune(b[i:])
|
||||
if !unicode.IsSpace(r) {
|
||||
return false
|
||||
}
|
||||
|
||||
i += size
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package swag
|
||||
|
||||
import "github.com/go-openapi/swag/mangling"
|
||||
|
||||
// GoNamePrefixFunc sets an optional rule to prefix go names
|
||||
// which do not start with a letter.
|
||||
//
|
||||
// GoNamePrefixFunc should not be written to while concurrently using the other mangling functions of this package.
|
||||
//
|
||||
// Deprecated: use [mangling.WithGoNamePrefixFunc] instead.
|
||||
var GoNamePrefixFunc mangling.PrefixFunc
|
||||
|
||||
// swagNameMangler is a global instance of the name mangler specifically alloted
|
||||
// to support deprecated functions.
|
||||
var swagNameMangler = mangling.NewNameMangler(
|
||||
mangling.WithGoNamePrefixFuncPtr(&GoNamePrefixFunc),
|
||||
)
|
||||
|
||||
// AddInitialisms adds additional initialisms to the default list (see [mangling.DefaultInitialisms]).
|
||||
//
|
||||
// AddInitialisms is not safe to be called concurrently.
|
||||
//
|
||||
// Deprecated: use [mangling.WithAdditionalInitialisms] instead.
|
||||
func AddInitialisms(words ...string) {
|
||||
swagNameMangler.AddInitialisms(words...)
|
||||
}
|
||||
|
||||
// Camelize a single word.
|
||||
//
|
||||
// Deprecated: use [mangling.NameMangler.Camelize] instead.
|
||||
func Camelize(word string) string { return swagNameMangler.Camelize(word) }
|
||||
|
||||
// ToFileName lowercases and underscores a go type name.
|
||||
//
|
||||
// Deprecated: use [mangling.NameMangler.ToFileName] instead.
|
||||
func ToFileName(name string) string { return swagNameMangler.ToFileName(name) }
|
||||
|
||||
// ToCommandName lowercases and underscores a go type name.
|
||||
//
|
||||
// Deprecated: use [mangling.NameMangler.ToCommandName] instead.
|
||||
func ToCommandName(name string) string { return swagNameMangler.ToCommandName(name) }
|
||||
|
||||
// ToHumanNameLower represents a code name as a human series of words.
|
||||
//
|
||||
// Deprecated: use [mangling.NameMangler.ToHumanNameLower] instead.
|
||||
func ToHumanNameLower(name string) string { return swagNameMangler.ToHumanNameLower(name) }
|
||||
|
||||
// ToHumanNameTitle represents a code name as a human series of words with the first letters titleized.
|
||||
//
|
||||
// Deprecated: use [mangling.NameMangler.ToHumanNameTitle] instead.
|
||||
func ToHumanNameTitle(name string) string { return swagNameMangler.ToHumanNameTitle(name) }
|
||||
|
||||
// ToJSONName camel-cases a name which can be underscored or pascal-cased.
|
||||
//
|
||||
// Deprecated: use [mangling.NameMangler.ToJSONName] instead.
|
||||
func ToJSONName(name string) string { return swagNameMangler.ToJSONName(name) }
|
||||
|
||||
// ToVarName camel-cases a name which can be underscored or pascal-cased.
|
||||
//
|
||||
// Deprecated: use [mangling.NameMangler.ToVarName] instead.
|
||||
func ToVarName(name string) string { return swagNameMangler.ToVarName(name) }
|
||||
|
||||
// ToGoName translates a swagger name which can be underscored or camel cased to a name that golint likes.
|
||||
//
|
||||
// Deprecated: use [mangling.NameMangler.ToGoName] instead.
|
||||
func ToGoName(name string) string { return swagNameMangler.ToGoName(name) }
|
||||
-93
@@ -1,93 +0,0 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// 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 swag
|
||||
|
||||
import (
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
type (
|
||||
lexemKind uint8
|
||||
|
||||
nameLexem struct {
|
||||
original string
|
||||
matchedInitialism string
|
||||
kind lexemKind
|
||||
}
|
||||
)
|
||||
|
||||
const (
|
||||
lexemKindCasualName lexemKind = iota
|
||||
lexemKindInitialismName
|
||||
)
|
||||
|
||||
func newInitialismNameLexem(original, matchedInitialism string) nameLexem {
|
||||
return nameLexem{
|
||||
kind: lexemKindInitialismName,
|
||||
original: original,
|
||||
matchedInitialism: matchedInitialism,
|
||||
}
|
||||
}
|
||||
|
||||
func newCasualNameLexem(original string) nameLexem {
|
||||
return nameLexem{
|
||||
kind: lexemKindCasualName,
|
||||
original: original,
|
||||
}
|
||||
}
|
||||
|
||||
func (l nameLexem) GetUnsafeGoName() string {
|
||||
if l.kind == lexemKindInitialismName {
|
||||
return l.matchedInitialism
|
||||
}
|
||||
|
||||
var (
|
||||
first rune
|
||||
rest string
|
||||
)
|
||||
|
||||
for i, orig := range l.original {
|
||||
if i == 0 {
|
||||
first = orig
|
||||
continue
|
||||
}
|
||||
|
||||
if i > 0 {
|
||||
rest = l.original[i:]
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if len(l.original) > 1 {
|
||||
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
|
||||
}
|
||||
|
||||
func (l nameLexem) GetOriginal() string {
|
||||
return l.original
|
||||
}
|
||||
|
||||
func (l nameLexem) IsInitialism() bool {
|
||||
return l.kind == lexemKindInitialismName
|
||||
}
|
||||
-38
@@ -1,38 +0,0 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// 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 swag
|
||||
|
||||
import (
|
||||
"net"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// SplitHostPort splits a network address into a host and a port.
|
||||
// The port is -1 when there is no port to be found
|
||||
func SplitHostPort(addr string) (host string, port int, err error) {
|
||||
h, p, err := net.SplitHostPort(addr)
|
||||
if err != nil {
|
||||
return "", -1, err
|
||||
}
|
||||
if p == "" {
|
||||
return "", -1, &net.AddrError{Err: "missing port in address", Addr: addr}
|
||||
}
|
||||
|
||||
pi, err := strconv.Atoi(p)
|
||||
if err != nil {
|
||||
return "", -1, err
|
||||
}
|
||||
return h, pi, nil
|
||||
}
|
||||
+202
@@ -0,0 +1,202 @@
|
||||
|
||||
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.
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Package netutils provides helpers for network-related tasks.
|
||||
package netutils
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package netutils
|
||||
|
||||
import (
|
||||
"net"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// SplitHostPort splits a network address into a host and a port.
|
||||
//
|
||||
// The difference with the standard net.SplitHostPort is that the port is converted to an int.
|
||||
//
|
||||
// The port is -1 when there is no port to be found.
|
||||
func SplitHostPort(addr string) (host string, port int, err error) {
|
||||
h, p, err := net.SplitHostPort(addr)
|
||||
if err != nil {
|
||||
return "", -1, err
|
||||
}
|
||||
if p == "" {
|
||||
return "", -1, &net.AddrError{Err: "missing port in address", Addr: addr}
|
||||
}
|
||||
|
||||
pi, err := strconv.Atoi(p)
|
||||
if err != nil {
|
||||
return "", -1, err
|
||||
}
|
||||
|
||||
return h, pi, nil
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user