diff --git a/go.mod b/go.mod index 71dd4f511..0fa46d09f 100644 --- a/go.mod +++ b/go.mod @@ -1,11 +1,13 @@ module github.com/hybrid-cloud-patterns/patterns-operator -go 1.26.5 +go 1.27.0 require ( code.gitea.io/sdk/gitea v0.25.1 + dario.cat/mergo v1.0.2 github.com/Masterminds/semver/v3 v3.5.0 github.com/argoproj-labs/argocd-operator v0.20.0-rc1 + github.com/argoproj/argo-cd/v3 v3.5.6 github.com/bradleyfalzon/ghinstallation/v2 v2.19.0 github.com/go-errors/errors v1.5.1 github.com/go-git/go-git/v5 v5.19.3 @@ -25,13 +27,8 @@ require ( k8s.io/api v0.37.1 k8s.io/apimachinery v0.37.1 k8s.io/client-go v12.0.0+incompatible - sigs.k8s.io/controller-runtime v0.24.1 -) - -require ( - dario.cat/mergo v1.0.2 - github.com/argoproj/argo-cd/v3 v3.5.6 k8s.io/utils v0.0.0-20261023123148-ca04ba58ecab + sigs.k8s.io/controller-runtime v0.24.1 sigs.k8s.io/controller-runtime/tools/setup-envtest v0.25.2 sigs.k8s.io/controller-tools v0.23.0 sigs.k8s.io/yaml v1.6.0 @@ -71,7 +68,6 @@ require ( github.com/davidmz/go-pageant v1.0.2 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/dlclark/regexp2 v1.12.0 // indirect - github.com/emicklei/go-restful/v3 v3.13.0 // indirect github.com/emirpasic/gods v1.18.1 // indirect github.com/evanphx/json-patch/v5 v5.9.11 // indirect github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect @@ -85,18 +81,10 @@ require ( github.com/go-logr/zapr v1.3.0 // indirect github.com/go-openapi/jsonpointer v1.0.0 // indirect github.com/go-openapi/jsonreference v1.0.0 // indirect - github.com/go-openapi/swag v0.28.0 // indirect - github.com/go-openapi/swag/cmdutils v0.28.0 // indirect github.com/go-openapi/swag/conv v0.28.0 // indirect - github.com/go-openapi/swag/fileutils v0.28.0 // indirect github.com/go-openapi/swag/jsonutils v0.28.0 // indirect - github.com/go-openapi/swag/loading v0.28.0 // indirect - github.com/go-openapi/swag/mangling v0.28.0 // indirect - github.com/go-openapi/swag/netutils v0.28.0 // indirect github.com/go-openapi/swag/pools v0.28.0 // indirect - github.com/go-openapi/swag/stringutils v0.28.0 // indirect github.com/go-openapi/swag/typeutils v0.28.0 // indirect - github.com/go-openapi/swag/yamlutils v0.28.0 // indirect github.com/go-redis/cache/v9 v9.0.0 // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/gobuffalo/flect v1.0.3 // indirect @@ -198,7 +186,7 @@ require ( k8s.io/gengo/v2 v2.0.0-20260408192533-25e2208e0dc3 // indirect k8s.io/klog/v2 v2.140.0 // indirect k8s.io/kube-aggregator v0.36.1 // indirect - k8s.io/kube-openapi v0.0.0-20260721132016-d427ff9ee9ad // indirect + k8s.io/kube-openapi v0.0.0-20261014044854-ca3452a79603 // indirect k8s.io/kubectl v0.37.1 // indirect k8s.io/kubernetes v1.36.1 // indirect oras.land/oras-go/v2 v2.6.2 // indirect @@ -207,6 +195,7 @@ require ( sigs.k8s.io/kustomize/kyaml v0.21.1 // indirect sigs.k8s.io/randfill v1.0.0 // indirect sigs.k8s.io/structured-merge-diff/v6 v6.4.2 // indirect + sigs.k8s.io/structured-merge-diff/v7 v7.0.0 // indirect ) replace ( diff --git a/go.sum b/go.sum index 9cf3c2088..f1e4fcb17 100644 --- a/go.sum +++ b/go.sum @@ -113,8 +113,6 @@ github.com/dlclark/regexp2 v1.12.0 h1:0j4c5qQmnC6XOWNjP3PIXURXN2gWx76rd3KvgdPkCz github.com/dlclark/regexp2 v1.12.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o= github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE= -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/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= github.com/evanphx/json-patch v5.9.11+incompatible h1:ixHHqfcGvxhWkniF1tWxBHA0yb4Z+d1UQi45df52xW8= @@ -171,31 +169,16 @@ github.com/go-openapi/jsonpointer v1.0.0/go.mod h1:Z3rw7dWu1p9IgitXCFamSlA5lmDik github.com/go-openapi/jsonreference v1.0.0 h1:jlmTr6torcd1YgDQvSfNmRtKzYDO4FGBkrAdlAVWnpY= github.com/go-openapi/jsonreference v1.0.0/go.mod h1:jtwdyGbJk0Xhe5Y+rwtglQP6Sb1WZST4rT32LWB+sv0= github.com/go-openapi/swag v0.28.0 h1:xkgbOSKj6DZziNpyqRRAOt3GJGtgjgsd2RoyT30VWuw= -github.com/go-openapi/swag v0.28.0/go.mod h1:4qYnT3Cqr1p1VknOdPo70evN4rgQnAg6jwApHyxSGIg= -github.com/go-openapi/swag/cmdutils v0.28.0 h1:7TOeNtkYru1SG8Y34tDh9WBbLsMqGnptuxWiHREPZ4Q= -github.com/go-openapi/swag/cmdutils v0.28.0/go.mod h1:Sm1MVFMkF6guJJ+pQqHnQA3N0j9qALV3NxzDSv6bETM= github.com/go-openapi/swag/conv v0.28.0 h1:GtqqbyFe7vR5Y7ehxG9W6/OvrSFdf1OLeTGp40TqxH8= github.com/go-openapi/swag/conv v0.28.0/go.mod h1:mbUE+mzctnhxi864m0Q07SpN8OowD9JhxmxuYvZZD/k= -github.com/go-openapi/swag/fileutils v0.28.0 h1:Z04XWQD7R8Eq+7GnOrjovBxPPmZzsS4gt2H2GPGIViU= -github.com/go-openapi/swag/fileutils v0.28.0/go.mod h1:VvJFZLTZS0AI854gEQz5tk7dBESdLjiNUMSZ/th2ry8= github.com/go-openapi/swag/jsonutils v0.28.0 h1:YIch6FwO7RXzeAnbO8Tu7dWBZeUEH+4nA0HXltVTnv4= github.com/go-openapi/swag/jsonutils v0.28.0/go.mod h1:CYM3WlTUcagR2ZoHdz54di/cbBqt82tuxuXgAjxw+mg= github.com/go-openapi/swag/jsonutils/fixtures_test v0.28.0 h1:qV+VVUAx5Oro8WjVWpZeql7YReTKhT4smR4zhcOQZr0= github.com/go-openapi/swag/jsonutils/fixtures_test v0.28.0/go.mod h1:mofwUWx70wvskwESqRJ//k/9kURmCgyJl5m5Ppoh5kY= -github.com/go-openapi/swag/loading v0.28.0 h1:td8QZdZC9MIYGGSnSPKShKiK22I2tU5UQvuUhIBPRLU= -github.com/go-openapi/swag/loading v0.28.0/go.mod h1:rXB0QiQX5mMveXEA7ouM4KiiM9jVJe4K6BVbwhD1M4k= -github.com/go-openapi/swag/mangling v0.28.0 h1:pH8eyeNO9SLYsTMWJrurnNfKmDa28XrlA+HePVD53VM= -github.com/go-openapi/swag/mangling v0.28.0/go.mod h1:jtBE2+V+3pILxOR7Vgce+Cwp6A2PgZbvVqfNntbVs0w= -github.com/go-openapi/swag/netutils v0.28.0 h1:YXN6TALEi2pzts8/8GNm6T61HTAZsieukGZidap989k= -github.com/go-openapi/swag/netutils v0.28.0/go.mod h1:J+WYyFMLtvtCGqa6jLv+YNUmIKI3ZRQRrvfNDMoQoEQ= github.com/go-openapi/swag/pools v0.28.0 h1:HPMZWSAfce3rdVTFcjFiCIBtDg9h4x2QlRrHipwhxeU= github.com/go-openapi/swag/pools v0.28.0/go.mod h1:kVQefhSK5RWuRe7BXsL8htgBPAMpN7HDGpGEknqugeE= -github.com/go-openapi/swag/stringutils v0.28.0 h1:ixsc9iYgDPubHL/8nSkbnryEHpD2VRlBMLKpQyPXcDU= -github.com/go-openapi/swag/stringutils v0.28.0/go.mod h1:lzRN95CxXmA03XcDWHLOb6nOMcxCqR5rGY0lOgsfRoM= github.com/go-openapi/swag/typeutils v0.28.0 h1:nRBKSBXjDgf01VDPB3fWeD9nQuhCOVeIYAkUx2tbkyY= github.com/go-openapi/swag/typeutils v0.28.0/go.mod h1:Srm0xFNRZ1Y+vCxJclo5qzx8aj+1pAKda/YfFPrG0dQ= -github.com/go-openapi/swag/yamlutils v0.28.0 h1:TV3JXH6DS46KUroDtMLAYHGkdWf5VDq3wVWFirmzROY= -github.com/go-openapi/swag/yamlutils v0.28.0/go.mod h1:x0q/yndZHEgk9Rx3DyDqzFUmHy55KTvIZldvF2dTJXs= github.com/go-openapi/testify/enable/yaml/v2 v2.6.0 h1:gGHwAJ0R/5jU8BEGDbfRNR3hL68dAVi84WuOApp29B0= github.com/go-openapi/testify/enable/yaml/v2 v2.6.0/go.mod h1:tY+St1SGq4NFl0QIqdTY4aEdbChAHxhyB77XQi9iJCo= github.com/go-openapi/testify/v2 v2.6.0 h1:5PKH2HE7YJ/LuRPQGvSxBRlFXNQhSetBLlGAgUEu3ug= @@ -716,8 +699,8 @@ k8s.io/klog/v2 v2.140.0 h1:Tf+J3AH7xnUzZyVVXhTgGhEKnFqye14aadWv7bzXdzc= k8s.io/klog/v2 v2.140.0/go.mod h1:o+/RWfJ6PwpnFn7OyAG3QnO47BFsymfEfrz6XyYSSp0= k8s.io/kube-aggregator v0.36.1 h1:IzNeRsJcTtgsiCyTgCR1pSwWCrXC1QZQWMTcBw18cFQ= k8s.io/kube-aggregator v0.36.1/go.mod h1:ROrIm5irUhVUJsKVCgBAAcXpK5IiqpdCn0Ka7LYMGs4= -k8s.io/kube-openapi v0.0.0-20260721132016-d427ff9ee9ad h1:oXImqH8mQNk7PmvzKhmN3ddJoY6OnyM225MXwGHPm0A= -k8s.io/kube-openapi v0.0.0-20260721132016-d427ff9ee9ad/go.mod h1:0/mqHCVhlumdJ3BhCfnjSZQE037nAhNodh1/hK0T8/I= +k8s.io/kube-openapi v0.0.0-20261014044854-ca3452a79603 h1:9zl8YVFBvuURO1ZrSa1SFWyfbnzyll2ivV163KCkRs0= +k8s.io/kube-openapi v0.0.0-20261014044854-ca3452a79603/go.mod h1:ijAJHxCK/9OftZdcKwI5BHyIeRUeoKe1ldIyM4JHMts= k8s.io/kubectl v0.36.1 h1:96HqS9twIdHM0MlJLTwbo14b9kUKPkOzZ4tlRDLv4qI= k8s.io/kubectl v0.36.1/go.mod h1:/DGPAIewKsFWF9VFgGvkPhao2Ev4SNuE3BioZo8yPbk= k8s.io/kubelet v0.36.1 h1:FcHiG9wv92xerRPNxztuhYWqwS4IilOQNPxTPQewYgo= @@ -748,5 +731,7 @@ sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= sigs.k8s.io/structured-merge-diff/v6 v6.4.2 h1:qdOxHwrl2Kaag1aQEarlYcOA9vSyGCp3CIki3aW8c4Q= sigs.k8s.io/structured-merge-diff/v6 v6.4.2/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= +sigs.k8s.io/structured-merge-diff/v7 v7.0.0 h1:LnKTE1vO6tDITDMVOJ5oCsWauLIAPJnV9egetSfUCpI= +sigs.k8s.io/structured-merge-diff/v7 v7.0.0/go.mod h1:xKoMSgtnJnkfRR+CTNSQ1dBVhkKJR5OQl5RxX/OqHbI= sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= diff --git a/vendor/github.com/emicklei/go-restful/v3/.gitignore b/vendor/github.com/emicklei/go-restful/v3/.gitignore deleted file mode 100644 index 446be09b4..000000000 --- a/vendor/github.com/emicklei/go-restful/v3/.gitignore +++ /dev/null @@ -1,71 +0,0 @@ -# Compiled Object files, Static and Dynamic libs (Shared Objects) -*.o -*.a -*.so - -# Folders -_obj -_test - -# Architecture specific extensions/prefixes -*.[568vq] -[568vq].out - -*.cgo1.go -*.cgo2.c -_cgo_defun.c -_cgo_gotypes.go -_cgo_export.* - -_testmain.go - -*.exe - -restful.html - -*.out - -tmp.prof - -go-restful.test - -examples/restful-basic-authentication - -examples/restful-encoding-filter - -examples/restful-filters - -examples/restful-hello-world - -examples/restful-resource-functions - -examples/restful-serve-static - -examples/restful-user-service - -*.DS_Store -examples/restful-user-resource - -examples/restful-multi-containers - -examples/restful-form-handling - -examples/restful-CORS-filter - -examples/restful-options-filter - -examples/restful-curly-router - -examples/restful-cpuprofiler-service - -examples/restful-pre-post-filters - -curly.prof - -examples/restful-NCSA-logging - -examples/restful-html-template - -s.html -restful-path-tail -.idea diff --git a/vendor/github.com/emicklei/go-restful/v3/.goconvey b/vendor/github.com/emicklei/go-restful/v3/.goconvey deleted file mode 100644 index 8485e986e..000000000 --- a/vendor/github.com/emicklei/go-restful/v3/.goconvey +++ /dev/null @@ -1 +0,0 @@ -ignore \ No newline at end of file diff --git a/vendor/github.com/emicklei/go-restful/v3/CHANGES.md b/vendor/github.com/emicklei/go-restful/v3/CHANGES.md deleted file mode 100644 index 4fcd920ab..000000000 --- a/vendor/github.com/emicklei/go-restful/v3/CHANGES.md +++ /dev/null @@ -1,421 +0,0 @@ -# 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) - -## [v3.12.1] - 2024-05-28 - -- fix misroute when dealing multiple webservice with regex (#549) (thanks Haitao Chen) - -## [v3.12.0] - 2024-03-11 - -- add Flush method #529 (#538) -- fix: Improper handling of empty POST requests (#543) - -## [v3.11.3] - 2024-01-09 - -- better not have 2 tags on one commit - -## [v3.11.1, v3.11.2] - 2024-01-09 - -- fix by restoring custom JSON handler functions (Mike Beaumont #540) - -## [v3.11.0] - 2023-08-19 - -- restored behavior as <= v3.9.0 with option to change path strategy using TrimRightSlashEnabled. - -## [v3.10.2] - 2023-03-09 - DO NOT USE - -- introduced MergePathStrategy to be able to revert behaviour of path concatenation to 3.9.0 - see comment in Readme how to customize this behaviour. - -## [v3.10.1] - 2022-11-19 - DO NOT USE - -- fix broken 3.10.0 by using path package for joining paths - -## [v3.10.0] - 2022-10-11 - BROKEN - -- changed tokenizer to match std route match behavior; do not trimright the path (#511) -- Add MIME_ZIP (#512) -- Add MIME_ZIP and HEADER_ContentDisposition (#513) -- Changed how to get query parameter issue #510 - -## [v3.9.0] - 2022-07-21 - -- add support for http.Handler implementations to work as FilterFunction, issue #504 (thanks to https://github.com/ggicci) - -## [v3.8.0] - 2022-06-06 - -- use exact matching of allowed domain entries, issue #489 (#493) - - this changes fixes [security] Authorization Bypass Through User-Controlled Key - by changing the behaviour of the AllowedDomains setting in the CORS filter. - To support the previous behaviour, the CORS filter type now has a AllowedDomainFunc - callback mechanism which is called when a simple domain match fails. -- add test and fix for POST without body and Content-type, issue #492 (#496) -- [Minor] Bad practice to have a mix of Receiver types. (#491) - -## [v3.7.2] - 2021-11-24 - -- restored FilterChain (#482 by SVilgelm) - - -## [v3.7.1] - 2021-10-04 - -- fix problem with contentEncodingEnabled setting (#479) - -## [v3.7.0] - 2021-09-24 - -- feat(parameter): adds additional openapi mappings (#478) - -## [v3.6.0] - 2021-09-18 - -- add support for vendor extensions (#477 thx erraggy) - -## [v3.5.2] - 2021-07-14 - -- fix removing absent route from webservice (#472) - -## [v3.5.1] - 2021-04-12 - -- fix handling no match access selected path -- remove obsolete field - -## [v3.5.0] - 2021-04-10 - -- add check for wildcard (#463) in CORS -- add access to Route from Request, issue #459 (#462) - -## [v3.4.0] - 2020-11-10 - -- Added OPTIONS to WebService - -## [v3.3.2] - 2020-01-23 - -- Fixed duplicate compression in dispatch. #449 - - -## [v3.3.1] - 2020-08-31 - -- Added check on writer to prevent compression of response twice. #447 - -## [v3.3.0] - 2020-08-19 - -- Enable content encoding on Handle and ServeHTTP (#446) -- List available representations in 406 body (#437) -- Convert to string using rune() (#443) - -## [v3.2.0] - 2020-06-21 - -- 405 Method Not Allowed must have Allow header (#436) (thx Bracken ) -- add field allowedMethodsWithoutContentType (#424) - -## [v3.1.0] - -- support describing response headers (#426) -- fix openapi examples (#425) - -v3.0.0 - -- fix: use request/response resulting from filter chain -- add Go module - Module consumer should use github.com/emicklei/go-restful/v3 as import path - -v2.10.0 - -- support for Custom Verbs (thanks Vinci Xu <277040271@qq.com>) -- fixed static example (thanks Arthur ) -- simplify code (thanks Christian Muehlhaeuser ) -- added JWT HMAC with SHA-512 authentication code example (thanks Amim Knabben ) - -v2.9.6 - -- small optimization in filter code - -v2.11.1 - -- fix WriteError return value (#415) - -v2.11.0 - -- allow prefix and suffix in path variable expression (#414) - -v2.9.6 - -- support google custome verb (#413) - -v2.9.5 - -- fix panic in Response.WriteError if err == nil - -v2.9.4 - -- fix issue #400 , parsing mime type quality -- Route Builder added option for contentEncodingEnabled (#398) - -v2.9.3 - -- Avoid return of 415 Unsupported Media Type when request body is empty (#396) - -v2.9.2 - -- Reduce allocations in per-request methods to improve performance (#395) - -v2.9.1 - -- Fix issue with default responses and invalid status code 0. (#393) - -v2.9.0 - -- add per Route content encoding setting (overrides container setting) - -v2.8.0 - -- add Request.QueryParameters() -- add json-iterator (via build tag) -- disable vgo module (until log is moved) - -v2.7.1 - -- add vgo module - -v2.6.1 - -- add JSONNewDecoderFunc to allow custom JSON Decoder usage (go 1.10+) - -v2.6.0 - -- Make JSR 311 routing and path param processing consistent -- Adding description to RouteBuilder.Reads() -- Update example for Swagger12 and OpenAPI - -2017-09-13 - -- added route condition functions using `.If(func)` in route building. - -2017-02-16 - -- solved issue #304, make operation names unique - -2017-01-30 - - [IMPORTANT] For swagger users, change your import statement to: - swagger "github.com/emicklei/go-restful-swagger12" - -- moved swagger 1.2 code to go-restful-swagger12 -- created TAG 2.0.0 - -2017-01-27 - -- remove defer request body close -- expose Dispatch for testing filters and Routefunctions -- swagger response model cannot be array -- created TAG 1.0.0 - -2016-12-22 - -- (API change) Remove code related to caching request content. Removes SetCacheReadEntity(doCache bool) - -2016-11-26 - -- Default change! now use CurlyRouter (was RouterJSR311) -- Default change! no more caching of request content -- Default change! do not recover from panics - -2016-09-22 - -- fix the DefaultRequestContentType feature - -2016-02-14 - -- take the qualify factor of the Accept header mediatype into account when deciding the contentype of the response -- add constructors for custom entity accessors for xml and json - -2015-09-27 - -- rename new WriteStatusAnd... to WriteHeaderAnd... for consistency - -2015-09-25 - -- fixed problem with changing Header after WriteHeader (issue 235) - -2015-09-14 - -- changed behavior of WriteHeader (immediate write) and WriteEntity (no status write) -- added support for custom EntityReaderWriters. - -2015-08-06 - -- add support for reading entities from compressed request content -- use sync.Pool for compressors of http response and request body -- add Description to Parameter for documentation in Swagger UI - -2015-03-20 - -- add configurable logging - -2015-03-18 - -- if not specified, the Operation is derived from the Route function - -2015-03-17 - -- expose Parameter creation functions -- make trace logger an interface -- fix OPTIONSFilter -- customize rendering of ServiceError -- JSR311 router now handles wildcards -- add Notes to Route - -2014-11-27 - -- (api add) PrettyPrint per response. (as proposed in #167) - -2014-11-12 - -- (api add) ApiVersion(.) for documentation in Swagger UI - -2014-11-10 - -- (api change) struct fields tagged with "description" show up in Swagger UI - -2014-10-31 - -- (api change) ReturnsError -> Returns -- (api add) RouteBuilder.Do(aBuilder) for DRY use of RouteBuilder -- fix swagger nested structs -- sort Swagger response messages by code - -2014-10-23 - -- (api add) ReturnsError allows you to document Http codes in swagger -- fixed problem with greedy CurlyRouter -- (api add) Access-Control-Max-Age in CORS -- add tracing functionality (injectable) for debugging purposes -- support JSON parse 64bit int -- fix empty parameters for swagger -- WebServicesUrl is now optional for swagger -- fixed duplicate AccessControlAllowOrigin in CORS -- (api change) expose ServeMux in container -- (api add) added AllowedDomains in CORS -- (api add) ParameterNamed for detailed documentation - -2014-04-16 - -- (api add) expose constructor of Request for testing. - -2014-06-27 - -- (api add) ParameterNamed gives access to a Parameter definition and its data (for further specification). -- (api add) SetCacheReadEntity allow scontrol over whether or not the request body is being cached (default true for compatibility reasons). - -2014-07-03 - -- (api add) CORS can be configured with a list of allowed domains - -2014-03-12 - -- (api add) Route path parameters can use wildcard or regular expressions. (requires CurlyRouter) - -2014-02-26 - -- (api add) Request now provides information about the matched Route, see method SelectedRoutePath - -2014-02-17 - -- (api change) renamed parameter constants (go-lint checks) - -2014-01-10 - -- (api add) support for CloseNotify, see http://golang.org/pkg/net/http/#CloseNotifier - -2014-01-07 - -- (api change) Write* methods in Response now return the error or nil. -- added example of serving HTML from a Go template. -- fixed comparing Allowed headers in CORS (is now case-insensitive) - -2013-11-13 - -- (api add) Response knows how many bytes are written to the response body. - -2013-10-29 - -- (api add) RecoverHandler(handler RecoverHandleFunction) to change how panic recovery is handled. Default behavior is to log and return a stacktrace. This may be a security issue as it exposes sourcecode information. - -2013-10-04 - -- (api add) Response knows what HTTP status has been written -- (api add) Request can have attributes (map of string->interface, also called request-scoped variables - -2013-09-12 - -- (api change) Router interface simplified -- Implemented CurlyRouter, a Router that does not use|allow regular expressions in paths - -2013-08-05 - - add OPTIONS support - - add CORS support - -2013-08-27 - -- fixed some reported issues (see github) -- (api change) deprecated use of WriteError; use WriteErrorString instead - -2014-04-15 - -- (fix) v1.0.1 tag: fix Issue 111: WriteErrorString - -2013-08-08 - -- (api add) Added implementation Container: a WebServices collection with its own http.ServeMux allowing multiple endpoints per program. Existing uses of go-restful will register their services to the DefaultContainer. -- (api add) the swagger package has be extended to have a UI per container. -- if panic is detected then a small stack trace is printed (thanks to runner-mei) -- (api add) WriteErrorString to Response - -Important API changes: - -- (api remove) package variable DoNotRecover no longer works ; use restful.DefaultContainer.DoNotRecover(true) instead. -- (api remove) package variable EnableContentEncoding no longer works ; use restful.DefaultContainer.EnableContentEncoding(true) instead. - - -2013-07-06 - -- (api add) Added support for response encoding (gzip and deflate(zlib)). This feature is disabled on default (for backwards compatibility). Use restful.EnableContentEncoding = true in your initialization to enable this feature. - -2013-06-19 - -- (improve) DoNotRecover option, moved request body closer, improved ReadEntity - -2013-06-03 - -- (api change) removed Dispatcher interface, hide PathExpression -- changed receiver names of type functions to be more idiomatic Go - -2013-06-02 - -- (optimize) Cache the RegExp compilation of Paths. - -2013-05-22 - -- (api add) Added support for request/response filter functions - -2013-05-18 - - -- (api add) Added feature to change the default Http Request Dispatch function (travis cline) -- (api change) Moved Swagger Webservice to swagger package (see example restful-user) - -[2012-11-14 .. 2013-05-18> - -- See https://github.com/emicklei/go-restful/commits - -2012-11-14 - -- Initial commit - - diff --git a/vendor/github.com/emicklei/go-restful/v3/LICENSE b/vendor/github.com/emicklei/go-restful/v3/LICENSE deleted file mode 100644 index ece7ec61e..000000000 --- a/vendor/github.com/emicklei/go-restful/v3/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -Copyright (c) 2012,2013 Ernest Micklei - -MIT License - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/vendor/github.com/emicklei/go-restful/v3/Makefile b/vendor/github.com/emicklei/go-restful/v3/Makefile deleted file mode 100644 index 16d0b80bb..000000000 --- a/vendor/github.com/emicklei/go-restful/v3/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -all: test - -test: - go vet . - go test -cover -v . - -ex: - find ./examples -type f -name "*.go" | xargs -I {} go build -o /tmp/ignore {} \ No newline at end of file diff --git a/vendor/github.com/emicklei/go-restful/v3/README.md b/vendor/github.com/emicklei/go-restful/v3/README.md deleted file mode 100644 index 50a79ab69..000000000 --- a/vendor/github.com/emicklei/go-restful/v3/README.md +++ /dev/null @@ -1,111 +0,0 @@ -go-restful -========== -package for building REST-style Web Services using Google Go - -[![Go Report Card](https://goreportcard.com/badge/github.com/emicklei/go-restful)](https://goreportcard.com/report/github.com/emicklei/go-restful) -[![Go Reference](https://pkg.go.dev/badge/github.com/emicklei/go-restful.svg)](https://pkg.go.dev/github.com/emicklei/go-restful/v3) -[![codecov](https://codecov.io/gh/emicklei/go-restful/branch/master/graph/badge.svg)](https://codecov.io/gh/emicklei/go-restful) - -- [Code examples use v3](https://github.com/emicklei/go-restful/tree/v3/examples) - -REST asks developers to use HTTP methods explicitly and in a way that's consistent with the protocol definition. This basic REST design principle establishes a one-to-one mapping between create, read, update, and delete (CRUD) operations and HTTP methods. According to this mapping: - -- GET = Retrieve a representation of a resource -- POST = Create if you are sending content to the server to create a subordinate of the specified resource collection, using some server-side algorithm. -- PUT = Create if you are sending the full content of the specified resource (URI). -- PUT = Update if you are updating the full content of the specified resource. -- DELETE = Delete if you are requesting the server to delete the resource -- PATCH = Update partial content of a resource -- OPTIONS = Get information about the communication options for the request URI - -### Usage - -#### Without Go Modules - -All versions up to `v2.*.*` (on the master) are not supporting Go modules. - -``` -import ( - restful "github.com/emicklei/go-restful" -) -``` - -#### Using Go Modules - -As of version `v3.0.0` (on the v3 branch), this package supports Go modules. - -``` -import ( - restful "github.com/emicklei/go-restful/v3" -) -``` - -### Example - -```Go -ws := new(restful.WebService) -ws. - Path("/users"). - Consumes(restful.MIME_XML, restful.MIME_JSON). - Produces(restful.MIME_JSON, restful.MIME_XML) - -ws.Route(ws.GET("/{user-id}").To(u.findUser). - Doc("get a user"). - Param(ws.PathParameter("user-id", "identifier of the user").DataType("string")). - Writes(User{})) -... - -func (u UserResource) findUser(request *restful.Request, response *restful.Response) { - id := request.PathParameter("user-id") - ... -} -``` - -[Full API of a UserResource](https://github.com/emicklei/go-restful/blob/v3/examples/user-resource/restful-user-resource.go) - -### Features - -- Routes for request → function mapping with path parameter (e.g. {id} but also prefix_{var} and {var}_suffix) support -- Configurable router: - - (default) Fast routing algorithm that allows static elements, [google custom method](https://cloud.google.com/apis/design/custom_methods), regular expressions and dynamic parameters in the URL path (e.g. /resource/name:customVerb, /meetings/{id} or /static/{subpath:*}) - - Routing algorithm after [JSR311](http://jsr311.java.net/nonav/releases/1.1/spec/spec.html) that is implemented using (but does **not** accept) regular expressions -- Request API for reading structs from JSON/XML and accessing parameters (path,query,header) -- Response API for writing structs to JSON/XML and setting headers -- Customizable encoding using EntityReaderWriter registration -- Filters for intercepting the request → response flow on Service or Route level -- Request-scoped variables using attributes -- Containers for WebServices on different HTTP endpoints -- Content encoding (gzip,deflate) of request and response payloads -- Automatic responses on OPTIONS (using a filter) -- Automatic CORS request handling (using a filter) -- API declaration for Swagger UI ([go-restful-openapi](https://github.com/emicklei/go-restful-openapi)) -- Panic recovery to produce HTTP 500, customizable using RecoverHandler(...) -- Route errors produce HTTP 404/405/406/415 errors, customizable using ServiceErrorHandler(...) -- 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. - -- Router algorithm -- Panic recovery -- JSON decoder -- Trace logging -- Compression -- Encoders for other serializers -- Use the package variable `TrimRightSlashEnabled` (default true) to control the behavior of matching routes that end with a slash `/` - -## Resources - -- [Example programs](./examples) -- [Example posted on blog](http://ernestmicklei.com/2012/11/go-restful-first-working-example/) -- [Design explained on blog](http://ernestmicklei.com/2012/11/go-restful-api-design/) -- [sourcegraph](https://sourcegraph.com/github.com/emicklei/go-restful) -- [showcase: Zazkia - tcp proxy for testing resiliency](https://github.com/emicklei/zazkia) -- [showcase: Mora - MongoDB REST Api server](https://github.com/emicklei/mora) - -Type ```git shortlog -s``` for a full list of contributors. - -© 2012 - 2023, http://ernestmicklei.com. MIT License. Contributions are welcome. diff --git a/vendor/github.com/emicklei/go-restful/v3/SECURITY.md b/vendor/github.com/emicklei/go-restful/v3/SECURITY.md deleted file mode 100644 index 810d3b510..000000000 --- a/vendor/github.com/emicklei/go-restful/v3/SECURITY.md +++ /dev/null @@ -1,13 +0,0 @@ -# Security Policy - -## Supported Versions - -| Version | Supported | -| ------- | ------------------ | -| v3.7.x | :white_check_mark: | -| < v3.0.1 | :x: | - -## Reporting a Vulnerability - -Create an Issue and put the label `[security]` in the title of the issue. -Valid reported security issues are expected to be solved within a week. diff --git a/vendor/github.com/emicklei/go-restful/v3/Srcfile b/vendor/github.com/emicklei/go-restful/v3/Srcfile deleted file mode 100644 index 16fd18689..000000000 --- a/vendor/github.com/emicklei/go-restful/v3/Srcfile +++ /dev/null @@ -1 +0,0 @@ -{"SkipDirs": ["examples"]} diff --git a/vendor/github.com/emicklei/go-restful/v3/bench_test.sh b/vendor/github.com/emicklei/go-restful/v3/bench_test.sh deleted file mode 100644 index 47ffbe4ac..000000000 --- a/vendor/github.com/emicklei/go-restful/v3/bench_test.sh +++ /dev/null @@ -1,10 +0,0 @@ -#go test -run=none -file bench_test.go -test.bench . -cpuprofile=bench_test.out - -go test -c -./go-restful.test -test.run=none -test.cpuprofile=tmp.prof -test.bench=BenchmarkMany -./go-restful.test -test.run=none -test.cpuprofile=curly.prof -test.bench=BenchmarkManyCurly - -#go tool pprof go-restful.test tmp.prof -go tool pprof go-restful.test curly.prof - - diff --git a/vendor/github.com/emicklei/go-restful/v3/compress.go b/vendor/github.com/emicklei/go-restful/v3/compress.go deleted file mode 100644 index 80adf55fd..000000000 --- a/vendor/github.com/emicklei/go-restful/v3/compress.go +++ /dev/null @@ -1,137 +0,0 @@ -package restful - -// Copyright 2013 Ernest Micklei. All rights reserved. -// Use of this source code is governed by a license -// that can be found in the LICENSE file. - -import ( - "bufio" - "compress/gzip" - "compress/zlib" - "errors" - "io" - "net" - "net/http" - "strings" -) - -// OBSOLETE : use restful.DefaultContainer.EnableContentEncoding(true) to change this setting. -var EnableContentEncoding = false - -// CompressingResponseWriter is a http.ResponseWriter that can perform content encoding (gzip and zlib) -type CompressingResponseWriter struct { - writer http.ResponseWriter - compressor io.WriteCloser - encoding string -} - -// Header is part of http.ResponseWriter interface -func (c *CompressingResponseWriter) Header() http.Header { - return c.writer.Header() -} - -// WriteHeader is part of http.ResponseWriter interface -func (c *CompressingResponseWriter) WriteHeader(status int) { - c.writer.WriteHeader(status) -} - -// Write is part of http.ResponseWriter interface -// It is passed through the compressor -func (c *CompressingResponseWriter) Write(bytes []byte) (int, error) { - if c.isCompressorClosed() { - return -1, errors.New("Compressing error: tried to write data using closed compressor") - } - return c.compressor.Write(bytes) -} - -// CloseNotify is part of http.CloseNotifier interface -func (c *CompressingResponseWriter) CloseNotify() <-chan bool { - return c.writer.(http.CloseNotifier).CloseNotify() -} - -// Flush is part of http.Flusher interface. Noop if the underlying writer doesn't support it. -func (c *CompressingResponseWriter) Flush() { - flusher, ok := c.writer.(http.Flusher) - if !ok { - // writer doesn't support http.Flusher interface - return - } - flusher.Flush() -} - -// Close the underlying compressor -func (c *CompressingResponseWriter) Close() error { - if c.isCompressorClosed() { - return errors.New("Compressing error: tried to close already closed compressor") - } - - c.compressor.Close() - if ENCODING_GZIP == c.encoding { - currentCompressorProvider.ReleaseGzipWriter(c.compressor.(*gzip.Writer)) - } - if ENCODING_DEFLATE == c.encoding { - currentCompressorProvider.ReleaseZlibWriter(c.compressor.(*zlib.Writer)) - } - // gc hint needed? - c.compressor = nil - return nil -} - -func (c *CompressingResponseWriter) isCompressorClosed() bool { - return nil == c.compressor -} - -// Hijack implements the Hijacker interface -// This is especially useful when combining Container.EnabledContentEncoding -// in combination with websockets (for instance gorilla/websocket) -func (c *CompressingResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) { - hijacker, ok := c.writer.(http.Hijacker) - if !ok { - return nil, nil, errors.New("ResponseWriter doesn't support Hijacker interface") - } - return hijacker.Hijack() -} - -// WantsCompressedResponse reads the Accept-Encoding header to see if and which encoding is requested. -// It also inspects the httpWriter whether its content-encoding is already set (non-empty). -func wantsCompressedResponse(httpRequest *http.Request, httpWriter http.ResponseWriter) (bool, string) { - if contentEncoding := httpWriter.Header().Get(HEADER_ContentEncoding); contentEncoding != "" { - return false, "" - } - header := httpRequest.Header.Get(HEADER_AcceptEncoding) - gi := strings.Index(header, ENCODING_GZIP) - zi := strings.Index(header, ENCODING_DEFLATE) - // use in order of appearance - if gi == -1 { - return zi != -1, ENCODING_DEFLATE - } else if zi == -1 { - return gi != -1, ENCODING_GZIP - } else { - if gi < zi { - return true, ENCODING_GZIP - } - return true, ENCODING_DEFLATE - } -} - -// NewCompressingResponseWriter create a CompressingResponseWriter for a known encoding = {gzip,deflate} -func NewCompressingResponseWriter(httpWriter http.ResponseWriter, encoding string) (*CompressingResponseWriter, error) { - httpWriter.Header().Set(HEADER_ContentEncoding, encoding) - c := new(CompressingResponseWriter) - c.writer = httpWriter - var err error - if ENCODING_GZIP == encoding { - w := currentCompressorProvider.AcquireGzipWriter() - w.Reset(httpWriter) - c.compressor = w - c.encoding = ENCODING_GZIP - } else if ENCODING_DEFLATE == encoding { - w := currentCompressorProvider.AcquireZlibWriter() - w.Reset(httpWriter) - c.compressor = w - c.encoding = ENCODING_DEFLATE - } else { - return nil, errors.New("Unknown encoding:" + encoding) - } - return c, err -} diff --git a/vendor/github.com/emicklei/go-restful/v3/compressor_cache.go b/vendor/github.com/emicklei/go-restful/v3/compressor_cache.go deleted file mode 100644 index ee426010a..000000000 --- a/vendor/github.com/emicklei/go-restful/v3/compressor_cache.go +++ /dev/null @@ -1,103 +0,0 @@ -package restful - -// Copyright 2015 Ernest Micklei. All rights reserved. -// Use of this source code is governed by a license -// that can be found in the LICENSE file. - -import ( - "compress/gzip" - "compress/zlib" -) - -// BoundedCachedCompressors is a CompressorProvider that uses a cache with a fixed amount -// of writers and readers (resources). -// If a new resource is acquired and all are in use, it will return a new unmanaged resource. -type BoundedCachedCompressors struct { - gzipWriters chan *gzip.Writer - gzipReaders chan *gzip.Reader - zlibWriters chan *zlib.Writer - writersCapacity int - readersCapacity int -} - -// NewBoundedCachedCompressors returns a new, with filled cache, BoundedCachedCompressors. -func NewBoundedCachedCompressors(writersCapacity, readersCapacity int) *BoundedCachedCompressors { - b := &BoundedCachedCompressors{ - gzipWriters: make(chan *gzip.Writer, writersCapacity), - gzipReaders: make(chan *gzip.Reader, readersCapacity), - zlibWriters: make(chan *zlib.Writer, writersCapacity), - writersCapacity: writersCapacity, - readersCapacity: readersCapacity, - } - for ix := 0; ix < writersCapacity; ix++ { - b.gzipWriters <- newGzipWriter() - b.zlibWriters <- newZlibWriter() - } - for ix := 0; ix < readersCapacity; ix++ { - b.gzipReaders <- newGzipReader() - } - return b -} - -// AcquireGzipWriter returns an resettable *gzip.Writer. Needs to be released. -func (b *BoundedCachedCompressors) AcquireGzipWriter() *gzip.Writer { - var writer *gzip.Writer - select { - case writer, _ = <-b.gzipWriters: - default: - // return a new unmanaged one - writer = newGzipWriter() - } - return writer -} - -// ReleaseGzipWriter accepts a writer (does not have to be one that was cached) -// only when the cache has room for it. It will ignore it otherwise. -func (b *BoundedCachedCompressors) ReleaseGzipWriter(w *gzip.Writer) { - // forget the unmanaged ones - if len(b.gzipWriters) < b.writersCapacity { - b.gzipWriters <- w - } -} - -// AcquireGzipReader returns a *gzip.Reader. Needs to be released. -func (b *BoundedCachedCompressors) AcquireGzipReader() *gzip.Reader { - var reader *gzip.Reader - select { - case reader, _ = <-b.gzipReaders: - default: - // return a new unmanaged one - reader = newGzipReader() - } - return reader -} - -// ReleaseGzipReader accepts a reader (does not have to be one that was cached) -// only when the cache has room for it. It will ignore it otherwise. -func (b *BoundedCachedCompressors) ReleaseGzipReader(r *gzip.Reader) { - // forget the unmanaged ones - if len(b.gzipReaders) < b.readersCapacity { - b.gzipReaders <- r - } -} - -// AcquireZlibWriter returns an resettable *zlib.Writer. Needs to be released. -func (b *BoundedCachedCompressors) AcquireZlibWriter() *zlib.Writer { - var writer *zlib.Writer - select { - case writer, _ = <-b.zlibWriters: - default: - // return a new unmanaged one - writer = newZlibWriter() - } - return writer -} - -// ReleaseZlibWriter accepts a writer (does not have to be one that was cached) -// only when the cache has room for it. It will ignore it otherwise. -func (b *BoundedCachedCompressors) ReleaseZlibWriter(w *zlib.Writer) { - // forget the unmanaged ones - if len(b.zlibWriters) < b.writersCapacity { - b.zlibWriters <- w - } -} diff --git a/vendor/github.com/emicklei/go-restful/v3/compressor_pools.go b/vendor/github.com/emicklei/go-restful/v3/compressor_pools.go deleted file mode 100644 index d866ce64b..000000000 --- a/vendor/github.com/emicklei/go-restful/v3/compressor_pools.go +++ /dev/null @@ -1,91 +0,0 @@ -package restful - -// Copyright 2015 Ernest Micklei. All rights reserved. -// Use of this source code is governed by a license -// that can be found in the LICENSE file. - -import ( - "bytes" - "compress/gzip" - "compress/zlib" - "sync" -) - -// SyncPoolCompessors is a CompressorProvider that use the standard sync.Pool. -type SyncPoolCompessors struct { - GzipWriterPool *sync.Pool - GzipReaderPool *sync.Pool - ZlibWriterPool *sync.Pool -} - -// NewSyncPoolCompessors returns a new ("empty") SyncPoolCompessors. -func NewSyncPoolCompessors() *SyncPoolCompessors { - return &SyncPoolCompessors{ - GzipWriterPool: &sync.Pool{ - New: func() interface{} { return newGzipWriter() }, - }, - GzipReaderPool: &sync.Pool{ - New: func() interface{} { return newGzipReader() }, - }, - ZlibWriterPool: &sync.Pool{ - New: func() interface{} { return newZlibWriter() }, - }, - } -} - -func (s *SyncPoolCompessors) AcquireGzipWriter() *gzip.Writer { - return s.GzipWriterPool.Get().(*gzip.Writer) -} - -func (s *SyncPoolCompessors) ReleaseGzipWriter(w *gzip.Writer) { - s.GzipWriterPool.Put(w) -} - -func (s *SyncPoolCompessors) AcquireGzipReader() *gzip.Reader { - return s.GzipReaderPool.Get().(*gzip.Reader) -} - -func (s *SyncPoolCompessors) ReleaseGzipReader(r *gzip.Reader) { - s.GzipReaderPool.Put(r) -} - -func (s *SyncPoolCompessors) AcquireZlibWriter() *zlib.Writer { - return s.ZlibWriterPool.Get().(*zlib.Writer) -} - -func (s *SyncPoolCompessors) ReleaseZlibWriter(w *zlib.Writer) { - s.ZlibWriterPool.Put(w) -} - -func newGzipWriter() *gzip.Writer { - // create with an empty bytes writer; it will be replaced before using the gzipWriter - writer, err := gzip.NewWriterLevel(new(bytes.Buffer), gzip.BestSpeed) - if err != nil { - panic(err.Error()) - } - return writer -} - -func newGzipReader() *gzip.Reader { - // create with an empty reader (but with GZIP header); it will be replaced before using the gzipReader - // we can safely use currentCompressProvider because it is set on package initialization. - w := currentCompressorProvider.AcquireGzipWriter() - defer currentCompressorProvider.ReleaseGzipWriter(w) - b := new(bytes.Buffer) - w.Reset(b) - w.Flush() - w.Close() - reader, err := gzip.NewReader(bytes.NewReader(b.Bytes())) - if err != nil { - panic(err.Error()) - } - return reader -} - -func newZlibWriter() *zlib.Writer { - writer, err := zlib.NewWriterLevel(new(bytes.Buffer), gzip.BestSpeed) - if err != nil { - panic(err.Error()) - } - return writer -} diff --git a/vendor/github.com/emicklei/go-restful/v3/compressors.go b/vendor/github.com/emicklei/go-restful/v3/compressors.go deleted file mode 100644 index 9db4a8c8e..000000000 --- a/vendor/github.com/emicklei/go-restful/v3/compressors.go +++ /dev/null @@ -1,54 +0,0 @@ -package restful - -// Copyright 2015 Ernest Micklei. All rights reserved. -// Use of this source code is governed by a license -// that can be found in the LICENSE file. - -import ( - "compress/gzip" - "compress/zlib" -) - -// CompressorProvider describes a component that can provider compressors for the std methods. -type CompressorProvider interface { - // Returns a *gzip.Writer which needs to be released later. - // Before using it, call Reset(). - AcquireGzipWriter() *gzip.Writer - - // Releases an acquired *gzip.Writer. - ReleaseGzipWriter(w *gzip.Writer) - - // Returns a *gzip.Reader which needs to be released later. - AcquireGzipReader() *gzip.Reader - - // Releases an acquired *gzip.Reader. - ReleaseGzipReader(w *gzip.Reader) - - // Returns a *zlib.Writer which needs to be released later. - // Before using it, call Reset(). - AcquireZlibWriter() *zlib.Writer - - // Releases an acquired *zlib.Writer. - ReleaseZlibWriter(w *zlib.Writer) -} - -// DefaultCompressorProvider is the actual provider of compressors (zlib or gzip). -var currentCompressorProvider CompressorProvider - -func init() { - currentCompressorProvider = NewSyncPoolCompessors() -} - -// CurrentCompressorProvider returns the current CompressorProvider. -// It is initialized using a SyncPoolCompessors. -func CurrentCompressorProvider() CompressorProvider { - return currentCompressorProvider -} - -// SetCompressorProvider sets the actual provider of compressors (zlib or gzip). -func SetCompressorProvider(p CompressorProvider) { - if p == nil { - panic("cannot set compressor provider to nil") - } - currentCompressorProvider = p -} diff --git a/vendor/github.com/emicklei/go-restful/v3/constants.go b/vendor/github.com/emicklei/go-restful/v3/constants.go deleted file mode 100644 index 2328bde6c..000000000 --- a/vendor/github.com/emicklei/go-restful/v3/constants.go +++ /dev/null @@ -1,32 +0,0 @@ -package restful - -// Copyright 2013 Ernest Micklei. All rights reserved. -// Use of this source code is governed by a license -// that can be found in the LICENSE file. - -const ( - MIME_XML = "application/xml" // Accept or Content-Type used in Consumes() and/or Produces() - MIME_JSON = "application/json" // Accept or Content-Type used in Consumes() and/or Produces() - MIME_ZIP = "application/zip" // Accept or Content-Type used in Consumes() and/or Produces() - MIME_OCTET = "application/octet-stream" // If Content-Type is not present in request, use the default - - HEADER_Allow = "Allow" - HEADER_Accept = "Accept" - HEADER_Origin = "Origin" - HEADER_ContentType = "Content-Type" - HEADER_ContentDisposition = "Content-Disposition" - HEADER_LastModified = "Last-Modified" - HEADER_AcceptEncoding = "Accept-Encoding" - HEADER_ContentEncoding = "Content-Encoding" - HEADER_AccessControlExposeHeaders = "Access-Control-Expose-Headers" - HEADER_AccessControlRequestMethod = "Access-Control-Request-Method" - HEADER_AccessControlRequestHeaders = "Access-Control-Request-Headers" - HEADER_AccessControlAllowMethods = "Access-Control-Allow-Methods" - HEADER_AccessControlAllowOrigin = "Access-Control-Allow-Origin" - HEADER_AccessControlAllowCredentials = "Access-Control-Allow-Credentials" - HEADER_AccessControlAllowHeaders = "Access-Control-Allow-Headers" - HEADER_AccessControlMaxAge = "Access-Control-Max-Age" - - ENCODING_GZIP = "gzip" - ENCODING_DEFLATE = "deflate" -) diff --git a/vendor/github.com/emicklei/go-restful/v3/container.go b/vendor/github.com/emicklei/go-restful/v3/container.go deleted file mode 100644 index dd56246dd..000000000 --- a/vendor/github.com/emicklei/go-restful/v3/container.go +++ /dev/null @@ -1,450 +0,0 @@ -package restful - -// Copyright 2013 Ernest Micklei. All rights reserved. -// Use of this source code is governed by a license -// that can be found in the LICENSE file. - -import ( - "bytes" - "errors" - "fmt" - "net/http" - "os" - "runtime" - "strings" - "sync" - - "github.com/emicklei/go-restful/v3/log" -) - -// Container holds a collection of WebServices and a http.ServeMux to dispatch http requests. -// The requests are further dispatched to routes of WebServices using a RouteSelector -type Container struct { - webServicesLock sync.RWMutex - webServices []*WebService - ServeMux *http.ServeMux - isRegisteredOnRoot bool - containerFilters []FilterFunction - doNotRecover bool // default is true - recoverHandleFunc RecoverHandleFunction - serviceErrorHandleFunc ServiceErrorHandleFunction - router RouteSelector // default is a CurlyRouter (RouterJSR311 is a slower alternative) - contentEncodingEnabled bool // default is false -} - -// NewContainer creates a new Container using a new ServeMux and default router (CurlyRouter) -func NewContainer() *Container { - return &Container{ - webServices: []*WebService{}, - ServeMux: http.NewServeMux(), - isRegisteredOnRoot: false, - containerFilters: []FilterFunction{}, - doNotRecover: true, - recoverHandleFunc: logStackOnRecover, - serviceErrorHandleFunc: writeServiceError, - router: CurlyRouter{}, - contentEncodingEnabled: false} -} - -// RecoverHandleFunction declares functions that can be used to handle a panic situation. -// The first argument is what recover() returns. The second must be used to communicate an error response. -type RecoverHandleFunction func(interface{}, http.ResponseWriter) - -// RecoverHandler changes the default function (logStackOnRecover) to be called -// when a panic is detected. DoNotRecover must be have its default value (=false). -func (c *Container) RecoverHandler(handler RecoverHandleFunction) { - c.recoverHandleFunc = handler -} - -// ServiceErrorHandleFunction declares functions that can be used to handle a service error situation. -// The first argument is the service error, the second is the request that resulted in the error and -// the third must be used to communicate an error response. -type ServiceErrorHandleFunction func(ServiceError, *Request, *Response) - -// ServiceErrorHandler changes the default function (writeServiceError) to be called -// when a ServiceError is detected. -func (c *Container) ServiceErrorHandler(handler ServiceErrorHandleFunction) { - c.serviceErrorHandleFunc = handler -} - -// DoNotRecover controls whether panics will be caught to return HTTP 500. -// If set to true, Route functions are responsible for handling any error situation. -// Default value is true. -func (c *Container) DoNotRecover(doNot bool) { - c.doNotRecover = doNot -} - -// Router changes the default Router (currently CurlyRouter) -func (c *Container) Router(aRouter RouteSelector) { - c.router = aRouter -} - -// EnableContentEncoding (default=false) allows for GZIP or DEFLATE encoding of responses. -func (c *Container) EnableContentEncoding(enabled bool) { - c.contentEncodingEnabled = enabled -} - -// Add a WebService to the Container. It will detect duplicate root paths and exit in that case. -func (c *Container) Add(service *WebService) *Container { - c.webServicesLock.Lock() - defer c.webServicesLock.Unlock() - - // if rootPath was not set then lazy initialize it - if len(service.rootPath) == 0 { - service.Path("/") - } - - // cannot have duplicate root paths - for _, each := range c.webServices { - if each.RootPath() == service.RootPath() { - log.Printf("WebService with duplicate root path detected:['%v']", each) - os.Exit(1) - } - } - - // If not registered on root then add specific mapping - if !c.isRegisteredOnRoot { - c.isRegisteredOnRoot = c.addHandler(service, c.ServeMux) - } - c.webServices = append(c.webServices, service) - return c -} - -// addHandler may set a new HandleFunc for the serveMux -// this function must run inside the critical region protected by the webServicesLock. -// returns true if the function was registered on root ("/") -func (c *Container) addHandler(service *WebService, serveMux *http.ServeMux) bool { - pattern := fixedPrefixPath(service.RootPath()) - // check if root path registration is needed - if "/" == pattern || "" == pattern { - serveMux.HandleFunc("/", c.dispatch) - return true - } - // detect if registration already exists - alreadyMapped := false - for _, each := range c.webServices { - if each.RootPath() == service.RootPath() { - alreadyMapped = true - break - } - } - if !alreadyMapped { - serveMux.HandleFunc(pattern, c.dispatch) - if !strings.HasSuffix(pattern, "/") { - serveMux.HandleFunc(pattern+"/", c.dispatch) - } - } - return false -} - -func (c *Container) Remove(ws *WebService) error { - if c.ServeMux == http.DefaultServeMux { - errMsg := fmt.Sprintf("cannot remove a WebService from a Container using the DefaultServeMux: ['%v']", ws) - log.Print(errMsg) - return errors.New(errMsg) - } - c.webServicesLock.Lock() - defer c.webServicesLock.Unlock() - // build a new ServeMux and re-register all WebServices - newServeMux := http.NewServeMux() - newServices := []*WebService{} - newIsRegisteredOnRoot := false - for _, each := range c.webServices { - if each.rootPath != ws.rootPath { - // If not registered on root then add specific mapping - if !newIsRegisteredOnRoot { - newIsRegisteredOnRoot = c.addHandler(each, newServeMux) - } - newServices = append(newServices, each) - } - } - c.webServices, c.ServeMux, c.isRegisteredOnRoot = newServices, newServeMux, newIsRegisteredOnRoot - return nil -} - -// logStackOnRecover is the default RecoverHandleFunction and is called -// when DoNotRecover is false and the recoverHandleFunc is not set for the container. -// Default implementation logs the stacktrace and writes the stacktrace on the response. -// This may be a security issue as it exposes sourcecode information. -func logStackOnRecover(panicReason interface{}, httpWriter http.ResponseWriter) { - var buffer bytes.Buffer - buffer.WriteString(fmt.Sprintf("recover from panic situation: - %v\r\n", panicReason)) - for i := 2; ; i += 1 { - _, file, line, ok := runtime.Caller(i) - if !ok { - break - } - buffer.WriteString(fmt.Sprintf(" %s:%d\r\n", file, line)) - } - log.Print(buffer.String()) - httpWriter.WriteHeader(http.StatusInternalServerError) - httpWriter.Write(buffer.Bytes()) -} - -// writeServiceError is the default ServiceErrorHandleFunction and is called -// when a ServiceError is returned during route selection. Default implementation -// calls resp.WriteErrorString(err.Code, err.Message) -func writeServiceError(err ServiceError, req *Request, resp *Response) { - for header, values := range err.Header { - for _, value := range values { - resp.Header().Add(header, value) - } - } - resp.WriteErrorString(err.Code, err.Message) -} - -// Dispatch the incoming Http Request to a matching WebService. -func (c *Container) Dispatch(httpWriter http.ResponseWriter, httpRequest *http.Request) { - if httpWriter == nil { - panic("httpWriter cannot be nil") - } - if httpRequest == nil { - panic("httpRequest cannot be nil") - } - c.dispatch(httpWriter, httpRequest) -} - -// Dispatch the incoming Http Request to a matching WebService. -func (c *Container) dispatch(httpWriter http.ResponseWriter, httpRequest *http.Request) { - // so we can assign a compressing one later - writer := httpWriter - - // CompressingResponseWriter should be closed after all operations are done - defer func() { - if compressWriter, ok := writer.(*CompressingResponseWriter); ok { - compressWriter.Close() - } - }() - - // Instal panic recovery unless told otherwise - if !c.doNotRecover { // catch all for 500 response - defer func() { - if r := recover(); r != nil { - c.recoverHandleFunc(r, writer) - return - } - }() - } - - // Find best match Route ; err is non nil if no match was found - var webService *WebService - var route *Route - var err error - func() { - c.webServicesLock.RLock() - defer c.webServicesLock.RUnlock() - webService, route, err = c.router.SelectRoute( - c.webServices, - httpRequest) - }() - if err != nil { - // a non-200 response (may be compressed) has already been written - // run container filters anyway ; they should not touch the response... - chain := FilterChain{Filters: c.containerFilters, Target: func(req *Request, resp *Response) { - switch err.(type) { - case ServiceError: - ser := err.(ServiceError) - c.serviceErrorHandleFunc(ser, req, resp) - } - // TODO - }} - chain.ProcessFilter(NewRequest(httpRequest), NewResponse(writer)) - return - } - - // Unless httpWriter is already an CompressingResponseWriter see if we need to install one - if _, isCompressing := httpWriter.(*CompressingResponseWriter); !isCompressing { - // Detect if compression is needed - // assume without compression, test for override - contentEncodingEnabled := c.contentEncodingEnabled - if route != nil && route.contentEncodingEnabled != nil { - contentEncodingEnabled = *route.contentEncodingEnabled - } - if contentEncodingEnabled { - doCompress, encoding := wantsCompressedResponse(httpRequest, httpWriter) - if doCompress { - var err error - writer, err = NewCompressingResponseWriter(httpWriter, encoding) - if err != nil { - log.Print("unable to install compressor: ", err) - httpWriter.WriteHeader(http.StatusInternalServerError) - return - } - } - } - } - - pathProcessor, routerProcessesPath := c.router.(PathProcessor) - if !routerProcessesPath { - pathProcessor = defaultPathProcessor{} - } - pathParams := pathProcessor.ExtractParameters(route, webService, httpRequest.URL.Path) - wrappedRequest, wrappedResponse := route.wrapRequestResponse(writer, httpRequest, pathParams) - // pass through filters (if any) - if size := len(c.containerFilters) + len(webService.filters) + len(route.Filters); size > 0 { - // compose filter chain - allFilters := make([]FilterFunction, 0, size) - allFilters = append(allFilters, c.containerFilters...) - allFilters = append(allFilters, webService.filters...) - allFilters = append(allFilters, route.Filters...) - chain := FilterChain{ - Filters: allFilters, - Target: route.Function, - ParameterDocs: route.ParameterDocs, - Operation: route.Operation, - } - chain.ProcessFilter(wrappedRequest, wrappedResponse) - } else { - // no filters, handle request by route - route.Function(wrappedRequest, wrappedResponse) - } -} - -// fixedPrefixPath returns the fixed part of the partspec ; it may include template vars {} -func fixedPrefixPath(pathspec string) string { - varBegin := strings.Index(pathspec, "{") - if -1 == varBegin { - return pathspec - } - return pathspec[:varBegin] -} - -// ServeHTTP implements net/http.Handler therefore a Container can be a Handler in a http.Server -func (c *Container) ServeHTTP(httpWriter http.ResponseWriter, httpRequest *http.Request) { - // Skip, if content encoding is disabled - if !c.contentEncodingEnabled { - c.ServeMux.ServeHTTP(httpWriter, httpRequest) - return - } - // content encoding is enabled - - // Skip, if httpWriter is already an CompressingResponseWriter - if _, ok := httpWriter.(*CompressingResponseWriter); ok { - c.ServeMux.ServeHTTP(httpWriter, httpRequest) - return - } - - writer := httpWriter - // CompressingResponseWriter should be closed after all operations are done - defer func() { - if compressWriter, ok := writer.(*CompressingResponseWriter); ok { - compressWriter.Close() - } - }() - - doCompress, encoding := wantsCompressedResponse(httpRequest, httpWriter) - if doCompress { - var err error - writer, err = NewCompressingResponseWriter(httpWriter, encoding) - if err != nil { - log.Print("unable to install compressor: ", err) - httpWriter.WriteHeader(http.StatusInternalServerError) - return - } - } - - c.ServeMux.ServeHTTP(writer, httpRequest) -} - -// Handle registers the handler for the given pattern. If a handler already exists for pattern, Handle panics. -func (c *Container) Handle(pattern string, handler http.Handler) { - c.ServeMux.Handle(pattern, http.HandlerFunc(func(httpWriter http.ResponseWriter, httpRequest *http.Request) { - // Skip, if httpWriter is already an CompressingResponseWriter - if _, ok := httpWriter.(*CompressingResponseWriter); ok { - handler.ServeHTTP(httpWriter, httpRequest) - return - } - - writer := httpWriter - - // CompressingResponseWriter should be closed after all operations are done - defer func() { - if compressWriter, ok := writer.(*CompressingResponseWriter); ok { - compressWriter.Close() - } - }() - - if c.contentEncodingEnabled { - doCompress, encoding := wantsCompressedResponse(httpRequest, httpWriter) - if doCompress { - var err error - writer, err = NewCompressingResponseWriter(httpWriter, encoding) - if err != nil { - log.Print("unable to install compressor: ", err) - httpWriter.WriteHeader(http.StatusInternalServerError) - return - } - } - } - - handler.ServeHTTP(writer, httpRequest) - })) -} - -// HandleWithFilter registers the handler for the given pattern. -// Container's filter chain is applied for handler. -// If a handler already exists for pattern, HandleWithFilter panics. -func (c *Container) HandleWithFilter(pattern string, handler http.Handler) { - f := func(httpResponse http.ResponseWriter, httpRequest *http.Request) { - if len(c.containerFilters) == 0 { - handler.ServeHTTP(httpResponse, httpRequest) - return - } - - chain := FilterChain{Filters: c.containerFilters, Target: func(req *Request, resp *Response) { - handler.ServeHTTP(resp, req.Request) - }} - chain.ProcessFilter(NewRequest(httpRequest), NewResponse(httpResponse)) - } - - c.Handle(pattern, http.HandlerFunc(f)) -} - -// Filter appends a container FilterFunction. These are called before dispatching -// a http.Request to a WebService from the container -func (c *Container) Filter(filter FilterFunction) { - c.containerFilters = append(c.containerFilters, filter) -} - -// RegisteredWebServices returns the collections of added WebServices -func (c *Container) RegisteredWebServices() []*WebService { - c.webServicesLock.RLock() - defer c.webServicesLock.RUnlock() - result := make([]*WebService, len(c.webServices)) - for ix := range c.webServices { - result[ix] = c.webServices[ix] - } - return result -} - -// computeAllowedMethods returns a list of HTTP methods that are valid for a Request -func (c *Container) computeAllowedMethods(req *Request) []string { - // Go through all RegisteredWebServices() and all its Routes to collect the options - methods := []string{} - requestPath := req.Request.URL.Path - for _, ws := range c.RegisteredWebServices() { - matches := ws.pathExpr.Matcher.FindStringSubmatch(requestPath) - if matches != nil { - finalMatch := matches[len(matches)-1] - for _, rt := range ws.Routes() { - matches := rt.pathExpr.Matcher.FindStringSubmatch(finalMatch) - if matches != nil { - lastMatch := matches[len(matches)-1] - if lastMatch == "" || lastMatch == "/" { // do not include if value is neither empty nor ‘/’. - methods = append(methods, rt.Method) - } - } - } - } - } - // methods = append(methods, "OPTIONS") not sure about this - return methods -} - -// newBasicRequestResponse creates a pair of Request,Response from its http versions. -// It is basic because no parameter or (produces) content-type information is given. -func newBasicRequestResponse(httpWriter http.ResponseWriter, httpRequest *http.Request) (*Request, *Response) { - resp := NewResponse(httpWriter) - resp.requestAccept = httpRequest.Header.Get(HEADER_Accept) - return NewRequest(httpRequest), resp -} diff --git a/vendor/github.com/emicklei/go-restful/v3/cors_filter.go b/vendor/github.com/emicklei/go-restful/v3/cors_filter.go deleted file mode 100644 index 9d18dfb7b..000000000 --- a/vendor/github.com/emicklei/go-restful/v3/cors_filter.go +++ /dev/null @@ -1,193 +0,0 @@ -package restful - -// Copyright 2013 Ernest Micklei. All rights reserved. -// Use of this source code is governed by a license -// that can be found in the LICENSE file. - -import ( - "regexp" - "strconv" - "strings" -) - -// CrossOriginResourceSharing is used to create a Container Filter that implements CORS. -// Cross-origin resource sharing (CORS) is a mechanism that allows JavaScript on a web page -// to make XMLHttpRequests to another domain, not the domain the JavaScript originated from. -// -// http://en.wikipedia.org/wiki/Cross-origin_resource_sharing -// http://enable-cors.org/server.html -// http://www.html5rocks.com/en/tutorials/cors/#toc-handling-a-not-so-simple-request -type CrossOriginResourceSharing struct { - ExposeHeaders []string // list of Header names - - // AllowedHeaders is alist of Header names. Checking is case-insensitive. - // The list may contain the special wildcard string ".*" ; all is allowed - AllowedHeaders []string - - // AllowedDomains is a list of allowed values for Http Origin. - // The list may contain the special wildcard string ".*" ; all is allowed - // If empty all are allowed. - AllowedDomains []string - - // AllowedDomainFunc is optional and is a function that will do the check - // when the origin is not part of the AllowedDomains and it does not contain the wildcard ".*". - AllowedDomainFunc func(origin string) bool - - // AllowedMethods is either empty or has a list of http methods names. Checking is case-insensitive. - AllowedMethods []string - MaxAge int // number of seconds before requiring new Options request - CookiesAllowed bool - Container *Container - - allowedOriginPatterns []*regexp.Regexp // internal field for origin regexp check. -} - -// Filter is a filter function that implements the CORS flow as documented on http://enable-cors.org/server.html -// and http://www.html5rocks.com/static/images/cors_server_flowchart.png -func (c CrossOriginResourceSharing) Filter(req *Request, resp *Response, chain *FilterChain) { - origin := req.Request.Header.Get(HEADER_Origin) - if len(origin) == 0 { - if trace { - traceLogger.Print("no Http header Origin set") - } - chain.ProcessFilter(req, resp) - return - } - if !c.isOriginAllowed(origin) { // check whether this origin is allowed - if trace { - traceLogger.Printf("HTTP Origin:%s is not part of %v, neither matches any part of %v", origin, c.AllowedDomains, c.allowedOriginPatterns) - } - chain.ProcessFilter(req, resp) - return - } - if req.Request.Method != "OPTIONS" { - c.doActualRequest(req, resp) - chain.ProcessFilter(req, resp) - return - } - if acrm := req.Request.Header.Get(HEADER_AccessControlRequestMethod); acrm != "" { - c.doPreflightRequest(req, resp) - } else { - c.doActualRequest(req, resp) - chain.ProcessFilter(req, resp) - return - } -} - -func (c CrossOriginResourceSharing) doActualRequest(req *Request, resp *Response) { - c.setOptionsHeaders(req, resp) - // continue processing the response -} - -func (c *CrossOriginResourceSharing) doPreflightRequest(req *Request, resp *Response) { - if len(c.AllowedMethods) == 0 { - if c.Container == nil { - c.AllowedMethods = DefaultContainer.computeAllowedMethods(req) - } else { - c.AllowedMethods = c.Container.computeAllowedMethods(req) - } - } - - acrm := req.Request.Header.Get(HEADER_AccessControlRequestMethod) - if !c.isValidAccessControlRequestMethod(acrm, c.AllowedMethods) { - if trace { - traceLogger.Printf("Http header %s:%s is not in %v", - HEADER_AccessControlRequestMethod, - acrm, - c.AllowedMethods) - } - return - } - acrhs := req.Request.Header.Get(HEADER_AccessControlRequestHeaders) - if len(acrhs) > 0 { - for _, each := range strings.Split(acrhs, ",") { - if !c.isValidAccessControlRequestHeader(strings.Trim(each, " ")) { - if trace { - traceLogger.Printf("Http header %s:%s is not in %v", - HEADER_AccessControlRequestHeaders, - acrhs, - c.AllowedHeaders) - } - return - } - } - } - resp.AddHeader(HEADER_AccessControlAllowMethods, strings.Join(c.AllowedMethods, ",")) - resp.AddHeader(HEADER_AccessControlAllowHeaders, acrhs) - c.setOptionsHeaders(req, resp) - - // return http 200 response, no body -} - -func (c CrossOriginResourceSharing) setOptionsHeaders(req *Request, resp *Response) { - c.checkAndSetExposeHeaders(resp) - c.setAllowOriginHeader(req, resp) - c.checkAndSetAllowCredentials(resp) - if c.MaxAge > 0 { - resp.AddHeader(HEADER_AccessControlMaxAge, strconv.Itoa(c.MaxAge)) - } -} - -func (c CrossOriginResourceSharing) isOriginAllowed(origin string) bool { - if len(origin) == 0 { - return false - } - lowerOrigin := strings.ToLower(origin) - if len(c.AllowedDomains) == 0 { - if c.AllowedDomainFunc != nil { - return c.AllowedDomainFunc(lowerOrigin) - } - return true - } - - // exact match on each allowed domain - for _, domain := range c.AllowedDomains { - if domain == ".*" || strings.ToLower(domain) == lowerOrigin { - return true - } - } - if c.AllowedDomainFunc != nil { - return c.AllowedDomainFunc(origin) - } - return false -} - -func (c CrossOriginResourceSharing) setAllowOriginHeader(req *Request, resp *Response) { - origin := req.Request.Header.Get(HEADER_Origin) - if c.isOriginAllowed(origin) { - resp.AddHeader(HEADER_AccessControlAllowOrigin, origin) - } -} - -func (c CrossOriginResourceSharing) checkAndSetExposeHeaders(resp *Response) { - if len(c.ExposeHeaders) > 0 { - resp.AddHeader(HEADER_AccessControlExposeHeaders, strings.Join(c.ExposeHeaders, ",")) - } -} - -func (c CrossOriginResourceSharing) checkAndSetAllowCredentials(resp *Response) { - if c.CookiesAllowed { - resp.AddHeader(HEADER_AccessControlAllowCredentials, "true") - } -} - -func (c CrossOriginResourceSharing) isValidAccessControlRequestMethod(method string, allowedMethods []string) bool { - for _, each := range allowedMethods { - if each == method { - return true - } - } - return false -} - -func (c CrossOriginResourceSharing) isValidAccessControlRequestHeader(header string) bool { - for _, each := range c.AllowedHeaders { - if strings.ToLower(each) == strings.ToLower(header) { - return true - } - if each == "*" { - return true - } - } - return false -} diff --git a/vendor/github.com/emicklei/go-restful/v3/coverage.sh b/vendor/github.com/emicklei/go-restful/v3/coverage.sh deleted file mode 100644 index e27dbf1a9..000000000 --- a/vendor/github.com/emicklei/go-restful/v3/coverage.sh +++ /dev/null @@ -1,2 +0,0 @@ -go test -coverprofile=coverage.out -go tool cover -html=coverage.out \ No newline at end of file diff --git a/vendor/github.com/emicklei/go-restful/v3/curly.go b/vendor/github.com/emicklei/go-restful/v3/curly.go deleted file mode 100644 index eec43bfd0..000000000 --- a/vendor/github.com/emicklei/go-restful/v3/curly.go +++ /dev/null @@ -1,225 +0,0 @@ -package restful - -// Copyright 2013 Ernest Micklei. All rights reserved. -// Use of this source code is governed by a license -// that can be found in the LICENSE file. - -import ( - "net/http" - "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( - webServices []*WebService, - httpRequest *http.Request) (selectedService *WebService, selected *Route, err error) { - - requestTokens := tokenizePath(httpRequest.URL.Path) - - detectedService := c.detectWebService(requestTokens, webServices) - if detectedService == nil { - if trace { - traceLogger.Printf("no WebService was found to match URL path:%s\n", httpRequest.URL.Path) - } - return nil, nil, NewError(http.StatusNotFound, "404: Page Not Found") - } - candidateRoutes := c.selectRoutes(detectedService, requestTokens) - if len(candidateRoutes) == 0 { - if trace { - traceLogger.Printf("no Route in WebService with path %s was found to match URL path:%s\n", detectedService.rootPath, httpRequest.URL.Path) - } - return detectedService, nil, NewError(http.StatusNotFound, "404: Page Not Found") - } - selectedRoute, err := c.detectRoute(candidateRoutes, httpRequest) - if selectedRoute == nil { - return detectedService, nil, err - } - return detectedService, selectedRoute, nil -} - -// selectRoutes return a collection of Route from a WebService that matches the path tokens from the request. -func (c CurlyRouter) selectRoutes(ws *WebService, requestTokens []string) sortableCurlyRoutes { - candidates := make(sortableCurlyRoutes, 0, 8) - for _, eachRoute := range ws.routes { - matches, paramCount, staticCount := c.matchesRouteByPathTokens(eachRoute.pathParts, requestTokens, eachRoute.hasCustomVerb) - if matches { - candidates.add(curlyRoute{eachRoute, paramCount, staticCount}) // TODO make sure Routes() return pointers? - } - } - sort.Sort(candidates) - return candidates -} - -// matchesRouteByPathTokens computes whether it matches, howmany parameters do match and what the number of static path elements are. -func (c CurlyRouter) matchesRouteByPathTokens(routeTokens, requestTokens []string, routeHasCustomVerb bool) (matches bool, paramCount int, staticCount int) { - if len(routeTokens) < len(requestTokens) { - // proceed in matching only if last routeToken is wildcard - count := len(routeTokens) - if count == 0 || !strings.HasSuffix(routeTokens[count-1], "*}") { - return false, 0, 0 - } - // proceed - } - for i, routeToken := range routeTokens { - if i == len(requestTokens) { - // reached end of request path - return false, 0, 0 - } - requestToken := requestTokens[i] - if routeHasCustomVerb && hasCustomVerb(routeToken) { - if !isMatchCustomVerb(routeToken, requestToken) { - return false, 0, 0 - } - staticCount++ - requestToken = removeCustomVerb(requestToken) - routeToken = removeCustomVerb(routeToken) - } - - if strings.HasPrefix(routeToken, "{") { - paramCount++ - if colon := strings.Index(routeToken, ":"); colon != -1 { - // match by regex - matchesToken, matchesRemainder := c.regularMatchesPathToken(routeToken, colon, requestToken) - if !matchesToken { - return false, 0, 0 - } - if matchesRemainder { - break - } - } - } else { // no { prefix - if requestToken != routeToken { - return false, 0, 0 - } - staticCount++ - } - } - return true, paramCount, staticCount -} - -// regularMatchesPathToken tests whether the regular expression part of routeToken matches the requestToken or all remaining tokens -// format routeToken is {someVar:someExpression}, e.g. {zipcode:[\d][\d][\d][\d][A-Z][A-Z]} -func (c CurlyRouter) regularMatchesPathToken(routeToken string, colon int, requestToken string) (matchesToken bool, matchesRemainder bool) { - regPart := routeToken[colon+1 : len(routeToken)-1] - if regPart == "*" { - if trace { - traceLogger.Printf("wildcard parameter detected in route token %s that matches %s\n", routeToken, requestToken) - } - return true, true - } - - // 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{} - -// detectRoute selectes from a list of Route the first match by inspecting both the Accept and Content-Type -// headers of the Request. See also RouterJSR311 in jsr311.go -func (c CurlyRouter) detectRoute(candidateRoutes sortableCurlyRoutes, httpRequest *http.Request) (*Route, error) { - // tracing is done inside detectRoute - return jsr311Router.detectRoute(candidateRoutes.routes(), httpRequest) -} - -// detectWebService returns the best matching webService given the list of path tokens. -// see also computeWebserviceScore -func (c CurlyRouter) detectWebService(requestTokens []string, webServices []*WebService) *WebService { - var bestWs *WebService - score := -1 - for _, eachWS := range webServices { - matches, eachScore := c.computeWebserviceScore(requestTokens, eachWS.pathExpr.tokens) - if matches && (eachScore > score) { - bestWs = eachWS - score = eachScore - } - } - return bestWs -} - -// computeWebserviceScore returns whether tokens match and -// the weighted score of the longest matching consecutive tokens from the beginning. -func (c CurlyRouter) computeWebserviceScore(requestTokens []string, routeTokens []string) (bool, int) { - if len(routeTokens) > len(requestTokens) { - return false, 0 - } - score := 0 - for i := 0; i < len(routeTokens); i++ { - eachRequestToken := requestTokens[i] - eachRouteToken := routeTokens[i] - if len(eachRequestToken) == 0 && len(eachRouteToken) == 0 { - score++ - continue - } - if len(eachRouteToken) > 0 && strings.HasPrefix(eachRouteToken, "{") { - // no empty match - if len(eachRequestToken) == 0 { - return false, score - } - score++ - - if colon := strings.Index(eachRouteToken, ":"); colon != -1 { - // match by regex - matchesToken, _ := c.regularMatchesPathToken(eachRouteToken, colon, eachRequestToken) - if matchesToken { - score++ // extra score for regex match - } - } - } else { - // not a parameter - if eachRequestToken != eachRouteToken { - return false, score - } - score += (len(routeTokens) - i) * 10 //fuzzy - } - } - return true, score -} diff --git a/vendor/github.com/emicklei/go-restful/v3/curly_route.go b/vendor/github.com/emicklei/go-restful/v3/curly_route.go deleted file mode 100644 index 403dd3be9..000000000 --- a/vendor/github.com/emicklei/go-restful/v3/curly_route.go +++ /dev/null @@ -1,54 +0,0 @@ -package restful - -// Copyright 2013 Ernest Micklei. All rights reserved. -// Use of this source code is governed by a license -// that can be found in the LICENSE file. - -// curlyRoute exits for sorting Routes by the CurlyRouter based on number of parameters and number of static path elements. -type curlyRoute struct { - route Route - paramCount int - staticCount int -} - -// sortableCurlyRoutes orders by most parameters and path elements first. -type sortableCurlyRoutes []curlyRoute - -func (s *sortableCurlyRoutes) add(route curlyRoute) { - *s = append(*s, route) -} - -func (s sortableCurlyRoutes) routes() (routes []Route) { - routes = make([]Route, 0, len(s)) - for _, each := range s { - routes = append(routes, each.route) // TODO change return type - } - return routes -} - -func (s sortableCurlyRoutes) Len() int { - return len(s) -} -func (s sortableCurlyRoutes) Swap(i, j int) { - s[i], s[j] = s[j], s[i] -} -func (s sortableCurlyRoutes) Less(i, j int) bool { - a := s[j] - b := s[i] - - // primary key - if a.staticCount < b.staticCount { - return true - } - if a.staticCount > b.staticCount { - return false - } - // secundary key - if a.paramCount < b.paramCount { - return true - } - if a.paramCount > b.paramCount { - return false - } - return a.route.Path < b.route.Path -} diff --git a/vendor/github.com/emicklei/go-restful/v3/custom_verb.go b/vendor/github.com/emicklei/go-restful/v3/custom_verb.go deleted file mode 100644 index 0b98eeb09..000000000 --- a/vendor/github.com/emicklei/go-restful/v3/custom_verb.go +++ /dev/null @@ -1,59 +0,0 @@ -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]+)$") - 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) -} - -func isMatchCustomVerb(routeToken string, pathToken string) bool { - rs := customVerbReg.FindStringSubmatch(routeToken) - if len(rs) < 2 { - return false - } - - customVerb := rs[1] - 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) -} - -func removeCustomVerb(str string) string { - return customVerbReg.ReplaceAllString(str, "") -} diff --git a/vendor/github.com/emicklei/go-restful/v3/doc.go b/vendor/github.com/emicklei/go-restful/v3/doc.go deleted file mode 100644 index 80809225b..000000000 --- a/vendor/github.com/emicklei/go-restful/v3/doc.go +++ /dev/null @@ -1,181 +0,0 @@ -/* -Package restful , a lean package for creating REST-style WebServices without magic. - -### 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. -WebServices must be added to a container (see below) in order to handler Http requests from a server. - -A Route is defined by a HTTP method, an URL path and (optionally) the MIME types it consumes (Content-Type) and produces (Accept). -This package has the logic to find the best matching Route and if found, call its Function. - - ws := new(restful.WebService) - ws. - Path("/users"). - Consumes(restful.MIME_JSON, restful.MIME_XML). - Produces(restful.MIME_JSON, restful.MIME_XML) - - ws.Route(ws.GET("/{user-id}").To(u.findUser)) // u is a UserResource - - ... - - // GET http://localhost:8080/users/1 - func (u UserResource) findUser(request *restful.Request, response *restful.Response) { - id := request.PathParameter("user-id") - ... - } - -The (*Request, *Response) arguments provide functions for reading information from the request and writing information back to the response. - -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 - -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 - -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. -The Default container of go-restful uses the http.DefaultServeMux. -You can create your own Container and create a new http.Server for that particular container. - - container := restful.NewContainer() - server := &http.Server{Addr: ":8081", Handler: container} - -### 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. -In the restful package there are three hooks into the request,response flow where filters can be added. -Each filter must define a FilterFunction: - - func (req *restful.Request, resp *restful.Response, chain *restful.FilterChain) - -Use the following statement to pass the request,response pair to the next filter or RouteFunction - - chain.ProcessFilter(req, resp) - -### 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 - -These are processed before any Route of a WebService. - - // install a webservice filter (processed before any route) - ws.Filter(webserviceLogging).Filter(measureTime) - -### Route Filters - -These are processed before calling the function associated with the Route. - - // install 2 chained route filters (processed before calling findUser) - ws.Route(ws.GET("/{user-id}").Filter(routeLogging).Filter(NewCountFilter().routeCounter).To(findUser)) - -See the example https://github.com/emicklei/go-restful/blob/v3/examples/filters/restful-filters.go with full implementations. - -### Response Encoding - -Two encodings are supported: gzip and deflate. To enable this for all responses: - - restful.DefaultContainer.EnableContentEncoding(true) - -If a Http request includes the Accept-Encoding header then the response content will be compressed using the specified encoding. -Alternatively, you can create a Filter that performs the encoding and install it per WebService or Route. - -See the example https://github.com/emicklei/go-restful/blob/v3/examples/encoding/restful-encoding-filter.go - -### OPTIONS support - -By installing a pre-defined container filter, your Webservice(s) can respond to the OPTIONS Http request. - - Filter(OPTIONSFilter()) - -### 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 - -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. - - 400: Bad Request - -If path or query parameters are not valid (content or type) then use http.StatusBadRequest. - - 404: Not Found - -Despite a valid URI, the resource requested may not be available - - 500: Internal Server Error - -If the application logic could not process the request (or write the response) then use http.StatusInternalServerError. - - 405: Method Not Allowed - -The request has a valid URL but the method (GET,PUT,POST,...) is not allowed. - - 406: Not Acceptable - -The request does not have or has an unknown Accept Header set for this operation. - - 415: Unsupported Media Type - -The request does not have or has an unknown Content-Type Header set for this operation. - -### ServiceError - -In addition to setting the correct (error) Http status code, you can choose to write a ServiceError message on the response. - -### 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. - - restful.DefaultContainer.DoNotRecover(false) - -DoNotRecover controls whether panics will be caught to return HTTP 500. -If set to false, the container will recover from panics. -Default value is true - - restful.SetCompressorProvider(NewBoundedCachedCompressors(20, 20)) - -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 - -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 - -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 - -(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/ -[showcases]: https://github.com/emicklei/mora, https://github.com/emicklei/landskape -*/ -package restful diff --git a/vendor/github.com/emicklei/go-restful/v3/entity_accessors.go b/vendor/github.com/emicklei/go-restful/v3/entity_accessors.go deleted file mode 100644 index 9808752ac..000000000 --- a/vendor/github.com/emicklei/go-restful/v3/entity_accessors.go +++ /dev/null @@ -1,169 +0,0 @@ -package restful - -// Copyright 2015 Ernest Micklei. All rights reserved. -// Use of this source code is governed by a license -// that can be found in the LICENSE file. - -import ( - "encoding/json" - "encoding/xml" - "strings" - "sync" -) - -var ( - MarshalIndent = json.MarshalIndent - NewDecoder = json.NewDecoder - NewEncoder = json.NewEncoder -) - -// EntityReaderWriter can read and write values using an encoding such as JSON,XML. -type EntityReaderWriter interface { - // Read a serialized version of the value from the request. - // The Request may have a decompressing reader. Depends on Content-Encoding. - Read(req *Request, v interface{}) error - - // Write a serialized version of the value on the response. - // The Response may have a compressing writer. Depends on Accept-Encoding. - // status should be a valid Http Status code - Write(resp *Response, status int, v interface{}) error -} - -// entityAccessRegistry is a singleton -var entityAccessRegistry = &entityReaderWriters{ - protection: new(sync.RWMutex), - accessors: map[string]EntityReaderWriter{}, -} - -// entityReaderWriters associates MIME to an EntityReaderWriter -type entityReaderWriters struct { - protection *sync.RWMutex - accessors map[string]EntityReaderWriter -} - -func init() { - RegisterEntityAccessor(MIME_JSON, NewEntityAccessorJSON(MIME_JSON)) - RegisterEntityAccessor(MIME_XML, NewEntityAccessorXML(MIME_XML)) -} - -// RegisterEntityAccessor add/overrides the ReaderWriter for encoding content with this MIME type. -func RegisterEntityAccessor(mime string, erw EntityReaderWriter) { - entityAccessRegistry.protection.Lock() - defer entityAccessRegistry.protection.Unlock() - entityAccessRegistry.accessors[mime] = erw -} - -// NewEntityAccessorJSON returns a new EntityReaderWriter for accessing JSON content. -// This package is already initialized with such an accessor using the MIME_JSON contentType. -func NewEntityAccessorJSON(contentType string) EntityReaderWriter { - return entityJSONAccess{ContentType: contentType} -} - -// NewEntityAccessorXML returns a new EntityReaderWriter for accessing XML content. -// This package is already initialized with such an accessor using the MIME_XML contentType. -func NewEntityAccessorXML(contentType string) EntityReaderWriter { - return entityXMLAccess{ContentType: contentType} -} - -// accessorAt returns the registered ReaderWriter for this MIME type. -func (r *entityReaderWriters) accessorAt(mime string) (EntityReaderWriter, bool) { - r.protection.RLock() - defer r.protection.RUnlock() - er, ok := r.accessors[mime] - if !ok { - // retry with reverse lookup - // more expensive but we are in an exceptional situation anyway - for k, v := range r.accessors { - if strings.Contains(mime, k) { - return v, true - } - } - } - return er, ok -} - -// entityXMLAccess is a EntityReaderWriter for XML encoding -type entityXMLAccess struct { - // This is used for setting the Content-Type header when writing - ContentType string -} - -// Read unmarshalls the value from XML -func (e entityXMLAccess) Read(req *Request, v interface{}) error { - return xml.NewDecoder(req.Request.Body).Decode(v) -} - -// Write marshalls the value to JSON and set the Content-Type Header. -func (e entityXMLAccess) Write(resp *Response, status int, v interface{}) error { - return writeXML(resp, status, e.ContentType, v) -} - -// writeXML marshalls the value to JSON and set the Content-Type Header. -func writeXML(resp *Response, status int, contentType string, v interface{}) error { - if v == nil { - resp.WriteHeader(status) - // do not write a nil representation - return nil - } - if resp.prettyPrint { - // pretty output must be created and written explicitly - output, err := xml.MarshalIndent(v, " ", " ") - if err != nil { - return err - } - resp.Header().Set(HEADER_ContentType, contentType) - resp.WriteHeader(status) - _, err = resp.Write([]byte(xml.Header)) - if err != nil { - return err - } - _, err = resp.Write(output) - return err - } - // not-so-pretty - resp.Header().Set(HEADER_ContentType, contentType) - resp.WriteHeader(status) - return xml.NewEncoder(resp).Encode(v) -} - -// entityJSONAccess is a EntityReaderWriter for JSON encoding -type entityJSONAccess struct { - // This is used for setting the Content-Type header when writing - ContentType string -} - -// Read unmarshalls the value from JSON -func (e entityJSONAccess) Read(req *Request, v interface{}) error { - decoder := NewDecoder(req.Request.Body) - decoder.UseNumber() - return decoder.Decode(v) -} - -// Write marshalls the value to JSON and set the Content-Type Header. -func (e entityJSONAccess) Write(resp *Response, status int, v interface{}) error { - return writeJSON(resp, status, e.ContentType, v) -} - -// write marshalls the value to JSON and set the Content-Type Header. -func writeJSON(resp *Response, status int, contentType string, v interface{}) error { - if v == nil { - resp.WriteHeader(status) - // do not write a nil representation - return nil - } - if resp.prettyPrint { - // pretty output must be created and written explicitly - output, err := MarshalIndent(v, "", " ") - if err != nil { - return err - } - resp.Header().Set(HEADER_ContentType, contentType) - resp.WriteHeader(status) - _, err = resp.Write(output) - return err - } - // not-so-pretty - resp.Header().Set(HEADER_ContentType, contentType) - resp.WriteHeader(status) - return NewEncoder(resp).Encode(v) -} diff --git a/vendor/github.com/emicklei/go-restful/v3/extensions.go b/vendor/github.com/emicklei/go-restful/v3/extensions.go deleted file mode 100644 index 5023fa049..000000000 --- a/vendor/github.com/emicklei/go-restful/v3/extensions.go +++ /dev/null @@ -1,21 +0,0 @@ -package restful - -// Copyright 2021 Ernest Micklei. All rights reserved. -// Use of this source code is governed by a license -// that can be found in the LICENSE file. - -// ExtensionProperties provides storage of vendor extensions for entities -type ExtensionProperties struct { - // Extensions vendor extensions used to describe extra functionality - // (https://swagger.io/docs/specification/2-0/swagger-extensions/) - Extensions map[string]interface{} -} - -// AddExtension adds or updates a key=value pair to the extension map. -func (ep *ExtensionProperties) AddExtension(key string, value interface{}) { - if ep.Extensions == nil { - ep.Extensions = map[string]interface{}{key: value} - } else { - ep.Extensions[key] = value - } -} diff --git a/vendor/github.com/emicklei/go-restful/v3/filter.go b/vendor/github.com/emicklei/go-restful/v3/filter.go deleted file mode 100644 index fd88c536c..000000000 --- a/vendor/github.com/emicklei/go-restful/v3/filter.go +++ /dev/null @@ -1,37 +0,0 @@ -package restful - -// Copyright 2013 Ernest Micklei. All rights reserved. -// Use of this source code is governed by a license -// that can be found in the LICENSE file. - -// FilterChain is a request scoped object to process one or more filters before calling the target RouteFunction. -type FilterChain struct { - Filters []FilterFunction // ordered list of FilterFunction - Index int // index into filters that is currently in progress - Target RouteFunction // function to call after passing all filters - ParameterDocs []*Parameter // the parameter docs for the route - Operation string // the name of the operation -} - -// ProcessFilter passes the request,response pair through the next of Filters. -// Each filter can decide to proceed to the next Filter or handle the Response itself. -func (f *FilterChain) ProcessFilter(request *Request, response *Response) { - if f.Index < len(f.Filters) { - f.Index++ - f.Filters[f.Index-1](request, response, f) - } else { - f.Target(request, response) - } -} - -// FilterFunction definitions must call ProcessFilter on the FilterChain to pass on the control and eventually call the RouteFunction -type FilterFunction func(*Request, *Response, *FilterChain) - -// NoBrowserCacheFilter is a filter function to set HTTP headers that disable browser caching -// See examples/restful-no-cache-filter.go for usage -func NoBrowserCacheFilter(req *Request, resp *Response, chain *FilterChain) { - resp.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate") // HTTP 1.1. - resp.Header().Set("Pragma", "no-cache") // HTTP 1.0. - resp.Header().Set("Expires", "0") // Proxies. - chain.ProcessFilter(req, resp) -} diff --git a/vendor/github.com/emicklei/go-restful/v3/filter_adapter.go b/vendor/github.com/emicklei/go-restful/v3/filter_adapter.go deleted file mode 100644 index c246512fc..000000000 --- a/vendor/github.com/emicklei/go-restful/v3/filter_adapter.go +++ /dev/null @@ -1,21 +0,0 @@ -package restful - -import ( - "net/http" -) - -// HttpMiddlewareHandler is a function that takes a http.Handler and returns a http.Handler -type HttpMiddlewareHandler func(http.Handler) http.Handler - -// HttpMiddlewareHandlerToFilter converts a HttpMiddlewareHandler to a FilterFunction. -func HttpMiddlewareHandlerToFilter(middleware HttpMiddlewareHandler) FilterFunction { - return func(req *Request, resp *Response, chain *FilterChain) { - next := http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { - req.Request = r - resp.ResponseWriter = rw - chain.ProcessFilter(req, resp) - }) - - middleware(next).ServeHTTP(resp.ResponseWriter, req.Request) - } -} diff --git a/vendor/github.com/emicklei/go-restful/v3/jsr311.go b/vendor/github.com/emicklei/go-restful/v3/jsr311.go deleted file mode 100644 index 7f04bd905..000000000 --- a/vendor/github.com/emicklei/go-restful/v3/jsr311.go +++ /dev/null @@ -1,313 +0,0 @@ -package restful - -// Copyright 2013 Ernest Micklei. All rights reserved. -// Use of this source code is governed by a license -// that can be found in the LICENSE file. - -import ( - "errors" - "fmt" - "net/http" - "sort" - "strings" -) - -// RouterJSR311 implements the flow for matching Requests to Routes (and consequently Resource Functions) -// as specified by the JSR311 http://jsr311.java.net/nonav/releases/1.1/spec/spec.html. -// RouterJSR311 implements the Router interface. -// Concept of locators is not implemented. -type RouterJSR311 struct{} - -// SelectRoute is part of the Router interface and returns the best match -// for the WebService and its Route for the given Request. -func (r RouterJSR311) SelectRoute( - webServices []*WebService, - httpRequest *http.Request) (selectedService *WebService, selectedRoute *Route, err error) { - - // Identify the root resource class (WebService) - dispatcher, finalMatch, err := r.detectDispatcher(httpRequest.URL.Path, webServices) - if err != nil { - return nil, nil, NewError(http.StatusNotFound, "") - } - // Obtain the set of candidate methods (Routes) - routes := r.selectRoutes(dispatcher, finalMatch) - if len(routes) == 0 { - return dispatcher, nil, NewError(http.StatusNotFound, "404: Page Not Found") - } - - // Identify the method (Route) that will handle the request - route, ok := r.detectRoute(routes, httpRequest) - return dispatcher, route, ok -} - -// ExtractParameters is used to obtain the path parameters from the route using the same matching -// engine as the JSR 311 router. -func (r RouterJSR311) ExtractParameters(route *Route, webService *WebService, urlPath string) map[string]string { - webServiceExpr := webService.pathExpr - webServiceMatches := webServiceExpr.Matcher.FindStringSubmatch(urlPath) - pathParameters := r.extractParams(webServiceExpr, webServiceMatches) - routeExpr := route.pathExpr - routeMatches := routeExpr.Matcher.FindStringSubmatch(webServiceMatches[len(webServiceMatches)-1]) - routeParams := r.extractParams(routeExpr, routeMatches) - for key, value := range routeParams { - pathParameters[key] = value - } - return pathParameters -} - -func (RouterJSR311) extractParams(pathExpr *pathExpression, matches []string) map[string]string { - params := map[string]string{} - for i := 1; i < len(matches); i++ { - if len(pathExpr.VarNames) >= i { - params[pathExpr.VarNames[i-1]] = matches[i] - } - } - return params -} - -// https://download.oracle.com/otndocs/jcp/jaxrs-1.1-mrel-eval-oth-JSpec/ -func (r RouterJSR311) detectRoute(routes []Route, httpRequest *http.Request) (*Route, error) { - candidates := make([]*Route, 0, 8) - for i, each := range routes { - ok := true - for _, fn := range each.If { - if !fn(httpRequest) { - ok = false - break - } - } - if ok { - candidates = append(candidates, &routes[i]) - } - } - if len(candidates) == 0 { - if trace { - traceLogger.Printf("no Route found (from %d) that passes conditional checks", len(routes)) - } - return nil, NewError(http.StatusNotFound, "404: Not Found") - } - - // http method - previous := candidates - candidates = candidates[:0] - for _, each := range previous { - if httpRequest.Method == each.Method { - candidates = append(candidates, each) - } - } - if len(candidates) == 0 { - if trace { - traceLogger.Printf("no Route found (in %d routes) that matches HTTP method %s\n", len(previous), httpRequest.Method) - } - allowed := []string{} - allowedLoop: - for _, candidate := range previous { - for _, method := range allowed { - if method == candidate.Method { - continue allowedLoop - } - } - allowed = append(allowed, candidate.Method) - } - header := http.Header{"Allow": []string{strings.Join(allowed, ", ")}} - return nil, NewErrorWithHeader(http.StatusMethodNotAllowed, "405: Method Not Allowed", header) - } - - // content-type - contentType := httpRequest.Header.Get(HEADER_ContentType) - previous = candidates - candidates = candidates[:0] - for _, each := range previous { - if each.matchesContentType(contentType) { - candidates = append(candidates, each) - } - } - if len(candidates) == 0 { - if trace { - traceLogger.Printf("no Route found (from %d) that matches HTTP Content-Type: %s\n", len(previous), contentType) - } - return nil, NewError(http.StatusUnsupportedMediaType, "415: Unsupported Media Type") - } - - // accept - previous = candidates - candidates = candidates[:0] - accept := httpRequest.Header.Get(HEADER_Accept) - if len(accept) == 0 { - accept = "*/*" - } - for _, each := range previous { - if each.matchesAccept(accept) { - candidates = append(candidates, each) - } - } - if len(candidates) == 0 { - if trace { - traceLogger.Printf("no Route found (from %d) that matches HTTP Accept: %s\n", len(previous), accept) - } - available := []string{} - for _, candidate := range previous { - available = append(available, candidate.Produces...) - } - return nil, NewError( - http.StatusNotAcceptable, - fmt.Sprintf("406: Not Acceptable\n\nAvailable representations: %s", strings.Join(available, ", "))) - } - // return r.bestMatchByMedia(outputMediaOk, contentType, accept), nil - return candidates[0], nil -} - -// http://jsr311.java.net/nonav/releases/1.1/spec/spec3.html#x3-360003.7.2 -// n/m > n/* > */* -func (r RouterJSR311) bestMatchByMedia(routes []Route, contentType string, accept string) *Route { - // TODO - return &routes[0] -} - -// http://jsr311.java.net/nonav/releases/1.1/spec/spec3.html#x3-360003.7.2 (step 2) -func (r RouterJSR311) selectRoutes(dispatcher *WebService, pathRemainder string) []Route { - filtered := &sortableRouteCandidates{} - for _, each := range dispatcher.Routes() { - pathExpr := each.pathExpr - matches := pathExpr.Matcher.FindStringSubmatch(pathRemainder) - if matches != nil { - lastMatch := matches[len(matches)-1] - if len(lastMatch) == 0 || lastMatch == "/" { // do not include if value is neither empty nor ‘/’. - filtered.candidates = append(filtered.candidates, - routeCandidate{each, len(matches) - 1, pathExpr.LiteralCount, pathExpr.VarCount}) - } - } - } - if len(filtered.candidates) == 0 { - if trace { - traceLogger.Printf("WebService on path %s has no routes that match URL path remainder:%s\n", dispatcher.rootPath, pathRemainder) - } - return []Route{} - } - sort.Sort(sort.Reverse(filtered)) - - // select other routes from candidates whoes expression matches rmatch - matchingRoutes := []Route{filtered.candidates[0].route} - for c := 1; c < len(filtered.candidates); c++ { - each := filtered.candidates[c] - if each.route.pathExpr.Matcher.MatchString(pathRemainder) { - matchingRoutes = append(matchingRoutes, each.route) - } - } - return matchingRoutes -} - -// http://jsr311.java.net/nonav/releases/1.1/spec/spec3.html#x3-360003.7.2 (step 1) -func (r RouterJSR311) detectDispatcher(requestPath string, dispatchers []*WebService) (*WebService, string, error) { - filtered := &sortableDispatcherCandidates{} - for _, each := range dispatchers { - matches := each.pathExpr.Matcher.FindStringSubmatch(requestPath) - if matches != nil { - filtered.candidates = append(filtered.candidates, - dispatcherCandidate{each, matches[len(matches)-1], len(matches), each.pathExpr.LiteralCount, each.pathExpr.VarCount}) - } - } - if len(filtered.candidates) == 0 { - if trace { - traceLogger.Printf("no WebService was found to match URL path:%s\n", requestPath) - } - return nil, "", errors.New("not found") - } - sort.Sort(sort.Reverse(filtered)) - return filtered.candidates[0].dispatcher, filtered.candidates[0].finalMatch, nil -} - -// Types and functions to support the sorting of Routes - -type routeCandidate struct { - route Route - matchesCount int // the number of capturing groups - literalCount int // the number of literal characters (means those not resulting from template variable substitution) - nonDefaultCount int // the number of capturing groups with non-default regular expressions (i.e. not ‘([^ /]+?)’) -} - -func (r routeCandidate) expressionToMatch() string { - return r.route.pathExpr.Source -} - -func (r routeCandidate) String() string { - return fmt.Sprintf("(m=%d,l=%d,n=%d)", r.matchesCount, r.literalCount, r.nonDefaultCount) -} - -type sortableRouteCandidates struct { - candidates []routeCandidate -} - -func (rcs *sortableRouteCandidates) Len() int { - return len(rcs.candidates) -} -func (rcs *sortableRouteCandidates) Swap(i, j int) { - rcs.candidates[i], rcs.candidates[j] = rcs.candidates[j], rcs.candidates[i] -} -func (rcs *sortableRouteCandidates) Less(i, j int) bool { - ci := rcs.candidates[i] - cj := rcs.candidates[j] - // primary key - if ci.literalCount < cj.literalCount { - return true - } - if ci.literalCount > cj.literalCount { - return false - } - // secundary key - if ci.matchesCount < cj.matchesCount { - return true - } - if ci.matchesCount > cj.matchesCount { - return false - } - // tertiary key - if ci.nonDefaultCount < cj.nonDefaultCount { - return true - } - if ci.nonDefaultCount > cj.nonDefaultCount { - return false - } - // quaternary key ("source" is interpreted as Path) - return ci.route.Path < cj.route.Path -} - -// Types and functions to support the sorting of Dispatchers - -type dispatcherCandidate struct { - dispatcher *WebService - finalMatch string - matchesCount int // the number of capturing groups - literalCount int // the number of literal characters (means those not resulting from template variable substitution) - nonDefaultCount int // the number of capturing groups with non-default regular expressions (i.e. not ‘([^ /]+?)’) -} -type sortableDispatcherCandidates struct { - candidates []dispatcherCandidate -} - -func (dc *sortableDispatcherCandidates) Len() int { - return len(dc.candidates) -} -func (dc *sortableDispatcherCandidates) Swap(i, j int) { - dc.candidates[i], dc.candidates[j] = dc.candidates[j], dc.candidates[i] -} -func (dc *sortableDispatcherCandidates) Less(i, j int) bool { - ci := dc.candidates[i] - cj := dc.candidates[j] - // primary key - if ci.matchesCount < cj.matchesCount { - return true - } - if ci.matchesCount > cj.matchesCount { - return false - } - // secundary key - if ci.literalCount < cj.literalCount { - return true - } - if ci.literalCount > cj.literalCount { - return false - } - // tertiary key - return ci.nonDefaultCount < cj.nonDefaultCount -} diff --git a/vendor/github.com/emicklei/go-restful/v3/log/log.go b/vendor/github.com/emicklei/go-restful/v3/log/log.go deleted file mode 100644 index 6cd44c7a5..000000000 --- a/vendor/github.com/emicklei/go-restful/v3/log/log.go +++ /dev/null @@ -1,34 +0,0 @@ -package log - -import ( - stdlog "log" - "os" -) - -// StdLogger corresponds to a minimal subset of the interface satisfied by stdlib log.Logger -type StdLogger interface { - Print(v ...interface{}) - Printf(format string, v ...interface{}) -} - -var Logger StdLogger - -func init() { - // default Logger - SetLogger(stdlog.New(os.Stderr, "[restful] ", stdlog.LstdFlags|stdlog.Lshortfile)) -} - -// SetLogger sets the logger for this package -func SetLogger(customLogger StdLogger) { - Logger = customLogger -} - -// Print delegates to the Logger -func Print(v ...interface{}) { - Logger.Print(v...) -} - -// Printf delegates to the Logger -func Printf(format string, v ...interface{}) { - Logger.Printf(format, v...) -} diff --git a/vendor/github.com/emicklei/go-restful/v3/logger.go b/vendor/github.com/emicklei/go-restful/v3/logger.go deleted file mode 100644 index 29202726f..000000000 --- a/vendor/github.com/emicklei/go-restful/v3/logger.go +++ /dev/null @@ -1,32 +0,0 @@ -package restful - -// Copyright 2014 Ernest Micklei. All rights reserved. -// Use of this source code is governed by a license -// that can be found in the LICENSE file. -import ( - "github.com/emicklei/go-restful/v3/log" -) - -var trace bool = false -var traceLogger log.StdLogger - -func init() { - traceLogger = log.Logger // use the package logger by default -} - -// TraceLogger enables detailed logging of Http request matching and filter invocation. Default no logger is set. -// You may call EnableTracing() directly to enable trace logging to the package-wide logger. -func TraceLogger(logger log.StdLogger) { - traceLogger = logger - EnableTracing(logger != nil) -} - -// SetLogger exposes the setter for the global logger on the top-level package -func SetLogger(customLogger log.StdLogger) { - log.SetLogger(customLogger) -} - -// EnableTracing can be used to Trace logging on and off. -func EnableTracing(enabled bool) { - trace = enabled -} diff --git a/vendor/github.com/emicklei/go-restful/v3/mime.go b/vendor/github.com/emicklei/go-restful/v3/mime.go deleted file mode 100644 index 33014471b..000000000 --- a/vendor/github.com/emicklei/go-restful/v3/mime.go +++ /dev/null @@ -1,50 +0,0 @@ -package restful - -import ( - "strconv" - "strings" -) - -type mime struct { - media string - quality float64 -} - -// insertMime adds a mime to a list and keeps it sorted by quality. -func insertMime(l []mime, e mime) []mime { - for i, each := range l { - // if current mime has lower quality then insert before - if e.quality > each.quality { - left := append([]mime{}, l[0:i]...) - return append(append(left, e), l[i:]...) - } - } - return append(l, e) -} - -const qFactorWeightingKey = "q" - -// sortedMimes returns a list of mime sorted (desc) by its specified quality. -// e.g. text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3 -func sortedMimes(accept string) (sorted []mime) { - for _, each := range strings.Split(accept, ",") { - typeAndQuality := strings.Split(strings.Trim(each, " "), ";") - if len(typeAndQuality) == 1 { - sorted = insertMime(sorted, mime{typeAndQuality[0], 1.0}) - } else { - // take factor - qAndWeight := strings.Split(typeAndQuality[1], "=") - if len(qAndWeight) == 2 && strings.Trim(qAndWeight[0], " ") == qFactorWeightingKey { - f, err := strconv.ParseFloat(qAndWeight[1], 64) - if err != nil { - traceLogger.Printf("unable to parse quality in %s, %v", each, err) - } else { - sorted = insertMime(sorted, mime{typeAndQuality[0], f}) - } - } else { - sorted = insertMime(sorted, mime{typeAndQuality[0], 1.0}) - } - } - } - return -} diff --git a/vendor/github.com/emicklei/go-restful/v3/options_filter.go b/vendor/github.com/emicklei/go-restful/v3/options_filter.go deleted file mode 100644 index 5c1b34251..000000000 --- a/vendor/github.com/emicklei/go-restful/v3/options_filter.go +++ /dev/null @@ -1,34 +0,0 @@ -package restful - -import "strings" - -// Copyright 2013 Ernest Micklei. All rights reserved. -// Use of this source code is governed by a license -// that can be found in the LICENSE file. - -// OPTIONSFilter is a filter function that inspects the Http Request for the OPTIONS method -// and provides the response with a set of allowed methods for the request URL Path. -// As for any filter, you can also install it for a particular WebService within a Container. -// Note: this filter is not needed when using CrossOriginResourceSharing (for CORS). -func (c *Container) OPTIONSFilter(req *Request, resp *Response, chain *FilterChain) { - if "OPTIONS" != req.Request.Method { - chain.ProcessFilter(req, resp) - return - } - - archs := req.Request.Header.Get(HEADER_AccessControlRequestHeaders) - methods := strings.Join(c.computeAllowedMethods(req), ",") - origin := req.Request.Header.Get(HEADER_Origin) - - resp.AddHeader(HEADER_Allow, methods) - resp.AddHeader(HEADER_AccessControlAllowOrigin, origin) - resp.AddHeader(HEADER_AccessControlAllowHeaders, archs) - resp.AddHeader(HEADER_AccessControlAllowMethods, methods) -} - -// OPTIONSFilter is a filter function that inspects the Http Request for the OPTIONS method -// and provides the response with a set of allowed methods for the request URL Path. -// Note: this filter is not needed when using CrossOriginResourceSharing (for CORS). -func OPTIONSFilter() FilterFunction { - return DefaultContainer.OPTIONSFilter -} diff --git a/vendor/github.com/emicklei/go-restful/v3/parameter.go b/vendor/github.com/emicklei/go-restful/v3/parameter.go deleted file mode 100644 index 0b851bb43..000000000 --- a/vendor/github.com/emicklei/go-restful/v3/parameter.go +++ /dev/null @@ -1,242 +0,0 @@ -package restful - -import "sort" - -// Copyright 2013 Ernest Micklei. All rights reserved. -// Use of this source code is governed by a license -// that can be found in the LICENSE file. - -const ( - // PathParameterKind = indicator of Request parameter type "path" - PathParameterKind = iota - - // QueryParameterKind = indicator of Request parameter type "query" - QueryParameterKind - - // BodyParameterKind = indicator of Request parameter type "body" - BodyParameterKind - - // HeaderParameterKind = indicator of Request parameter type "header" - HeaderParameterKind - - // FormParameterKind = indicator of Request parameter type "form" - FormParameterKind - - // MultiPartFormParameterKind = indicator of Request parameter type "multipart/form-data" - MultiPartFormParameterKind - - // CollectionFormatCSV comma separated values `foo,bar` - CollectionFormatCSV = CollectionFormat("csv") - - // CollectionFormatSSV space separated values `foo bar` - CollectionFormatSSV = CollectionFormat("ssv") - - // CollectionFormatTSV tab separated values `foo\tbar` - CollectionFormatTSV = CollectionFormat("tsv") - - // CollectionFormatPipes pipe separated values `foo|bar` - CollectionFormatPipes = CollectionFormat("pipes") - - // CollectionFormatMulti corresponds to multiple parameter instances instead of multiple values for a single - // instance `foo=bar&foo=baz`. This is valid only for QueryParameters and FormParameters - CollectionFormatMulti = CollectionFormat("multi") -) - -type CollectionFormat string - -func (cf CollectionFormat) String() string { - return string(cf) -} - -// Parameter is for documententing the parameter used in a Http Request -// ParameterData kinds are Path,Query and Body -type Parameter struct { - data *ParameterData -} - -// ParameterData represents the state of a Parameter. -// It is made public to make it accessible to e.g. the Swagger package. -type ParameterData struct { - ExtensionProperties - Name, Description, DataType, DataFormat string - Kind int - Required bool - // AllowableValues is deprecated. Use PossibleValues instead - AllowableValues map[string]string - PossibleValues []string - AllowMultiple bool - AllowEmptyValue bool - DefaultValue string - CollectionFormat string - Pattern string - Minimum *float64 - Maximum *float64 - MinLength *int64 - MaxLength *int64 - MinItems *int64 - MaxItems *int64 - UniqueItems bool -} - -// Data returns the state of the Parameter -func (p *Parameter) Data() ParameterData { - return *p.data -} - -// Kind returns the parameter type indicator (see const for valid values) -func (p *Parameter) Kind() int { - return p.data.Kind -} - -func (p *Parameter) bePath() *Parameter { - p.data.Kind = PathParameterKind - return p -} -func (p *Parameter) beQuery() *Parameter { - p.data.Kind = QueryParameterKind - return p -} -func (p *Parameter) beBody() *Parameter { - p.data.Kind = BodyParameterKind - return p -} - -func (p *Parameter) beHeader() *Parameter { - p.data.Kind = HeaderParameterKind - return p -} - -func (p *Parameter) beForm() *Parameter { - p.data.Kind = FormParameterKind - return p -} - -func (p *Parameter) beMultiPartForm() *Parameter { - p.data.Kind = MultiPartFormParameterKind - return p -} - -// Required sets the required field and returns the receiver -func (p *Parameter) Required(required bool) *Parameter { - p.data.Required = required - return p -} - -// AllowMultiple sets the allowMultiple field and returns the receiver -func (p *Parameter) AllowMultiple(multiple bool) *Parameter { - p.data.AllowMultiple = multiple - return p -} - -// AddExtension adds or updates a key=value pair to the extension map -func (p *Parameter) AddExtension(key string, value interface{}) *Parameter { - p.data.AddExtension(key, value) - return p -} - -// AllowEmptyValue sets the AllowEmptyValue field and returns the receiver -func (p *Parameter) AllowEmptyValue(multiple bool) *Parameter { - p.data.AllowEmptyValue = multiple - return p -} - -// AllowableValues is deprecated. Use PossibleValues instead. Both will be set. -func (p *Parameter) AllowableValues(values map[string]string) *Parameter { - p.data.AllowableValues = values - - allowableSortedKeys := make([]string, 0, len(values)) - for k := range values { - allowableSortedKeys = append(allowableSortedKeys, k) - } - sort.Strings(allowableSortedKeys) - - p.data.PossibleValues = make([]string, 0, len(values)) - for _, k := range allowableSortedKeys { - p.data.PossibleValues = append(p.data.PossibleValues, values[k]) - } - return p -} - -// PossibleValues sets the possible values field and returns the receiver -func (p *Parameter) PossibleValues(values []string) *Parameter { - p.data.PossibleValues = values - return p -} - -// DataType sets the dataType field and returns the receiver -func (p *Parameter) DataType(typeName string) *Parameter { - p.data.DataType = typeName - return p -} - -// DataFormat sets the dataFormat field for Swagger UI -func (p *Parameter) DataFormat(formatName string) *Parameter { - p.data.DataFormat = formatName - return p -} - -// DefaultValue sets the default value field and returns the receiver -func (p *Parameter) DefaultValue(stringRepresentation string) *Parameter { - p.data.DefaultValue = stringRepresentation - return p -} - -// Description sets the description value field and returns the receiver -func (p *Parameter) Description(doc string) *Parameter { - p.data.Description = doc - return p -} - -// CollectionFormat sets the collection format for an array type -func (p *Parameter) CollectionFormat(format CollectionFormat) *Parameter { - p.data.CollectionFormat = format.String() - return p -} - -// Pattern sets the pattern field and returns the receiver -func (p *Parameter) Pattern(pattern string) *Parameter { - p.data.Pattern = pattern - return p -} - -// Minimum sets the minimum field and returns the receiver -func (p *Parameter) Minimum(minimum float64) *Parameter { - p.data.Minimum = &minimum - return p -} - -// Maximum sets the maximum field and returns the receiver -func (p *Parameter) Maximum(maximum float64) *Parameter { - p.data.Maximum = &maximum - return p -} - -// MinLength sets the minLength field and returns the receiver -func (p *Parameter) MinLength(minLength int64) *Parameter { - p.data.MinLength = &minLength - return p -} - -// MaxLength sets the maxLength field and returns the receiver -func (p *Parameter) MaxLength(maxLength int64) *Parameter { - p.data.MaxLength = &maxLength - return p -} - -// MinItems sets the minItems field and returns the receiver -func (p *Parameter) MinItems(minItems int64) *Parameter { - p.data.MinItems = &minItems - return p -} - -// MaxItems sets the maxItems field and returns the receiver -func (p *Parameter) MaxItems(maxItems int64) *Parameter { - p.data.MaxItems = &maxItems - return p -} - -// UniqueItems sets the uniqueItems field and returns the receiver -func (p *Parameter) UniqueItems(uniqueItems bool) *Parameter { - p.data.UniqueItems = uniqueItems - return p -} diff --git a/vendor/github.com/emicklei/go-restful/v3/path_expression.go b/vendor/github.com/emicklei/go-restful/v3/path_expression.go deleted file mode 100644 index 95a9a2545..000000000 --- a/vendor/github.com/emicklei/go-restful/v3/path_expression.go +++ /dev/null @@ -1,74 +0,0 @@ -package restful - -// Copyright 2013 Ernest Micklei. All rights reserved. -// Use of this source code is governed by a license -// that can be found in the LICENSE file. - -import ( - "bytes" - "fmt" - "regexp" - "strings" -) - -// PathExpression holds a compiled path expression (RegExp) needed to match against -// Http request paths and to extract path parameter values. -type pathExpression struct { - LiteralCount int // the number of literal characters (means those not resulting from template variable substitution) - VarNames []string // the names of parameters (enclosed by {}) in the path - VarCount int // the number of named parameters (enclosed by {}) in the path - Matcher *regexp.Regexp - Source string // Path as defined by the RouteBuilder - tokens []string -} - -// NewPathExpression creates a PathExpression from the input URL path. -// Returns an error if the path is invalid. -func newPathExpression(path string) (*pathExpression, error) { - expression, literalCount, varNames, varCount, tokens := templateToRegularExpression(path) - compiled, err := regexp.Compile(expression) - if err != nil { - return nil, err - } - return &pathExpression{literalCount, varNames, varCount, compiled, expression, tokens}, nil -} - -// http://jsr311.java.net/nonav/releases/1.1/spec/spec3.html#x3-370003.7.3 -func templateToRegularExpression(template string) (expression string, literalCount int, varNames []string, varCount int, tokens []string) { - var buffer bytes.Buffer - buffer.WriteString("^") - //tokens = strings.Split(template, "/") - tokens = tokenizePath(template) - for _, each := range tokens { - if each == "" { - continue - } - buffer.WriteString("/") - if strings.HasPrefix(each, "{") { - // check for regular expression in variable - colon := strings.Index(each, ":") - var varName string - if colon != -1 { - // extract expression - varName = strings.TrimSpace(each[1:colon]) - paramExpr := strings.TrimSpace(each[colon+1 : len(each)-1]) - if paramExpr == "*" { // special case - buffer.WriteString("(.*)") - } else { - buffer.WriteString(fmt.Sprintf("(%s)", paramExpr)) // between colon and closing moustache - } - } else { - // plain var - varName = strings.TrimSpace(each[1 : len(each)-1]) - buffer.WriteString("([^/]+?)") - } - varNames = append(varNames, varName) - varCount += 1 - } else { - literalCount += len(each) - encoded := each // TODO URI encode - buffer.WriteString(regexp.QuoteMeta(encoded)) - } - } - return strings.TrimRight(buffer.String(), "/") + "(/.*)?$", literalCount, varNames, varCount, tokens -} diff --git a/vendor/github.com/emicklei/go-restful/v3/path_processor.go b/vendor/github.com/emicklei/go-restful/v3/path_processor.go deleted file mode 100644 index 141573245..000000000 --- a/vendor/github.com/emicklei/go-restful/v3/path_processor.go +++ /dev/null @@ -1,74 +0,0 @@ -package restful - -import ( - "bytes" - "strings" -) - -// Copyright 2018 Ernest Micklei. All rights reserved. -// Use of this source code is governed by a license -// that can be found in the LICENSE file. - -// PathProcessor is extra behaviour that a Router can provide to extract path parameters from the path. -// If a Router does not implement this interface then the default behaviour will be used. -type PathProcessor interface { - // ExtractParameters gets the path parameters defined in the route and webService from the urlPath - ExtractParameters(route *Route, webService *WebService, urlPath string) map[string]string -} - -type defaultPathProcessor struct{} - -// Extract the parameters from the request url path -func (d defaultPathProcessor) ExtractParameters(r *Route, _ *WebService, urlPath string) map[string]string { - urlParts := tokenizePath(urlPath) - pathParameters := map[string]string{} - for i, key := range r.pathParts { - var value string - if i >= len(urlParts) { - value = "" - } else { - value = urlParts[i] - } - if r.hasCustomVerb && hasCustomVerb(key) { - key = removeCustomVerb(key) - value = removeCustomVerb(value) - } - - if strings.Index(key, "{") > -1 { // path-parameter - if colon := strings.Index(key, ":"); colon != -1 { - // extract by regex - regPart := key[colon+1 : len(key)-1] - keyPart := key[1:colon] - if regPart == "*" { - pathParameters[keyPart] = untokenizePath(i, urlParts) - break - } else { - pathParameters[keyPart] = value - } - } else { - // without enclosing {} - startIndex := strings.Index(key, "{") - endKeyIndex := strings.Index(key, "}") - - suffixLength := len(key) - endKeyIndex - 1 - endValueIndex := len(value) - suffixLength - - pathParameters[key[startIndex+1:endKeyIndex]] = value[startIndex:endValueIndex] - } - } - } - return pathParameters -} - -// Untokenize back into an URL path using the slash separator -func untokenizePath(offset int, parts []string) string { - var buffer bytes.Buffer - for p := offset; p < len(parts); p++ { - buffer.WriteString(parts[p]) - // do not end - if p < len(parts)-1 { - buffer.WriteString("/") - } - } - return buffer.String() -} diff --git a/vendor/github.com/emicklei/go-restful/v3/request.go b/vendor/github.com/emicklei/go-restful/v3/request.go deleted file mode 100644 index 0020095e8..000000000 --- a/vendor/github.com/emicklei/go-restful/v3/request.go +++ /dev/null @@ -1,133 +0,0 @@ -package restful - -// Copyright 2013 Ernest Micklei. All rights reserved. -// Use of this source code is governed by a license -// that can be found in the LICENSE file. - -import ( - "compress/zlib" - "net/http" -) - -var defaultRequestContentType string - -// Request is a wrapper for a http Request that provides convenience methods -type Request struct { - Request *http.Request - pathParameters map[string]string - attributes map[string]interface{} // for storing request-scoped values - selectedRoute *Route // is nil when no route was matched -} - -func NewRequest(httpRequest *http.Request) *Request { - return &Request{ - Request: httpRequest, - pathParameters: map[string]string{}, - attributes: map[string]interface{}{}, - } // empty parameters, attributes -} - -// If ContentType is missing or */* is given then fall back to this type, otherwise -// a "Unable to unmarshal content of type:" response is returned. -// Valid values are restful.MIME_JSON and restful.MIME_XML -// Example: -// -// restful.DefaultRequestContentType(restful.MIME_JSON) -func DefaultRequestContentType(mime string) { - defaultRequestContentType = mime -} - -// PathParameter accesses the Path parameter value by its name -func (r *Request) PathParameter(name string) string { - return r.pathParameters[name] -} - -// PathParameters accesses the Path parameter values -func (r *Request) PathParameters() map[string]string { - return r.pathParameters -} - -// QueryParameter returns the (first) Query parameter value by its name -func (r *Request) QueryParameter(name string) string { - return r.Request.URL.Query().Get(name) -} - -// QueryParameters returns the all the query parameters values by name -func (r *Request) QueryParameters(name string) []string { - return r.Request.URL.Query()[name] -} - -// BodyParameter parses the body of the request (once for typically a POST or a PUT) and returns the value of the given name or an error. -func (r *Request) BodyParameter(name string) (string, error) { - err := r.Request.ParseForm() - if err != nil { - return "", err - } - return r.Request.PostFormValue(name), nil -} - -// HeaderParameter returns the HTTP Header value of a Header name or empty if missing -func (r *Request) HeaderParameter(name string) string { - return r.Request.Header.Get(name) -} - -// ReadEntity checks the Accept header and reads the content into the entityPointer. -func (r *Request) ReadEntity(entityPointer interface{}) (err error) { - contentType := r.Request.Header.Get(HEADER_ContentType) - contentEncoding := r.Request.Header.Get(HEADER_ContentEncoding) - - // check if the request body needs decompression - if ENCODING_GZIP == contentEncoding { - gzipReader := currentCompressorProvider.AcquireGzipReader() - defer currentCompressorProvider.ReleaseGzipReader(gzipReader) - gzipReader.Reset(r.Request.Body) - r.Request.Body = gzipReader - } else if ENCODING_DEFLATE == contentEncoding { - zlibReader, err := zlib.NewReader(r.Request.Body) - if err != nil { - return err - } - r.Request.Body = zlibReader - } - - // lookup the EntityReader, use defaultRequestContentType if needed and provided - entityReader, ok := entityAccessRegistry.accessorAt(contentType) - if !ok { - if len(defaultRequestContentType) != 0 { - entityReader, ok = entityAccessRegistry.accessorAt(defaultRequestContentType) - } - if !ok { - return NewError(http.StatusBadRequest, "Unable to unmarshal content of type:"+contentType) - } - } - return entityReader.Read(r, entityPointer) -} - -// SetAttribute adds or replaces the attribute with the given value. -func (r *Request) SetAttribute(name string, value interface{}) { - r.attributes[name] = value -} - -// Attribute returns the value associated to the given name. Returns nil if absent. -func (r Request) Attribute(name string) interface{} { - return r.attributes[name] -} - -// SelectedRoutePath root path + route path that matched the request, e.g. /meetings/{id}/attendees -// If no route was matched then return an empty string. -func (r Request) SelectedRoutePath() string { - if r.selectedRoute == nil { - return "" - } - // skip creating an accessor - return r.selectedRoute.Path -} - -// SelectedRoute returns a reader to access the selected Route by the container -// Returns nil if no route was matched. -func (r Request) SelectedRoute() RouteReader { - if r.selectedRoute == nil { - return nil - } - return routeAccessor{route: r.selectedRoute} -} diff --git a/vendor/github.com/emicklei/go-restful/v3/response.go b/vendor/github.com/emicklei/go-restful/v3/response.go deleted file mode 100644 index a41a92cc2..000000000 --- a/vendor/github.com/emicklei/go-restful/v3/response.go +++ /dev/null @@ -1,259 +0,0 @@ -package restful - -// Copyright 2013 Ernest Micklei. All rights reserved. -// Use of this source code is governed by a license -// that can be found in the LICENSE file. - -import ( - "bufio" - "errors" - "net" - "net/http" -) - -// DefaultResponseMimeType is DEPRECATED, use DefaultResponseContentType(mime) -var DefaultResponseMimeType string - -//PrettyPrintResponses controls the indentation feature of XML and JSON serialization -var PrettyPrintResponses = true - -// Response is a wrapper on the actual http ResponseWriter -// It provides several convenience methods to prepare and write response content. -type Response struct { - http.ResponseWriter - requestAccept string // mime-type what the Http Request says it wants to receive - routeProduces []string // mime-types what the Route says it can produce - statusCode int // HTTP status code that has been written explicitly (if zero then net/http has written 200) - contentLength int // number of bytes written for the response body - prettyPrint bool // controls the indentation feature of XML and JSON serialization. It is initialized using var PrettyPrintResponses. - err error // err property is kept when WriteError is called - hijacker http.Hijacker // if underlying ResponseWriter supports it -} - -// NewResponse creates a new response based on a http ResponseWriter. -func NewResponse(httpWriter http.ResponseWriter) *Response { - hijacker, _ := httpWriter.(http.Hijacker) - return &Response{ResponseWriter: httpWriter, routeProduces: []string{}, statusCode: http.StatusOK, prettyPrint: PrettyPrintResponses, hijacker: hijacker} -} - -// DefaultResponseContentType set a default. -// If Accept header matching fails, fall back to this type. -// Valid values are restful.MIME_JSON and restful.MIME_XML -// Example: -// restful.DefaultResponseContentType(restful.MIME_JSON) -func DefaultResponseContentType(mime string) { - DefaultResponseMimeType = mime -} - -// InternalServerError writes the StatusInternalServerError header. -// DEPRECATED, use WriteErrorString(http.StatusInternalServerError,reason) -func (r Response) InternalServerError() Response { - r.WriteHeader(http.StatusInternalServerError) - return r -} - -// Hijack implements the http.Hijacker interface. This expands -// the Response to fulfill http.Hijacker if the underlying -// http.ResponseWriter supports it. -func (r *Response) Hijack() (net.Conn, *bufio.ReadWriter, error) { - if r.hijacker == nil { - return nil, nil, errors.New("http.Hijacker not implemented by underlying http.ResponseWriter") - } - return r.hijacker.Hijack() -} - -// PrettyPrint changes whether this response must produce pretty (line-by-line, indented) JSON or XML output. -func (r *Response) PrettyPrint(bePretty bool) { - r.prettyPrint = bePretty -} - -// AddHeader is a shortcut for .Header().Add(header,value) -func (r Response) AddHeader(header string, value string) Response { - r.Header().Add(header, value) - return r -} - -// SetRequestAccepts tells the response what Mime-type(s) the HTTP request said it wants to accept. Exposed for testing. -func (r *Response) SetRequestAccepts(mime string) { - r.requestAccept = mime -} - -// EntityWriter returns the registered EntityWriter that the entity (requested resource) -// can write according to what the request wants (Accept) and what the Route can produce or what the restful defaults say. -// If called before WriteEntity and WriteHeader then a false return value can be used to write a 406: Not Acceptable. -func (r *Response) EntityWriter() (EntityReaderWriter, bool) { - sorted := sortedMimes(r.requestAccept) - for _, eachAccept := range sorted { - for _, eachProduce := range r.routeProduces { - if eachProduce == eachAccept.media { - if w, ok := entityAccessRegistry.accessorAt(eachAccept.media); ok { - return w, true - } - } - } - if eachAccept.media == "*/*" { - for _, each := range r.routeProduces { - if w, ok := entityAccessRegistry.accessorAt(each); ok { - return w, true - } - } - } - } - // if requestAccept is empty - writer, ok := entityAccessRegistry.accessorAt(r.requestAccept) - if !ok { - // if not registered then fallback to the defaults (if set) - if DefaultResponseMimeType == MIME_JSON { - return entityAccessRegistry.accessorAt(MIME_JSON) - } - if DefaultResponseMimeType == MIME_XML { - return entityAccessRegistry.accessorAt(MIME_XML) - } - if DefaultResponseMimeType == MIME_ZIP { - return entityAccessRegistry.accessorAt(MIME_ZIP) - } - // Fallback to whatever the route says it can produce. - // https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html - for _, each := range r.routeProduces { - if w, ok := entityAccessRegistry.accessorAt(each); ok { - return w, true - } - } - if trace { - traceLogger.Printf("no registered EntityReaderWriter found for %s", r.requestAccept) - } - } - return writer, ok -} - -// WriteEntity calls WriteHeaderAndEntity with Http Status OK (200) -func (r *Response) WriteEntity(value interface{}) error { - return r.WriteHeaderAndEntity(http.StatusOK, value) -} - -// WriteHeaderAndEntity marshals the value using the representation denoted by the Accept Header and the registered EntityWriters. -// If no Accept header is specified (or */*) then respond with the Content-Type as specified by the first in the Route.Produces. -// If an Accept header is specified then respond with the Content-Type as specified by the first in the Route.Produces that is matched with the Accept header. -// If the value is nil then no response is send except for the Http status. You may want to call WriteHeader(http.StatusNotFound) instead. -// If there is no writer available that can represent the value in the requested MIME type then Http Status NotAcceptable is written. -// Current implementation ignores any q-parameters in the Accept Header. -// Returns an error if the value could not be written on the response. -func (r *Response) WriteHeaderAndEntity(status int, value interface{}) error { - writer, ok := r.EntityWriter() - if !ok { - r.WriteHeader(http.StatusNotAcceptable) - return nil - } - return writer.Write(r, status, value) -} - -// WriteAsXml is a convenience method for writing a value in xml (requires Xml tags on the value) -// It uses the standard encoding/xml package for marshalling the value ; not using a registered EntityReaderWriter. -func (r *Response) WriteAsXml(value interface{}) error { - return writeXML(r, http.StatusOK, MIME_XML, value) -} - -// WriteHeaderAndXml is a convenience method for writing a status and value in xml (requires Xml tags on the value) -// It uses the standard encoding/xml package for marshalling the value ; not using a registered EntityReaderWriter. -func (r *Response) WriteHeaderAndXml(status int, value interface{}) error { - return writeXML(r, status, MIME_XML, value) -} - -// WriteAsJson is a convenience method for writing a value in json. -// It uses the standard encoding/json package for marshalling the value ; not using a registered EntityReaderWriter. -func (r *Response) WriteAsJson(value interface{}) error { - return writeJSON(r, http.StatusOK, MIME_JSON, value) -} - -// WriteJson is a convenience method for writing a value in Json with a given Content-Type. -// It uses the standard encoding/json package for marshalling the value ; not using a registered EntityReaderWriter. -func (r *Response) WriteJson(value interface{}, contentType string) error { - return writeJSON(r, http.StatusOK, contentType, value) -} - -// WriteHeaderAndJson is a convenience method for writing the status and a value in Json with a given Content-Type. -// It uses the standard encoding/json package for marshalling the value ; not using a registered EntityReaderWriter. -func (r *Response) WriteHeaderAndJson(status int, value interface{}, contentType string) error { - return writeJSON(r, status, contentType, value) -} - -// WriteError writes the http status and the error string on the response. err can be nil. -// Return an error if writing was not successful. -func (r *Response) WriteError(httpStatus int, err error) (writeErr error) { - r.err = err - if err == nil { - writeErr = r.WriteErrorString(httpStatus, "") - } else { - writeErr = r.WriteErrorString(httpStatus, err.Error()) - } - return writeErr -} - -// WriteServiceError is a convenience method for a responding with a status and a ServiceError -func (r *Response) WriteServiceError(httpStatus int, err ServiceError) error { - r.err = err - return r.WriteHeaderAndEntity(httpStatus, err) -} - -// WriteErrorString is a convenience method for an error status with the actual error -func (r *Response) WriteErrorString(httpStatus int, errorReason string) error { - if r.err == nil { - // if not called from WriteError - r.err = errors.New(errorReason) - } - r.WriteHeader(httpStatus) - if _, err := r.Write([]byte(errorReason)); err != nil { - return err - } - return nil -} - -// Flush implements http.Flusher interface, which sends any buffered data to the client. -func (r *Response) Flush() { - if f, ok := r.ResponseWriter.(http.Flusher); ok { - f.Flush() - } else if trace { - traceLogger.Printf("ResponseWriter %v doesn't support Flush", r) - } -} - -// WriteHeader is overridden to remember the Status Code that has been written. -// Changes to the Header of the response have no effect after this. -func (r *Response) WriteHeader(httpStatus int) { - r.statusCode = httpStatus - r.ResponseWriter.WriteHeader(httpStatus) -} - -// StatusCode returns the code that has been written using WriteHeader. -func (r Response) StatusCode() int { - if 0 == r.statusCode { - // no status code has been written yet; assume OK - return http.StatusOK - } - return r.statusCode -} - -// Write writes the data to the connection as part of an HTTP reply. -// Write is part of http.ResponseWriter interface. -func (r *Response) Write(bytes []byte) (int, error) { - written, err := r.ResponseWriter.Write(bytes) - r.contentLength += written - return written, err -} - -// ContentLength returns the number of bytes written for the response content. -// Note that this value is only correct if all data is written through the Response using its Write* methods. -// Data written directly using the underlying http.ResponseWriter is not accounted for. -func (r Response) ContentLength() int { - return r.contentLength -} - -// CloseNotify is part of http.CloseNotifier interface -func (r Response) CloseNotify() <-chan bool { - return r.ResponseWriter.(http.CloseNotifier).CloseNotify() -} - -// Error returns the err created by WriteError -func (r Response) Error() error { - return r.err -} diff --git a/vendor/github.com/emicklei/go-restful/v3/route.go b/vendor/github.com/emicklei/go-restful/v3/route.go deleted file mode 100644 index a2056e2ac..000000000 --- a/vendor/github.com/emicklei/go-restful/v3/route.go +++ /dev/null @@ -1,193 +0,0 @@ -package restful - -// Copyright 2013 Ernest Micklei. All rights reserved. -// Use of this source code is governed by a license -// that can be found in the LICENSE file. - -import ( - "net/http" - "strings" -) - -// RouteFunction declares the signature of a function that can be bound to a Route. -type RouteFunction func(*Request, *Response) - -// RouteSelectionConditionFunction declares the signature of a function that -// can be used to add extra conditional logic when selecting whether the route -// matches the HTTP request. -type RouteSelectionConditionFunction func(httpRequest *http.Request) bool - -// Route binds a HTTP Method,Path,Consumes combination to a RouteFunction. -type Route struct { - ExtensionProperties - Method string - Produces []string - Consumes []string - Path string // webservice root path + described path - Function RouteFunction - Filters []FilterFunction - If []RouteSelectionConditionFunction - - // cached values for dispatching - relativePath string - pathParts []string - pathExpr *pathExpression // cached compilation of relativePath as RegExp - - // documentation - Doc string - Notes string - Operation string - ParameterDocs []*Parameter - ResponseErrors map[int]ResponseError - DefaultResponse *ResponseError - ReadSample, WriteSample interface{} // structs that model an example request or response payload - WriteSamples []interface{} // if more than one return types is possible (oneof) then this will contain multiple values - - // Extra information used to store custom information about the route. - Metadata map[string]interface{} - - // marks a route as deprecated - Deprecated bool - - //Overrides the container.contentEncodingEnabled - contentEncodingEnabled *bool - - // indicate route path has custom verb - hasCustomVerb bool - - // if a request does not include a content-type header then - // depending on the method, it may return a 415 Unsupported Media - // Must have uppercase HTTP Method names such as GET,HEAD,OPTIONS,... - allowedMethodsWithoutContentType []string -} - -// Initialize for Route -func (r *Route) postBuild() { - r.pathParts = tokenizePath(r.Path) - r.hasCustomVerb = hasCustomVerb(r.Path) -} - -// Create Request and Response from their http versions -func (r *Route) wrapRequestResponse(httpWriter http.ResponseWriter, httpRequest *http.Request, pathParams map[string]string) (*Request, *Response) { - wrappedRequest := NewRequest(httpRequest) - wrappedRequest.pathParameters = pathParams - wrappedRequest.selectedRoute = r - wrappedResponse := NewResponse(httpWriter) - wrappedResponse.requestAccept = httpRequest.Header.Get(HEADER_Accept) - wrappedResponse.routeProduces = r.Produces - return wrappedRequest, wrappedResponse -} - -func stringTrimSpaceCutset(r rune) bool { - return r == ' ' -} - -// Return whether the mimeType matches to what this Route can produce. -func (r Route) matchesAccept(mimeTypesWithQuality string) bool { - remaining := mimeTypesWithQuality - for { - var mimeType string - if end := strings.Index(remaining, ","); end == -1 { - mimeType, remaining = remaining, "" - } else { - mimeType, remaining = remaining[:end], remaining[end+1:] - } - if quality := strings.Index(mimeType, ";"); quality != -1 { - mimeType = mimeType[:quality] - } - mimeType = strings.TrimFunc(mimeType, stringTrimSpaceCutset) - if mimeType == "*/*" { - return true - } - for _, producibleType := range r.Produces { - if producibleType == "*/*" || producibleType == mimeType { - return true - } - } - if len(remaining) == 0 { - return false - } - } -} - -// Return whether this Route can consume content with a type specified by mimeTypes (can be empty). -// If the route does not specify Consumes then return true (*/*). -// If no content type is set then return true for GET,HEAD,OPTIONS,DELETE and TRACE. -func (r Route) matchesContentType(mimeTypes string) bool { - - if len(r.Consumes) == 0 { - // did not specify what it can consume ; any media type (“*/*”) is assumed - return true - } - - if len(mimeTypes) == 0 { - // idempotent methods with (most-likely or guaranteed) empty content match missing Content-Type - m := r.Method - // if route specifies less or non-idempotent methods then use that - if len(r.allowedMethodsWithoutContentType) > 0 { - for _, each := range r.allowedMethodsWithoutContentType { - if m == each { - return true - } - } - } else { - if m == "GET" || m == "HEAD" || m == "OPTIONS" || m == "DELETE" || m == "TRACE" { - return true - } - } - // proceed with default - mimeTypes = MIME_OCTET - } - - remaining := mimeTypes - for { - var mimeType string - if end := strings.Index(remaining, ","); end == -1 { - mimeType, remaining = remaining, "" - } else { - mimeType, remaining = remaining[:end], remaining[end+1:] - } - if quality := strings.Index(mimeType, ";"); quality != -1 { - mimeType = mimeType[:quality] - } - mimeType = strings.TrimFunc(mimeType, stringTrimSpaceCutset) - for _, consumeableType := range r.Consumes { - if consumeableType == "*/*" || consumeableType == mimeType { - return true - } - } - if len(remaining) == 0 { - return false - } - } -} - -// Tokenize an URL path using the slash separator ; the result does not have empty tokens -func tokenizePath(path string) []string { - if "/" == path { - return nil - } - if TrimRightSlashEnabled { - // 3.9.0 - return strings.Split(strings.Trim(path, "/"), "/") - } else { - // 3.10.2 - return strings.Split(strings.TrimLeft(path, "/"), "/") - } -} - -// for debugging -func (r *Route) String() string { - return r.Method + " " + r.Path -} - -// EnableContentEncoding (default=false) allows for GZIP or DEFLATE encoding of responses. Overrides the container.contentEncodingEnabled value. -func (r *Route) EnableContentEncoding(enabled bool) { - r.contentEncodingEnabled = &enabled -} - -// TrimRightSlashEnabled controls whether -// - path on route building is using path.Join -// - the path of the incoming request is trimmed of its slash suffux. -// Value of true matches the behavior of <= 3.9.0 -var TrimRightSlashEnabled = true diff --git a/vendor/github.com/emicklei/go-restful/v3/route_builder.go b/vendor/github.com/emicklei/go-restful/v3/route_builder.go deleted file mode 100644 index 75168c12e..000000000 --- a/vendor/github.com/emicklei/go-restful/v3/route_builder.go +++ /dev/null @@ -1,389 +0,0 @@ -package restful - -// Copyright 2013 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" - "os" - "path" - "reflect" - "runtime" - "strings" - "sync/atomic" - - "github.com/emicklei/go-restful/v3/log" -) - -// RouteBuilder is a helper to construct Routes. -type RouteBuilder struct { - rootPath string - currentPath string - produces []string - consumes []string - httpMethod string // required - function RouteFunction // required - filters []FilterFunction - conditions []RouteSelectionConditionFunction - allowedMethodsWithoutContentType []string // see Route - - typeNameHandleFunc TypeNameHandleFunction // required - - // documentation - doc string - notes string - operation string - readSample interface{} - writeSamples []interface{} - parameters []*Parameter - errorMap map[int]ResponseError - defaultResponse *ResponseError - metadata map[string]interface{} - extensions map[string]interface{} - deprecated bool - contentEncodingEnabled *bool -} - -// Do evaluates each argument with the RouteBuilder itself. -// This allows you to follow DRY principles without breaking the fluent programming style. -// Example: -// -// ws.Route(ws.DELETE("/{name}").To(t.deletePerson).Do(Returns200, Returns500)) -// -// func Returns500(b *RouteBuilder) { -// b.Returns(500, "Internal Server Error", restful.ServiceError{}) -// } -func (b *RouteBuilder) Do(oneArgBlocks ...func(*RouteBuilder)) *RouteBuilder { - for _, each := range oneArgBlocks { - each(b) - } - return b -} - -// To bind the route to a function. -// If this route is matched with the incoming Http Request then call this function with the *Request,*Response pair. Required. -func (b *RouteBuilder) To(function RouteFunction) *RouteBuilder { - b.function = function - return b -} - -// Method specifies what HTTP method to match. Required. -func (b *RouteBuilder) Method(method string) *RouteBuilder { - b.httpMethod = method - return b -} - -// Produces specifies what MIME types can be produced ; the matched one will appear in the Content-Type Http header. -func (b *RouteBuilder) Produces(mimeTypes ...string) *RouteBuilder { - b.produces = mimeTypes - return b -} - -// Consumes specifies what MIME types can be consumes ; the Accept Http header must matched any of these -func (b *RouteBuilder) Consumes(mimeTypes ...string) *RouteBuilder { - b.consumes = mimeTypes - return b -} - -// Path specifies the relative (w.r.t WebService root path) URL path to match. Default is "/". -func (b *RouteBuilder) Path(subPath string) *RouteBuilder { - b.currentPath = subPath - return b -} - -// Doc tells what this route is all about. Optional. -func (b *RouteBuilder) Doc(documentation string) *RouteBuilder { - b.doc = documentation - return b -} - -// Notes is a verbose explanation of the operation behavior. Optional. -func (b *RouteBuilder) Notes(notes string) *RouteBuilder { - b.notes = notes - return b -} - -// Reads tells what resource type will be read from the request payload. Optional. -// A parameter of type "body" is added ,required is set to true and the dataType is set to the qualified name of the sample's type. -func (b *RouteBuilder) Reads(sample interface{}, optionalDescription ...string) *RouteBuilder { - fn := b.typeNameHandleFunc - if fn == nil { - fn = reflectTypeName - } - typeAsName := fn(sample) - description := "" - if len(optionalDescription) > 0 { - description = optionalDescription[0] - } - b.readSample = sample - bodyParameter := &Parameter{&ParameterData{Name: "body", Description: description}} - bodyParameter.beBody() - bodyParameter.Required(true) - bodyParameter.DataType(typeAsName) - b.Param(bodyParameter) - return b -} - -// ParameterNamed returns a Parameter already known to the RouteBuilder. Returns nil if not. -// Use this to modify or extend information for the Parameter (through its Data()). -func (b RouteBuilder) ParameterNamed(name string) (p *Parameter) { - for _, each := range b.parameters { - if each.Data().Name == name { - return each - } - } - return p -} - -// Writes tells which one of the resource types will be written as the response payload. Optional. -func (b *RouteBuilder) Writes(samples ...interface{}) *RouteBuilder { - b.writeSamples = samples // oneof - return b -} - -// Param allows you to document the parameters of the Route. It adds a new Parameter (does not check for duplicates). -func (b *RouteBuilder) Param(parameter *Parameter) *RouteBuilder { - if b.parameters == nil { - b.parameters = []*Parameter{} - } - b.parameters = append(b.parameters, parameter) - return b -} - -// Operation allows you to document what the actual method/function call is of the Route. -// Unless called, the operation name is derived from the RouteFunction set using To(..). -func (b *RouteBuilder) Operation(name string) *RouteBuilder { - b.operation = name - return b -} - -// ReturnsError is deprecated, use Returns instead. -func (b *RouteBuilder) ReturnsError(code int, message string, model interface{}) *RouteBuilder { - log.Print("ReturnsError is deprecated, use Returns instead.") - return b.Returns(code, message, model) -} - -// Returns allows you to document what responses (errors or regular) can be expected. -// The model parameter is optional ; either pass a struct instance or use nil if not applicable. -func (b *RouteBuilder) Returns(code int, message string, model interface{}) *RouteBuilder { - err := ResponseError{ - Code: code, - Message: message, - Model: model, - IsDefault: false, // this field is deprecated, use default response instead. - } - // lazy init because there is no NewRouteBuilder (yet) - if b.errorMap == nil { - b.errorMap = map[int]ResponseError{} - } - b.errorMap[code] = err - return b -} - -// ReturnsWithHeaders is similar to Returns, but can specify response headers -func (b *RouteBuilder) ReturnsWithHeaders(code int, message string, model interface{}, headers map[string]Header) *RouteBuilder { - b.Returns(code, message, model) - err := b.errorMap[code] - err.Headers = headers - b.errorMap[code] = err - return b -} - -// DefaultReturns is a special Returns call that sets the default of the response. -func (b *RouteBuilder) DefaultReturns(message string, model interface{}) *RouteBuilder { - b.defaultResponse = &ResponseError{ - Message: message, - Model: model, - } - return b -} - -// Metadata adds or updates a key=value pair to the metadata map. -func (b *RouteBuilder) Metadata(key string, value interface{}) *RouteBuilder { - if b.metadata == nil { - b.metadata = map[string]interface{}{} - } - b.metadata[key] = value - return b -} - -// AddExtension adds or updates a key=value pair to the extensions map. -func (b *RouteBuilder) AddExtension(key string, value interface{}) *RouteBuilder { - if b.extensions == nil { - b.extensions = map[string]interface{}{} - } - b.extensions[key] = value - return b -} - -// Deprecate sets the value of deprecated to true. Deprecated routes have a special UI treatment to warn against use -func (b *RouteBuilder) Deprecate() *RouteBuilder { - b.deprecated = true - return b -} - -// AllowedMethodsWithoutContentType overrides the default list GET,HEAD,OPTIONS,DELETE,TRACE -// If a request does not include a content-type header then -// depending on the method, it may return a 415 Unsupported Media. -// Must have uppercase HTTP Method names such as GET,HEAD,OPTIONS,... -func (b *RouteBuilder) AllowedMethodsWithoutContentType(methods []string) *RouteBuilder { - b.allowedMethodsWithoutContentType = methods - return b -} - -// ResponseError represents a response; not necessarily an error. -type ResponseError struct { - ExtensionProperties - Code int - Message string - Model interface{} - Headers map[string]Header - IsDefault bool -} - -// Header describes a header for a response of the API -// -// For more information: http://goo.gl/8us55a#headerObject -type Header struct { - *Items - Description string -} - -// Items describe swagger simple schemas for headers -type Items struct { - Type string - Format string - Items *Items - CollectionFormat string - Default interface{} -} - -func (b *RouteBuilder) servicePath(path string) *RouteBuilder { - b.rootPath = path - return b -} - -// Filter appends a FilterFunction to the end of filters for this Route to build. -func (b *RouteBuilder) Filter(filter FilterFunction) *RouteBuilder { - b.filters = append(b.filters, filter) - return b -} - -// If sets a condition function that controls matching the Route based on custom logic. -// The condition function is provided the HTTP request and should return true if the route -// should be considered. -// -// Efficiency note: the condition function is called before checking the method, produces, and -// consumes criteria, so that the correct HTTP status code can be returned. -// -// Lifecycle note: no filter functions have been called prior to calling the condition function, -// so the condition function should not depend on any context that might be set up by container -// or route filters. -func (b *RouteBuilder) If(condition RouteSelectionConditionFunction) *RouteBuilder { - b.conditions = append(b.conditions, condition) - return b -} - -// ContentEncodingEnabled allows you to override the Containers value for auto-compressing this route response. -func (b *RouteBuilder) ContentEncodingEnabled(enabled bool) *RouteBuilder { - b.contentEncodingEnabled = &enabled - return b -} - -// If no specific Route path then set to rootPath -// If no specific Produces then set to rootProduces -// If no specific Consumes then set to rootConsumes -func (b *RouteBuilder) copyDefaults(rootProduces, rootConsumes []string) { - if len(b.produces) == 0 { - b.produces = rootProduces - } - if len(b.consumes) == 0 { - b.consumes = rootConsumes - } -} - -// typeNameHandler sets the function that will convert types to strings in the parameter -// and model definitions. -func (b *RouteBuilder) typeNameHandler(handler TypeNameHandleFunction) *RouteBuilder { - b.typeNameHandleFunc = handler - return b -} - -// Build creates a new Route using the specification details collected by the RouteBuilder -func (b *RouteBuilder) Build() Route { - pathExpr, err := newPathExpression(b.currentPath) - if err != nil { - log.Printf("Invalid path:%s because:%v", b.currentPath, err) - os.Exit(1) - } - if b.function == nil { - log.Printf("No function specified for route:" + b.currentPath) - os.Exit(1) - } - operationName := b.operation - if len(operationName) == 0 && b.function != nil { - // extract from definition - operationName = nameOfFunction(b.function) - } - route := Route{ - Method: b.httpMethod, - Path: concatPath(b.rootPath, b.currentPath), - Produces: b.produces, - Consumes: b.consumes, - Function: b.function, - Filters: b.filters, - If: b.conditions, - relativePath: b.currentPath, - pathExpr: pathExpr, - Doc: b.doc, - Notes: b.notes, - Operation: operationName, - ParameterDocs: b.parameters, - ResponseErrors: b.errorMap, - DefaultResponse: b.defaultResponse, - ReadSample: b.readSample, - WriteSamples: b.writeSamples, - Metadata: b.metadata, - Deprecated: b.deprecated, - contentEncodingEnabled: b.contentEncodingEnabled, - allowedMethodsWithoutContentType: b.allowedMethodsWithoutContentType, - } - // set WriteSample if one specified - if len(b.writeSamples) == 1 { - route.WriteSample = b.writeSamples[0] - } - route.Extensions = b.extensions - route.postBuild() - return route -} - -// merge two paths using the current (package global) merge path strategy. -func concatPath(rootPath, routePath string) string { - - if TrimRightSlashEnabled { - return strings.TrimRight(rootPath, "/") + "/" + strings.TrimLeft(routePath, "/") - } else { - return path.Join(rootPath, routePath) - } -} - -var anonymousFuncCount int32 - -// nameOfFunction returns the short name of the function f for documentation. -// It uses a runtime feature for debugging ; its value may change for later Go versions. -func nameOfFunction(f interface{}) string { - fun := runtime.FuncForPC(reflect.ValueOf(f).Pointer()) - tokenized := strings.Split(fun.Name(), ".") - last := tokenized[len(tokenized)-1] - last = strings.TrimSuffix(last, ")·fm") // < Go 1.5 - last = strings.TrimSuffix(last, ")-fm") // Go 1.5 - last = strings.TrimSuffix(last, "·fm") // < Go 1.5 - last = strings.TrimSuffix(last, "-fm") // Go 1.5 - if last == "func1" { // this could mean conflicts in API docs - val := atomic.AddInt32(&anonymousFuncCount, 1) - last = "func" + fmt.Sprintf("%d", val) - atomic.StoreInt32(&anonymousFuncCount, val) - } - return last -} diff --git a/vendor/github.com/emicklei/go-restful/v3/route_reader.go b/vendor/github.com/emicklei/go-restful/v3/route_reader.go deleted file mode 100644 index c9f4ee75f..000000000 --- a/vendor/github.com/emicklei/go-restful/v3/route_reader.go +++ /dev/null @@ -1,66 +0,0 @@ -package restful - -// Copyright 2021 Ernest Micklei. All rights reserved. -// Use of this source code is governed by a license -// that can be found in the LICENSE file. - -type RouteReader interface { - Method() string - Consumes() []string - Path() string - Doc() string - Notes() string - Operation() string - ParameterDocs() []*Parameter - // Returns a copy - Metadata() map[string]interface{} - Deprecated() bool -} - -type routeAccessor struct { - route *Route -} - -func (r routeAccessor) Method() string { - return r.route.Method -} -func (r routeAccessor) Consumes() []string { - return r.route.Consumes[:] -} -func (r routeAccessor) Path() string { - return r.route.Path -} -func (r routeAccessor) Doc() string { - return r.route.Doc -} -func (r routeAccessor) Notes() string { - return r.route.Notes -} -func (r routeAccessor) Operation() string { - return r.route.Operation -} -func (r routeAccessor) ParameterDocs() []*Parameter { - return r.route.ParameterDocs[:] -} - -// Returns a copy -func (r routeAccessor) Metadata() map[string]interface{} { - return copyMap(r.route.Metadata) -} -func (r routeAccessor) Deprecated() bool { - return r.route.Deprecated -} - -// https://stackoverflow.com/questions/23057785/how-to-copy-a-map -func copyMap(m map[string]interface{}) map[string]interface{} { - cp := make(map[string]interface{}) - for k, v := range m { - vm, ok := v.(map[string]interface{}) - if ok { - cp[k] = copyMap(vm) - } else { - cp[k] = v - } - } - return cp -} diff --git a/vendor/github.com/emicklei/go-restful/v3/router.go b/vendor/github.com/emicklei/go-restful/v3/router.go deleted file mode 100644 index 19078af1c..000000000 --- a/vendor/github.com/emicklei/go-restful/v3/router.go +++ /dev/null @@ -1,20 +0,0 @@ -package restful - -// Copyright 2013 Ernest Micklei. All rights reserved. -// Use of this source code is governed by a license -// that can be found in the LICENSE file. - -import "net/http" - -// A RouteSelector finds the best matching Route given the input HTTP Request -// RouteSelectors can optionally also implement the PathProcessor interface to also calculate the -// path parameters after the route has been selected. -type RouteSelector interface { - - // SelectRoute finds a Route given the input HTTP Request and a list of WebServices. - // It returns a selected Route and its containing WebService or an error indicating - // a problem. - SelectRoute( - webServices []*WebService, - httpRequest *http.Request) (selectedService *WebService, selected *Route, err error) -} diff --git a/vendor/github.com/emicklei/go-restful/v3/service_error.go b/vendor/github.com/emicklei/go-restful/v3/service_error.go deleted file mode 100644 index a41575469..000000000 --- a/vendor/github.com/emicklei/go-restful/v3/service_error.go +++ /dev/null @@ -1,32 +0,0 @@ -package restful - -// Copyright 2013 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" - "net/http" -) - -// ServiceError is a transport object to pass information about a non-Http error occurred in a WebService while processing a request. -type ServiceError struct { - Code int - Message string - Header http.Header -} - -// NewError returns a ServiceError using the code and reason -func NewError(code int, message string) ServiceError { - return ServiceError{Code: code, Message: message} -} - -// NewErrorWithHeader returns a ServiceError using the code, reason and header -func NewErrorWithHeader(code int, message string, header http.Header) ServiceError { - return ServiceError{Code: code, Message: message, Header: header} -} - -// Error returns a text representation of the service error -func (s ServiceError) Error() string { - return fmt.Sprintf("[ServiceError:%v] %v", s.Code, s.Message) -} diff --git a/vendor/github.com/emicklei/go-restful/v3/web_service.go b/vendor/github.com/emicklei/go-restful/v3/web_service.go deleted file mode 100644 index 789c4df25..000000000 --- a/vendor/github.com/emicklei/go-restful/v3/web_service.go +++ /dev/null @@ -1,305 +0,0 @@ -package restful - -import ( - "errors" - "os" - "reflect" - "sync" - - "github.com/emicklei/go-restful/v3/log" -) - -// Copyright 2013 Ernest Micklei. All rights reserved. -// Use of this source code is governed by a license -// that can be found in the LICENSE file. - -// WebService holds a collection of Route values that bind a Http Method + URL Path to a function. -type WebService struct { - rootPath string - pathExpr *pathExpression // cached compilation of rootPath as RegExp - routes []Route - produces []string - consumes []string - pathParameters []*Parameter - filters []FilterFunction - documentation string - apiVersion string - - typeNameHandleFunc TypeNameHandleFunction - - dynamicRoutes bool - - // protects 'routes' if dynamic routes are enabled - routesLock sync.RWMutex -} - -func (w *WebService) SetDynamicRoutes(enable bool) { - w.dynamicRoutes = enable -} - -// TypeNameHandleFunction declares functions that can handle translating the name of a sample object -// into the restful documentation for the service. -type TypeNameHandleFunction func(sample interface{}) string - -// TypeNameHandler sets the function that will convert types to strings in the parameter -// and model definitions. If not set, the web service will invoke -// reflect.TypeOf(object).String(). -func (w *WebService) TypeNameHandler(handler TypeNameHandleFunction) *WebService { - w.typeNameHandleFunc = handler - return w -} - -// reflectTypeName is the default TypeNameHandleFunction and for a given object -// returns the name that Go identifies it with (e.g. "string" or "v1.Object") via -// the reflection API. -func reflectTypeName(sample interface{}) string { - return reflect.TypeOf(sample).String() -} - -// compilePathExpression ensures that the path is compiled into a RegEx for those routers that need it. -func (w *WebService) compilePathExpression() { - compiled, err := newPathExpression(w.rootPath) - if err != nil { - log.Printf("invalid path:%s because:%v", w.rootPath, err) - os.Exit(1) - } - w.pathExpr = compiled -} - -// ApiVersion sets the API version for documentation purposes. -func (w *WebService) ApiVersion(apiVersion string) *WebService { - w.apiVersion = apiVersion - return w -} - -// Version returns the API version for documentation purposes. -func (w *WebService) Version() string { return w.apiVersion } - -// Path specifies the root URL template path of the WebService. -// All Routes will be relative to this path. -func (w *WebService) Path(root string) *WebService { - w.rootPath = root - if len(w.rootPath) == 0 { - w.rootPath = "/" - } - w.compilePathExpression() - return w -} - -// Param adds a PathParameter to document parameters used in the root path. -func (w *WebService) Param(parameter *Parameter) *WebService { - if w.pathParameters == nil { - w.pathParameters = []*Parameter{} - } - w.pathParameters = append(w.pathParameters, parameter) - return w -} - -// PathParameter creates a new Parameter of kind Path for documentation purposes. -// It is initialized as required with string as its DataType. -func (w *WebService) PathParameter(name, description string) *Parameter { - return PathParameter(name, description) -} - -// PathParameter creates a new Parameter of kind Path for documentation purposes. -// It is initialized as required with string as its DataType. -func PathParameter(name, description string) *Parameter { - p := &Parameter{&ParameterData{Name: name, Description: description, Required: true, DataType: "string"}} - p.bePath() - return p -} - -// QueryParameter creates a new Parameter of kind Query for documentation purposes. -// It is initialized as not required with string as its DataType. -func (w *WebService) QueryParameter(name, description string) *Parameter { - return QueryParameter(name, description) -} - -// QueryParameter creates a new Parameter of kind Query for documentation purposes. -// It is initialized as not required with string as its DataType. -func QueryParameter(name, description string) *Parameter { - p := &Parameter{&ParameterData{Name: name, Description: description, Required: false, DataType: "string", CollectionFormat: CollectionFormatCSV.String()}} - p.beQuery() - return p -} - -// BodyParameter creates a new Parameter of kind Body for documentation purposes. -// It is initialized as required without a DataType. -func (w *WebService) BodyParameter(name, description string) *Parameter { - return BodyParameter(name, description) -} - -// BodyParameter creates a new Parameter of kind Body for documentation purposes. -// It is initialized as required without a DataType. -func BodyParameter(name, description string) *Parameter { - p := &Parameter{&ParameterData{Name: name, Description: description, Required: true}} - p.beBody() - return p -} - -// HeaderParameter creates a new Parameter of kind (Http) Header for documentation purposes. -// It is initialized as not required with string as its DataType. -func (w *WebService) HeaderParameter(name, description string) *Parameter { - return HeaderParameter(name, description) -} - -// HeaderParameter creates a new Parameter of kind (Http) Header for documentation purposes. -// It is initialized as not required with string as its DataType. -func HeaderParameter(name, description string) *Parameter { - p := &Parameter{&ParameterData{Name: name, Description: description, Required: false, DataType: "string"}} - p.beHeader() - return p -} - -// FormParameter creates a new Parameter of kind Form (using application/x-www-form-urlencoded) for documentation purposes. -// It is initialized as required with string as its DataType. -func (w *WebService) FormParameter(name, description string) *Parameter { - return FormParameter(name, description) -} - -// FormParameter creates a new Parameter of kind Form (using application/x-www-form-urlencoded) for documentation purposes. -// It is initialized as required with string as its DataType. -func FormParameter(name, description string) *Parameter { - p := &Parameter{&ParameterData{Name: name, Description: description, Required: false, DataType: "string"}} - p.beForm() - return p -} - -// MultiPartFormParameter creates a new Parameter of kind Form (using multipart/form-data) for documentation purposes. -// It is initialized as required with string as its DataType. -func (w *WebService) MultiPartFormParameter(name, description string) *Parameter { - return MultiPartFormParameter(name, description) -} - -func MultiPartFormParameter(name, description string) *Parameter { - p := &Parameter{&ParameterData{Name: name, Description: description, Required: false, DataType: "string"}} - p.beMultiPartForm() - return p -} - -// Route creates a new Route using the RouteBuilder and add to the ordered list of Routes. -func (w *WebService) Route(builder *RouteBuilder) *WebService { - w.routesLock.Lock() - defer w.routesLock.Unlock() - builder.copyDefaults(w.produces, w.consumes) - w.routes = append(w.routes, builder.Build()) - return w -} - -// RemoveRoute removes the specified route, looks for something that matches 'path' and 'method' -func (w *WebService) RemoveRoute(path, method string) error { - if !w.dynamicRoutes { - return errors.New("dynamic routes are not enabled.") - } - w.routesLock.Lock() - defer w.routesLock.Unlock() - newRoutes := []Route{} - for _, route := range w.routes { - if route.Method == method && route.Path == path { - continue - } - newRoutes = append(newRoutes, route) - } - w.routes = newRoutes - return nil -} - -// Method creates a new RouteBuilder and initialize its http method -func (w *WebService) Method(httpMethod string) *RouteBuilder { - return new(RouteBuilder).typeNameHandler(w.typeNameHandleFunc).servicePath(w.rootPath).Method(httpMethod) -} - -// Produces specifies that this WebService can produce one or more MIME types. -// Http requests must have one of these values set for the Accept header. -func (w *WebService) Produces(contentTypes ...string) *WebService { - w.produces = contentTypes - return w -} - -// Consumes specifies that this WebService can consume one or more MIME types. -// Http requests must have one of these values set for the Content-Type header. -func (w *WebService) Consumes(accepts ...string) *WebService { - w.consumes = accepts - return w -} - -// Routes returns the Routes associated with this WebService -func (w *WebService) Routes() []Route { - if !w.dynamicRoutes { - return w.routes - } - // Make a copy of the array to prevent concurrency problems - w.routesLock.RLock() - defer w.routesLock.RUnlock() - result := make([]Route, len(w.routes)) - for ix := range w.routes { - result[ix] = w.routes[ix] - } - return result -} - -// RootPath returns the RootPath associated with this WebService. Default "/" -func (w *WebService) RootPath() string { - return w.rootPath -} - -// PathParameters return the path parameter names for (shared among its Routes) -func (w *WebService) PathParameters() []*Parameter { - return w.pathParameters -} - -// Filter adds a filter function to the chain of filters applicable to all its Routes -func (w *WebService) Filter(filter FilterFunction) *WebService { - w.filters = append(w.filters, filter) - return w -} - -// Doc is used to set the documentation of this service. -func (w *WebService) Doc(plainText string) *WebService { - w.documentation = plainText - return w -} - -// Documentation returns it. -func (w *WebService) Documentation() string { - return w.documentation -} - -/* - Convenience methods -*/ - -// HEAD is a shortcut for .Method("HEAD").Path(subPath) -func (w *WebService) HEAD(subPath string) *RouteBuilder { - return new(RouteBuilder).typeNameHandler(w.typeNameHandleFunc).servicePath(w.rootPath).Method("HEAD").Path(subPath) -} - -// GET is a shortcut for .Method("GET").Path(subPath) -func (w *WebService) GET(subPath string) *RouteBuilder { - return new(RouteBuilder).typeNameHandler(w.typeNameHandleFunc).servicePath(w.rootPath).Method("GET").Path(subPath) -} - -// POST is a shortcut for .Method("POST").Path(subPath) -func (w *WebService) POST(subPath string) *RouteBuilder { - return new(RouteBuilder).typeNameHandler(w.typeNameHandleFunc).servicePath(w.rootPath).Method("POST").Path(subPath) -} - -// PUT is a shortcut for .Method("PUT").Path(subPath) -func (w *WebService) PUT(subPath string) *RouteBuilder { - return new(RouteBuilder).typeNameHandler(w.typeNameHandleFunc).servicePath(w.rootPath).Method("PUT").Path(subPath) -} - -// PATCH is a shortcut for .Method("PATCH").Path(subPath) -func (w *WebService) PATCH(subPath string) *RouteBuilder { - return new(RouteBuilder).typeNameHandler(w.typeNameHandleFunc).servicePath(w.rootPath).Method("PATCH").Path(subPath) -} - -// DELETE is a shortcut for .Method("DELETE").Path(subPath) -func (w *WebService) DELETE(subPath string) *RouteBuilder { - return new(RouteBuilder).typeNameHandler(w.typeNameHandleFunc).servicePath(w.rootPath).Method("DELETE").Path(subPath) -} - -// OPTIONS is a shortcut for .Method("OPTIONS").Path(subPath) -func (w *WebService) OPTIONS(subPath string) *RouteBuilder { - return new(RouteBuilder).typeNameHandler(w.typeNameHandleFunc).servicePath(w.rootPath).Method("OPTIONS").Path(subPath) -} diff --git a/vendor/github.com/emicklei/go-restful/v3/web_service_container.go b/vendor/github.com/emicklei/go-restful/v3/web_service_container.go deleted file mode 100644 index c9d31b06c..000000000 --- a/vendor/github.com/emicklei/go-restful/v3/web_service_container.go +++ /dev/null @@ -1,39 +0,0 @@ -package restful - -// Copyright 2013 Ernest Micklei. All rights reserved. -// Use of this source code is governed by a license -// that can be found in the LICENSE file. - -import ( - "net/http" -) - -// DefaultContainer is a restful.Container that uses http.DefaultServeMux -var DefaultContainer *Container - -func init() { - DefaultContainer = NewContainer() - DefaultContainer.ServeMux = http.DefaultServeMux -} - -// If set the true then panics will not be caught to return HTTP 500. -// In that case, Route functions are responsible for handling any error situation. -// Default value is false = recover from panics. This has performance implications. -// OBSOLETE ; use restful.DefaultContainer.DoNotRecover(true) -var DoNotRecover = false - -// Add registers a new WebService add it to the DefaultContainer. -func Add(service *WebService) { - DefaultContainer.Add(service) -} - -// Filter appends a container FilterFunction from the DefaultContainer. -// These are called before dispatching a http.Request to a WebService. -func Filter(filter FilterFunction) { - DefaultContainer.Filter(filter) -} - -// RegisteredWebServices returns the collections of WebServices from the DefaultContainer -func RegisteredWebServices() []*WebService { - return DefaultContainer.RegisteredWebServices() -} diff --git a/vendor/github.com/go-openapi/swag/.codecov.yml b/vendor/github.com/go-openapi/swag/.codecov.yml deleted file mode 100644 index 3354f44b2..000000000 --- a/vendor/github.com/go-openapi/swag/.codecov.yml +++ /dev/null @@ -1,4 +0,0 @@ -ignore: - - jsonutils/fixtures_test - - jsonutils/adapters/ifaces/mocks - - jsonutils/adapters/testintegration/benchmarks diff --git a/vendor/github.com/go-openapi/swag/.editorconfig b/vendor/github.com/go-openapi/swag/.editorconfig deleted file mode 100644 index 3152da69a..000000000 --- a/vendor/github.com/go-openapi/swag/.editorconfig +++ /dev/null @@ -1,26 +0,0 @@ -# top-most EditorConfig file -root = true - -# Unix-style newlines with a newline ending every file -[*] -end_of_line = lf -insert_final_newline = true -indent_style = space -indent_size = 2 -trim_trailing_whitespace = true - -# Set default charset -[*.{js,py,go,scala,rb,java,html,css,less,sass,md}] -charset = utf-8 - -# Tab indentation (no size specified) -[*.go] -indent_style = tab - -[*.md] -trim_trailing_whitespace = false - -# Matches the exact files either package.json or .travis.yml -[{package.json,.travis.yml}] -indent_style = space -indent_size = 2 diff --git a/vendor/github.com/go-openapi/swag/.gitattributes b/vendor/github.com/go-openapi/swag/.gitattributes deleted file mode 100644 index 49ad52766..000000000 --- a/vendor/github.com/go-openapi/swag/.gitattributes +++ /dev/null @@ -1,2 +0,0 @@ -# gofmt always uses LF, whereas Git uses CRLF on Windows. -*.go text eol=lf diff --git a/vendor/github.com/go-openapi/swag/.gitignore b/vendor/github.com/go-openapi/swag/.gitignore deleted file mode 100644 index 3ceb596fa..000000000 --- a/vendor/github.com/go-openapi/swag/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -secrets.yml -vendor -Godeps -.idea -*.out -.mcp.json -.worktrees diff --git a/vendor/github.com/go-openapi/swag/.golangci.yml b/vendor/github.com/go-openapi/swag/.golangci.yml deleted file mode 100644 index 099c0a78c..000000000 --- a/vendor/github.com/go-openapi/swag/.golangci.yml +++ /dev/null @@ -1,81 +0,0 @@ -version: "2" -linters: - default: all - disable: - - cyclop - - depguard - - errchkjson - - errorlint - - exhaustruct - - forcetypeassert - - funlen - - gochecknoglobals - - gochecknoinits - - gocognit - - godot - - godox - - goconst - - gomoddirectives - - gomodguard - - gomodguard_v2 - - 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 diff --git a/vendor/github.com/go-openapi/swag/.mockery.yml b/vendor/github.com/go-openapi/swag/.mockery.yml deleted file mode 100644 index 8557cb58d..000000000 --- a/vendor/github.com/go-openapi/swag/.mockery.yml +++ /dev/null @@ -1,30 +0,0 @@ -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: diff --git a/vendor/github.com/go-openapi/swag/CODE_OF_CONDUCT.md b/vendor/github.com/go-openapi/swag/CODE_OF_CONDUCT.md deleted file mode 100644 index bac878f21..000000000 --- a/vendor/github.com/go-openapi/swag/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,76 +0,0 @@ -# Contributor Covenant Code of Conduct - -## Our Pledge - -In the interest of fostering an open and welcoming environment, we as -contributors and maintainers pledge to making participation in our project and -our community a harassment-free experience for everyone, regardless of age, body -size, disability, ethnicity, gender identity and expression, level of experience, -nationality, personal appearance, race, religion, or sexual identity and -orientation. - -## Our Standards - -Examples of behavior that contributes to creating a positive environment -include: - -* Using welcoming and inclusive language -* Being respectful of differing viewpoints and experiences -* Gracefully accepting constructive criticism -* Focusing on what is best for the community -* Showing empathy towards other community members - -Examples of unacceptable behavior by participants include: - -* The use of sexualized language or imagery and unwelcome sexual attention or - -advances - -* Trolling, insulting/derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or electronic - address, without explicit permission -* Other conduct which could reasonably be considered inappropriate in a - professional setting - -## Our Responsibilities - -Project maintainers are responsible for clarifying the standards of acceptable -behavior and are expected to take appropriate and fair corrective action in -response to any instances of unacceptable behavior. - -Project maintainers have the right and responsibility to remove, edit, or -reject comments, commits, code, wiki edits, issues, and other contributions -that are not aligned to this Code of Conduct, or to ban temporarily or -permanently any contributor for other behaviors that they deem inappropriate, -threatening, offensive, or harmful. - -## Scope - -This Code of Conduct applies both within project spaces and in public spaces -when an individual is representing the project or its community. Examples of -representing a project or community include using an official project e-mail -address, posting via an official social media account, or acting as an appointed -representative at an online or offline event. Representation of a project may be -further defined and clarified by project maintainers. - -## Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported by contacting the project team at . All -complaints will be reviewed and investigated and will result in a response that -is deemed necessary and appropriate to the circumstances. The project team is -obligated to maintain confidentiality with regard to the reporter of an incident. -Further details of specific enforcement policies may be posted separately. - -Project maintainers who do not follow or enforce the Code of Conduct in good -faith may face temporary or permanent repercussions as determined by other -members of the project's leadership. - -## Attribution - -This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, -available at [][version] - -[homepage]: http://contributor-covenant.org -[version]: http://contributor-covenant.org/version/1/4/ diff --git a/vendor/github.com/go-openapi/swag/CONTRIBUTORS.md b/vendor/github.com/go-openapi/swag/CONTRIBUTORS.md deleted file mode 100644 index 0f0711cd5..000000000 --- a/vendor/github.com/go-openapi/swag/CONTRIBUTORS.md +++ /dev/null @@ -1,36 +0,0 @@ -# Contributors - -- Repository: ['go-openapi/swag'] - -| Total Contributors | Total Contributions | -| --- | --- | -| 24 | 251 | - -| Username | All Time Contribution Count | All Commits | -| --- | --- | --- | -| @fredbi | 121 | | -| @casualjim | 98 | | -| @alexandear | 4 | | -| @orisano | 3 | | -| @reinerRubin | 2 | | -| @n-inja | 2 | | -| @nitinmohan87 | 2 | | -| @Neo2308 | 2 | | -| @michaelbowler-form3 | 2 | | -| @ujjwalsh | 1 | | -| @griffin-stewie | 1 | | -| @POD666 | 1 | | -| @pytlesk4 | 1 | | -| @shirou | 1 | | -| @seanprince | 1 | | -| @petrkotas | 1 | | -| @mszczygiel | 1 | | -| @sosiska | 1 | | -| @kzys | 1 | | -| @faguirre1 | 1 | | -| @posener | 1 | | -| @diego-fu-hs | 1 | | -| @davidalpert | 1 | | -| @Xe | 1 | | - - _this file was generated by the [Contributors GitHub Action](https://github.com/github-community-projects/contributors)_ diff --git a/vendor/github.com/go-openapi/swag/LICENSE b/vendor/github.com/go-openapi/swag/LICENSE deleted file mode 100644 index d64569567..000000000 --- a/vendor/github.com/go-openapi/swag/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/go-openapi/swag/README.md b/vendor/github.com/go-openapi/swag/README.md deleted file mode 100644 index c6c2d21e9..000000000 --- a/vendor/github.com/go-openapi/swag/README.md +++ /dev/null @@ -1,223 +0,0 @@ -# Swag - - -[![Tests][test-badge]][test-url] [![Coverage][cov-badge]][cov-url] [![CI vuln scan][vuln-scan-badge]][vuln-scan-url] [![CodeQL][codeql-badge]][codeql-url] - - - -[![Release][release-badge]][release-url] [![Go Report Card][gocard-badge]][gocard-url] [![CodeFactor Grade][codefactor-badge]][codefactor-url] [![License][license-badge]][license-url] - - -[![GoDoc][godoc-badge]][godoc-url] [![Discord Channel][discord-badge]][discord-url] [![go version][goversion-badge]][goversion-url] ![Top language][top-badge] ![Commits since latest release][commits-badge] - ---- - -A bunch of helper functions for go-openapi and go-swagger projects. - -You may also use it standalone for your projects. - -> **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) -* [Change log](#change-log) -* [Licensing](#licensing) -* [Note to contributors](#note-to-contributors) -* [Roadmap](#roadmap) - -## Announcements - -* **2025-12-19** : new community chat on discord - * a new discord community channel is available to be notified of changes and support users - -You may join the discord community by clicking the invite link on the discord badge (also above). [![Discord Channel][discord-badge]][discord-url] - -## Status - -API is stable. - -## Import this library in your project - -```cmd -go get github.com/go-openapi/swag/{module} -``` - -Or for backward compatibility: - -```cmd -go get github.com/go-openapi/swag -``` - -## 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
convert from string to builtin types (wraps `strconv`)
require `./typeutils` (test dependency)
| -| `fileutils` | file utilities | | -| `jsonname` | JSON utilities (deprecated) | infer JSON names from `go` properties
use `github.com/go-openapi/jsonpointer/jsonname` instead | -| `jsonutils` | JSON utilities | fast json concatenation
read and write JSON from and to dynamic `go` data structures
~require `github.com/mailru/easyjson`~
| -| `loading` | file loading | load from file or http
require `./yamlutils`
| -| `mangling` | safe name generation | name mangling for `go`
| -| `netutils` | networking utilities | host, port from address
| -| `pools` | utilities to work with sync.Pools | | -| `stringutils` | `string` utilities | search in slice (with case-insensitive)
split/join query parameters as arrays
| -| `typeutils` | `go` types utilities | check the zero value for any type
safe check for a nil value
| -| `yamlutils` | YAML utilities | converting YAML to JSON
loading YAML into a dynamic YAML document
maintaining the original order of keys in YAML objects
require `./jsonutils`
~require `github.com/mailru/easyjson`~
require `go.yaml.in/yaml/v3`
| - ---- - -## 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` - -## Usage - -**How to explicitly register a dependency at runtime**? - -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). - ---- - -## Note to contributors - -All kinds of contributions are welcome. - -This repo is a go mono-repo. See [docs](docs/MAINTAINERS.md). - -More general guidelines are available [here](.github/CONTRIBUTING.md). - -## Roadmap - -See the current [TODO list](docs/TODOS.md) - -## Change log - -See - -For pre-v0.26.0 releases, see [release notes](./docs/NOTES.md). - -**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. - - - -## Licensing - -This library ships under the [SPDX-License-Identifier: Apache-2.0](./LICENSE). - - - - - -## Other documentation - -* [All-time contributors](./CONTRIBUTORS.md) -* [Contributing guidelines][contributing-doc-site] -* [Maintainers documentation][maintainers-doc-site] -* [Code style][style-doc-site] - -## Cutting a new release - -Maintainers can cut a new release by either: - -* running [this workflow](https://github.com/go-openapi/swag/actions/workflows/bump-release.yml) -* or pushing a semver tag - * signed tags are preferred - * The tag message is prepended to release notes - - -[test-badge]: https://github.com/go-openapi/swag/actions/workflows/go-test.yml/badge.svg -[test-url]: https://github.com/go-openapi/swag/actions/workflows/go-test.yml -[cov-badge]: https://codecov.io/gh/go-openapi/swag/branch/master/graph/badge.svg -[cov-url]: https://codecov.io/gh/go-openapi/swag -[vuln-scan-badge]: https://github.com/go-openapi/swag/actions/workflows/scanner.yml/badge.svg -[vuln-scan-url]: https://github.com/go-openapi/swag/actions/workflows/scanner.yml -[codeql-badge]: https://github.com/go-openapi/swag/actions/workflows/codeql.yml/badge.svg -[codeql-url]: https://github.com/go-openapi/swag/actions/workflows/codeql.yml - -[release-badge]: https://badge.fury.io/gh/go-openapi%2Fswag.svg -[release-url]: https://badge.fury.io/gh/go-openapi%2Fswag -[gomod-badge]: https://badge.fury.io/go/github.com%2Fgo-openapi%2Fswag.svg -[gomod-url]: https://badge.fury.io/go/github.com%2Fgo-openapi%2Fswag - -[gocard-badge]: https://goreportcard.com/badge/github.com/go-openapi/swag -[gocard-url]: https://goreportcard.com/report/github.com/go-openapi/swag -[codefactor-badge]: https://img.shields.io/codefactor/grade/github/go-openapi/swag -[codefactor-url]: https://www.codefactor.io/repository/github/go-openapi/swag - -[doc-badge]: https://img.shields.io/badge/doc-site-blue?link=https%3A%2F%2Fgoswagger.io%2Fgo-openapi%2F -[doc-url]: https://goswagger.io/go-openapi -[godoc-badge]: https://pkg.go.dev/badge/github.com/go-openapi/swag -[godoc-url]: http://pkg.go.dev/github.com/go-openapi/swag -[discord-badge]: https://img.shields.io/discord/1446918742398341256?logo=discord&label=discord&color=blue -[discord-url]: https://discord.gg/FfnFYaC3k5 - - -[license-badge]: http://img.shields.io/badge/license-Apache%20v2-orange.svg -[license-url]: https://github.com/go-openapi/swag/?tab=Apache-2.0-1-ov-file#readme - -[goversion-badge]: https://img.shields.io/github/go-mod/go-version/go-openapi/swag -[goversion-url]: https://github.com/go-openapi/swag/blob/master/go.mod -[top-badge]: https://img.shields.io/github/languages/top/go-openapi/swag -[commits-badge]: https://img.shields.io/github/commits-since/go-openapi/swag/latest - -[contributing-doc-site]: https://go-openapi.github.io/doc-site/contributing/contributing/index.html -[maintainers-doc-site]: https://go-openapi.github.io/doc-site/maintainers/index.html -[style-doc-site]: https://go-openapi.github.io/doc-site/contributing/style/index.html diff --git a/vendor/github.com/go-openapi/swag/SECURITY.md b/vendor/github.com/go-openapi/swag/SECURITY.md deleted file mode 100644 index 1fea2c573..000000000 --- a/vendor/github.com/go-openapi/swag/SECURITY.md +++ /dev/null @@ -1,37 +0,0 @@ -# Security Policy - -This policy outlines the commitment and practices of the go-openapi maintainers regarding security. - -## Supported Versions - -| Version | Supported | -| ------- | ------------------ | -| O.x | :white_check_mark: | - -## Vulnerability checks in place - -This repository uses automated vulnerability scans, at every merged commit and at least once a week. - -We use: - -* [`GitHub CodeQL`][codeql-url] -* [`trivy`][trivy-url] -* [`govulncheck`][govulncheck-url] - -Reports are centralized in github security reports and visible only to the maintainers. - -## Reporting a vulnerability - -If you become aware of a security vulnerability that affects the current repository, -**please report it privately to the maintainers** -rather than opening a publicly visible GitHub issue. - -Please follow the instructions provided by github to [Privately report a security vulnerability][github-guidance-url]. - -> [!NOTE] -> On Github, navigate to the project's "Security" tab then click on "Report a vulnerability". - -[codeql-url]: https://github.com/github/codeql -[trivy-url]: https://trivy.dev/docs/latest/getting-started -[govulncheck-url]: https://go.dev/blog/govulncheck -[github-guidance-url]: 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 diff --git a/vendor/github.com/go-openapi/swag/cmdutils/LICENSE b/vendor/github.com/go-openapi/swag/cmdutils/LICENSE deleted file mode 100644 index d64569567..000000000 --- a/vendor/github.com/go-openapi/swag/cmdutils/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/go-openapi/swag/cmdutils/cmd_utils.go b/vendor/github.com/go-openapi/swag/cmdutils/cmd_utils.go deleted file mode 100644 index 6c7bbb26f..000000000 --- a/vendor/github.com/go-openapi/swag/cmdutils/cmd_utils.go +++ /dev/null @@ -1,13 +0,0 @@ -// 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 -} diff --git a/vendor/github.com/go-openapi/swag/cmdutils/doc.go b/vendor/github.com/go-openapi/swag/cmdutils/doc.go deleted file mode 100644 index 31f2c3753..000000000 --- a/vendor/github.com/go-openapi/swag/cmdutils/doc.go +++ /dev/null @@ -1,5 +0,0 @@ -// 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 diff --git a/vendor/github.com/go-openapi/swag/cmdutils_iface.go b/vendor/github.com/go-openapi/swag/cmdutils_iface.go deleted file mode 100644 index bd0c1fc12..000000000 --- a/vendor/github.com/go-openapi/swag/cmdutils_iface.go +++ /dev/null @@ -1,11 +0,0 @@ -// 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 diff --git a/vendor/github.com/go-openapi/swag/conv_iface.go b/vendor/github.com/go-openapi/swag/conv_iface.go deleted file mode 100644 index eea7b2e56..000000000 --- a/vendor/github.com/go-openapi/swag/conv_iface.go +++ /dev/null @@ -1,486 +0,0 @@ -// 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) } diff --git a/vendor/github.com/go-openapi/swag/doc.go b/vendor/github.com/go-openapi/swag/doc.go deleted file mode 100644 index b54b57478..000000000 --- a/vendor/github.com/go-openapi/swag/doc.go +++ /dev/null @@ -1,47 +0,0 @@ -// 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. -// -// You may also use it standalone for your projects. -// -// 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. -// -// 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 diff --git a/vendor/github.com/go-openapi/swag/fileutils/doc.go b/vendor/github.com/go-openapi/swag/fileutils/doc.go deleted file mode 100644 index 859a200d8..000000000 --- a/vendor/github.com/go-openapi/swag/fileutils/doc.go +++ /dev/null @@ -1,10 +0,0 @@ -// 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 diff --git a/vendor/github.com/go-openapi/swag/fileutils/file.go b/vendor/github.com/go-openapi/swag/fileutils/file.go deleted file mode 100644 index 5ad4cfaea..000000000 --- a/vendor/github.com/go-openapi/swag/fileutils/file.go +++ /dev/null @@ -1,22 +0,0 @@ -// 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() -} diff --git a/vendor/github.com/go-openapi/swag/fileutils/path.go b/vendor/github.com/go-openapi/swag/fileutils/path.go deleted file mode 100644 index dd09f690b..000000000 --- a/vendor/github.com/go-openapi/swag/fileutils/path.go +++ /dev/null @@ -1,52 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers -// SPDX-License-Identifier: Apache-2.0 - -package fileutils - -import ( - "os" - "path/filepath" - "runtime" - "strings" -) - -// 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 { - pathsList := filepath.SplitList(searchPath) - for _, path := range pathsList { - if evaluatedPath, err := filepath.EvalSymlinks(filepath.Join(path, "src", pkg)); err == nil { - if _, err := os.Stat(evaluatedPath); err == nil { - return evaluatedPath - } - } - } - return "" -} - -// 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 == "" { - allPaths = filepath.Join(os.Getenv("HOME"), "go") - } - if allPaths != "" { - allPaths = strings.Join([]string{allPaths, runtime.GOROOT()}, ":") - } else { - allPaths = runtime.GOROOT() - } - return allPaths -} diff --git a/vendor/github.com/go-openapi/swag/fileutils_iface.go b/vendor/github.com/go-openapi/swag/fileutils_iface.go deleted file mode 100644 index f3e79a0e4..000000000 --- a/vendor/github.com/go-openapi/swag/fileutils_iface.go +++ /dev/null @@ -1,33 +0,0 @@ -// 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() } diff --git a/vendor/github.com/go-openapi/swag/go.work b/vendor/github.com/go-openapi/swag/go.work deleted file mode 100644 index f1dddc436..000000000 --- a/vendor/github.com/go-openapi/swag/go.work +++ /dev/null @@ -1,21 +0,0 @@ -use ( - . - ./cmdutils - ./conv - ./fileutils - ./jsonname - ./jsonutils - ./jsonutils/adapters/easyjson - ./jsonutils/adapters/testintegration - ./jsonutils/adapters/testintegration/benchmarks - ./jsonutils/fixtures_test - ./loading - ./mangling - ./netutils - ./pools - ./stringutils - ./typeutils - ./yamlutils -) - -go 1.25.0 diff --git a/vendor/github.com/go-openapi/swag/go.work.sum b/vendor/github.com/go-openapi/swag/go.work.sum deleted file mode 100644 index c1308cafa..000000000 --- a/vendor/github.com/go-openapi/swag/go.work.sum +++ /dev/null @@ -1,7 +0,0 @@ -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= diff --git a/vendor/github.com/go-openapi/swag/jsonname_iface.go b/vendor/github.com/go-openapi/swag/jsonname_iface.go deleted file mode 100644 index 443560caa..000000000 --- a/vendor/github.com/go-openapi/swag/jsonname_iface.go +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers -// SPDX-License-Identifier: Apache-2.0 - -package swag - -import ( - "github.com/go-openapi/jsonpointer/jsonname" -) - -// DefaultJSONNameProvider is the default cache for types -// -// Deprecated: use [github.com/go-openapi/jsonpointer/jsonname.DefaultJSONNameProvider] instead. -var DefaultJSONNameProvider = jsonname.DefaultJSONNameProvider - -// NameProvider represents an object capable of translating from go property names -// to json property names. -// -// Deprecated: use [github.com/go-openapi/jsonpointer/jsonname.NameProvider] instead. -type NameProvider = jsonname.NameProvider - -// NewNameProvider creates a new name provider -// -// Deprecated: use [github.com/go-openapi/jsonpointer/jsonname.NewNameProvider] instead. -func NewNameProvider() *NameProvider { return jsonname.NewNameProvider() } diff --git a/vendor/github.com/go-openapi/swag/jsonutils_iface.go b/vendor/github.com/go-openapi/swag/jsonutils_iface.go deleted file mode 100644 index 7bd4105fa..000000000 --- a/vendor/github.com/go-openapi/swag/jsonutils_iface.go +++ /dev/null @@ -1,65 +0,0 @@ -// 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) } diff --git a/vendor/github.com/go-openapi/swag/loading/LICENSE b/vendor/github.com/go-openapi/swag/loading/LICENSE deleted file mode 100644 index d64569567..000000000 --- a/vendor/github.com/go-openapi/swag/loading/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/go-openapi/swag/loading/doc.go b/vendor/github.com/go-openapi/swag/loading/doc.go deleted file mode 100644 index 112c49968..000000000 --- a/vendor/github.com/go-openapi/swag/loading/doc.go +++ /dev/null @@ -1,29 +0,0 @@ -// 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. -// -// # Security -// -// By default, the local loader reads any path the process can access, including absolute -// paths and "file://" URIs (for example "file:///etc/passwd"). Applications that pass -// untrusted input to [LoadFromFileOrHTTP], [JSONDoc] (or to downstream consumers such as -// go-openapi/loads) must confine local loading to a trusted directory. -// -// Use [WithRoot] to do so: it resolves every requested path relative to a chosen directory -// and rejects anything that escapes it, including via symlink. It is built on [os.Root] -// and is therefore safer than passing an [os.DirFS] to [WithFS], which does not block -// symlink escapes. -// -// Remote loading uses a standard [net/http] client. -// By default it follows redirects and performs no destination filtering — exactly like [net/http.DefaultClient]. -// -// A caller-controlled URL may therefore reach internal services or cloud metadata endpoints -// (server-side request forgery). -// -// This package does not, and should not, embed a network policy: -// when the URL may derive from untrusted input, supply a restricted client with -// [WithHTTPClient] whose transport rejects unwanted destinations at dial time — which also -// covers redirects and DNS rebinding. -// See the example on [LoadFromFileOrHTTP]. -package loading diff --git a/vendor/github.com/go-openapi/swag/loading/errors.go b/vendor/github.com/go-openapi/swag/loading/errors.go deleted file mode 100644 index b3964289c..000000000 --- a/vendor/github.com/go-openapi/swag/loading/errors.go +++ /dev/null @@ -1,15 +0,0 @@ -// 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) -} diff --git a/vendor/github.com/go-openapi/swag/loading/json.go b/vendor/github.com/go-openapi/swag/loading/json.go deleted file mode 100644 index 59db12f5c..000000000 --- a/vendor/github.com/go-openapi/swag/loading/json.go +++ /dev/null @@ -1,25 +0,0 @@ -// 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 -} diff --git a/vendor/github.com/go-openapi/swag/loading/loading.go b/vendor/github.com/go-openapi/swag/loading/loading.go deleted file mode 100644 index b06450c64..000000000 --- a/vendor/github.com/go-openapi/swag/loading/loading.go +++ /dev/null @@ -1,190 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers -// SPDX-License-Identifier: Apache-2.0 - -package loading - -import ( - "context" - "embed" - "fmt" - "io" - "log" - "net/http" - "net/url" - "path" - "path/filepath" - "runtime" - "strings" -) - -// LoadFromFileOrHTTP loads the bytes from a file or a remote http server based on the path passed in. -// -// Security: by default a local path is read with no confinement, so a caller-controlled path -// (including a "file://" URI or an absolute path) may read any file the process can access. -// When the path may derive from untrusted input, confine local loading with [WithRoot]. -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. -// -// The load strategy returns the remote load for any path starting with `http`. -// So this works for any URI with a scheme `http` or `https`. -// -// The fallback strategy is to call the local loader. -// -// The local loader takes a local file system path (absolute or relative) as argument, -// or alternatively a `file://...` URI, **without host** (see also below for windows). -// -// There are a few liberalities, initially intended to be tolerant regarding the URI syntax, -// especially on windows. -// -// Before the local loader is called, the given path is transformed: -// - percent-encoded characters are unescaped -// - simple paths (e.g. `./folder/file`) are passed as-is -// - on windows, occurrences of `/` are replaced by `\`, so providing a relative path such a `folder/file` works too. -// -// For paths provided as URIs with the "file" scheme, please note that: -// - `file://` is simply stripped. -// This means that the host part of the URI is not parsed at all. -// For example, `file:///folder/file" becomes "/folder/file`, -// but `file://localhost/folder/file` becomes `localhost/folder/file` on unix systems. -// Similarly, `file://./folder/file` yields `./folder/file`. -// - on windows, `file://...` can take a host so as to specify an UNC share location. -// -// Reminder about windows-specifics: -// - `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), opts ...Option) func(string) ([]byte, error) { - if hasHTTPScheme(pth) { - return remote - } - o := optionsWithDefaults(opts) - _, isEmbedFS := o.fs.(embed.FS) - // any loader backed by an fs.FS or an os.Root consumes forward-slash paths on every - // platform, so it must not go through the windows-native file:// preprocessing below. - isFSBacked := o.fs != nil || o.root != "" - - return func(p string) ([]byte, error) { - upth, err := url.PathUnescape(p) - if err != nil { - return nil, err - } - - cpth, hasPrefix := strings.CutPrefix(upth, "file://") - if !hasPrefix || isFSBacked || 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 - if isEmbedFS { - // embed.FS always uses "/" as separator, even on windows, and rejects leading "./" or "/". - return local(strings.TrimLeft(filepath.ToSlash(cpth), "./")) // remove invalid leading characters for embed FS - } - - if isFSBacked { - // other fs.FS (e.g. os.DirFS) and os.Root loaders also use "/" on every platform. - // Path confinement is enforced by the loader, not here: the os.Root loader rebases - // absolute in-root paths and rejects escaping paths ("..", out-of-root absolute, - // escaping symlinks); an fs.FS loader rejects what its file system does not allow. - return local(filepath.ToSlash(cpth)) - } - - return local(filepath.FromSlash(cpth)) - } - - // windows-only pre-processing of file://... URIs, excluding embed.FS - - // support for canonical file URIs on windows. - u, err := url.Parse(filepath.ToSlash(upth)) - if err != nil { - return nil, err - } - - if u.Host != "" { - // assume UNC name (volume share) - // NOTE: UNC port not yet supported - - // when the "host" segment is a drive letter: - // file://C:/folder/... => C:\folder - upth = path.Clean(strings.Join([]string{u.Host, u.Path}, `/`)) - if !strings.HasSuffix(u.Host, ":") && u.Host[0] != '.' { - // tolerance: if we have a leading dot, this can't be a host - // file://host/share/folder\... ==> \\host\share\path\folder - upth = "//" + upth - } - } else { - // no host, let's figure out if this is a drive letter - upth = strings.TrimPrefix(upth, `file://`) - first, _, _ := strings.Cut(strings.TrimPrefix(u.Path, "/"), "/") - if strings.HasSuffix(first, ":") { - // drive letter in the first segment: - // file:///c:/folder/... ==> strip the leading slash - upth = strings.TrimPrefix(upth, `/`) - } - } - - return local(filepath.FromSlash(upth)) - } -} - -// hasHTTPScheme reports whether pth is an absolute URL with an http or https scheme, -// selecting the remote loader. The comparison is case-insensitive, as URL schemes are. -// -// Requiring the "://" separator (rather than a bare "http" prefix) avoids misrouting a -// local file whose name merely starts with "http" (e.g. "httpbin.json") to the remote loader. -func hasHTTPScheme(pth string) bool { - for _, scheme := range [...]string{"http://", "https://"} { - if len(pth) >= len(scheme) && strings.EqualFold(pth[:len(scheme)], scheme) { - return true - } - } - - return false -} - -func loadHTTPBytes(opts ...Option) func(path string) ([]byte, error) { - o := optionsWithDefaults(opts) - - return func(path string) ([]byte, error) { - 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 o.basicAuthUsername != "" && o.basicAuthPassword != "" { - req.SetBasicAuth(o.basicAuthUsername, o.basicAuthPassword) - } - - for key, val := range o.customHeaders { - req.Header.Set(key, val) - } - - resp, err := client.Do(req) - defer func() { - if resp != nil { - if e := resp.Body.Close(); e != nil { - log.Println(e) - } - } - }() - if err != nil { - return nil, err - } - - if resp.StatusCode != http.StatusOK { - return nil, fmt.Errorf("could not access document at %q [%s]: %w", path, resp.Status, ErrLoader) - } - - return io.ReadAll(resp.Body) - } -} diff --git a/vendor/github.com/go-openapi/swag/loading/options.go b/vendor/github.com/go-openapi/swag/loading/options.go deleted file mode 100644 index 539987547..000000000 --- a/vendor/github.com/go-openapi/swag/loading/options.go +++ /dev/null @@ -1,237 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers -// SPDX-License-Identifier: Apache-2.0 - -package loading - -import ( - "errors" - "io/fs" - "net/http" - "os" - "path/filepath" - "runtime" - "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 - root string // when non-empty, local reads are confined to this directory via os.Root - } - - options struct { - httpOptions - fileOptions - } -) - -func (fo fileOptions) ReadFileFunc() func(string) ([]byte, error) { - if fo.root != "" { - root := fo.root - - return func(name string) ([]byte, error) { - // os.Root only accepts paths relative to the root, but callers (and this package's - // own file:// handling) routinely produce absolute paths. Rebase an absolute path - // onto the root before handing it to os.Root. - rel, err := rootRelative(root, name) - if err != nil { - return nil, errors.Join(err, ErrLoader) - } - - r, err := os.OpenRoot(root) - if err != nil { - return nil, errors.Join(err, ErrLoader) - } - defer func() { _ = r.Close() }() - - return r.ReadFile(rel) - } - } - - if fo.fs == nil { - return os.ReadFile - } - - return fo.fs.ReadFile -} - -// rootRelative expresses name as a path relative to root, so that it can be resolved by os.Root. -// -// A relative name is returned unchanged: os.Root confines it directly (including "../" traversal -// and symlink escapes, which it rejects at open time). -// -// An absolute name is rebased onto root. If it cannot be expressed relative to root — for -// example because it lives on a different volume on Windows — filepath.Rel returns an error, -// which is propagated so the read is rejected rather than silently escaping the root. An -// absolute path that lexically escapes root yields a "../" prefix here and is then rejected by -// os.Root. -func rootRelative(root, name string) (string, error) { - osName := toOSPath(name) - if !filepath.IsAbs(osName) { - return name, nil - } - - absRoot, err := filepath.Abs(toOSPath(root)) - if err != nil { - return "", err - } - - return filepath.Rel(absRoot, osName) -} - -// toOSPath converts a slash-separated path to an OS-native path. -// -// On Windows it additionally normalizes the "/C:/dir" form — a leading separator before a drive -// letter — that file URIs and URL-style path normalization (as performed by -// github.com/go-openapi/spec) produce. Without this, filepath.IsAbs does not recognize such a -// path as absolute and os.Root rejects an otherwise in-root target. This mirrors the file:// -// drive-letter handling in LoadStrategy, which the os.Root loader bypasses. -func toOSPath(p string) string { - p = filepath.FromSlash(p) - if runtime.GOOS == "windows" { - p = stripLeadingDriveSlash(p) - } - - return p -} - -// stripLeadingDriveSlash removes a leading separator that precedes a Windows drive letter, -// turning "\C:\dir" (from a "/C:/dir" URL path) into "C:\dir". Any other path is returned -// unchanged. It is pure (no OS dependency) so that its logic can be tested on any platform. -func stripLeadingDriveSlash(p string) string { - if len(p) >= 3 && (p[0] == '/' || p[0] == '\\') && p[2] == ':' && isASCIILetter(p[1]) { - return p[1:] - } - - return p -} - -func isASCIILetter(b byte) bool { - return ('a' <= b && b <= 'z') || ('A' <= b && b <= 'Z') -} - -// 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. -// -// WithFS and [WithRoot] are mutually exclusive: the last one applied wins. -// -// Security note: a file system built from [os.DirFS] confines paths but does NOT protect -// against symlinks that escape the root. To load from a directory derived from untrusted -// input, prefer [WithRoot], which is symlink-escape resistant. -func WithFS(filesystem fs.FS) Option { - return func(o *options) { - o.root = "" // last-wins vs WithRoot - if rfs, ok := filesystem.(fs.ReadFileFS); ok { - o.fs = rfs - - return - } - o.fs = readFileFS{FS: filesystem} - } -} - -// WithRoot confines local file loading to dir. -// -// Every requested path is resolved within dir. A relative path is resolved against dir; an -// absolute path is rebased onto dir (so a caller that normalizes references to absolute paths, -// such as github.com/go-openapi/spec, still resolves correctly). Any path that would escape dir -// — through ".." traversal, an absolute path pointing outside dir, or a symlink pointing outside -// dir — is rejected. This is built on [os.Root] and is therefore resistant to the symlink -// escapes that a plain [os.DirFS] does not prevent. -// -// WithRoot is the recommended option when loading specs from a location derived from -// untrusted input. It applies to local loading only and has no effect on remote -// (http/https) loading. WithRoot and [WithFS] are mutually exclusive: the last one applied -// wins. -// -// Note: [os.Root] confines path resolution but does not, by itself, protect against -// traversal of mount/bind boundaries, /proc special files, or device files. Point WithRoot -// at a directory that holds only the documents you intend to expose. -func WithRoot(dir string) Option { - return func(o *options) { - o.root = dir - o.fs = nil // last-wins vs WithFS - } -} - -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 -} diff --git a/vendor/github.com/go-openapi/swag/loading/yaml.go b/vendor/github.com/go-openapi/swag/loading/yaml.go deleted file mode 100644 index 3ebb53668..000000000 --- a/vendor/github.com/go-openapi/swag/loading/yaml.go +++ /dev/null @@ -1,37 +0,0 @@ -// 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) -} diff --git a/vendor/github.com/go-openapi/swag/loading_iface.go b/vendor/github.com/go-openapi/swag/loading_iface.go deleted file mode 100644 index 78dadfccd..000000000 --- a/vendor/github.com/go-openapi/swag/loading_iface.go +++ /dev/null @@ -1,93 +0,0 @@ -// 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 { - const defaultOptions = 3 - o := make([]loading.Option, 0, defaultOptions+len(opts)) - o = append(o, []loading.Option{ - loading.WithTimeout(LoadHTTPTimeout), - loading.WithBasicAuth(LoadHTTPBasicAuthUsername, LoadHTTPBasicAuthPassword), - loading.WithCustomHeaders(LoadHTTPCustomHeaders), - }...) - o = append(o, opts...) - - return o -} diff --git a/vendor/github.com/go-openapi/swag/mangling/BENCHMARK.md b/vendor/github.com/go-openapi/swag/mangling/BENCHMARK.md deleted file mode 100644 index abe6e9533..000000000 --- a/vendor/github.com/go-openapi/swag/mangling/BENCHMARK.md +++ /dev/null @@ -1,90 +0,0 @@ -# Benchmarking name mangling utilities - -```bash -go test -bench XXX -run XXX -benchtime 30s -``` - -## Benchmarks at `b3e7a5386f996177e4808f11acb2aa93a0f660df` - -``` -goos: linux -goarch: amd64 -pkg: github.com/go-openapi/swag -cpu: Intel(R) Core(TM) i5-6200U CPU @ 2.30GHz -BenchmarkToXXXName/ToGoName-4 862623 44101 ns/op 10450 B/op 732 allocs/op -BenchmarkToXXXName/ToVarName-4 853656 40728 ns/op 10468 B/op 734 allocs/op -BenchmarkToXXXName/ToFileName-4 1268312 27813 ns/op 9785 B/op 617 allocs/op -BenchmarkToXXXName/ToCommandName-4 1276322 27903 ns/op 9785 B/op 617 allocs/op -BenchmarkToXXXName/ToHumanNameLower-4 895334 40354 ns/op 10472 B/op 731 allocs/op -BenchmarkToXXXName/ToHumanNameTitle-4 882441 40678 ns/op 10566 B/op 749 allocs/op -``` - -## Benchmarks after PR #79 - -~ x10 performance improvement and ~ /100 memory allocations. - -``` -goos: linux -goarch: amd64 -pkg: github.com/go-openapi/swag -cpu: Intel(R) Core(TM) i5-6200U CPU @ 2.30GHz -BenchmarkToXXXName/ToGoName-4 9595830 3991 ns/op 42 B/op 5 allocs/op -BenchmarkToXXXName/ToVarName-4 9194276 3984 ns/op 62 B/op 7 allocs/op -BenchmarkToXXXName/ToFileName-4 17002711 2123 ns/op 147 B/op 7 allocs/op -BenchmarkToXXXName/ToCommandName-4 16772926 2111 ns/op 147 B/op 7 allocs/op -BenchmarkToXXXName/ToHumanNameLower-4 9788331 3749 ns/op 92 B/op 6 allocs/op -BenchmarkToXXXName/ToHumanNameTitle-4 9188260 3941 ns/op 104 B/op 6 allocs/op -``` - -``` -goos: linux -goarch: amd64 -pkg: github.com/go-openapi/swag -cpu: AMD Ryzen 7 5800X 8-Core Processor -BenchmarkToXXXName/ToGoName-16 18527378 1972 ns/op 42 B/op 5 allocs/op -BenchmarkToXXXName/ToVarName-16 15552692 2093 ns/op 62 B/op 7 allocs/op -BenchmarkToXXXName/ToFileName-16 32161176 1117 ns/op 147 B/op 7 allocs/op -BenchmarkToXXXName/ToCommandName-16 32256634 1137 ns/op 147 B/op 7 allocs/op -BenchmarkToXXXName/ToHumanNameLower-16 18599661 1946 ns/op 92 B/op 6 allocs/op -BenchmarkToXXXName/ToHumanNameTitle-16 17581353 2054 ns/op 105 B/op 6 allocs/op -``` - -## 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 -``` diff --git a/vendor/github.com/go-openapi/swag/mangling/LICENSE b/vendor/github.com/go-openapi/swag/mangling/LICENSE deleted file mode 100644 index d64569567..000000000 --- a/vendor/github.com/go-openapi/swag/mangling/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/go-openapi/swag/mangling/doc.go b/vendor/github.com/go-openapi/swag/mangling/doc.go deleted file mode 100644 index ce0d89048..000000000 --- a/vendor/github.com/go-openapi/swag/mangling/doc.go +++ /dev/null @@ -1,25 +0,0 @@ -// 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 diff --git a/vendor/github.com/go-openapi/swag/mangling/initialism_index.go b/vendor/github.com/go-openapi/swag/mangling/initialism_index.go deleted file mode 100644 index e5b70c149..000000000 --- a/vendor/github.com/go-openapi/swag/mangling/initialism_index.go +++ /dev/null @@ -1,270 +0,0 @@ -// 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 "" - } -} - -// 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 -} diff --git a/vendor/github.com/go-openapi/swag/mangling/name_lexem.go b/vendor/github.com/go-openapi/swag/mangling/name_lexem.go deleted file mode 100644 index bc837e3b9..000000000 --- a/vendor/github.com/go-openapi/swag/mangling/name_lexem.go +++ /dev/null @@ -1,186 +0,0 @@ -// 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 -} diff --git a/vendor/github.com/go-openapi/swag/mangling/name_mangler.go b/vendor/github.com/go-openapi/swag/mangling/name_mangler.go deleted file mode 100644 index da685681d..000000000 --- a/vendor/github.com/go-openapi/swag/mangling/name_mangler.go +++ /dev/null @@ -1,370 +0,0 @@ -// 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 -} diff --git a/vendor/github.com/go-openapi/swag/mangling/options.go b/vendor/github.com/go-openapi/swag/mangling/options.go deleted file mode 100644 index 3c92b2f18..000000000 --- a/vendor/github.com/go-openapi/swag/mangling/options.go +++ /dev/null @@ -1,150 +0,0 @@ -// 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 -} diff --git a/vendor/github.com/go-openapi/swag/mangling/pools.go b/vendor/github.com/go-openapi/swag/mangling/pools.go deleted file mode 100644 index f81043514..000000000 --- a/vendor/github.com/go-openapi/swag/mangling/pools.go +++ /dev/null @@ -1,123 +0,0 @@ -// 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) -} diff --git a/vendor/github.com/go-openapi/swag/mangling/split.go b/vendor/github.com/go-openapi/swag/mangling/split.go deleted file mode 100644 index ed12ea256..000000000 --- a/vendor/github.com/go-openapi/swag/mangling/split.go +++ /dev/null @@ -1,341 +0,0 @@ -// 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()) - } -} diff --git a/vendor/github.com/go-openapi/swag/mangling/string_bytes.go b/vendor/github.com/go-openapi/swag/mangling/string_bytes.go deleted file mode 100644 index 28daaf72b..000000000 --- a/vendor/github.com/go-openapi/swag/mangling/string_bytes.go +++ /dev/null @@ -1,11 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers -// SPDX-License-Identifier: Apache-2.0 - -package mangling - -import "unsafe" - -// hackStringBytes returns the (unsafe) underlying bytes slice of a string. -func hackStringBytes(str string) []byte { - return unsafe.Slice(unsafe.StringData(str), len(str)) -} diff --git a/vendor/github.com/go-openapi/swag/mangling/util.go b/vendor/github.com/go-openapi/swag/mangling/util.go deleted file mode 100644 index 0636417e3..000000000 --- a/vendor/github.com/go-openapi/swag/mangling/util.go +++ /dev/null @@ -1,118 +0,0 @@ -// 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 -} diff --git a/vendor/github.com/go-openapi/swag/mangling_iface.go b/vendor/github.com/go-openapi/swag/mangling_iface.go deleted file mode 100644 index 98b9a9992..000000000 --- a/vendor/github.com/go-openapi/swag/mangling_iface.go +++ /dev/null @@ -1,69 +0,0 @@ -// 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) } diff --git a/vendor/github.com/go-openapi/swag/netutils/LICENSE b/vendor/github.com/go-openapi/swag/netutils/LICENSE deleted file mode 100644 index d64569567..000000000 --- a/vendor/github.com/go-openapi/swag/netutils/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/go-openapi/swag/netutils/doc.go b/vendor/github.com/go-openapi/swag/netutils/doc.go deleted file mode 100644 index 74282f8e5..000000000 --- a/vendor/github.com/go-openapi/swag/netutils/doc.go +++ /dev/null @@ -1,5 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers -// SPDX-License-Identifier: Apache-2.0 - -// Package netutils provides helpers for network-related tasks. -package netutils diff --git a/vendor/github.com/go-openapi/swag/netutils/net.go b/vendor/github.com/go-openapi/swag/netutils/net.go deleted file mode 100644 index 82a1544af..000000000 --- a/vendor/github.com/go-openapi/swag/netutils/net.go +++ /dev/null @@ -1,31 +0,0 @@ -// 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 -} diff --git a/vendor/github.com/go-openapi/swag/netutils_iface.go b/vendor/github.com/go-openapi/swag/netutils_iface.go deleted file mode 100644 index d658de25b..000000000 --- a/vendor/github.com/go-openapi/swag/netutils_iface.go +++ /dev/null @@ -1,13 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers -// SPDX-License-Identifier: Apache-2.0 - -package swag - -import "github.com/go-openapi/swag/netutils" - -// SplitHostPort splits a network address into a host and a port. -// -// Deprecated: use [netutils.SplitHostPort] instead. -func SplitHostPort(addr string) (host string, port int, err error) { - return netutils.SplitHostPort(addr) -} diff --git a/vendor/github.com/go-openapi/swag/stringutils/LICENSE b/vendor/github.com/go-openapi/swag/stringutils/LICENSE deleted file mode 100644 index d64569567..000000000 --- a/vendor/github.com/go-openapi/swag/stringutils/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/go-openapi/swag/stringutils/collection_formats.go b/vendor/github.com/go-openapi/swag/stringutils/collection_formats.go deleted file mode 100644 index 28056ad25..000000000 --- a/vendor/github.com/go-openapi/swag/stringutils/collection_formats.go +++ /dev/null @@ -1,74 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers -// SPDX-License-Identifier: Apache-2.0 - -package stringutils - -import "strings" - -const ( - // collectionFormatComma = "csv" - collectionFormatSpace = "ssv" - collectionFormatTab = "tsv" - collectionFormatPipe = "pipes" - collectionFormatMulti = "multi" - - collectionFormatDefaultSep = "," -) - -// JoinByFormat joins a string array by a known format (e.g. swagger's collectionFormat attribute): -// -// ssv: space separated value -// tsv: tab separated value -// pipes: pipe (|) separated value -// csv: comma separated value (default) -func JoinByFormat(data []string, format string) []string { - if len(data) == 0 { - return data - } - var sep string - switch format { - case collectionFormatSpace: - sep = " " - case collectionFormatTab: - sep = "\t" - case collectionFormatPipe: - sep = "|" - case collectionFormatMulti: - return data - default: - sep = collectionFormatDefaultSep - } - return []string{strings.Join(data, sep)} -} - -// SplitByFormat splits a string by a known format: -// -// ssv: space separated value -// tsv: tab separated value -// pipes: pipe (|) separated value -// csv: comma separated value (default) -func SplitByFormat(data, format string) []string { - if data == "" { - return nil - } - var sep string - switch format { - case collectionFormatSpace: - sep = " " - case collectionFormatTab: - sep = "\t" - case collectionFormatPipe: - sep = "|" - case collectionFormatMulti: - return nil - default: - sep = collectionFormatDefaultSep - } - var result []string - for _, s := range strings.Split(data, sep) { - if ts := strings.TrimSpace(s); ts != "" { - result = append(result, ts) - } - } - return result -} diff --git a/vendor/github.com/go-openapi/swag/stringutils/doc.go b/vendor/github.com/go-openapi/swag/stringutils/doc.go deleted file mode 100644 index c6d17a116..000000000 --- a/vendor/github.com/go-openapi/swag/stringutils/doc.go +++ /dev/null @@ -1,5 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers -// SPDX-License-Identifier: Apache-2.0 - -// Package stringutils exposes helpers to search and process strings. -package stringutils diff --git a/vendor/github.com/go-openapi/swag/stringutils/strings.go b/vendor/github.com/go-openapi/swag/stringutils/strings.go deleted file mode 100644 index cd792b7d0..000000000 --- a/vendor/github.com/go-openapi/swag/stringutils/strings.go +++ /dev/null @@ -1,23 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers -// SPDX-License-Identifier: Apache-2.0 - -package stringutils - -import ( - "slices" - "strings" -) - -// ContainsStrings searches a slice of strings for a case-sensitive match -// -// Now equivalent to the standard library [slice.Contains]. -func ContainsStrings(coll []string, item string) bool { - return slices.Contains(coll, item) -} - -// ContainsStringsCI searches a slice of strings for a case-insensitive match -func ContainsStringsCI(coll []string, item string) bool { - return slices.ContainsFunc(coll, func(e string) bool { - return strings.EqualFold(e, item) - }) -} diff --git a/vendor/github.com/go-openapi/swag/stringutils_iface.go b/vendor/github.com/go-openapi/swag/stringutils_iface.go deleted file mode 100644 index dbfa48484..000000000 --- a/vendor/github.com/go-openapi/swag/stringutils_iface.go +++ /dev/null @@ -1,34 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers -// SPDX-License-Identifier: Apache-2.0 - -package swag - -import "github.com/go-openapi/swag/stringutils" - -// ContainsStrings searches a slice of strings for a case-sensitive match. -// -// Deprecated: use [slices.Contains] or [stringutils.ContainsStrings] instead. -func ContainsStrings(coll []string, item string) bool { - return stringutils.ContainsStrings(coll, item) -} - -// ContainsStringsCI searches a slice of strings for a case-insensitive match. -// -// Deprecated: use [stringutils.ContainsStringsCI] instead. -func ContainsStringsCI(coll []string, item string) bool { - return stringutils.ContainsStringsCI(coll, item) -} - -// JoinByFormat joins a string array by a known format (e.g. swagger's collectionFormat attribute). -// -// Deprecated: use [stringutils.JoinByFormat] instead. -func JoinByFormat(data []string, format string) []string { - return stringutils.JoinByFormat(data, format) -} - -// SplitByFormat splits a string by a known format. -// -// Deprecated: use [stringutils.SplitByFormat] instead. -func SplitByFormat(data, format string) []string { - return stringutils.SplitByFormat(data, format) -} diff --git a/vendor/github.com/go-openapi/swag/typeutils_iface.go b/vendor/github.com/go-openapi/swag/typeutils_iface.go deleted file mode 100644 index b63813ea4..000000000 --- a/vendor/github.com/go-openapi/swag/typeutils_iface.go +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers -// SPDX-License-Identifier: Apache-2.0 - -package swag - -import "github.com/go-openapi/swag/typeutils" - -// IsZero returns true when the value passed into the function is a zero value. -// This allows for safer checking of interface values. -// -// Deprecated: use [typeutils.IsZero] instead. -func IsZero(data any) bool { return typeutils.IsZero(data) } diff --git a/vendor/github.com/go-openapi/swag/yamlutils/LICENSE b/vendor/github.com/go-openapi/swag/yamlutils/LICENSE deleted file mode 100644 index d64569567..000000000 --- a/vendor/github.com/go-openapi/swag/yamlutils/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/go-openapi/swag/yamlutils/doc.go b/vendor/github.com/go-openapi/swag/yamlutils/doc.go deleted file mode 100644 index 7bb92a82f..000000000 --- a/vendor/github.com/go-openapi/swag/yamlutils/doc.go +++ /dev/null @@ -1,13 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers -// SPDX-License-Identifier: Apache-2.0 - -// Package yamlutils provides utilities to work with YAML documents. -// -// - [BytesToYAMLDoc] to construct a [yaml.Node] document -// - [YAMLToJSON] to convert a [yaml.Node] document to JSON bytes -// - [YAMLMapSlice] to serialize and deserialize YAML with the order of keys maintained -package yamlutils - -import ( - _ "go.yaml.in/yaml/v3" // for documentation purpose only -) diff --git a/vendor/github.com/go-openapi/swag/yamlutils/errors.go b/vendor/github.com/go-openapi/swag/yamlutils/errors.go deleted file mode 100644 index e87bc5e8b..000000000 --- a/vendor/github.com/go-openapi/swag/yamlutils/errors.go +++ /dev/null @@ -1,15 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers -// SPDX-License-Identifier: Apache-2.0 - -package yamlutils - -type yamlError string - -const ( - // ErrYAML is an error raised by YAML utilities - ErrYAML yamlError = "yaml error" -) - -func (e yamlError) Error() string { - return string(e) -} diff --git a/vendor/github.com/go-openapi/swag/yamlutils/ordered_map.go b/vendor/github.com/go-openapi/swag/yamlutils/ordered_map.go deleted file mode 100644 index 24d951f8d..000000000 --- a/vendor/github.com/go-openapi/swag/yamlutils/ordered_map.go +++ /dev/null @@ -1,335 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers -// SPDX-License-Identifier: Apache-2.0 - -package yamlutils - -import ( - "fmt" - "iter" - "slices" - "sort" - "strconv" - - "github.com/go-openapi/swag/conv" - "github.com/go-openapi/swag/jsonutils" - "github.com/go-openapi/swag/jsonutils/adapters/ifaces" - "github.com/go-openapi/swag/typeutils" - yaml "go.yaml.in/yaml/v3" -) - -var ( - _ yaml.Marshaler = YAMLMapSlice{} - _ yaml.Unmarshaler = &YAMLMapSlice{} -) - -// YAMLMapSlice represents a YAML object, with the order of keys maintained. -// -// It is similar to [jsonutils.JSONMapSlice] and also knows how to marshal and unmarshal YAML. -// -// It behaves like an ordered map, but keys can't be accessed in constant time. -type YAMLMapSlice []YAMLMapItem - -// YAMLMapItem represents the value of a key in a YAML object held by [YAMLMapSlice]. -// -// It is entirely equivalent to [jsonutils.JSONMapItem], with the same limitation that -// you should not Marshal or Unmarshal directly this type, outside of a [YAMLMapSlice]. -type YAMLMapItem = jsonutils.JSONMapItem - -func (s YAMLMapSlice) OrderedItems() iter.Seq2[string, any] { - return func(yield func(string, any) bool) { - for _, item := range s { - if !yield(item.Key, item.Value) { - return - } - } - } -} - -// SetOrderedItems implements [ifaces.SetOrdered]: it merges keys passed by the iterator argument -// into the [YAMLMapSlice]. -func (s *YAMLMapSlice) 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, YAMLMapItem{Key: k, Value: v}) - } - - *s = m - - return - } - - for k, v := range items { - m = append(m, YAMLMapItem{Key: k, Value: v}) - } - - *s = m -} - -// MarshalJSON renders this YAML object as JSON bytes. -// -// The difference with standard JSON marshaling is that the order of keys is maintained. -func (s YAMLMapSlice) MarshalJSON() ([]byte, error) { - return jsonutils.JSONMapSlice(s).MarshalJSON() -} - -// UnmarshalJSON builds this YAML object from JSON bytes. -// -// The difference with standard JSON marshaling is that the order of keys is maintained. -func (s *YAMLMapSlice) UnmarshalJSON(data []byte) error { - js := jsonutils.JSONMapSlice(*s) - - if err := js.UnmarshalJSON(data); err != nil { - return err - } - - *s = YAMLMapSlice(js) - - return nil -} - -// MarshalYAML produces a YAML document as bytes -// -// The difference with standard YAML marshaling is that the order of keys is maintained. -// -// It implements [yaml.Marshaler]. -func (s YAMLMapSlice) MarshalYAML() (any, error) { - if typeutils.IsNil(s) { - return []byte("null\n"), nil - } - var n yaml.Node - n.Kind = yaml.DocumentNode - var nodes []*yaml.Node - - for _, item := range s { - nn, err := json2yaml(item.Value, 1) - if err != nil { - return nil, err - } - - ns := []*yaml.Node{ - { - Kind: yaml.ScalarNode, - Tag: yamlStringScalar, - Value: item.Key, - }, - nn, - } - nodes = append(nodes, ns...) - } - - n.Content = []*yaml.Node{ - { - Kind: yaml.MappingNode, - Content: nodes, - }, - } - - return yaml.Marshal(&n) -} - -// UnmarshalYAML builds a YAMLMapSlice object from a YAML document [yaml.Node]. -// -// It implements [yaml.Unmarshaler]. -func (s *YAMLMapSlice) UnmarshalYAML(node *yaml.Node) error { - return s.unmarshalYAML(newYAMLWalker(), node, 0) -} - -// unmarshalYAML builds the slice from a [yaml.Node], tracking the recursion depth (against -// stack-overflow) and threading the [yamlWalker] so anchor/alias expansion stays bounded -// across the whole document. -func (s *YAMLMapSlice) unmarshalYAML(w *yamlWalker, node *yaml.Node, depth int) error { - if depth > defaultMaxNestingDepth { - return errMaxNestingDepth - } - - if typeutils.IsNil(*s) { - // allow to unmarshal with a simple var declaration (nil slice) - *s = YAMLMapSlice{} - } - if node == nil { - *s = nil - return nil - } - - const sensibleAllocDivider = 2 - m := slices.Grow(*s, len(node.Content)/sensibleAllocDivider) - m = m[:0] - - for i := 0; i < len(node.Content); i += 2 { - if err := w.account(); err != nil { // account the key node - return err - } - - var nmi YAMLMapItem - k, err := yamlStringScalarC(node.Content[i]) - if err != nil { - return fmt.Errorf("unable to decode YAML map key: %w: %w", err, ErrYAML) - } - nmi.Key = k - v, err := w.node(node.Content[i+1], depth+1) - if err != nil { - return fmt.Errorf("unable to process YAML map value for key %q: %w: %w", k, err, ErrYAML) - } - nmi.Value = v - m = append(m, nmi) - } - - *s = m - - return nil -} - -func json2yaml(item any, depth int) (*yaml.Node, error) { - if depth > defaultMaxNestingDepth { - return nil, errMaxNestingDepth - } - - if typeutils.IsNil(item) { - return &yaml.Node{ - Kind: yaml.ScalarNode, - Value: "null", - }, nil - } - - switch val := item.(type) { - case ifaces.Ordered: - return orderedYAML(val, depth) - - case map[string]any: - var n yaml.Node - n.Kind = yaml.MappingNode - keys := make([]string, 0, len(val)) - for k := range val { - keys = append(keys, k) - } - sort.Strings(keys) - - for _, k := range keys { - v := val[k] - childNode, err := json2yaml(v, depth+1) - if err != nil { - return nil, err - } - n.Content = append(n.Content, &yaml.Node{ - Kind: yaml.ScalarNode, - Tag: yamlStringScalar, - Value: k, - }, childNode) - } - return &n, nil - - case []any: - var n yaml.Node - n.Kind = yaml.SequenceNode - for i := range val { - childNode, err := json2yaml(val[i], depth+1) - if err != nil { - return nil, err - } - n.Content = append(n.Content, childNode) - } - return &n, nil - case string: - return &yaml.Node{ - Kind: yaml.ScalarNode, - Tag: yamlStringScalar, - Value: val, - }, nil - case float32: - return floatNode(val) - case float64: - return floatNode(val) - case int: - return integerNode(val) - case int8: - return integerNode(val) - case int16: - return integerNode(val) - case int32: - return integerNode(val) - case int64: - return integerNode(val) - case uint: - return uintegerNode(val) - case uint8: - return uintegerNode(val) - case uint16: - return uintegerNode(val) - case uint32: - return uintegerNode(val) - case uint64: - return uintegerNode(val) - case bool: - return &yaml.Node{ - Kind: yaml.ScalarNode, - Tag: yamlBoolScalar, - Value: strconv.FormatBool(val), - }, nil - default: - return nil, fmt.Errorf("unhandled type: %T: %w", val, ErrYAML) - } -} - -func floatNode[T conv.Float](val T) (*yaml.Node, error) { - return &yaml.Node{ - Kind: yaml.ScalarNode, - Tag: yamlFloatScalar, - Value: conv.FormatFloat(val), - }, nil -} - -func integerNode[T conv.Signed](val T) (*yaml.Node, error) { - return &yaml.Node{ - Kind: yaml.ScalarNode, - Tag: yamlIntScalar, - Value: conv.FormatInteger(val), - }, nil -} - -func uintegerNode[T conv.Unsigned](val T) (*yaml.Node, error) { - return &yaml.Node{ - Kind: yaml.ScalarNode, - Tag: yamlIntScalar, - Value: conv.FormatUinteger(val), - }, nil -} - -func orderedYAML[T ifaces.Ordered](val T, depth int) (*yaml.Node, error) { - var n yaml.Node - n.Kind = yaml.MappingNode - for key, value := range val.OrderedItems() { - childNode, err := json2yaml(value, depth+1) - if err != nil { - return nil, err - } - - n.Content = append(n.Content, &yaml.Node{ - Kind: yaml.ScalarNode, - Tag: yamlStringScalar, - Value: key, - }, childNode) - } - return &n, nil -} diff --git a/vendor/github.com/go-openapi/swag/yamlutils/yaml.go b/vendor/github.com/go-openapi/swag/yamlutils/yaml.go deleted file mode 100644 index d4b5335f6..000000000 --- a/vendor/github.com/go-openapi/swag/yamlutils/yaml.go +++ /dev/null @@ -1,328 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers -// SPDX-License-Identifier: Apache-2.0 - -package yamlutils - -import ( - json "encoding/json" - "fmt" - "strconv" - - "github.com/go-openapi/swag/jsonutils" - yaml "go.yaml.in/yaml/v3" -) - -// defaultMaxNestingDepth caps the recursion depth of the YAML<->JSON transforms to -// guard against stack-overflow on deeply nested (possibly adversarial) input. -// -// It matches the limit enforced by go.yaml.in/yaml/v3's own parser and by -// encoding/json's decoder. -const defaultMaxNestingDepth = 10000 - -// Bounds on YAML anchor/alias expansion. -// -// go.yaml.in/yaml/v3 enforces these when decoding into Go values, but that guard is -// coupled to the library's own tree walk: when we decode into a low-level [yaml.Node] -// (to preserve key order) and expand aliases ourselves in [yamlWalker.node], we bypass -// it. We therefore reproduce it here, with the same constants and ratio schedule as the -// library's decoder (see go.yaml.in/yaml/v3 decode.go, "excessive aliasing"). -const ( - aliasCountThreshold = 100 - decodeCountThreshold = 1000 - - // 400,000 decode operations is ~500kb of dense object declarations, or - // ~5kb of dense object declarations with 10000% alias expansion. - aliasRatioRangeLow = 400000 - // 4,000,000 decode operations is ~5MB of dense object declarations. - aliasRatioRangeHigh = 4000000 - aliasRatioRange = float64(aliasRatioRangeHigh - aliasRatioRangeLow) - - // tolerated share of alias-driven decodes: from aliasRatioSmall (small/medium documents) - // down to aliasRatioLarge (very large ones), interpolated with slope aliasRatioSlope. - aliasRatioSmall = 0.99 - aliasRatioLarge = 0.10 - aliasRatioSlope = aliasRatioSmall - aliasRatioLarge -) - -var ( - // errMaxNestingDepth is returned when a document nests deeper than [defaultMaxNestingDepth]. - errMaxNestingDepth = fmt.Errorf("maximum nesting depth of %d exceeded: %w", defaultMaxNestingDepth, ErrYAML) - - // errExcessiveAliasing is returned when anchor/alias expansion is disproportionate to the - // size of the document, i.e. an "alias bomb". - errExcessiveAliasing = fmt.Errorf("document contains excessive aliasing: %w", ErrYAML) -) - -// allowedAliasRatio scales the tolerated share of alias-driven decode operations from 99% -// for small-to-medium documents down to 10% for very large ones, mirroring go.yaml.in/yaml/v3. -func allowedAliasRatio(decodeCount int) float64 { - switch { - case decodeCount <= aliasRatioRangeLow: - return aliasRatioSmall - case decodeCount >= aliasRatioRangeHigh: - return aliasRatioLarge - default: - return aliasRatioSmall - aliasRatioSlope*(float64(decodeCount-aliasRatioRangeLow)/aliasRatioRange) - } -} - -// yamlWalker carries the state needed to bound a single YAML-tree traversal: -// anchor/alias expansion accounting and cycle detection. -// -// A fresh walker is created per top-level conversion; it is threaded (not copied) through -// the whole recursive walk so its counters accumulate across the entire document. -type yamlWalker struct { - decodeCount int - aliasCount int - aliasDepth int - aliases map[*yaml.Node]bool // anchors currently being expanded, for cycle detection -} - -func newYAMLWalker() *yamlWalker { - return &yamlWalker{aliases: make(map[*yaml.Node]bool)} -} - -// account records one processed node and fails if alias expansion has become excessive. -func (w *yamlWalker) account() error { - w.decodeCount++ - if w.aliasDepth > 0 { - w.aliasCount++ - } - - if w.aliasCount > aliasCountThreshold && - w.decodeCount > decodeCountThreshold && - float64(w.aliasCount)/float64(w.decodeCount) > allowedAliasRatio(w.decodeCount) { - return errExcessiveAliasing - } - - return nil -} - -// YAMLToJSON converts a YAML document into JSON bytes. -// -// Note: a YAML document is the output from a [yaml.Marshaler], e.g a pointer to a [yaml.Node]. -// -// [YAMLToJSON] is typically called after [BytesToYAMLDoc]. -func YAMLToJSON(value any) (json.RawMessage, error) { - jm, err := transformData(value, 0) - if err != nil { - return nil, err - } - - b, err := jsonutils.WriteJSON(jm) - - return json.RawMessage(b), err -} - -// BytesToYAMLDoc converts a byte slice into a YAML document. -// -// This function only supports root documents that are objects. -// -// A YAML document is a pointer to a [yaml.Node]. -func BytesToYAMLDoc(data []byte) (any, error) { - var document yaml.Node // preserve order that is present in the document - if err := yaml.Unmarshal(data, &document); err != nil { - return nil, err - } - if document.Kind != yaml.DocumentNode || len(document.Content) != 1 || document.Content[0].Kind != yaml.MappingNode { - return nil, fmt.Errorf("only YAML documents that are objects are supported: %w", ErrYAML) - } - return &document, nil -} - -func (w *yamlWalker) node(root *yaml.Node, depth int) (any, error) { - if depth > defaultMaxNestingDepth { - return nil, errMaxNestingDepth - } - if err := w.account(); err != nil { - return nil, err - } - - switch root.Kind { - case yaml.DocumentNode: - return w.document(root, depth) - case yaml.SequenceNode: - return w.sequence(root, depth) - case yaml.MappingNode: - return w.mapping(root, depth) - case yaml.ScalarNode: - return yamlScalar(root) - case yaml.AliasNode: - return w.alias(root, depth) - default: - return nil, fmt.Errorf("unsupported YAML node type: %v: %w", root.Kind, ErrYAML) - } -} - -// alias resolves an anchor reference, expanding the anchored subtree. It detects cycles -// (an anchor whose expansion transitively references itself) and accounts the expansion -// against the alias-bomb budget via [yamlWalker.aliasDepth]. -func (w *yamlWalker) alias(node *yaml.Node, depth int) (any, error) { - if node.Alias == nil { - return nil, fmt.Errorf("invalid YAML alias node %q: %w", node.Value, ErrYAML) - } - if w.aliases[node.Alias] { - return nil, fmt.Errorf("anchor %q contains itself: %w", node.Value, ErrYAML) - } - - w.aliases[node.Alias] = true - w.aliasDepth++ - out, err := w.node(node.Alias, depth+1) - w.aliasDepth-- - delete(w.aliases, node.Alias) - - return out, err -} - -func (w *yamlWalker) document(node *yaml.Node, depth int) (any, error) { - if len(node.Content) != 1 { - return nil, fmt.Errorf("unexpected YAML Document node content length: %d: %w", len(node.Content), ErrYAML) - } - return w.node(node.Content[0], depth+1) -} - -func (w *yamlWalker) mapping(node *yaml.Node, depth int) (any, error) { - const sensibleAllocDivider = 2 // nodes concatenate (key,value) sequences - m := make(YAMLMapSlice, len(node.Content)/sensibleAllocDivider) - - if err := m.unmarshalYAML(w, node, depth); err != nil { - return nil, err - } - - return m, nil -} - -func (w *yamlWalker) sequence(node *yaml.Node, depth int) (any, error) { - s := make([]any, 0) - - for i := range len(node.Content) { - v, err := w.node(node.Content[i], depth+1) - if err != nil { - return nil, fmt.Errorf("unable to decode YAML sequence value: %w: %w", err, ErrYAML) - } - s = append(s, v) - } - return s, nil -} - -const ( // See https://yaml.org/type/ - yamlStringScalar = "tag:yaml.org,2002:str" - yamlIntScalar = "tag:yaml.org,2002:int" - yamlBoolScalar = "tag:yaml.org,2002:bool" - yamlFloatScalar = "tag:yaml.org,2002:float" - yamlTimestamp = "tag:yaml.org,2002:timestamp" - yamlNull = "tag:yaml.org,2002:null" -) - -func yamlScalar(node *yaml.Node) (any, error) { - switch node.LongTag() { - case yamlStringScalar: - return node.Value, nil - case yamlBoolScalar: - b, err := strconv.ParseBool(node.Value) - if err != nil { - return nil, fmt.Errorf("unable to process scalar node. Got %q. Expecting bool content: %w: %w", node.Value, err, ErrYAML) - } - return b, nil - case yamlIntScalar: - i, err := strconv.ParseInt(node.Value, 10, 64) - if err != nil { - return nil, fmt.Errorf("unable to process scalar node. Got %q. Expecting integer content: %w: %w", node.Value, err, ErrYAML) - } - return i, nil - case yamlFloatScalar: - f, err := strconv.ParseFloat(node.Value, 64) - if err != nil { - return nil, fmt.Errorf("unable to process scalar node. Got %q. Expecting float content: %w: %w", node.Value, err, ErrYAML) - } - return f, nil - case yamlTimestamp: - // YAML timestamp is marshaled as string, not time - return node.Value, nil - case yamlNull: - return nil, nil //nolint:nilnil - default: - return nil, fmt.Errorf("YAML tag %q is not supported: %w", node.LongTag(), ErrYAML) - } -} - -func yamlStringScalarC(node *yaml.Node) (string, error) { - if node.Kind != yaml.ScalarNode { - return "", fmt.Errorf("expecting a string scalar but got %q: %w", node.Kind, ErrYAML) - } - switch node.LongTag() { - case yamlStringScalar, yamlIntScalar, yamlFloatScalar: - return node.Value, nil - default: - return "", fmt.Errorf("YAML tag %q is not supported as map key: %w", node.LongTag(), ErrYAML) - } -} - -func format(t any) (string, error) { - switch k := t.(type) { - case string: - return k, nil - case uint: - return strconv.FormatUint(uint64(k), 10), nil - case uint8: - return strconv.FormatUint(uint64(k), 10), nil - case uint16: - return strconv.FormatUint(uint64(k), 10), nil - case uint32: - return strconv.FormatUint(uint64(k), 10), nil - case uint64: - return strconv.FormatUint(k, 10), nil - case int: - return strconv.Itoa(k), nil - case int8: - return strconv.FormatInt(int64(k), 10), nil - case int16: - return strconv.FormatInt(int64(k), 10), nil - case int32: - return strconv.FormatInt(int64(k), 10), nil - case int64: - return strconv.FormatInt(k, 10), nil - default: - return "", fmt.Errorf("unexpected map key type, got: %T: %w", k, ErrYAML) - } -} - -func transformData(input any, depth int) (out any, err error) { - if depth > defaultMaxNestingDepth { - return nil, errMaxNestingDepth - } - - switch in := input.(type) { - case yaml.Node: - return newYAMLWalker().node(&in, depth) - case *yaml.Node: - return newYAMLWalker().node(in, depth) - case map[any]any: - o := make(YAMLMapSlice, 0, len(in)) - for ke, va := range in { - var nmi YAMLMapItem - if nmi.Key, err = format(ke); err != nil { - return nil, err - } - - v, ert := transformData(va, depth+1) - if ert != nil { - return nil, ert - } - nmi.Value = v - o = append(o, nmi) - } - return o, nil - case []any: - len1 := len(in) - o := make([]any, len1) - for i := range len1 { - o[i], err = transformData(in[i], depth+1) - if err != nil { - return nil, err - } - } - return o, nil - } - return input, nil -} diff --git a/vendor/github.com/go-openapi/swag/yamlutils_iface.go b/vendor/github.com/go-openapi/swag/yamlutils_iface.go deleted file mode 100644 index 57767efc5..000000000 --- a/vendor/github.com/go-openapi/swag/yamlutils_iface.go +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers -// SPDX-License-Identifier: Apache-2.0 - -package swag - -import ( - "encoding/json" - - "github.com/go-openapi/swag/yamlutils" -) - -// YAMLToJSON converts YAML unmarshaled data into json compatible data -// -// Deprecated: use [yamlutils.YAMLToJSON] instead. -func YAMLToJSON(data any) (json.RawMessage, error) { return yamlutils.YAMLToJSON(data) } - -// BytesToYAMLDoc converts a byte slice into a YAML document -// -// Deprecated: use [yamlutils.BytesToYAMLDoc] instead. -func BytesToYAMLDoc(data []byte) (any, error) { return yamlutils.BytesToYAMLDoc(data) } diff --git a/vendor/k8s.io/kube-openapi/pkg/common/common.go b/vendor/k8s.io/kube-openapi/pkg/common/common.go index da2e8f11a..695d93a5e 100644 --- a/vendor/k8s.io/kube-openapi/pkg/common/common.go +++ b/vendor/k8s.io/kube-openapi/pkg/common/common.go @@ -20,8 +20,6 @@ import ( "net/http" "strings" - "github.com/emicklei/go-restful/v3" - "k8s.io/kube-openapi/pkg/spec3" "k8s.io/kube-openapi/pkg/validation/spec" ) @@ -97,12 +95,6 @@ type Config struct { // This takes precedent over the GetDefinitions function Definitions map[string]OpenAPIDefinition - // GetOperationIDAndTags returns operation id and tags for a restful route. It is an optional function to customize operation IDs. - // - // Deprecated: GetOperationIDAndTagsFromRoute should be used instead. This cannot be specified if using the new Route - // interface set of funcs. - GetOperationIDAndTags func(r *restful.Route) (string, []string, error) - // GetOperationIDAndTagsFromRoute returns operation id and tags for a Route. It is an optional function to customize operation IDs. GetOperationIDAndTagsFromRoute func(r Route) (string, []string, error) @@ -151,12 +143,6 @@ type OpenAPIV3Config struct { // This takes precedent over the GetDefinitions function Definitions map[string]OpenAPIDefinition - // GetOperationIDAndTags returns operation id and tags for a restful route. It is an optional function to customize operation IDs. - // - // Deprecated: GetOperationIDAndTagsFromRoute should be used instead. This cannot be specified if using the new Route - // interface set of funcs. - GetOperationIDAndTags func(r *restful.Route) (string, []string, error) - // GetOperationIDAndTagsFromRoute returns operation id and tags for a Route. It is an optional function to customize operation IDs. GetOperationIDAndTagsFromRoute func(r Route) (string, []string, error) diff --git a/vendor/k8s.io/kube-openapi/pkg/internal/flags.go b/vendor/k8s.io/kube-openapi/pkg/internal/flags.go deleted file mode 100644 index da5485f6a..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/flags.go +++ /dev/null @@ -1,25 +0,0 @@ -/* -Copyright 2022 The Kubernetes Authors. - -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 internal - -// Used by tests to selectively disable experimental JSON unmarshaler -var UseOptimizedJSONUnmarshaling bool = true -var UseOptimizedJSONUnmarshalingV3 bool = true - -// Used by tests to selectively disable experimental JSON marshaler -var UseOptimizedJSONMarshaling bool = true -var UseOptimizedJSONMarshalingV3 bool = true diff --git a/vendor/k8s.io/kube-openapi/pkg/internal/serialization.go b/vendor/k8s.io/kube-openapi/pkg/internal/serialization.go index 5d8ee9aa4..91c369963 100644 --- a/vendor/k8s.io/kube-openapi/pkg/internal/serialization.go +++ b/vendor/k8s.io/kube-openapi/pkg/internal/serialization.go @@ -17,8 +17,9 @@ limitations under the License. package internal import ( + jsonv2 "encoding/json/v2" + "github.com/go-openapi/jsonreference" - jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json" ) // DeterministicMarshal calls the jsonv2 library with the deterministic diff --git a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/AUTHORS b/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/AUTHORS deleted file mode 100644 index 2b00ddba0..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/AUTHORS +++ /dev/null @@ -1,3 +0,0 @@ -# This source code refers to The Go Authors for copyright purposes. -# The master list of authors is in the main Go distribution, -# visible at https://tip.golang.org/AUTHORS. diff --git a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/CONTRIBUTORS b/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/CONTRIBUTORS deleted file mode 100644 index 1fbd3e976..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/CONTRIBUTORS +++ /dev/null @@ -1,3 +0,0 @@ -# This source code was written by the Go contributors. -# The master list of contributors is in the main Go distribution, -# visible at https://tip.golang.org/CONTRIBUTORS. diff --git a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/LICENSE b/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/LICENSE deleted file mode 100644 index 244127300..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2020 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/README.md b/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/README.md deleted file mode 100644 index 937c39800..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/README.md +++ /dev/null @@ -1,175 +0,0 @@ -# JSON Serialization (v2) - -[![GoDev](https://img.shields.io/static/v1?label=godev&message=reference&color=00add8)](https://pkg.go.dev/github.com/go-json-experiment/json) -[![Build Status](https://github.com/go-json-experiment/json/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/go-json-experiment/json/actions) - -This module hosts an experimental implementation of v2 `encoding/json`. -The API is unstable and breaking changes will regularly be made. -Do not depend on this in publicly available modules. - -Any commits that make breaking API or behavior changes will be marked -with the string "WARNING: " near the top of the commit message. -It is your responsibility to inspect the list of commit changes -when upgrading the module. Not all breaking changes will lead to build failures. - -A [proposal to include this module in Go as `encoding/json/v2` and `encoding/json/jsontext`](https://github.com/golang/go/issues/71497) has been started on the Go Github project on 2025-01-30. Please provide your feedback there. - -## Goals and objectives - -* **Mostly backwards compatible:** If possible, v2 should aim to be _mostly_ -compatible with v1 in terms of both API and default behavior to ease migration. -For example, the `Marshal` and `Unmarshal` functions are the most widely used -declarations in the v1 package. It seems sensible for equivalent functionality -in v2 to be named the same and have a mostly compatible signature. -Behaviorally, we should aim for 95% to 99% backwards compatibility. -We do not aim for 100% compatibility since we want the freedom to break -certain behaviors that are now considered to have been a mistake. -Options exist that can bring the v2 implementation to 100% compatibility, -but it will not be the default. - -* **More flexible:** There is a -[long list of feature requests](https://github.com/golang/go/issues?q=is%3Aissue+is%3Aopen+encoding%2Fjson+in%3Atitle). -We should aim to provide the most flexible features that addresses most usages. -We do not want to over fit the v2 API to handle every possible use case. -Ideally, the features provided should be orthogonal in nature such that -any combination of features results in as few surprising edge cases as possible. - -* **More performant:** JSON serialization is widely used and any bit of extra -performance gains will be greatly appreciated. Some rarely used behaviors of v1 -may be dropped in favor of better performance. For example, -despite `Encoder` and `Decoder` operating on an `io.Writer` and `io.Reader`, -they do not operate in a truly streaming manner, -leading to a loss in performance. The v2 implementation should aim to be truly -streaming by default (see [#33714](https://golang.org/issue/33714)). - -* **Easy to use (hard to misuse):** The v2 API should aim to make -the common case easy and the less common case at least possible. -The API should avoid behavior that goes contrary to user expectation, -which may result in subtle bugs (see [#36225](https://golang.org/issue/36225)). - -* **v1 and v2 maintainability:** Since the v1 implementation must stay forever, -it would be beneficial if v1 could be implemented under the hood with v2, -allowing for less maintenance burden in the future. This probably implies that -behavioral changes in v2 relative to v1 need to be exposed as options. - -* **Avoid unsafe:** Standard library packages generally avoid the use of -package `unsafe` even if it could provide a performance boost. -We aim to preserve this property. - -## Expectations - -While this module aims to possibly be the v2 implementation of `encoding/json`, -there is no guarantee that this outcome will occur. As with any major change -to the Go standard library, this will eventually go through the -[Go proposal process](https://github.com/golang/proposal#readme). -At the present moment, this is still in the design and experimentation phase -and is not ready for a formal proposal. - -There are several possible outcomes from this experiment: -1. We determine that a v2 `encoding/json` would not provide sufficient benefit -over the existing v1 `encoding/json` package. Thus, we abandon this effort. -2. We propose a v2 `encoding/json` design, but it is rejected in favor of some -other design that is considered superior. -3. We propose a v2 `encoding/json` design, but rather than adding an entirely -new v2 `encoding/json` package, we decide to merge its functionality into -the existing v1 `encoding/json` package. -4. We propose a v2 `encoding/json` design and it is accepted, resulting in -its addition to the standard library. -5. Some other unforeseen outcome (among the infinite number of possibilities). - -## Development - -This module is primarily developed by -[@dsnet](https://github.com/dsnet), -[@mvdan](https://github.com/mvdan), and -[@johanbrandhorst](https://github.com/johanbrandhorst) -with feedback provided by -[@rogpeppe](https://github.com/rogpeppe), -[@ChrisHines](https://github.com/ChrisHines), and -[@rsc](https://github.com/rsc). - -Discussion about semantics occur semi-regularly, where a -[record of past meetings can be found here](https://docs.google.com/document/d/1rovrOTd-wTawGMPPlPuKhwXaYBg9VszTXR9AQQL5LfI/edit?usp=sharing). - -## Design overview - -This package aims to provide a clean separation between syntax and semantics. -Syntax deals with the structural representation of JSON (as specified in -[RFC 4627](https://tools.ietf.org/html/rfc4627), -[RFC 7159](https://tools.ietf.org/html/rfc7159), -[RFC 7493](https://tools.ietf.org/html/rfc7493), -[RFC 8259](https://tools.ietf.org/html/rfc8259), and -[RFC 8785](https://tools.ietf.org/html/rfc8785)). -Semantics deals with the meaning of syntactic data as usable application data. - -The `Encoder` and `Decoder` types are streaming tokenizers concerned with the -packing or parsing of JSON data. They operate on `Token` and `Value` types -which represent the common data structures that are representable in JSON. -`Encoder` and `Decoder` do not aim to provide any interpretation of the data. - -Functions like `Marshal`, `MarshalWrite`, `MarshalEncode`, `Unmarshal`, -`UnmarshalRead`, and `UnmarshalDecode` provide semantic meaning by correlating -any arbitrary Go type with some JSON representation of that type (as stored in -data types like `[]byte`, `io.Writer`, `io.Reader`, `Encoder`, or `Decoder`). - -![API overview](api.png) - -This diagram provides a high-level overview of the v2 `json` and `jsontext` packages. -Purple blocks represent types, while blue blocks represent functions or methods. -The arrows and their direction represent the approximate flow of data. -The bottom half of the diagram contains functionality that is only concerned -with syntax (implemented by the `jsontext` package), -while the upper half contains functionality that assigns -semantic meaning to syntactic data handled by the bottom half -(as implemented by the v2 `json` package). - -In contrast to v1 `encoding/json`, options are represented as separate types -rather than being setter methods on the `Encoder` or `Decoder` types. -Some options affects JSON serialization at the syntactic layer, -while others affect it at the semantic layer. -Some options only affect JSON when decoding, -while others affect JSON while encoding. - -## Behavior changes - -The v2 `json` package changes the default behavior of `Marshal` and `Unmarshal` -relative to the v1 `json` package to be more sensible. -Some of these behavior changes have options and workarounds to opt into -behavior similar to what v1 provided. - -This table shows an overview of the changes: - -| v1 | v2 | Details | -| -- | -- | ------- | -| JSON object members are unmarshaled into a Go struct using a **case-insensitive name match**. | JSON object members are unmarshaled into a Go struct using a **case-sensitive name match**. | [CaseSensitivity](/v1/diff_test.go#:~:text=TestCaseSensitivity) | -| When marshaling a Go struct, a struct field marked as `omitempty` is omitted if **the field value is an empty Go value**, which is defined as false, 0, a nil pointer, a nil interface value, and any empty array, slice, map, or string. | When marshaling a Go struct, a struct field marked as `omitempty` is omitted if **the field value would encode as an empty JSON value**, which is defined as a JSON null, or an empty JSON string, object, or array. | [OmitEmptyOption](/v1/diff_test.go#:~:text=TestOmitEmptyOption) | -| The `string` option **does affect** Go strings and bools. | The `string` option **does not affect** Go strings or bools. | [StringOption](/v1/diff_test.go#:~:text=TestStringOption) | -| The `string` option **does not recursively affect** sub-values of the Go field value. | The `string` option **does recursively affect** sub-values of the Go field value. | [StringOption](/v1/diff_test.go#:~:text=TestStringOption) | -| The `string` option **sometimes accepts** a JSON null escaped within a JSON string. | The `string` option **never accepts** a JSON null escaped within a JSON string. | [StringOption](/v1/diff_test.go#:~:text=TestStringOption) | -| A nil Go slice is marshaled as a **JSON null**. | A nil Go slice is marshaled as an **empty JSON array**. | [NilSlicesAndMaps](/v1/diff_test.go#:~:text=TestNilSlicesAndMaps) | -| A nil Go map is marshaled as a **JSON null**. | A nil Go map is marshaled as an **empty JSON object**. | [NilSlicesAndMaps](/v1/diff_test.go#:~:text=TestNilSlicesAndMaps) | -| A Go array may be unmarshaled from a **JSON array of any length**. | A Go array must be unmarshaled from a **JSON array of the same length**. | [Arrays](/v1/diff_test.go#:~:text=Arrays) | -| A Go byte array is represented as a **JSON array of JSON numbers**. | A Go byte array is represented as a **Base64-encoded JSON string**. | [ByteArrays](/v1/diff_test.go#:~:text=TestByteArrays) | -| `MarshalJSON` and `UnmarshalJSON` methods declared on a pointer receiver are **inconsistently called**. | `MarshalJSON` and `UnmarshalJSON` methods declared on a pointer receiver are **consistently called**. | [PointerReceiver](/v1/diff_test.go#:~:text=TestPointerReceiver) | -| A Go map is marshaled in a **deterministic order**. | A Go map is marshaled in a **non-deterministic order**. | [MapDeterminism](/v1/diff_test.go#:~:text=TestMapDeterminism) | -| JSON strings are encoded **with HTML-specific characters being escaped**. | JSON strings are encoded **without any characters being escaped** (unless necessary). | [EscapeHTML](/v1/diff_test.go#:~:text=TestEscapeHTML) | -| When marshaling, invalid UTF-8 within a Go string **are silently replaced**. | When marshaling, invalid UTF-8 within a Go string **results in an error**. | [InvalidUTF8](/v1/diff_test.go#:~:text=TestInvalidUTF8) | -| When unmarshaling, invalid UTF-8 within a JSON string **are silently replaced**. | When unmarshaling, invalid UTF-8 within a JSON string **results in an error**. | [InvalidUTF8](/v1/diff_test.go#:~:text=TestInvalidUTF8) | -| When marshaling, **an error does not occur** if the output JSON value contains objects with duplicate names. | When marshaling, **an error does occur** if the output JSON value contains objects with duplicate names. | [DuplicateNames](/v1/diff_test.go#:~:text=TestDuplicateNames) | -| When unmarshaling, **an error does not occur** if the input JSON value contains objects with duplicate names. | When unmarshaling, **an error does occur** if the input JSON value contains objects with duplicate names. | [DuplicateNames](/v1/diff_test.go#:~:text=TestDuplicateNames) | -| Unmarshaling a JSON null into a non-empty Go value **inconsistently clears the value or does nothing**. | Unmarshaling a JSON null into a non-empty Go value **always clears the value**. | [MergeNull](/v1/diff_test.go#:~:text=TestMergeNull) | -| Unmarshaling a JSON value into a non-empty Go value **follows inconsistent and bizarre behavior**. | Unmarshaling a JSON value into a non-empty Go value **always merges if the input is an object, and otherwise replaces**. | [MergeComposite](/v1/diff_test.go#:~:text=TestMergeComposite) | -| A `time.Duration` is represented as a **JSON number containing the decimal number of nanoseconds**. | A `time.Duration` has no default representation in v2 (see [#71631](https://golang.org/issue/71631)) and results in an error. | | -| A Go struct with only unexported fields **can be serialized**. | A Go struct with only unexported fields **cannot be serialized**. | [EmptyStructs](/v1/diff_test.go#:~:text=TestEmptyStructs) | - -See [diff_test.go](/v1/diff_test.go) for details about every change. - -## Performance - -One of the goals of the v2 module is to be more performant than v1, -but not at the expense of correctness. -In general, v2 is at performance parity with v1 for marshaling, -but dramatically faster for unmarshaling. - -See https://github.com/go-json-experiment/jsonbench for benchmarks -comparing v2 with v1 and a number of other popular JSON implementations. diff --git a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/arshal.go b/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/arshal.go deleted file mode 100644 index dbf92432d..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/arshal.go +++ /dev/null @@ -1,578 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package json - -import ( - "bytes" - "encoding" - "io" - "reflect" - "slices" - "strings" - "sync" - "time" - - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonflags" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonopts" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext" -) - -// Reference encoding and time packages to assist pkgsite -// in being able to hotlink references to those packages. -var ( - _ encoding.TextMarshaler - _ encoding.TextAppender - _ encoding.TextUnmarshaler - _ time.Time - _ time.Duration -) - -// export exposes internal functionality of the "jsontext" package. -var export = jsontext.Internal.Export(&internal.AllowInternalUse) - -// Marshal serializes a Go value as a []byte according to the provided -// marshal and encode options (while ignoring unmarshal or decode options). -// It does not terminate the output with a newline. -// -// Type-specific marshal functions and methods take precedence -// over the default representation of a value. -// Functions or methods that operate on *T are only called when encoding -// a value of type T (by taking its address) or a non-nil value of *T. -// Marshal ensures that a value is always addressable -// (by boxing it on the heap if necessary) so that -// these functions and methods can be consistently called. For performance, -// it is recommended that Marshal be passed a non-nil pointer to the value. -// -// The input value is encoded as JSON according the following rules: -// -// - If any type-specific functions in a [WithMarshalers] option match -// the value type, then those functions are called to encode the value. -// If all applicable functions return [SkipFunc], -// then the value is encoded according to subsequent rules. -// -// - If the value type implements [MarshalerTo], -// then the MarshalJSONTo method is called to encode the value. -// -// - If the value type implements [Marshaler], -// then the MarshalJSON method is called to encode the value. -// -// - If the value type implements [encoding.TextAppender], -// then the AppendText method is called to encode the value and -// subsequently encode its result as a JSON string. -// -// - If the value type implements [encoding.TextMarshaler], -// then the MarshalText method is called to encode the value and -// subsequently encode its result as a JSON string. -// -// - Otherwise, the value is encoded according to the value's type -// as described in detail below. -// -// Most Go types have a default JSON representation. -// Certain types support specialized formatting according to -// a format flag optionally specified in the Go struct tag -// for the struct field that contains the current value -// (see the “JSON Representation of Go structs” section for more details). -// -// The representation of each type is as follows: -// -// - A Go boolean is encoded as a JSON boolean (e.g., true or false). -// It does not support any custom format flags. -// -// - A Go string is encoded as a JSON string. -// It does not support any custom format flags. -// -// - A Go []byte or [N]byte is encoded as a JSON string containing -// the binary value encoded using RFC 4648. -// If the format is "base64" or unspecified, then this uses RFC 4648, section 4. -// If the format is "base64url", then this uses RFC 4648, section 5. -// If the format is "base32", then this uses RFC 4648, section 6. -// If the format is "base32hex", then this uses RFC 4648, section 7. -// If the format is "base16" or "hex", then this uses RFC 4648, section 8. -// If the format is "array", then the bytes value is encoded as a JSON array -// where each byte is recursively JSON-encoded as each JSON array element. -// -// - A Go integer is encoded as a JSON number without fractions or exponents. -// If [StringifyNumbers] is specified or encoding a JSON object name, -// then the JSON number is encoded within a JSON string. -// It does not support any custom format flags. -// -// - A Go float is encoded as a JSON number. -// If [StringifyNumbers] is specified or encoding a JSON object name, -// then the JSON number is encoded within a JSON string. -// If the format is "nonfinite", then NaN, +Inf, and -Inf are encoded as -// the JSON strings "NaN", "Infinity", and "-Infinity", respectively. -// Otherwise, the presence of non-finite numbers results in a [SemanticError]. -// -// - A Go map is encoded as a JSON object, where each Go map key and value -// is recursively encoded as a name and value pair in the JSON object. -// The Go map key must encode as a JSON string, otherwise this results -// in a [SemanticError]. The Go map is traversed in a non-deterministic order. -// For deterministic encoding, consider using the [Deterministic] option. -// If the format is "emitnull", then a nil map is encoded as a JSON null. -// If the format is "emitempty", then a nil map is encoded as an empty JSON object, -// regardless of whether [FormatNilMapAsNull] is specified. -// Otherwise by default, a nil map is encoded as an empty JSON object. -// -// - A Go struct is encoded as a JSON object. -// See the “JSON Representation of Go structs” section -// in the package-level documentation for more details. -// -// - A Go slice is encoded as a JSON array, where each Go slice element -// is recursively JSON-encoded as the elements of the JSON array. -// If the format is "emitnull", then a nil slice is encoded as a JSON null. -// If the format is "emitempty", then a nil slice is encoded as an empty JSON array, -// regardless of whether [FormatNilSliceAsNull] is specified. -// Otherwise by default, a nil slice is encoded as an empty JSON array. -// -// - A Go array is encoded as a JSON array, where each Go array element -// is recursively JSON-encoded as the elements of the JSON array. -// The JSON array length is always identical to the Go array length. -// It does not support any custom format flags. -// -// - A Go pointer is encoded as a JSON null if nil, otherwise it is -// the recursively JSON-encoded representation of the underlying value. -// Format flags are forwarded to the encoding of the underlying value. -// -// - A Go interface is encoded as a JSON null if nil, otherwise it is -// the recursively JSON-encoded representation of the underlying value. -// It does not support any custom format flags. -// -// - A Go [time.Time] is encoded as a JSON string containing the timestamp -// formatted in RFC 3339 with nanosecond precision. -// If the format matches one of the format constants declared -// in the time package (e.g., RFC1123), then that format is used. -// If the format is "unix", "unixmilli", "unixmicro", or "unixnano", -// then the timestamp is encoded as a possibly fractional JSON number -// of the number of seconds (or milliseconds, microseconds, or nanoseconds) -// since the Unix epoch, which is January 1st, 1970 at 00:00:00 UTC. -// To avoid a fractional component, round the timestamp to the relevant unit. -// Otherwise, the format is used as-is with [time.Time.Format] if non-empty. -// -// - A Go [time.Duration] currently has no default representation and -// requires an explicit format to be specified. -// If the format is "sec", "milli", "micro", or "nano", -// then the duration is encoded as a possibly fractional JSON number -// of the number of seconds (or milliseconds, microseconds, or nanoseconds). -// To avoid a fractional component, round the duration to the relevant unit. -// If the format is "units", it is encoded as a JSON string formatted using -// [time.Duration.String] (e.g., "1h30m" for 1 hour 30 minutes). -// If the format is "iso8601", it is encoded as a JSON string using the -// ISO 8601 standard for durations (e.g., "PT1H30M" for 1 hour 30 minutes) -// using only accurate units of hours, minutes, and seconds. -// -// - All other Go types (e.g., complex numbers, channels, and functions) -// have no default representation and result in a [SemanticError]. -// -// JSON cannot represent cyclic data structures and Marshal does not handle them. -// Passing cyclic structures will result in an error. -func Marshal(in any, opts ...Options) (out []byte, err error) { - enc := export.GetBufferedEncoder(opts...) - defer export.PutBufferedEncoder(enc) - xe := export.Encoder(enc) - xe.Flags.Set(jsonflags.OmitTopLevelNewline | 1) - err = marshalEncode(enc, in, &xe.Struct) - if err != nil && xe.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) { - return nil, internal.TransformMarshalError(in, err) - } - return bytes.Clone(xe.Buf), err -} - -// MarshalWrite serializes a Go value into an [io.Writer] according to the provided -// marshal and encode options (while ignoring unmarshal or decode options). -// It does not terminate the output with a newline. -// See [Marshal] for details about the conversion of a Go value into JSON. -func MarshalWrite(out io.Writer, in any, opts ...Options) (err error) { - enc := export.GetStreamingEncoder(out, opts...) - defer export.PutStreamingEncoder(enc) - xe := export.Encoder(enc) - xe.Flags.Set(jsonflags.OmitTopLevelNewline | 1) - err = marshalEncode(enc, in, &xe.Struct) - if err != nil && xe.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) { - return internal.TransformMarshalError(in, err) - } - return err -} - -// MarshalEncode serializes a Go value into an [jsontext.Encoder] according to -// the provided marshal options (while ignoring unmarshal, encode, or decode options). -// Any marshal-relevant options already specified on the [jsontext.Encoder] -// take lower precedence than the set of options provided by the caller. -// Unlike [Marshal] and [MarshalWrite], encode options are ignored because -// they must have already been specified on the provided [jsontext.Encoder]. -// -// See [Marshal] for details about the conversion of a Go value into JSON. -func MarshalEncode(out *jsontext.Encoder, in any, opts ...Options) (err error) { - xe := export.Encoder(out) - if len(opts) > 0 { - optsOriginal := xe.Struct - defer func() { xe.Struct = optsOriginal }() - xe.Struct.JoinWithoutCoderOptions(opts...) - } - err = marshalEncode(out, in, &xe.Struct) - if err != nil && xe.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) { - return internal.TransformMarshalError(in, err) - } - return err -} - -func marshalEncode(out *jsontext.Encoder, in any, mo *jsonopts.Struct) (err error) { - v := reflect.ValueOf(in) - if !v.IsValid() || (v.Kind() == reflect.Pointer && v.IsNil()) { - return out.WriteToken(jsontext.Null) - } - // Shallow copy non-pointer values to obtain an addressable value. - // It is beneficial to performance to always pass pointers to avoid this. - forceAddr := v.Kind() != reflect.Pointer - if forceAddr { - v2 := reflect.New(v.Type()) - v2.Elem().Set(v) - v = v2 - } - va := addressableValue{v.Elem(), forceAddr} // dereferenced pointer is always addressable - t := va.Type() - - // Lookup and call the marshal function for this type. - marshal := lookupArshaler(t).marshal - if mo.Marshalers != nil { - marshal, _ = mo.Marshalers.(*Marshalers).lookup(marshal, t) - } - if err := marshal(out, va, mo); err != nil { - if !mo.Flags.Get(jsonflags.AllowDuplicateNames) { - export.Encoder(out).Tokens.InvalidateDisabledNamespaces() - } - return err - } - return nil -} - -// Unmarshal decodes a []byte input into a Go value according to the provided -// unmarshal and decode options (while ignoring marshal or encode options). -// The input must be a single JSON value with optional whitespace interspersed. -// The output must be a non-nil pointer. -// -// Type-specific unmarshal functions and methods take precedence -// over the default representation of a value. -// Functions or methods that operate on *T are only called when decoding -// a value of type T (by taking its address) or a non-nil value of *T. -// Unmarshal ensures that a value is always addressable -// (by boxing it on the heap if necessary) so that -// these functions and methods can be consistently called. -// -// The input is decoded into the output according the following rules: -// -// - If any type-specific functions in a [WithUnmarshalers] option match -// the value type, then those functions are called to decode the JSON -// value. If all applicable functions return [SkipFunc], -// then the input is decoded according to subsequent rules. -// -// - If the value type implements [UnmarshalerFrom], -// then the UnmarshalJSONFrom method is called to decode the JSON value. -// -// - If the value type implements [Unmarshaler], -// then the UnmarshalJSON method is called to decode the JSON value. -// -// - If the value type implements [encoding.TextUnmarshaler], -// then the input is decoded as a JSON string and -// the UnmarshalText method is called with the decoded string value. -// This fails with a [SemanticError] if the input is not a JSON string. -// -// - Otherwise, the JSON value is decoded according to the value's type -// as described in detail below. -// -// Most Go types have a default JSON representation. -// Certain types support specialized formatting according to -// a format flag optionally specified in the Go struct tag -// for the struct field that contains the current value -// (see the “JSON Representation of Go structs” section for more details). -// A JSON null may be decoded into every supported Go value where -// it is equivalent to storing the zero value of the Go value. -// If the input JSON kind is not handled by the current Go value type, -// then this fails with a [SemanticError]. Unless otherwise specified, -// the decoded value replaces any pre-existing value. -// -// The representation of each type is as follows: -// -// - A Go boolean is decoded from a JSON boolean (e.g., true or false). -// It does not support any custom format flags. -// -// - A Go string is decoded from a JSON string. -// It does not support any custom format flags. -// -// - A Go []byte or [N]byte is decoded from a JSON string -// containing the binary value encoded using RFC 4648. -// If the format is "base64" or unspecified, then this uses RFC 4648, section 4. -// If the format is "base64url", then this uses RFC 4648, section 5. -// If the format is "base32", then this uses RFC 4648, section 6. -// If the format is "base32hex", then this uses RFC 4648, section 7. -// If the format is "base16" or "hex", then this uses RFC 4648, section 8. -// If the format is "array", then the Go slice or array is decoded from a -// JSON array where each JSON element is recursively decoded for each byte. -// When decoding into a non-nil []byte, the slice length is reset to zero -// and the decoded input is appended to it. -// When decoding into a [N]byte, the input must decode to exactly N bytes, -// otherwise it fails with a [SemanticError]. -// -// - A Go integer is decoded from a JSON number. -// It must be decoded from a JSON string containing a JSON number -// if [StringifyNumbers] is specified or decoding a JSON object name. -// It fails with a [SemanticError] if the JSON number -// has a fractional or exponent component. -// It also fails if it overflows the representation of the Go integer type. -// It does not support any custom format flags. -// -// - A Go float is decoded from a JSON number. -// It must be decoded from a JSON string containing a JSON number -// if [StringifyNumbers] is specified or decoding a JSON object name. -// It fails if it overflows the representation of the Go float type. -// If the format is "nonfinite", then the JSON strings -// "NaN", "Infinity", and "-Infinity" are decoded as NaN, +Inf, and -Inf. -// Otherwise, the presence of such strings results in a [SemanticError]. -// -// - A Go map is decoded from a JSON object, -// where each JSON object name and value pair is recursively decoded -// as the Go map key and value. Maps are not cleared. -// If the Go map is nil, then a new map is allocated to decode into. -// If the decoded key matches an existing Go map entry, the entry value -// is reused by decoding the JSON object value into it. -// The formats "emitnull" and "emitempty" have no effect when decoding. -// -// - A Go struct is decoded from a JSON object. -// See the “JSON Representation of Go structs” section -// in the package-level documentation for more details. -// -// - A Go slice is decoded from a JSON array, where each JSON element -// is recursively decoded and appended to the Go slice. -// Before appending into a Go slice, a new slice is allocated if it is nil, -// otherwise the slice length is reset to zero. -// The formats "emitnull" and "emitempty" have no effect when decoding. -// -// - A Go array is decoded from a JSON array, where each JSON array element -// is recursively decoded as each corresponding Go array element. -// Each Go array element is zeroed before decoding into it. -// It fails with a [SemanticError] if the JSON array does not contain -// the exact same number of elements as the Go array. -// It does not support any custom format flags. -// -// - A Go pointer is decoded based on the JSON kind and underlying Go type. -// If the input is a JSON null, then this stores a nil pointer. -// Otherwise, it allocates a new underlying value if the pointer is nil, -// and recursively JSON decodes into the underlying value. -// Format flags are forwarded to the decoding of the underlying type. -// -// - A Go interface is decoded based on the JSON kind and underlying Go type. -// If the input is a JSON null, then this stores a nil interface value. -// Otherwise, a nil interface value of an empty interface type is initialized -// with a zero Go bool, string, float64, map[string]any, or []any if the -// input is a JSON boolean, string, number, object, or array, respectively. -// If the interface value is still nil, then this fails with a [SemanticError] -// since decoding could not determine an appropriate Go type to decode into. -// For example, unmarshaling into a nil io.Reader fails since -// there is no concrete type to populate the interface value with. -// Otherwise an underlying value exists and it recursively decodes -// the JSON input into it. It does not support any custom format flags. -// -// - A Go [time.Time] is decoded from a JSON string containing the time -// formatted in RFC 3339 with nanosecond precision. -// If the format matches one of the format constants declared in -// the time package (e.g., RFC1123), then that format is used for parsing. -// If the format is "unix", "unixmilli", "unixmicro", or "unixnano", -// then the timestamp is decoded from an optionally fractional JSON number -// of the number of seconds (or milliseconds, microseconds, or nanoseconds) -// since the Unix epoch, which is January 1st, 1970 at 00:00:00 UTC. -// Otherwise, the format is used as-is with [time.Time.Parse] if non-empty. -// -// - A Go [time.Duration] currently has no default representation and -// requires an explicit format to be specified. -// If the format is "sec", "milli", "micro", or "nano", -// then the duration is decoded from an optionally fractional JSON number -// of the number of seconds (or milliseconds, microseconds, or nanoseconds). -// If the format is "units", it is decoded from a JSON string parsed using -// [time.ParseDuration] (e.g., "1h30m" for 1 hour 30 minutes). -// If the format is "iso8601", it is decoded from a JSON string using the -// ISO 8601 standard for durations (e.g., "PT1H30M" for 1 hour 30 minutes) -// accepting only accurate units of hours, minutes, or seconds. -// -// - All other Go types (e.g., complex numbers, channels, and functions) -// have no default representation and result in a [SemanticError]. -// -// In general, unmarshaling follows merge semantics (similar to RFC 7396) -// where the decoded Go value replaces the destination value -// for any JSON kind other than an object. -// For JSON objects, the input object is merged into the destination value -// where matching object members recursively apply merge semantics. -func Unmarshal(in []byte, out any, opts ...Options) (err error) { - dec := export.GetBufferedDecoder(in, opts...) - defer export.PutBufferedDecoder(dec) - xd := export.Decoder(dec) - err = unmarshalDecode(dec, out, &xd.Struct, true) - if err != nil && xd.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) { - return internal.TransformUnmarshalError(out, err) - } - return err -} - -// UnmarshalRead deserializes a Go value from an [io.Reader] according to the -// provided unmarshal and decode options (while ignoring marshal or encode options). -// The input must be a single JSON value with optional whitespace interspersed. -// It consumes the entirety of [io.Reader] until [io.EOF] is encountered, -// without reporting an error for EOF. The output must be a non-nil pointer. -// See [Unmarshal] for details about the conversion of JSON into a Go value. -func UnmarshalRead(in io.Reader, out any, opts ...Options) (err error) { - dec := export.GetStreamingDecoder(in, opts...) - defer export.PutStreamingDecoder(dec) - xd := export.Decoder(dec) - err = unmarshalDecode(dec, out, &xd.Struct, true) - if err != nil && xd.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) { - return internal.TransformUnmarshalError(out, err) - } - return err -} - -// UnmarshalDecode deserializes a Go value from a [jsontext.Decoder] according to -// the provided unmarshal options (while ignoring marshal, encode, or decode options). -// Any unmarshal options already specified on the [jsontext.Decoder] -// take lower precedence than the set of options provided by the caller. -// Unlike [Unmarshal] and [UnmarshalRead], decode options are ignored because -// they must have already been specified on the provided [jsontext.Decoder]. -// -// The input may be a stream of one or more JSON values, -// where this only unmarshals the next JSON value in the stream. -// The output must be a non-nil pointer. -// See [Unmarshal] for details about the conversion of JSON into a Go value. -func UnmarshalDecode(in *jsontext.Decoder, out any, opts ...Options) (err error) { - xd := export.Decoder(in) - if len(opts) > 0 { - optsOriginal := xd.Struct - defer func() { xd.Struct = optsOriginal }() - xd.Struct.JoinWithoutCoderOptions(opts...) - } - err = unmarshalDecode(in, out, &xd.Struct, false) - if err != nil && xd.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) { - return internal.TransformUnmarshalError(out, err) - } - return err -} - -func unmarshalDecode(in *jsontext.Decoder, out any, uo *jsonopts.Struct, last bool) (err error) { - v := reflect.ValueOf(out) - if v.Kind() != reflect.Pointer || v.IsNil() { - return &SemanticError{action: "unmarshal", GoType: reflect.TypeOf(out), Err: internal.ErrNonNilReference} - } - va := addressableValue{v.Elem(), false} // dereferenced pointer is always addressable - t := va.Type() - - // In legacy semantics, the entirety of the next JSON value - // was validated before attempting to unmarshal it. - if uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) { - if err := export.Decoder(in).CheckNextValue(last); err != nil { - if err == io.EOF && last { - offset := in.InputOffset() + int64(len(in.UnreadBuffer())) - return &jsontext.SyntacticError{ByteOffset: offset, Err: io.ErrUnexpectedEOF} - } - return err - } - } - - // Lookup and call the unmarshal function for this type. - unmarshal := lookupArshaler(t).unmarshal - if uo.Unmarshalers != nil { - unmarshal, _ = uo.Unmarshalers.(*Unmarshalers).lookup(unmarshal, t) - } - if err := unmarshal(in, va, uo); err != nil { - if !uo.Flags.Get(jsonflags.AllowDuplicateNames) { - export.Decoder(in).Tokens.InvalidateDisabledNamespaces() - } - if err == io.EOF && last { - offset := in.InputOffset() + int64(len(in.UnreadBuffer())) - return &jsontext.SyntacticError{ByteOffset: offset, Err: io.ErrUnexpectedEOF} - } - return err - } - if last { - return export.Decoder(in).CheckEOF() - } - return nil -} - -// addressableValue is a reflect.Value that is guaranteed to be addressable -// such that calling the Addr and Set methods do not panic. -// -// There is no compile magic that enforces this property, -// but rather the need to construct this type makes it easier to examine each -// construction site to ensure that this property is upheld. -type addressableValue struct { - reflect.Value - - // forcedAddr reports whether this value is addressable - // only through the use of [newAddressableValue]. - // This is only used for [jsonflags.CallMethodsWithLegacySemantics]. - forcedAddr bool -} - -// newAddressableValue constructs a new addressable value of type t. -func newAddressableValue(t reflect.Type) addressableValue { - return addressableValue{reflect.New(t).Elem(), true} -} - -// TODO: Remove *jsonopts.Struct argument from [marshaler] and [unmarshaler]. -// This can be directly accessed on the encoder or decoder. - -// All marshal and unmarshal behavior is implemented using these signatures. -// The *jsonopts.Struct argument is guaranteed to identical to or at least -// a strict super-set of the options in Encoder.Struct or Decoder.Struct. -// It is identical for Marshal, Unmarshal, MarshalWrite, and UnmarshalRead. -// It is a super-set for MarshalEncode and UnmarshalDecode. -type ( - marshaler = func(*jsontext.Encoder, addressableValue, *jsonopts.Struct) error - unmarshaler = func(*jsontext.Decoder, addressableValue, *jsonopts.Struct) error -) - -type arshaler struct { - marshal marshaler - unmarshal unmarshaler - nonDefault bool -} - -var lookupArshalerCache sync.Map // map[reflect.Type]*arshaler - -func lookupArshaler(t reflect.Type) *arshaler { - if v, ok := lookupArshalerCache.Load(t); ok { - return v.(*arshaler) - } - - fncs := makeDefaultArshaler(t) - fncs = makeMethodArshaler(fncs, t) - fncs = makeTimeArshaler(fncs, t) - - // Use the last stored so that duplicate arshalers can be garbage collected. - v, _ := lookupArshalerCache.LoadOrStore(t, fncs) - return v.(*arshaler) -} - -var stringsPools = &sync.Pool{New: func() any { return new(stringSlice) }} - -type stringSlice []string - -// getStrings returns a non-nil pointer to a slice with length n. -func getStrings(n int) *stringSlice { - s := stringsPools.Get().(*stringSlice) - if cap(*s) < n { - *s = make([]string, n) - } - *s = (*s)[:n] - return s -} - -func putStrings(s *stringSlice) { - if cap(*s) > 1<<10 { - *s = nil // avoid pinning arbitrarily large amounts of memory - } - stringsPools.Put(s) -} - -func (ss *stringSlice) Sort() { - slices.SortFunc(*ss, func(x, y string) int { return strings.Compare(x, y) }) -} diff --git a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/arshal_any.go b/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/arshal_any.go deleted file mode 100644 index fd034c1a1..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/arshal_any.go +++ /dev/null @@ -1,285 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package json - -import ( - "cmp" - "math" - "reflect" - "strconv" - - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonflags" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonopts" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonwire" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext" -) - -// This file contains an optimized marshal and unmarshal implementation -// for the any type. This type is often used when the Go program has -// no knowledge of the JSON schema. This is a common enough occurrence -// to justify the complexity of adding logic for this. - -// marshalValueAny marshals a Go any as a JSON value. -// This assumes that there are no special formatting directives -// for any possible nested value. -func marshalValueAny(enc *jsontext.Encoder, val any, mo *jsonopts.Struct) error { - switch val := val.(type) { - case nil: - return enc.WriteToken(jsontext.Null) - case bool: - return enc.WriteToken(jsontext.Bool(val)) - case string: - return enc.WriteToken(jsontext.String(val)) - case float64: - if math.IsNaN(val) || math.IsInf(val, 0) { - break // use default logic below - } - return enc.WriteToken(jsontext.Float(val)) - case map[string]any: - return marshalObjectAny(enc, val, mo) - case []any: - return marshalArrayAny(enc, val, mo) - } - - v := newAddressableValue(reflect.TypeOf(val)) - v.Set(reflect.ValueOf(val)) - marshal := lookupArshaler(v.Type()).marshal - if mo.Marshalers != nil { - marshal, _ = mo.Marshalers.(*Marshalers).lookup(marshal, v.Type()) - } - return marshal(enc, v, mo) -} - -// unmarshalValueAny unmarshals a JSON value as a Go any. -// This assumes that there are no special formatting directives -// for any possible nested value. -// Duplicate names must be rejected since this does not implement merging. -func unmarshalValueAny(dec *jsontext.Decoder, uo *jsonopts.Struct) (any, error) { - switch k := dec.PeekKind(); k { - case '{': - return unmarshalObjectAny(dec, uo) - case '[': - return unmarshalArrayAny(dec, uo) - default: - xd := export.Decoder(dec) - var flags jsonwire.ValueFlags - val, err := xd.ReadValue(&flags) - if err != nil { - return nil, err - } - switch val.Kind() { - case 'n': - return nil, nil - case 'f': - return false, nil - case 't': - return true, nil - case '"': - val = jsonwire.UnquoteMayCopy(val, flags.IsVerbatim()) - if xd.StringCache == nil { - xd.StringCache = new(stringCache) - } - return makeString(xd.StringCache, val), nil - case '0': - if uo.Flags.Get(jsonflags.UnmarshalAnyWithRawNumber) { - return internal.RawNumberOf(val), nil - } - fv, ok := jsonwire.ParseFloat(val, 64) - if !ok { - return fv, newUnmarshalErrorAfterWithValue(dec, float64Type, strconv.ErrRange) - } - return fv, nil - default: - panic("BUG: invalid kind: " + k.String()) - } - } -} - -// marshalObjectAny marshals a Go map[string]any as a JSON object -// (or as a JSON null if nil and [jsonflags.FormatNilMapAsNull]). -func marshalObjectAny(enc *jsontext.Encoder, obj map[string]any, mo *jsonopts.Struct) error { - // Check for cycles. - xe := export.Encoder(enc) - if xe.Tokens.Depth() > startDetectingCyclesAfter { - v := reflect.ValueOf(obj) - if err := visitPointer(&xe.SeenPointers, v); err != nil { - return newMarshalErrorBefore(enc, mapStringAnyType, err) - } - defer leavePointer(&xe.SeenPointers, v) - } - - // Handle empty maps. - if len(obj) == 0 { - if mo.Flags.Get(jsonflags.FormatNilMapAsNull) && obj == nil { - return enc.WriteToken(jsontext.Null) - } - // Optimize for marshaling an empty map without any preceding whitespace. - if !mo.Flags.Get(jsonflags.AnyWhitespace) && !xe.Tokens.Last.NeedObjectName() { - xe.Buf = append(xe.Tokens.MayAppendDelim(xe.Buf, '{'), "{}"...) - xe.Tokens.Last.Increment() - if xe.NeedFlush() { - return xe.Flush() - } - return nil - } - } - - if err := enc.WriteToken(jsontext.BeginObject); err != nil { - return err - } - // A Go map guarantees that each entry has a unique key - // The only possibility of duplicates is due to invalid UTF-8. - if !mo.Flags.Get(jsonflags.AllowInvalidUTF8) { - xe.Tokens.Last.DisableNamespace() - } - if !mo.Flags.Get(jsonflags.Deterministic) || len(obj) <= 1 { - for name, val := range obj { - if err := enc.WriteToken(jsontext.String(name)); err != nil { - return err - } - if err := marshalValueAny(enc, val, mo); err != nil { - return err - } - } - } else { - names := getStrings(len(obj)) - var i int - for name := range obj { - (*names)[i] = name - i++ - } - names.Sort() - for _, name := range *names { - if err := enc.WriteToken(jsontext.String(name)); err != nil { - return err - } - if err := marshalValueAny(enc, obj[name], mo); err != nil { - return err - } - } - putStrings(names) - } - if err := enc.WriteToken(jsontext.EndObject); err != nil { - return err - } - return nil -} - -// unmarshalObjectAny unmarshals a JSON object as a Go map[string]any. -// It panics if not decoding a JSON object. -func unmarshalObjectAny(dec *jsontext.Decoder, uo *jsonopts.Struct) (map[string]any, error) { - switch tok, err := dec.ReadToken(); { - case err != nil: - return nil, err - case tok.Kind() != '{': - panic("BUG: invalid kind: " + tok.Kind().String()) - } - obj := make(map[string]any) - // A Go map guarantees that each entry has a unique key - // The only possibility of duplicates is due to invalid UTF-8. - if !uo.Flags.Get(jsonflags.AllowInvalidUTF8) { - export.Decoder(dec).Tokens.Last.DisableNamespace() - } - var errUnmarshal error - for dec.PeekKind() != '}' { - tok, err := dec.ReadToken() - if err != nil { - return obj, err - } - name := tok.String() - - // Manually check for duplicate names. - if _, ok := obj[name]; ok { - // TODO: Unread the object name. - name := export.Decoder(dec).PreviousTokenOrValue() - err := newDuplicateNameError(dec.StackPointer(), nil, dec.InputOffset()-len64(name)) - return obj, err - } - - val, err := unmarshalValueAny(dec, uo) - obj[name] = val - if err != nil { - if isFatalError(err, uo.Flags) { - return obj, err - } - errUnmarshal = cmp.Or(err, errUnmarshal) - } - } - if _, err := dec.ReadToken(); err != nil { - return obj, err - } - return obj, errUnmarshal -} - -// marshalArrayAny marshals a Go []any as a JSON array -// (or as a JSON null if nil and [jsonflags.FormatNilSliceAsNull]). -func marshalArrayAny(enc *jsontext.Encoder, arr []any, mo *jsonopts.Struct) error { - // Check for cycles. - xe := export.Encoder(enc) - if xe.Tokens.Depth() > startDetectingCyclesAfter { - v := reflect.ValueOf(arr) - if err := visitPointer(&xe.SeenPointers, v); err != nil { - return newMarshalErrorBefore(enc, sliceAnyType, err) - } - defer leavePointer(&xe.SeenPointers, v) - } - - // Handle empty slices. - if len(arr) == 0 { - if mo.Flags.Get(jsonflags.FormatNilSliceAsNull) && arr == nil { - return enc.WriteToken(jsontext.Null) - } - // Optimize for marshaling an empty slice without any preceding whitespace. - if !mo.Flags.Get(jsonflags.AnyWhitespace) && !xe.Tokens.Last.NeedObjectName() { - xe.Buf = append(xe.Tokens.MayAppendDelim(xe.Buf, '['), "[]"...) - xe.Tokens.Last.Increment() - if xe.NeedFlush() { - return xe.Flush() - } - return nil - } - } - - if err := enc.WriteToken(jsontext.BeginArray); err != nil { - return err - } - for _, val := range arr { - if err := marshalValueAny(enc, val, mo); err != nil { - return err - } - } - if err := enc.WriteToken(jsontext.EndArray); err != nil { - return err - } - return nil -} - -// unmarshalArrayAny unmarshals a JSON array as a Go []any. -// It panics if not decoding a JSON array. -func unmarshalArrayAny(dec *jsontext.Decoder, uo *jsonopts.Struct) ([]any, error) { - switch tok, err := dec.ReadToken(); { - case err != nil: - return nil, err - case tok.Kind() != '[': - panic("BUG: invalid kind: " + tok.Kind().String()) - } - arr := []any{} - var errUnmarshal error - for dec.PeekKind() != ']' { - val, err := unmarshalValueAny(dec, uo) - arr = append(arr, val) - if err != nil { - if isFatalError(err, uo.Flags) { - return arr, err - } - errUnmarshal = cmp.Or(errUnmarshal, err) - } - } - if _, err := dec.ReadToken(); err != nil { - return arr, err - } - return arr, errUnmarshal -} diff --git a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/arshal_default.go b/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/arshal_default.go deleted file mode 100644 index 3f21c8d35..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/arshal_default.go +++ /dev/null @@ -1,1908 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package json - -import ( - "bytes" - "cmp" - "encoding" - "encoding/base32" - "encoding/base64" - "encoding/hex" - "errors" - "fmt" - "math" - "reflect" - "slices" - "strconv" - "strings" - "sync" - - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonflags" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonopts" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonwire" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext" -) - -// optimizeCommon specifies whether to use optimizations targeted for certain -// common patterns, rather than using the slower, but more general logic. -// All tests should pass regardless of whether this is true or not. -const optimizeCommon = true - -var ( - // Most natural Go type that correspond with each JSON type. - anyType = reflect.TypeFor[any]() // JSON value - boolType = reflect.TypeFor[bool]() // JSON bool - stringType = reflect.TypeFor[string]() // JSON string - float64Type = reflect.TypeFor[float64]() // JSON number - mapStringAnyType = reflect.TypeFor[map[string]any]() // JSON object - sliceAnyType = reflect.TypeFor[[]any]() // JSON array - - bytesType = reflect.TypeFor[[]byte]() - emptyStructType = reflect.TypeFor[struct{}]() -) - -const startDetectingCyclesAfter = 1000 - -type seenPointers = map[any]struct{} - -type typedPointer struct { - typ reflect.Type - ptr any // always stores unsafe.Pointer, but avoids depending on unsafe - len int // remember slice length to avoid false positives -} - -// visitPointer visits pointer p of type t, reporting an error if seen before. -// If successfully visited, then the caller must eventually call leave. -func visitPointer(m *seenPointers, v reflect.Value) error { - p := typedPointer{v.Type(), v.UnsafePointer(), sliceLen(v)} - if _, ok := (*m)[p]; ok { - return internal.ErrCycle - } - if *m == nil { - *m = make(seenPointers) - } - (*m)[p] = struct{}{} - return nil -} -func leavePointer(m *seenPointers, v reflect.Value) { - p := typedPointer{v.Type(), v.UnsafePointer(), sliceLen(v)} - delete(*m, p) -} - -func sliceLen(v reflect.Value) int { - if v.Kind() == reflect.Slice { - return v.Len() - } - return 0 -} - -func len64[Bytes ~[]byte | ~string](in Bytes) int64 { - return int64(len(in)) -} - -func makeDefaultArshaler(t reflect.Type) *arshaler { - switch t.Kind() { - case reflect.Bool: - return makeBoolArshaler(t) - case reflect.String: - return makeStringArshaler(t) - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return makeIntArshaler(t) - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - return makeUintArshaler(t) - case reflect.Float32, reflect.Float64: - return makeFloatArshaler(t) - case reflect.Map: - return makeMapArshaler(t) - case reflect.Struct: - return makeStructArshaler(t) - case reflect.Slice: - fncs := makeSliceArshaler(t) - if t.Elem().Kind() == reflect.Uint8 { - return makeBytesArshaler(t, fncs) - } - return fncs - case reflect.Array: - fncs := makeArrayArshaler(t) - if t.Elem().Kind() == reflect.Uint8 { - return makeBytesArshaler(t, fncs) - } - return fncs - case reflect.Pointer: - return makePointerArshaler(t) - case reflect.Interface: - return makeInterfaceArshaler(t) - default: - return makeInvalidArshaler(t) - } -} - -func makeBoolArshaler(t reflect.Type) *arshaler { - var fncs arshaler - fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error { - xe := export.Encoder(enc) - if mo.Format != "" && mo.FormatDepth == xe.Tokens.Depth() { - return newInvalidFormatError(enc, t) - } - - // Optimize for marshaling without preceding whitespace. - if optimizeCommon && !mo.Flags.Get(jsonflags.AnyWhitespace|jsonflags.StringifyBoolsAndStrings) && !xe.Tokens.Last.NeedObjectName() { - xe.Buf = strconv.AppendBool(xe.Tokens.MayAppendDelim(xe.Buf, 't'), va.Bool()) - xe.Tokens.Last.Increment() - if xe.NeedFlush() { - return xe.Flush() - } - return nil - } - - if mo.Flags.Get(jsonflags.StringifyBoolsAndStrings) { - if va.Bool() { - return enc.WriteToken(jsontext.String("true")) - } else { - return enc.WriteToken(jsontext.String("false")) - } - } - return enc.WriteToken(jsontext.Bool(va.Bool())) - } - fncs.unmarshal = func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error { - xd := export.Decoder(dec) - if uo.Format != "" && uo.FormatDepth == xd.Tokens.Depth() { - return newInvalidFormatError(dec, t) - } - tok, err := dec.ReadToken() - if err != nil { - return err - } - k := tok.Kind() - switch k { - case 'n': - if !uo.Flags.Get(jsonflags.MergeWithLegacySemantics) { - va.SetBool(false) - } - return nil - case 't', 'f': - if !uo.Flags.Get(jsonflags.StringifyBoolsAndStrings) { - va.SetBool(tok.Bool()) - return nil - } - case '"': - if uo.Flags.Get(jsonflags.StringifyBoolsAndStrings) { - switch tok.String() { - case "true": - va.SetBool(true) - case "false": - va.SetBool(false) - default: - if uo.Flags.Get(jsonflags.StringifyWithLegacySemantics) && tok.String() == "null" { - if !uo.Flags.Get(jsonflags.MergeWithLegacySemantics) { - va.SetBool(false) - } - return nil - } - return newUnmarshalErrorAfterWithValue(dec, t, strconv.ErrSyntax) - } - return nil - } - } - return newUnmarshalErrorAfterWithSkipping(dec, t, nil) - } - return &fncs -} - -func makeStringArshaler(t reflect.Type) *arshaler { - var fncs arshaler - fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error { - xe := export.Encoder(enc) - if mo.Format != "" && mo.FormatDepth == xe.Tokens.Depth() { - return newInvalidFormatError(enc, t) - } - - // Optimize for marshaling without preceding whitespace. - s := va.String() - if optimizeCommon && !mo.Flags.Get(jsonflags.AnyWhitespace|jsonflags.StringifyBoolsAndStrings) && !xe.Tokens.Last.NeedObjectName() { - b := xe.Buf - b = xe.Tokens.MayAppendDelim(b, '"') - b, err := jsonwire.AppendQuote(b, s, &mo.Flags) - if err == nil { - xe.Buf = b - xe.Tokens.Last.Increment() - if xe.NeedFlush() { - return xe.Flush() - } - return nil - } - // Otherwise, the string contains invalid UTF-8, - // so let the logic below construct the proper error. - } - - if mo.Flags.Get(jsonflags.StringifyBoolsAndStrings) { - b, err := jsonwire.AppendQuote(nil, s, &mo.Flags) - if err != nil { - return newMarshalErrorBefore(enc, t, &jsontext.SyntacticError{Err: err}) - } - q, err := jsontext.AppendQuote(nil, b) - if err != nil { - panic("BUG: second AppendQuote should never fail: " + err.Error()) - } - return enc.WriteValue(q) - } - return enc.WriteToken(jsontext.String(s)) - } - fncs.unmarshal = func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error { - xd := export.Decoder(dec) - if uo.Format != "" && uo.FormatDepth == xd.Tokens.Depth() { - return newInvalidFormatError(dec, t) - } - var flags jsonwire.ValueFlags - val, err := xd.ReadValue(&flags) - if err != nil { - return err - } - k := val.Kind() - switch k { - case 'n': - if !uo.Flags.Get(jsonflags.MergeWithLegacySemantics) { - va.SetString("") - } - return nil - case '"': - val = jsonwire.UnquoteMayCopy(val, flags.IsVerbatim()) - if uo.Flags.Get(jsonflags.StringifyBoolsAndStrings) { - val, err = jsontext.AppendUnquote(nil, val) - if err != nil { - return newUnmarshalErrorAfter(dec, t, err) - } - if uo.Flags.Get(jsonflags.StringifyWithLegacySemantics) && string(val) == "null" { - if !uo.Flags.Get(jsonflags.MergeWithLegacySemantics) { - va.SetString("") - } - return nil - } - } - if xd.StringCache == nil { - xd.StringCache = new(stringCache) - } - str := makeString(xd.StringCache, val) - va.SetString(str) - return nil - } - return newUnmarshalErrorAfter(dec, t, nil) - } - return &fncs -} - -var ( - appendEncodeBase16 = hex.AppendEncode - appendEncodeBase32 = base32.StdEncoding.AppendEncode - appendEncodeBase32Hex = base32.HexEncoding.AppendEncode - appendEncodeBase64 = base64.StdEncoding.AppendEncode - appendEncodeBase64URL = base64.URLEncoding.AppendEncode - encodedLenBase16 = hex.EncodedLen - encodedLenBase32 = base32.StdEncoding.EncodedLen - encodedLenBase32Hex = base32.HexEncoding.EncodedLen - encodedLenBase64 = base64.StdEncoding.EncodedLen - encodedLenBase64URL = base64.URLEncoding.EncodedLen - appendDecodeBase16 = hex.AppendDecode - appendDecodeBase32 = base32.StdEncoding.AppendDecode - appendDecodeBase32Hex = base32.HexEncoding.AppendDecode - appendDecodeBase64 = base64.StdEncoding.AppendDecode - appendDecodeBase64URL = base64.URLEncoding.AppendDecode -) - -func makeBytesArshaler(t reflect.Type, fncs *arshaler) *arshaler { - // NOTE: This handles both []~byte and [N]~byte. - // The v2 default is to treat a []namedByte as equivalent to []T - // since being able to convert []namedByte to []byte relies on - // dubious Go reflection behavior (see https://go.dev/issue/24746). - // For v1 emulation, we use jsonflags.FormatBytesWithLegacySemantics - // to forcibly treat []namedByte as a []byte. - marshalArray := fncs.marshal - isNamedByte := t.Elem().PkgPath() != "" - hasMarshaler := implementsAny(t.Elem(), allMarshalerTypes...) - fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error { - if !mo.Flags.Get(jsonflags.FormatBytesWithLegacySemantics) && isNamedByte { - return marshalArray(enc, va, mo) // treat as []T or [N]T - } - xe := export.Encoder(enc) - appendEncode := appendEncodeBase64 - if mo.Format != "" && mo.FormatDepth == xe.Tokens.Depth() { - switch mo.Format { - case "base64": - appendEncode = appendEncodeBase64 - case "base64url": - appendEncode = appendEncodeBase64URL - case "base32": - appendEncode = appendEncodeBase32 - case "base32hex": - appendEncode = appendEncodeBase32Hex - case "base16", "hex": - appendEncode = appendEncodeBase16 - case "array": - mo.Format = "" - return marshalArray(enc, va, mo) - default: - return newInvalidFormatError(enc, t) - } - } else if mo.Flags.Get(jsonflags.FormatByteArrayAsArray) && va.Kind() == reflect.Array { - return marshalArray(enc, va, mo) - } else if mo.Flags.Get(jsonflags.FormatBytesWithLegacySemantics) && hasMarshaler { - return marshalArray(enc, va, mo) - } - if mo.Flags.Get(jsonflags.FormatNilSliceAsNull) && va.Kind() == reflect.Slice && va.IsNil() { - // TODO: Provide a "emitempty" format override? - return enc.WriteToken(jsontext.Null) - } - return xe.AppendRaw('"', true, func(b []byte) ([]byte, error) { - return appendEncode(b, va.Bytes()), nil - }) - } - unmarshalArray := fncs.unmarshal - fncs.unmarshal = func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error { - if !uo.Flags.Get(jsonflags.FormatBytesWithLegacySemantics) && isNamedByte { - return unmarshalArray(dec, va, uo) // treat as []T or [N]T - } - xd := export.Decoder(dec) - appendDecode, encodedLen := appendDecodeBase64, encodedLenBase64 - if uo.Format != "" && uo.FormatDepth == xd.Tokens.Depth() { - switch uo.Format { - case "base64": - appendDecode, encodedLen = appendDecodeBase64, encodedLenBase64 - case "base64url": - appendDecode, encodedLen = appendDecodeBase64URL, encodedLenBase64URL - case "base32": - appendDecode, encodedLen = appendDecodeBase32, encodedLenBase32 - case "base32hex": - appendDecode, encodedLen = appendDecodeBase32Hex, encodedLenBase32Hex - case "base16", "hex": - appendDecode, encodedLen = appendDecodeBase16, encodedLenBase16 - case "array": - uo.Format = "" - return unmarshalArray(dec, va, uo) - default: - return newInvalidFormatError(dec, t) - } - } else if uo.Flags.Get(jsonflags.FormatByteArrayAsArray) && va.Kind() == reflect.Array { - return unmarshalArray(dec, va, uo) - } else if uo.Flags.Get(jsonflags.FormatBytesWithLegacySemantics) && dec.PeekKind() == '[' { - return unmarshalArray(dec, va, uo) - } - var flags jsonwire.ValueFlags - val, err := xd.ReadValue(&flags) - if err != nil { - return err - } - k := val.Kind() - switch k { - case 'n': - if !uo.Flags.Get(jsonflags.MergeWithLegacySemantics) || va.Kind() != reflect.Array { - va.SetZero() - } - return nil - case '"': - // NOTE: The v2 default is to strictly comply with RFC 4648. - // Section 3.2 specifies that padding is required. - // Section 3.3 specifies that non-alphabet characters - // (e.g., '\r' or '\n') must be rejected. - // Section 3.5 specifies that unnecessary non-zero bits in - // the last quantum may be rejected. Since this is optional, - // we do not reject such inputs. - val = jsonwire.UnquoteMayCopy(val, flags.IsVerbatim()) - b, err := appendDecode(va.Bytes()[:0], val) - if err != nil { - return newUnmarshalErrorAfter(dec, t, err) - } - if len(val) != encodedLen(len(b)) && !uo.Flags.Get(jsonflags.ParseBytesWithLooseRFC4648) { - // TODO(https://go.dev/issue/53845): RFC 4648, section 3.3, - // specifies that non-alphabet characters must be rejected. - // Unfortunately, the "base32" and "base64" packages allow - // '\r' and '\n' characters by default. - i := bytes.IndexAny(val, "\r\n") - err := fmt.Errorf("illegal character %s at offset %d", jsonwire.QuoteRune(val[i:]), i) - return newUnmarshalErrorAfter(dec, t, err) - } - - if va.Kind() == reflect.Array { - dst := va.Bytes() - clear(dst[copy(dst, b):]) // noop if len(b) <= len(dst) - if len(b) != len(dst) && !uo.Flags.Get(jsonflags.UnmarshalArrayFromAnyLength) { - err := fmt.Errorf("decoded length of %d mismatches array length of %d", len(b), len(dst)) - return newUnmarshalErrorAfter(dec, t, err) - } - } else { - if b == nil { - b = []byte{} - } - va.SetBytes(b) - } - return nil - } - return newUnmarshalErrorAfter(dec, t, nil) - } - return fncs -} - -func makeIntArshaler(t reflect.Type) *arshaler { - var fncs arshaler - bits := t.Bits() - fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error { - xe := export.Encoder(enc) - if mo.Format != "" && mo.FormatDepth == xe.Tokens.Depth() { - return newInvalidFormatError(enc, t) - } - - // Optimize for marshaling without preceding whitespace or string escaping. - if optimizeCommon && !mo.Flags.Get(jsonflags.AnyWhitespace|jsonflags.StringifyNumbers) && !xe.Tokens.Last.NeedObjectName() { - xe.Buf = strconv.AppendInt(xe.Tokens.MayAppendDelim(xe.Buf, '0'), va.Int(), 10) - xe.Tokens.Last.Increment() - if xe.NeedFlush() { - return xe.Flush() - } - return nil - } - - k := stringOrNumberKind(xe.Tokens.Last.NeedObjectName() || mo.Flags.Get(jsonflags.StringifyNumbers)) - return xe.AppendRaw(k, true, func(b []byte) ([]byte, error) { - return strconv.AppendInt(b, va.Int(), 10), nil - }) - } - fncs.unmarshal = func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error { - xd := export.Decoder(dec) - if uo.Format != "" && uo.FormatDepth == xd.Tokens.Depth() { - return newInvalidFormatError(dec, t) - } - stringify := xd.Tokens.Last.NeedObjectName() || uo.Flags.Get(jsonflags.StringifyNumbers) - var flags jsonwire.ValueFlags - val, err := xd.ReadValue(&flags) - if err != nil { - return err - } - k := val.Kind() - switch k { - case 'n': - if !uo.Flags.Get(jsonflags.MergeWithLegacySemantics) { - va.SetInt(0) - } - return nil - case '"': - if !stringify { - break - } - val = jsonwire.UnquoteMayCopy(val, flags.IsVerbatim()) - if uo.Flags.Get(jsonflags.StringifyWithLegacySemantics) && string(val) == "null" { - if !uo.Flags.Get(jsonflags.MergeWithLegacySemantics) { - va.SetInt(0) - } - return nil - } - fallthrough - case '0': - if stringify && k == '0' { - break - } - var negOffset int - neg := len(val) > 0 && val[0] == '-' - if neg { - negOffset = 1 - } - n, ok := jsonwire.ParseUint(val[negOffset:]) - maxInt := uint64(1) << (bits - 1) - overflow := (neg && n > maxInt) || (!neg && n > maxInt-1) - if !ok { - if n != math.MaxUint64 { - return newUnmarshalErrorAfterWithValue(dec, t, strconv.ErrSyntax) - } - overflow = true - } - if overflow { - return newUnmarshalErrorAfterWithValue(dec, t, strconv.ErrRange) - } - if neg { - va.SetInt(int64(-n)) - } else { - va.SetInt(int64(+n)) - } - return nil - } - return newUnmarshalErrorAfter(dec, t, nil) - } - return &fncs -} - -func makeUintArshaler(t reflect.Type) *arshaler { - var fncs arshaler - bits := t.Bits() - fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error { - xe := export.Encoder(enc) - if mo.Format != "" && mo.FormatDepth == xe.Tokens.Depth() { - return newInvalidFormatError(enc, t) - } - - // Optimize for marshaling without preceding whitespace or string escaping. - if optimizeCommon && !mo.Flags.Get(jsonflags.AnyWhitespace|jsonflags.StringifyNumbers) && !xe.Tokens.Last.NeedObjectName() { - xe.Buf = strconv.AppendUint(xe.Tokens.MayAppendDelim(xe.Buf, '0'), va.Uint(), 10) - xe.Tokens.Last.Increment() - if xe.NeedFlush() { - return xe.Flush() - } - return nil - } - - k := stringOrNumberKind(xe.Tokens.Last.NeedObjectName() || mo.Flags.Get(jsonflags.StringifyNumbers)) - return xe.AppendRaw(k, true, func(b []byte) ([]byte, error) { - return strconv.AppendUint(b, va.Uint(), 10), nil - }) - } - fncs.unmarshal = func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error { - xd := export.Decoder(dec) - if uo.Format != "" && uo.FormatDepth == xd.Tokens.Depth() { - return newInvalidFormatError(dec, t) - } - stringify := xd.Tokens.Last.NeedObjectName() || uo.Flags.Get(jsonflags.StringifyNumbers) - var flags jsonwire.ValueFlags - val, err := xd.ReadValue(&flags) - if err != nil { - return err - } - k := val.Kind() - switch k { - case 'n': - if !uo.Flags.Get(jsonflags.MergeWithLegacySemantics) { - va.SetUint(0) - } - return nil - case '"': - if !stringify { - break - } - val = jsonwire.UnquoteMayCopy(val, flags.IsVerbatim()) - if uo.Flags.Get(jsonflags.StringifyWithLegacySemantics) && string(val) == "null" { - if !uo.Flags.Get(jsonflags.MergeWithLegacySemantics) { - va.SetUint(0) - } - return nil - } - fallthrough - case '0': - if stringify && k == '0' { - break - } - n, ok := jsonwire.ParseUint(val) - maxUint := uint64(1) << bits - overflow := n > maxUint-1 - if !ok { - if n != math.MaxUint64 { - return newUnmarshalErrorAfterWithValue(dec, t, strconv.ErrSyntax) - } - overflow = true - } - if overflow { - return newUnmarshalErrorAfterWithValue(dec, t, strconv.ErrRange) - } - va.SetUint(n) - return nil - } - return newUnmarshalErrorAfter(dec, t, nil) - } - return &fncs -} - -func makeFloatArshaler(t reflect.Type) *arshaler { - var fncs arshaler - bits := t.Bits() - fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error { - xe := export.Encoder(enc) - var allowNonFinite bool - if mo.Format != "" && mo.FormatDepth == xe.Tokens.Depth() { - if mo.Format == "nonfinite" { - allowNonFinite = true - } else { - return newInvalidFormatError(enc, t) - } - } - - fv := va.Float() - if math.IsNaN(fv) || math.IsInf(fv, 0) { - if !allowNonFinite { - err := fmt.Errorf("unsupported value: %v", fv) - return newMarshalErrorBefore(enc, t, err) - } - return enc.WriteToken(jsontext.Float(fv)) - } - - // Optimize for marshaling without preceding whitespace or string escaping. - if optimizeCommon && !mo.Flags.Get(jsonflags.AnyWhitespace|jsonflags.StringifyNumbers) && !xe.Tokens.Last.NeedObjectName() { - xe.Buf = jsonwire.AppendFloat(xe.Tokens.MayAppendDelim(xe.Buf, '0'), fv, bits) - xe.Tokens.Last.Increment() - if xe.NeedFlush() { - return xe.Flush() - } - return nil - } - - k := stringOrNumberKind(xe.Tokens.Last.NeedObjectName() || mo.Flags.Get(jsonflags.StringifyNumbers)) - return xe.AppendRaw(k, true, func(b []byte) ([]byte, error) { - return jsonwire.AppendFloat(b, va.Float(), bits), nil - }) - } - fncs.unmarshal = func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error { - xd := export.Decoder(dec) - var allowNonFinite bool - if uo.Format != "" && uo.FormatDepth == xd.Tokens.Depth() { - if uo.Format == "nonfinite" { - allowNonFinite = true - } else { - return newInvalidFormatError(dec, t) - } - } - stringify := xd.Tokens.Last.NeedObjectName() || uo.Flags.Get(jsonflags.StringifyNumbers) - var flags jsonwire.ValueFlags - val, err := xd.ReadValue(&flags) - if err != nil { - return err - } - k := val.Kind() - switch k { - case 'n': - if !uo.Flags.Get(jsonflags.MergeWithLegacySemantics) { - va.SetFloat(0) - } - return nil - case '"': - val = jsonwire.UnquoteMayCopy(val, flags.IsVerbatim()) - if allowNonFinite { - switch string(val) { - case "NaN": - va.SetFloat(math.NaN()) - return nil - case "Infinity": - va.SetFloat(math.Inf(+1)) - return nil - case "-Infinity": - va.SetFloat(math.Inf(-1)) - return nil - } - } - if !stringify { - break - } - if uo.Flags.Get(jsonflags.StringifyWithLegacySemantics) && string(val) == "null" { - if !uo.Flags.Get(jsonflags.MergeWithLegacySemantics) { - va.SetFloat(0) - } - return nil - } - if n, err := jsonwire.ConsumeNumber(val); n != len(val) || err != nil { - return newUnmarshalErrorAfterWithValue(dec, t, strconv.ErrSyntax) - } - fallthrough - case '0': - if stringify && k == '0' { - break - } - fv, ok := jsonwire.ParseFloat(val, bits) - va.SetFloat(fv) - if !ok { - return newUnmarshalErrorAfterWithValue(dec, t, strconv.ErrRange) - } - return nil - } - return newUnmarshalErrorAfter(dec, t, nil) - } - return &fncs -} - -func makeMapArshaler(t reflect.Type) *arshaler { - // NOTE: The logic below disables namespaces for tracking duplicate names - // when handling map keys with a unique representation. - - // NOTE: Values retrieved from a map are not addressable, - // so we shallow copy the values to make them addressable and - // store them back into the map afterwards. - - var fncs arshaler - var ( - once sync.Once - keyFncs *arshaler - valFncs *arshaler - ) - init := func() { - keyFncs = lookupArshaler(t.Key()) - valFncs = lookupArshaler(t.Elem()) - } - nillableLegacyKey := t.Key().Kind() == reflect.Pointer && - implementsAny(t.Key(), textMarshalerType, textAppenderType) - fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error { - // Check for cycles. - xe := export.Encoder(enc) - if xe.Tokens.Depth() > startDetectingCyclesAfter { - if err := visitPointer(&xe.SeenPointers, va.Value); err != nil { - return newMarshalErrorBefore(enc, t, err) - } - defer leavePointer(&xe.SeenPointers, va.Value) - } - - emitNull := mo.Flags.Get(jsonflags.FormatNilMapAsNull) - if mo.Format != "" && mo.FormatDepth == xe.Tokens.Depth() { - switch mo.Format { - case "emitnull": - emitNull = true - mo.Format = "" - case "emitempty": - emitNull = false - mo.Format = "" - default: - return newInvalidFormatError(enc, t) - } - } - - // Handle empty maps. - n := va.Len() - if n == 0 { - if emitNull && va.IsNil() { - return enc.WriteToken(jsontext.Null) - } - // Optimize for marshaling an empty map without any preceding whitespace. - if optimizeCommon && !mo.Flags.Get(jsonflags.AnyWhitespace) && !xe.Tokens.Last.NeedObjectName() { - xe.Buf = append(xe.Tokens.MayAppendDelim(xe.Buf, '{'), "{}"...) - xe.Tokens.Last.Increment() - if xe.NeedFlush() { - return xe.Flush() - } - return nil - } - } - - once.Do(init) - if err := enc.WriteToken(jsontext.BeginObject); err != nil { - return err - } - if n > 0 { - nonDefaultKey := keyFncs.nonDefault - marshalKey := keyFncs.marshal - marshalVal := valFncs.marshal - if mo.Marshalers != nil { - var ok bool - marshalKey, ok = mo.Marshalers.(*Marshalers).lookup(marshalKey, t.Key()) - marshalVal, _ = mo.Marshalers.(*Marshalers).lookup(marshalVal, t.Elem()) - nonDefaultKey = nonDefaultKey || ok - } - k := newAddressableValue(t.Key()) - v := newAddressableValue(t.Elem()) - - // A Go map guarantees that each entry has a unique key. - // As such, disable the expensive duplicate name check if we know - // that every Go key will serialize as a unique JSON string. - if !nonDefaultKey && mapKeyWithUniqueRepresentation(k.Kind(), mo.Flags.Get(jsonflags.AllowInvalidUTF8)) { - xe.Tokens.Last.DisableNamespace() - } - - switch { - case !mo.Flags.Get(jsonflags.Deterministic) || n <= 1: - for iter := va.Value.MapRange(); iter.Next(); { - k.SetIterKey(iter) - err := marshalKey(enc, k, mo) - if err != nil { - if mo.Flags.Get(jsonflags.CallMethodsWithLegacySemantics) && - errors.Is(err, jsontext.ErrNonStringName) && nillableLegacyKey && k.IsNil() { - err = enc.WriteToken(jsontext.String("")) - } - if err != nil { - if serr, ok := err.(*jsontext.SyntacticError); ok && serr.Err == jsontext.ErrNonStringName { - err = newMarshalErrorBefore(enc, k.Type(), err) - } - return err - } - } - v.SetIterValue(iter) - if err := marshalVal(enc, v, mo); err != nil { - return err - } - } - case !nonDefaultKey && t.Key().Kind() == reflect.String: - names := getStrings(n) - for i, iter := 0, va.Value.MapRange(); i < n && iter.Next(); i++ { - k.SetIterKey(iter) - (*names)[i] = k.String() - } - names.Sort() - for _, name := range *names { - if err := enc.WriteToken(jsontext.String(name)); err != nil { - return err - } - // TODO(https://go.dev/issue/57061): Use v.SetMapIndexOf. - k.SetString(name) - v.Set(va.MapIndex(k.Value)) - if err := marshalVal(enc, v, mo); err != nil { - return err - } - } - putStrings(names) - default: - type member struct { - name string // unquoted name - key addressableValue - val addressableValue - } - members := make([]member, n) - keys := reflect.MakeSlice(reflect.SliceOf(t.Key()), n, n) - vals := reflect.MakeSlice(reflect.SliceOf(t.Elem()), n, n) - for i, iter := 0, va.Value.MapRange(); i < n && iter.Next(); i++ { - // Marshal the member name. - k := addressableValue{keys.Index(i), true} // indexed slice element is always addressable - k.SetIterKey(iter) - v := addressableValue{vals.Index(i), true} // indexed slice element is always addressable - v.SetIterValue(iter) - err := marshalKey(enc, k, mo) - if err != nil { - if mo.Flags.Get(jsonflags.CallMethodsWithLegacySemantics) && - errors.Is(err, jsontext.ErrNonStringName) && nillableLegacyKey && k.IsNil() { - err = enc.WriteToken(jsontext.String("")) - } - if err != nil { - if serr, ok := err.(*jsontext.SyntacticError); ok && serr.Err == jsontext.ErrNonStringName { - err = newMarshalErrorBefore(enc, k.Type(), err) - } - return err - } - } - name := xe.UnwriteOnlyObjectMemberName() - members[i] = member{name, k, v} - } - // TODO: If AllowDuplicateNames is enabled, then sort according - // to reflect.Value as well if the names are equal. - // See internal/fmtsort. - slices.SortFunc(members, func(x, y member) int { - return strings.Compare(x.name, y.name) - }) - for _, member := range members { - if err := enc.WriteToken(jsontext.String(member.name)); err != nil { - return err - } - if err := marshalVal(enc, member.val, mo); err != nil { - return err - } - } - } - } - if err := enc.WriteToken(jsontext.EndObject); err != nil { - return err - } - return nil - } - fncs.unmarshal = func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error { - xd := export.Decoder(dec) - if uo.Format != "" && uo.FormatDepth == xd.Tokens.Depth() { - switch uo.Format { - case "emitnull", "emitempty": - uo.Format = "" // only relevant for marshaling - default: - return newInvalidFormatError(dec, t) - } - } - tok, err := dec.ReadToken() - if err != nil { - return err - } - k := tok.Kind() - switch k { - case 'n': - va.SetZero() - return nil - case '{': - once.Do(init) - if va.IsNil() { - va.Set(reflect.MakeMap(t)) - } - - nonDefaultKey := keyFncs.nonDefault - unmarshalKey := keyFncs.unmarshal - unmarshalVal := valFncs.unmarshal - if uo.Unmarshalers != nil { - var ok bool - unmarshalKey, ok = uo.Unmarshalers.(*Unmarshalers).lookup(unmarshalKey, t.Key()) - unmarshalVal, _ = uo.Unmarshalers.(*Unmarshalers).lookup(unmarshalVal, t.Elem()) - nonDefaultKey = nonDefaultKey || ok - } - k := newAddressableValue(t.Key()) - v := newAddressableValue(t.Elem()) - - // Manually check for duplicate entries by virtue of whether the - // unmarshaled key already exists in the destination Go map. - // Consequently, syntactically different names (e.g., "0" and "-0") - // will be rejected as duplicates since they semantically refer - // to the same Go value. This is an unusual interaction - // between syntax and semantics, but is more correct. - if !nonDefaultKey && mapKeyWithUniqueRepresentation(k.Kind(), uo.Flags.Get(jsonflags.AllowInvalidUTF8)) { - xd.Tokens.Last.DisableNamespace() - } - - // In the rare case where the map is not already empty, - // then we need to manually track which keys we already saw - // since existing presence alone is insufficient to indicate - // whether the input had a duplicate name. - var seen reflect.Value - if !uo.Flags.Get(jsonflags.AllowDuplicateNames) && va.Len() > 0 { - seen = reflect.MakeMap(reflect.MapOf(k.Type(), emptyStructType)) - } - - var errUnmarshal error - for dec.PeekKind() != '}' { - // Unmarshal the map entry key. - k.SetZero() - err := unmarshalKey(dec, k, uo) - if err != nil { - if isFatalError(err, uo.Flags) { - return err - } - if err := dec.SkipValue(); err != nil { - return err - } - errUnmarshal = cmp.Or(errUnmarshal, err) - continue - } - if k.Kind() == reflect.Interface && !k.IsNil() && !k.Elem().Type().Comparable() { - err := newUnmarshalErrorAfter(dec, t, fmt.Errorf("invalid incomparable key type %v", k.Elem().Type())) - if !uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) { - return err - } - if err2 := dec.SkipValue(); err2 != nil { - return err2 - } - errUnmarshal = cmp.Or(errUnmarshal, err) - continue - } - - // Check if a pre-existing map entry value exists for this key. - if v2 := va.MapIndex(k.Value); v2.IsValid() { - if !uo.Flags.Get(jsonflags.AllowDuplicateNames) && (!seen.IsValid() || seen.MapIndex(k.Value).IsValid()) { - // TODO: Unread the object name. - name := xd.PreviousTokenOrValue() - return newDuplicateNameError(dec.StackPointer(), nil, dec.InputOffset()-len64(name)) - } - if !uo.Flags.Get(jsonflags.MergeWithLegacySemantics) { - v.Set(v2) - } else { - v.SetZero() - } - } else { - v.SetZero() - } - - // Unmarshal the map entry value. - err = unmarshalVal(dec, v, uo) - va.SetMapIndex(k.Value, v.Value) - if seen.IsValid() { - seen.SetMapIndex(k.Value, reflect.Zero(emptyStructType)) - } - if err != nil { - if isFatalError(err, uo.Flags) { - return err - } - errUnmarshal = cmp.Or(errUnmarshal, err) - } - } - if _, err := dec.ReadToken(); err != nil { - return err - } - return errUnmarshal - } - return newUnmarshalErrorAfterWithSkipping(dec, t, nil) - } - return &fncs -} - -// mapKeyWithUniqueRepresentation reports whether all possible values of k -// marshal to a different JSON value, and whether all possible JSON values -// that can unmarshal into k unmarshal to different Go values. -// In other words, the representation must be a bijective. -func mapKeyWithUniqueRepresentation(k reflect.Kind, allowInvalidUTF8 bool) bool { - switch k { - case reflect.Bool, - reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, - reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - return true - case reflect.String: - // For strings, we have to be careful since names with invalid UTF-8 - // maybe unescape to the same Go string value. - return !allowInvalidUTF8 - default: - // Floating-point kinds are not listed above since NaNs - // can appear multiple times and all serialize as "NaN". - return false - } -} - -var errNilField = errors.New("cannot set embedded pointer to unexported struct type") - -func makeStructArshaler(t reflect.Type) *arshaler { - // NOTE: The logic below disables namespaces for tracking duplicate names - // and does the tracking locally with an efficient bit-set based on which - // Go struct fields were seen. - - var fncs arshaler - var ( - once sync.Once - fields structFields - errInit *SemanticError - ) - init := func() { - fields, errInit = makeStructFields(t) - } - fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error { - xe := export.Encoder(enc) - if mo.Format != "" && mo.FormatDepth == xe.Tokens.Depth() { - return newInvalidFormatError(enc, t) - } - once.Do(init) - if errInit != nil && !mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) { - return newMarshalErrorBefore(enc, errInit.GoType, errInit.Err) - } - if err := enc.WriteToken(jsontext.BeginObject); err != nil { - return err - } - var seenIdxs uintSet - prevIdx := -1 - xe.Tokens.Last.DisableNamespace() // we manually ensure unique names below - for i := range fields.flattened { - f := &fields.flattened[i] - v := addressableValue{va.Field(f.index0), va.forcedAddr} // addressable if struct value is addressable - if len(f.index) > 0 { - v = v.fieldByIndex(f.index, false) - if !v.IsValid() { - continue // implies a nil inlined field - } - } - - // OmitZero skips the field if the Go value is zero, - // which we can determine up front without calling the marshaler. - if (f.omitzero || mo.Flags.Get(jsonflags.OmitZeroStructFields)) && - ((f.isZero == nil && v.IsZero()) || (f.isZero != nil && f.isZero(v))) { - continue - } - - // Check for the legacy definition of omitempty. - if f.omitempty && mo.Flags.Get(jsonflags.OmitEmptyWithLegacySemantics) && isLegacyEmpty(v) { - continue - } - - marshal := f.fncs.marshal - nonDefault := f.fncs.nonDefault - if mo.Marshalers != nil { - var ok bool - marshal, ok = mo.Marshalers.(*Marshalers).lookup(marshal, f.typ) - nonDefault = nonDefault || ok - } - - // OmitEmpty skips the field if the marshaled JSON value is empty, - // which we can know up front if there are no custom marshalers, - // otherwise we must marshal the value and unwrite it if empty. - if f.omitempty && !mo.Flags.Get(jsonflags.OmitEmptyWithLegacySemantics) && - !nonDefault && f.isEmpty != nil && f.isEmpty(v) { - continue // fast path for omitempty - } - - // Write the object member name. - // - // The logic below is semantically equivalent to: - // enc.WriteToken(String(f.name)) - // but specialized and simplified because: - // 1. The Encoder must be expecting an object name. - // 2. The object namespace is guaranteed to be disabled. - // 3. The object name is guaranteed to be valid and pre-escaped. - // 4. There is no need to flush the buffer (for unwrite purposes). - // 5. There is no possibility of an error occurring. - if optimizeCommon { - // Append any delimiters or optional whitespace. - b := xe.Buf - if xe.Tokens.Last.Length() > 0 { - b = append(b, ',') - if mo.Flags.Get(jsonflags.SpaceAfterComma) { - b = append(b, ' ') - } - } - if mo.Flags.Get(jsonflags.Multiline) { - b = xe.AppendIndent(b, xe.Tokens.NeedIndent('"')) - } - - // Append the token to the output and to the state machine. - n0 := len(b) // offset before calling AppendQuote - if !f.nameNeedEscape { - b = append(b, f.quotedName...) - } else { - b, _ = jsonwire.AppendQuote(b, f.name, &mo.Flags) - } - xe.Buf = b - xe.Names.ReplaceLastQuotedOffset(n0) - xe.Tokens.Last.Increment() - } else { - if err := enc.WriteToken(jsontext.String(f.name)); err != nil { - return err - } - } - - // Write the object member value. - flagsOriginal := mo.Flags - if f.string { - if !mo.Flags.Get(jsonflags.StringifyWithLegacySemantics) { - mo.Flags.Set(jsonflags.StringifyNumbers | 1) - } else if canLegacyStringify(f.typ) { - mo.Flags.Set(jsonflags.StringifyNumbers | jsonflags.StringifyBoolsAndStrings | 1) - } - } - if f.format != "" { - mo.FormatDepth = xe.Tokens.Depth() - mo.Format = f.format - } - err := marshal(enc, v, mo) - mo.Flags = flagsOriginal - mo.Format = "" - if err != nil { - return err - } - - // Try unwriting the member if empty (slow path for omitempty). - if f.omitempty && !mo.Flags.Get(jsonflags.OmitEmptyWithLegacySemantics) { - var prevName *string - if prevIdx >= 0 { - prevName = &fields.flattened[prevIdx].name - } - if xe.UnwriteEmptyObjectMember(prevName) { - continue - } - } - - // Remember the previous written object member. - // The set of seen fields only needs to be updated to detect - // duplicate names with those from the inlined fallback. - if !mo.Flags.Get(jsonflags.AllowDuplicateNames) && fields.inlinedFallback != nil { - seenIdxs.insert(uint(f.id)) - } - prevIdx = f.id - } - if fields.inlinedFallback != nil && !(mo.Flags.Get(jsonflags.DiscardUnknownMembers) && fields.inlinedFallback.unknown) { - var insertUnquotedName func([]byte) bool - if !mo.Flags.Get(jsonflags.AllowDuplicateNames) { - insertUnquotedName = func(name []byte) bool { - // Check that the name from inlined fallback does not match - // one of the previously marshaled names from known fields. - if foldedFields := fields.lookupByFoldedName(name); len(foldedFields) > 0 { - if f := fields.byActualName[string(name)]; f != nil { - return seenIdxs.insert(uint(f.id)) - } - for _, f := range foldedFields { - if f.matchFoldedName(name, &mo.Flags) { - return seenIdxs.insert(uint(f.id)) - } - } - } - - // Check that the name does not match any other name - // previously marshaled from the inlined fallback. - return xe.Namespaces.Last().InsertUnquoted(name) - } - } - if err := marshalInlinedFallbackAll(enc, va, mo, fields.inlinedFallback, insertUnquotedName); err != nil { - return err - } - } - if err := enc.WriteToken(jsontext.EndObject); err != nil { - return err - } - return nil - } - fncs.unmarshal = func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error { - xd := export.Decoder(dec) - if uo.Format != "" && uo.FormatDepth == xd.Tokens.Depth() { - return newInvalidFormatError(dec, t) - } - tok, err := dec.ReadToken() - if err != nil { - return err - } - k := tok.Kind() - switch k { - case 'n': - if !uo.Flags.Get(jsonflags.MergeWithLegacySemantics) { - va.SetZero() - } - return nil - case '{': - once.Do(init) - if errInit != nil && !uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) { - return newUnmarshalErrorAfter(dec, errInit.GoType, errInit.Err) - } - var seenIdxs uintSet - xd.Tokens.Last.DisableNamespace() - var errUnmarshal error - for dec.PeekKind() != '}' { - // Process the object member name. - var flags jsonwire.ValueFlags - val, err := xd.ReadValue(&flags) - if err != nil { - return err - } - name := jsonwire.UnquoteMayCopy(val, flags.IsVerbatim()) - f := fields.byActualName[string(name)] - if f == nil { - for _, f2 := range fields.lookupByFoldedName(name) { - if f2.matchFoldedName(name, &uo.Flags) { - f = f2 - break - } - } - if f == nil { - if uo.Flags.Get(jsonflags.RejectUnknownMembers) && (fields.inlinedFallback == nil || fields.inlinedFallback.unknown) { - err := newUnmarshalErrorAfter(dec, t, ErrUnknownName) - if !uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) { - return err - } - errUnmarshal = cmp.Or(errUnmarshal, err) - } - if !uo.Flags.Get(jsonflags.AllowDuplicateNames) && !xd.Namespaces.Last().InsertUnquoted(name) { - // TODO: Unread the object name. - return newDuplicateNameError(dec.StackPointer(), nil, dec.InputOffset()-len64(val)) - } - - if fields.inlinedFallback == nil { - // Skip unknown value since we have no place to store it. - if err := dec.SkipValue(); err != nil { - return err - } - } else { - // Marshal into value capable of storing arbitrary object members. - if err := unmarshalInlinedFallbackNext(dec, va, uo, fields.inlinedFallback, val, name); err != nil { - if isFatalError(err, uo.Flags) { - return err - } - errUnmarshal = cmp.Or(errUnmarshal, err) - } - } - continue - } - } - if !uo.Flags.Get(jsonflags.AllowDuplicateNames) && !seenIdxs.insert(uint(f.id)) { - // TODO: Unread the object name. - return newDuplicateNameError(dec.StackPointer(), nil, dec.InputOffset()-len64(val)) - } - - // Process the object member value. - unmarshal := f.fncs.unmarshal - if uo.Unmarshalers != nil { - unmarshal, _ = uo.Unmarshalers.(*Unmarshalers).lookup(unmarshal, f.typ) - } - flagsOriginal := uo.Flags - if f.string { - if !uo.Flags.Get(jsonflags.StringifyWithLegacySemantics) { - uo.Flags.Set(jsonflags.StringifyNumbers | 1) - } else if canLegacyStringify(f.typ) { - uo.Flags.Set(jsonflags.StringifyNumbers | jsonflags.StringifyBoolsAndStrings | 1) - } - } - if f.format != "" { - uo.FormatDepth = xd.Tokens.Depth() - uo.Format = f.format - } - v := addressableValue{va.Field(f.index0), va.forcedAddr} // addressable if struct value is addressable - if len(f.index) > 0 { - v = v.fieldByIndex(f.index, true) - if !v.IsValid() { - err := newUnmarshalErrorBefore(dec, t, errNilField) - if !uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) { - return err - } - errUnmarshal = cmp.Or(errUnmarshal, err) - unmarshal = func(dec *jsontext.Decoder, _ addressableValue, _ *jsonopts.Struct) error { - return dec.SkipValue() - } - } - } - err = unmarshal(dec, v, uo) - uo.Flags = flagsOriginal - uo.Format = "" - if err != nil { - if isFatalError(err, uo.Flags) { - return err - } - errUnmarshal = cmp.Or(errUnmarshal, err) - } - } - if _, err := dec.ReadToken(); err != nil { - return err - } - return errUnmarshal - } - return newUnmarshalErrorAfterWithSkipping(dec, t, nil) - } - return &fncs -} - -func (va addressableValue) fieldByIndex(index []int, mayAlloc bool) addressableValue { - for _, i := range index { - va = va.indirect(mayAlloc) - if !va.IsValid() { - return va - } - va = addressableValue{va.Field(i), va.forcedAddr} // addressable if struct value is addressable - } - return va -} - -func (va addressableValue) indirect(mayAlloc bool) addressableValue { - if va.Kind() == reflect.Pointer { - if va.IsNil() { - if !mayAlloc || !va.CanSet() { - return addressableValue{} - } - va.Set(reflect.New(va.Type().Elem())) - } - va = addressableValue{va.Elem(), false} // dereferenced pointer is always addressable - } - return va -} - -// isLegacyEmpty reports whether a value is empty according to the v1 definition. -func isLegacyEmpty(v addressableValue) bool { - // Equivalent to encoding/json.isEmptyValue@v1.21.0. - switch v.Kind() { - case reflect.Bool: - return v.Bool() == false - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return v.Int() == 0 - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - return v.Uint() == 0 - case reflect.Float32, reflect.Float64: - return v.Float() == 0 - case reflect.String, reflect.Map, reflect.Slice, reflect.Array: - return v.Len() == 0 - case reflect.Pointer, reflect.Interface: - return v.IsNil() - } - return false -} - -// canLegacyStringify reports whether t can be stringified according to v1, -// where t is a bool, string, or number (or unnamed pointer to such). -// In v1, the `string` option does not apply recursively to nested types within -// a composite Go type (e.g., an array, slice, struct, map, or interface). -func canLegacyStringify(t reflect.Type) bool { - // Based on encoding/json.typeFields#L1126-L1143@v1.23.0 - if t.Name() == "" && t.Kind() == reflect.Ptr { - t = t.Elem() - } - switch t.Kind() { - case reflect.Bool, reflect.String, - reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, - reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr, - reflect.Float32, reflect.Float64: - return true - } - return false -} - -func makeSliceArshaler(t reflect.Type) *arshaler { - var fncs arshaler - var ( - once sync.Once - valFncs *arshaler - ) - init := func() { - valFncs = lookupArshaler(t.Elem()) - } - fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error { - // Check for cycles. - xe := export.Encoder(enc) - if xe.Tokens.Depth() > startDetectingCyclesAfter { - if err := visitPointer(&xe.SeenPointers, va.Value); err != nil { - return newMarshalErrorBefore(enc, t, err) - } - defer leavePointer(&xe.SeenPointers, va.Value) - } - - emitNull := mo.Flags.Get(jsonflags.FormatNilSliceAsNull) - if mo.Format != "" && mo.FormatDepth == xe.Tokens.Depth() { - switch mo.Format { - case "emitnull": - emitNull = true - mo.Format = "" - case "emitempty": - emitNull = false - mo.Format = "" - default: - return newInvalidFormatError(enc, t) - } - } - - // Handle empty slices. - n := va.Len() - if n == 0 { - if emitNull && va.IsNil() { - return enc.WriteToken(jsontext.Null) - } - // Optimize for marshaling an empty slice without any preceding whitespace. - if optimizeCommon && !mo.Flags.Get(jsonflags.AnyWhitespace) && !xe.Tokens.Last.NeedObjectName() { - xe.Buf = append(xe.Tokens.MayAppendDelim(xe.Buf, '['), "[]"...) - xe.Tokens.Last.Increment() - if xe.NeedFlush() { - return xe.Flush() - } - return nil - } - } - - once.Do(init) - if err := enc.WriteToken(jsontext.BeginArray); err != nil { - return err - } - marshal := valFncs.marshal - if mo.Marshalers != nil { - marshal, _ = mo.Marshalers.(*Marshalers).lookup(marshal, t.Elem()) - } - for i := range n { - v := addressableValue{va.Index(i), false} // indexed slice element is always addressable - if err := marshal(enc, v, mo); err != nil { - return err - } - } - if err := enc.WriteToken(jsontext.EndArray); err != nil { - return err - } - return nil - } - emptySlice := reflect.MakeSlice(t, 0, 0) - fncs.unmarshal = func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error { - xd := export.Decoder(dec) - if uo.Format != "" && uo.FormatDepth == xd.Tokens.Depth() { - switch uo.Format { - case "emitnull", "emitempty": - uo.Format = "" // only relevant for marshaling - default: - return newInvalidFormatError(dec, t) - } - } - - tok, err := dec.ReadToken() - if err != nil { - return err - } - k := tok.Kind() - switch k { - case 'n': - va.SetZero() - return nil - case '[': - once.Do(init) - unmarshal := valFncs.unmarshal - if uo.Unmarshalers != nil { - unmarshal, _ = uo.Unmarshalers.(*Unmarshalers).lookup(unmarshal, t.Elem()) - } - mustZero := true // we do not know the cleanliness of unused capacity - cap := va.Cap() - if cap > 0 { - va.SetLen(cap) - } - var i int - var errUnmarshal error - for dec.PeekKind() != ']' { - if i == cap { - va.Value.Grow(1) - cap = va.Cap() - va.SetLen(cap) - mustZero = false // reflect.Value.Grow ensures new capacity is zero-initialized - } - v := addressableValue{va.Index(i), false} // indexed slice element is always addressable - i++ - if mustZero && !uo.Flags.Get(jsonflags.MergeWithLegacySemantics) { - v.SetZero() - } - if err := unmarshal(dec, v, uo); err != nil { - if isFatalError(err, uo.Flags) { - va.SetLen(i) - return err - } - errUnmarshal = cmp.Or(errUnmarshal, err) - } - } - if i == 0 { - va.Set(emptySlice) - } else { - va.SetLen(i) - } - if _, err := dec.ReadToken(); err != nil { - return err - } - return errUnmarshal - } - return newUnmarshalErrorAfterWithSkipping(dec, t, nil) - } - return &fncs -} - -var errArrayUnderflow = errors.New("too few array elements") -var errArrayOverflow = errors.New("too many array elements") - -func makeArrayArshaler(t reflect.Type) *arshaler { - var fncs arshaler - var ( - once sync.Once - valFncs *arshaler - ) - init := func() { - valFncs = lookupArshaler(t.Elem()) - } - n := t.Len() - fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error { - xe := export.Encoder(enc) - if mo.Format != "" && mo.FormatDepth == xe.Tokens.Depth() { - return newInvalidFormatError(enc, t) - } - once.Do(init) - if err := enc.WriteToken(jsontext.BeginArray); err != nil { - return err - } - marshal := valFncs.marshal - if mo.Marshalers != nil { - marshal, _ = mo.Marshalers.(*Marshalers).lookup(marshal, t.Elem()) - } - for i := range n { - v := addressableValue{va.Index(i), va.forcedAddr} // indexed array element is addressable if array is addressable - if err := marshal(enc, v, mo); err != nil { - return err - } - } - if err := enc.WriteToken(jsontext.EndArray); err != nil { - return err - } - return nil - } - fncs.unmarshal = func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error { - xd := export.Decoder(dec) - if uo.Format != "" && uo.FormatDepth == xd.Tokens.Depth() { - return newInvalidFormatError(dec, t) - } - tok, err := dec.ReadToken() - if err != nil { - return err - } - k := tok.Kind() - switch k { - case 'n': - if !uo.Flags.Get(jsonflags.MergeWithLegacySemantics) { - va.SetZero() - } - return nil - case '[': - once.Do(init) - unmarshal := valFncs.unmarshal - if uo.Unmarshalers != nil { - unmarshal, _ = uo.Unmarshalers.(*Unmarshalers).lookup(unmarshal, t.Elem()) - } - var i int - var errUnmarshal error - for dec.PeekKind() != ']' { - if i >= n { - if err := dec.SkipValue(); err != nil { - return err - } - err = errArrayOverflow - continue - } - v := addressableValue{va.Index(i), va.forcedAddr} // indexed array element is addressable if array is addressable - if !uo.Flags.Get(jsonflags.MergeWithLegacySemantics) { - v.SetZero() - } - if err := unmarshal(dec, v, uo); err != nil { - if isFatalError(err, uo.Flags) { - return err - } - errUnmarshal = cmp.Or(errUnmarshal, err) - } - i++ - } - for ; i < n; i++ { - va.Index(i).SetZero() - err = errArrayUnderflow - } - if _, err := dec.ReadToken(); err != nil { - return err - } - if err != nil && !uo.Flags.Get(jsonflags.UnmarshalArrayFromAnyLength) { - return newUnmarshalErrorAfter(dec, t, err) - } - return errUnmarshal - } - return newUnmarshalErrorAfterWithSkipping(dec, t, nil) - } - return &fncs -} - -func makePointerArshaler(t reflect.Type) *arshaler { - var fncs arshaler - var ( - once sync.Once - valFncs *arshaler - ) - init := func() { - valFncs = lookupArshaler(t.Elem()) - } - fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error { - // Check for cycles. - xe := export.Encoder(enc) - if xe.Tokens.Depth() > startDetectingCyclesAfter { - if err := visitPointer(&xe.SeenPointers, va.Value); err != nil { - return newMarshalErrorBefore(enc, t, err) - } - defer leavePointer(&xe.SeenPointers, va.Value) - } - - // NOTE: Struct.Format is forwarded to underlying marshal. - if va.IsNil() { - return enc.WriteToken(jsontext.Null) - } - once.Do(init) - marshal := valFncs.marshal - if mo.Marshalers != nil { - marshal, _ = mo.Marshalers.(*Marshalers).lookup(marshal, t.Elem()) - } - v := addressableValue{va.Elem(), false} // dereferenced pointer is always addressable - return marshal(enc, v, mo) - } - fncs.unmarshal = func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error { - // NOTE: Struct.Format is forwarded to underlying unmarshal. - if dec.PeekKind() == 'n' { - if _, err := dec.ReadToken(); err != nil { - return err - } - va.SetZero() - return nil - } - once.Do(init) - unmarshal := valFncs.unmarshal - if uo.Unmarshalers != nil { - unmarshal, _ = uo.Unmarshalers.(*Unmarshalers).lookup(unmarshal, t.Elem()) - } - if va.IsNil() { - va.Set(reflect.New(t.Elem())) - } - v := addressableValue{va.Elem(), false} // dereferenced pointer is always addressable - if err := unmarshal(dec, v, uo); err != nil { - return err - } - if uo.Flags.Get(jsonflags.StringifyWithLegacySemantics) && - uo.Flags.Get(jsonflags.StringifyNumbers|jsonflags.StringifyBoolsAndStrings) { - // A JSON null quoted within a JSON string should take effect - // within the pointer value, rather than the indirect value. - // - // TODO: This does not correctly handle escaped nulls - // (e.g., "\u006e\u0075\u006c\u006c"), but is good enough - // for such an esoteric use case of the `string` option. - if string(export.Decoder(dec).PreviousTokenOrValue()) == `"null"` { - va.SetZero() - } - } - return nil - } - return &fncs -} - -func makeInterfaceArshaler(t reflect.Type) *arshaler { - // NOTE: Values retrieved from an interface are not addressable, - // so we shallow copy the values to make them addressable and - // store them back into the interface afterwards. - - var fncs arshaler - var whichMarshaler reflect.Type - for _, iface := range allMarshalerTypes { - if t.Implements(iface) { - whichMarshaler = t - break - } - } - fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error { - xe := export.Encoder(enc) - if mo.Format != "" && mo.FormatDepth == xe.Tokens.Depth() { - return newInvalidFormatError(enc, t) - } - if va.IsNil() { - return enc.WriteToken(jsontext.Null) - } else if mo.Flags.Get(jsonflags.CallMethodsWithLegacySemantics) && whichMarshaler != nil { - // The marshaler for a pointer never calls the method on a nil receiver. - // Wrap the nil pointer within a struct type so that marshal - // instead appears on a value receiver and may be called. - if va.Elem().Kind() == reflect.Pointer && va.Elem().IsNil() { - v2 := newAddressableValue(whichMarshaler) - switch whichMarshaler { - case jsonMarshalerToType: - v2.Set(reflect.ValueOf(struct{ MarshalerTo }{va.Elem().Interface().(MarshalerTo)})) - case jsonMarshalerType: - v2.Set(reflect.ValueOf(struct{ Marshaler }{va.Elem().Interface().(Marshaler)})) - case textAppenderType: - v2.Set(reflect.ValueOf(struct{ encoding.TextAppender }{va.Elem().Interface().(encoding.TextAppender)})) - case textMarshalerType: - v2.Set(reflect.ValueOf(struct{ encoding.TextMarshaler }{va.Elem().Interface().(encoding.TextMarshaler)})) - } - va = v2 - } - } - v := newAddressableValue(va.Elem().Type()) - v.Set(va.Elem()) - marshal := lookupArshaler(v.Type()).marshal - if mo.Marshalers != nil { - marshal, _ = mo.Marshalers.(*Marshalers).lookup(marshal, v.Type()) - } - // Optimize for the any type if there are no special options. - if optimizeCommon && - t == anyType && !mo.Flags.Get(jsonflags.StringifyNumbers|jsonflags.StringifyBoolsAndStrings) && mo.Format == "" && - (mo.Marshalers == nil || !mo.Marshalers.(*Marshalers).fromAny) { - return marshalValueAny(enc, va.Elem().Interface(), mo) - } - return marshal(enc, v, mo) - } - fncs.unmarshal = func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error { - xd := export.Decoder(dec) - if uo.Format != "" && uo.FormatDepth == xd.Tokens.Depth() { - return newInvalidFormatError(dec, t) - } - if uo.Flags.Get(jsonflags.MergeWithLegacySemantics) && !va.IsNil() { - // Legacy merge behavior is difficult to explain. - // In general, it only merges for non-nil pointer kinds. - // As a special case, unmarshaling a JSON null into a pointer - // sets a concrete nil pointer of the underlying type - // (rather than setting the interface value itself to nil). - e := va.Elem() - if e.Kind() == reflect.Pointer && !e.IsNil() { - if dec.PeekKind() == 'n' && e.Elem().Kind() == reflect.Pointer { - if _, err := dec.ReadToken(); err != nil { - return err - } - va.Elem().Elem().SetZero() - return nil - } - } else { - va.SetZero() - } - } - if dec.PeekKind() == 'n' { - if _, err := dec.ReadToken(); err != nil { - return err - } - va.SetZero() - return nil - } - var v addressableValue - if va.IsNil() { - // Optimize for the any type if there are no special options. - // We do not care about stringified numbers since JSON strings - // are always unmarshaled into an any value as Go strings. - // Duplicate name check must be enforced since unmarshalValueAny - // does not implement merge semantics. - if optimizeCommon && - t == anyType && !uo.Flags.Get(jsonflags.AllowDuplicateNames) && uo.Format == "" && - (uo.Unmarshalers == nil || !uo.Unmarshalers.(*Unmarshalers).fromAny) { - v, err := unmarshalValueAny(dec, uo) - // We must check for nil interface values up front. - // See https://go.dev/issue/52310. - if v != nil { - va.Set(reflect.ValueOf(v)) - } - return err - } - - k := dec.PeekKind() - if !isAnyType(t) { - return newUnmarshalErrorBeforeWithSkipping(dec, t, internal.ErrNilInterface) - } - switch k { - case 'f', 't': - v = newAddressableValue(boolType) - case '"': - v = newAddressableValue(stringType) - case '0': - if uo.Flags.Get(jsonflags.UnmarshalAnyWithRawNumber) { - v = addressableValue{reflect.ValueOf(internal.NewRawNumber()).Elem(), true} - } else { - v = newAddressableValue(float64Type) - } - case '{': - v = newAddressableValue(mapStringAnyType) - case '[': - v = newAddressableValue(sliceAnyType) - default: - // If k is invalid (e.g., due to an I/O or syntax error), then - // that will be cached by PeekKind and returned by ReadValue. - // If k is '}' or ']', then ReadValue must error since - // those are invalid kinds at the start of a JSON value. - _, err := dec.ReadValue() - return err - } - } else { - // Shallow copy the existing value to keep it addressable. - // Any mutations at the top-level of the value will be observable - // since we always store this value back into the interface value. - v = newAddressableValue(va.Elem().Type()) - v.Set(va.Elem()) - } - unmarshal := lookupArshaler(v.Type()).unmarshal - if uo.Unmarshalers != nil { - unmarshal, _ = uo.Unmarshalers.(*Unmarshalers).lookup(unmarshal, v.Type()) - } - err := unmarshal(dec, v, uo) - va.Set(v.Value) - return err - } - return &fncs -} - -// isAnyType reports wether t is equivalent to the any interface type. -func isAnyType(t reflect.Type) bool { - // This is forward compatible if the Go language permits type sets within - // ordinary interfaces where an interface with zero methods does not - // necessarily mean it can hold every possible Go type. - // See https://go.dev/issue/45346. - return t == anyType || anyType.Implements(t) -} - -func makeInvalidArshaler(t reflect.Type) *arshaler { - var fncs arshaler - fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error { - return newMarshalErrorBefore(enc, t, nil) - } - fncs.unmarshal = func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error { - return newUnmarshalErrorBefore(dec, t, nil) - } - return &fncs -} - -func stringOrNumberKind(isString bool) jsontext.Kind { - if isString { - return '"' - } else { - return '0' - } -} - -type uintSet64 uint64 - -func (s uintSet64) has(i uint) bool { return s&(1< 0 } -func (s *uintSet64) set(i uint) { *s |= 1 << i } - -// uintSet is a set of unsigned integers. -// It is optimized for most integers being close to zero. -type uintSet struct { - lo uintSet64 - hi []uintSet64 -} - -// has reports whether i is in the set. -func (s *uintSet) has(i uint) bool { - if i < 64 { - return s.lo.has(i) - } else { - i -= 64 - iHi, iLo := int(i/64), i%64 - return iHi < len(s.hi) && s.hi[iHi].has(iLo) - } -} - -// insert inserts i into the set and reports whether it was the first insertion. -func (s *uintSet) insert(i uint) bool { - // TODO: Make this inlinable at least for the lower 64-bit case. - if i < 64 { - has := s.lo.has(i) - s.lo.set(i) - return !has - } else { - i -= 64 - iHi, iLo := int(i/64), i%64 - if iHi >= len(s.hi) { - s.hi = append(s.hi, make([]uintSet64, iHi+1-len(s.hi))...) - s.hi = s.hi[:cap(s.hi)] - } - has := s.hi[iHi].has(iLo) - s.hi[iHi].set(iLo) - return !has - } -} diff --git a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/arshal_funcs.go b/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/arshal_funcs.go deleted file mode 100644 index 50dca26b8..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/arshal_funcs.go +++ /dev/null @@ -1,430 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package json - -import ( - "errors" - "fmt" - "reflect" - "sync" - - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonflags" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonopts" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext" -) - -// SkipFunc may be returned by [MarshalToFunc] and [UnmarshalFromFunc] functions. -// -// Any function that returns SkipFunc must not cause observable side effects -// on the provided [jsontext.Encoder] or [jsontext.Decoder]. -// For example, it is permissible to call [jsontext.Decoder.PeekKind], -// but not permissible to call [jsontext.Decoder.ReadToken] or -// [jsontext.Encoder.WriteToken] since such methods mutate the state. -var SkipFunc = errors.New("json: skip function") - -var errSkipMutation = errors.New("must not read or write any tokens when skipping") -var errNonSingularValue = errors.New("must read or write exactly one value") - -// Marshalers is a list of functions that may override the marshal behavior -// of specific types. Populate [WithMarshalers] to use it with -// [Marshal], [MarshalWrite], or [MarshalEncode]. -// A nil *Marshalers is equivalent to an empty list. -// There are no exported fields or methods on Marshalers. -type Marshalers = typedMarshalers - -// JoinMarshalers constructs a flattened list of marshal functions. -// If multiple functions in the list are applicable for a value of a given type, -// then those earlier in the list take precedence over those that come later. -// If a function returns [SkipFunc], then the next applicable function is called, -// otherwise the default marshaling behavior is used. -// -// For example: -// -// m1 := JoinMarshalers(f1, f2) -// m2 := JoinMarshalers(f0, m1, f3) // equivalent to m3 -// m3 := JoinMarshalers(f0, f1, f2, f3) // equivalent to m2 -func JoinMarshalers(ms ...*Marshalers) *Marshalers { - return newMarshalers(ms...) -} - -// Unmarshalers is a list of functions that may override the unmarshal behavior -// of specific types. Populate [WithUnmarshalers] to use it with -// [Unmarshal], [UnmarshalRead], or [UnmarshalDecode]. -// A nil *Unmarshalers is equivalent to an empty list. -// There are no exported fields or methods on Unmarshalers. -type Unmarshalers = typedUnmarshalers - -// JoinUnmarshalers constructs a flattened list of unmarshal functions. -// If multiple functions in the list are applicable for a value of a given type, -// then those earlier in the list take precedence over those that come later. -// If a function returns [SkipFunc], then the next applicable function is called, -// otherwise the default unmarshaling behavior is used. -// -// For example: -// -// u1 := JoinUnmarshalers(f1, f2) -// u2 := JoinUnmarshalers(f0, u1, f3) // equivalent to u3 -// u3 := JoinUnmarshalers(f0, f1, f2, f3) // equivalent to u2 -func JoinUnmarshalers(us ...*Unmarshalers) *Unmarshalers { - return newUnmarshalers(us...) -} - -type typedMarshalers = typedArshalers[jsontext.Encoder] -type typedUnmarshalers = typedArshalers[jsontext.Decoder] -type typedArshalers[Coder any] struct { - nonComparable - - fncVals []typedArshaler[Coder] - fncCache sync.Map // map[reflect.Type]arshaler - - // fromAny reports whether any of Go types used to represent arbitrary JSON - // (i.e., any, bool, string, float64, map[string]any, or []any) matches - // any of the provided type-specific arshalers. - // - // This bit of information is needed in arshal_default.go to determine - // whether to use the specialized logic in arshal_any.go to handle - // the any interface type. The logic in arshal_any.go does not support - // type-specific arshal functions, so we must avoid using that logic - // if this is true. - fromAny bool -} -type typedMarshaler = typedArshaler[jsontext.Encoder] -type typedUnmarshaler = typedArshaler[jsontext.Decoder] -type typedArshaler[Coder any] struct { - typ reflect.Type - fnc func(*Coder, addressableValue, *jsonopts.Struct) error - maySkip bool -} - -func newMarshalers(ms ...*Marshalers) *Marshalers { return newTypedArshalers(ms...) } -func newUnmarshalers(us ...*Unmarshalers) *Unmarshalers { return newTypedArshalers(us...) } -func newTypedArshalers[Coder any](as ...*typedArshalers[Coder]) *typedArshalers[Coder] { - var a typedArshalers[Coder] - for _, a2 := range as { - if a2 != nil { - a.fncVals = append(a.fncVals, a2.fncVals...) - a.fromAny = a.fromAny || a2.fromAny - } - } - if len(a.fncVals) == 0 { - return nil - } - return &a -} - -func (a *typedArshalers[Coder]) lookup(fnc func(*Coder, addressableValue, *jsonopts.Struct) error, t reflect.Type) (func(*Coder, addressableValue, *jsonopts.Struct) error, bool) { - if a == nil { - return fnc, false - } - if v, ok := a.fncCache.Load(t); ok { - if v == nil { - return fnc, false - } - return v.(func(*Coder, addressableValue, *jsonopts.Struct) error), true - } - - // Collect a list of arshalers that can be called for this type. - // This list may be longer than 1 since some arshalers can be skipped. - var fncs []func(*Coder, addressableValue, *jsonopts.Struct) error - for _, fncVal := range a.fncVals { - if !castableTo(t, fncVal.typ) { - continue - } - fncs = append(fncs, fncVal.fnc) - if !fncVal.maySkip { - break // subsequent arshalers will never be called - } - } - - if len(fncs) == 0 { - a.fncCache.Store(t, nil) // nil to indicate that no funcs found - return fnc, false - } - - // Construct an arshaler that may call every applicable arshaler. - fncDefault := fnc - fnc = func(c *Coder, v addressableValue, o *jsonopts.Struct) error { - for _, fnc := range fncs { - if err := fnc(c, v, o); err != SkipFunc { - return err // may be nil or non-nil - } - } - return fncDefault(c, v, o) - } - - // Use the first stored so duplicate work can be garbage collected. - v, _ := a.fncCache.LoadOrStore(t, fnc) - return v.(func(*Coder, addressableValue, *jsonopts.Struct) error), true -} - -// MarshalFunc constructs a type-specific marshaler that -// specifies how to marshal values of type T. -// T can be any type except a named pointer. -// The function is always provided with a non-nil pointer value -// if T is an interface or pointer type. -// -// The function must marshal exactly one JSON value. -// The value of T must not be retained outside the function call. -// It may not return [SkipFunc]. -func MarshalFunc[T any](fn func(T) ([]byte, error)) *Marshalers { - t := reflect.TypeFor[T]() - assertCastableTo(t, true) - typFnc := typedMarshaler{ - typ: t, - fnc: func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error { - val, err := fn(va.castTo(t).Interface().(T)) - if err != nil { - err = wrapSkipFunc(err, "marshal function of type func(T) ([]byte, error)") - if mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) { - return internal.NewMarshalerError(va.Addr().Interface(), err, "MarshalFunc") // unlike unmarshal, always wrapped - } - err = newMarshalErrorBefore(enc, t, err) - return collapseSemanticErrors(err) - } - if err := enc.WriteValue(val); err != nil { - if mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) { - return internal.NewMarshalerError(va.Addr().Interface(), err, "MarshalFunc") // unlike unmarshal, always wrapped - } - if isSyntacticError(err) { - err = newMarshalErrorBefore(enc, t, err) - } - return err - } - return nil - }, - } - return &Marshalers{fncVals: []typedMarshaler{typFnc}, fromAny: castableToFromAny(t)} -} - -// MarshalToFunc constructs a type-specific marshaler that -// specifies how to marshal values of type T. -// T can be any type except a named pointer. -// The function is always provided with a non-nil pointer value -// if T is an interface or pointer type. -// -// The function must marshal exactly one JSON value by calling write methods -// on the provided encoder. It may return [SkipFunc] such that marshaling can -// move on to the next marshal function. However, no mutable method calls may -// be called on the encoder if [SkipFunc] is returned. -// The pointer to [jsontext.Encoder] and the value of T -// must not be retained outside the function call. -func MarshalToFunc[T any](fn func(*jsontext.Encoder, T) error) *Marshalers { - t := reflect.TypeFor[T]() - assertCastableTo(t, true) - typFnc := typedMarshaler{ - typ: t, - fnc: func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error { - xe := export.Encoder(enc) - prevDepth, prevLength := xe.Tokens.DepthLength() - xe.Flags.Set(jsonflags.WithinArshalCall | 1) - err := fn(enc, va.castTo(t).Interface().(T)) - xe.Flags.Set(jsonflags.WithinArshalCall | 0) - currDepth, currLength := xe.Tokens.DepthLength() - if err == nil && (prevDepth != currDepth || prevLength+1 != currLength) { - err = errNonSingularValue - } - if err != nil { - if err == SkipFunc { - if prevDepth == currDepth && prevLength == currLength { - return SkipFunc - } - err = errSkipMutation - } - if mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) { - return internal.NewMarshalerError(va.Addr().Interface(), err, "MarshalToFunc") // unlike unmarshal, always wrapped - } - if !export.IsIOError(err) { - err = newSemanticErrorWithPosition(enc, t, prevDepth, prevLength, err) - } - return err - } - return nil - }, - maySkip: true, - } - return &Marshalers{fncVals: []typedMarshaler{typFnc}, fromAny: castableToFromAny(t)} -} - -// UnmarshalFunc constructs a type-specific unmarshaler that -// specifies how to unmarshal values of type T. -// T must be an unnamed pointer or an interface type. -// The function is always provided with a non-nil pointer value. -// -// The function must unmarshal exactly one JSON value. -// The input []byte must not be mutated. -// The input []byte and value T must not be retained outside the function call. -// It may not return [SkipFunc]. -func UnmarshalFunc[T any](fn func([]byte, T) error) *Unmarshalers { - t := reflect.TypeFor[T]() - assertCastableTo(t, false) - typFnc := typedUnmarshaler{ - typ: t, - fnc: func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error { - val, err := dec.ReadValue() - if err != nil { - return err // must be a syntactic or I/O error - } - err = fn(val, va.castTo(t).Interface().(T)) - if err != nil { - err = wrapSkipFunc(err, "unmarshal function of type func([]byte, T) error") - if uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) { - return err // unlike marshal, never wrapped - } - err = newUnmarshalErrorAfter(dec, t, err) - return collapseSemanticErrors(err) - } - return nil - }, - } - return &Unmarshalers{fncVals: []typedUnmarshaler{typFnc}, fromAny: castableToFromAny(t)} -} - -// UnmarshalFromFunc constructs a type-specific unmarshaler that -// specifies how to unmarshal values of type T. -// T must be an unnamed pointer or an interface type. -// The function is always provided with a non-nil pointer value. -// -// The function must unmarshal exactly one JSON value by calling read methods -// on the provided decoder. It may return [SkipFunc] such that unmarshaling can -// move on to the next unmarshal function. However, no mutable method calls may -// be called on the decoder if [SkipFunc] is returned. -// The pointer to [jsontext.Decoder] and the value of T -// must not be retained outside the function call. -func UnmarshalFromFunc[T any](fn func(*jsontext.Decoder, T) error) *Unmarshalers { - t := reflect.TypeFor[T]() - assertCastableTo(t, false) - typFnc := typedUnmarshaler{ - typ: t, - fnc: func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error { - xd := export.Decoder(dec) - prevDepth, prevLength := xd.Tokens.DepthLength() - xd.Flags.Set(jsonflags.WithinArshalCall | 1) - err := fn(dec, va.castTo(t).Interface().(T)) - xd.Flags.Set(jsonflags.WithinArshalCall | 0) - currDepth, currLength := xd.Tokens.DepthLength() - if err == nil && (prevDepth != currDepth || prevLength+1 != currLength) { - err = errNonSingularValue - } - if err != nil { - if err == SkipFunc { - if prevDepth == currDepth && prevLength == currLength { - return SkipFunc - } - err = errSkipMutation - } - if uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) { - if err2 := xd.SkipUntil(prevDepth, prevLength+1); err2 != nil { - return err2 - } - return err // unlike marshal, never wrapped - } - if !isSyntacticError(err) && !export.IsIOError(err) { - err = newSemanticErrorWithPosition(dec, t, prevDepth, prevLength, err) - } - return err - } - return nil - }, - maySkip: true, - } - return &Unmarshalers{fncVals: []typedUnmarshaler{typFnc}, fromAny: castableToFromAny(t)} -} - -// assertCastableTo asserts that "to" is a valid type to be casted to. -// These are the Go types that type-specific arshalers may operate upon. -// -// Let AllTypes be the universal set of all possible Go types. -// This function generally asserts that: -// -// len([from for from in AllTypes if castableTo(from, to)]) > 0 -// -// otherwise it panics. -// -// As a special-case if marshal is false, then we forbid any non-pointer or -// non-interface type since it is almost always a bug trying to unmarshal -// into something where the end-user caller did not pass in an addressable value -// since they will not observe the mutations. -func assertCastableTo(to reflect.Type, marshal bool) { - switch to.Kind() { - case reflect.Interface: - return - case reflect.Pointer: - // Only allow unnamed pointers to be consistent with the fact that - // taking the address of a value produces an unnamed pointer type. - if to.Name() == "" { - return - } - default: - // Technically, non-pointer types are permissible for unmarshal. - // However, they are often a bug since the receiver would be immutable. - // Thus, only allow them for marshaling. - if marshal { - return - } - } - if marshal { - panic(fmt.Sprintf("input type %v must be an interface type, an unnamed pointer type, or a non-pointer type", to)) - } else { - panic(fmt.Sprintf("input type %v must be an interface type or an unnamed pointer type", to)) - } -} - -// castableTo checks whether values of type "from" can be casted to type "to". -// Nil pointer or interface "from" values are never considered castable. -// -// This function must be kept in sync with addressableValue.castTo. -func castableTo(from, to reflect.Type) bool { - switch to.Kind() { - case reflect.Interface: - // TODO: This breaks when ordinary interfaces can have type sets - // since interfaces now exist where only the value form of a type (T) - // implements the interface, but not the pointer variant (*T). - // See https://go.dev/issue/45346. - return reflect.PointerTo(from).Implements(to) - case reflect.Pointer: - // Common case for unmarshaling. - // From must be a concrete or interface type. - return reflect.PointerTo(from) == to - default: - // Common case for marshaling. - // From must be a concrete type. - return from == to - } -} - -// castTo casts va to the specified type. -// If the type is an interface, then the underlying type will always -// be a non-nil pointer to a concrete type. -// -// Requirement: castableTo(va.Type(), to) must hold. -func (va addressableValue) castTo(to reflect.Type) reflect.Value { - switch to.Kind() { - case reflect.Interface: - return va.Addr().Convert(to) - case reflect.Pointer: - return va.Addr() - default: - return va.Value - } -} - -// castableToFromAny reports whether "to" can be casted to from any -// of the dynamic types used to represent arbitrary JSON. -func castableToFromAny(to reflect.Type) bool { - for _, from := range []reflect.Type{anyType, boolType, stringType, float64Type, mapStringAnyType, sliceAnyType} { - if castableTo(from, to) { - return true - } - } - return false -} - -func wrapSkipFunc(err error, what string) error { - if err == SkipFunc { - return errors.New(what + " cannot be skipped") - } - return err -} diff --git a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/arshal_inlined.go b/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/arshal_inlined.go deleted file mode 100644 index 4509b87e4..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/arshal_inlined.go +++ /dev/null @@ -1,228 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package json - -import ( - "bytes" - "errors" - "io" - "reflect" - - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonflags" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonopts" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonwire" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext" -) - -// This package supports "inlining" a Go struct field, where the contents -// of the serialized field (which must be a JSON object) are treated as if -// they are part of the parent Go struct (which represents a JSON object). -// -// Generally, inlined fields are of a Go struct type, where the fields of the -// nested struct are virtually hoisted up to the parent struct using rules -// similar to how Go embedding works (but operating within the JSON namespace). -// -// However, inlined fields may also be of a Go map type with a string key or -// a jsontext.Value. Such inlined fields are called "fallback" fields since they -// represent any arbitrary JSON object member. Explicitly named fields take -// precedence over the inlined fallback. Only one inlined fallback is allowed. - -var errRawInlinedNotObject = errors.New("inlined raw value must be a JSON object") - -var jsontextValueType = reflect.TypeFor[jsontext.Value]() - -// marshalInlinedFallbackAll marshals all the members in an inlined fallback. -func marshalInlinedFallbackAll(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct, f *structField, insertUnquotedName func([]byte) bool) error { - v := addressableValue{va.Field(f.index0), va.forcedAddr} // addressable if struct value is addressable - if len(f.index) > 0 { - v = v.fieldByIndex(f.index, false) - if !v.IsValid() { - return nil // implies a nil inlined field - } - } - v = v.indirect(false) - if !v.IsValid() { - return nil - } - - if v.Type() == jsontextValueType { - // TODO(https://go.dev/issue/62121): Use reflect.Value.AssertTo. - b := *v.Addr().Interface().(*jsontext.Value) - if len(b) == 0 { // TODO: Should this be nil? What if it were all whitespace? - return nil - } - - dec := export.GetBufferedDecoder(b) - defer export.PutBufferedDecoder(dec) - xd := export.Decoder(dec) - xd.Flags.Set(jsonflags.AllowDuplicateNames | jsonflags.AllowInvalidUTF8 | 1) - - tok, err := dec.ReadToken() - if err != nil { - if err == io.EOF { - err = io.ErrUnexpectedEOF - } - return newMarshalErrorBefore(enc, v.Type(), err) - } - if tok.Kind() != '{' { - return newMarshalErrorBefore(enc, v.Type(), errRawInlinedNotObject) - } - for dec.PeekKind() != '}' { - // Parse the JSON object name. - var flags jsonwire.ValueFlags - val, err := xd.ReadValue(&flags) - if err != nil { - return newMarshalErrorBefore(enc, v.Type(), err) - } - if insertUnquotedName != nil { - name := jsonwire.UnquoteMayCopy(val, flags.IsVerbatim()) - if !insertUnquotedName(name) { - return newDuplicateNameError(enc.StackPointer().Parent(), val, enc.OutputOffset()) - } - } - if err := enc.WriteValue(val); err != nil { - return err - } - - // Parse the JSON object value. - val, err = xd.ReadValue(&flags) - if err != nil { - return newMarshalErrorBefore(enc, v.Type(), err) - } - if err := enc.WriteValue(val); err != nil { - return err - } - } - if _, err := dec.ReadToken(); err != nil { - return newMarshalErrorBefore(enc, v.Type(), err) - } - if err := xd.CheckEOF(); err != nil { - return newMarshalErrorBefore(enc, v.Type(), err) - } - return nil - } else { - m := v // must be a map[~string]V - n := m.Len() - if n == 0 { - return nil - } - mk := newAddressableValue(m.Type().Key()) - mv := newAddressableValue(m.Type().Elem()) - marshalKey := func(mk addressableValue) error { - b, err := jsonwire.AppendQuote(enc.AvailableBuffer(), mk.String(), &mo.Flags) - if err != nil { - return newMarshalErrorBefore(enc, m.Type().Key(), err) - } - if insertUnquotedName != nil { - isVerbatim := bytes.IndexByte(b, '\\') < 0 - name := jsonwire.UnquoteMayCopy(b, isVerbatim) - if !insertUnquotedName(name) { - return newDuplicateNameError(enc.StackPointer().Parent(), b, enc.OutputOffset()) - } - } - return enc.WriteValue(b) - } - marshalVal := f.fncs.marshal - if mo.Marshalers != nil { - marshalVal, _ = mo.Marshalers.(*Marshalers).lookup(marshalVal, mv.Type()) - } - if !mo.Flags.Get(jsonflags.Deterministic) || n <= 1 { - for iter := m.MapRange(); iter.Next(); { - mk.SetIterKey(iter) - if err := marshalKey(mk); err != nil { - return err - } - mv.Set(iter.Value()) - if err := marshalVal(enc, mv, mo); err != nil { - return err - } - } - } else { - names := getStrings(n) - for i, iter := 0, m.Value.MapRange(); i < n && iter.Next(); i++ { - mk.SetIterKey(iter) - (*names)[i] = mk.String() - } - names.Sort() - for _, name := range *names { - mk.SetString(name) - if err := marshalKey(mk); err != nil { - return err - } - // TODO(https://go.dev/issue/57061): Use mv.SetMapIndexOf. - mv.Set(m.MapIndex(mk.Value)) - if err := marshalVal(enc, mv, mo); err != nil { - return err - } - } - putStrings(names) - } - return nil - } -} - -// unmarshalInlinedFallbackNext unmarshals only the next member in an inlined fallback. -func unmarshalInlinedFallbackNext(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct, f *structField, quotedName, unquotedName []byte) error { - v := addressableValue{va.Field(f.index0), va.forcedAddr} // addressable if struct value is addressable - if len(f.index) > 0 { - v = v.fieldByIndex(f.index, true) - } - v = v.indirect(true) - - if v.Type() == jsontextValueType { - b := v.Addr().Interface().(*jsontext.Value) - if len(*b) == 0 { // TODO: Should this be nil? What if it were all whitespace? - *b = append(*b, '{') - } else { - *b = jsonwire.TrimSuffixWhitespace(*b) - if jsonwire.HasSuffixByte(*b, '}') { - // TODO: When merging into an object for the first time, - // should we verify that it is valid? - *b = jsonwire.TrimSuffixByte(*b, '}') - *b = jsonwire.TrimSuffixWhitespace(*b) - if !jsonwire.HasSuffixByte(*b, ',') && !jsonwire.HasSuffixByte(*b, '{') { - *b = append(*b, ',') - } - } else { - return newUnmarshalErrorAfterWithSkipping(dec, v.Type(), errRawInlinedNotObject) - } - } - *b = append(*b, quotedName...) - *b = append(*b, ':') - val, err := dec.ReadValue() - if err != nil { - return err - } - *b = append(*b, val...) - *b = append(*b, '}') - return nil - } else { - name := string(unquotedName) // TODO: Intern this? - - m := v // must be a map[~string]V - if m.IsNil() { - m.Set(reflect.MakeMap(m.Type())) - } - mk := reflect.ValueOf(name) - if mkt := m.Type().Key(); mkt != stringType { - mk = mk.Convert(mkt) - } - mv := newAddressableValue(m.Type().Elem()) // TODO: Cache across calls? - if v2 := m.MapIndex(mk); v2.IsValid() { - mv.Set(v2) - } - - unmarshal := f.fncs.unmarshal - if uo.Unmarshalers != nil { - unmarshal, _ = uo.Unmarshalers.(*Unmarshalers).lookup(unmarshal, mv.Type()) - } - err := unmarshal(dec, mv, uo) - m.SetMapIndex(mk, mv.Value) - if err != nil { - return err - } - return nil - } -} diff --git a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/arshal_methods.go b/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/arshal_methods.go deleted file mode 100644 index 42d6ee876..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/arshal_methods.go +++ /dev/null @@ -1,335 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package json - -import ( - "encoding" - "errors" - "reflect" - - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonflags" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonopts" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonwire" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext" -) - -var errNonStringValue = errors.New("JSON value must be string type") - -// Interfaces for custom serialization. -var ( - jsonMarshalerType = reflect.TypeFor[Marshaler]() - jsonMarshalerToType = reflect.TypeFor[MarshalerTo]() - jsonUnmarshalerType = reflect.TypeFor[Unmarshaler]() - jsonUnmarshalerFromType = reflect.TypeFor[UnmarshalerFrom]() - textAppenderType = reflect.TypeFor[encoding.TextAppender]() - textMarshalerType = reflect.TypeFor[encoding.TextMarshaler]() - textUnmarshalerType = reflect.TypeFor[encoding.TextUnmarshaler]() - - allMarshalerTypes = []reflect.Type{jsonMarshalerToType, jsonMarshalerType, textAppenderType, textMarshalerType} - allUnmarshalerTypes = []reflect.Type{jsonUnmarshalerFromType, jsonUnmarshalerType, textUnmarshalerType} - allMethodTypes = append(allMarshalerTypes, allUnmarshalerTypes...) -) - -// Marshaler is implemented by types that can marshal themselves. -// It is recommended that types implement [MarshalerTo] unless the implementation -// is trying to avoid a hard dependency on the "jsontext" package. -// -// It is recommended that implementations return a buffer that is safe -// for the caller to retain and potentially mutate. -type Marshaler interface { - MarshalJSON() ([]byte, error) -} - -// MarshalerTo is implemented by types that can marshal themselves. -// It is recommended that types implement MarshalerTo instead of [Marshaler] -// since this is both more performant and flexible. -// If a type implements both Marshaler and MarshalerTo, -// then MarshalerTo takes precedence. In such a case, both implementations -// should aim to have equivalent behavior for the default marshal options. -// -// The implementation must write only one JSON value to the Encoder and -// must not retain the pointer to [jsontext.Encoder]. -type MarshalerTo interface { - MarshalJSONTo(*jsontext.Encoder) error - - // TODO: Should users call the MarshalEncode function or - // should/can they call this method directly? Does it matter? -} - -// Unmarshaler is implemented by types that can unmarshal themselves. -// It is recommended that types implement [UnmarshalerFrom] unless the implementation -// is trying to avoid a hard dependency on the "jsontext" package. -// -// The input can be assumed to be a valid encoding of a JSON value -// if called from unmarshal functionality in this package. -// UnmarshalJSON must copy the JSON data if it is retained after returning. -// It is recommended that UnmarshalJSON implement merge semantics when -// unmarshaling into a pre-populated value. -// -// Implementations must not retain or mutate the input []byte. -type Unmarshaler interface { - UnmarshalJSON([]byte) error -} - -// UnmarshalerFrom is implemented by types that can unmarshal themselves. -// It is recommended that types implement UnmarshalerFrom instead of [Unmarshaler] -// since this is both more performant and flexible. -// If a type implements both Unmarshaler and UnmarshalerFrom, -// then UnmarshalerFrom takes precedence. In such a case, both implementations -// should aim to have equivalent behavior for the default unmarshal options. -// -// The implementation must read only one JSON value from the Decoder. -// It is recommended that UnmarshalJSONFrom implement merge semantics when -// unmarshaling into a pre-populated value. -// -// Implementations must not retain the pointer to [jsontext.Decoder]. -type UnmarshalerFrom interface { - UnmarshalJSONFrom(*jsontext.Decoder) error - - // TODO: Should users call the UnmarshalDecode function or - // should/can they call this method directly? Does it matter? -} - -func makeMethodArshaler(fncs *arshaler, t reflect.Type) *arshaler { - // Avoid injecting method arshaler on the pointer or interface version - // to avoid ever calling the method on a nil pointer or interface receiver. - // Let it be injected on the value receiver (which is always addressable). - if t.Kind() == reflect.Pointer || t.Kind() == reflect.Interface { - return fncs - } - - if needAddr, ok := implements(t, textMarshalerType); ok { - fncs.nonDefault = true - prevMarshal := fncs.marshal - fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error { - if mo.Flags.Get(jsonflags.CallMethodsWithLegacySemantics) && - (needAddr && va.forcedAddr) { - return prevMarshal(enc, va, mo) - } - marshaler := va.Addr().Interface().(encoding.TextMarshaler) - if err := export.Encoder(enc).AppendRaw('"', false, func(b []byte) ([]byte, error) { - b2, err := marshaler.MarshalText() - return append(b, b2...), err - }); err != nil { - err = wrapSkipFunc(err, "marshal method") - if mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) { - return internal.NewMarshalerError(va.Addr().Interface(), err, "MarshalText") // unlike unmarshal, always wrapped - } - if !isSemanticError(err) && !export.IsIOError(err) { - err = newMarshalErrorBefore(enc, t, err) - } - return err - } - return nil - } - } - - if needAddr, ok := implements(t, textAppenderType); ok { - fncs.nonDefault = true - prevMarshal := fncs.marshal - fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) (err error) { - if mo.Flags.Get(jsonflags.CallMethodsWithLegacySemantics) && - (needAddr && va.forcedAddr) { - return prevMarshal(enc, va, mo) - } - appender := va.Addr().Interface().(encoding.TextAppender) - if err := export.Encoder(enc).AppendRaw('"', false, appender.AppendText); err != nil { - err = wrapSkipFunc(err, "append method") - if mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) { - return internal.NewMarshalerError(va.Addr().Interface(), err, "AppendText") // unlike unmarshal, always wrapped - } - if !isSemanticError(err) && !export.IsIOError(err) { - err = newMarshalErrorBefore(enc, t, err) - } - return err - } - return nil - } - } - - if needAddr, ok := implements(t, jsonMarshalerType); ok { - fncs.nonDefault = true - prevMarshal := fncs.marshal - fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error { - if mo.Flags.Get(jsonflags.CallMethodsWithLegacySemantics) && - ((needAddr && va.forcedAddr) || export.Encoder(enc).Tokens.Last.NeedObjectName()) { - return prevMarshal(enc, va, mo) - } - marshaler := va.Addr().Interface().(Marshaler) - val, err := marshaler.MarshalJSON() - if err != nil { - err = wrapSkipFunc(err, "marshal method") - if mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) { - return internal.NewMarshalerError(va.Addr().Interface(), err, "MarshalJSON") // unlike unmarshal, always wrapped - } - err = newMarshalErrorBefore(enc, t, err) - return collapseSemanticErrors(err) - } - if err := enc.WriteValue(val); err != nil { - if mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) { - return internal.NewMarshalerError(va.Addr().Interface(), err, "MarshalJSON") // unlike unmarshal, always wrapped - } - if isSyntacticError(err) { - err = newMarshalErrorBefore(enc, t, err) - } - return err - } - return nil - } - } - - if needAddr, ok := implements(t, jsonMarshalerToType); ok { - fncs.nonDefault = true - prevMarshal := fncs.marshal - fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error { - if mo.Flags.Get(jsonflags.CallMethodsWithLegacySemantics) && - ((needAddr && va.forcedAddr) || export.Encoder(enc).Tokens.Last.NeedObjectName()) { - return prevMarshal(enc, va, mo) - } - xe := export.Encoder(enc) - prevDepth, prevLength := xe.Tokens.DepthLength() - xe.Flags.Set(jsonflags.WithinArshalCall | 1) - err := va.Addr().Interface().(MarshalerTo).MarshalJSONTo(enc) - xe.Flags.Set(jsonflags.WithinArshalCall | 0) - currDepth, currLength := xe.Tokens.DepthLength() - if (prevDepth != currDepth || prevLength+1 != currLength) && err == nil { - err = errNonSingularValue - } - if err != nil { - err = wrapSkipFunc(err, "marshal method") - if mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) { - return internal.NewMarshalerError(va.Addr().Interface(), err, "MarshalJSONTo") // unlike unmarshal, always wrapped - } - if !export.IsIOError(err) { - err = newSemanticErrorWithPosition(enc, t, prevDepth, prevLength, err) - } - return err - } - return nil - } - } - - if _, ok := implements(t, textUnmarshalerType); ok { - fncs.nonDefault = true - fncs.unmarshal = func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error { - xd := export.Decoder(dec) - var flags jsonwire.ValueFlags - val, err := xd.ReadValue(&flags) - if err != nil { - return err // must be a syntactic or I/O error - } - if val.Kind() == 'n' { - if !uo.Flags.Get(jsonflags.MergeWithLegacySemantics) { - va.SetZero() - } - return nil - } - if val.Kind() != '"' { - return newUnmarshalErrorAfter(dec, t, errNonStringValue) - } - s := jsonwire.UnquoteMayCopy(val, flags.IsVerbatim()) - unmarshaler := va.Addr().Interface().(encoding.TextUnmarshaler) - if err := unmarshaler.UnmarshalText(s); err != nil { - err = wrapSkipFunc(err, "unmarshal method") - if uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) { - return err // unlike marshal, never wrapped - } - if !isSemanticError(err) && !isSyntacticError(err) && !export.IsIOError(err) { - err = newUnmarshalErrorAfter(dec, t, err) - } - return err - } - return nil - } - } - - if _, ok := implements(t, jsonUnmarshalerType); ok { - fncs.nonDefault = true - prevUnmarshal := fncs.unmarshal - fncs.unmarshal = func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error { - if uo.Flags.Get(jsonflags.CallMethodsWithLegacySemantics) && - export.Decoder(dec).Tokens.Last.NeedObjectName() { - return prevUnmarshal(dec, va, uo) - } - val, err := dec.ReadValue() - if err != nil { - return err // must be a syntactic or I/O error - } - unmarshaler := va.Addr().Interface().(Unmarshaler) - if err := unmarshaler.UnmarshalJSON(val); err != nil { - err = wrapSkipFunc(err, "unmarshal method") - if uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) { - return err // unlike marshal, never wrapped - } - err = newUnmarshalErrorAfter(dec, t, err) - return collapseSemanticErrors(err) - } - return nil - } - } - - if _, ok := implements(t, jsonUnmarshalerFromType); ok { - fncs.nonDefault = true - prevUnmarshal := fncs.unmarshal - fncs.unmarshal = func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error { - if uo.Flags.Get(jsonflags.CallMethodsWithLegacySemantics) && - export.Decoder(dec).Tokens.Last.NeedObjectName() { - return prevUnmarshal(dec, va, uo) - } - xd := export.Decoder(dec) - prevDepth, prevLength := xd.Tokens.DepthLength() - xd.Flags.Set(jsonflags.WithinArshalCall | 1) - err := va.Addr().Interface().(UnmarshalerFrom).UnmarshalJSONFrom(dec) - xd.Flags.Set(jsonflags.WithinArshalCall | 0) - currDepth, currLength := xd.Tokens.DepthLength() - if (prevDepth != currDepth || prevLength+1 != currLength) && err == nil { - err = errNonSingularValue - } - if err != nil { - err = wrapSkipFunc(err, "unmarshal method") - if uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) { - if err2 := xd.SkipUntil(prevDepth, prevLength+1); err2 != nil { - return err2 - } - return err // unlike marshal, never wrapped - } - if !isSyntacticError(err) && !export.IsIOError(err) { - err = newSemanticErrorWithPosition(dec, t, prevDepth, prevLength, err) - } - return err - } - return nil - } - } - - return fncs -} - -// implementsAny is like t.Implements(ifaceType) for a list of interfaces, -// but checks whether either t or reflect.PointerTo(t) implements the interface. -func implementsAny(t reflect.Type, ifaceTypes ...reflect.Type) bool { - for _, ifaceType := range ifaceTypes { - if _, ok := implements(t, ifaceType); ok { - return true - } - } - return false -} - -// implements is like t.Implements(ifaceType) but checks whether -// either t or reflect.PointerTo(t) implements the interface. -// It also reports whether the value needs to be addressed -// in order to satisfy the interface. -func implements(t, ifaceType reflect.Type) (needAddr, ok bool) { - switch { - case t.Implements(ifaceType): - return false, true - case reflect.PointerTo(t).Implements(ifaceType): - return true, true - default: - return false, false - } -} diff --git a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/arshal_time.go b/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/arshal_time.go deleted file mode 100644 index 30dd584d1..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/arshal_time.go +++ /dev/null @@ -1,775 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package json - -import ( - "bytes" - "cmp" - "errors" - "fmt" - "math" - "math/bits" - "reflect" - "strconv" - "strings" - "time" - - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonflags" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonopts" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonwire" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext" -) - -var ( - timeDurationType = reflect.TypeFor[time.Duration]() - timeTimeType = reflect.TypeFor[time.Time]() -) - -func makeTimeArshaler(fncs *arshaler, t reflect.Type) *arshaler { - // Ideally, time types would implement MarshalerTo and UnmarshalerFrom, - // but that would incur a dependency on package json from package time. - // Given how widely used time is, it is more acceptable that we incur a - // dependency on time from json. - // - // Injecting the arshaling functionality like this will not be identical - // to actually declaring methods on the time types since embedding of the - // time types will not be able to forward this functionality. - switch t { - case timeDurationType: - fncs.nonDefault = true - marshalNano := fncs.marshal - fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error { - xe := export.Encoder(enc) - var m durationArshaler - if mo.Format != "" && mo.FormatDepth == xe.Tokens.Depth() { - if !m.initFormat(mo.Format) { - return newInvalidFormatError(enc, t) - } - } else if mo.Flags.Get(jsonflags.FormatDurationAsNano) { - return marshalNano(enc, va, mo) - } else { - // TODO(https://go.dev/issue/71631): Decide on default duration representation. - return newMarshalErrorBefore(enc, t, errors.New("no default representation (see https://go.dev/issue/71631); specify an explicit format")) - } - - // TODO(https://go.dev/issue/62121): Use reflect.Value.AssertTo. - m.td = *va.Addr().Interface().(*time.Duration) - k := stringOrNumberKind(!m.isNumeric() || xe.Tokens.Last.NeedObjectName() || mo.Flags.Get(jsonflags.StringifyNumbers)) - if err := xe.AppendRaw(k, true, m.appendMarshal); err != nil { - if !isSyntacticError(err) && !export.IsIOError(err) { - err = newMarshalErrorBefore(enc, t, err) - } - return err - } - return nil - } - unmarshalNano := fncs.unmarshal - fncs.unmarshal = func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error { - xd := export.Decoder(dec) - var u durationArshaler - if uo.Format != "" && uo.FormatDepth == xd.Tokens.Depth() { - if !u.initFormat(uo.Format) { - return newInvalidFormatError(dec, t) - } - } else if uo.Flags.Get(jsonflags.FormatDurationAsNano) { - return unmarshalNano(dec, va, uo) - } else { - // TODO(https://go.dev/issue/71631): Decide on default duration representation. - return newUnmarshalErrorBeforeWithSkipping(dec, t, errors.New("no default representation (see https://go.dev/issue/71631); specify an explicit format")) - } - - stringify := !u.isNumeric() || xd.Tokens.Last.NeedObjectName() || uo.Flags.Get(jsonflags.StringifyNumbers) - var flags jsonwire.ValueFlags - td := va.Addr().Interface().(*time.Duration) - val, err := xd.ReadValue(&flags) - if err != nil { - return err - } - switch k := val.Kind(); k { - case 'n': - if !uo.Flags.Get(jsonflags.MergeWithLegacySemantics) { - *td = time.Duration(0) - } - return nil - case '"': - if !stringify { - break - } - val = jsonwire.UnquoteMayCopy(val, flags.IsVerbatim()) - if err := u.unmarshal(val); err != nil { - return newUnmarshalErrorAfter(dec, t, err) - } - *td = u.td - return nil - case '0': - if stringify { - break - } - if err := u.unmarshal(val); err != nil { - return newUnmarshalErrorAfter(dec, t, err) - } - *td = u.td - return nil - } - return newUnmarshalErrorAfter(dec, t, nil) - } - case timeTimeType: - fncs.nonDefault = true - fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) (err error) { - xe := export.Encoder(enc) - var m timeArshaler - if mo.Format != "" && mo.FormatDepth == xe.Tokens.Depth() { - if !m.initFormat(mo.Format) { - return newInvalidFormatError(enc, t) - } - } - - // TODO(https://go.dev/issue/62121): Use reflect.Value.AssertTo. - m.tt = *va.Addr().Interface().(*time.Time) - k := stringOrNumberKind(!m.isNumeric() || xe.Tokens.Last.NeedObjectName() || mo.Flags.Get(jsonflags.StringifyNumbers)) - if err := xe.AppendRaw(k, !m.hasCustomFormat(), m.appendMarshal); err != nil { - if mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) { - return internal.NewMarshalerError(va.Addr().Interface(), err, "MarshalJSON") // unlike unmarshal, always wrapped - } - if !isSyntacticError(err) && !export.IsIOError(err) { - err = newMarshalErrorBefore(enc, t, err) - } - return err - } - return nil - } - fncs.unmarshal = func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) (err error) { - xd := export.Decoder(dec) - var u timeArshaler - if uo.Format != "" && uo.FormatDepth == xd.Tokens.Depth() { - if !u.initFormat(uo.Format) { - return newInvalidFormatError(dec, t) - } - } else if uo.Flags.Get(jsonflags.ParseTimeWithLooseRFC3339) { - u.looseRFC3339 = true - } - - stringify := !u.isNumeric() || xd.Tokens.Last.NeedObjectName() || uo.Flags.Get(jsonflags.StringifyNumbers) - var flags jsonwire.ValueFlags - tt := va.Addr().Interface().(*time.Time) - val, err := xd.ReadValue(&flags) - if err != nil { - return err - } - switch k := val.Kind(); k { - case 'n': - if !uo.Flags.Get(jsonflags.MergeWithLegacySemantics) { - *tt = time.Time{} - } - return nil - case '"': - if !stringify { - break - } - val = jsonwire.UnquoteMayCopy(val, flags.IsVerbatim()) - if err := u.unmarshal(val); err != nil { - if uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) { - return err // unlike marshal, never wrapped - } - return newUnmarshalErrorAfter(dec, t, err) - } - *tt = u.tt - return nil - case '0': - if stringify { - break - } - if err := u.unmarshal(val); err != nil { - if uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) { - return err // unlike marshal, never wrapped - } - return newUnmarshalErrorAfter(dec, t, err) - } - *tt = u.tt - return nil - } - return newUnmarshalErrorAfter(dec, t, nil) - } - } - return fncs -} - -type durationArshaler struct { - td time.Duration - - // base records the representation where: - // - 0 uses time.Duration.String - // - 1e0, 1e3, 1e6, or 1e9 use a decimal encoding of the duration as - // nanoseconds, microseconds, milliseconds, or seconds. - // - 8601 uses ISO 8601 - base uint64 -} - -func (a *durationArshaler) initFormat(format string) (ok bool) { - switch format { - case "units": - a.base = 0 - case "sec": - a.base = 1e9 - case "milli": - a.base = 1e6 - case "micro": - a.base = 1e3 - case "nano": - a.base = 1e0 - case "iso8601": - a.base = 8601 - default: - return false - } - return true -} - -func (a *durationArshaler) isNumeric() bool { - return a.base != 0 && a.base != 8601 -} - -func (a *durationArshaler) appendMarshal(b []byte) ([]byte, error) { - switch a.base { - case 0: - return append(b, a.td.String()...), nil - case 8601: - return appendDurationISO8601(b, a.td), nil - default: - return appendDurationBase10(b, a.td, a.base), nil - } -} - -func (a *durationArshaler) unmarshal(b []byte) (err error) { - switch a.base { - case 0: - a.td, err = time.ParseDuration(string(b)) - case 8601: - a.td, err = parseDurationISO8601(b) - default: - a.td, err = parseDurationBase10(b, a.base) - } - return err -} - -type timeArshaler struct { - tt time.Time - - // base records the representation where: - // - 0 uses RFC 3339 encoding of the timestamp - // - 1e0, 1e3, 1e6, or 1e9 use a decimal encoding of the timestamp as - // seconds, milliseconds, microseconds, or nanoseconds since Unix epoch. - // - math.MaxUint uses time.Time.Format to encode the timestamp - base uint64 - format string // time format passed to time.Parse - - looseRFC3339 bool -} - -func (a *timeArshaler) initFormat(format string) bool { - // We assume that an exported constant in the time package will - // always start with an uppercase ASCII letter. - if len(format) == 0 { - return false - } - a.base = math.MaxUint // implies custom format - if c := format[0]; !('a' <= c && c <= 'z') && !('A' <= c && c <= 'Z') { - a.format = format - return true - } - switch format { - case "ANSIC": - a.format = time.ANSIC - case "UnixDate": - a.format = time.UnixDate - case "RubyDate": - a.format = time.RubyDate - case "RFC822": - a.format = time.RFC822 - case "RFC822Z": - a.format = time.RFC822Z - case "RFC850": - a.format = time.RFC850 - case "RFC1123": - a.format = time.RFC1123 - case "RFC1123Z": - a.format = time.RFC1123Z - case "RFC3339": - a.base = 0 - a.format = time.RFC3339 - case "RFC3339Nano": - a.base = 0 - a.format = time.RFC3339Nano - case "Kitchen": - a.format = time.Kitchen - case "Stamp": - a.format = time.Stamp - case "StampMilli": - a.format = time.StampMilli - case "StampMicro": - a.format = time.StampMicro - case "StampNano": - a.format = time.StampNano - case "DateTime": - a.format = time.DateTime - case "DateOnly": - a.format = time.DateOnly - case "TimeOnly": - a.format = time.TimeOnly - case "unix": - a.base = 1e0 - case "unixmilli": - a.base = 1e3 - case "unixmicro": - a.base = 1e6 - case "unixnano": - a.base = 1e9 - default: - // Reject any Go identifier in case new constants are supported. - if strings.TrimFunc(format, isLetterOrDigit) == "" { - return false - } - a.format = format - } - return true -} - -func (a *timeArshaler) isNumeric() bool { - return int(a.base) > 0 -} - -func (a *timeArshaler) hasCustomFormat() bool { - return a.base == math.MaxUint -} - -func (a *timeArshaler) appendMarshal(b []byte) ([]byte, error) { - switch a.base { - case 0: - format := cmp.Or(a.format, time.RFC3339Nano) - n0 := len(b) - b = a.tt.AppendFormat(b, format) - // Not all Go timestamps can be represented as valid RFC 3339. - // Explicitly check for these edge cases. - // See https://go.dev/issue/4556 and https://go.dev/issue/54580. - switch b := b[n0:]; { - case b[len("9999")] != '-': // year must be exactly 4 digits wide - return b, errors.New("year outside of range [0,9999]") - case b[len(b)-1] != 'Z': - c := b[len(b)-len("Z07:00")] - if ('0' <= c && c <= '9') || parseDec2(b[len(b)-len("07:00"):]) >= 24 { - return b, errors.New("timezone hour outside of range [0,23]") - } - } - return b, nil - case math.MaxUint: - return a.tt.AppendFormat(b, a.format), nil - default: - return appendTimeUnix(b, a.tt, a.base), nil - } -} - -func (a *timeArshaler) unmarshal(b []byte) (err error) { - switch a.base { - case 0: - // Use time.Time.UnmarshalText to avoid possible string allocation. - if err := a.tt.UnmarshalText(b); err != nil { - return err - } - // TODO(https://go.dev/issue/57912): - // RFC 3339 specifies the grammar for a valid timestamp. - // However, the parsing functionality in "time" is too loose and - // incorrectly accepts invalid timestamps as valid. - // Remove these manual checks when "time" checks it for us. - newParseError := func(layout, value, layoutElem, valueElem, message string) error { - return &time.ParseError{Layout: layout, Value: value, LayoutElem: layoutElem, ValueElem: valueElem, Message: message} - } - switch { - case a.looseRFC3339: - return nil - case b[len("2006-01-02T")+1] == ':': // hour must be two digits - return newParseError(time.RFC3339, string(b), "15", string(b[len("2006-01-02T"):][:1]), "") - case b[len("2006-01-02T15:04:05")] == ',': // sub-second separator must be a period - return newParseError(time.RFC3339, string(b), ".", ",", "") - case b[len(b)-1] != 'Z': - switch { - case parseDec2(b[len(b)-len("07:00"):]) >= 24: // timezone hour must be in range - return newParseError(time.RFC3339, string(b), "Z07:00", string(b[len(b)-len("Z07:00"):]), ": timezone hour out of range") - case parseDec2(b[len(b)-len("00"):]) >= 60: // timezone minute must be in range - return newParseError(time.RFC3339, string(b), "Z07:00", string(b[len(b)-len("Z07:00"):]), ": timezone minute out of range") - } - } - return nil - case math.MaxUint: - a.tt, err = time.Parse(a.format, string(b)) - return err - default: - a.tt, err = parseTimeUnix(b, a.base) - return err - } -} - -// appendDurationBase10 appends d formatted as a decimal fractional number, -// where pow10 is a power-of-10 used to scale down the number. -func appendDurationBase10(b []byte, d time.Duration, pow10 uint64) []byte { - b, n := mayAppendDurationSign(b, d) // append sign - whole, frac := bits.Div64(0, n, uint64(pow10)) // compute whole and frac fields - b = strconv.AppendUint(b, whole, 10) // append whole field - return appendFracBase10(b, frac, pow10) // append frac field -} - -// parseDurationBase10 parses d from a decimal fractional number, -// where pow10 is a power-of-10 used to scale up the number. -func parseDurationBase10(b []byte, pow10 uint64) (time.Duration, error) { - suffix, neg := consumeSign(b, false) // consume sign - wholeBytes, fracBytes := bytesCutByte(suffix, '.', true) // consume whole and frac fields - whole, okWhole := jsonwire.ParseUint(wholeBytes) // parse whole field; may overflow - frac, okFrac := parseFracBase10(fracBytes, pow10) // parse frac field - hi, lo := bits.Mul64(whole, uint64(pow10)) // overflow if hi > 0 - sum, co := bits.Add64(lo, uint64(frac), 0) // overflow if co > 0 - switch d := mayApplyDurationSign(sum, neg); { // overflow if neg != (d < 0) - case (!okWhole && whole != math.MaxUint64) || !okFrac: - return 0, fmt.Errorf("invalid duration %q: %w", b, strconv.ErrSyntax) - case !okWhole || hi > 0 || co > 0 || neg != (d < 0): - return 0, fmt.Errorf("invalid duration %q: %w", b, strconv.ErrRange) - default: - return d, nil - } -} - -// appendDurationISO8601 appends an ISO 8601 duration with a restricted grammar, -// where leading and trailing zeroes and zero-value designators are omitted. -// It only uses hour, minute, and second designators since ISO 8601 defines -// those as being "accurate", while year, month, week, and day are "nominal". -func appendDurationISO8601(b []byte, d time.Duration) []byte { - if d == 0 { - return append(b, "PT0S"...) - } - b, n := mayAppendDurationSign(b, d) - b = append(b, "PT"...) - n, nsec := bits.Div64(0, n, 1e9) // compute nsec field - n, sec := bits.Div64(0, n, 60) // compute sec field - hour, min := bits.Div64(0, n, 60) // compute hour and min fields - if hour > 0 { - b = append(strconv.AppendUint(b, hour, 10), 'H') - } - if min > 0 { - b = append(strconv.AppendUint(b, min, 10), 'M') - } - if sec > 0 || nsec > 0 { - b = append(appendFracBase10(strconv.AppendUint(b, sec, 10), nsec, 1e9), 'S') - } - return b -} - -// daysPerYear is the exact average number of days in a year according to -// the Gregorian calender, which has an extra day each year that is -// a multiple of 4, unless it is evenly divisible by 100 but not by 400. -// This does not take into account leap seconds, which are not deterministic. -const daysPerYear = 365.2425 - -var errInaccurateDateUnits = errors.New("inaccurate year, month, week, or day units") - -// parseDurationISO8601 parses a duration according to ISO 8601-1:2019, -// section 5.5.2.2 and 5.5.2.3 with the following restrictions or extensions: -// -// - A leading minus sign is permitted for negative duration according -// to ISO 8601-2:2019, section 4.4.1.9. We do not permit negative values -// for each "time scale component", which is permitted by section 4.4.1.1, -// but rarely supported by parsers. -// -// - A leading plus sign is permitted (and ignored). -// This is not required by ISO 8601, but not forbidden either. -// There is some precedent for this as it is supported by the principle of -// duration arithmetic as specified in ISO 8601-2-2019, section 14.1. -// Of note, the JavaScript grammar for ISO 8601 permits a leading plus sign. -// -// - A fractional value is only permitted for accurate units -// (i.e., hour, minute, and seconds) in the last time component, -// which is permissible by ISO 8601-1:2019, section 5.5.2.3. -// -// - Both periods ('.') and commas (',') are supported as the separator -// between the integer part and fraction part of a number, -// as specified in ISO 8601-1:2019, section 3.2.6. -// While ISO 8601 recommends comma as the default separator, -// most formatters uses a period. -// -// - Leading zeros are ignored. This is not required by ISO 8601, -// but also not forbidden by the standard. Many parsers support this. -// -// - Lowercase designators are supported. This is not required by ISO 8601, -// but also not forbidden by the standard. Many parsers support this. -// -// If the nominal units of year, month, week, or day are present, -// this produces a best-effort value and also reports [errInaccurateDateUnits]. -// -// The accepted grammar is identical to JavaScript's Duration: -// -// https://tc39.es/proposal-temporal/#prod-Duration -// -// We follow JavaScript's grammar as JSON itself is derived from JavaScript. -// The Temporal.Duration.toJSON method is guaranteed to produce an output -// that can be parsed by this function so long as arithmetic in JavaScript -// do not use a largestUnit value higher than "hours" (which is the default). -// Even if it does, this will do a best-effort parsing with inaccurate units, -// but report [errInaccurateDateUnits]. -func parseDurationISO8601(b []byte) (time.Duration, error) { - var invalid, overflow, inaccurate, sawFrac bool - var sumNanos, n, co uint64 - - // cutBytes is like [bytes.Cut], but uses either c0 or c1 as the separator. - cutBytes := func(b []byte, c0, c1 byte) (prefix, suffix []byte, ok bool) { - for i, c := range b { - if c == c0 || c == c1 { - return b[:i], b[i+1:], true - } - } - return b, nil, false - } - - // mayParseUnit attempts to parse another date or time number - // identified by the desHi and desLo unit characters. - // If the part is absent for current unit, it returns b as is. - mayParseUnit := func(b []byte, desHi, desLo byte, unit time.Duration) []byte { - number, suffix, ok := cutBytes(b, desHi, desLo) - if !ok || sawFrac { - return b // designator is not present or already saw fraction, which can only be in the last component - } - - // Parse the number. - // A fraction allowed for the accurate units in the last part. - whole, frac, ok := cutBytes(number, '.', ',') - if ok { - sawFrac = true - invalid = invalid || len(frac) == len("") || unit > time.Hour - if unit == time.Second { - n, ok = parsePaddedBase10(frac, uint64(time.Second)) - invalid = invalid || !ok - } else { - f, err := strconv.ParseFloat("0."+string(frac), 64) - invalid = invalid || err != nil || len(bytes.Trim(frac[len("."):], "0123456789")) > 0 - n = uint64(math.Round(f * float64(unit))) // never overflows since f is within [0..1] - } - sumNanos, co = bits.Add64(sumNanos, n, 0) // overflow if co > 0 - overflow = overflow || co > 0 - } - for len(whole) > 1 && whole[0] == '0' { - whole = whole[len("0"):] // trim leading zeros - } - n, ok := jsonwire.ParseUint(whole) // overflow if !ok && MaxUint64 - hi, lo := bits.Mul64(n, uint64(unit)) // overflow if hi > 0 - sumNanos, co = bits.Add64(sumNanos, lo, 0) // overflow if co > 0 - invalid = invalid || (!ok && n != math.MaxUint64) - overflow = overflow || (!ok && n == math.MaxUint64) || hi > 0 || co > 0 - inaccurate = inaccurate || unit > time.Hour - return suffix - } - - suffix, neg := consumeSign(b, true) - prefix, suffix, okP := cutBytes(suffix, 'P', 'p') - durDate, durTime, okT := cutBytes(suffix, 'T', 't') - invalid = invalid || len(prefix) > 0 || !okP || (okT && len(durTime) == 0) || len(durDate)+len(durTime) == 0 - if len(durDate) > 0 { // nominal portion of the duration - durDate = mayParseUnit(durDate, 'Y', 'y', time.Duration(daysPerYear*24*60*60*1e9)) - durDate = mayParseUnit(durDate, 'M', 'm', time.Duration(daysPerYear/12*24*60*60*1e9)) - durDate = mayParseUnit(durDate, 'W', 'w', time.Duration(7*24*60*60*1e9)) - durDate = mayParseUnit(durDate, 'D', 'd', time.Duration(24*60*60*1e9)) - invalid = invalid || len(durDate) > 0 // unknown elements - } - if len(durTime) > 0 { // accurate portion of the duration - durTime = mayParseUnit(durTime, 'H', 'h', time.Duration(60*60*1e9)) - durTime = mayParseUnit(durTime, 'M', 'm', time.Duration(60*1e9)) - durTime = mayParseUnit(durTime, 'S', 's', time.Duration(1e9)) - invalid = invalid || len(durTime) > 0 // unknown elements - } - d := mayApplyDurationSign(sumNanos, neg) - overflow = overflow || (neg != (d < 0) && d != 0) // overflows signed duration - - switch { - case invalid: - return 0, fmt.Errorf("invalid ISO 8601 duration %q: %w", b, strconv.ErrSyntax) - case overflow: - return 0, fmt.Errorf("invalid ISO 8601 duration %q: %w", b, strconv.ErrRange) - case inaccurate: - return d, fmt.Errorf("invalid ISO 8601 duration %q: %w", b, errInaccurateDateUnits) - default: - return d, nil - } -} - -// mayAppendDurationSign appends a negative sign if n is negative. -func mayAppendDurationSign(b []byte, d time.Duration) ([]byte, uint64) { - if d < 0 { - b = append(b, '-') - d *= -1 - } - return b, uint64(d) -} - -// mayApplyDurationSign inverts n if neg is specified. -func mayApplyDurationSign(n uint64, neg bool) time.Duration { - if neg { - return -1 * time.Duration(n) - } else { - return +1 * time.Duration(n) - } -} - -// appendTimeUnix appends t formatted as a decimal fractional number, -// where pow10 is a power-of-10 used to scale up the number. -func appendTimeUnix(b []byte, t time.Time, pow10 uint64) []byte { - sec, nsec := t.Unix(), int64(t.Nanosecond()) - if sec < 0 { - b = append(b, '-') - sec, nsec = negateSecNano(sec, nsec) - } - switch { - case pow10 == 1e0: // fast case where units is in seconds - b = strconv.AppendUint(b, uint64(sec), 10) - return appendFracBase10(b, uint64(nsec), 1e9) - case uint64(sec) < 1e9: // intermediate case where units is not seconds, but no overflow - b = strconv.AppendUint(b, uint64(sec)*uint64(pow10)+uint64(uint64(nsec)/(1e9/pow10)), 10) - return appendFracBase10(b, (uint64(nsec)*pow10)%1e9, 1e9) - default: // slow case where units is not seconds and overflow would occur - b = strconv.AppendUint(b, uint64(sec), 10) - b = appendPaddedBase10(b, uint64(nsec)/(1e9/pow10), pow10) - return appendFracBase10(b, (uint64(nsec)*pow10)%1e9, 1e9) - } -} - -// parseTimeUnix parses t formatted as a decimal fractional number, -// where pow10 is a power-of-10 used to scale down the number. -func parseTimeUnix(b []byte, pow10 uint64) (time.Time, error) { - suffix, neg := consumeSign(b, false) // consume sign - wholeBytes, fracBytes := bytesCutByte(suffix, '.', true) // consume whole and frac fields - whole, okWhole := jsonwire.ParseUint(wholeBytes) // parse whole field; may overflow - frac, okFrac := parseFracBase10(fracBytes, 1e9/pow10) // parse frac field - var sec, nsec int64 - switch { - case pow10 == 1e0: // fast case where units is in seconds - sec = int64(whole) // check overflow later after negation - nsec = int64(frac) // cannot overflow - case okWhole: // intermediate case where units is not seconds, but no overflow - sec = int64(whole / pow10) // check overflow later after negation - nsec = int64((whole%pow10)*(1e9/pow10) + frac) // cannot overflow - case !okWhole && whole == math.MaxUint64: // slow case where units is not seconds and overflow occurred - width := int(math.Log10(float64(pow10))) // compute len(strconv.Itoa(pow10-1)) - whole, okWhole = jsonwire.ParseUint(wholeBytes[:len(wholeBytes)-width]) // parse the upper whole field - mid, _ := parsePaddedBase10(wholeBytes[len(wholeBytes)-width:], pow10) // parse the lower whole field - sec = int64(whole) // check overflow later after negation - nsec = int64(mid*(1e9/pow10) + frac) // cannot overflow - } - if neg { - sec, nsec = negateSecNano(sec, nsec) - } - switch t := time.Unix(sec, nsec).UTC(); { - case (!okWhole && whole != math.MaxUint64) || !okFrac: - return time.Time{}, fmt.Errorf("invalid time %q: %w", b, strconv.ErrSyntax) - case !okWhole || neg != (t.Unix() < 0): - return time.Time{}, fmt.Errorf("invalid time %q: %w", b, strconv.ErrRange) - default: - return t, nil - } -} - -// negateSecNano negates a Unix timestamp, where nsec must be within [0, 1e9). -func negateSecNano(sec, nsec int64) (int64, int64) { - sec = ^sec // twos-complement negation (i.e., -1*sec + 1) - nsec = -nsec + 1e9 // negate nsec and add 1e9 (which is the extra +1 from sec negation) - sec += int64(nsec / 1e9) // handle possible overflow of nsec if it started as zero - nsec %= 1e9 // ensure nsec stays within [0, 1e9) - return sec, nsec -} - -// appendFracBase10 appends the fraction of n/max10, -// where max10 is a power-of-10 that is larger than n. -func appendFracBase10(b []byte, n, max10 uint64) []byte { - if n == 0 { - return b - } - return bytes.TrimRight(appendPaddedBase10(append(b, '.'), n, max10), "0") -} - -// parseFracBase10 parses the fraction of n/max10, -// where max10 is a power-of-10 that is larger than n. -func parseFracBase10(b []byte, max10 uint64) (n uint64, ok bool) { - switch { - case len(b) == 0: - return 0, true - case len(b) < len(".0") || b[0] != '.': - return 0, false - } - return parsePaddedBase10(b[len("."):], max10) -} - -// appendPaddedBase10 appends a zero-padded encoding of n, -// where max10 is a power-of-10 that is larger than n. -func appendPaddedBase10(b []byte, n, max10 uint64) []byte { - if n < max10/10 { - // Formatting of n is shorter than log10(max10), - // so add max10/10 to ensure the length is equal to log10(max10). - i := len(b) - b = strconv.AppendUint(b, n+max10/10, 10) - b[i]-- // subtract the addition of max10/10 - return b - } - return strconv.AppendUint(b, n, 10) -} - -// parsePaddedBase10 parses b as the zero-padded encoding of n, -// where max10 is a power-of-10 that is larger than n. -// Truncated suffix is treated as implicit zeros. -// Extended suffix is ignored, but verified to contain only digits. -func parsePaddedBase10(b []byte, max10 uint64) (n uint64, ok bool) { - pow10 := uint64(1) - for pow10 < max10 { - n *= 10 - if len(b) > 0 { - if b[0] < '0' || '9' < b[0] { - return n, false - } - n += uint64(b[0] - '0') - b = b[1:] - } - pow10 *= 10 - } - if len(b) > 0 && len(bytes.TrimRight(b, "0123456789")) > 0 { - return n, false // trailing characters are not digits - } - return n, true -} - -// consumeSign consumes an optional leading negative or positive sign. -func consumeSign(b []byte, allowPlus bool) ([]byte, bool) { - if len(b) > 0 { - if b[0] == '-' { - return b[len("-"):], true - } else if b[0] == '+' && allowPlus { - return b[len("+"):], false - } - } - return b, false -} - -// bytesCutByte is similar to bytes.Cut(b, []byte{c}), -// except c may optionally be included as part of the suffix. -func bytesCutByte(b []byte, c byte, include bool) ([]byte, []byte) { - if i := bytes.IndexByte(b, c); i >= 0 { - if include { - return b[:i], b[i:] - } - return b[:i], b[i+1:] - } - return b, nil -} - -// parseDec2 parses b as an unsigned, base-10, 2-digit number. -// The result is undefined if digits are not base-10. -func parseDec2(b []byte) byte { - if len(b) < 2 { - return 0 - } - return 10*(b[0]-'0') + (b[1] - '0') -} diff --git a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/doc.go b/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/doc.go deleted file mode 100644 index ff70951ab..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/doc.go +++ /dev/null @@ -1,262 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package json implements semantic processing of JSON as specified in RFC 8259. -// JSON is a simple data interchange format that can represent -// primitive data types such as booleans, strings, and numbers, -// in addition to structured data types such as objects and arrays. -// -// [Marshal] and [Unmarshal] encode and decode Go values -// to/from JSON text contained within a []byte. -// [MarshalWrite] and [UnmarshalRead] operate on JSON text -// by writing to or reading from an [io.Writer] or [io.Reader]. -// [MarshalEncode] and [UnmarshalDecode] operate on JSON text -// by encoding to or decoding from a [jsontext.Encoder] or [jsontext.Decoder]. -// [Options] may be passed to each of the marshal or unmarshal functions -// to configure the semantic behavior of marshaling and unmarshaling -// (i.e., alter how JSON data is understood as Go data and vice versa). -// [jsontext.Options] may also be passed to the marshal or unmarshal functions -// to configure the syntactic behavior of encoding or decoding. -// -// The data types of JSON are mapped to/from the data types of Go based on -// the closest logical equivalent between the two type systems. For example, -// a JSON boolean corresponds with a Go bool, -// a JSON string corresponds with a Go string, -// a JSON number corresponds with a Go int, uint or float, -// a JSON array corresponds with a Go slice or array, and -// a JSON object corresponds with a Go struct or map. -// See the documentation on [Marshal] and [Unmarshal] for a comprehensive list -// of how the JSON and Go type systems correspond. -// -// Arbitrary Go types can customize their JSON representation by implementing -// [Marshaler], [MarshalerTo], [Unmarshaler], or [UnmarshalerFrom]. -// This provides authors of Go types with control over how their types are -// serialized as JSON. Alternatively, users can implement functions that match -// [MarshalFunc], [MarshalToFunc], [UnmarshalFunc], or [UnmarshalFromFunc] -// to specify the JSON representation for arbitrary types. -// This provides callers of JSON functionality with control over -// how any arbitrary type is serialized as JSON. -// -// # JSON Representation of Go structs -// -// A Go struct is naturally represented as a JSON object, -// where each Go struct field corresponds with a JSON object member. -// When marshaling, all Go struct fields are recursively encoded in depth-first -// order as JSON object members except those that are ignored or omitted. -// When unmarshaling, JSON object members are recursively decoded -// into the corresponding Go struct fields. -// Object members that do not match any struct fields, -// also known as “unknown members”, are ignored by default or rejected -// if [RejectUnknownMembers] is specified. -// -// The representation of each struct field can be customized in the -// "json" struct field tag, where the tag is a comma separated list of options. -// As a special case, if the entire tag is `json:"-"`, -// then the field is ignored with regard to its JSON representation. -// Some options also have equivalent behavior controlled by a caller-specified [Options]. -// Field-specified options take precedence over caller-specified options. -// -// The first option is the JSON object name override for the Go struct field. -// If the name is not specified, then the Go struct field name -// is used as the JSON object name. JSON names containing commas or quotes, -// or names identical to "" or "-", can be specified using -// a single-quoted string literal, where the syntax is identical to -// the Go grammar for a double-quoted string literal, -// but instead uses single quotes as the delimiters. -// By default, unmarshaling uses case-sensitive matching to identify -// the Go struct field associated with a JSON object name. -// -// After the name, the following tag options are supported: -// -// - omitzero: When marshaling, the "omitzero" option specifies that -// the struct field should be omitted if the field value is zero -// as determined by the "IsZero() bool" method if present, -// otherwise based on whether the field is the zero Go value. -// This option has no effect when unmarshaling. -// -// - omitempty: When marshaling, the "omitempty" option specifies that -// the struct field should be omitted if the field value would have been -// encoded as a JSON null, empty string, empty object, or empty array. -// This option has no effect when unmarshaling. -// -// - string: The "string" option specifies that [StringifyNumbers] -// be set when marshaling or unmarshaling a struct field value. -// This causes numeric types to be encoded as a JSON number -// within a JSON string, and to be decoded from a JSON string -// containing the JSON number without any surrounding whitespace. -// This extra level of encoding is often necessary since -// many JSON parsers cannot precisely represent 64-bit integers. -// -// - case: When unmarshaling, the "case" option specifies how -// JSON object names are matched with the JSON name for Go struct fields. -// The option is a key-value pair specified as "case:value" where -// the value must either be 'ignore' or 'strict'. -// The 'ignore' value specifies that matching is case-insensitive -// where dashes and underscores are also ignored. If multiple fields match, -// the first declared field in breadth-first order takes precedence. -// The 'strict' value specifies that matching is case-sensitive. -// This takes precedence over the [MatchCaseInsensitiveNames] option. -// -// - inline: The "inline" option specifies that -// the JSON representable content of this field type is to be promoted -// as if they were specified in the parent struct. -// It is the JSON equivalent of Go struct embedding. -// A Go embedded field is implicitly inlined unless an explicit JSON name -// is specified. The inlined field must be a Go struct -// (that does not implement any JSON methods), [jsontext.Value], -// map[~string]T, or an unnamed pointer to such types. When marshaling, -// inlined fields from a pointer type are omitted if it is nil. -// Inlined fields of type [jsontext.Value] and map[~string]T are called -// “inlined fallbacks” as they can represent all possible -// JSON object members not directly handled by the parent struct. -// Only one inlined fallback field may be specified in a struct, -// while many non-fallback fields may be specified. This option -// must not be specified with any other option (including the JSON name). -// -// - unknown: The "unknown" option is a specialized variant -// of the inlined fallback to indicate that this Go struct field -// contains any number of unknown JSON object members. The field type must -// be a [jsontext.Value], map[~string]T, or an unnamed pointer to such types. -// If [DiscardUnknownMembers] is specified when marshaling, -// the contents of this field are ignored. -// If [RejectUnknownMembers] is specified when unmarshaling, -// any unknown object members are rejected regardless of whether -// an inlined fallback with the "unknown" option exists. This option -// must not be specified with any other option (including the JSON name). -// -// - format: The "format" option specifies a format flag -// used to specialize the formatting of the field value. -// The option is a key-value pair specified as "format:value" where -// the value must be either a literal consisting of letters and numbers -// (e.g., "format:RFC3339") or a single-quoted string literal -// (e.g., "format:'2006-01-02'"). The interpretation of the format flag -// is determined by the struct field type. -// -// The "omitzero" and "omitempty" options are mostly semantically identical. -// The former is defined in terms of the Go type system, -// while the latter in terms of the JSON type system. -// Consequently they behave differently in some circumstances. -// For example, only a nil slice or map is omitted under "omitzero", while -// an empty slice or map is omitted under "omitempty" regardless of nilness. -// The "omitzero" option is useful for types with a well-defined zero value -// (e.g., [net/netip.Addr]) or have an IsZero method (e.g., [time.Time.IsZero]). -// -// Every Go struct corresponds to a list of JSON representable fields -// which is constructed by performing a breadth-first search over -// all struct fields (excluding unexported or ignored fields), -// where the search recursively descends into inlined structs. -// The set of non-inlined fields in a struct must have unique JSON names. -// If multiple fields all have the same JSON name, then the one -// at shallowest depth takes precedence and the other fields at deeper depths -// are excluded from the list of JSON representable fields. -// If multiple fields at the shallowest depth have the same JSON name, -// but exactly one is explicitly tagged with a JSON name, -// then that field takes precedence and all others are excluded from the list. -// This is analogous to Go visibility rules for struct field selection -// with embedded struct types. -// -// Marshaling or unmarshaling a non-empty struct -// without any JSON representable fields results in a [SemanticError]. -// Unexported fields must not have any `json` tags except for `json:"-"`. -// -// # Security Considerations -// -// JSON is frequently used as a data interchange format to communicate -// between different systems, possibly implemented in different languages. -// For interoperability and security reasons, it is important that -// all implementations agree upon the semantic meaning of the data. -// -// [For example, suppose we have two micro-services.] -// The first service is responsible for authenticating a JSON request, -// while the second service is responsible for executing the request -// (having assumed that the prior service authenticated the request). -// If an attacker were able to maliciously craft a JSON request such that -// both services believe that the same request is from different users, -// it could bypass the authenticator with valid credentials for one user, -// but maliciously perform an action on behalf of a different user. -// -// According to RFC 8259, there unfortunately exist many JSON texts -// that are syntactically valid but semantically ambiguous. -// For example, the standard does not define how to interpret duplicate -// names within an object. -// -// The v1 [encoding/json] and [encoding/json/v2] packages -// interpret some inputs in different ways. In particular: -// -// - The standard specifies that JSON must be encoded using UTF-8. -// By default, v1 replaces invalid bytes of UTF-8 in JSON strings -// with the Unicode replacement character, -// while v2 rejects inputs with invalid UTF-8. -// To change the default, specify the [jsontext.AllowInvalidUTF8] option. -// The replacement of invalid UTF-8 is a form of data corruption -// that alters the precise meaning of strings. -// -// - The standard does not specify a particular behavior when -// duplicate names are encountered within a JSON object, -// which means that different implementations may behave differently. -// By default, v1 allows for the presence of duplicate names, -// while v2 rejects duplicate names. -// To change the default, specify the [jsontext.AllowDuplicateNames] option. -// If allowed, object members are processed in the order they are observed, -// meaning that later values will replace or be merged into prior values, -// depending on the Go value type. -// -// - The standard defines a JSON object as an unordered collection of name/value pairs. -// While ordering can be observed through the underlying [jsontext] API, -// both v1 and v2 generally avoid exposing the ordering. -// No application should semantically depend on the order of object members. -// Allowing duplicate names is a vector through which ordering of members -// can accidentally be observed and depended upon. -// -// - The standard suggests that JSON object names are typically compared -// based on equality of the sequence of Unicode code points, -// which implies that comparing names is often case-sensitive. -// When unmarshaling a JSON object into a Go struct, -// by default, v1 uses a (loose) case-insensitive match on the name, -// while v2 uses a (strict) case-sensitive match on the name. -// To change the default, specify the [MatchCaseInsensitiveNames] option. -// The use of case-insensitive matching provides another vector through -// which duplicate names can occur. Allowing case-insensitive matching -// means that v1 or v2 might interpret JSON objects differently from most -// other JSON implementations (which typically use a case-sensitive match). -// -// - The standard does not specify a particular behavior when -// an unknown name in a JSON object is encountered. -// When unmarshaling a JSON object into a Go struct, by default -// both v1 and v2 ignore unknown names and their corresponding values. -// To change the default, specify the [RejectUnknownMembers] option. -// -// - The standard suggests that implementations may use a float64 -// to represent a JSON number. Consequently, large JSON integers -// may lose precision when stored as a floating-point type. -// Both v1 and v2 correctly preserve precision when marshaling and -// unmarshaling a concrete integer type. However, even if v1 and v2 -// preserve precision for concrete types, other JSON implementations -// may not be able to preserve precision for outputs produced by v1 or v2. -// The `string` tag option can be used to specify that an integer type -// is to be quoted within a JSON string to avoid loss of precision. -// Furthermore, v1 and v2 may still lose precision when unmarshaling -// into an any interface value, where unmarshal uses a float64 -// by default to represent a JSON number. -// To change the default, specify the [WithUnmarshalers] option -// with a custom unmarshaler that pre-populates the interface value -// with a concrete Go type that can preserve precision. -// -// RFC 8785 specifies a canonical form for any JSON text, -// which explicitly defines specific behaviors that RFC 8259 leaves undefined. -// In theory, if a text can successfully [jsontext.Value.Canonicalize] -// without changing the semantic meaning of the data, then it provides a -// greater degree of confidence that the data is more secure and interoperable. -// -// The v2 API generally chooses more secure defaults than v1, -// but care should still be taken with large integers or unknown members. -// -// [For example, suppose we have two micro-services.]: https://www.youtube.com/watch?v=avilmOcHKHE&t=1057s -package json - -// requireKeyedLiterals can be embedded in a struct to require keyed literals. -type requireKeyedLiterals struct{} - -// nonComparable can be embedded in a struct to prevent comparability. -type nonComparable [0]func() diff --git a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/errors.go b/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/errors.go deleted file mode 100644 index 1df765384..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/errors.go +++ /dev/null @@ -1,428 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package json - -import ( - "cmp" - "errors" - "fmt" - "reflect" - "strconv" - "strings" - "sync" - - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonflags" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonopts" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonwire" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext" -) - -// ErrUnknownName indicates that a JSON object member could not be -// unmarshaled because the name is not known to the target Go struct. -// This error is directly wrapped within a [SemanticError] when produced. -// -// The name of an unknown JSON object member can be extracted as: -// -// err := ... -// var serr json.SemanticError -// if errors.As(err, &serr) && serr.Err == json.ErrUnknownName { -// ptr := serr.JSONPointer // JSON pointer to unknown name -// name := ptr.LastToken() // unknown name itself -// ... -// } -// -// This error is only returned if [RejectUnknownMembers] is true. -var ErrUnknownName = errors.New("unknown object member name") - -const errorPrefix = "json: " - -func isSemanticError(err error) bool { - _, ok := err.(*SemanticError) - return ok -} - -func isSyntacticError(err error) bool { - _, ok := err.(*jsontext.SyntacticError) - return ok -} - -// isFatalError reports whether this error must terminate asharling. -// All errors are considered fatal unless operating under -// [jsonflags.ReportErrorsWithLegacySemantics] in which case only -// syntactic errors and I/O errors are considered fatal. -func isFatalError(err error, flags jsonflags.Flags) bool { - return !flags.Get(jsonflags.ReportErrorsWithLegacySemantics) || - isSyntacticError(err) || export.IsIOError(err) -} - -// SemanticError describes an error determining the meaning -// of JSON data as Go data or vice-versa. -// -// The contents of this error as produced by this package may change over time. -type SemanticError struct { - requireKeyedLiterals - nonComparable - - action string // either "marshal" or "unmarshal" - - // ByteOffset indicates that an error occurred after this byte offset. - ByteOffset int64 - // JSONPointer indicates that an error occurred within this JSON value - // as indicated using the JSON Pointer notation (see RFC 6901). - JSONPointer jsontext.Pointer - - // JSONKind is the JSON kind that could not be handled. - JSONKind jsontext.Kind // may be zero if unknown - // JSONValue is the JSON number or string that could not be unmarshaled. - // It is not populated during marshaling. - JSONValue jsontext.Value // may be nil if irrelevant or unknown - // GoType is the Go type that could not be handled. - GoType reflect.Type // may be nil if unknown - - // Err is the underlying error. - Err error // may be nil -} - -// coder is implemented by [jsontext.Encoder] or [jsontext.Decoder]. -type coder interface { - StackPointer() jsontext.Pointer - Options() Options -} - -// newInvalidFormatError wraps err in a SemanticError because -// the current type t cannot handle the provided options format. -// This error must be called before producing or consuming the next value. -// -// If [jsonflags.ReportErrorsWithLegacySemantics] is specified, -// then this automatically skips the next value when unmarshaling -// to ensure that the value is fully consumed. -func newInvalidFormatError(c coder, t reflect.Type) error { - err := fmt.Errorf("invalid format flag %q", c.Options().(*jsonopts.Struct).Format) - switch c := c.(type) { - case *jsontext.Encoder: - err = newMarshalErrorBefore(c, t, err) - case *jsontext.Decoder: - err = newUnmarshalErrorBeforeWithSkipping(c, t, err) - } - return err -} - -// newMarshalErrorBefore wraps err in a SemanticError assuming that e -// is positioned right before the next token or value, which causes an error. -func newMarshalErrorBefore(e *jsontext.Encoder, t reflect.Type, err error) error { - return &SemanticError{action: "marshal", GoType: t, Err: err, - ByteOffset: e.OutputOffset() + int64(export.Encoder(e).CountNextDelimWhitespace()), - JSONPointer: jsontext.Pointer(export.Encoder(e).AppendStackPointer(nil, +1))} -} - -// newUnmarshalErrorBefore wraps err in a SemanticError assuming that d -// is positioned right before the next token or value, which causes an error. -// It does not record the next JSON kind as this error is used to indicate -// the receiving Go value is invalid to unmarshal into (and not a JSON error). -// However, if [jsonflags.ReportErrorsWithLegacySemantics] is specified, -// then it does record the next JSON kind for historical reporting reasons. -func newUnmarshalErrorBefore(d *jsontext.Decoder, t reflect.Type, err error) error { - var k jsontext.Kind - if export.Decoder(d).Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) { - k = d.PeekKind() - } - return &SemanticError{action: "unmarshal", GoType: t, Err: err, - ByteOffset: d.InputOffset() + int64(export.Decoder(d).CountNextDelimWhitespace()), - JSONPointer: jsontext.Pointer(export.Decoder(d).AppendStackPointer(nil, +1)), - JSONKind: k} -} - -// newUnmarshalErrorBeforeWithSkipping is like [newUnmarshalErrorBefore], -// but automatically skips the next value if -// [jsonflags.ReportErrorsWithLegacySemantics] is specified. -func newUnmarshalErrorBeforeWithSkipping(d *jsontext.Decoder, t reflect.Type, err error) error { - err = newUnmarshalErrorBefore(d, t, err) - if export.Decoder(d).Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) { - if err2 := export.Decoder(d).SkipValue(); err2 != nil { - return err2 - } - } - return err -} - -// newUnmarshalErrorAfter wraps err in a SemanticError assuming that d -// is positioned right after the previous token or value, which caused an error. -func newUnmarshalErrorAfter(d *jsontext.Decoder, t reflect.Type, err error) error { - tokOrVal := export.Decoder(d).PreviousTokenOrValue() - return &SemanticError{action: "unmarshal", GoType: t, Err: err, - ByteOffset: d.InputOffset() - int64(len(tokOrVal)), - JSONPointer: jsontext.Pointer(export.Decoder(d).AppendStackPointer(nil, -1)), - JSONKind: jsontext.Value(tokOrVal).Kind()} -} - -// newUnmarshalErrorAfter wraps err in a SemanticError assuming that d -// is positioned right after the previous token or value, which caused an error. -// It also stores a copy of the last JSON value if it is a string or number. -func newUnmarshalErrorAfterWithValue(d *jsontext.Decoder, t reflect.Type, err error) error { - serr := newUnmarshalErrorAfter(d, t, err).(*SemanticError) - if serr.JSONKind == '"' || serr.JSONKind == '0' { - serr.JSONValue = jsontext.Value(export.Decoder(d).PreviousTokenOrValue()).Clone() - } - return serr -} - -// newUnmarshalErrorAfterWithSkipping is like [newUnmarshalErrorAfter], -// but automatically skips the remainder of the current value if -// [jsonflags.ReportErrorsWithLegacySemantics] is specified. -func newUnmarshalErrorAfterWithSkipping(d *jsontext.Decoder, t reflect.Type, err error) error { - err = newUnmarshalErrorAfter(d, t, err) - if export.Decoder(d).Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) { - if err2 := export.Decoder(d).SkipValueRemainder(); err2 != nil { - return err2 - } - } - return err -} - -// newSemanticErrorWithPosition wraps err in a SemanticError assuming that -// the error occurred at the provided depth, and length. -// If err is already a SemanticError, then position information is only -// injected if it is currently unpopulated. -// -// If the position is unpopulated, it is ambiguous where the error occurred -// in the user code, whether it was before or after the current position. -// For the byte offset, we assume that the error occurred before the last read -// token or value when decoding, or before the next value when encoding. -// For the JSON pointer, we point to the parent object or array unless -// we can be certain that it happened with an object member. -// -// This is used to annotate errors returned by user-provided -// v2 MarshalJSON or UnmarshalJSON methods or functions. -func newSemanticErrorWithPosition(c coder, t reflect.Type, prevDepth int, prevLength int64, err error) error { - serr, _ := err.(*SemanticError) - if serr == nil { - serr = &SemanticError{Err: err} - } - var currDepth int - var currLength int64 - var coderState interface{ AppendStackPointer([]byte, int) []byte } - var offset int64 - switch c := c.(type) { - case *jsontext.Encoder: - e := export.Encoder(c) - serr.action = cmp.Or(serr.action, "marshal") - currDepth, currLength = e.Tokens.DepthLength() - offset = c.OutputOffset() + int64(export.Encoder(c).CountNextDelimWhitespace()) - coderState = e - case *jsontext.Decoder: - d := export.Decoder(c) - serr.action = cmp.Or(serr.action, "unmarshal") - currDepth, currLength = d.Tokens.DepthLength() - tokOrVal := d.PreviousTokenOrValue() - offset = c.InputOffset() - int64(len(tokOrVal)) - if (prevDepth == currDepth && prevLength == currLength) || len(tokOrVal) == 0 { - // If no Read method was called in the user-defined method or - // if the Peek method was called, then use the offset of the next value. - offset = c.InputOffset() + int64(export.Decoder(c).CountNextDelimWhitespace()) - } - coderState = d - } - serr.ByteOffset = cmp.Or(serr.ByteOffset, offset) - if serr.JSONPointer == "" { - where := 0 // default to ambiguous positioning - switch { - case prevDepth == currDepth && prevLength+0 == currLength: - where = +1 - case prevDepth == currDepth && prevLength+1 == currLength: - where = -1 - } - serr.JSONPointer = jsontext.Pointer(coderState.AppendStackPointer(nil, where)) - } - serr.GoType = cmp.Or(serr.GoType, t) - return serr -} - -// collapseSemanticErrors collapses double SemanticErrors at the outer levels -// into a single SemanticError by preserving the inner error, -// but prepending the ByteOffset and JSONPointer with the outer error. -// -// For example: -// -// collapseSemanticErrors(&SemanticError{ -// ByteOffset: len64(`[0,{"alpha":[0,1,`), -// JSONPointer: "/1/alpha/2", -// GoType: reflect.TypeFor[outerType](), -// Err: &SemanticError{ -// ByteOffset: len64(`{"foo":"bar","fizz":[0,`), -// JSONPointer: "/fizz/1", -// GoType: reflect.TypeFor[innerType](), -// Err: ..., -// }, -// }) -// -// results in: -// -// &SemanticError{ -// ByteOffset: len64(`[0,{"alpha":[0,1,`) + len64(`{"foo":"bar","fizz":[0,`), -// JSONPointer: "/1/alpha/2" + "/fizz/1", -// GoType: reflect.TypeFor[innerType](), -// Err: ..., -// } -// -// This is used to annotate errors returned by user-provided -// v1 MarshalJSON or UnmarshalJSON methods with precise position information -// if they themselves happened to return a SemanticError. -// Since MarshalJSON and UnmarshalJSON are not operating on the root JSON value, -// their positioning must be relative to the nested JSON value -// returned by UnmarshalJSON or passed to MarshalJSON. -// Therefore, we can construct an absolute position by concatenating -// the outer with the inner positions. -// -// Note that we do not use collapseSemanticErrors with user-provided functions -// that take in an [jsontext.Encoder] or [jsontext.Decoder] since they contain -// methods to report position relative to the root JSON value. -// We assume user-constructed errors are correctly precise about position. -func collapseSemanticErrors(err error) error { - if serr1, ok := err.(*SemanticError); ok { - if serr2, ok := serr1.Err.(*SemanticError); ok { - serr2.ByteOffset = serr1.ByteOffset + serr2.ByteOffset - serr2.JSONPointer = serr1.JSONPointer + serr2.JSONPointer - *serr1 = *serr2 - } - } - return err -} - -// errorModalVerb is a modal verb like "cannot" or "unable to". -// -// Once per process, Hyrum-proof the error message by deliberately -// switching between equivalent renderings of the same error message. -// The randomization is tied to the Hyrum-proofing already applied -// on map iteration in Go. -var errorModalVerb = sync.OnceValue(func() string { - for phrase := range map[string]struct{}{"cannot": {}, "unable to": {}} { - return phrase // use whichever phrase we get in the first iteration - } - return "" -}) - -func (e *SemanticError) Error() string { - var sb strings.Builder - sb.WriteString(errorPrefix) - sb.WriteString(errorModalVerb()) - - // Format action. - var preposition string - switch e.action { - case "marshal": - sb.WriteString(" marshal") - preposition = " from" - case "unmarshal": - sb.WriteString(" unmarshal") - preposition = " into" - default: - sb.WriteString(" handle") - preposition = " with" - } - - // Format JSON kind. - switch e.JSONKind { - case 'n': - sb.WriteString(" JSON null") - case 'f', 't': - sb.WriteString(" JSON boolean") - case '"': - sb.WriteString(" JSON string") - case '0': - sb.WriteString(" JSON number") - case '{', '}': - sb.WriteString(" JSON object") - case '[', ']': - sb.WriteString(" JSON array") - default: - if e.action == "" { - preposition = "" - } - } - if len(e.JSONValue) > 0 && len(e.JSONValue) < 100 { - sb.WriteByte(' ') - sb.Write(e.JSONValue) - } - - // Format Go type. - if e.GoType != nil { - typeString := e.GoType.String() - if len(typeString) > 100 { - // An excessively long type string most likely occurs for - // an anonymous struct declaration with many fields. - // Reduce the noise by just printing the kind, - // and optionally prepending it with the package name - // if the struct happens to include an unexported field. - typeString = e.GoType.Kind().String() - if e.GoType.Kind() == reflect.Struct && e.GoType.Name() == "" { - for i := range e.GoType.NumField() { - if pkgPath := e.GoType.Field(i).PkgPath; pkgPath != "" { - typeString = pkgPath[strings.LastIndexByte(pkgPath, '/')+len("/"):] + ".struct" - break - } - } - } - } - sb.WriteString(preposition) - sb.WriteString(" Go ") - sb.WriteString(typeString) - } - - // Special handling for unknown names. - if e.Err == ErrUnknownName { - sb.WriteString(": ") - sb.WriteString(ErrUnknownName.Error()) - sb.WriteString(" ") - sb.WriteString(strconv.Quote(e.JSONPointer.LastToken())) - if parent := e.JSONPointer.Parent(); parent != "" { - sb.WriteString(" within ") - sb.WriteString(strconv.Quote(jsonwire.TruncatePointer(string(parent), 100))) - } - return sb.String() - } - - // Format where. - // Avoid printing if it overlaps with a wrapped SyntacticError. - switch serr, _ := e.Err.(*jsontext.SyntacticError); { - case e.JSONPointer != "": - if serr == nil || !e.JSONPointer.Contains(serr.JSONPointer) { - sb.WriteString(" within ") - sb.WriteString(strconv.Quote(jsonwire.TruncatePointer(string(e.JSONPointer), 100))) - } - case e.ByteOffset > 0: - if serr == nil || !(e.ByteOffset <= serr.ByteOffset) { - sb.WriteString(" after offset ") - sb.WriteString(strconv.FormatInt(e.ByteOffset, 10)) - } - } - - // Format underlying error. - if e.Err != nil { - errString := e.Err.Error() - if isSyntacticError(e.Err) { - errString = strings.TrimPrefix(errString, "jsontext: ") - } - sb.WriteString(": ") - sb.WriteString(errString) - } - - return sb.String() -} - -func (e *SemanticError) Unwrap() error { - return e.Err -} - -func newDuplicateNameError(ptr jsontext.Pointer, quotedName []byte, offset int64) error { - if quotedName != nil { - name, _ := jsonwire.AppendUnquote(nil, quotedName) - ptr = ptr.AppendToken(string(name)) - } - return &jsontext.SyntacticError{ - ByteOffset: offset, - JSONPointer: ptr, - Err: jsontext.ErrDuplicateName, - } -} diff --git a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/fields.go b/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/fields.go deleted file mode 100644 index d539feedd..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/fields.go +++ /dev/null @@ -1,652 +0,0 @@ -// Copyright 2021 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package json - -import ( - "cmp" - "errors" - "fmt" - "io" - "reflect" - "slices" - "strconv" - "strings" - "unicode" - "unicode/utf8" - - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonflags" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonwire" -) - -type isZeroer interface { - IsZero() bool -} - -var isZeroerType = reflect.TypeFor[isZeroer]() - -type structFields struct { - flattened []structField // listed in depth-first ordering - byActualName map[string]*structField - byFoldedName map[string][]*structField - inlinedFallback *structField -} - -// reindex recomputes index to avoid bounds check during runtime. -// -// During the construction of each [structField] in [makeStructFields], -// the index field is 0-indexed. However, before it returns, -// the 0th field is stored in index0 and index stores the remainder. -func (sf *structFields) reindex() { - reindex := func(f *structField) { - f.index0 = f.index[0] - f.index = f.index[1:] - if len(f.index) == 0 { - f.index = nil // avoid pinning the backing slice - } - } - for i := range sf.flattened { - reindex(&sf.flattened[i]) - } - if sf.inlinedFallback != nil { - reindex(sf.inlinedFallback) - } -} - -// lookupByFoldedName looks up name by a case-insensitive match -// that also ignores the presence of dashes and underscores. -func (fs *structFields) lookupByFoldedName(name []byte) []*structField { - return fs.byFoldedName[string(foldName(name))] -} - -type structField struct { - id int // unique numeric ID in breadth-first ordering - index0 int // 0th index into a struct according to [reflect.Type.FieldByIndex] - index []int // 1st index and remainder according to [reflect.Type.FieldByIndex] - typ reflect.Type - fncs *arshaler - isZero func(addressableValue) bool - isEmpty func(addressableValue) bool - fieldOptions -} - -var errNoExportedFields = errors.New("Go struct has no exported fields") - -func makeStructFields(root reflect.Type) (fs structFields, serr *SemanticError) { - orErrorf := func(serr *SemanticError, t reflect.Type, f string, a ...any) *SemanticError { - return cmp.Or(serr, &SemanticError{GoType: t, Err: fmt.Errorf(f, a...)}) - } - - // Setup a queue for a breath-first search. - var queueIndex int - type queueEntry struct { - typ reflect.Type - index []int - visitChildren bool // whether to recursively visit inlined field in this struct - } - queue := []queueEntry{{root, nil, true}} - seen := map[reflect.Type]bool{root: true} - - // Perform a breadth-first search over all reachable fields. - // This ensures that len(f.index) will be monotonically increasing. - var allFields, inlinedFallbacks []structField - for queueIndex < len(queue) { - qe := queue[queueIndex] - queueIndex++ - - t := qe.typ - inlinedFallbackIndex := -1 // index of last inlined fallback field in current struct - namesIndex := make(map[string]int) // index of each field with a given JSON object name in current struct - var hasAnyJSONTag bool // whether any Go struct field has a `json` tag - var hasAnyJSONField bool // whether any JSON serializable fields exist in current struct - for i := range t.NumField() { - sf := t.Field(i) - _, hasTag := sf.Tag.Lookup("json") - hasAnyJSONTag = hasAnyJSONTag || hasTag - options, ignored, err := parseFieldOptions(sf) - if err != nil { - serr = cmp.Or(serr, &SemanticError{GoType: t, Err: err}) - } - if ignored { - continue - } - hasAnyJSONField = true - f := structField{ - // Allocate a new slice (len=N+1) to hold both - // the parent index (len=N) and the current index (len=1). - // Do this to avoid clobbering the memory of the parent index. - index: append(append(make([]int, 0, len(qe.index)+1), qe.index...), i), - typ: sf.Type, - fieldOptions: options, - } - if sf.Anonymous && !f.hasName { - if indirectType(f.typ).Kind() != reflect.Struct { - serr = orErrorf(serr, t, "embedded Go struct field %s of non-struct type must be explicitly given a JSON name", sf.Name) - } else { - f.inline = true // implied by use of Go embedding without an explicit name - } - } - if f.inline || f.unknown { - // Handle an inlined field that serializes to/from - // zero or more JSON object members. - - switch f.fieldOptions { - case fieldOptions{name: f.name, quotedName: f.quotedName, inline: true}: - case fieldOptions{name: f.name, quotedName: f.quotedName, unknown: true}: - case fieldOptions{name: f.name, quotedName: f.quotedName, inline: true, unknown: true}: - serr = orErrorf(serr, t, "Go struct field %s cannot have both `inline` and `unknown` specified", sf.Name) - f.inline = false // let `unknown` take precedence - default: - serr = orErrorf(serr, t, "Go struct field %s cannot have any options other than `inline` or `unknown` specified", sf.Name) - if f.hasName { - continue // invalid inlined field; treat as ignored - } - f.fieldOptions = fieldOptions{name: f.name, quotedName: f.quotedName, inline: f.inline, unknown: f.unknown} - if f.inline && f.unknown { - f.inline = false // let `unknown` take precedence - } - } - - // Reject any types with custom serialization otherwise - // it becomes impossible to know what sub-fields to inline. - tf := indirectType(f.typ) - if implementsAny(tf, allMethodTypes...) && tf != jsontextValueType { - serr = orErrorf(serr, t, "inlined Go struct field %s of type %s must not implement marshal or unmarshal methods", sf.Name, tf) - } - - // Handle an inlined field that serializes to/from - // a finite number of JSON object members backed by a Go struct. - if tf.Kind() == reflect.Struct { - if f.unknown { - serr = orErrorf(serr, t, "inlined Go struct field %s of type %s with `unknown` tag must be a Go map of string key or a jsontext.Value", sf.Name, tf) - continue // invalid inlined field; treat as ignored - } - if qe.visitChildren { - queue = append(queue, queueEntry{tf, f.index, !seen[tf]}) - } - seen[tf] = true - continue - } else if !sf.IsExported() { - serr = orErrorf(serr, t, "inlined Go struct field %s is not exported", sf.Name) - continue // invalid inlined field; treat as ignored - } - - // Handle an inlined field that serializes to/from any number of - // JSON object members back by a Go map or jsontext.Value. - switch { - case tf == jsontextValueType: - f.fncs = nil // specially handled in arshal_inlined.go - case tf.Kind() == reflect.Map && tf.Key().Kind() == reflect.String: - if implementsAny(tf.Key(), allMethodTypes...) { - serr = orErrorf(serr, t, "inlined map field %s of type %s must have a string key that does not implement marshal or unmarshal methods", sf.Name, tf) - continue // invalid inlined field; treat as ignored - } - f.fncs = lookupArshaler(tf.Elem()) - default: - serr = orErrorf(serr, t, "inlined Go struct field %s of type %s must be a Go struct, Go map of string key, or jsontext.Value", sf.Name, tf) - continue // invalid inlined field; treat as ignored - } - - // Reject multiple inlined fallback fields within the same struct. - if inlinedFallbackIndex >= 0 { - serr = orErrorf(serr, t, "inlined Go struct fields %s and %s cannot both be a Go map or jsontext.Value", t.Field(inlinedFallbackIndex).Name, sf.Name) - // Still append f to inlinedFallbacks as there is still a - // check for a dominant inlined fallback before returning. - } - inlinedFallbackIndex = i - - inlinedFallbacks = append(inlinedFallbacks, f) - } else { - // Handle normal Go struct field that serializes to/from - // a single JSON object member. - - // Unexported fields cannot be serialized except for - // embedded fields of a struct type, - // which might promote exported fields of their own. - if !sf.IsExported() { - tf := indirectType(f.typ) - if !(sf.Anonymous && tf.Kind() == reflect.Struct) { - serr = orErrorf(serr, t, "Go struct field %s is not exported", sf.Name) - continue - } - // Unfortunately, methods on the unexported field - // still cannot be called. - if implementsAny(tf, allMethodTypes...) || - (f.omitzero && implementsAny(tf, isZeroerType)) { - serr = orErrorf(serr, t, "Go struct field %s is not exported for method calls", sf.Name) - continue - } - } - - // Provide a function that uses a type's IsZero method. - switch { - case sf.Type.Kind() == reflect.Interface && sf.Type.Implements(isZeroerType): - f.isZero = func(va addressableValue) bool { - // Avoid panics calling IsZero on a nil interface or - // non-nil interface with nil pointer. - return va.IsNil() || (va.Elem().Kind() == reflect.Pointer && va.Elem().IsNil()) || va.Interface().(isZeroer).IsZero() - } - case sf.Type.Kind() == reflect.Pointer && sf.Type.Implements(isZeroerType): - f.isZero = func(va addressableValue) bool { - // Avoid panics calling IsZero on nil pointer. - return va.IsNil() || va.Interface().(isZeroer).IsZero() - } - case sf.Type.Implements(isZeroerType): - f.isZero = func(va addressableValue) bool { return va.Interface().(isZeroer).IsZero() } - case reflect.PointerTo(sf.Type).Implements(isZeroerType): - f.isZero = func(va addressableValue) bool { return va.Addr().Interface().(isZeroer).IsZero() } - } - - // Provide a function that can determine whether the value would - // serialize as an empty JSON value. - switch sf.Type.Kind() { - case reflect.String, reflect.Map, reflect.Array, reflect.Slice: - f.isEmpty = func(va addressableValue) bool { return va.Len() == 0 } - case reflect.Pointer, reflect.Interface: - f.isEmpty = func(va addressableValue) bool { return va.IsNil() } - } - - // Reject multiple fields with same name within the same struct. - if j, ok := namesIndex[f.name]; ok { - serr = orErrorf(serr, t, "Go struct fields %s and %s conflict over JSON object name %q", t.Field(j).Name, sf.Name, f.name) - // Still append f to allFields as there is still a - // check for a dominant field before returning. - } - namesIndex[f.name] = i - - f.id = len(allFields) - f.fncs = lookupArshaler(sf.Type) - allFields = append(allFields, f) - } - } - - // NOTE: New users to the json package are occasionally surprised that - // unexported fields are ignored. This occurs by necessity due to our - // inability to directly introspect such fields with Go reflection - // without the use of unsafe. - // - // To reduce friction here, refuse to serialize any Go struct that - // has no JSON serializable fields, has at least one Go struct field, - // and does not have any `json` tags present. For example, - // errors returned by errors.New would fail to serialize. - isEmptyStruct := t.NumField() == 0 - if !isEmptyStruct && !hasAnyJSONTag && !hasAnyJSONField { - serr = cmp.Or(serr, &SemanticError{GoType: t, Err: errNoExportedFields}) - } - } - - // Sort the fields by exact name (breaking ties by depth and - // then by presence of an explicitly provided JSON name). - // Select the dominant field from each set of fields with the same name. - // If multiple fields have the same name, then the dominant field - // is the one that exists alone at the shallowest depth, - // or the one that is uniquely tagged with a JSON name. - // Otherwise, no dominant field exists for the set. - flattened := allFields[:0] - slices.SortStableFunc(allFields, func(x, y structField) int { - return cmp.Or( - strings.Compare(x.name, y.name), - cmp.Compare(len(x.index), len(y.index)), - boolsCompare(!x.hasName, !y.hasName)) - }) - for len(allFields) > 0 { - n := 1 // number of fields with the same exact name - for n < len(allFields) && allFields[n-1].name == allFields[n].name { - n++ - } - if n == 1 || len(allFields[0].index) != len(allFields[1].index) || allFields[0].hasName != allFields[1].hasName { - flattened = append(flattened, allFields[0]) // only keep field if there is a dominant field - } - allFields = allFields[n:] - } - - // Sort the fields according to a breadth-first ordering - // so that we can re-number IDs with the smallest possible values. - // This optimizes use of uintSet such that it fits in the 64-entry bit set. - slices.SortFunc(flattened, func(x, y structField) int { - return cmp.Compare(x.id, y.id) - }) - for i := range flattened { - flattened[i].id = i - } - - // Sort the fields according to a depth-first ordering - // as the typical order that fields are marshaled. - slices.SortFunc(flattened, func(x, y structField) int { - return slices.Compare(x.index, y.index) - }) - - // Compute the mapping of fields in the byActualName map. - // Pre-fold all names so that we can lookup folded names quickly. - fs = structFields{ - flattened: flattened, - byActualName: make(map[string]*structField, len(flattened)), - byFoldedName: make(map[string][]*structField, len(flattened)), - } - for i, f := range fs.flattened { - foldedName := string(foldName([]byte(f.name))) - fs.byActualName[f.name] = &fs.flattened[i] - fs.byFoldedName[foldedName] = append(fs.byFoldedName[foldedName], &fs.flattened[i]) - } - for foldedName, fields := range fs.byFoldedName { - if len(fields) > 1 { - // The precedence order for conflicting ignoreCase names - // is by breadth-first order, rather than depth-first order. - slices.SortFunc(fields, func(x, y *structField) int { - return cmp.Compare(x.id, y.id) - }) - fs.byFoldedName[foldedName] = fields - } - } - if n := len(inlinedFallbacks); n == 1 || (n > 1 && len(inlinedFallbacks[0].index) != len(inlinedFallbacks[1].index)) { - fs.inlinedFallback = &inlinedFallbacks[0] // dominant inlined fallback field - } - fs.reindex() - return fs, serr -} - -// indirectType unwraps one level of pointer indirection -// similar to how Go only allows embedding either T or *T, -// but not **T or P (which is a named pointer). -func indirectType(t reflect.Type) reflect.Type { - if t.Kind() == reflect.Pointer && t.Name() == "" { - t = t.Elem() - } - return t -} - -// matchFoldedName matches a case-insensitive name depending on the options. -// It assumes that foldName(f.name) == foldName(name). -// -// Case-insensitive matching is used if the `case:ignore` tag option is specified -// or the MatchCaseInsensitiveNames call option is specified -// (and the `case:strict` tag option is not specified). -// Functionally, the `case:ignore` and `case:strict` tag options take precedence. -// -// The v1 definition of case-insensitivity operated under strings.EqualFold -// and would strictly compare dashes and underscores, -// while the v2 definition would ignore the presence of dashes and underscores. -// Thus, if the MatchCaseSensitiveDelimiter call option is specified, -// the match is further restricted to using strings.EqualFold. -func (f *structField) matchFoldedName(name []byte, flags *jsonflags.Flags) bool { - if f.casing == caseIgnore || (flags.Get(jsonflags.MatchCaseInsensitiveNames) && f.casing != caseStrict) { - if !flags.Get(jsonflags.MatchCaseSensitiveDelimiter) || strings.EqualFold(string(name), f.name) { - return true - } - } - return false -} - -const ( - caseIgnore = 1 - caseStrict = 2 -) - -type fieldOptions struct { - name string - quotedName string // quoted name per RFC 8785, section 3.2.2.2. - hasName bool - nameNeedEscape bool - casing int8 // either 0, caseIgnore, or caseStrict - inline bool - unknown bool - omitzero bool - omitempty bool - string bool - format string -} - -// parseFieldOptions parses the `json` tag in a Go struct field as -// a structured set of options configuring parameters such as -// the JSON member name and other features. -func parseFieldOptions(sf reflect.StructField) (out fieldOptions, ignored bool, err error) { - tag, hasTag := sf.Tag.Lookup("json") - tagOrig := tag - - // Check whether this field is explicitly ignored. - if tag == "-" { - return fieldOptions{}, true, nil - } - - // Check whether this field is unexported and not embedded, - // which Go reflection cannot mutate for the sake of serialization. - // - // An embedded field of an unexported type is still capable of - // forwarding exported fields, which may be JSON serialized. - // This technically operates on the edge of what is permissible by - // the Go language, but the most recent decision is to permit this. - // - // See https://go.dev/issue/24153 and https://go.dev/issue/32772. - if !sf.IsExported() && !sf.Anonymous { - // Tag options specified on an unexported field suggests user error. - if hasTag { - err = cmp.Or(err, fmt.Errorf("unexported Go struct field %s cannot have non-ignored `json:%q` tag", sf.Name, tag)) - } - return fieldOptions{}, true, err - } - - // Determine the JSON member name for this Go field. A user-specified name - // may be provided as either an identifier or a single-quoted string. - // The single-quoted string allows arbitrary characters in the name. - // See https://go.dev/issue/2718 and https://go.dev/issue/3546. - out.name = sf.Name // always starts with an uppercase character - if len(tag) > 0 && !strings.HasPrefix(tag, ",") { - // For better compatibility with v1, accept almost any unescaped name. - n := len(tag) - len(strings.TrimLeftFunc(tag, func(r rune) bool { - return !strings.ContainsRune(",\\'\"`", r) // reserve comma, backslash, and quotes - })) - name := tag[:n] - - // If the next character is not a comma, then the name is either - // malformed (if n > 0) or a single-quoted name. - // In either case, call consumeTagOption to handle it further. - var err2 error - if !strings.HasPrefix(tag[n:], ",") && len(name) != len(tag) { - name, n, err2 = consumeTagOption(tag) - if err2 != nil { - err = cmp.Or(err, fmt.Errorf("Go struct field %s has malformed `json` tag: %v", sf.Name, err2)) - } - } - if !utf8.ValidString(name) { - err = cmp.Or(err, fmt.Errorf("Go struct field %s has JSON object name %q with invalid UTF-8", sf.Name, name)) - name = string([]rune(name)) // replace invalid UTF-8 with utf8.RuneError - } - if name == "-" && tag[0] == '-' { - defer func() { // defer to let other errors take precedence - err = cmp.Or(err, fmt.Errorf("Go struct field %s has JSON object name %q; either "+ - "use `json:\"-\"` to ignore the field or "+ - "use `json:\"'-'%s` to specify %q as the name", sf.Name, out.name, strings.TrimPrefix(strconv.Quote(tagOrig), `"-`), name)) - }() - } - if err2 == nil { - out.hasName = true - out.name = name - } - tag = tag[n:] - } - b, _ := jsonwire.AppendQuote(nil, out.name, &jsonflags.Flags{}) - out.quotedName = string(b) - out.nameNeedEscape = jsonwire.NeedEscape(out.name) - - // Handle any additional tag options (if any). - var wasFormat bool - seenOpts := make(map[string]bool) - for len(tag) > 0 { - // Consume comma delimiter. - if tag[0] != ',' { - err = cmp.Or(err, fmt.Errorf("Go struct field %s has malformed `json` tag: invalid character %q before next option (expecting ',')", sf.Name, tag[0])) - } else { - tag = tag[len(","):] - if len(tag) == 0 { - err = cmp.Or(err, fmt.Errorf("Go struct field %s has malformed `json` tag: invalid trailing ',' character", sf.Name)) - break - } - } - - // Consume and process the tag option. - opt, n, err2 := consumeTagOption(tag) - if err2 != nil { - err = cmp.Or(err, fmt.Errorf("Go struct field %s has malformed `json` tag: %v", sf.Name, err2)) - } - rawOpt := tag[:n] - tag = tag[n:] - switch { - case wasFormat: - err = cmp.Or(err, fmt.Errorf("Go struct field %s has `format` tag option that was not specified last", sf.Name)) - case strings.HasPrefix(rawOpt, "'") && strings.TrimFunc(opt, isLetterOrDigit) == "": - err = cmp.Or(err, fmt.Errorf("Go struct field %s has unnecessarily quoted appearance of `%s` tag option; specify `%s` instead", sf.Name, rawOpt, opt)) - } - switch opt { - case "case": - if !strings.HasPrefix(tag, ":") { - err = cmp.Or(err, fmt.Errorf("Go struct field %s is missing value for `case` tag option; specify `case:ignore` or `case:strict` instead", sf.Name)) - break - } - tag = tag[len(":"):] - opt, n, err2 := consumeTagOption(tag) - if err2 != nil { - err = cmp.Or(err, fmt.Errorf("Go struct field %s has malformed value for `case` tag option: %v", sf.Name, err2)) - break - } - rawOpt := tag[:n] - tag = tag[n:] - if strings.HasPrefix(rawOpt, "'") { - err = cmp.Or(err, fmt.Errorf("Go struct field %s has unnecessarily quoted appearance of `case:%s` tag option; specify `case:%s` instead", sf.Name, rawOpt, opt)) - } - switch opt { - case "ignore": - out.casing |= caseIgnore - case "strict": - out.casing |= caseStrict - default: - err = cmp.Or(err, fmt.Errorf("Go struct field %s has unknown `case:%s` tag value", sf.Name, rawOpt)) - } - case "inline": - out.inline = true - case "unknown": - out.unknown = true - case "omitzero": - out.omitzero = true - case "omitempty": - out.omitempty = true - case "string": - out.string = true - case "format": - if !strings.HasPrefix(tag, ":") { - err = cmp.Or(err, fmt.Errorf("Go struct field %s is missing value for `format` tag option", sf.Name)) - break - } - tag = tag[len(":"):] - opt, n, err2 := consumeTagOption(tag) - if err2 != nil { - err = cmp.Or(err, fmt.Errorf("Go struct field %s has malformed value for `format` tag option: %v", sf.Name, err2)) - break - } - tag = tag[n:] - out.format = opt - wasFormat = true - default: - // Reject keys that resemble one of the supported options. - // This catches invalid mutants such as "omitEmpty" or "omit_empty". - normOpt := strings.ReplaceAll(strings.ToLower(opt), "_", "") - switch normOpt { - case "case", "inline", "unknown", "omitzero", "omitempty", "string", "format": - err = cmp.Or(err, fmt.Errorf("Go struct field %s has invalid appearance of `%s` tag option; specify `%s` instead", sf.Name, opt, normOpt)) - } - - // NOTE: Everything else is ignored. This does not mean it is - // forward compatible to insert arbitrary tag options since - // a future version of this package may understand that tag. - } - - // Reject duplicates. - switch { - case out.casing == caseIgnore|caseStrict: - err = cmp.Or(err, fmt.Errorf("Go struct field %s cannot have both `case:ignore` and `case:strict` tag options", sf.Name)) - case seenOpts[opt]: - err = cmp.Or(err, fmt.Errorf("Go struct field %s has duplicate appearance of `%s` tag option", sf.Name, rawOpt)) - } - seenOpts[opt] = true - } - return out, false, err -} - -// consumeTagOption consumes the next option, -// which is either a Go identifier or a single-quoted string. -// If the next option is invalid, it returns all of in until the next comma, -// and reports an error. -func consumeTagOption(in string) (string, int, error) { - // For legacy compatibility with v1, assume options are comma-separated. - i := strings.IndexByte(in, ',') - if i < 0 { - i = len(in) - } - - switch r, _ := utf8.DecodeRuneInString(in); { - // Option as a Go identifier. - case r == '_' || unicode.IsLetter(r): - n := len(in) - len(strings.TrimLeftFunc(in, isLetterOrDigit)) - return in[:n], n, nil - // Option as a single-quoted string. - case r == '\'': - // The grammar is nearly identical to a double-quoted Go string literal, - // but uses single quotes as the terminators. The reason for a custom - // grammar is because both backtick and double quotes cannot be used - // verbatim in a struct tag. - // - // Convert a single-quoted string to a double-quote string and rely on - // strconv.Unquote to handle the rest. - var inEscape bool - b := []byte{'"'} - n := len(`'`) - for len(in) > n { - r, rn := utf8.DecodeRuneInString(in[n:]) - switch { - case inEscape: - if r == '\'' { - b = b[:len(b)-1] // remove escape character: `\'` => `'` - } - inEscape = false - case r == '\\': - inEscape = true - case r == '"': - b = append(b, '\\') // insert escape character: `"` => `\"` - case r == '\'': - b = append(b, '"') - n += len(`'`) - out, err := strconv.Unquote(string(b)) - if err != nil { - return in[:i], i, fmt.Errorf("invalid single-quoted string: %s", in[:n]) - } - return out, n, nil - } - b = append(b, in[n:][:rn]...) - n += rn - } - if n > 10 { - n = 10 // limit the amount of context printed in the error - } - return in[:i], i, fmt.Errorf("single-quoted string not terminated: %s...", in[:n]) - case len(in) == 0: - return in[:i], i, io.ErrUnexpectedEOF - default: - return in[:i], i, fmt.Errorf("invalid character %q at start of option (expecting Unicode letter or single quote)", r) - } -} - -func isLetterOrDigit(r rune) bool { - return r == '_' || unicode.IsLetter(r) || unicode.IsNumber(r) -} - -// boolsCompare compares x and y, ordering false before true. -func boolsCompare(x, y bool) int { - switch { - case !x && y: - return -1 - default: - return 0 - case x && !y: - return +1 - } -} diff --git a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/fold.go b/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/fold.go deleted file mode 100644 index 9ab735814..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/fold.go +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package json - -import ( - "unicode" - "unicode/utf8" -) - -// foldName returns a folded string such that foldName(x) == foldName(y) -// is similar to strings.EqualFold(x, y), but ignores underscore and dashes. -// This allows foldName to match common naming conventions. -func foldName(in []byte) []byte { - // This is inlinable to take advantage of "function outlining". - // See https://blog.filippo.io/efficient-go-apis-with-the-inliner/ - var arr [32]byte // large enough for most JSON names - return appendFoldedName(arr[:0], in) -} -func appendFoldedName(out, in []byte) []byte { - for i := 0; i < len(in); { - // Handle single-byte ASCII. - if c := in[i]; c < utf8.RuneSelf { - if c != '_' && c != '-' { - if 'a' <= c && c <= 'z' { - c -= 'a' - 'A' - } - out = append(out, c) - } - i++ - continue - } - // Handle multi-byte Unicode. - r, n := utf8.DecodeRune(in[i:]) - out = utf8.AppendRune(out, foldRune(r)) - i += n - } - return out -} - -// foldRune is a variation on unicode.SimpleFold that returns the same rune -// for all runes in the same fold set. -// -// Invariant: -// -// foldRune(x) == foldRune(y) ⇔ strings.EqualFold(string(x), string(y)) -func foldRune(r rune) rune { - for { - r2 := unicode.SimpleFold(r) - if r2 <= r { - return r2 // smallest character in the fold set - } - r = r2 - } -} diff --git a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/intern.go b/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/intern.go deleted file mode 100644 index 42fc3d471..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/intern.go +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package json - -import ( - "encoding/binary" - "math/bits" -) - -// stringCache is a cache for strings converted from a []byte. -type stringCache = [256]string // 256*unsafe.Sizeof(string("")) => 4KiB - -// makeString returns the string form of b. -// It returns a pre-allocated string from c if present, otherwise -// it allocates a new string, inserts it into the cache, and returns it. -func makeString(c *stringCache, b []byte) string { - const ( - minCachedLen = 2 // single byte strings are already interned by the runtime - maxCachedLen = 256 // large enough for UUIDs, IPv6 addresses, SHA-256 checksums, etc. - ) - if c == nil || len(b) < minCachedLen || len(b) > maxCachedLen { - return string(b) - } - - // Compute a hash from the fixed-width prefix and suffix of the string. - // This ensures hashing a string is a constant time operation. - var h uint32 - switch { - case len(b) >= 8: - lo := binary.LittleEndian.Uint64(b[:8]) - hi := binary.LittleEndian.Uint64(b[len(b)-8:]) - h = hash64(uint32(lo), uint32(lo>>32)) ^ hash64(uint32(hi), uint32(hi>>32)) - case len(b) >= 4: - lo := binary.LittleEndian.Uint32(b[:4]) - hi := binary.LittleEndian.Uint32(b[len(b)-4:]) - h = hash64(lo, hi) - case len(b) >= 2: - lo := binary.LittleEndian.Uint16(b[:2]) - hi := binary.LittleEndian.Uint16(b[len(b)-2:]) - h = hash64(uint32(lo), uint32(hi)) - } - - // Check the cache for the string. - i := h % uint32(len(*c)) - if s := (*c)[i]; s == string(b) { - return s - } - s := string(b) - (*c)[i] = s - return s -} - -// hash64 returns the hash of two uint32s as a single uint32. -func hash64(lo, hi uint32) uint32 { - // If avalanche=true, this is identical to XXH32 hash on a 8B string: - // var b [8]byte - // binary.LittleEndian.PutUint32(b[:4], lo) - // binary.LittleEndian.PutUint32(b[4:], hi) - // return xxhash.Sum32(b[:]) - const ( - prime1 = 0x9e3779b1 - prime2 = 0x85ebca77 - prime3 = 0xc2b2ae3d - prime4 = 0x27d4eb2f - prime5 = 0x165667b1 - ) - h := prime5 + uint32(8) - h += lo * prime3 - h = bits.RotateLeft32(h, 17) * prime4 - h += hi * prime3 - h = bits.RotateLeft32(h, 17) * prime4 - // Skip final mix (avalanche) step of XXH32 for performance reasons. - // Empirical testing shows that the improvements in unbiased distribution - // does not outweigh the extra cost in computational complexity. - const avalanche = false - if avalanche { - h ^= h >> 15 - h *= prime2 - h ^= h >> 13 - h *= prime3 - h ^= h >> 16 - } - return h -} diff --git a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/internal.go b/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/internal.go deleted file mode 100644 index 05801c6b2..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/internal.go +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2023 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package internal - -import "errors" - -// NotForPublicUse is a marker type that an API is for internal use only. -// It does not perfectly prevent usage of that API, but helps to restrict usage. -// Anything with this marker is not covered by the Go compatibility agreement. -type NotForPublicUse struct{} - -// AllowInternalUse is passed from "json" to "jsontext" to authenticate -// that the caller can have access to internal functionality. -var AllowInternalUse NotForPublicUse - -// Sentinel error values internally shared between jsonv1 and jsonv2. -var ( - ErrCycle = errors.New("encountered a cycle") - ErrNonNilReference = errors.New("value must be passed as a non-nil pointer reference") - ErrNilInterface = errors.New("cannot derive concrete type for nil interface with finite type set") -) - -var ( - // TransformMarshalError converts a v2 error into a v1 error. - // It is called only at the top-level of a Marshal function. - TransformMarshalError func(any, error) error - // NewMarshalerError constructs a jsonv1.MarshalerError. - // It is called after a user-defined Marshal method/function fails. - NewMarshalerError func(any, error, string) error - // TransformUnmarshalError converts a v2 error into a v1 error. - // It is called only at the top-level of a Unmarshal function. - TransformUnmarshalError func(any, error) error - - // NewRawNumber returns new(jsonv1.Number). - NewRawNumber func() any - // RawNumberOf returns jsonv1.Number(b). - RawNumberOf func(b []byte) any -) diff --git a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonflags/flags.go b/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonflags/flags.go deleted file mode 100644 index 810128b51..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonflags/flags.go +++ /dev/null @@ -1,213 +0,0 @@ -// Copyright 2023 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// jsonflags implements all the optional boolean flags. -// These flags are shared across both "json", "jsontext", and "jsonopts". -package jsonflags - -import "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal" - -// Bools represents zero or more boolean flags, all set to true or false. -// The least-significant bit is the boolean value of all flags in the set. -// The remaining bits identify which particular flags. -// -// In common usage, this is OR'd with 0 or 1. For example: -// - (AllowInvalidUTF8 | 0) means "AllowInvalidUTF8 is false" -// - (Multiline | Indent | 1) means "Multiline and Indent are true" -type Bools uint64 - -func (Bools) JSONOptions(internal.NotForPublicUse) {} - -const ( - // AllFlags is the set of all flags. - AllFlags = AllCoderFlags | AllArshalV2Flags | AllArshalV1Flags - - // AllCoderFlags is the set of all encoder/decoder flags. - AllCoderFlags = (maxCoderFlag - 1) - initFlag - - // AllArshalV2Flags is the set of all v2 marshal/unmarshal flags. - AllArshalV2Flags = (maxArshalV2Flag - 1) - (maxCoderFlag - 1) - - // AllArshalV1Flags is the set of all v1 marshal/unmarshal flags. - AllArshalV1Flags = (maxArshalV1Flag - 1) - (maxArshalV2Flag - 1) - - // NonBooleanFlags is the set of non-boolean flags, - // where the value is some other concrete Go type. - // The value of the flag is stored within jsonopts.Struct. - NonBooleanFlags = 0 | - Indent | - IndentPrefix | - ByteLimit | - DepthLimit | - Marshalers | - Unmarshalers - - // DefaultV1Flags is the set of booleans flags that default to true under - // v1 semantics. None of the non-boolean flags differ between v1 and v2. - DefaultV1Flags = 0 | - AllowDuplicateNames | - AllowInvalidUTF8 | - EscapeForHTML | - EscapeForJS | - PreserveRawStrings | - Deterministic | - FormatNilMapAsNull | - FormatNilSliceAsNull | - MatchCaseInsensitiveNames | - CallMethodsWithLegacySemantics | - FormatByteArrayAsArray | - FormatBytesWithLegacySemantics | - FormatDurationAsNano | - MatchCaseSensitiveDelimiter | - MergeWithLegacySemantics | - OmitEmptyWithLegacySemantics | - ParseBytesWithLooseRFC4648 | - ParseTimeWithLooseRFC3339 | - ReportErrorsWithLegacySemantics | - StringifyWithLegacySemantics | - UnmarshalArrayFromAnyLength - - // AnyWhitespace reports whether the encoded output might have any whitespace. - AnyWhitespace = Multiline | SpaceAfterColon | SpaceAfterComma - - // WhitespaceFlags is the set of flags related to whitespace formatting. - // In contrast to AnyWhitespace, this includes Indent and IndentPrefix - // as those settings take no effect if Multiline is false. - WhitespaceFlags = AnyWhitespace | Indent | IndentPrefix - - // AnyEscape is the set of flags related to escaping in a JSON string. - AnyEscape = EscapeForHTML | EscapeForJS - - // CanonicalizeNumbers is the set of flags related to raw number canonicalization. - CanonicalizeNumbers = CanonicalizeRawInts | CanonicalizeRawFloats -) - -// Encoder and decoder flags. -const ( - initFlag Bools = 1 << iota // reserved for the boolean value itself - - AllowDuplicateNames // encode or decode - AllowInvalidUTF8 // encode or decode - WithinArshalCall // encode or decode; for internal use by json.Marshal and json.Unmarshal - OmitTopLevelNewline // encode only; for internal use by json.Marshal and json.MarshalWrite - PreserveRawStrings // encode only - CanonicalizeRawInts // encode only - CanonicalizeRawFloats // encode only - ReorderRawObjects // encode only - EscapeForHTML // encode only - EscapeForJS // encode only - Multiline // encode only - SpaceAfterColon // encode only - SpaceAfterComma // encode only - Indent // encode only; non-boolean flag - IndentPrefix // encode only; non-boolean flag - ByteLimit // encode or decode; non-boolean flag - DepthLimit // encode or decode; non-boolean flag - - maxCoderFlag -) - -// Marshal and Unmarshal flags (for v2). -const ( - _ Bools = (maxCoderFlag >> 1) << iota - - StringifyNumbers // marshal or unmarshal - Deterministic // marshal only - FormatNilMapAsNull // marshal only - FormatNilSliceAsNull // marshal only - OmitZeroStructFields // marshal only - MatchCaseInsensitiveNames // marshal or unmarshal - DiscardUnknownMembers // marshal only - RejectUnknownMembers // unmarshal only - Marshalers // marshal only; non-boolean flag - Unmarshalers // unmarshal only; non-boolean flag - - maxArshalV2Flag -) - -// Marshal and Unmarshal flags (for v1). -const ( - _ Bools = (maxArshalV2Flag >> 1) << iota - - CallMethodsWithLegacySemantics // marshal or unmarshal - FormatByteArrayAsArray // marshal or unmarshal - FormatBytesWithLegacySemantics // marshal or unmarshal - FormatDurationAsNano // marshal or unmarshal - MatchCaseSensitiveDelimiter // marshal or unmarshal - MergeWithLegacySemantics // unmarshal - OmitEmptyWithLegacySemantics // marshal - ParseBytesWithLooseRFC4648 // unmarshal - ParseTimeWithLooseRFC3339 // unmarshal - ReportErrorsWithLegacySemantics // marshal or unmarshal - StringifyWithLegacySemantics // marshal or unmarshal - StringifyBoolsAndStrings // marshal or unmarshal; for internal use by jsonv2.makeStructArshaler - UnmarshalAnyWithRawNumber // unmarshal; for internal use by jsonv1.Decoder.UseNumber - UnmarshalArrayFromAnyLength // unmarshal - - maxArshalV1Flag -) - -// bitsUsed is the number of bits used in the 64-bit boolean flags -const bitsUsed = 42 - -// Static compile check that bitsUsed and maxArshalV1Flag are in sync. -const _ = uint64((1< 0b_110_11011 - dst.Values &= ^src.Presence // e.g., 0b_1000_0011 & 0b_1010_0101 -> 0b_100_00001 - dst.Values |= src.Values // e.g., 0b_1000_0001 | 0b_1001_0010 -> 0b_100_10011 -} - -// Set sets both the presence and value for the provided bool (or set of bools). -func (fs *Flags) Set(f Bools) { - // Select out the bits for the flag identifiers (everything except LSB), - // then set the presence for all the identifier bits (using OR), - // then invert the identifier bits to clear out the values (using AND-NOT), - // then copy over all the identifier bits to the value if LSB is 1. - // e.g., fs := Flags{Presence: 0b_0101_0010, Value: 0b_0001_0010} - // e.g., f := 0b_1001_0001 - id := uint64(f) &^ uint64(1) // e.g., 0b_1001_0001 & 0b_1111_1110 -> 0b_1001_0000 - fs.Presence |= id // e.g., 0b_0101_0010 | 0b_1001_0000 -> 0b_1101_0011 - fs.Values &= ^id // e.g., 0b_0001_0010 & 0b_0110_1111 -> 0b_0000_0010 - fs.Values |= uint64(f&1) * id // e.g., 0b_0000_0010 | 0b_1001_0000 -> 0b_1001_0010 -} - -// Get reports whether the bool (or any of the bools) is true. -// This is generally only used with a singular bool. -// The value bit of f (i.e., the LSB) is ignored. -func (fs Flags) Get(f Bools) bool { - return fs.Values&uint64(f) > 0 -} - -// Has reports whether the bool (or any of the bools) is set. -// The value bit of f (i.e., the LSB) is ignored. -func (fs Flags) Has(f Bools) bool { - return fs.Presence&uint64(f) > 0 -} - -// Clear clears both the presence and value for the provided bool or bools. -// The value bit of f (i.e., the LSB) is ignored. -func (fs *Flags) Clear(f Bools) { - // Invert f to produce a mask to clear all bits in f (using AND). - // e.g., fs := Flags{Presence: 0b_0101_0010, Value: 0b_0001_0010} - // e.g., f := 0b_0001_1000 - mask := uint64(^f) // e.g., 0b_0001_1000 -> 0b_1110_0111 - fs.Presence &= mask // e.g., 0b_0101_0010 & 0b_1110_0111 -> 0b_0100_0010 - fs.Values &= mask // e.g., 0b_0001_0010 & 0b_1110_0111 -> 0b_0000_0010 -} diff --git a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonopts/options.go b/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonopts/options.go deleted file mode 100644 index 142653518..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonopts/options.go +++ /dev/null @@ -1,200 +0,0 @@ -// Copyright 2023 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package jsonopts - -import ( - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonflags" -) - -// Options is the common options type shared across json packages. -type Options interface { - // JSONOptions is exported so related json packages can implement Options. - JSONOptions(internal.NotForPublicUse) -} - -// Struct is the combination of all options in struct form. -// This is efficient to pass down the call stack and to query. -type Struct struct { - Flags jsonflags.Flags - - CoderValues - ArshalValues -} - -type CoderValues struct { - Indent string // jsonflags.Indent - IndentPrefix string // jsonflags.IndentPrefix - ByteLimit int64 // jsonflags.ByteLimit - DepthLimit int // jsonflags.DepthLimit -} - -type ArshalValues struct { - // The Marshalers and Unmarshalers fields use the any type to avoid a - // concrete dependency on *json.Marshalers and *json.Unmarshalers, - // which would in turn create a dependency on the "reflect" package. - - Marshalers any // jsonflags.Marshalers - Unmarshalers any // jsonflags.Unmarshalers - - Format string - FormatDepth int -} - -// DefaultOptionsV2 is the set of all options that define default v2 behavior. -var DefaultOptionsV2 = Struct{ - Flags: jsonflags.Flags{ - Presence: uint64(jsonflags.AllFlags & ^jsonflags.WhitespaceFlags), - Values: uint64(0), - }, -} - -// DefaultOptionsV1 is the set of all options that define default v1 behavior. -var DefaultOptionsV1 = Struct{ - Flags: jsonflags.Flags{ - Presence: uint64(jsonflags.AllFlags & ^jsonflags.WhitespaceFlags), - Values: uint64(jsonflags.DefaultV1Flags), - }, -} - -func (*Struct) JSONOptions(internal.NotForPublicUse) {} - -// GetUnknownOption is injected by the "json" package to handle Options -// declared in that package so that "jsonopts" can handle them. -var GetUnknownOption = func(Struct, Options) (any, bool) { panic("unknown option") } - -func GetOption[T any](opts Options, setter func(T) Options) (T, bool) { - // Collapse the options to *Struct to simplify lookup. - structOpts, ok := opts.(*Struct) - if !ok { - var structOpts2 Struct - structOpts2.Join(opts) - structOpts = &structOpts2 - } - - // Lookup the option based on the return value of the setter. - var zero T - switch opt := setter(zero).(type) { - case jsonflags.Bools: - v := structOpts.Flags.Get(opt) - ok := structOpts.Flags.Has(opt) - return any(v).(T), ok - case Indent: - if !structOpts.Flags.Has(jsonflags.Indent) { - return zero, false - } - return any(structOpts.Indent).(T), true - case IndentPrefix: - if !structOpts.Flags.Has(jsonflags.IndentPrefix) { - return zero, false - } - return any(structOpts.IndentPrefix).(T), true - case ByteLimit: - if !structOpts.Flags.Has(jsonflags.ByteLimit) { - return zero, false - } - return any(structOpts.ByteLimit).(T), true - case DepthLimit: - if !structOpts.Flags.Has(jsonflags.DepthLimit) { - return zero, false - } - return any(structOpts.DepthLimit).(T), true - default: - v, ok := GetUnknownOption(*structOpts, opt) - return v.(T), ok - } -} - -// JoinUnknownOption is injected by the "json" package to handle Options -// declared in that package so that "jsonopts" can handle them. -var JoinUnknownOption = func(Struct, Options) Struct { panic("unknown option") } - -func (dst *Struct) Join(srcs ...Options) { - dst.join(false, srcs...) -} - -func (dst *Struct) JoinWithoutCoderOptions(srcs ...Options) { - dst.join(true, srcs...) -} - -func (dst *Struct) join(excludeCoderOptions bool, srcs ...Options) { - for _, src := range srcs { - switch src := src.(type) { - case nil: - continue - case jsonflags.Bools: - if excludeCoderOptions { - src &= ^jsonflags.AllCoderFlags - } - dst.Flags.Set(src) - case Indent: - if excludeCoderOptions { - continue - } - dst.Flags.Set(jsonflags.Multiline | jsonflags.Indent | 1) - dst.Indent = string(src) - case IndentPrefix: - if excludeCoderOptions { - continue - } - dst.Flags.Set(jsonflags.Multiline | jsonflags.IndentPrefix | 1) - dst.IndentPrefix = string(src) - case ByteLimit: - if excludeCoderOptions { - continue - } - dst.Flags.Set(jsonflags.ByteLimit | 1) - dst.ByteLimit = int64(src) - case DepthLimit: - if excludeCoderOptions { - continue - } - dst.Flags.Set(jsonflags.DepthLimit | 1) - dst.DepthLimit = int(src) - case *Struct: - srcFlags := src.Flags // shallow copy the flags - if excludeCoderOptions { - srcFlags.Clear(jsonflags.AllCoderFlags) - } - dst.Flags.Join(srcFlags) - if srcFlags.Has(jsonflags.NonBooleanFlags) { - if srcFlags.Has(jsonflags.Indent) { - dst.Indent = src.Indent - } - if srcFlags.Has(jsonflags.IndentPrefix) { - dst.IndentPrefix = src.IndentPrefix - } - if srcFlags.Has(jsonflags.ByteLimit) { - dst.ByteLimit = src.ByteLimit - } - if srcFlags.Has(jsonflags.DepthLimit) { - dst.DepthLimit = src.DepthLimit - } - if srcFlags.Has(jsonflags.Marshalers) { - dst.Marshalers = src.Marshalers - } - if srcFlags.Has(jsonflags.Unmarshalers) { - dst.Unmarshalers = src.Unmarshalers - } - } - default: - *dst = JoinUnknownOption(*dst, src) - } - } -} - -type ( - Indent string // jsontext.WithIndent - IndentPrefix string // jsontext.WithIndentPrefix - ByteLimit int64 // jsontext.WithByteLimit - DepthLimit int // jsontext.WithDepthLimit - // type for jsonflags.Marshalers declared in "json" package - // type for jsonflags.Unmarshalers declared in "json" package -) - -func (Indent) JSONOptions(internal.NotForPublicUse) {} -func (IndentPrefix) JSONOptions(internal.NotForPublicUse) {} -func (ByteLimit) JSONOptions(internal.NotForPublicUse) {} -func (DepthLimit) JSONOptions(internal.NotForPublicUse) {} diff --git a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonwire/decode.go b/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonwire/decode.go deleted file mode 100644 index 02787719c..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonwire/decode.go +++ /dev/null @@ -1,627 +0,0 @@ -// Copyright 2023 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package jsonwire - -import ( - "io" - "math" - "slices" - "strconv" - "unicode/utf16" - "unicode/utf8" -) - -type ValueFlags uint - -const ( - _ ValueFlags = (1 << iota) / 2 // powers of two starting with zero - - stringNonVerbatim // string cannot be naively treated as valid UTF-8 - stringNonCanonical // string not formatted according to RFC 8785, section 3.2.2.2. - // TODO: Track whether a number is a non-integer? -) - -func (f *ValueFlags) Join(f2 ValueFlags) { *f |= f2 } -func (f ValueFlags) IsVerbatim() bool { return f&stringNonVerbatim == 0 } -func (f ValueFlags) IsCanonical() bool { return f&stringNonCanonical == 0 } - -// ConsumeWhitespace consumes leading JSON whitespace per RFC 7159, section 2. -func ConsumeWhitespace(b []byte) (n int) { - // NOTE: The arguments and logic are kept simple to keep this inlinable. - for len(b) > n && (b[n] == ' ' || b[n] == '\t' || b[n] == '\r' || b[n] == '\n') { - n++ - } - return n -} - -// ConsumeNull consumes the next JSON null literal per RFC 7159, section 3. -// It returns 0 if it is invalid, in which case consumeLiteral should be used. -func ConsumeNull(b []byte) int { - // NOTE: The arguments and logic are kept simple to keep this inlinable. - const literal = "null" - if len(b) >= len(literal) && string(b[:len(literal)]) == literal { - return len(literal) - } - return 0 -} - -// ConsumeFalse consumes the next JSON false literal per RFC 7159, section 3. -// It returns 0 if it is invalid, in which case consumeLiteral should be used. -func ConsumeFalse(b []byte) int { - // NOTE: The arguments and logic are kept simple to keep this inlinable. - const literal = "false" - if len(b) >= len(literal) && string(b[:len(literal)]) == literal { - return len(literal) - } - return 0 -} - -// ConsumeTrue consumes the next JSON true literal per RFC 7159, section 3. -// It returns 0 if it is invalid, in which case consumeLiteral should be used. -func ConsumeTrue(b []byte) int { - // NOTE: The arguments and logic are kept simple to keep this inlinable. - const literal = "true" - if len(b) >= len(literal) && string(b[:len(literal)]) == literal { - return len(literal) - } - return 0 -} - -// ConsumeLiteral consumes the next JSON literal per RFC 7159, section 3. -// If the input appears truncated, it returns io.ErrUnexpectedEOF. -func ConsumeLiteral(b []byte, lit string) (n int, err error) { - for i := 0; i < len(b) && i < len(lit); i++ { - if b[i] != lit[i] { - return i, NewInvalidCharacterError(b[i:], "in literal "+lit+" (expecting "+strconv.QuoteRune(rune(lit[i]))+")") - } - } - if len(b) < len(lit) { - return len(b), io.ErrUnexpectedEOF - } - return len(lit), nil -} - -// ConsumeSimpleString consumes the next JSON string per RFC 7159, section 7 -// but is limited to the grammar for an ASCII string without escape sequences. -// It returns 0 if it is invalid or more complicated than a simple string, -// in which case consumeString should be called. -// -// It rejects '<', '>', and '&' for compatibility reasons since these were -// always escaped in the v1 implementation. Thus, if this function reports -// non-zero then we know that the string would be encoded the same way -// under both v1 or v2 escape semantics. -func ConsumeSimpleString(b []byte) (n int) { - // NOTE: The arguments and logic are kept simple to keep this inlinable. - if len(b) > 0 && b[0] == '"' { - n++ - for len(b) > n && b[n] < utf8.RuneSelf && escapeASCII[b[n]] == 0 { - n++ - } - if uint(len(b)) > uint(n) && b[n] == '"' { - n++ - return n - } - } - return 0 -} - -// ConsumeString consumes the next JSON string per RFC 7159, section 7. -// If validateUTF8 is false, then this allows the presence of invalid UTF-8 -// characters within the string itself. -// It reports the number of bytes consumed and whether an error was encountered. -// If the input appears truncated, it returns io.ErrUnexpectedEOF. -func ConsumeString(flags *ValueFlags, b []byte, validateUTF8 bool) (n int, err error) { - return ConsumeStringResumable(flags, b, 0, validateUTF8) -} - -// ConsumeStringResumable is identical to consumeString but supports resuming -// from a previous call that returned io.ErrUnexpectedEOF. -func ConsumeStringResumable(flags *ValueFlags, b []byte, resumeOffset int, validateUTF8 bool) (n int, err error) { - // Consume the leading double quote. - switch { - case resumeOffset > 0: - n = resumeOffset // already handled the leading quote - case uint(len(b)) == 0: - return n, io.ErrUnexpectedEOF - case b[0] == '"': - n++ - default: - return n, NewInvalidCharacterError(b[n:], `at start of string (expecting '"')`) - } - - // Consume every character in the string. - for uint(len(b)) > uint(n) { - // Optimize for long sequences of unescaped characters. - noEscape := func(c byte) bool { - return c < utf8.RuneSelf && ' ' <= c && c != '\\' && c != '"' - } - for uint(len(b)) > uint(n) && noEscape(b[n]) { - n++ - } - if uint(len(b)) <= uint(n) { - return n, io.ErrUnexpectedEOF - } - - // Check for terminating double quote. - if b[n] == '"' { - n++ - return n, nil - } - - switch r, rn := utf8.DecodeRune(b[n:]); { - // Handle UTF-8 encoded byte sequence. - // Due to specialized handling of ASCII above, we know that - // all normal sequences at this point must be 2 bytes or larger. - case rn > 1: - n += rn - // Handle escape sequence. - case r == '\\': - flags.Join(stringNonVerbatim) - resumeOffset = n - if uint(len(b)) < uint(n+2) { - return resumeOffset, io.ErrUnexpectedEOF - } - switch r := b[n+1]; r { - case '/': - // Forward slash is the only character with 3 representations. - // Per RFC 8785, section 3.2.2.2., this must not be escaped. - flags.Join(stringNonCanonical) - n += 2 - case '"', '\\', 'b', 'f', 'n', 'r', 't': - n += 2 - case 'u': - if uint(len(b)) < uint(n+6) { - if hasEscapedUTF16Prefix(b[n:], false) { - return resumeOffset, io.ErrUnexpectedEOF - } - flags.Join(stringNonCanonical) - return n, NewInvalidEscapeSequenceError(b[n:]) - } - v1, ok := parseHexUint16(b[n+2 : n+6]) - if !ok { - flags.Join(stringNonCanonical) - return n, NewInvalidEscapeSequenceError(b[n : n+6]) - } - // Only certain control characters can use the \uFFFF notation - // for canonical formatting (per RFC 8785, section 3.2.2.2.). - switch v1 { - // \uFFFF notation not permitted for these characters. - case '\b', '\f', '\n', '\r', '\t': - flags.Join(stringNonCanonical) - default: - // \uFFFF notation only permitted for control characters. - if v1 >= ' ' { - flags.Join(stringNonCanonical) - } else { - // \uFFFF notation must be lower case. - for _, c := range b[n+2 : n+6] { - if 'A' <= c && c <= 'F' { - flags.Join(stringNonCanonical) - } - } - } - } - n += 6 - - r := rune(v1) - if validateUTF8 && utf16.IsSurrogate(r) { - if uint(len(b)) < uint(n+6) { - if hasEscapedUTF16Prefix(b[n:], true) { - return resumeOffset, io.ErrUnexpectedEOF - } - flags.Join(stringNonCanonical) - return n - 6, NewInvalidEscapeSequenceError(b[n-6:]) - } else if v2, ok := parseHexUint16(b[n+2 : n+6]); b[n] != '\\' || b[n+1] != 'u' || !ok { - flags.Join(stringNonCanonical) - return n - 6, NewInvalidEscapeSequenceError(b[n-6 : n+6]) - } else if r = utf16.DecodeRune(rune(v1), rune(v2)); r == utf8.RuneError { - flags.Join(stringNonCanonical) - return n - 6, NewInvalidEscapeSequenceError(b[n-6 : n+6]) - } else { - n += 6 - } - } - default: - flags.Join(stringNonCanonical) - return n, NewInvalidEscapeSequenceError(b[n : n+2]) - } - // Handle invalid UTF-8. - case r == utf8.RuneError: - if !utf8.FullRune(b[n:]) { - return n, io.ErrUnexpectedEOF - } - flags.Join(stringNonVerbatim | stringNonCanonical) - if validateUTF8 { - return n, ErrInvalidUTF8 - } - n++ - // Handle invalid control characters. - case r < ' ': - flags.Join(stringNonVerbatim | stringNonCanonical) - return n, NewInvalidCharacterError(b[n:], "in string (expecting non-control character)") - default: - panic("BUG: unhandled character " + QuoteRune(b[n:])) - } - } - return n, io.ErrUnexpectedEOF -} - -// AppendUnquote appends the unescaped form of a JSON string in src to dst. -// Any invalid UTF-8 within the string will be replaced with utf8.RuneError, -// but the error will be specified as having encountered such an error. -// The input must be an entire JSON string with no surrounding whitespace. -func AppendUnquote[Bytes ~[]byte | ~string](dst []byte, src Bytes) (v []byte, err error) { - dst = slices.Grow(dst, len(src)) - - // Consume the leading double quote. - var i, n int - switch { - case uint(len(src)) == 0: - return dst, io.ErrUnexpectedEOF - case src[0] == '"': - i, n = 1, 1 - default: - return dst, NewInvalidCharacterError(src, `at start of string (expecting '"')`) - } - - // Consume every character in the string. - for uint(len(src)) > uint(n) { - // Optimize for long sequences of unescaped characters. - noEscape := func(c byte) bool { - return c < utf8.RuneSelf && ' ' <= c && c != '\\' && c != '"' - } - for uint(len(src)) > uint(n) && noEscape(src[n]) { - n++ - } - if uint(len(src)) <= uint(n) { - dst = append(dst, src[i:n]...) - return dst, io.ErrUnexpectedEOF - } - - // Check for terminating double quote. - if src[n] == '"' { - dst = append(dst, src[i:n]...) - n++ - if n < len(src) { - err = NewInvalidCharacterError(src[n:], "after string value") - } - return dst, err - } - - switch r, rn := utf8.DecodeRuneInString(string(truncateMaxUTF8(src[n:]))); { - // Handle UTF-8 encoded byte sequence. - // Due to specialized handling of ASCII above, we know that - // all normal sequences at this point must be 2 bytes or larger. - case rn > 1: - n += rn - // Handle escape sequence. - case r == '\\': - dst = append(dst, src[i:n]...) - - // Handle escape sequence. - if uint(len(src)) < uint(n+2) { - return dst, io.ErrUnexpectedEOF - } - switch r := src[n+1]; r { - case '"', '\\', '/': - dst = append(dst, r) - n += 2 - case 'b': - dst = append(dst, '\b') - n += 2 - case 'f': - dst = append(dst, '\f') - n += 2 - case 'n': - dst = append(dst, '\n') - n += 2 - case 'r': - dst = append(dst, '\r') - n += 2 - case 't': - dst = append(dst, '\t') - n += 2 - case 'u': - if uint(len(src)) < uint(n+6) { - if hasEscapedUTF16Prefix(src[n:], false) { - return dst, io.ErrUnexpectedEOF - } - return dst, NewInvalidEscapeSequenceError(src[n:]) - } - v1, ok := parseHexUint16(src[n+2 : n+6]) - if !ok { - return dst, NewInvalidEscapeSequenceError(src[n : n+6]) - } - n += 6 - - // Check whether this is a surrogate half. - r := rune(v1) - if utf16.IsSurrogate(r) { - r = utf8.RuneError // assume failure unless the following succeeds - if uint(len(src)) < uint(n+6) { - if hasEscapedUTF16Prefix(src[n:], true) { - return utf8.AppendRune(dst, r), io.ErrUnexpectedEOF - } - err = NewInvalidEscapeSequenceError(src[n-6:]) - } else if v2, ok := parseHexUint16(src[n+2 : n+6]); src[n] != '\\' || src[n+1] != 'u' || !ok { - err = NewInvalidEscapeSequenceError(src[n-6 : n+6]) - } else if r = utf16.DecodeRune(rune(v1), rune(v2)); r == utf8.RuneError { - err = NewInvalidEscapeSequenceError(src[n-6 : n+6]) - } else { - n += 6 - } - } - - dst = utf8.AppendRune(dst, r) - default: - return dst, NewInvalidEscapeSequenceError(src[n : n+2]) - } - i = n - // Handle invalid UTF-8. - case r == utf8.RuneError: - dst = append(dst, src[i:n]...) - if !utf8.FullRuneInString(string(truncateMaxUTF8(src[n:]))) { - return dst, io.ErrUnexpectedEOF - } - // NOTE: An unescaped string may be longer than the escaped string - // because invalid UTF-8 bytes are being replaced. - dst = append(dst, "\uFFFD"...) - n += rn - i = n - err = ErrInvalidUTF8 - // Handle invalid control characters. - case r < ' ': - dst = append(dst, src[i:n]...) - return dst, NewInvalidCharacterError(src[n:], "in string (expecting non-control character)") - default: - panic("BUG: unhandled character " + QuoteRune(src[n:])) - } - } - dst = append(dst, src[i:n]...) - return dst, io.ErrUnexpectedEOF -} - -// hasEscapedUTF16Prefix reports whether b is possibly -// the truncated prefix of a \uFFFF escape sequence. -func hasEscapedUTF16Prefix[Bytes ~[]byte | ~string](b Bytes, lowerSurrogateHalf bool) bool { - for i := range len(b) { - switch c := b[i]; { - case i == 0 && c != '\\': - return false - case i == 1 && c != 'u': - return false - case i == 2 && lowerSurrogateHalf && c != 'd' && c != 'D': - return false // not within ['\uDC00':'\uDFFF'] - case i == 3 && lowerSurrogateHalf && !('c' <= c && c <= 'f') && !('C' <= c && c <= 'F'): - return false // not within ['\uDC00':'\uDFFF'] - case i >= 2 && i < 6 && !('0' <= c && c <= '9') && !('a' <= c && c <= 'f') && !('A' <= c && c <= 'F'): - return false - } - } - return true -} - -// UnquoteMayCopy returns the unescaped form of b. -// If there are no escaped characters, the output is simply a subslice of -// the input with the surrounding quotes removed. -// Otherwise, a new buffer is allocated for the output. -// It assumes the input is valid. -func UnquoteMayCopy(b []byte, isVerbatim bool) []byte { - // NOTE: The arguments and logic are kept simple to keep this inlinable. - if isVerbatim { - return b[len(`"`) : len(b)-len(`"`)] - } - b, _ = AppendUnquote(nil, b) - return b -} - -// ConsumeSimpleNumber consumes the next JSON number per RFC 7159, section 6 -// but is limited to the grammar for a positive integer. -// It returns 0 if it is invalid or more complicated than a simple integer, -// in which case consumeNumber should be called. -func ConsumeSimpleNumber(b []byte) (n int) { - // NOTE: The arguments and logic are kept simple to keep this inlinable. - if len(b) > 0 { - if b[0] == '0' { - n++ - } else if '1' <= b[0] && b[0] <= '9' { - n++ - for len(b) > n && ('0' <= b[n] && b[n] <= '9') { - n++ - } - } else { - return 0 - } - if uint(len(b)) <= uint(n) || (b[n] != '.' && b[n] != 'e' && b[n] != 'E') { - return n - } - } - return 0 -} - -type ConsumeNumberState uint - -const ( - consumeNumberInit ConsumeNumberState = iota - beforeIntegerDigits - withinIntegerDigits - beforeFractionalDigits - withinFractionalDigits - beforeExponentDigits - withinExponentDigits -) - -// ConsumeNumber consumes the next JSON number per RFC 7159, section 6. -// It reports the number of bytes consumed and whether an error was encountered. -// If the input appears truncated, it returns io.ErrUnexpectedEOF. -// -// Note that JSON numbers are not self-terminating. -// If the entire input is consumed, then the caller needs to consider whether -// there may be subsequent unread data that may still be part of this number. -func ConsumeNumber(b []byte) (n int, err error) { - n, _, err = ConsumeNumberResumable(b, 0, consumeNumberInit) - return n, err -} - -// ConsumeNumberResumable is identical to consumeNumber but supports resuming -// from a previous call that returned io.ErrUnexpectedEOF. -func ConsumeNumberResumable(b []byte, resumeOffset int, state ConsumeNumberState) (n int, _ ConsumeNumberState, err error) { - // Jump to the right state when resuming from a partial consumption. - n = resumeOffset - if state > consumeNumberInit { - switch state { - case withinIntegerDigits, withinFractionalDigits, withinExponentDigits: - // Consume leading digits. - for uint(len(b)) > uint(n) && ('0' <= b[n] && b[n] <= '9') { - n++ - } - if uint(len(b)) <= uint(n) { - return n, state, nil // still within the same state - } - state++ // switches "withinX" to "beforeY" where Y is the state after X - } - switch state { - case beforeIntegerDigits: - goto beforeInteger - case beforeFractionalDigits: - goto beforeFractional - case beforeExponentDigits: - goto beforeExponent - default: - return n, state, nil - } - } - - // Consume required integer component (with optional minus sign). -beforeInteger: - resumeOffset = n - if uint(len(b)) > 0 && b[0] == '-' { - n++ - } - switch { - case uint(len(b)) <= uint(n): - return resumeOffset, beforeIntegerDigits, io.ErrUnexpectedEOF - case b[n] == '0': - n++ - state = beforeFractionalDigits - case '1' <= b[n] && b[n] <= '9': - n++ - for uint(len(b)) > uint(n) && ('0' <= b[n] && b[n] <= '9') { - n++ - } - state = withinIntegerDigits - default: - return n, state, NewInvalidCharacterError(b[n:], "in number (expecting digit)") - } - - // Consume optional fractional component. -beforeFractional: - if uint(len(b)) > uint(n) && b[n] == '.' { - resumeOffset = n - n++ - switch { - case uint(len(b)) <= uint(n): - return resumeOffset, beforeFractionalDigits, io.ErrUnexpectedEOF - case '0' <= b[n] && b[n] <= '9': - n++ - default: - return n, state, NewInvalidCharacterError(b[n:], "in number (expecting digit)") - } - for uint(len(b)) > uint(n) && ('0' <= b[n] && b[n] <= '9') { - n++ - } - state = withinFractionalDigits - } - - // Consume optional exponent component. -beforeExponent: - if uint(len(b)) > uint(n) && (b[n] == 'e' || b[n] == 'E') { - resumeOffset = n - n++ - if uint(len(b)) > uint(n) && (b[n] == '-' || b[n] == '+') { - n++ - } - switch { - case uint(len(b)) <= uint(n): - return resumeOffset, beforeExponentDigits, io.ErrUnexpectedEOF - case '0' <= b[n] && b[n] <= '9': - n++ - default: - return n, state, NewInvalidCharacterError(b[n:], "in number (expecting digit)") - } - for uint(len(b)) > uint(n) && ('0' <= b[n] && b[n] <= '9') { - n++ - } - state = withinExponentDigits - } - - return n, state, nil -} - -// parseHexUint16 is similar to strconv.ParseUint, -// but operates directly on []byte and is optimized for base-16. -// See https://go.dev/issue/42429. -func parseHexUint16[Bytes ~[]byte | ~string](b Bytes) (v uint16, ok bool) { - if len(b) != 4 { - return 0, false - } - for i := range 4 { - c := b[i] - switch { - case '0' <= c && c <= '9': - c = c - '0' - case 'a' <= c && c <= 'f': - c = 10 + c - 'a' - case 'A' <= c && c <= 'F': - c = 10 + c - 'A' - default: - return 0, false - } - v = v*16 + uint16(c) - } - return v, true -} - -// ParseUint parses b as a decimal unsigned integer according to -// a strict subset of the JSON number grammar, returning the value if valid. -// It returns (0, false) if there is a syntax error and -// returns (math.MaxUint64, false) if there is an overflow. -func ParseUint(b []byte) (v uint64, ok bool) { - const unsafeWidth = 20 // len(fmt.Sprint(uint64(math.MaxUint64))) - var n int - for ; len(b) > n && ('0' <= b[n] && b[n] <= '9'); n++ { - v = 10*v + uint64(b[n]-'0') - } - switch { - case n == 0 || len(b) != n || (b[0] == '0' && string(b) != "0"): - return 0, false - case n >= unsafeWidth && (b[0] != '1' || v < 1e19 || n > unsafeWidth): - return math.MaxUint64, false - } - return v, true -} - -// ParseFloat parses a floating point number according to the Go float grammar. -// Note that the JSON number grammar is a strict subset. -// -// If the number overflows the finite representation of a float, -// then we return MaxFloat since any finite value will always be infinitely -// more accurate at representing another finite value than an infinite value. -func ParseFloat(b []byte, bits int) (v float64, ok bool) { - fv, err := strconv.ParseFloat(string(b), bits) - if math.IsInf(fv, 0) { - switch { - case bits == 32 && math.IsInf(fv, +1): - fv = +math.MaxFloat32 - case bits == 64 && math.IsInf(fv, +1): - fv = +math.MaxFloat64 - case bits == 32 && math.IsInf(fv, -1): - fv = -math.MaxFloat32 - case bits == 64 && math.IsInf(fv, -1): - fv = -math.MaxFloat64 - } - } - return fv, err == nil -} diff --git a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonwire/encode.go b/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonwire/encode.go deleted file mode 100644 index 35b238a2e..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonwire/encode.go +++ /dev/null @@ -1,288 +0,0 @@ -// Copyright 2023 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package jsonwire - -import ( - "math" - "slices" - "strconv" - "unicode/utf16" - "unicode/utf8" - - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonflags" -) - -// escapeASCII reports whether the ASCII character needs to be escaped. -// It conservatively assumes EscapeForHTML. -var escapeASCII = [...]uint8{ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // escape control characters - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // escape control characters - 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, // escape '"' and '&' - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, // escape '<' and '>' - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, // escape '\\' - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -} - -// NeedEscape reports whether src needs escaping of any characters. -// It conservatively assumes EscapeForHTML and EscapeForJS. -// It reports true for inputs with invalid UTF-8. -func NeedEscape[Bytes ~[]byte | ~string](src Bytes) bool { - var i int - for uint(len(src)) > uint(i) { - if c := src[i]; c < utf8.RuneSelf { - if escapeASCII[c] > 0 { - return true - } - i++ - } else { - r, rn := utf8.DecodeRuneInString(string(truncateMaxUTF8(src[i:]))) - if r == utf8.RuneError || r == '\u2028' || r == '\u2029' { - return true - } - i += rn - } - } - return false -} - -// AppendQuote appends src to dst as a JSON string per RFC 7159, section 7. -// -// It takes in flags and respects the following: -// - EscapeForHTML escapes '<', '>', and '&'. -// - EscapeForJS escapes '\u2028' and '\u2029'. -// - AllowInvalidUTF8 avoids reporting an error for invalid UTF-8. -// -// Regardless of whether AllowInvalidUTF8 is specified, -// invalid bytes are replaced with the Unicode replacement character ('\ufffd'). -// If no escape flags are set, then the shortest representable form is used, -// which is also the canonical form for strings (RFC 8785, section 3.2.2.2). -func AppendQuote[Bytes ~[]byte | ~string](dst []byte, src Bytes, flags *jsonflags.Flags) ([]byte, error) { - var i, n int - var hasInvalidUTF8 bool - dst = slices.Grow(dst, len(`"`)+len(src)+len(`"`)) - dst = append(dst, '"') - for uint(len(src)) > uint(n) { - if c := src[n]; c < utf8.RuneSelf { - // Handle single-byte ASCII. - n++ - if escapeASCII[c] == 0 { - continue // no escaping possibly needed - } - // Handle escaping of single-byte ASCII. - if !(c == '<' || c == '>' || c == '&') || flags.Get(jsonflags.EscapeForHTML) { - dst = append(dst, src[i:n-1]...) - dst = appendEscapedASCII(dst, c) - i = n - } - } else { - // Handle multi-byte Unicode. - r, rn := utf8.DecodeRuneInString(string(truncateMaxUTF8(src[n:]))) - n += rn - if r != utf8.RuneError && r != '\u2028' && r != '\u2029' { - continue // no escaping possibly needed - } - // Handle escaping of multi-byte Unicode. - switch { - case isInvalidUTF8(r, rn): - hasInvalidUTF8 = true - dst = append(dst, src[i:n-rn]...) - dst = append(dst, "\ufffd"...) - i = n - case (r == '\u2028' || r == '\u2029') && flags.Get(jsonflags.EscapeForJS): - dst = append(dst, src[i:n-rn]...) - dst = appendEscapedUnicode(dst, r) - i = n - } - } - } - dst = append(dst, src[i:n]...) - dst = append(dst, '"') - if hasInvalidUTF8 && !flags.Get(jsonflags.AllowInvalidUTF8) { - return dst, ErrInvalidUTF8 - } - return dst, nil -} - -func appendEscapedASCII(dst []byte, c byte) []byte { - switch c { - case '"', '\\': - dst = append(dst, '\\', c) - case '\b': - dst = append(dst, "\\b"...) - case '\f': - dst = append(dst, "\\f"...) - case '\n': - dst = append(dst, "\\n"...) - case '\r': - dst = append(dst, "\\r"...) - case '\t': - dst = append(dst, "\\t"...) - default: - dst = appendEscapedUTF16(dst, uint16(c)) - } - return dst -} - -func appendEscapedUnicode(dst []byte, r rune) []byte { - if r1, r2 := utf16.EncodeRune(r); r1 != '\ufffd' && r2 != '\ufffd' { - dst = appendEscapedUTF16(dst, uint16(r1)) - dst = appendEscapedUTF16(dst, uint16(r2)) - } else { - dst = appendEscapedUTF16(dst, uint16(r)) - } - return dst -} - -func appendEscapedUTF16(dst []byte, x uint16) []byte { - const hex = "0123456789abcdef" - return append(dst, '\\', 'u', hex[(x>>12)&0xf], hex[(x>>8)&0xf], hex[(x>>4)&0xf], hex[(x>>0)&0xf]) -} - -// ReformatString consumes a JSON string from src and appends it to dst, -// reformatting it if necessary according to the specified flags. -// It returns the appended output and the number of consumed input bytes. -func ReformatString(dst, src []byte, flags *jsonflags.Flags) ([]byte, int, error) { - // TODO: Should this update ValueFlags as input? - var valFlags ValueFlags - n, err := ConsumeString(&valFlags, src, !flags.Get(jsonflags.AllowInvalidUTF8)) - if err != nil { - return dst, n, err - } - - // If the output requires no special escapes, and the input - // is already in canonical form or should be preserved verbatim, - // then directly copy the input to the output. - if !flags.Get(jsonflags.AnyEscape) && - (valFlags.IsCanonical() || flags.Get(jsonflags.PreserveRawStrings)) { - dst = append(dst, src[:n]...) // copy the string verbatim - return dst, n, nil - } - - // Under [jsonflags.PreserveRawStrings], any pre-escaped sequences - // remain escaped, however we still need to respect the - // [jsonflags.EscapeForHTML] and [jsonflags.EscapeForJS] options. - if flags.Get(jsonflags.PreserveRawStrings) { - var i, lastAppendIndex int - for i < n { - if c := src[i]; c < utf8.RuneSelf { - if (c == '<' || c == '>' || c == '&') && flags.Get(jsonflags.EscapeForHTML) { - dst = append(dst, src[lastAppendIndex:i]...) - dst = appendEscapedASCII(dst, c) - lastAppendIndex = i + 1 - } - i++ - } else { - r, rn := utf8.DecodeRune(truncateMaxUTF8(src[i:])) - if (r == '\u2028' || r == '\u2029') && flags.Get(jsonflags.EscapeForJS) { - dst = append(dst, src[lastAppendIndex:i]...) - dst = appendEscapedUnicode(dst, r) - lastAppendIndex = i + rn - } - i += rn - } - } - return append(dst, src[lastAppendIndex:n]...), n, nil - } - - // The input contains characters that might need escaping, - // unnecessary escape sequences, or invalid UTF-8. - // Perform a round-trip unquote and quote to properly reformat - // these sequences according the current flags. - b, _ := AppendUnquote(nil, src[:n]) - dst, _ = AppendQuote(dst, b, flags) - return dst, n, nil -} - -// AppendFloat appends src to dst as a JSON number per RFC 7159, section 6. -// It formats numbers similar to the ES6 number-to-string conversion. -// See https://go.dev/issue/14135. -// -// The output is identical to ECMA-262, 6th edition, section 7.1.12.1 and with -// RFC 8785, section 3.2.2.3 for 64-bit floating-point numbers except for -0, -// which is formatted as -0 instead of just 0. -// -// For 32-bit floating-point numbers, -// the output is a 32-bit equivalent of the algorithm. -// Note that ECMA-262 specifies no algorithm for 32-bit numbers. -func AppendFloat(dst []byte, src float64, bits int) []byte { - if bits == 32 { - src = float64(float32(src)) - } - - abs := math.Abs(src) - fmt := byte('f') - if abs != 0 { - if bits == 64 && (float64(abs) < 1e-6 || float64(abs) >= 1e21) || - bits == 32 && (float32(abs) < 1e-6 || float32(abs) >= 1e21) { - fmt = 'e' - } - } - dst = strconv.AppendFloat(dst, src, fmt, -1, bits) - if fmt == 'e' { - // Clean up e-09 to e-9. - n := len(dst) - if n >= 4 && dst[n-4] == 'e' && dst[n-3] == '-' && dst[n-2] == '0' { - dst[n-2] = dst[n-1] - dst = dst[:n-1] - } - } - return dst -} - -// ReformatNumber consumes a JSON string from src and appends it to dst, -// canonicalizing it if specified. -// It returns the appended output and the number of consumed input bytes. -func ReformatNumber(dst, src []byte, flags *jsonflags.Flags) ([]byte, int, error) { - n, err := ConsumeNumber(src) - if err != nil { - return dst, n, err - } - if !flags.Get(jsonflags.CanonicalizeNumbers) { - dst = append(dst, src[:n]...) // copy the number verbatim - return dst, n, nil - } - - // Identify the kind of number. - var isFloat bool - for _, c := range src[:n] { - if c == '.' || c == 'e' || c == 'E' { - isFloat = true // has fraction or exponent - break - } - } - - // Check if need to canonicalize this kind of number. - switch { - case string(src[:n]) == "-0": - break // canonicalize -0 as 0 regardless of kind - case isFloat: - if !flags.Get(jsonflags.CanonicalizeRawFloats) { - dst = append(dst, src[:n]...) // copy the number verbatim - return dst, n, nil - } - default: - // As an optimization, we can copy integer numbers below 2⁵³ verbatim - // since the canonical form is always identical. - const maxExactIntegerDigits = 16 // len(strconv.AppendUint(nil, 1<<53, 10)) - if !flags.Get(jsonflags.CanonicalizeRawInts) || n < maxExactIntegerDigits { - dst = append(dst, src[:n]...) // copy the number verbatim - return dst, n, nil - } - } - - // Parse and reformat the number (which uses a canonical format). - fv, _ := strconv.ParseFloat(string(src[:n]), 64) - switch { - case fv == 0: - fv = 0 // normalize negative zero as just zero - case math.IsInf(fv, +1): - fv = +math.MaxFloat64 - case math.IsInf(fv, -1): - fv = -math.MaxFloat64 - } - return AppendFloat(dst, fv, 64), n, nil -} diff --git a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonwire/wire.go b/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonwire/wire.go deleted file mode 100644 index 1831a66bd..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonwire/wire.go +++ /dev/null @@ -1,215 +0,0 @@ -// Copyright 2023 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package jsonwire implements stateless functionality for handling JSON text. -package jsonwire - -import ( - "cmp" - "errors" - "strconv" - "strings" - "unicode" - "unicode/utf16" - "unicode/utf8" -) - -// TrimSuffixWhitespace trims JSON from the end of b. -func TrimSuffixWhitespace(b []byte) []byte { - // NOTE: The arguments and logic are kept simple to keep this inlinable. - n := len(b) - 1 - for n >= 0 && (b[n] == ' ' || b[n] == '\t' || b[n] == '\r' || b[n] == '\n') { - n-- - } - return b[:n+1] -} - -// TrimSuffixString trims a valid JSON string at the end of b. -// The behavior is undefined if there is not a valid JSON string present. -func TrimSuffixString(b []byte) []byte { - // NOTE: The arguments and logic are kept simple to keep this inlinable. - if len(b) > 0 && b[len(b)-1] == '"' { - b = b[:len(b)-1] - } - for len(b) >= 2 && !(b[len(b)-1] == '"' && b[len(b)-2] != '\\') { - b = b[:len(b)-1] // trim all characters except an unescaped quote - } - if len(b) > 0 && b[len(b)-1] == '"' { - b = b[:len(b)-1] - } - return b -} - -// HasSuffixByte reports whether b ends with c. -func HasSuffixByte(b []byte, c byte) bool { - // NOTE: The arguments and logic are kept simple to keep this inlinable. - return len(b) > 0 && b[len(b)-1] == c -} - -// TrimSuffixByte removes c from the end of b if it is present. -func TrimSuffixByte(b []byte, c byte) []byte { - // NOTE: The arguments and logic are kept simple to keep this inlinable. - if len(b) > 0 && b[len(b)-1] == c { - return b[:len(b)-1] - } - return b -} - -// QuoteRune quotes the first rune in the input. -func QuoteRune[Bytes ~[]byte | ~string](b Bytes) string { - r, n := utf8.DecodeRuneInString(string(truncateMaxUTF8(b))) - if r == utf8.RuneError && n == 1 { - return `'\x` + strconv.FormatUint(uint64(b[0]), 16) + `'` - } - return strconv.QuoteRune(r) -} - -// CompareUTF16 lexicographically compares x to y according -// to the UTF-16 codepoints of the UTF-8 encoded input strings. -// This implements the ordering specified in RFC 8785, section 3.2.3. -func CompareUTF16[Bytes ~[]byte | ~string](x, y Bytes) int { - // NOTE: This is an optimized, mostly allocation-free implementation - // of CompareUTF16Simple in wire_test.go. FuzzCompareUTF16 verifies that the - // two implementations agree on the result of comparing any two strings. - isUTF16Self := func(r rune) bool { - return ('\u0000' <= r && r <= '\uD7FF') || ('\uE000' <= r && r <= '\uFFFF') - } - - for { - if len(x) == 0 || len(y) == 0 { - return cmp.Compare(len(x), len(y)) - } - - // ASCII fast-path. - if x[0] < utf8.RuneSelf || y[0] < utf8.RuneSelf { - if x[0] != y[0] { - return cmp.Compare(x[0], y[0]) - } - x, y = x[1:], y[1:] - continue - } - - // Decode next pair of runes as UTF-8. - rx, nx := utf8.DecodeRuneInString(string(truncateMaxUTF8(x))) - ry, ny := utf8.DecodeRuneInString(string(truncateMaxUTF8(y))) - - selfx := isUTF16Self(rx) - selfy := isUTF16Self(ry) - switch { - // The x rune is a single UTF-16 codepoint, while - // the y rune is a surrogate pair of UTF-16 codepoints. - case selfx && !selfy: - ry, _ = utf16.EncodeRune(ry) - // The y rune is a single UTF-16 codepoint, while - // the x rune is a surrogate pair of UTF-16 codepoints. - case selfy && !selfx: - rx, _ = utf16.EncodeRune(rx) - } - if rx != ry { - return cmp.Compare(rx, ry) - } - - // Check for invalid UTF-8, in which case, - // we just perform a byte-for-byte comparison. - if isInvalidUTF8(rx, nx) || isInvalidUTF8(ry, ny) { - if x[0] != y[0] { - return cmp.Compare(x[0], y[0]) - } - } - x, y = x[nx:], y[ny:] - } -} - -// truncateMaxUTF8 truncates b such it contains at least one rune. -// -// The utf8 package currently lacks generic variants, which complicates -// generic functions that operates on either []byte or string. -// As a hack, we always call the utf8 function operating on strings, -// but always truncate the input such that the result is identical. -// -// Example usage: -// -// utf8.DecodeRuneInString(string(truncateMaxUTF8(b))) -// -// Converting a []byte to a string is stack allocated since -// truncateMaxUTF8 guarantees that the []byte is short. -func truncateMaxUTF8[Bytes ~[]byte | ~string](b Bytes) Bytes { - // TODO(https://go.dev/issue/56948): Remove this function and - // instead directly call generic utf8 functions wherever used. - if len(b) > utf8.UTFMax { - return b[:utf8.UTFMax] - } - return b -} - -// TODO(https://go.dev/issue/70547): Use utf8.ErrInvalid instead. -var ErrInvalidUTF8 = errors.New("invalid UTF-8") - -func NewInvalidCharacterError[Bytes ~[]byte | ~string](prefix Bytes, where string) error { - what := QuoteRune(prefix) - return errors.New("invalid character " + what + " " + where) -} - -func NewInvalidEscapeSequenceError[Bytes ~[]byte | ~string](what Bytes) error { - label := "escape sequence" - if len(what) > 6 { - label = "surrogate pair" - } - needEscape := strings.IndexFunc(string(what), func(r rune) bool { - return r == '`' || r == utf8.RuneError || unicode.IsSpace(r) || !unicode.IsPrint(r) - }) >= 0 - if needEscape { - return errors.New("invalid " + label + " " + strconv.Quote(string(what)) + " in string") - } else { - return errors.New("invalid " + label + " `" + string(what) + "` in string") - } -} - -// TruncatePointer optionally truncates the JSON pointer, -// enforcing that the length roughly does not exceed n. -func TruncatePointer(s string, n int) string { - if len(s) <= n { - return s - } - i := n / 2 - j := len(s) - n/2 - - // Avoid truncating a name if there are multiple names present. - if k := strings.LastIndexByte(s[:i], '/'); k > 0 { - i = k - } - if k := strings.IndexByte(s[j:], '/'); k >= 0 { - j += k + len("/") - } - - // Avoid truncation in the middle of a UTF-8 rune. - for i > 0 && isInvalidUTF8(utf8.DecodeLastRuneInString(s[:i])) { - i-- - } - for j < len(s) && isInvalidUTF8(utf8.DecodeRuneInString(s[j:])) { - j++ - } - - // Determine the right middle fragment to use. - var middle string - switch strings.Count(s[i:j], "/") { - case 0: - middle = "…" - case 1: - middle = "…/…" - default: - middle = "…/…/…" - } - if strings.HasPrefix(s[i:j], "/") && middle != "…" { - middle = strings.TrimPrefix(middle, "…") - } - if strings.HasSuffix(s[i:j], "/") && middle != "…" { - middle = strings.TrimSuffix(middle, "…") - } - return s[:i] + middle + s[j:] -} - -func isInvalidUTF8(r rune, rn int) bool { - return r == utf8.RuneError && rn == 1 -} diff --git a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext/decode.go b/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext/decode.go deleted file mode 100644 index 96fd5c27c..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext/decode.go +++ /dev/null @@ -1,1177 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package jsontext - -import ( - "bytes" - "errors" - "io" - - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonflags" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonopts" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonwire" -) - -// NOTE: The logic for decoding is complicated by the fact that reading from -// an io.Reader into a temporary buffer means that the buffer may contain a -// truncated portion of some valid input, requiring the need to fetch more data. -// -// This file is structured in the following way: -// -// - consumeXXX functions parse an exact JSON token from a []byte. -// If the buffer appears truncated, then it returns io.ErrUnexpectedEOF. -// The consumeSimpleXXX functions are so named because they only handle -// a subset of the grammar for the JSON token being parsed. -// They do not handle the full grammar to keep these functions inlinable. -// -// - Decoder.consumeXXX methods parse the next JSON token from Decoder.buf, -// automatically fetching more input if necessary. These methods take -// a position relative to the start of Decoder.buf as an argument and -// return the end of the consumed JSON token as a position, -// also relative to the start of Decoder.buf. -// -// - In the event of an I/O errors or state machine violations, -// the implementation avoids mutating the state of Decoder -// (aside from the book-keeping needed to implement Decoder.fetch). -// For this reason, only Decoder.ReadToken and Decoder.ReadValue are -// responsible for updated Decoder.prevStart and Decoder.prevEnd. -// -// - For performance, much of the implementation uses the pattern of calling -// the inlinable consumeXXX functions first, and if more work is necessary, -// then it calls the slower Decoder.consumeXXX methods. -// TODO: Revisit this pattern if the Go compiler provides finer control -// over exactly which calls are inlined or not. - -// Decoder is a streaming decoder for raw JSON tokens and values. -// It is used to read a stream of top-level JSON values, -// each separated by optional whitespace characters. -// -// [Decoder.ReadToken] and [Decoder.ReadValue] calls may be interleaved. -// For example, the following JSON value: -// -// {"name":"value","array":[null,false,true,3.14159],"object":{"k":"v"}} -// -// can be parsed with the following calls (ignoring errors for brevity): -// -// d.ReadToken() // { -// d.ReadToken() // "name" -// d.ReadToken() // "value" -// d.ReadValue() // "array" -// d.ReadToken() // [ -// d.ReadToken() // null -// d.ReadToken() // false -// d.ReadValue() // true -// d.ReadToken() // 3.14159 -// d.ReadToken() // ] -// d.ReadValue() // "object" -// d.ReadValue() // {"k":"v"} -// d.ReadToken() // } -// -// The above is one of many possible sequence of calls and -// may not represent the most sensible method to call for any given token/value. -// For example, it is probably more common to call [Decoder.ReadToken] to obtain a -// string token for object names. -type Decoder struct { - s decoderState -} - -// decoderState is the low-level state of Decoder. -// It has exported fields and method for use by the "json" package. -type decoderState struct { - state - decodeBuffer - jsonopts.Struct - - StringCache *[256]string // only used when unmarshaling; identical to json.stringCache -} - -// decodeBuffer is a buffer split into 4 segments: -// -// - buf[0:prevEnd] // already read portion of the buffer -// - buf[prevStart:prevEnd] // previously read value -// - buf[prevEnd:len(buf)] // unread portion of the buffer -// - buf[len(buf):cap(buf)] // unused portion of the buffer -// -// Invariants: -// -// 0 ≤ prevStart ≤ prevEnd ≤ len(buf) ≤ cap(buf) -type decodeBuffer struct { - peekPos int // non-zero if valid offset into buf for start of next token - peekErr error // implies peekPos is -1 - - buf []byte // may alias rd if it is a bytes.Buffer - prevStart int - prevEnd int - - // baseOffset is added to prevStart and prevEnd to obtain - // the absolute offset relative to the start of io.Reader stream. - baseOffset int64 - - rd io.Reader -} - -// NewDecoder constructs a new streaming decoder reading from r. -// -// If r is a [bytes.Buffer], then the decoder parses directly from the buffer -// without first copying the contents to an intermediate buffer. -// Additional writes to the buffer must not occur while the decoder is in use. -func NewDecoder(r io.Reader, opts ...Options) *Decoder { - d := new(Decoder) - d.Reset(r, opts...) - return d -} - -// Reset resets a decoder such that it is reading afresh from r and -// configured with the provided options. Reset must not be called on an -// a Decoder passed to the [encoding/json/v2.UnmarshalerFrom.UnmarshalJSONFrom] method -// or the [encoding/json/v2.UnmarshalFromFunc] function. -func (d *Decoder) Reset(r io.Reader, opts ...Options) { - switch { - case d == nil: - panic("jsontext: invalid nil Decoder") - case r == nil: - panic("jsontext: invalid nil io.Reader") - case d.s.Flags.Get(jsonflags.WithinArshalCall): - panic("jsontext: cannot reset Decoder passed to json.UnmarshalerFrom") - } - // Reuse the buffer if it does not alias a previous [bytes.Buffer]. - b := d.s.buf[:0] - if _, ok := d.s.rd.(*bytes.Buffer); ok { - b = nil - } - d.s.reset(b, r, opts...) -} - -func (d *decoderState) reset(b []byte, r io.Reader, opts ...Options) { - d.state.reset() - d.decodeBuffer = decodeBuffer{buf: b, rd: r} - opts2 := jsonopts.Struct{} // avoid mutating d.Struct in case it is part of opts - opts2.Join(opts...) - d.Struct = opts2 -} - -// Options returns the options used to construct the encoder and -// may additionally contain semantic options passed to a -// [encoding/json/v2.UnmarshalDecode] call. -// -// If operating within -// a [encoding/json/v2.UnmarshalerFrom.UnmarshalJSONFrom] method call or -// a [encoding/json/v2.UnmarshalFromFunc] function call, -// then the returned options are only valid within the call. -func (d *Decoder) Options() Options { - return &d.s.Struct -} - -var errBufferWriteAfterNext = errors.New("invalid bytes.Buffer.Write call after calling bytes.Buffer.Next") - -// fetch reads at least 1 byte from the underlying io.Reader. -// It returns io.ErrUnexpectedEOF if zero bytes were read and io.EOF was seen. -func (d *decoderState) fetch() error { - if d.rd == nil { - return io.ErrUnexpectedEOF - } - - // Inform objectNameStack that we are about to fetch new buffer content. - d.Names.copyQuotedBuffer(d.buf) - - // Specialize bytes.Buffer for better performance. - if bb, ok := d.rd.(*bytes.Buffer); ok { - switch { - case bb.Len() == 0: - return io.ErrUnexpectedEOF - case len(d.buf) == 0: - d.buf = bb.Next(bb.Len()) // "read" all data in the buffer - return nil - default: - // This only occurs if a partially filled bytes.Buffer was provided - // and more data is written to it while Decoder is reading from it. - // This practice will lead to data corruption since future writes - // may overwrite the contents of the current buffer. - // - // The user is trying to use a bytes.Buffer as a pipe, - // but a bytes.Buffer is poor implementation of a pipe, - // the purpose-built io.Pipe should be used instead. - return &ioError{action: "read", err: errBufferWriteAfterNext} - } - } - - // Allocate initial buffer if empty. - if cap(d.buf) == 0 { - d.buf = make([]byte, 0, 64) - } - - // Check whether to grow the buffer. - const maxBufferSize = 4 << 10 - const growthSizeFactor = 2 // higher value is faster - const growthRateFactor = 2 // higher value is slower - // By default, grow if below the maximum buffer size. - grow := cap(d.buf) <= maxBufferSize/growthSizeFactor - // Growing can be expensive, so only grow - // if a sufficient number of bytes have been processed. - grow = grow && int64(cap(d.buf)) < d.previousOffsetEnd()/growthRateFactor - // If prevStart==0, then fetch was called in order to fetch more data - // to finish consuming a large JSON value contiguously. - // Grow if less than 25% of the remaining capacity is available. - // Note that this may cause the input buffer to exceed maxBufferSize. - grow = grow || (d.prevStart == 0 && len(d.buf) >= 3*cap(d.buf)/4) - - if grow { - // Allocate a new buffer and copy the contents of the old buffer over. - // TODO: Provide a hard limit on the maximum internal buffer size? - buf := make([]byte, 0, cap(d.buf)*growthSizeFactor) - d.buf = append(buf, d.buf[d.prevStart:]...) - } else { - // Move unread portion of the data to the front. - n := copy(d.buf[:cap(d.buf)], d.buf[d.prevStart:]) - d.buf = d.buf[:n] - } - d.baseOffset += int64(d.prevStart) - d.prevEnd -= d.prevStart - d.prevStart = 0 - - // Read more data into the internal buffer. - for { - n, err := d.rd.Read(d.buf[len(d.buf):cap(d.buf)]) - switch { - case n > 0: - d.buf = d.buf[:len(d.buf)+n] - return nil // ignore errors if any bytes are read - case err == io.EOF: - return io.ErrUnexpectedEOF - case err != nil: - return &ioError{action: "read", err: err} - default: - continue // Read returned (0, nil) - } - } -} - -const invalidateBufferByte = '#' // invalid starting character for JSON grammar - -// invalidatePreviousRead invalidates buffers returned by Peek and Read calls -// so that the first byte is an invalid character. -// This Hyrum-proofs the API against faulty application code that assumes -// values returned by ReadValue remain valid past subsequent Read calls. -func (d *decodeBuffer) invalidatePreviousRead() { - // Avoid mutating the buffer if d.rd is nil which implies that d.buf - // is provided by the user code and may not expect mutations. - isBytesBuffer := func(r io.Reader) bool { - _, ok := r.(*bytes.Buffer) - return ok - } - if d.rd != nil && !isBytesBuffer(d.rd) && d.prevStart < d.prevEnd && uint(d.prevStart) < uint(len(d.buf)) { - d.buf[d.prevStart] = invalidateBufferByte - d.prevStart = d.prevEnd - } -} - -// needMore reports whether there are no more unread bytes. -func (d *decodeBuffer) needMore(pos int) bool { - // NOTE: The arguments and logic are kept simple to keep this inlinable. - return pos == len(d.buf) -} - -func (d *decodeBuffer) offsetAt(pos int) int64 { return d.baseOffset + int64(pos) } -func (d *decodeBuffer) previousOffsetStart() int64 { return d.baseOffset + int64(d.prevStart) } -func (d *decodeBuffer) previousOffsetEnd() int64 { return d.baseOffset + int64(d.prevEnd) } -func (d *decodeBuffer) previousBuffer() []byte { return d.buf[d.prevStart:d.prevEnd] } -func (d *decodeBuffer) unreadBuffer() []byte { return d.buf[d.prevEnd:len(d.buf)] } - -// PreviousTokenOrValue returns the previously read token or value -// unless it has been invalidated by a call to PeekKind. -// If a token is just a delimiter, then this returns a 1-byte buffer. -// This method is used for error reporting at the semantic layer. -func (d *decodeBuffer) PreviousTokenOrValue() []byte { - b := d.previousBuffer() - // If peek was called, then the previous token or buffer is invalidated. - if d.peekPos > 0 || len(b) > 0 && b[0] == invalidateBufferByte { - return nil - } - // ReadToken does not preserve the buffer for null, bools, or delimiters. - // Manually re-construct that buffer. - if len(b) == 0 { - b = d.buf[:d.prevEnd] // entirety of the previous buffer - for _, tok := range []string{"null", "false", "true", "{", "}", "[", "]"} { - if len(b) >= len(tok) && string(b[len(b)-len(tok):]) == tok { - return b[len(b)-len(tok):] - } - } - } - return b -} - -// PeekKind retrieves the next token kind, but does not advance the read offset. -// -// It returns 0 if an error occurs. Any such error is cached until -// the next read call and it is the caller's responsibility to eventually -// follow up a PeekKind call with a read call. -func (d *Decoder) PeekKind() Kind { - return d.s.PeekKind() -} -func (d *decoderState) PeekKind() Kind { - // Check whether we have a cached peek result. - if d.peekPos > 0 { - return Kind(d.buf[d.peekPos]).normalize() - } - - var err error - d.invalidatePreviousRead() - pos := d.prevEnd - - // Consume leading whitespace. - pos += jsonwire.ConsumeWhitespace(d.buf[pos:]) - if d.needMore(pos) { - if pos, err = d.consumeWhitespace(pos); err != nil { - if err == io.ErrUnexpectedEOF && d.Tokens.Depth() == 1 { - err = io.EOF // EOF possibly if no Tokens present after top-level value - } - d.peekPos, d.peekErr = -1, wrapSyntacticError(d, err, pos, 0) - return invalidKind - } - } - - // Consume colon or comma. - var delim byte - if c := d.buf[pos]; c == ':' || c == ',' { - delim = c - pos += 1 - pos += jsonwire.ConsumeWhitespace(d.buf[pos:]) - if d.needMore(pos) { - if pos, err = d.consumeWhitespace(pos); err != nil { - err = wrapSyntacticError(d, err, pos, 0) - d.peekPos, d.peekErr = -1, d.checkDelimBeforeIOError(delim, err) - return invalidKind - } - } - } - next := Kind(d.buf[pos]).normalize() - if d.Tokens.needDelim(next) != delim { - d.peekPos, d.peekErr = -1, d.checkDelim(delim, next) - return invalidKind - } - - // This may set peekPos to zero, which is indistinguishable from - // the uninitialized state. While a small hit to performance, it is correct - // since ReadValue and ReadToken will disregard the cached result and - // recompute the next kind. - d.peekPos, d.peekErr = pos, nil - return next -} - -// checkDelimBeforeIOError checks whether the delim is even valid -// before returning an IO error, which occurs after the delim. -func (d *decoderState) checkDelimBeforeIOError(delim byte, err error) error { - // Since an IO error occurred, we do not know what the next kind is. - // However, knowing the next kind is necessary to validate - // whether the current delim is at least potentially valid. - // Since a JSON string is always valid as the next token, - // conservatively assume that is the next kind for validation. - const next = Kind('"') - if d.Tokens.needDelim(next) != delim { - err = d.checkDelim(delim, next) - } - return err -} - -// CountNextDelimWhitespace counts the number of upcoming bytes of -// delimiter or whitespace characters. -// This method is used for error reporting at the semantic layer. -func (d *decoderState) CountNextDelimWhitespace() int { - d.PeekKind() // populate unreadBuffer - return len(d.unreadBuffer()) - len(bytes.TrimLeft(d.unreadBuffer(), ",: \n\r\t")) -} - -// checkDelim checks whether delim is valid for the given next kind. -func (d *decoderState) checkDelim(delim byte, next Kind) error { - where := "at start of value" - switch d.Tokens.needDelim(next) { - case delim: - return nil - case ':': - where = "after object name (expecting ':')" - case ',': - if d.Tokens.Last.isObject() { - where = "after object value (expecting ',' or '}')" - } else { - where = "after array element (expecting ',' or ']')" - } - } - pos := d.prevEnd // restore position to right after leading whitespace - pos += jsonwire.ConsumeWhitespace(d.buf[pos:]) - err := jsonwire.NewInvalidCharacterError(d.buf[pos:], where) - return wrapSyntacticError(d, err, pos, 0) -} - -// SkipValue is semantically equivalent to calling [Decoder.ReadValue] and discarding -// the result except that memory is not wasted trying to hold the entire result. -func (d *Decoder) SkipValue() error { - return d.s.SkipValue() -} -func (d *decoderState) SkipValue() error { - switch d.PeekKind() { - case '{', '[': - // For JSON objects and arrays, keep skipping all tokens - // until the depth matches the starting depth. - depth := d.Tokens.Depth() - for { - if _, err := d.ReadToken(); err != nil { - return err - } - if depth >= d.Tokens.Depth() { - return nil - } - } - default: - // Trying to skip a value when the next token is a '}' or ']' - // will result in an error being returned here. - var flags jsonwire.ValueFlags - if _, err := d.ReadValue(&flags); err != nil { - return err - } - return nil - } -} - -// SkipValueRemainder skips the remainder of a value -// after reading a '{' or '[' token. -func (d *decoderState) SkipValueRemainder() error { - if d.Tokens.Depth()-1 > 0 && d.Tokens.Last.Length() == 0 { - for n := d.Tokens.Depth(); d.Tokens.Depth() >= n; { - if _, err := d.ReadToken(); err != nil { - return err - } - } - } - return nil -} - -// SkipUntil skips all tokens until the state machine -// is at or past the specified depth and length. -func (d *decoderState) SkipUntil(depth int, length int64) error { - for d.Tokens.Depth() > depth || (d.Tokens.Depth() == depth && d.Tokens.Last.Length() < length) { - if _, err := d.ReadToken(); err != nil { - return err - } - } - return nil -} - -// ReadToken reads the next [Token], advancing the read offset. -// The returned token is only valid until the next Peek, Read, or Skip call. -// It returns [io.EOF] if there are no more tokens. -func (d *Decoder) ReadToken() (Token, error) { - return d.s.ReadToken() -} -func (d *decoderState) ReadToken() (Token, error) { - // Determine the next kind. - var err error - var next Kind - pos := d.peekPos - if pos != 0 { - // Use cached peek result. - if d.peekErr != nil { - err := d.peekErr - d.peekPos, d.peekErr = 0, nil // possibly a transient I/O error - return Token{}, err - } - next = Kind(d.buf[pos]).normalize() - d.peekPos = 0 // reset cache - } else { - d.invalidatePreviousRead() - pos = d.prevEnd - - // Consume leading whitespace. - pos += jsonwire.ConsumeWhitespace(d.buf[pos:]) - if d.needMore(pos) { - if pos, err = d.consumeWhitespace(pos); err != nil { - if err == io.ErrUnexpectedEOF && d.Tokens.Depth() == 1 { - err = io.EOF // EOF possibly if no Tokens present after top-level value - } - return Token{}, wrapSyntacticError(d, err, pos, 0) - } - } - - // Consume colon or comma. - var delim byte - if c := d.buf[pos]; c == ':' || c == ',' { - delim = c - pos += 1 - pos += jsonwire.ConsumeWhitespace(d.buf[pos:]) - if d.needMore(pos) { - if pos, err = d.consumeWhitespace(pos); err != nil { - err = wrapSyntacticError(d, err, pos, 0) - return Token{}, d.checkDelimBeforeIOError(delim, err) - } - } - } - next = Kind(d.buf[pos]).normalize() - if d.Tokens.needDelim(next) != delim { - return Token{}, d.checkDelim(delim, next) - } - } - - // Handle the next token. - var n int - switch next { - case 'n': - if jsonwire.ConsumeNull(d.buf[pos:]) == 0 { - pos, err = d.consumeLiteral(pos, "null") - if err != nil { - return Token{}, wrapSyntacticError(d, err, pos, +1) - } - } else { - pos += len("null") - } - if err = d.Tokens.appendLiteral(); err != nil { - return Token{}, wrapSyntacticError(d, err, pos-len("null"), +1) // report position at start of literal - } - d.prevStart, d.prevEnd = pos, pos - return Null, nil - - case 'f': - if jsonwire.ConsumeFalse(d.buf[pos:]) == 0 { - pos, err = d.consumeLiteral(pos, "false") - if err != nil { - return Token{}, wrapSyntacticError(d, err, pos, +1) - } - } else { - pos += len("false") - } - if err = d.Tokens.appendLiteral(); err != nil { - return Token{}, wrapSyntacticError(d, err, pos-len("false"), +1) // report position at start of literal - } - d.prevStart, d.prevEnd = pos, pos - return False, nil - - case 't': - if jsonwire.ConsumeTrue(d.buf[pos:]) == 0 { - pos, err = d.consumeLiteral(pos, "true") - if err != nil { - return Token{}, wrapSyntacticError(d, err, pos, +1) - } - } else { - pos += len("true") - } - if err = d.Tokens.appendLiteral(); err != nil { - return Token{}, wrapSyntacticError(d, err, pos-len("true"), +1) // report position at start of literal - } - d.prevStart, d.prevEnd = pos, pos - return True, nil - - case '"': - var flags jsonwire.ValueFlags // TODO: Preserve this in Token? - if n = jsonwire.ConsumeSimpleString(d.buf[pos:]); n == 0 { - oldAbsPos := d.baseOffset + int64(pos) - pos, err = d.consumeString(&flags, pos) - newAbsPos := d.baseOffset + int64(pos) - n = int(newAbsPos - oldAbsPos) - if err != nil { - return Token{}, wrapSyntacticError(d, err, pos, +1) - } - } else { - pos += n - } - if d.Tokens.Last.NeedObjectName() { - if !d.Flags.Get(jsonflags.AllowDuplicateNames) { - if !d.Tokens.Last.isValidNamespace() { - return Token{}, wrapSyntacticError(d, errInvalidNamespace, pos-n, +1) - } - if d.Tokens.Last.isActiveNamespace() && !d.Namespaces.Last().insertQuoted(d.buf[pos-n:pos], flags.IsVerbatim()) { - err = wrapWithObjectName(ErrDuplicateName, d.buf[pos-n:pos]) - return Token{}, wrapSyntacticError(d, err, pos-n, +1) // report position at start of string - } - } - d.Names.ReplaceLastQuotedOffset(pos - n) // only replace if insertQuoted succeeds - } - if err = d.Tokens.appendString(); err != nil { - return Token{}, wrapSyntacticError(d, err, pos-n, +1) // report position at start of string - } - d.prevStart, d.prevEnd = pos-n, pos - return Token{raw: &d.decodeBuffer, num: uint64(d.previousOffsetStart())}, nil - - case '0': - // NOTE: Since JSON numbers are not self-terminating, - // we need to make sure that the next byte is not part of a number. - if n = jsonwire.ConsumeSimpleNumber(d.buf[pos:]); n == 0 || d.needMore(pos+n) { - oldAbsPos := d.baseOffset + int64(pos) - pos, err = d.consumeNumber(pos) - newAbsPos := d.baseOffset + int64(pos) - n = int(newAbsPos - oldAbsPos) - if err != nil { - return Token{}, wrapSyntacticError(d, err, pos, +1) - } - } else { - pos += n - } - if err = d.Tokens.appendNumber(); err != nil { - return Token{}, wrapSyntacticError(d, err, pos-n, +1) // report position at start of number - } - d.prevStart, d.prevEnd = pos-n, pos - return Token{raw: &d.decodeBuffer, num: uint64(d.previousOffsetStart())}, nil - - case '{': - if err = d.Tokens.pushObject(); err != nil { - return Token{}, wrapSyntacticError(d, err, pos, +1) - } - d.Names.push() - if !d.Flags.Get(jsonflags.AllowDuplicateNames) { - d.Namespaces.push() - } - pos += 1 - d.prevStart, d.prevEnd = pos, pos - return BeginObject, nil - - case '}': - if err = d.Tokens.popObject(); err != nil { - return Token{}, wrapSyntacticError(d, err, pos, +1) - } - d.Names.pop() - if !d.Flags.Get(jsonflags.AllowDuplicateNames) { - d.Namespaces.pop() - } - pos += 1 - d.prevStart, d.prevEnd = pos, pos - return EndObject, nil - - case '[': - if err = d.Tokens.pushArray(); err != nil { - return Token{}, wrapSyntacticError(d, err, pos, +1) - } - pos += 1 - d.prevStart, d.prevEnd = pos, pos - return BeginArray, nil - - case ']': - if err = d.Tokens.popArray(); err != nil { - return Token{}, wrapSyntacticError(d, err, pos, +1) - } - pos += 1 - d.prevStart, d.prevEnd = pos, pos - return EndArray, nil - - default: - err = jsonwire.NewInvalidCharacterError(d.buf[pos:], "at start of value") - return Token{}, wrapSyntacticError(d, err, pos, +1) - } -} - -// ReadValue returns the next raw JSON value, advancing the read offset. -// The value is stripped of any leading or trailing whitespace and -// contains the exact bytes of the input, which may contain invalid UTF-8 -// if [AllowInvalidUTF8] is specified. -// -// The returned value is only valid until the next Peek, Read, or Skip call and -// may not be mutated while the Decoder remains in use. -// If the decoder is currently at the end token for an object or array, -// then it reports a [SyntacticError] and the internal state remains unchanged. -// It returns [io.EOF] if there are no more values. -func (d *Decoder) ReadValue() (Value, error) { - var flags jsonwire.ValueFlags - return d.s.ReadValue(&flags) -} -func (d *decoderState) ReadValue(flags *jsonwire.ValueFlags) (Value, error) { - // Determine the next kind. - var err error - var next Kind - pos := d.peekPos - if pos != 0 { - // Use cached peek result. - if d.peekErr != nil { - err := d.peekErr - d.peekPos, d.peekErr = 0, nil // possibly a transient I/O error - return nil, err - } - next = Kind(d.buf[pos]).normalize() - d.peekPos = 0 // reset cache - } else { - d.invalidatePreviousRead() - pos = d.prevEnd - - // Consume leading whitespace. - pos += jsonwire.ConsumeWhitespace(d.buf[pos:]) - if d.needMore(pos) { - if pos, err = d.consumeWhitespace(pos); err != nil { - if err == io.ErrUnexpectedEOF && d.Tokens.Depth() == 1 { - err = io.EOF // EOF possibly if no Tokens present after top-level value - } - return nil, wrapSyntacticError(d, err, pos, 0) - } - } - - // Consume colon or comma. - var delim byte - if c := d.buf[pos]; c == ':' || c == ',' { - delim = c - pos += 1 - pos += jsonwire.ConsumeWhitespace(d.buf[pos:]) - if d.needMore(pos) { - if pos, err = d.consumeWhitespace(pos); err != nil { - err = wrapSyntacticError(d, err, pos, 0) - return nil, d.checkDelimBeforeIOError(delim, err) - } - } - } - next = Kind(d.buf[pos]).normalize() - if d.Tokens.needDelim(next) != delim { - return nil, d.checkDelim(delim, next) - } - } - - // Handle the next value. - oldAbsPos := d.baseOffset + int64(pos) - pos, err = d.consumeValue(flags, pos, d.Tokens.Depth()) - newAbsPos := d.baseOffset + int64(pos) - n := int(newAbsPos - oldAbsPos) - if err != nil { - return nil, wrapSyntacticError(d, err, pos, +1) - } - switch next { - case 'n', 't', 'f': - err = d.Tokens.appendLiteral() - case '"': - if d.Tokens.Last.NeedObjectName() { - if !d.Flags.Get(jsonflags.AllowDuplicateNames) { - if !d.Tokens.Last.isValidNamespace() { - err = errInvalidNamespace - break - } - if d.Tokens.Last.isActiveNamespace() && !d.Namespaces.Last().insertQuoted(d.buf[pos-n:pos], flags.IsVerbatim()) { - err = wrapWithObjectName(ErrDuplicateName, d.buf[pos-n:pos]) - break - } - } - d.Names.ReplaceLastQuotedOffset(pos - n) // only replace if insertQuoted succeeds - } - err = d.Tokens.appendString() - case '0': - err = d.Tokens.appendNumber() - case '{': - if err = d.Tokens.pushObject(); err != nil { - break - } - if err = d.Tokens.popObject(); err != nil { - panic("BUG: popObject should never fail immediately after pushObject: " + err.Error()) - } - case '[': - if err = d.Tokens.pushArray(); err != nil { - break - } - if err = d.Tokens.popArray(); err != nil { - panic("BUG: popArray should never fail immediately after pushArray: " + err.Error()) - } - } - if err != nil { - return nil, wrapSyntacticError(d, err, pos-n, +1) // report position at start of value - } - d.prevEnd = pos - d.prevStart = pos - n - return d.buf[pos-n : pos : pos], nil -} - -// CheckNextValue checks whether the next value is syntactically valid, -// but does not advance the read offset. -// If last, it verifies that the stream cleanly terminates with [io.EOF]. -func (d *decoderState) CheckNextValue(last bool) error { - d.PeekKind() // populates d.peekPos and d.peekErr - pos, err := d.peekPos, d.peekErr - d.peekPos, d.peekErr = 0, nil - if err != nil { - return err - } - - var flags jsonwire.ValueFlags - if pos, err := d.consumeValue(&flags, pos, d.Tokens.Depth()); err != nil { - return wrapSyntacticError(d, err, pos, +1) - } else if last { - return d.checkEOF(pos) - } - return nil -} - -// CheckEOF verifies that the input has no more data. -func (d *decoderState) CheckEOF() error { - return d.checkEOF(d.prevEnd) -} -func (d *decoderState) checkEOF(pos int) error { - switch pos, err := d.consumeWhitespace(pos); err { - case nil: - err := jsonwire.NewInvalidCharacterError(d.buf[pos:], "after top-level value") - return wrapSyntacticError(d, err, pos, 0) - case io.ErrUnexpectedEOF: - return nil - default: - return err - } -} - -// consumeWhitespace consumes all whitespace starting at d.buf[pos:]. -// It returns the new position in d.buf immediately after the last whitespace. -// If it returns nil, there is guaranteed to at least be one unread byte. -// -// The following pattern is common in this implementation: -// -// pos += jsonwire.ConsumeWhitespace(d.buf[pos:]) -// if d.needMore(pos) { -// if pos, err = d.consumeWhitespace(pos); err != nil { -// return ... -// } -// } -// -// It is difficult to simplify this without sacrificing performance since -// consumeWhitespace must be inlined. The body of the if statement is -// executed only in rare situations where we need to fetch more data. -// Since fetching may return an error, we also need to check the error. -func (d *decoderState) consumeWhitespace(pos int) (newPos int, err error) { - for { - pos += jsonwire.ConsumeWhitespace(d.buf[pos:]) - if d.needMore(pos) { - absPos := d.baseOffset + int64(pos) - err = d.fetch() // will mutate d.buf and invalidate pos - pos = int(absPos - d.baseOffset) - if err != nil { - return pos, err - } - continue - } - return pos, nil - } -} - -// consumeValue consumes a single JSON value starting at d.buf[pos:]. -// It returns the new position in d.buf immediately after the value. -func (d *decoderState) consumeValue(flags *jsonwire.ValueFlags, pos, depth int) (newPos int, err error) { - for { - var n int - var err error - switch next := Kind(d.buf[pos]).normalize(); next { - case 'n': - if n = jsonwire.ConsumeNull(d.buf[pos:]); n == 0 { - n, err = jsonwire.ConsumeLiteral(d.buf[pos:], "null") - } - case 'f': - if n = jsonwire.ConsumeFalse(d.buf[pos:]); n == 0 { - n, err = jsonwire.ConsumeLiteral(d.buf[pos:], "false") - } - case 't': - if n = jsonwire.ConsumeTrue(d.buf[pos:]); n == 0 { - n, err = jsonwire.ConsumeLiteral(d.buf[pos:], "true") - } - case '"': - if n = jsonwire.ConsumeSimpleString(d.buf[pos:]); n == 0 { - return d.consumeString(flags, pos) - } - case '0': - // NOTE: Since JSON numbers are not self-terminating, - // we need to make sure that the next byte is not part of a number. - if n = jsonwire.ConsumeSimpleNumber(d.buf[pos:]); n == 0 || d.needMore(pos+n) { - return d.consumeNumber(pos) - } - case '{': - return d.consumeObject(flags, pos, depth) - case '[': - return d.consumeArray(flags, pos, depth) - default: - if (d.Tokens.Last.isObject() && next == ']') || (d.Tokens.Last.isArray() && next == '}') { - return pos, errMismatchDelim - } - return pos, jsonwire.NewInvalidCharacterError(d.buf[pos:], "at start of value") - } - if err == io.ErrUnexpectedEOF { - absPos := d.baseOffset + int64(pos) - err = d.fetch() // will mutate d.buf and invalidate pos - pos = int(absPos - d.baseOffset) - if err != nil { - return pos + n, err - } - continue - } - return pos + n, err - } -} - -// consumeLiteral consumes a single JSON literal starting at d.buf[pos:]. -// It returns the new position in d.buf immediately after the literal. -func (d *decoderState) consumeLiteral(pos int, lit string) (newPos int, err error) { - for { - n, err := jsonwire.ConsumeLiteral(d.buf[pos:], lit) - if err == io.ErrUnexpectedEOF { - absPos := d.baseOffset + int64(pos) - err = d.fetch() // will mutate d.buf and invalidate pos - pos = int(absPos - d.baseOffset) - if err != nil { - return pos + n, err - } - continue - } - return pos + n, err - } -} - -// consumeString consumes a single JSON string starting at d.buf[pos:]. -// It returns the new position in d.buf immediately after the string. -func (d *decoderState) consumeString(flags *jsonwire.ValueFlags, pos int) (newPos int, err error) { - var n int - for { - n, err = jsonwire.ConsumeStringResumable(flags, d.buf[pos:], n, !d.Flags.Get(jsonflags.AllowInvalidUTF8)) - if err == io.ErrUnexpectedEOF { - absPos := d.baseOffset + int64(pos) - err = d.fetch() // will mutate d.buf and invalidate pos - pos = int(absPos - d.baseOffset) - if err != nil { - return pos + n, err - } - continue - } - return pos + n, err - } -} - -// consumeNumber consumes a single JSON number starting at d.buf[pos:]. -// It returns the new position in d.buf immediately after the number. -func (d *decoderState) consumeNumber(pos int) (newPos int, err error) { - var n int - var state jsonwire.ConsumeNumberState - for { - n, state, err = jsonwire.ConsumeNumberResumable(d.buf[pos:], n, state) - // NOTE: Since JSON numbers are not self-terminating, - // we need to make sure that the next byte is not part of a number. - if err == io.ErrUnexpectedEOF || d.needMore(pos+n) { - mayTerminate := err == nil - absPos := d.baseOffset + int64(pos) - err = d.fetch() // will mutate d.buf and invalidate pos - pos = int(absPos - d.baseOffset) - if err != nil { - if mayTerminate && err == io.ErrUnexpectedEOF { - return pos + n, nil - } - return pos, err - } - continue - } - return pos + n, err - } -} - -// consumeObject consumes a single JSON object starting at d.buf[pos:]. -// It returns the new position in d.buf immediately after the object. -func (d *decoderState) consumeObject(flags *jsonwire.ValueFlags, pos, depth int) (newPos int, err error) { - var n int - var names *objectNamespace - if !d.Flags.Get(jsonflags.AllowDuplicateNames) { - d.Namespaces.push() - defer d.Namespaces.pop() - names = d.Namespaces.Last() - } - - // Handle before start. - if uint(pos) >= uint(len(d.buf)) || d.buf[pos] != '{' { - panic("BUG: consumeObject must be called with a buffer that starts with '{'") - } else if depth == maxNestingDepth+1 { - return pos, errMaxDepth - } - pos++ - - // Handle after start. - pos += jsonwire.ConsumeWhitespace(d.buf[pos:]) - if d.needMore(pos) { - if pos, err = d.consumeWhitespace(pos); err != nil { - return pos, err - } - } - if d.buf[pos] == '}' { - pos++ - return pos, nil - } - - depth++ - for { - // Handle before name. - pos += jsonwire.ConsumeWhitespace(d.buf[pos:]) - if d.needMore(pos) { - if pos, err = d.consumeWhitespace(pos); err != nil { - return pos, err - } - } - var flags2 jsonwire.ValueFlags - if n = jsonwire.ConsumeSimpleString(d.buf[pos:]); n == 0 { - oldAbsPos := d.baseOffset + int64(pos) - pos, err = d.consumeString(&flags2, pos) - newAbsPos := d.baseOffset + int64(pos) - n = int(newAbsPos - oldAbsPos) - flags.Join(flags2) - if err != nil { - return pos, err - } - } else { - pos += n - } - quotedName := d.buf[pos-n : pos] - if !d.Flags.Get(jsonflags.AllowDuplicateNames) && !names.insertQuoted(quotedName, flags2.IsVerbatim()) { - return pos - n, wrapWithObjectName(ErrDuplicateName, quotedName) - } - - // Handle after name. - pos += jsonwire.ConsumeWhitespace(d.buf[pos:]) - if d.needMore(pos) { - if pos, err = d.consumeWhitespace(pos); err != nil { - return pos, wrapWithObjectName(err, quotedName) - } - } - if d.buf[pos] != ':' { - err := jsonwire.NewInvalidCharacterError(d.buf[pos:], "after object name (expecting ':')") - return pos, wrapWithObjectName(err, quotedName) - } - pos++ - - // Handle before value. - pos += jsonwire.ConsumeWhitespace(d.buf[pos:]) - if d.needMore(pos) { - if pos, err = d.consumeWhitespace(pos); err != nil { - return pos, wrapWithObjectName(err, quotedName) - } - } - pos, err = d.consumeValue(flags, pos, depth) - if err != nil { - return pos, wrapWithObjectName(err, quotedName) - } - - // Handle after value. - pos += jsonwire.ConsumeWhitespace(d.buf[pos:]) - if d.needMore(pos) { - if pos, err = d.consumeWhitespace(pos); err != nil { - return pos, err - } - } - switch d.buf[pos] { - case ',': - pos++ - continue - case '}': - pos++ - return pos, nil - default: - return pos, jsonwire.NewInvalidCharacterError(d.buf[pos:], "after object value (expecting ',' or '}')") - } - } -} - -// consumeArray consumes a single JSON array starting at d.buf[pos:]. -// It returns the new position in d.buf immediately after the array. -func (d *decoderState) consumeArray(flags *jsonwire.ValueFlags, pos, depth int) (newPos int, err error) { - // Handle before start. - if uint(pos) >= uint(len(d.buf)) || d.buf[pos] != '[' { - panic("BUG: consumeArray must be called with a buffer that starts with '['") - } else if depth == maxNestingDepth+1 { - return pos, errMaxDepth - } - pos++ - - // Handle after start. - pos += jsonwire.ConsumeWhitespace(d.buf[pos:]) - if d.needMore(pos) { - if pos, err = d.consumeWhitespace(pos); err != nil { - return pos, err - } - } - if d.buf[pos] == ']' { - pos++ - return pos, nil - } - - var idx int64 - depth++ - for { - // Handle before value. - pos += jsonwire.ConsumeWhitespace(d.buf[pos:]) - if d.needMore(pos) { - if pos, err = d.consumeWhitespace(pos); err != nil { - return pos, err - } - } - pos, err = d.consumeValue(flags, pos, depth) - if err != nil { - return pos, wrapWithArrayIndex(err, idx) - } - - // Handle after value. - pos += jsonwire.ConsumeWhitespace(d.buf[pos:]) - if d.needMore(pos) { - if pos, err = d.consumeWhitespace(pos); err != nil { - return pos, err - } - } - switch d.buf[pos] { - case ',': - pos++ - idx++ - continue - case ']': - pos++ - return pos, nil - default: - return pos, jsonwire.NewInvalidCharacterError(d.buf[pos:], "after array element (expecting ',' or ']')") - } - } -} - -// InputOffset returns the current input byte offset. It gives the location -// of the next byte immediately after the most recently returned token or value. -// The number of bytes actually read from the underlying [io.Reader] may be more -// than this offset due to internal buffering effects. -func (d *Decoder) InputOffset() int64 { - return d.s.previousOffsetEnd() -} - -// UnreadBuffer returns the data remaining in the unread buffer, -// which may contain zero or more bytes. -// The returned buffer must not be mutated while Decoder continues to be used. -// The buffer contents are valid until the next Peek, Read, or Skip call. -func (d *Decoder) UnreadBuffer() []byte { - return d.s.unreadBuffer() -} - -// StackDepth returns the depth of the state machine for read JSON data. -// Each level on the stack represents a nested JSON object or array. -// It is incremented whenever an [BeginObject] or [BeginArray] token is encountered -// and decremented whenever an [EndObject] or [EndArray] token is encountered. -// The depth is zero-indexed, where zero represents the top-level JSON value. -func (d *Decoder) StackDepth() int { - // NOTE: Keep in sync with Encoder.StackDepth. - return d.s.Tokens.Depth() - 1 -} - -// StackIndex returns information about the specified stack level. -// It must be a number between 0 and [Decoder.StackDepth], inclusive. -// For each level, it reports the kind: -// -// - 0 for a level of zero, -// - '{' for a level representing a JSON object, and -// - '[' for a level representing a JSON array. -// -// It also reports the length of that JSON object or array. -// Each name and value in a JSON object is counted separately, -// so the effective number of members would be half the length. -// A complete JSON object must have an even length. -func (d *Decoder) StackIndex(i int) (Kind, int64) { - // NOTE: Keep in sync with Encoder.StackIndex. - switch s := d.s.Tokens.index(i); { - case i > 0 && s.isObject(): - return '{', s.Length() - case i > 0 && s.isArray(): - return '[', s.Length() - default: - return 0, s.Length() - } -} - -// StackPointer returns a JSON Pointer (RFC 6901) to the most recently read value. -func (d *Decoder) StackPointer() Pointer { - return Pointer(d.s.AppendStackPointer(nil, -1)) -} - -func (d *decoderState) AppendStackPointer(b []byte, where int) []byte { - d.Names.copyQuotedBuffer(d.buf) - return d.state.appendStackPointer(b, where) -} diff --git a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext/doc.go b/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext/doc.go deleted file mode 100644 index bea3ccd34..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext/doc.go +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright 2023 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package jsontext implements syntactic processing of JSON -// as specified in RFC 4627, RFC 7159, RFC 7493, RFC 8259, and RFC 8785. -// JSON is a simple data interchange format that can represent -// primitive data types such as booleans, strings, and numbers, -// in addition to structured data types such as objects and arrays. -// -// The [Encoder] and [Decoder] types are used to encode or decode -// a stream of JSON tokens or values. -// -// # Tokens and Values -// -// A JSON token refers to the basic structural elements of JSON: -// -// - a JSON literal (i.e., null, true, or false) -// - a JSON string (e.g., "hello, world!") -// - a JSON number (e.g., 123.456) -// - a begin or end delimiter for a JSON object (i.e., '{' or '}') -// - a begin or end delimiter for a JSON array (i.e., '[' or ']') -// -// A JSON token is represented by the [Token] type in Go. Technically, -// there are two additional structural characters (i.e., ':' and ','), -// but there is no [Token] representation for them since their presence -// can be inferred by the structure of the JSON grammar itself. -// For example, there must always be an implicit colon between -// the name and value of a JSON object member. -// -// A JSON value refers to a complete unit of JSON data: -// -// - a JSON literal, string, or number -// - a JSON object (e.g., `{"name":"value"}`) -// - a JSON array (e.g., `[1,2,3,]`) -// -// A JSON value is represented by the [Value] type in Go and is a []byte -// containing the raw textual representation of the value. There is some overlap -// between tokens and values as both contain literals, strings, and numbers. -// However, only a value can represent the entirety of a JSON object or array. -// -// The [Encoder] and [Decoder] types contain methods to read or write the next -// [Token] or [Value] in a sequence. They maintain a state machine to validate -// whether the sequence of JSON tokens and/or values produces a valid JSON. -// [Options] may be passed to the [NewEncoder] or [NewDecoder] constructors -// to configure the syntactic behavior of encoding and decoding. -// -// # Terminology -// -// The terms "encode" and "decode" are used for syntactic functionality -// that is concerned with processing JSON based on its grammar, and -// the terms "marshal" and "unmarshal" are used for semantic functionality -// that determines the meaning of JSON values as Go values and vice-versa. -// This package (i.e., [jsontext]) deals with JSON at a syntactic layer, -// while [encoding/json/v2] deals with JSON at a semantic layer. -// The goal is to provide a clear distinction between functionality that -// is purely concerned with encoding versus that of marshaling. -// For example, one can directly encode a stream of JSON tokens without -// needing to marshal a concrete Go value representing them. -// Similarly, one can decode a stream of JSON tokens without -// needing to unmarshal them into a concrete Go value. -// -// This package uses JSON terminology when discussing JSON, which may differ -// from related concepts in Go or elsewhere in computing literature. -// -// - a JSON "object" refers to an unordered collection of name/value members. -// - a JSON "array" refers to an ordered sequence of elements. -// - a JSON "value" refers to either a literal (i.e., null, false, or true), -// string, number, object, or array. -// -// See RFC 8259 for more information. -// -// # Specifications -// -// Relevant specifications include RFC 4627, RFC 7159, RFC 7493, RFC 8259, -// and RFC 8785. Each RFC is generally a stricter subset of another RFC. -// In increasing order of strictness: -// -// - RFC 4627 and RFC 7159 do not require (but recommend) the use of UTF-8 -// and also do not require (but recommend) that object names be unique. -// - RFC 8259 requires the use of UTF-8, -// but does not require (but recommends) that object names be unique. -// - RFC 7493 requires the use of UTF-8 -// and also requires that object names be unique. -// - RFC 8785 defines a canonical representation. It requires the use of UTF-8 -// and also requires that object names be unique and in a specific ordering. -// It specifies exactly how strings and numbers must be formatted. -// -// The primary difference between RFC 4627 and RFC 7159 is that the former -// restricted top-level values to only JSON objects and arrays, while -// RFC 7159 and subsequent RFCs permit top-level values to additionally be -// JSON nulls, booleans, strings, or numbers. -// -// By default, this package operates on RFC 7493, but can be configured -// to operate according to the other RFC specifications. -// RFC 7493 is a stricter subset of RFC 8259 and fully compliant with it. -// In particular, it makes specific choices about behavior that RFC 8259 -// leaves as undefined in order to ensure greater interoperability. -// -// # Security Considerations -// -// See the "Security Considerations" section in [encoding/json/v2]. -package jsontext - -// requireKeyedLiterals can be embedded in a struct to require keyed literals. -type requireKeyedLiterals struct{} - -// nonComparable can be embedded in a struct to prevent comparability. -type nonComparable [0]func() diff --git a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext/encode.go b/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext/encode.go deleted file mode 100644 index 36bf7efdf..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext/encode.go +++ /dev/null @@ -1,975 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package jsontext - -import ( - "bytes" - "io" - "math/bits" - - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonflags" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonopts" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonwire" -) - -// Encoder is a streaming encoder from raw JSON tokens and values. -// It is used to write a stream of top-level JSON values, -// each terminated with a newline character. -// -// [Encoder.WriteToken] and [Encoder.WriteValue] calls may be interleaved. -// For example, the following JSON value: -// -// {"name":"value","array":[null,false,true,3.14159],"object":{"k":"v"}} -// -// can be composed with the following calls (ignoring errors for brevity): -// -// e.WriteToken(BeginObject) // { -// e.WriteToken(String("name")) // "name" -// e.WriteToken(String("value")) // "value" -// e.WriteValue(Value(`"array"`)) // "array" -// e.WriteToken(BeginArray) // [ -// e.WriteToken(Null) // null -// e.WriteToken(False) // false -// e.WriteValue(Value("true")) // true -// e.WriteToken(Float(3.14159)) // 3.14159 -// e.WriteToken(EndArray) // ] -// e.WriteValue(Value(`"object"`)) // "object" -// e.WriteValue(Value(`{"k":"v"}`)) // {"k":"v"} -// e.WriteToken(EndObject) // } -// -// The above is one of many possible sequence of calls and -// may not represent the most sensible method to call for any given token/value. -// For example, it is probably more common to call [Encoder.WriteToken] with a string -// for object names. -type Encoder struct { - s encoderState -} - -// encoderState is the low-level state of Encoder. -// It has exported fields and method for use by the "json" package. -type encoderState struct { - state - encodeBuffer - jsonopts.Struct - - SeenPointers map[any]struct{} // only used when marshaling; identical to json.seenPointers -} - -// encodeBuffer is a buffer split into 2 segments: -// -// - buf[0:len(buf)] // written (but unflushed) portion of the buffer -// - buf[len(buf):cap(buf)] // unused portion of the buffer -type encodeBuffer struct { - Buf []byte // may alias wr if it is a bytes.Buffer - - // baseOffset is added to len(buf) to obtain the absolute offset - // relative to the start of io.Writer stream. - baseOffset int64 - - wr io.Writer - - // maxValue is the approximate maximum Value size passed to WriteValue. - maxValue int - // availBuffer is the buffer returned by the AvailableBuffer method. - availBuffer []byte // always has zero length - // bufStats is statistics about buffer utilization. - // It is only used with pooled encoders in pools.go. - bufStats bufferStatistics -} - -// NewEncoder constructs a new streaming encoder writing to w -// configured with the provided options. -// It flushes the internal buffer when the buffer is sufficiently full or -// when a top-level value has been written. -// -// If w is a [bytes.Buffer], then the encoder appends directly into the buffer -// without copying the contents from an intermediate buffer. -func NewEncoder(w io.Writer, opts ...Options) *Encoder { - e := new(Encoder) - e.Reset(w, opts...) - return e -} - -// Reset resets an encoder such that it is writing afresh to w and -// configured with the provided options. Reset must not be called on -// a Encoder passed to the [encoding/json/v2.MarshalerTo.MarshalJSONTo] method -// or the [encoding/json/v2.MarshalToFunc] function. -func (e *Encoder) Reset(w io.Writer, opts ...Options) { - switch { - case e == nil: - panic("jsontext: invalid nil Encoder") - case w == nil: - panic("jsontext: invalid nil io.Writer") - case e.s.Flags.Get(jsonflags.WithinArshalCall): - panic("jsontext: cannot reset Encoder passed to json.MarshalerTo") - } - // Reuse the buffer if it does not alias a previous [bytes.Buffer]. - b := e.s.Buf[:0] - if _, ok := e.s.wr.(*bytes.Buffer); ok { - b = nil - } - e.s.reset(b, w, opts...) -} - -func (e *encoderState) reset(b []byte, w io.Writer, opts ...Options) { - e.state.reset() - e.encodeBuffer = encodeBuffer{Buf: b, wr: w, availBuffer: e.availBuffer, bufStats: e.bufStats} - if bb, ok := w.(*bytes.Buffer); ok && bb != nil { - e.Buf = bb.AvailableBuffer() // alias the unused buffer of bb - } - opts2 := jsonopts.Struct{} // avoid mutating e.Struct in case it is part of opts - opts2.Join(opts...) - e.Struct = opts2 - if e.Flags.Get(jsonflags.Multiline) { - if !e.Flags.Has(jsonflags.SpaceAfterColon) { - e.Flags.Set(jsonflags.SpaceAfterColon | 1) - } - if !e.Flags.Has(jsonflags.SpaceAfterComma) { - e.Flags.Set(jsonflags.SpaceAfterComma | 0) - } - if !e.Flags.Has(jsonflags.Indent) { - e.Flags.Set(jsonflags.Indent | 1) - e.Indent = "\t" - } - } -} - -// Options returns the options used to construct the decoder and -// may additionally contain semantic options passed to a -// [encoding/json/v2.MarshalEncode] call. -// -// If operating within -// a [encoding/json/v2.MarshalerTo.MarshalJSONTo] method call or -// a [encoding/json/v2.MarshalToFunc] function call, -// then the returned options are only valid within the call. -func (e *Encoder) Options() Options { - return &e.s.Struct -} - -// NeedFlush determines whether to flush at this point. -func (e *encoderState) NeedFlush() bool { - // NOTE: This function is carefully written to be inlinable. - - // Avoid flushing if e.wr is nil since there is no underlying writer. - // Flush if less than 25% of the capacity remains. - // Flushing at some constant fraction ensures that the buffer stops growing - // so long as the largest Token or Value fits within that unused capacity. - return e.wr != nil && (e.Tokens.Depth() == 1 || len(e.Buf) > 3*cap(e.Buf)/4) -} - -// Flush flushes the buffer to the underlying io.Writer. -// It may append a trailing newline after the top-level value. -func (e *encoderState) Flush() error { - if e.wr == nil || e.avoidFlush() { - return nil - } - - // In streaming mode, always emit a newline after the top-level value. - if e.Tokens.Depth() == 1 && !e.Flags.Get(jsonflags.OmitTopLevelNewline) { - e.Buf = append(e.Buf, '\n') - } - - // Inform objectNameStack that we are about to flush the buffer content. - e.Names.copyQuotedBuffer(e.Buf) - - // Specialize bytes.Buffer for better performance. - if bb, ok := e.wr.(*bytes.Buffer); ok { - // If e.buf already aliases the internal buffer of bb, - // then the Write call simply increments the internal offset, - // otherwise Write operates as expected. - // See https://go.dev/issue/42986. - n, _ := bb.Write(e.Buf) // never fails unless bb is nil - e.baseOffset += int64(n) - - // If the internal buffer of bytes.Buffer is too small, - // append operations elsewhere in the Encoder may grow the buffer. - // This would be semantically correct, but hurts performance. - // As such, ensure 25% of the current length is always available - // to reduce the probability that other appends must allocate. - if avail := bb.Available(); avail < bb.Len()/4 { - bb.Grow(avail + 1) - } - - e.Buf = bb.AvailableBuffer() - return nil - } - - // Flush the internal buffer to the underlying io.Writer. - n, err := e.wr.Write(e.Buf) - e.baseOffset += int64(n) - if err != nil { - // In the event of an error, preserve the unflushed portion. - // Thus, write errors aren't fatal so long as the io.Writer - // maintains consistent state after errors. - if n > 0 { - e.Buf = e.Buf[:copy(e.Buf, e.Buf[n:])] - } - return &ioError{action: "write", err: err} - } - e.Buf = e.Buf[:0] - - // Check whether to grow the buffer. - // Note that cap(e.buf) may already exceed maxBufferSize since - // an append elsewhere already grew it to store a large token. - const maxBufferSize = 4 << 10 - const growthSizeFactor = 2 // higher value is faster - const growthRateFactor = 2 // higher value is slower - // By default, grow if below the maximum buffer size. - grow := cap(e.Buf) <= maxBufferSize/growthSizeFactor - // Growing can be expensive, so only grow - // if a sufficient number of bytes have been processed. - grow = grow && int64(cap(e.Buf)) < e.previousOffsetEnd()/growthRateFactor - if grow { - e.Buf = make([]byte, 0, cap(e.Buf)*growthSizeFactor) - } - - return nil -} -func (d *encodeBuffer) offsetAt(pos int) int64 { return d.baseOffset + int64(pos) } -func (e *encodeBuffer) previousOffsetEnd() int64 { return e.baseOffset + int64(len(e.Buf)) } -func (e *encodeBuffer) unflushedBuffer() []byte { return e.Buf } - -// avoidFlush indicates whether to avoid flushing to ensure there is always -// enough in the buffer to unwrite the last object member if it were empty. -func (e *encoderState) avoidFlush() bool { - switch { - case e.Tokens.Last.Length() == 0: - // Never flush after BeginObject or BeginArray since we don't know yet - // if the object or array will end up being empty. - return true - case e.Tokens.Last.needObjectValue(): - // Never flush before the object value since we don't know yet - // if the object value will end up being empty. - return true - case e.Tokens.Last.NeedObjectName() && len(e.Buf) >= 2: - // Never flush after the object value if it does turn out to be empty. - switch string(e.Buf[len(e.Buf)-2:]) { - case `ll`, `""`, `{}`, `[]`: // last two bytes of every empty value - return true - } - } - return false -} - -// UnwriteEmptyObjectMember unwrites the last object member if it is empty -// and reports whether it performed an unwrite operation. -func (e *encoderState) UnwriteEmptyObjectMember(prevName *string) bool { - if last := e.Tokens.Last; !last.isObject() || !last.NeedObjectName() || last.Length() == 0 { - panic("BUG: must be called on an object after writing a value") - } - - // The flushing logic is modified to never flush a trailing empty value. - // The encoder never writes trailing whitespace eagerly. - b := e.unflushedBuffer() - - // Detect whether the last value was empty. - var n int - if len(b) >= 3 { - switch string(b[len(b)-2:]) { - case "ll": // last two bytes of `null` - n = len(`null`) - case `""`: - // It is possible for a non-empty string to have `""` as a suffix - // if the second to the last quote was escaped. - if b[len(b)-3] == '\\' { - return false // e.g., `"\""` is not empty - } - n = len(`""`) - case `{}`: - n = len(`{}`) - case `[]`: - n = len(`[]`) - } - } - if n == 0 { - return false - } - - // Unwrite the value, whitespace, colon, name, whitespace, and comma. - b = b[:len(b)-n] - b = jsonwire.TrimSuffixWhitespace(b) - b = jsonwire.TrimSuffixByte(b, ':') - b = jsonwire.TrimSuffixString(b) - b = jsonwire.TrimSuffixWhitespace(b) - b = jsonwire.TrimSuffixByte(b, ',') - e.Buf = b // store back truncated unflushed buffer - - // Undo state changes. - e.Tokens.Last.decrement() // for object member value - e.Tokens.Last.decrement() // for object member name - if !e.Flags.Get(jsonflags.AllowDuplicateNames) { - if e.Tokens.Last.isActiveNamespace() { - e.Namespaces.Last().removeLast() - } - } - e.Names.clearLast() - if prevName != nil { - e.Names.copyQuotedBuffer(e.Buf) // required by objectNameStack.replaceLastUnquotedName - e.Names.replaceLastUnquotedName(*prevName) - } - return true -} - -// UnwriteOnlyObjectMemberName unwrites the only object member name -// and returns the unquoted name. -func (e *encoderState) UnwriteOnlyObjectMemberName() string { - if last := e.Tokens.Last; !last.isObject() || last.Length() != 1 { - panic("BUG: must be called on an object after writing first name") - } - - // Unwrite the name and whitespace. - b := jsonwire.TrimSuffixString(e.Buf) - isVerbatim := bytes.IndexByte(e.Buf[len(b):], '\\') < 0 - name := string(jsonwire.UnquoteMayCopy(e.Buf[len(b):], isVerbatim)) - e.Buf = jsonwire.TrimSuffixWhitespace(b) - - // Undo state changes. - e.Tokens.Last.decrement() - if !e.Flags.Get(jsonflags.AllowDuplicateNames) { - if e.Tokens.Last.isActiveNamespace() { - e.Namespaces.Last().removeLast() - } - } - e.Names.clearLast() - return name -} - -// WriteToken writes the next token and advances the internal write offset. -// -// The provided token kind must be consistent with the JSON grammar. -// For example, it is an error to provide a number when the encoder -// is expecting an object name (which is always a string), or -// to provide an end object delimiter when the encoder is finishing an array. -// If the provided token is invalid, then it reports a [SyntacticError] and -// the internal state remains unchanged. The offset reported -// in [SyntacticError] will be relative to the [Encoder.OutputOffset]. -func (e *Encoder) WriteToken(t Token) error { - return e.s.WriteToken(t) -} -func (e *encoderState) WriteToken(t Token) error { - k := t.Kind() - b := e.Buf // use local variable to avoid mutating e in case of error - - // Append any delimiters or optional whitespace. - b = e.Tokens.MayAppendDelim(b, k) - if e.Flags.Get(jsonflags.AnyWhitespace) { - b = e.appendWhitespace(b, k) - } - pos := len(b) // offset before the token - - // Append the token to the output and to the state machine. - var err error - switch k { - case 'n': - b = append(b, "null"...) - err = e.Tokens.appendLiteral() - case 'f': - b = append(b, "false"...) - err = e.Tokens.appendLiteral() - case 't': - b = append(b, "true"...) - err = e.Tokens.appendLiteral() - case '"': - if b, err = t.appendString(b, &e.Flags); err != nil { - break - } - if e.Tokens.Last.NeedObjectName() { - if !e.Flags.Get(jsonflags.AllowDuplicateNames) { - if !e.Tokens.Last.isValidNamespace() { - err = errInvalidNamespace - break - } - if e.Tokens.Last.isActiveNamespace() && !e.Namespaces.Last().insertQuoted(b[pos:], false) { - err = wrapWithObjectName(ErrDuplicateName, b[pos:]) - break - } - } - e.Names.ReplaceLastQuotedOffset(pos) // only replace if insertQuoted succeeds - } - err = e.Tokens.appendString() - case '0': - if b, err = t.appendNumber(b, &e.Flags); err != nil { - break - } - err = e.Tokens.appendNumber() - case '{': - b = append(b, '{') - if err = e.Tokens.pushObject(); err != nil { - break - } - e.Names.push() - if !e.Flags.Get(jsonflags.AllowDuplicateNames) { - e.Namespaces.push() - } - case '}': - b = append(b, '}') - if err = e.Tokens.popObject(); err != nil { - break - } - e.Names.pop() - if !e.Flags.Get(jsonflags.AllowDuplicateNames) { - e.Namespaces.pop() - } - case '[': - b = append(b, '[') - err = e.Tokens.pushArray() - case ']': - b = append(b, ']') - err = e.Tokens.popArray() - default: - err = errInvalidToken - } - if err != nil { - return wrapSyntacticError(e, err, pos, +1) - } - - // Finish off the buffer and store it back into e. - e.Buf = b - if e.NeedFlush() { - return e.Flush() - } - return nil -} - -// AppendRaw appends either a raw string (without double quotes) or number. -// Specify safeASCII if the string output is guaranteed to be ASCII -// without any characters (including '<', '>', and '&') that need escaping, -// otherwise this will validate whether the string needs escaping. -// The appended bytes for a JSON number must be valid. -// -// This is a specialized implementation of Encoder.WriteValue -// that allows appending directly into the buffer. -// It is only called from marshal logic in the "json" package. -func (e *encoderState) AppendRaw(k Kind, safeASCII bool, appendFn func([]byte) ([]byte, error)) error { - b := e.Buf // use local variable to avoid mutating e in case of error - - // Append any delimiters or optional whitespace. - b = e.Tokens.MayAppendDelim(b, k) - if e.Flags.Get(jsonflags.AnyWhitespace) { - b = e.appendWhitespace(b, k) - } - pos := len(b) // offset before the token - - var err error - switch k { - case '"': - // Append directly into the encoder buffer by assuming that - // most of the time none of the characters need escaping. - b = append(b, '"') - if b, err = appendFn(b); err != nil { - return err - } - b = append(b, '"') - - // Check whether we need to escape the string and if necessary - // copy it to a scratch buffer and then escape it back. - isVerbatim := safeASCII || !jsonwire.NeedEscape(b[pos+len(`"`):len(b)-len(`"`)]) - if !isVerbatim { - var err error - b2 := append(e.availBuffer, b[pos+len(`"`):len(b)-len(`"`)]...) - b, err = jsonwire.AppendQuote(b[:pos], string(b2), &e.Flags) - e.availBuffer = b2[:0] - if err != nil { - return wrapSyntacticError(e, err, pos, +1) - } - } - - // Update the state machine. - if e.Tokens.Last.NeedObjectName() { - if !e.Flags.Get(jsonflags.AllowDuplicateNames) { - if !e.Tokens.Last.isValidNamespace() { - return wrapSyntacticError(e, err, pos, +1) - } - if e.Tokens.Last.isActiveNamespace() && !e.Namespaces.Last().insertQuoted(b[pos:], isVerbatim) { - err = wrapWithObjectName(ErrDuplicateName, b[pos:]) - return wrapSyntacticError(e, err, pos, +1) - } - } - e.Names.ReplaceLastQuotedOffset(pos) // only replace if insertQuoted succeeds - } - if err := e.Tokens.appendString(); err != nil { - return wrapSyntacticError(e, err, pos, +1) - } - case '0': - if b, err = appendFn(b); err != nil { - return err - } - if err := e.Tokens.appendNumber(); err != nil { - return wrapSyntacticError(e, err, pos, +1) - } - default: - panic("BUG: invalid kind") - } - - // Finish off the buffer and store it back into e. - e.Buf = b - if e.NeedFlush() { - return e.Flush() - } - return nil -} - -// WriteValue writes the next raw value and advances the internal write offset. -// The Encoder does not simply copy the provided value verbatim, but -// parses it to ensure that it is syntactically valid and reformats it -// according to how the Encoder is configured to format whitespace and strings. -// If [AllowInvalidUTF8] is specified, then any invalid UTF-8 is mangled -// as the Unicode replacement character, U+FFFD. -// -// The provided value kind must be consistent with the JSON grammar -// (see examples on [Encoder.WriteToken]). If the provided value is invalid, -// then it reports a [SyntacticError] and the internal state remains unchanged. -// The offset reported in [SyntacticError] will be relative to the -// [Encoder.OutputOffset] plus the offset into v of any encountered syntax error. -func (e *Encoder) WriteValue(v Value) error { - return e.s.WriteValue(v) -} -func (e *encoderState) WriteValue(v Value) error { - e.maxValue |= len(v) // bitwise OR is a fast approximation of max - - k := v.Kind() - b := e.Buf // use local variable to avoid mutating e in case of error - - // Append any delimiters or optional whitespace. - b = e.Tokens.MayAppendDelim(b, k) - if e.Flags.Get(jsonflags.AnyWhitespace) { - b = e.appendWhitespace(b, k) - } - pos := len(b) // offset before the value - - // Append the value the output. - var n int - n += jsonwire.ConsumeWhitespace(v[n:]) - b, m, err := e.reformatValue(b, v[n:], e.Tokens.Depth()) - if err != nil { - return wrapSyntacticError(e, err, pos+n+m, +1) - } - n += m - n += jsonwire.ConsumeWhitespace(v[n:]) - if len(v) > n { - err = jsonwire.NewInvalidCharacterError(v[n:], "after top-level value") - return wrapSyntacticError(e, err, pos+n, 0) - } - - // Append the kind to the state machine. - switch k { - case 'n', 'f', 't': - err = e.Tokens.appendLiteral() - case '"': - if e.Tokens.Last.NeedObjectName() { - if !e.Flags.Get(jsonflags.AllowDuplicateNames) { - if !e.Tokens.Last.isValidNamespace() { - err = errInvalidNamespace - break - } - if e.Tokens.Last.isActiveNamespace() && !e.Namespaces.Last().insertQuoted(b[pos:], false) { - err = wrapWithObjectName(ErrDuplicateName, b[pos:]) - break - } - } - e.Names.ReplaceLastQuotedOffset(pos) // only replace if insertQuoted succeeds - } - err = e.Tokens.appendString() - case '0': - err = e.Tokens.appendNumber() - case '{': - if err = e.Tokens.pushObject(); err != nil { - break - } - if err = e.Tokens.popObject(); err != nil { - panic("BUG: popObject should never fail immediately after pushObject: " + err.Error()) - } - if e.Flags.Get(jsonflags.ReorderRawObjects) { - mustReorderObjects(b[pos:]) - } - case '[': - if err = e.Tokens.pushArray(); err != nil { - break - } - if err = e.Tokens.popArray(); err != nil { - panic("BUG: popArray should never fail immediately after pushArray: " + err.Error()) - } - if e.Flags.Get(jsonflags.ReorderRawObjects) { - mustReorderObjects(b[pos:]) - } - } - if err != nil { - return wrapSyntacticError(e, err, pos, +1) - } - - // Finish off the buffer and store it back into e. - e.Buf = b - if e.NeedFlush() { - return e.Flush() - } - return nil -} - -// CountNextDelimWhitespace counts the number of bytes of delimiter and -// whitespace bytes assuming the upcoming token is a JSON value. -// This method is used for error reporting at the semantic layer. -func (e *encoderState) CountNextDelimWhitespace() (n int) { - const next = Kind('"') // arbitrary kind as next JSON value - delim := e.Tokens.needDelim(next) - if delim > 0 { - n += len(",") | len(":") - } - if delim == ':' { - if e.Flags.Get(jsonflags.SpaceAfterColon) { - n += len(" ") - } - } else { - if delim == ',' && e.Flags.Get(jsonflags.SpaceAfterComma) { - n += len(" ") - } - if e.Flags.Get(jsonflags.Multiline) { - if m := e.Tokens.NeedIndent(next); m > 0 { - n += len("\n") + len(e.IndentPrefix) + (m-1)*len(e.Indent) - } - } - } - return n -} - -// appendWhitespace appends whitespace that immediately precedes the next token. -func (e *encoderState) appendWhitespace(b []byte, next Kind) []byte { - if delim := e.Tokens.needDelim(next); delim == ':' { - if e.Flags.Get(jsonflags.SpaceAfterColon) { - b = append(b, ' ') - } - } else { - if delim == ',' && e.Flags.Get(jsonflags.SpaceAfterComma) { - b = append(b, ' ') - } - if e.Flags.Get(jsonflags.Multiline) { - b = e.AppendIndent(b, e.Tokens.NeedIndent(next)) - } - } - return b -} - -// AppendIndent appends the appropriate number of indentation characters -// for the current nested level, n. -func (e *encoderState) AppendIndent(b []byte, n int) []byte { - if n == 0 { - return b - } - b = append(b, '\n') - b = append(b, e.IndentPrefix...) - for ; n > 1; n-- { - b = append(b, e.Indent...) - } - return b -} - -// reformatValue parses a JSON value from the start of src and -// appends it to the end of dst, reformatting whitespace and strings as needed. -// It returns the extended dst buffer and the number of consumed input bytes. -func (e *encoderState) reformatValue(dst []byte, src Value, depth int) ([]byte, int, error) { - // TODO: Should this update ValueFlags as input? - if len(src) == 0 { - return dst, 0, io.ErrUnexpectedEOF - } - switch k := Kind(src[0]).normalize(); k { - case 'n': - if jsonwire.ConsumeNull(src) == 0 { - n, err := jsonwire.ConsumeLiteral(src, "null") - return dst, n, err - } - return append(dst, "null"...), len("null"), nil - case 'f': - if jsonwire.ConsumeFalse(src) == 0 { - n, err := jsonwire.ConsumeLiteral(src, "false") - return dst, n, err - } - return append(dst, "false"...), len("false"), nil - case 't': - if jsonwire.ConsumeTrue(src) == 0 { - n, err := jsonwire.ConsumeLiteral(src, "true") - return dst, n, err - } - return append(dst, "true"...), len("true"), nil - case '"': - if n := jsonwire.ConsumeSimpleString(src); n > 0 { - dst = append(dst, src[:n]...) // copy simple strings verbatim - return dst, n, nil - } - return jsonwire.ReformatString(dst, src, &e.Flags) - case '0': - if n := jsonwire.ConsumeSimpleNumber(src); n > 0 && !e.Flags.Get(jsonflags.CanonicalizeNumbers) { - dst = append(dst, src[:n]...) // copy simple numbers verbatim - return dst, n, nil - } - return jsonwire.ReformatNumber(dst, src, &e.Flags) - case '{': - return e.reformatObject(dst, src, depth) - case '[': - return e.reformatArray(dst, src, depth) - default: - return dst, 0, jsonwire.NewInvalidCharacterError(src, "at start of value") - } -} - -// reformatObject parses a JSON object from the start of src and -// appends it to the end of src, reformatting whitespace and strings as needed. -// It returns the extended dst buffer and the number of consumed input bytes. -func (e *encoderState) reformatObject(dst []byte, src Value, depth int) ([]byte, int, error) { - // Append object begin. - if len(src) == 0 || src[0] != '{' { - panic("BUG: reformatObject must be called with a buffer that starts with '{'") - } else if depth == maxNestingDepth+1 { - return dst, 0, errMaxDepth - } - dst = append(dst, '{') - n := len("{") - - // Append (possible) object end. - n += jsonwire.ConsumeWhitespace(src[n:]) - if uint(len(src)) <= uint(n) { - return dst, n, io.ErrUnexpectedEOF - } - if src[n] == '}' { - dst = append(dst, '}') - n += len("}") - return dst, n, nil - } - - var err error - var names *objectNamespace - if !e.Flags.Get(jsonflags.AllowDuplicateNames) { - e.Namespaces.push() - defer e.Namespaces.pop() - names = e.Namespaces.Last() - } - depth++ - for { - // Append optional newline and indentation. - if e.Flags.Get(jsonflags.Multiline) { - dst = e.AppendIndent(dst, depth) - } - - // Append object name. - n += jsonwire.ConsumeWhitespace(src[n:]) - if uint(len(src)) <= uint(n) { - return dst, n, io.ErrUnexpectedEOF - } - m := jsonwire.ConsumeSimpleString(src[n:]) - isVerbatim := m > 0 - if isVerbatim { - dst = append(dst, src[n:n+m]...) - } else { - dst, m, err = jsonwire.ReformatString(dst, src[n:], &e.Flags) - if err != nil { - return dst, n + m, err - } - } - quotedName := src[n : n+m] - if !e.Flags.Get(jsonflags.AllowDuplicateNames) && !names.insertQuoted(quotedName, isVerbatim) { - return dst, n, wrapWithObjectName(ErrDuplicateName, quotedName) - } - n += m - - // Append colon. - n += jsonwire.ConsumeWhitespace(src[n:]) - if uint(len(src)) <= uint(n) { - return dst, n, wrapWithObjectName(io.ErrUnexpectedEOF, quotedName) - } - if src[n] != ':' { - err = jsonwire.NewInvalidCharacterError(src[n:], "after object name (expecting ':')") - return dst, n, wrapWithObjectName(err, quotedName) - } - dst = append(dst, ':') - n += len(":") - if e.Flags.Get(jsonflags.SpaceAfterColon) { - dst = append(dst, ' ') - } - - // Append object value. - n += jsonwire.ConsumeWhitespace(src[n:]) - if uint(len(src)) <= uint(n) { - return dst, n, wrapWithObjectName(io.ErrUnexpectedEOF, quotedName) - } - dst, m, err = e.reformatValue(dst, src[n:], depth) - if err != nil { - return dst, n + m, wrapWithObjectName(err, quotedName) - } - n += m - - // Append comma or object end. - n += jsonwire.ConsumeWhitespace(src[n:]) - if uint(len(src)) <= uint(n) { - return dst, n, io.ErrUnexpectedEOF - } - switch src[n] { - case ',': - dst = append(dst, ',') - if e.Flags.Get(jsonflags.SpaceAfterComma) { - dst = append(dst, ' ') - } - n += len(",") - continue - case '}': - if e.Flags.Get(jsonflags.Multiline) { - dst = e.AppendIndent(dst, depth-1) - } - dst = append(dst, '}') - n += len("}") - return dst, n, nil - default: - return dst, n, jsonwire.NewInvalidCharacterError(src[n:], "after object value (expecting ',' or '}')") - } - } -} - -// reformatArray parses a JSON array from the start of src and -// appends it to the end of dst, reformatting whitespace and strings as needed. -// It returns the extended dst buffer and the number of consumed input bytes. -func (e *encoderState) reformatArray(dst []byte, src Value, depth int) ([]byte, int, error) { - // Append array begin. - if len(src) == 0 || src[0] != '[' { - panic("BUG: reformatArray must be called with a buffer that starts with '['") - } else if depth == maxNestingDepth+1 { - return dst, 0, errMaxDepth - } - dst = append(dst, '[') - n := len("[") - - // Append (possible) array end. - n += jsonwire.ConsumeWhitespace(src[n:]) - if uint(len(src)) <= uint(n) { - return dst, n, io.ErrUnexpectedEOF - } - if src[n] == ']' { - dst = append(dst, ']') - n += len("]") - return dst, n, nil - } - - var idx int64 - var err error - depth++ - for { - // Append optional newline and indentation. - if e.Flags.Get(jsonflags.Multiline) { - dst = e.AppendIndent(dst, depth) - } - - // Append array value. - n += jsonwire.ConsumeWhitespace(src[n:]) - if uint(len(src)) <= uint(n) { - return dst, n, io.ErrUnexpectedEOF - } - var m int - dst, m, err = e.reformatValue(dst, src[n:], depth) - if err != nil { - return dst, n + m, wrapWithArrayIndex(err, idx) - } - n += m - - // Append comma or array end. - n += jsonwire.ConsumeWhitespace(src[n:]) - if uint(len(src)) <= uint(n) { - return dst, n, io.ErrUnexpectedEOF - } - switch src[n] { - case ',': - dst = append(dst, ',') - if e.Flags.Get(jsonflags.SpaceAfterComma) { - dst = append(dst, ' ') - } - n += len(",") - idx++ - continue - case ']': - if e.Flags.Get(jsonflags.Multiline) { - dst = e.AppendIndent(dst, depth-1) - } - dst = append(dst, ']') - n += len("]") - return dst, n, nil - default: - return dst, n, jsonwire.NewInvalidCharacterError(src[n:], "after array value (expecting ',' or ']')") - } - } -} - -// OutputOffset returns the current output byte offset. It gives the location -// of the next byte immediately after the most recently written token or value. -// The number of bytes actually written to the underlying [io.Writer] may be less -// than this offset due to internal buffering effects. -func (e *Encoder) OutputOffset() int64 { - return e.s.previousOffsetEnd() -} - -// AvailableBuffer returns a zero-length buffer with a possible non-zero capacity. -// This buffer is intended to be used to populate a [Value] -// being passed to an immediately succeeding [Encoder.WriteValue] call. -// -// Example usage: -// -// b := d.AvailableBuffer() -// b = append(b, '"') -// b = appendString(b, v) // append the string formatting of v -// b = append(b, '"') -// ... := d.WriteValue(b) -// -// It is the user's responsibility to ensure that the value is valid JSON. -func (e *Encoder) AvailableBuffer() []byte { - // NOTE: We don't return e.buf[len(e.buf):cap(e.buf)] since WriteValue would - // need to take special care to avoid mangling the data while reformatting. - // WriteValue can't easily identify whether the input Value aliases e.buf - // without using unsafe.Pointer. Thus, we just return a different buffer. - // Should this ever alias e.buf, we need to consider how it operates with - // the specialized performance optimization for bytes.Buffer. - n := 1 << bits.Len(uint(e.s.maxValue|63)) // fast approximation for max length - if cap(e.s.availBuffer) < n { - e.s.availBuffer = make([]byte, 0, n) - } - return e.s.availBuffer -} - -// StackDepth returns the depth of the state machine for written JSON data. -// Each level on the stack represents a nested JSON object or array. -// It is incremented whenever an [BeginObject] or [BeginArray] token is encountered -// and decremented whenever an [EndObject] or [EndArray] token is encountered. -// The depth is zero-indexed, where zero represents the top-level JSON value. -func (e *Encoder) StackDepth() int { - // NOTE: Keep in sync with Decoder.StackDepth. - return e.s.Tokens.Depth() - 1 -} - -// StackIndex returns information about the specified stack level. -// It must be a number between 0 and [Encoder.StackDepth], inclusive. -// For each level, it reports the kind: -// -// - 0 for a level of zero, -// - '{' for a level representing a JSON object, and -// - '[' for a level representing a JSON array. -// -// It also reports the length of that JSON object or array. -// Each name and value in a JSON object is counted separately, -// so the effective number of members would be half the length. -// A complete JSON object must have an even length. -func (e *Encoder) StackIndex(i int) (Kind, int64) { - // NOTE: Keep in sync with Decoder.StackIndex. - switch s := e.s.Tokens.index(i); { - case i > 0 && s.isObject(): - return '{', s.Length() - case i > 0 && s.isArray(): - return '[', s.Length() - default: - return 0, s.Length() - } -} - -// StackPointer returns a JSON Pointer (RFC 6901) to the most recently written value. -func (e *Encoder) StackPointer() Pointer { - return Pointer(e.s.AppendStackPointer(nil, -1)) -} - -func (e *encoderState) AppendStackPointer(b []byte, where int) []byte { - e.Names.copyQuotedBuffer(e.Buf) - return e.state.appendStackPointer(b, where) -} diff --git a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext/errors.go b/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext/errors.go deleted file mode 100644 index 1af86d5b6..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext/errors.go +++ /dev/null @@ -1,180 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package jsontext - -import ( - "bytes" - "io" - "strconv" - - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonwire" -) - -const errorPrefix = "jsontext: " - -type ioError struct { - action string // either "read" or "write" - err error -} - -func (e *ioError) Error() string { - return errorPrefix + e.action + " error: " + e.err.Error() -} -func (e *ioError) Unwrap() error { - return e.err -} - -// SyntacticError is a description of a syntactic error that occurred when -// encoding or decoding JSON according to the grammar. -// -// The contents of this error as produced by this package may change over time. -type SyntacticError struct { - requireKeyedLiterals - nonComparable - - // ByteOffset indicates that an error occurred after this byte offset. - ByteOffset int64 - // JSONPointer indicates that an error occurred within this JSON value - // as indicated using the JSON Pointer notation (see RFC 6901). - JSONPointer Pointer - - // Err is the underlying error. - Err error -} - -// wrapSyntacticError wraps an error and annotates it with a precise location -// using the provided [encoderState] or [decoderState]. -// If err is an [ioError] or [io.EOF], then it is not wrapped. -// -// It takes a relative offset pos that can be resolved into -// an absolute offset using state.offsetAt. -// -// It takes a where that specify how the JSON pointer is derived. -// If the underlying error is a [pointerSuffixError], -// then the suffix is appended to the derived pointer. -func wrapSyntacticError(state interface { - offsetAt(pos int) int64 - AppendStackPointer(b []byte, where int) []byte -}, err error, pos, where int) error { - if _, ok := err.(*ioError); err == io.EOF || ok { - return err - } - offset := state.offsetAt(pos) - ptr := state.AppendStackPointer(nil, where) - if serr, ok := err.(*pointerSuffixError); ok { - ptr = serr.appendPointer(ptr) - err = serr.error - } - if d, ok := state.(*decoderState); ok && err == errMismatchDelim { - where := "at start of value" - if len(d.Tokens.Stack) > 0 && d.Tokens.Last.Length() > 0 { - switch { - case d.Tokens.Last.isArray(): - where = "after array element (expecting ',' or ']')" - ptr = []byte(Pointer(ptr).Parent()) // problem is with parent array - case d.Tokens.Last.isObject(): - where = "after object value (expecting ',' or '}')" - ptr = []byte(Pointer(ptr).Parent()) // problem is with parent object - } - } - err = jsonwire.NewInvalidCharacterError(d.buf[pos:], where) - } - return &SyntacticError{ByteOffset: offset, JSONPointer: Pointer(ptr), Err: err} -} - -func (e *SyntacticError) Error() string { - pointer := e.JSONPointer - offset := e.ByteOffset - b := []byte(errorPrefix) - if e.Err != nil { - b = append(b, e.Err.Error()...) - if e.Err == ErrDuplicateName { - b = strconv.AppendQuote(append(b, ' '), pointer.LastToken()) - pointer = pointer.Parent() - offset = 0 // not useful to print offset for duplicate names - } - } else { - b = append(b, "syntactic error"...) - } - if pointer != "" { - b = strconv.AppendQuote(append(b, " within "...), jsonwire.TruncatePointer(string(pointer), 100)) - } - if offset > 0 { - b = strconv.AppendInt(append(b, " after offset "...), offset, 10) - } - return string(b) -} - -func (e *SyntacticError) Unwrap() error { - return e.Err -} - -// pointerSuffixError represents a JSON pointer suffix to be appended -// to [SyntacticError.JSONPointer]. It is an internal error type -// used within this package and does not appear in the public API. -// -// This type is primarily used to annotate errors in Encoder.WriteValue -// and Decoder.ReadValue with precise positions. -// At the time WriteValue or ReadValue is called, a JSON pointer to the -// upcoming value can be constructed using the Encoder/Decoder state. -// However, tracking pointers within values during normal operation -// would incur a performance penalty in the error-free case. -// -// To provide precise error locations without this overhead, -// the error is wrapped with object names or array indices -// as the call stack is popped when an error occurs. -// Since this happens in reverse order, pointerSuffixError holds -// the pointer in reverse and is only later reversed when appending to -// the pointer prefix. -// -// For example, if the encoder is at "/alpha/bravo/charlie" -// and an error occurs in WriteValue at "/xray/yankee/zulu", then -// the final pointer should be "/alpha/bravo/charlie/xray/yankee/zulu". -// -// As pointerSuffixError is populated during the error return path, -// it first contains "/zulu", then "/zulu/yankee", -// and finally "/zulu/yankee/xray". -// These tokens are reversed and concatenated to "/alpha/bravo/charlie" -// to form the full pointer. -type pointerSuffixError struct { - error - - // reversePointer is a JSON pointer, but with each token in reverse order. - reversePointer []byte -} - -// wrapWithObjectName wraps err with a JSON object name access, -// which must be a valid quoted JSON string. -func wrapWithObjectName(err error, quotedName []byte) error { - serr, _ := err.(*pointerSuffixError) - if serr == nil { - serr = &pointerSuffixError{error: err} - } - name := jsonwire.UnquoteMayCopy(quotedName, false) - serr.reversePointer = appendEscapePointerName(append(serr.reversePointer, '/'), name) - return serr -} - -// wrapWithArrayIndex wraps err with a JSON array index access. -func wrapWithArrayIndex(err error, index int64) error { - serr, _ := err.(*pointerSuffixError) - if serr == nil { - serr = &pointerSuffixError{error: err} - } - serr.reversePointer = strconv.AppendUint(append(serr.reversePointer, '/'), uint64(index), 10) - return serr -} - -// appendPointer appends the path encoded in e to the end of pointer. -func (e *pointerSuffixError) appendPointer(pointer []byte) []byte { - // Copy each token in reversePointer to the end of pointer in reverse order. - // Double reversal means that the appended suffix is now in forward order. - bi, bo := e.reversePointer, pointer - for len(bi) > 0 { - i := bytes.LastIndexByte(bi, '/') - bi, bo = bi[:i], append(bo, bi[i:]...) - } - return bo -} diff --git a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext/export.go b/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext/export.go deleted file mode 100644 index b30bb99ed..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext/export.go +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2023 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package jsontext - -import ( - "io" - - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal" -) - -// Internal is for internal use only. -// This is exempt from the Go compatibility agreement. -var Internal exporter - -type exporter struct{} - -// Export exposes internal functionality from "jsontext" to "json". -// This cannot be dynamically called by other packages since -// they cannot obtain a reference to the internal.AllowInternalUse value. -func (exporter) Export(p *internal.NotForPublicUse) export { - if p != &internal.AllowInternalUse { - panic("unauthorized call to Export") - } - return export{} -} - -// The export type exposes functionality to packages with visibility to -// the internal.AllowInternalUse variable. The "json" package uses this -// to modify low-level state in the Encoder and Decoder types. -// It mutates the state directly instead of calling ReadToken or WriteToken -// since this is more performant. The public APIs need to track state to ensure -// that users are constructing a valid JSON value, but the "json" implementation -// guarantees that it emits valid JSON by the structure of the code itself. -type export struct{} - -// Encoder returns a pointer to the underlying encoderState. -func (export) Encoder(e *Encoder) *encoderState { return &e.s } - -// Decoder returns a pointer to the underlying decoderState. -func (export) Decoder(d *Decoder) *decoderState { return &d.s } - -func (export) GetBufferedEncoder(o ...Options) *Encoder { - return getBufferedEncoder(o...) -} -func (export) PutBufferedEncoder(e *Encoder) { - putBufferedEncoder(e) -} - -func (export) GetStreamingEncoder(w io.Writer, o ...Options) *Encoder { - return getStreamingEncoder(w, o...) -} -func (export) PutStreamingEncoder(e *Encoder) { - putStreamingEncoder(e) -} - -func (export) GetBufferedDecoder(b []byte, o ...Options) *Decoder { - return getBufferedDecoder(b, o...) -} -func (export) PutBufferedDecoder(d *Decoder) { - putBufferedDecoder(d) -} - -func (export) GetStreamingDecoder(r io.Reader, o ...Options) *Decoder { - return getStreamingDecoder(r, o...) -} -func (export) PutStreamingDecoder(d *Decoder) { - putStreamingDecoder(d) -} - -func (export) IsIOError(err error) bool { - _, ok := err.(*ioError) - return ok -} diff --git a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext/options.go b/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext/options.go deleted file mode 100644 index e973b58d6..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext/options.go +++ /dev/null @@ -1,302 +0,0 @@ -// Copyright 2023 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package jsontext - -import ( - "strings" - - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonflags" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonopts" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonwire" -) - -// Options configures [NewEncoder], [Encoder.Reset], [NewDecoder], -// and [Decoder.Reset] with specific features. -// Each function takes in a variadic list of options, where properties -// set in latter options override the value of previously set properties. -// -// There is a single Options type, which is used with both encoding and decoding. -// Some options affect both operations, while others only affect one operation: -// -// - [AllowDuplicateNames] affects encoding and decoding -// - [AllowInvalidUTF8] affects encoding and decoding -// - [EscapeForHTML] affects encoding only -// - [EscapeForJS] affects encoding only -// - [PreserveRawStrings] affects encoding only -// - [CanonicalizeRawInts] affects encoding only -// - [CanonicalizeRawFloats] affects encoding only -// - [ReorderRawObjects] affects encoding only -// - [SpaceAfterColon] affects encoding only -// - [SpaceAfterComma] affects encoding only -// - [Multiline] affects encoding only -// - [WithIndent] affects encoding only -// - [WithIndentPrefix] affects encoding only -// -// Options that do not affect a particular operation are ignored. -// -// The Options type is identical to [encoding/json.Options] and -// [encoding/json/v2.Options]. Options from the other packages may -// be passed to functionality in this package, but are ignored. -// Options from this package may be used with the other packages. -type Options = jsonopts.Options - -// AllowDuplicateNames specifies that JSON objects may contain -// duplicate member names. Disabling the duplicate name check may provide -// performance benefits, but breaks compliance with RFC 7493, section 2.3. -// The input or output will still be compliant with RFC 8259, -// which leaves the handling of duplicate names as unspecified behavior. -// -// This affects either encoding or decoding. -func AllowDuplicateNames(v bool) Options { - if v { - return jsonflags.AllowDuplicateNames | 1 - } else { - return jsonflags.AllowDuplicateNames | 0 - } -} - -// AllowInvalidUTF8 specifies that JSON strings may contain invalid UTF-8, -// which will be mangled as the Unicode replacement character, U+FFFD. -// This causes the encoder or decoder to break compliance with -// RFC 7493, section 2.1, and RFC 8259, section 8.1. -// -// This affects either encoding or decoding. -func AllowInvalidUTF8(v bool) Options { - if v { - return jsonflags.AllowInvalidUTF8 | 1 - } else { - return jsonflags.AllowInvalidUTF8 | 0 - } -} - -// EscapeForHTML specifies that '<', '>', and '&' characters within JSON strings -// should be escaped as a hexadecimal Unicode codepoint (e.g., \u003c) so that -// the output is safe to embed within HTML. -// -// This only affects encoding and is ignored when decoding. -func EscapeForHTML(v bool) Options { - if v { - return jsonflags.EscapeForHTML | 1 - } else { - return jsonflags.EscapeForHTML | 0 - } -} - -// EscapeForJS specifies that U+2028 and U+2029 characters within JSON strings -// should be escaped as a hexadecimal Unicode codepoint (e.g., \u2028) so that -// the output is valid to embed within JavaScript. See RFC 8259, section 12. -// -// This only affects encoding and is ignored when decoding. -func EscapeForJS(v bool) Options { - if v { - return jsonflags.EscapeForJS | 1 - } else { - return jsonflags.EscapeForJS | 0 - } -} - -// PreserveRawStrings specifies that when encoding a raw JSON string in a -// [Token] or [Value], pre-escaped sequences -// in a JSON string are preserved to the output. -// However, raw strings still respect [EscapeForHTML] and [EscapeForJS] -// such that the relevant characters are escaped. -// If [AllowInvalidUTF8] is enabled, bytes of invalid UTF-8 -// are preserved to the output. -// -// This only affects encoding and is ignored when decoding. -func PreserveRawStrings(v bool) Options { - if v { - return jsonflags.PreserveRawStrings | 1 - } else { - return jsonflags.PreserveRawStrings | 0 - } -} - -// CanonicalizeRawInts specifies that when encoding a raw JSON -// integer number (i.e., a number without a fraction and exponent) in a -// [Token] or [Value], the number is canonicalized -// according to RFC 8785, section 3.2.2.3. As a special case, -// the number -0 is canonicalized as 0. -// -// JSON numbers are treated as IEEE 754 double precision numbers. -// Any numbers with precision beyond what is representable by that form -// will lose their precision when canonicalized. For example, -// integer values beyond ±2⁵³ will lose their precision. -// For example, 1234567890123456789 is formatted as 1234567890123456800. -// -// This only affects encoding and is ignored when decoding. -func CanonicalizeRawInts(v bool) Options { - if v { - return jsonflags.CanonicalizeRawInts | 1 - } else { - return jsonflags.CanonicalizeRawInts | 0 - } -} - -// CanonicalizeRawFloats specifies that when encoding a raw JSON -// floating-point number (i.e., a number with a fraction or exponent) in a -// [Token] or [Value], the number is canonicalized -// according to RFC 8785, section 3.2.2.3. As a special case, -// the number -0 is canonicalized as 0. -// -// JSON numbers are treated as IEEE 754 double precision numbers. -// It is safe to canonicalize a serialized single precision number and -// parse it back as a single precision number and expect the same value. -// If a number exceeds ±1.7976931348623157e+308, which is the maximum -// finite number, then it saturated at that value and formatted as such. -// -// This only affects encoding and is ignored when decoding. -func CanonicalizeRawFloats(v bool) Options { - if v { - return jsonflags.CanonicalizeRawFloats | 1 - } else { - return jsonflags.CanonicalizeRawFloats | 0 - } -} - -// ReorderRawObjects specifies that when encoding a raw JSON object in a -// [Value], the object members are reordered according to -// RFC 8785, section 3.2.3. -// -// This only affects encoding and is ignored when decoding. -func ReorderRawObjects(v bool) Options { - if v { - return jsonflags.ReorderRawObjects | 1 - } else { - return jsonflags.ReorderRawObjects | 0 - } -} - -// SpaceAfterColon specifies that the JSON output should emit a space character -// after each colon separator following a JSON object name. -// If false, then no space character appears after the colon separator. -// -// This only affects encoding and is ignored when decoding. -func SpaceAfterColon(v bool) Options { - if v { - return jsonflags.SpaceAfterColon | 1 - } else { - return jsonflags.SpaceAfterColon | 0 - } -} - -// SpaceAfterComma specifies that the JSON output should emit a space character -// after each comma separator following a JSON object value or array element. -// If false, then no space character appears after the comma separator. -// -// This only affects encoding and is ignored when decoding. -func SpaceAfterComma(v bool) Options { - if v { - return jsonflags.SpaceAfterComma | 1 - } else { - return jsonflags.SpaceAfterComma | 0 - } -} - -// Multiline specifies that the JSON output should expand to multiple lines, -// where every JSON object member or JSON array element appears on -// a new, indented line according to the nesting depth. -// -// If [SpaceAfterColon] is not specified, then the default is true. -// If [SpaceAfterComma] is not specified, then the default is false. -// If [WithIndent] is not specified, then the default is "\t". -// -// If set to false, then the output is a single-line, -// where the only whitespace emitted is determined by the current -// values of [SpaceAfterColon] and [SpaceAfterComma]. -// -// This only affects encoding and is ignored when decoding. -func Multiline(v bool) Options { - if v { - return jsonflags.Multiline | 1 - } else { - return jsonflags.Multiline | 0 - } -} - -// WithIndent specifies that the encoder should emit multiline output -// where each element in a JSON object or array begins on a new, indented line -// beginning with the indent prefix (see [WithIndentPrefix]) -// followed by one or more copies of indent according to the nesting depth. -// The indent must only be composed of space or tab characters. -// -// If the intent to emit indented output without a preference for -// the particular indent string, then use [Multiline] instead. -// -// This only affects encoding and is ignored when decoding. -// Use of this option implies [Multiline] being set to true. -func WithIndent(indent string) Options { - // Fast-path: Return a constant for common indents, which avoids allocating. - // These are derived from analyzing the Go module proxy on 2023-07-01. - switch indent { - case "\t": - return jsonopts.Indent("\t") // ~14k usages - case " ": - return jsonopts.Indent(" ") // ~18k usages - case " ": - return jsonopts.Indent(" ") // ~1.7k usages - case " ": - return jsonopts.Indent(" ") // ~52k usages - case " ": - return jsonopts.Indent(" ") // ~12k usages - case "": - return jsonopts.Indent("") // ~1.5k usages - } - - // Otherwise, allocate for this unique value. - if s := strings.Trim(indent, " \t"); len(s) > 0 { - panic("json: invalid character " + jsonwire.QuoteRune(s) + " in indent") - } - return jsonopts.Indent(indent) -} - -// WithIndentPrefix specifies that the encoder should emit multiline output -// where each element in a JSON object or array begins on a new, indented line -// beginning with the indent prefix followed by one or more copies of indent -// (see [WithIndent]) according to the nesting depth. -// The prefix must only be composed of space or tab characters. -// -// This only affects encoding and is ignored when decoding. -// Use of this option implies [Multiline] being set to true. -func WithIndentPrefix(prefix string) Options { - if s := strings.Trim(prefix, " \t"); len(s) > 0 { - panic("json: invalid character " + jsonwire.QuoteRune(s) + " in indent prefix") - } - return jsonopts.IndentPrefix(prefix) -} - -/* -// TODO(https://go.dev/issue/56733): Implement WithByteLimit and WithDepthLimit. -// Remember to also update the "Security Considerations" section. - -// WithByteLimit sets a limit on the number of bytes of input or output bytes -// that may be consumed or produced for each top-level JSON value. -// If a [Decoder] or [Encoder] method call would need to consume/produce -// more than a total of n bytes to make progress on the top-level JSON value, -// then the call will report an error. -// Whitespace before and within the top-level value are counted against the limit. -// Whitespace after a top-level value are counted against the limit -// for the next top-level value. -// -// A non-positive limit is equivalent to no limit at all. -// If unspecified, the default limit is no limit at all. -// This affects either encoding or decoding. -func WithByteLimit(n int64) Options { - return jsonopts.ByteLimit(max(n, 0)) -} - -// WithDepthLimit sets a limit on the maximum depth of JSON nesting -// that may be consumed or produced for each top-level JSON value. -// If a [Decoder] or [Encoder] method call would need to consume or produce -// a depth greater than n to make progress on the top-level JSON value, -// then the call will report an error. -// -// A non-positive limit is equivalent to no limit at all. -// If unspecified, the default limit is 10000. -// This affects either encoding or decoding. -func WithDepthLimit(n int) Options { - return jsonopts.DepthLimit(max(n, 0)) -} -*/ diff --git a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext/pools.go b/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext/pools.go deleted file mode 100644 index 63941baac..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext/pools.go +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package jsontext - -import ( - "bytes" - "io" - "math/bits" - "sync" -) - -// TODO(https://go.dev/issue/47657): Use sync.PoolOf. - -var ( - // This owns the internal buffer since there is no io.Writer to output to. - // Since the buffer can get arbitrarily large in normal usage, - // there is statistical tracking logic to determine whether to recycle - // the internal buffer or not based on a history of utilization. - bufferedEncoderPool = &sync.Pool{New: func() any { return new(Encoder) }} - - // This owns the internal buffer, but it is only used to temporarily store - // buffered JSON before flushing it to the underlying io.Writer. - // In a sufficiently efficient streaming mode, we do not expect the buffer - // to grow arbitrarily large. Thus, we avoid recycling large buffers. - streamingEncoderPool = &sync.Pool{New: func() any { return new(Encoder) }} - - // This does not own the internal buffer since - // it is taken directly from the provided bytes.Buffer. - bytesBufferEncoderPool = &sync.Pool{New: func() any { return new(Encoder) }} -) - -// bufferStatistics is statistics to track buffer utilization. -// It is used to determine whether to recycle a buffer or not -// to avoid https://go.dev/issue/23199. -type bufferStatistics struct { - strikes int // number of times the buffer was under-utilized - prevLen int // length of previous buffer -} - -func getBufferedEncoder(opts ...Options) *Encoder { - e := bufferedEncoderPool.Get().(*Encoder) - if e.s.Buf == nil { - // Round up to nearest 2ⁿ to make best use of malloc size classes. - // See runtime/sizeclasses.go on Go1.15. - // Logical OR with 63 to ensure 64 as the minimum buffer size. - n := 1 << bits.Len(uint(e.s.bufStats.prevLen|63)) - e.s.Buf = make([]byte, 0, n) - } - e.s.reset(e.s.Buf[:0], nil, opts...) - return e -} -func putBufferedEncoder(e *Encoder) { - // Recycle large buffers only if sufficiently utilized. - // If a buffer is under-utilized enough times sequentially, - // then it is discarded, ensuring that a single large buffer - // won't be kept alive by a continuous stream of small usages. - // - // The worst case utilization is computed as: - // MIN_UTILIZATION_THRESHOLD / (1 + MAX_NUM_STRIKES) - // - // For the constants chosen below, this is (25%)/(1+4) ⇒ 5%. - // This may seem low, but it ensures a lower bound on - // the absolute worst-case utilization. Without this check, - // this would be theoretically 0%, which is infinitely worse. - // - // See https://go.dev/issue/27735. - switch { - case cap(e.s.Buf) <= 4<<10: // always recycle buffers smaller than 4KiB - e.s.bufStats.strikes = 0 - case cap(e.s.Buf)/4 <= len(e.s.Buf): // at least 25% utilization - e.s.bufStats.strikes = 0 - case e.s.bufStats.strikes < 4: // at most 4 strikes - e.s.bufStats.strikes++ - default: // discard the buffer; too large and too often under-utilized - e.s.bufStats.strikes = 0 - e.s.bufStats.prevLen = len(e.s.Buf) // heuristic for size to allocate next time - e.s.Buf = nil - } - bufferedEncoderPool.Put(e) -} - -func getStreamingEncoder(w io.Writer, opts ...Options) *Encoder { - if _, ok := w.(*bytes.Buffer); ok { - e := bytesBufferEncoderPool.Get().(*Encoder) - e.s.reset(nil, w, opts...) // buffer taken from bytes.Buffer - return e - } else { - e := streamingEncoderPool.Get().(*Encoder) - e.s.reset(e.s.Buf[:0], w, opts...) // preserve existing buffer - return e - } -} -func putStreamingEncoder(e *Encoder) { - if _, ok := e.s.wr.(*bytes.Buffer); ok { - bytesBufferEncoderPool.Put(e) - } else { - if cap(e.s.Buf) > 64<<10 { - e.s.Buf = nil // avoid pinning arbitrarily large amounts of memory - } - streamingEncoderPool.Put(e) - } -} - -var ( - // This does not own the internal buffer since it is externally provided. - bufferedDecoderPool = &sync.Pool{New: func() any { return new(Decoder) }} - - // This owns the internal buffer, but it is only used to temporarily store - // buffered JSON fetched from the underlying io.Reader. - // In a sufficiently efficient streaming mode, we do not expect the buffer - // to grow arbitrarily large. Thus, we avoid recycling large buffers. - streamingDecoderPool = &sync.Pool{New: func() any { return new(Decoder) }} - - // This does not own the internal buffer since - // it is taken directly from the provided bytes.Buffer. - bytesBufferDecoderPool = bufferedDecoderPool -) - -func getBufferedDecoder(b []byte, opts ...Options) *Decoder { - d := bufferedDecoderPool.Get().(*Decoder) - d.s.reset(b, nil, opts...) - return d -} -func putBufferedDecoder(d *Decoder) { - bufferedDecoderPool.Put(d) -} - -func getStreamingDecoder(r io.Reader, opts ...Options) *Decoder { - if _, ok := r.(*bytes.Buffer); ok { - d := bytesBufferDecoderPool.Get().(*Decoder) - d.s.reset(nil, r, opts...) // buffer taken from bytes.Buffer - return d - } else { - d := streamingDecoderPool.Get().(*Decoder) - d.s.reset(d.s.buf[:0], r, opts...) // preserve existing buffer - return d - } -} -func putStreamingDecoder(d *Decoder) { - if _, ok := d.s.rd.(*bytes.Buffer); ok { - bytesBufferDecoderPool.Put(d) - } else { - if cap(d.s.buf) > 64<<10 { - d.s.buf = nil // avoid pinning arbitrarily large amounts of memory - } - streamingDecoderPool.Put(d) - } -} diff --git a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext/quote.go b/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext/quote.go deleted file mode 100644 index 77897b43f..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext/quote.go +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2023 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package jsontext - -import ( - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonflags" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonwire" -) - -// AppendQuote appends a double-quoted JSON string literal representing src -// to dst and returns the extended buffer. -// It uses the minimal string representation per RFC 8785, section 3.2.2.2. -// Invalid UTF-8 bytes are replaced with the Unicode replacement character -// and an error is returned at the end indicating the presence of invalid UTF-8. -// The dst must not overlap with the src. -func AppendQuote[Bytes ~[]byte | ~string](dst []byte, src Bytes) ([]byte, error) { - dst, err := jsonwire.AppendQuote(dst, src, &jsonflags.Flags{}) - if err != nil { - err = &SyntacticError{Err: err} - } - return dst, err -} - -// AppendUnquote appends the decoded interpretation of src as a -// double-quoted JSON string literal to dst and returns the extended buffer. -// The input src must be a JSON string without any surrounding whitespace. -// Invalid UTF-8 bytes are replaced with the Unicode replacement character -// and an error is returned at the end indicating the presence of invalid UTF-8. -// Any trailing bytes after the JSON string literal results in an error. -// The dst must not overlap with the src. -func AppendUnquote[Bytes ~[]byte | ~string](dst []byte, src Bytes) ([]byte, error) { - dst, err := jsonwire.AppendUnquote(dst, src) - if err != nil { - err = &SyntacticError{Err: err} - } - return dst, err -} diff --git a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext/state.go b/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext/state.go deleted file mode 100644 index fdbfd5d3d..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext/state.go +++ /dev/null @@ -1,826 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package jsontext - -import ( - "errors" - "iter" - "math" - "strconv" - "strings" - "unicode/utf8" - - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonwire" -) - -// ErrDuplicateName indicates that a JSON token could not be -// encoded or decoded because it results in a duplicate JSON object name. -// This error is directly wrapped within a [SyntacticError] when produced. -// -// The name of a duplicate JSON object member can be extracted as: -// -// err := ... -// var serr jsontext.SyntacticError -// if errors.As(err, &serr) && serr.Err == jsontext.ErrDuplicateName { -// ptr := serr.JSONPointer // JSON pointer to duplicate name -// name := ptr.LastToken() // duplicate name itself -// ... -// } -// -// This error is only returned if [AllowDuplicateNames] is false. -var ErrDuplicateName = errors.New("duplicate object member name") - -// ErrNonStringName indicates that a JSON token could not be -// encoded or decoded because it is not a string, -// as required for JSON object names according to RFC 8259, section 4. -// This error is directly wrapped within a [SyntacticError] when produced. -var ErrNonStringName = errors.New("object member name must be a string") - -var ( - errMissingValue = errors.New("missing value after object name") - errMismatchDelim = errors.New("mismatching structural token for object or array") - errMaxDepth = errors.New("exceeded max depth") - - errInvalidNamespace = errors.New("object namespace is in an invalid state") -) - -// Per RFC 8259, section 9, implementations may enforce a maximum depth. -// Such a limit is necessary to prevent stack overflows. -const maxNestingDepth = 10000 - -type state struct { - // Tokens validates whether the next token kind is valid. - Tokens stateMachine - - // Names is a stack of object names. - Names objectNameStack - - // Namespaces is a stack of object namespaces. - // For performance reasons, Encoder or Decoder may not update this - // if Marshal or Unmarshal is able to track names in a more efficient way. - // See makeMapArshaler and makeStructArshaler. - // Not used if AllowDuplicateNames is true. - Namespaces objectNamespaceStack -} - -// needObjectValue reports whether the next token should be an object value. -// This method is used by [wrapSyntacticError]. -func (s *state) needObjectValue() bool { - return s.Tokens.Last.needObjectValue() -} - -func (s *state) reset() { - s.Tokens.reset() - s.Names.reset() - s.Namespaces.reset() -} - -// Pointer is a JSON Pointer (RFC 6901) that references a particular JSON value -// relative to the root of the top-level JSON value. -// -// A Pointer is a slash-separated list of tokens, where each token is -// either a JSON object name or an index to a JSON array element -// encoded as a base-10 integer value. -// It is impossible to distinguish between an array index and an object name -// (that happens to be an base-10 encoded integer) without also knowing -// the structure of the top-level JSON value that the pointer refers to. -// -// There is exactly one representation of a pointer to a particular value, -// so comparability of Pointer values is equivalent to checking whether -// they both point to the exact same value. -type Pointer string - -// IsValid reports whether p is a valid JSON Pointer according to RFC 6901. -// Note that the concatenation of two valid pointers produces a valid pointer. -func (p Pointer) IsValid() bool { - for i, r := range p { - switch { - case r == '~' && (i+1 == len(p) || (p[i+1] != '0' && p[i+1] != '1')): - return false // invalid escape - case r == '\ufffd' && !strings.HasPrefix(string(p[i:]), "\ufffd"): - return false // invalid UTF-8 - } - } - return len(p) == 0 || p[0] == '/' -} - -// Contains reports whether the JSON value that p points to -// is equal to or contains the JSON value that pc points to. -func (p Pointer) Contains(pc Pointer) bool { - // Invariant: len(p) <= len(pc) if p.Contains(pc) - suffix, ok := strings.CutPrefix(string(pc), string(p)) - return ok && (suffix == "" || suffix[0] == '/') -} - -// Parent strips off the last token and returns the remaining pointer. -// The parent of an empty p is an empty string. -func (p Pointer) Parent() Pointer { - return p[:max(strings.LastIndexByte(string(p), '/'), 0)] -} - -// LastToken returns the last token in the pointer. -// The last token of an empty p is an empty string. -func (p Pointer) LastToken() string { - last := p[max(strings.LastIndexByte(string(p), '/'), 0):] - return unescapePointerToken(strings.TrimPrefix(string(last), "/")) -} - -// AppendToken appends a token to the end of p and returns the full pointer. -func (p Pointer) AppendToken(tok string) Pointer { - return Pointer(appendEscapePointerName([]byte(p+"/"), tok)) -} - -// TODO: Add Pointer.AppendTokens, -// but should this take in a ...string or an iter.Seq[string]? - -// Tokens returns an iterator over the reference tokens in the JSON pointer, -// starting from the first token until the last token (unless stopped early). -func (p Pointer) Tokens() iter.Seq[string] { - return func(yield func(string) bool) { - for len(p) > 0 { - p = Pointer(strings.TrimPrefix(string(p), "/")) - i := min(uint(strings.IndexByte(string(p), '/')), uint(len(p))) - if !yield(unescapePointerToken(string(p)[:i])) { - return - } - p = p[i:] - } - } -} - -func unescapePointerToken(token string) string { - if strings.Contains(token, "~") { - // Per RFC 6901, section 3, unescape '~' and '/' characters. - token = strings.ReplaceAll(token, "~1", "/") - token = strings.ReplaceAll(token, "~0", "~") - } - return token -} - -// appendStackPointer appends a JSON Pointer (RFC 6901) to the current value. -// -// - If where is -1, then it points to the previously processed token. -// -// - If where is 0, then it points to the parent JSON object or array, -// or an object member if in-between an object member key and value. -// This is useful when the position is ambiguous whether -// we are interested in the previous or next token, or -// when we are uncertain whether the next token -// continues or terminates the current object or array. -// -// - If where is +1, then it points to the next expected value, -// assuming that it continues the current JSON object or array. -// As a special case, if the next token is a JSON object name, -// then it points to the parent JSON object. -// -// Invariant: Must call s.names.copyQuotedBuffer beforehand. -func (s state) appendStackPointer(b []byte, where int) []byte { - var objectDepth int - for i := 1; i < s.Tokens.Depth(); i++ { - e := s.Tokens.index(i) - arrayDelta := -1 // by default point to previous array element - if isLast := i == s.Tokens.Depth()-1; isLast { - switch { - case where < 0 && e.Length() == 0 || where == 0 && !e.needObjectValue() || where > 0 && e.NeedObjectName(): - return b - case where > 0 && e.isArray(): - arrayDelta = 0 // point to next array element - } - } - switch { - case e.isObject(): - b = appendEscapePointerName(append(b, '/'), s.Names.getUnquoted(objectDepth)) - objectDepth++ - case e.isArray(): - b = strconv.AppendUint(append(b, '/'), uint64(e.Length()+int64(arrayDelta)), 10) - } - } - return b -} - -func appendEscapePointerName[Bytes ~[]byte | ~string](b []byte, name Bytes) []byte { - for _, r := range string(name) { - // Per RFC 6901, section 3, escape '~' and '/' characters. - switch r { - case '~': - b = append(b, "~0"...) - case '/': - b = append(b, "~1"...) - default: - b = utf8.AppendRune(b, r) - } - } - return b -} - -// stateMachine is a push-down automaton that validates whether -// a sequence of tokens is valid or not according to the JSON grammar. -// It is useful for both encoding and decoding. -// -// It is a stack where each entry represents a nested JSON object or array. -// The stack has a minimum depth of 1 where the first level is a -// virtual JSON array to handle a stream of top-level JSON values. -// The top-level virtual JSON array is special in that it doesn't require commas -// between each JSON value. -// -// For performance, most methods are carefully written to be inlinable. -// The zero value is a valid state machine ready for use. -type stateMachine struct { - Stack []stateEntry - Last stateEntry -} - -// reset resets the state machine. -// The machine always starts with a minimum depth of 1. -func (m *stateMachine) reset() { - m.Stack = m.Stack[:0] - if cap(m.Stack) > 1<<10 { - m.Stack = nil - } - m.Last = stateTypeArray -} - -// Depth is the current nested depth of JSON objects and arrays. -// It is one-indexed (i.e., top-level values have a depth of 1). -func (m stateMachine) Depth() int { - return len(m.Stack) + 1 -} - -// index returns a reference to the ith entry. -// It is only valid until the next push method call. -func (m *stateMachine) index(i int) *stateEntry { - if i == len(m.Stack) { - return &m.Last - } - return &m.Stack[i] -} - -// DepthLength reports the current nested depth and -// the length of the last JSON object or array. -func (m stateMachine) DepthLength() (int, int64) { - return m.Depth(), m.Last.Length() -} - -// appendLiteral appends a JSON literal as the next token in the sequence. -// If an error is returned, the state is not mutated. -func (m *stateMachine) appendLiteral() error { - switch { - case m.Last.NeedObjectName(): - return ErrNonStringName - case !m.Last.isValidNamespace(): - return errInvalidNamespace - default: - m.Last.Increment() - return nil - } -} - -// appendString appends a JSON string as the next token in the sequence. -// If an error is returned, the state is not mutated. -func (m *stateMachine) appendString() error { - switch { - case !m.Last.isValidNamespace(): - return errInvalidNamespace - default: - m.Last.Increment() - return nil - } -} - -// appendNumber appends a JSON number as the next token in the sequence. -// If an error is returned, the state is not mutated. -func (m *stateMachine) appendNumber() error { - return m.appendLiteral() -} - -// pushObject appends a JSON begin object token as next in the sequence. -// If an error is returned, the state is not mutated. -func (m *stateMachine) pushObject() error { - switch { - case m.Last.NeedObjectName(): - return ErrNonStringName - case !m.Last.isValidNamespace(): - return errInvalidNamespace - case len(m.Stack) == maxNestingDepth: - return errMaxDepth - default: - m.Last.Increment() - m.Stack = append(m.Stack, m.Last) - m.Last = stateTypeObject - return nil - } -} - -// popObject appends a JSON end object token as next in the sequence. -// If an error is returned, the state is not mutated. -func (m *stateMachine) popObject() error { - switch { - case !m.Last.isObject(): - return errMismatchDelim - case m.Last.needObjectValue(): - return errMissingValue - case !m.Last.isValidNamespace(): - return errInvalidNamespace - default: - m.Last = m.Stack[len(m.Stack)-1] - m.Stack = m.Stack[:len(m.Stack)-1] - return nil - } -} - -// pushArray appends a JSON begin array token as next in the sequence. -// If an error is returned, the state is not mutated. -func (m *stateMachine) pushArray() error { - switch { - case m.Last.NeedObjectName(): - return ErrNonStringName - case !m.Last.isValidNamespace(): - return errInvalidNamespace - case len(m.Stack) == maxNestingDepth: - return errMaxDepth - default: - m.Last.Increment() - m.Stack = append(m.Stack, m.Last) - m.Last = stateTypeArray - return nil - } -} - -// popArray appends a JSON end array token as next in the sequence. -// If an error is returned, the state is not mutated. -func (m *stateMachine) popArray() error { - switch { - case !m.Last.isArray() || len(m.Stack) == 0: // forbid popping top-level virtual JSON array - return errMismatchDelim - case !m.Last.isValidNamespace(): - return errInvalidNamespace - default: - m.Last = m.Stack[len(m.Stack)-1] - m.Stack = m.Stack[:len(m.Stack)-1] - return nil - } -} - -// NeedIndent reports whether indent whitespace should be injected. -// A zero value means that no whitespace should be injected. -// A positive value means '\n', indentPrefix, and (n-1) copies of indentBody -// should be appended to the output immediately before the next token. -func (m stateMachine) NeedIndent(next Kind) (n int) { - willEnd := next == '}' || next == ']' - switch { - case m.Depth() == 1: - return 0 // top-level values are never indented - case m.Last.Length() == 0 && willEnd: - return 0 // an empty object or array is never indented - case m.Last.Length() == 0 || m.Last.needImplicitComma(next): - return m.Depth() - case willEnd: - return m.Depth() - 1 - default: - return 0 - } -} - -// MayAppendDelim appends a colon or comma that may precede the next token. -func (m stateMachine) MayAppendDelim(b []byte, next Kind) []byte { - switch { - case m.Last.needImplicitColon(): - return append(b, ':') - case m.Last.needImplicitComma(next) && len(m.Stack) != 0: // comma not needed for top-level values - return append(b, ',') - default: - return b - } -} - -// needDelim reports whether a colon or comma token should be implicitly emitted -// before the next token of the specified kind. -// A zero value means no delimiter should be emitted. -func (m stateMachine) needDelim(next Kind) (delim byte) { - switch { - case m.Last.needImplicitColon(): - return ':' - case m.Last.needImplicitComma(next) && len(m.Stack) != 0: // comma not needed for top-level values - return ',' - default: - return 0 - } -} - -// InvalidateDisabledNamespaces marks all disabled namespaces as invalid. -// -// For efficiency, Marshal and Unmarshal may disable namespaces since there are -// more efficient ways to track duplicate names. However, if an error occurs, -// the namespaces in Encoder or Decoder will be left in an inconsistent state. -// Mark the namespaces as invalid so that future method calls on -// Encoder or Decoder will return an error. -func (m *stateMachine) InvalidateDisabledNamespaces() { - for i := range m.Depth() { - e := m.index(i) - if !e.isActiveNamespace() { - e.invalidateNamespace() - } - } -} - -// stateEntry encodes several artifacts within a single unsigned integer: -// - whether this represents a JSON object or array, -// - whether this object should check for duplicate names, and -// - how many elements are in this JSON object or array. -type stateEntry uint64 - -const ( - // The type mask (1 bit) records whether this is a JSON object or array. - stateTypeMask stateEntry = 0x8000_0000_0000_0000 - stateTypeObject stateEntry = 0x8000_0000_0000_0000 - stateTypeArray stateEntry = 0x0000_0000_0000_0000 - - // The name check mask (2 bit) records whether to update - // the namespaces for the current JSON object and - // whether the namespace is valid. - stateNamespaceMask stateEntry = 0x6000_0000_0000_0000 - stateDisableNamespace stateEntry = 0x4000_0000_0000_0000 - stateInvalidNamespace stateEntry = 0x2000_0000_0000_0000 - - // The count mask (61 bits) records the number of elements. - stateCountMask stateEntry = 0x1fff_ffff_ffff_ffff - stateCountLSBMask stateEntry = 0x0000_0000_0000_0001 - stateCountOdd stateEntry = 0x0000_0000_0000_0001 - stateCountEven stateEntry = 0x0000_0000_0000_0000 -) - -// Length reports the number of elements in the JSON object or array. -// Each name and value in an object entry is treated as a separate element. -func (e stateEntry) Length() int64 { - return int64(e & stateCountMask) -} - -// isObject reports whether this is a JSON object. -func (e stateEntry) isObject() bool { - return e&stateTypeMask == stateTypeObject -} - -// isArray reports whether this is a JSON array. -func (e stateEntry) isArray() bool { - return e&stateTypeMask == stateTypeArray -} - -// NeedObjectName reports whether the next token must be a JSON string, -// which is necessary for JSON object names. -func (e stateEntry) NeedObjectName() bool { - return e&(stateTypeMask|stateCountLSBMask) == stateTypeObject|stateCountEven -} - -// needImplicitColon reports whether an colon should occur next, -// which always occurs after JSON object names. -func (e stateEntry) needImplicitColon() bool { - return e.needObjectValue() -} - -// needObjectValue reports whether the next token must be a JSON value, -// which is necessary after every JSON object name. -func (e stateEntry) needObjectValue() bool { - return e&(stateTypeMask|stateCountLSBMask) == stateTypeObject|stateCountOdd -} - -// needImplicitComma reports whether an comma should occur next, -// which always occurs after a value in a JSON object or array -// before the next value (or name). -func (e stateEntry) needImplicitComma(next Kind) bool { - return !e.needObjectValue() && e.Length() > 0 && next != '}' && next != ']' -} - -// Increment increments the number of elements for the current object or array. -// This assumes that overflow won't practically be an issue since -// 1< 0. -func (e *stateEntry) decrement() { - (*e)-- -} - -// DisableNamespace disables the JSON object namespace such that the -// Encoder or Decoder no longer updates the namespace. -func (e *stateEntry) DisableNamespace() { - *e |= stateDisableNamespace -} - -// isActiveNamespace reports whether the JSON object namespace is actively -// being updated and used for duplicate name checks. -func (e stateEntry) isActiveNamespace() bool { - return e&(stateDisableNamespace) == 0 -} - -// invalidateNamespace marks the JSON object namespace as being invalid. -func (e *stateEntry) invalidateNamespace() { - *e |= stateInvalidNamespace -} - -// isValidNamespace reports whether the JSON object namespace is valid. -func (e stateEntry) isValidNamespace() bool { - return e&(stateInvalidNamespace) == 0 -} - -// objectNameStack is a stack of names when descending into a JSON object. -// In contrast to objectNamespaceStack, this only has to remember a single name -// per JSON object. -// -// This data structure may contain offsets to encodeBuffer or decodeBuffer. -// It violates clean abstraction of layers, but is significantly more efficient. -// This ensures that popping and pushing in the common case is a trivial -// push/pop of an offset integer. -// -// The zero value is an empty names stack ready for use. -type objectNameStack struct { - // offsets is a stack of offsets for each name. - // A non-negative offset is the ending offset into the local names buffer. - // A negative offset is the bit-wise inverse of a starting offset into - // a remote buffer (e.g., encodeBuffer or decodeBuffer). - // A math.MinInt offset at the end implies that the last object is empty. - // Invariant: Positive offsets always occur before negative offsets. - offsets []int - // unquotedNames is a back-to-back concatenation of names. - unquotedNames []byte -} - -func (ns *objectNameStack) reset() { - ns.offsets = ns.offsets[:0] - ns.unquotedNames = ns.unquotedNames[:0] - if cap(ns.offsets) > 1<<6 { - ns.offsets = nil // avoid pinning arbitrarily large amounts of memory - } - if cap(ns.unquotedNames) > 1<<10 { - ns.unquotedNames = nil // avoid pinning arbitrarily large amounts of memory - } -} - -func (ns *objectNameStack) length() int { - return len(ns.offsets) -} - -// getUnquoted retrieves the ith unquoted name in the stack. -// It returns an empty string if the last object is empty. -// -// Invariant: Must call copyQuotedBuffer beforehand. -func (ns *objectNameStack) getUnquoted(i int) []byte { - ns.ensureCopiedBuffer() - if i == 0 { - return ns.unquotedNames[:ns.offsets[0]] - } else { - return ns.unquotedNames[ns.offsets[i-1]:ns.offsets[i-0]] - } -} - -// invalidOffset indicates that the last JSON object currently has no name. -const invalidOffset = math.MinInt - -// push descends into a nested JSON object. -func (ns *objectNameStack) push() { - ns.offsets = append(ns.offsets, invalidOffset) -} - -// ReplaceLastQuotedOffset replaces the last name with the starting offset -// to the quoted name in some remote buffer. All offsets provided must be -// relative to the same buffer until copyQuotedBuffer is called. -func (ns *objectNameStack) ReplaceLastQuotedOffset(i int) { - // Use bit-wise inversion instead of naive multiplication by -1 to avoid - // ambiguity regarding zero (which is a valid offset into the names field). - // Bit-wise inversion is mathematically equivalent to -i-1, - // such that 0 becomes -1, 1 becomes -2, and so forth. - // This ensures that remote offsets are always negative. - ns.offsets[len(ns.offsets)-1] = ^i -} - -// replaceLastUnquotedName replaces the last name with the provided name. -// -// Invariant: Must call copyQuotedBuffer beforehand. -func (ns *objectNameStack) replaceLastUnquotedName(s string) { - ns.ensureCopiedBuffer() - var startOffset int - if len(ns.offsets) > 1 { - startOffset = ns.offsets[len(ns.offsets)-2] - } - ns.unquotedNames = append(ns.unquotedNames[:startOffset], s...) - ns.offsets[len(ns.offsets)-1] = len(ns.unquotedNames) -} - -// clearLast removes any name in the last JSON object. -// It is semantically equivalent to ns.push followed by ns.pop. -func (ns *objectNameStack) clearLast() { - ns.offsets[len(ns.offsets)-1] = invalidOffset -} - -// pop ascends out of a nested JSON object. -func (ns *objectNameStack) pop() { - ns.offsets = ns.offsets[:len(ns.offsets)-1] -} - -// copyQuotedBuffer copies names from the remote buffer into the local names -// buffer so that there are no more offset references into the remote buffer. -// This allows the remote buffer to change contents without affecting -// the names that this data structure is trying to remember. -func (ns *objectNameStack) copyQuotedBuffer(b []byte) { - // Find the first negative offset. - var i int - for i = len(ns.offsets) - 1; i >= 0 && ns.offsets[i] < 0; i-- { - continue - } - - // Copy each name from the remote buffer into the local buffer. - for i = i + 1; i < len(ns.offsets); i++ { - if i == len(ns.offsets)-1 && ns.offsets[i] == invalidOffset { - if i == 0 { - ns.offsets[i] = 0 - } else { - ns.offsets[i] = ns.offsets[i-1] - } - break // last JSON object had a push without any names - } - - // As a form of Hyrum proofing, we write an invalid character into the - // buffer to make misuse of Decoder.ReadToken more obvious. - // We need to undo that mutation here. - quotedName := b[^ns.offsets[i]:] - if quotedName[0] == invalidateBufferByte { - quotedName[0] = '"' - } - - // Append the unquoted name to the local buffer. - var startOffset int - if i > 0 { - startOffset = ns.offsets[i-1] - } - if n := jsonwire.ConsumeSimpleString(quotedName); n > 0 { - ns.unquotedNames = append(ns.unquotedNames[:startOffset], quotedName[len(`"`):n-len(`"`)]...) - } else { - ns.unquotedNames, _ = jsonwire.AppendUnquote(ns.unquotedNames[:startOffset], quotedName) - } - ns.offsets[i] = len(ns.unquotedNames) - } -} - -func (ns *objectNameStack) ensureCopiedBuffer() { - if len(ns.offsets) > 0 && ns.offsets[len(ns.offsets)-1] < 0 { - panic("BUG: copyQuotedBuffer not called beforehand") - } -} - -// objectNamespaceStack is a stack of object namespaces. -// This data structure assists in detecting duplicate names. -type objectNamespaceStack []objectNamespace - -// reset resets the object namespace stack. -func (nss *objectNamespaceStack) reset() { - if cap(*nss) > 1<<10 { - *nss = nil - } - *nss = (*nss)[:0] -} - -// push starts a new namespace for a nested JSON object. -func (nss *objectNamespaceStack) push() { - if cap(*nss) > len(*nss) { - *nss = (*nss)[:len(*nss)+1] - nss.Last().reset() - } else { - *nss = append(*nss, objectNamespace{}) - } -} - -// Last returns a pointer to the last JSON object namespace. -func (nss objectNamespaceStack) Last() *objectNamespace { - return &nss[len(nss)-1] -} - -// pop terminates the namespace for a nested JSON object. -func (nss *objectNamespaceStack) pop() { - *nss = (*nss)[:len(*nss)-1] -} - -// objectNamespace is the namespace for a JSON object. -// In contrast to objectNameStack, this needs to remember a all names -// per JSON object. -// -// The zero value is an empty namespace ready for use. -type objectNamespace struct { - // It relies on a linear search over all the names before switching - // to use a Go map for direct lookup. - - // endOffsets is a list of offsets to the end of each name in buffers. - // The length of offsets is the number of names in the namespace. - endOffsets []uint - // allUnquotedNames is a back-to-back concatenation of every name in the namespace. - allUnquotedNames []byte - // mapNames is a Go map containing every name in the namespace. - // Only valid if non-nil. - mapNames map[string]struct{} -} - -// reset resets the namespace to be empty. -func (ns *objectNamespace) reset() { - ns.endOffsets = ns.endOffsets[:0] - ns.allUnquotedNames = ns.allUnquotedNames[:0] - ns.mapNames = nil - if cap(ns.endOffsets) > 1<<6 { - ns.endOffsets = nil // avoid pinning arbitrarily large amounts of memory - } - if cap(ns.allUnquotedNames) > 1<<10 { - ns.allUnquotedNames = nil // avoid pinning arbitrarily large amounts of memory - } -} - -// length reports the number of names in the namespace. -func (ns *objectNamespace) length() int { - return len(ns.endOffsets) -} - -// getUnquoted retrieves the ith unquoted name in the namespace. -func (ns *objectNamespace) getUnquoted(i int) []byte { - if i == 0 { - return ns.allUnquotedNames[:ns.endOffsets[0]] - } else { - return ns.allUnquotedNames[ns.endOffsets[i-1]:ns.endOffsets[i-0]] - } -} - -// lastUnquoted retrieves the last name in the namespace. -func (ns *objectNamespace) lastUnquoted() []byte { - return ns.getUnquoted(ns.length() - 1) -} - -// insertQuoted inserts a name and reports whether it was inserted, -// which only occurs if name is not already in the namespace. -// The provided name must be a valid JSON string. -func (ns *objectNamespace) insertQuoted(name []byte, isVerbatim bool) bool { - if isVerbatim { - name = name[len(`"`) : len(name)-len(`"`)] - } - return ns.insert(name, !isVerbatim) -} -func (ns *objectNamespace) InsertUnquoted(name []byte) bool { - return ns.insert(name, false) -} -func (ns *objectNamespace) insert(name []byte, quoted bool) bool { - var allNames []byte - if quoted { - allNames, _ = jsonwire.AppendUnquote(ns.allUnquotedNames, name) - } else { - allNames = append(ns.allUnquotedNames, name...) - } - name = allNames[len(ns.allUnquotedNames):] - - // Switch to a map if the buffer is too large for linear search. - // This does not add the current name to the map. - if ns.mapNames == nil && (ns.length() > 64 || len(ns.allUnquotedNames) > 1024) { - ns.mapNames = make(map[string]struct{}) - var startOffset uint - for _, endOffset := range ns.endOffsets { - name := ns.allUnquotedNames[startOffset:endOffset] - ns.mapNames[string(name)] = struct{}{} // allocates a new string - startOffset = endOffset - } - } - - if ns.mapNames == nil { - // Perform linear search over the buffer to find matching names. - // It provides O(n) lookup, but does not require any allocations. - var startOffset uint - for _, endOffset := range ns.endOffsets { - if string(ns.allUnquotedNames[startOffset:endOffset]) == string(name) { - return false - } - startOffset = endOffset - } - } else { - // Use the map if it is populated. - // It provides O(1) lookup, but requires a string allocation per name. - if _, ok := ns.mapNames[string(name)]; ok { - return false - } - ns.mapNames[string(name)] = struct{}{} // allocates a new string - } - - ns.allUnquotedNames = allNames - ns.endOffsets = append(ns.endOffsets, uint(len(ns.allUnquotedNames))) - return true -} - -// removeLast removes the last name in the namespace. -func (ns *objectNamespace) removeLast() { - if ns.mapNames != nil { - delete(ns.mapNames, string(ns.lastUnquoted())) - } - if ns.length()-1 == 0 { - ns.endOffsets = ns.endOffsets[:0] - ns.allUnquotedNames = ns.allUnquotedNames[:0] - } else { - ns.endOffsets = ns.endOffsets[:ns.length()-1] - ns.allUnquotedNames = ns.allUnquotedNames[:ns.endOffsets[ns.length()-1]] - } -} diff --git a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext/token.go b/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext/token.go deleted file mode 100644 index ea8c30eb5..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext/token.go +++ /dev/null @@ -1,525 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package jsontext - -import ( - "bytes" - "errors" - "math" - "strconv" - - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonflags" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonwire" -) - -// NOTE: Token is analogous to v1 json.Token. - -const ( - maxInt64 = math.MaxInt64 - minInt64 = math.MinInt64 - maxUint64 = math.MaxUint64 - minUint64 = 0 // for consistency and readability purposes - - invalidTokenPanic = "invalid jsontext.Token; it has been voided by a subsequent json.Decoder call" -) - -var errInvalidToken = errors.New("invalid jsontext.Token") - -// Token represents a lexical JSON token, which may be one of the following: -// - a JSON literal (i.e., null, true, or false) -// - a JSON string (e.g., "hello, world!") -// - a JSON number (e.g., 123.456) -// - a begin or end delimiter for a JSON object (i.e., { or } ) -// - a begin or end delimiter for a JSON array (i.e., [ or ] ) -// -// A Token cannot represent entire array or object values, while a [Value] can. -// There is no Token to represent commas and colons since -// these structural tokens can be inferred from the surrounding context. -type Token struct { - nonComparable - - // Tokens can exist in either a "raw" or an "exact" form. - // Tokens produced by the Decoder are in the "raw" form. - // Tokens returned by constructors are usually in the "exact" form. - // The Encoder accepts Tokens in either the "raw" or "exact" form. - // - // The following chart shows the possible values for each Token type: - // ╔═════════════════╦════════════╤════════════╤════════════╗ - // ║ Token type ║ raw field │ str field │ num field ║ - // ╠═════════════════╬════════════╪════════════╪════════════╣ - // ║ null (raw) ║ "null" │ "" │ 0 ║ - // ║ false (raw) ║ "false" │ "" │ 0 ║ - // ║ true (raw) ║ "true" │ "" │ 0 ║ - // ║ string (raw) ║ non-empty │ "" │ offset ║ - // ║ string (string) ║ nil │ non-empty │ 0 ║ - // ║ number (raw) ║ non-empty │ "" │ offset ║ - // ║ number (float) ║ nil │ "f" │ non-zero ║ - // ║ number (int64) ║ nil │ "i" │ non-zero ║ - // ║ number (uint64) ║ nil │ "u" │ non-zero ║ - // ║ object (delim) ║ "{" or "}" │ "" │ 0 ║ - // ║ array (delim) ║ "[" or "]" │ "" │ 0 ║ - // ╚═════════════════╩════════════╧════════════╧════════════╝ - // - // Notes: - // - For tokens stored in "raw" form, the num field contains the - // absolute offset determined by raw.previousOffsetStart(). - // The buffer itself is stored in raw.previousBuffer(). - // - JSON literals and structural characters are always in the "raw" form. - // - JSON strings and numbers can be in either "raw" or "exact" forms. - // - The exact zero value of JSON strings and numbers in the "exact" forms - // have ambiguous representation. Thus, they are always represented - // in the "raw" form. - - // raw contains a reference to the raw decode buffer. - // If non-nil, then its value takes precedence over str and num. - // It is only valid if num == raw.previousOffsetStart(). - raw *decodeBuffer - - // str is the unescaped JSON string if num is zero. - // Otherwise, it is "f", "i", or "u" if num should be interpreted - // as a float64, int64, or uint64, respectively. - str string - - // num is a float64, int64, or uint64 stored as a uint64 value. - // It is non-zero for any JSON number in the "exact" form. - num uint64 -} - -// TODO: Does representing 1-byte delimiters as *decodeBuffer cause performance issues? - -var ( - Null Token = rawToken("null") - False Token = rawToken("false") - True Token = rawToken("true") - - BeginObject Token = rawToken("{") - EndObject Token = rawToken("}") - BeginArray Token = rawToken("[") - EndArray Token = rawToken("]") - - zeroString Token = rawToken(`""`) - zeroNumber Token = rawToken(`0`) - - nanString Token = String("NaN") - pinfString Token = String("Infinity") - ninfString Token = String("-Infinity") -) - -func rawToken(s string) Token { - return Token{raw: &decodeBuffer{buf: []byte(s), prevStart: 0, prevEnd: len(s)}} -} - -// Bool constructs a Token representing a JSON boolean. -func Bool(b bool) Token { - if b { - return True - } - return False -} - -// String constructs a Token representing a JSON string. -// The provided string should contain valid UTF-8, otherwise invalid characters -// may be mangled as the Unicode replacement character. -func String(s string) Token { - if len(s) == 0 { - return zeroString - } - return Token{str: s} -} - -// Float constructs a Token representing a JSON number. -// The values NaN, +Inf, and -Inf will be represented -// as a JSON string with the values "NaN", "Infinity", and "-Infinity". -func Float(n float64) Token { - switch { - case math.Float64bits(n) == 0: - return zeroNumber - case math.IsNaN(n): - return nanString - case math.IsInf(n, +1): - return pinfString - case math.IsInf(n, -1): - return ninfString - } - return Token{str: "f", num: math.Float64bits(n)} -} - -// Int constructs a Token representing a JSON number from an int64. -func Int(n int64) Token { - if n == 0 { - return zeroNumber - } - return Token{str: "i", num: uint64(n)} -} - -// Uint constructs a Token representing a JSON number from a uint64. -func Uint(n uint64) Token { - if n == 0 { - return zeroNumber - } - return Token{str: "u", num: uint64(n)} -} - -// Clone makes a copy of the Token such that its value remains valid -// even after a subsequent [Decoder.Read] call. -func (t Token) Clone() Token { - // TODO: Allow caller to avoid any allocations? - if raw := t.raw; raw != nil { - // Avoid copying globals. - if t.raw.prevStart == 0 { - switch t.raw { - case Null.raw: - return Null - case False.raw: - return False - case True.raw: - return True - case BeginObject.raw: - return BeginObject - case EndObject.raw: - return EndObject - case BeginArray.raw: - return BeginArray - case EndArray.raw: - return EndArray - } - } - - if uint64(raw.previousOffsetStart()) != t.num { - panic(invalidTokenPanic) - } - buf := bytes.Clone(raw.previousBuffer()) - return Token{raw: &decodeBuffer{buf: buf, prevStart: 0, prevEnd: len(buf)}} - } - return t -} - -// Bool returns the value for a JSON boolean. -// It panics if the token kind is not a JSON boolean. -func (t Token) Bool() bool { - switch t.raw { - case True.raw: - return true - case False.raw: - return false - default: - panic("invalid JSON token kind: " + t.Kind().String()) - } -} - -// appendString appends a JSON string to dst and returns it. -// It panics if t is not a JSON string. -func (t Token) appendString(dst []byte, flags *jsonflags.Flags) ([]byte, error) { - if raw := t.raw; raw != nil { - // Handle raw string value. - buf := raw.previousBuffer() - if Kind(buf[0]) == '"' { - if jsonwire.ConsumeSimpleString(buf) == len(buf) { - return append(dst, buf...), nil - } - dst, _, err := jsonwire.ReformatString(dst, buf, flags) - return dst, err - } - } else if len(t.str) != 0 && t.num == 0 { - // Handle exact string value. - return jsonwire.AppendQuote(dst, t.str, flags) - } - - panic("invalid JSON token kind: " + t.Kind().String()) -} - -// String returns the unescaped string value for a JSON string. -// For other JSON kinds, this returns the raw JSON representation. -func (t Token) String() string { - // This is inlinable to take advantage of "function outlining". - // This avoids an allocation for the string(b) conversion - // if the caller does not use the string in an escaping manner. - // See https://blog.filippo.io/efficient-go-apis-with-the-inliner/ - s, b := t.string() - if len(b) > 0 { - return string(b) - } - return s -} -func (t Token) string() (string, []byte) { - if raw := t.raw; raw != nil { - if uint64(raw.previousOffsetStart()) != t.num { - panic(invalidTokenPanic) - } - buf := raw.previousBuffer() - if buf[0] == '"' { - // TODO: Preserve ValueFlags in Token? - isVerbatim := jsonwire.ConsumeSimpleString(buf) == len(buf) - return "", jsonwire.UnquoteMayCopy(buf, isVerbatim) - } - // Handle tokens that are not JSON strings for fmt.Stringer. - return "", buf - } - if len(t.str) != 0 && t.num == 0 { - return t.str, nil - } - // Handle tokens that are not JSON strings for fmt.Stringer. - if t.num > 0 { - switch t.str[0] { - case 'f': - return string(jsonwire.AppendFloat(nil, math.Float64frombits(t.num), 64)), nil - case 'i': - return strconv.FormatInt(int64(t.num), 10), nil - case 'u': - return strconv.FormatUint(uint64(t.num), 10), nil - } - } - return "", nil -} - -// appendNumber appends a JSON number to dst and returns it. -// It panics if t is not a JSON number. -func (t Token) appendNumber(dst []byte, flags *jsonflags.Flags) ([]byte, error) { - if raw := t.raw; raw != nil { - // Handle raw number value. - buf := raw.previousBuffer() - if Kind(buf[0]).normalize() == '0' { - dst, _, err := jsonwire.ReformatNumber(dst, buf, flags) - return dst, err - } - } else if t.num != 0 { - // Handle exact number value. - switch t.str[0] { - case 'f': - return jsonwire.AppendFloat(dst, math.Float64frombits(t.num), 64), nil - case 'i': - return strconv.AppendInt(dst, int64(t.num), 10), nil - case 'u': - return strconv.AppendUint(dst, uint64(t.num), 10), nil - } - } - - panic("invalid JSON token kind: " + t.Kind().String()) -} - -// Float returns the floating-point value for a JSON number. -// It returns a NaN, +Inf, or -Inf value for any JSON string -// with the values "NaN", "Infinity", or "-Infinity". -// It panics for all other cases. -func (t Token) Float() float64 { - if raw := t.raw; raw != nil { - // Handle raw number value. - if uint64(raw.previousOffsetStart()) != t.num { - panic(invalidTokenPanic) - } - buf := raw.previousBuffer() - if Kind(buf[0]).normalize() == '0' { - fv, _ := jsonwire.ParseFloat(buf, 64) - return fv - } - } else if t.num != 0 { - // Handle exact number value. - switch t.str[0] { - case 'f': - return math.Float64frombits(t.num) - case 'i': - return float64(int64(t.num)) - case 'u': - return float64(uint64(t.num)) - } - } - - // Handle string values with "NaN", "Infinity", or "-Infinity". - if t.Kind() == '"' { - switch t.String() { - case "NaN": - return math.NaN() - case "Infinity": - return math.Inf(+1) - case "-Infinity": - return math.Inf(-1) - } - } - - panic("invalid JSON token kind: " + t.Kind().String()) -} - -// Int returns the signed integer value for a JSON number. -// The fractional component of any number is ignored (truncation toward zero). -// Any number beyond the representation of an int64 will be saturated -// to the closest representable value. -// It panics if the token kind is not a JSON number. -func (t Token) Int() int64 { - if raw := t.raw; raw != nil { - // Handle raw integer value. - if uint64(raw.previousOffsetStart()) != t.num { - panic(invalidTokenPanic) - } - neg := false - buf := raw.previousBuffer() - if len(buf) > 0 && buf[0] == '-' { - neg, buf = true, buf[1:] - } - if numAbs, ok := jsonwire.ParseUint(buf); ok { - if neg { - if numAbs > -minInt64 { - return minInt64 - } - return -1 * int64(numAbs) - } else { - if numAbs > +maxInt64 { - return maxInt64 - } - return +1 * int64(numAbs) - } - } - } else if t.num != 0 { - // Handle exact integer value. - switch t.str[0] { - case 'i': - return int64(t.num) - case 'u': - if t.num > maxInt64 { - return maxInt64 - } - return int64(t.num) - } - } - - // Handle JSON number that is a floating-point value. - if t.Kind() == '0' { - switch fv := t.Float(); { - case fv >= maxInt64: - return maxInt64 - case fv <= minInt64: - return minInt64 - default: - return int64(fv) // truncation toward zero - } - } - - panic("invalid JSON token kind: " + t.Kind().String()) -} - -// Uint returns the unsigned integer value for a JSON number. -// The fractional component of any number is ignored (truncation toward zero). -// Any number beyond the representation of an uint64 will be saturated -// to the closest representable value. -// It panics if the token kind is not a JSON number. -func (t Token) Uint() uint64 { - // NOTE: This accessor returns 0 for any negative JSON number, - // which might be surprising, but is at least consistent with the behavior - // of saturating out-of-bounds numbers to the closest representable number. - - if raw := t.raw; raw != nil { - // Handle raw integer value. - if uint64(raw.previousOffsetStart()) != t.num { - panic(invalidTokenPanic) - } - neg := false - buf := raw.previousBuffer() - if len(buf) > 0 && buf[0] == '-' { - neg, buf = true, buf[1:] - } - if num, ok := jsonwire.ParseUint(buf); ok { - if neg { - return minUint64 - } - return num - } - } else if t.num != 0 { - // Handle exact integer value. - switch t.str[0] { - case 'u': - return t.num - case 'i': - if int64(t.num) < minUint64 { - return minUint64 - } - return uint64(int64(t.num)) - } - } - - // Handle JSON number that is a floating-point value. - if t.Kind() == '0' { - switch fv := t.Float(); { - case fv >= maxUint64: - return maxUint64 - case fv <= minUint64: - return minUint64 - default: - return uint64(fv) // truncation toward zero - } - } - - panic("invalid JSON token kind: " + t.Kind().String()) -} - -// Kind returns the token kind. -func (t Token) Kind() Kind { - switch { - case t.raw != nil: - raw := t.raw - if uint64(raw.previousOffsetStart()) != t.num { - panic(invalidTokenPanic) - } - return Kind(t.raw.buf[raw.prevStart]).normalize() - case t.num != 0: - return '0' - case len(t.str) != 0: - return '"' - default: - return invalidKind - } -} - -// Kind represents each possible JSON token kind with a single byte, -// which is conveniently the first byte of that kind's grammar -// with the restriction that numbers always be represented with '0': -// -// - 'n': null -// - 'f': false -// - 't': true -// - '"': string -// - '0': number -// - '{': object begin -// - '}': object end -// - '[': array begin -// - ']': array end -// -// An invalid kind is usually represented using 0, -// but may be non-zero due to invalid JSON data. -type Kind byte - -const invalidKind Kind = 0 - -// String prints the kind in a humanly readable fashion. -func (k Kind) String() string { - switch k { - case 'n': - return "null" - case 'f': - return "false" - case 't': - return "true" - case '"': - return "string" - case '0': - return "number" - case '{': - return "{" - case '}': - return "}" - case '[': - return "[" - case ']': - return "]" - default: - return "" - } -} - -// normalize coalesces all possible starting characters of a number as just '0'. -func (k Kind) normalize() Kind { - if k == '-' || ('0' <= k && k <= '9') { - return '0' - } - return k -} diff --git a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext/value.go b/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext/value.go deleted file mode 100644 index 3ea05d3a0..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext/value.go +++ /dev/null @@ -1,393 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package jsontext - -import ( - "bytes" - "errors" - "io" - "slices" - "sync" - - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonflags" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonwire" -) - -// NOTE: Value is analogous to v1 json.RawMessage. - -// AppendFormat formats the JSON value in src and appends it to dst -// according to the specified options. -// See [Value.Format] for more details about the formatting behavior. -// -// The dst and src may overlap. -// If an error is reported, then the entirety of src is appended to dst. -func AppendFormat(dst, src []byte, opts ...Options) ([]byte, error) { - e := getBufferedEncoder(opts...) - defer putBufferedEncoder(e) - e.s.Flags.Set(jsonflags.OmitTopLevelNewline | 1) - if err := e.s.WriteValue(src); err != nil { - return append(dst, src...), err - } - return append(dst, e.s.Buf...), nil -} - -// Value represents a single raw JSON value, which may be one of the following: -// - a JSON literal (i.e., null, true, or false) -// - a JSON string (e.g., "hello, world!") -// - a JSON number (e.g., 123.456) -// - an entire JSON object (e.g., {"fizz":"buzz"} ) -// - an entire JSON array (e.g., [1,2,3] ) -// -// Value can represent entire array or object values, while [Token] cannot. -// Value may contain leading and/or trailing whitespace. -type Value []byte - -// Clone returns a copy of v. -func (v Value) Clone() Value { - return bytes.Clone(v) -} - -// String returns the string formatting of v. -func (v Value) String() string { - if v == nil { - return "null" - } - return string(v) -} - -// IsValid reports whether the raw JSON value is syntactically valid -// according to the specified options. -// -// By default (if no options are specified), it validates according to RFC 7493. -// It verifies whether the input is properly encoded as UTF-8, -// that escape sequences within strings decode to valid Unicode codepoints, and -// that all names in each object are unique. -// It does not verify whether numbers are representable within the limits -// of any common numeric type (e.g., float64, int64, or uint64). -// -// Relevant options include: -// - [AllowDuplicateNames] -// - [AllowInvalidUTF8] -// -// All other options are ignored. -func (v Value) IsValid(opts ...Options) bool { - // TODO: Document support for [WithByteLimit] and [WithDepthLimit]. - d := getBufferedDecoder(v, opts...) - defer putBufferedDecoder(d) - _, errVal := d.ReadValue() - _, errEOF := d.ReadToken() - return errVal == nil && errEOF == io.EOF -} - -// Format formats the raw JSON value in place. -// -// By default (if no options are specified), it validates according to RFC 7493 -// and produces the minimal JSON representation, where -// all whitespace is elided and JSON strings use the shortest encoding. -// -// Relevant options include: -// - [AllowDuplicateNames] -// - [AllowInvalidUTF8] -// - [EscapeForHTML] -// - [EscapeForJS] -// - [PreserveRawStrings] -// - [CanonicalizeRawInts] -// - [CanonicalizeRawFloats] -// - [ReorderRawObjects] -// - [SpaceAfterColon] -// - [SpaceAfterComma] -// - [Multiline] -// - [WithIndent] -// - [WithIndentPrefix] -// -// All other options are ignored. -// -// It is guaranteed to succeed if the value is valid according to the same options. -// If the value is already formatted, then the buffer is not mutated. -func (v *Value) Format(opts ...Options) error { - // TODO: Document support for [WithByteLimit] and [WithDepthLimit]. - return v.format(opts, nil) -} - -// format accepts two []Options to avoid the allocation appending them together. -// It is equivalent to v.Format(append(opts1, opts2...)...). -func (v *Value) format(opts1, opts2 []Options) error { - e := getBufferedEncoder(opts1...) - defer putBufferedEncoder(e) - e.s.Join(opts2...) - e.s.Flags.Set(jsonflags.OmitTopLevelNewline | 1) - if err := e.s.WriteValue(*v); err != nil { - return err - } - if !bytes.Equal(*v, e.s.Buf) { - *v = append((*v)[:0], e.s.Buf...) - } - return nil -} - -// Compact removes all whitespace from the raw JSON value. -// -// It does not reformat JSON strings or numbers to use any other representation. -// To maximize the set of JSON values that can be formatted, -// this permits values with duplicate names and invalid UTF-8. -// -// Compact is equivalent to calling [Value.Format] with the following options: -// - [AllowDuplicateNames](true) -// - [AllowInvalidUTF8](true) -// - [PreserveRawStrings](true) -// -// Any options specified by the caller are applied after the initial set -// and may deliberately override prior options. -func (v *Value) Compact(opts ...Options) error { - return v.format([]Options{ - AllowDuplicateNames(true), - AllowInvalidUTF8(true), - PreserveRawStrings(true), - }, opts) -} - -// Indent reformats the whitespace in the raw JSON value so that each element -// in a JSON object or array begins on a indented line according to the nesting. -// -// It does not reformat JSON strings or numbers to use any other representation. -// To maximize the set of JSON values that can be formatted, -// this permits values with duplicate names and invalid UTF-8. -// -// Indent is equivalent to calling [Value.Format] with the following options: -// - [AllowDuplicateNames](true) -// - [AllowInvalidUTF8](true) -// - [PreserveRawStrings](true) -// - [Multiline](true) -// -// Any options specified by the caller are applied after the initial set -// and may deliberately override prior options. -func (v *Value) Indent(opts ...Options) error { - return v.format([]Options{ - AllowDuplicateNames(true), - AllowInvalidUTF8(true), - PreserveRawStrings(true), - Multiline(true), - }, opts) -} - -// Canonicalize canonicalizes the raw JSON value according to the -// JSON Canonicalization Scheme (JCS) as defined by RFC 8785 -// where it produces a stable representation of a JSON value. -// -// JSON strings are formatted to use their minimal representation, -// JSON numbers are formatted as double precision numbers according -// to some stable serialization algorithm. -// JSON object members are sorted in ascending order by name. -// All whitespace is removed. -// -// The output stability is dependent on the stability of the application data -// (see RFC 8785, Appendix E). It cannot produce stable output from -// fundamentally unstable input. For example, if the JSON value -// contains ephemeral data (e.g., a frequently changing timestamp), -// then the value is still unstable regardless of whether this is called. -// -// Canonicalize is equivalent to calling [Value.Format] with the following options: -// - [CanonicalizeRawInts](true) -// - [CanonicalizeRawFloats](true) -// - [ReorderRawObjects](true) -// -// Any options specified by the caller are applied after the initial set -// and may deliberately override prior options. -// -// Note that JCS treats all JSON numbers as IEEE 754 double precision numbers. -// Any numbers with precision beyond what is representable by that form -// will lose their precision when canonicalized. For example, integer values -// beyond ±2⁵³ will lose their precision. To preserve the original representation -// of JSON integers, additionally set [CanonicalizeRawInts] to false: -// -// v.Canonicalize(jsontext.CanonicalizeRawInts(false)) -func (v *Value) Canonicalize(opts ...Options) error { - return v.format([]Options{ - CanonicalizeRawInts(true), - CanonicalizeRawFloats(true), - ReorderRawObjects(true), - }, opts) -} - -// MarshalJSON returns v as the JSON encoding of v. -// It returns the stored value as the raw JSON output without any validation. -// If v is nil, then this returns a JSON null. -func (v Value) MarshalJSON() ([]byte, error) { - // NOTE: This matches the behavior of v1 json.RawMessage.MarshalJSON. - if v == nil { - return []byte("null"), nil - } - return v, nil -} - -// UnmarshalJSON sets v as the JSON encoding of b. -// It stores a copy of the provided raw JSON input without any validation. -func (v *Value) UnmarshalJSON(b []byte) error { - // NOTE: This matches the behavior of v1 json.RawMessage.UnmarshalJSON. - if v == nil { - return errors.New("jsontext.Value: UnmarshalJSON on nil pointer") - } - *v = append((*v)[:0], b...) - return nil -} - -// Kind returns the starting token kind. -// For a valid value, this will never include '}' or ']'. -func (v Value) Kind() Kind { - if v := v[jsonwire.ConsumeWhitespace(v):]; len(v) > 0 { - return Kind(v[0]).normalize() - } - return invalidKind -} - -const commaAndWhitespace = ", \n\r\t" - -type objectMember struct { - // name is the unquoted name. - name []byte // e.g., "name" - // buffer is the entirety of the raw JSON object member - // starting from right after the previous member (or opening '{') - // until right after the member value. - buffer []byte // e.g., `, \n\r\t"name": "value"` -} - -func (x objectMember) Compare(y objectMember) int { - if c := jsonwire.CompareUTF16(x.name, y.name); c != 0 { - return c - } - // With [AllowDuplicateNames] or [AllowInvalidUTF8], - // names could be identical, so also sort using the member value. - return jsonwire.CompareUTF16( - bytes.TrimLeft(x.buffer, commaAndWhitespace), - bytes.TrimLeft(y.buffer, commaAndWhitespace)) -} - -var objectMemberPool = sync.Pool{New: func() any { return new([]objectMember) }} - -func getObjectMembers() *[]objectMember { - ns := objectMemberPool.Get().(*[]objectMember) - *ns = (*ns)[:0] - return ns -} -func putObjectMembers(ns *[]objectMember) { - if cap(*ns) < 1<<10 { - clear(*ns) // avoid pinning name and buffer - objectMemberPool.Put(ns) - } -} - -// mustReorderObjects reorders in-place all object members in a JSON value, -// which must be valid otherwise it panics. -func mustReorderObjects(b []byte) { - // Obtain a buffered encoder just to use its internal buffer as - // a scratch buffer for reordering object members. - e2 := getBufferedEncoder() - defer putBufferedEncoder(e2) - - // Disable unnecessary checks to syntactically parse the JSON value. - d := getBufferedDecoder(b) - defer putBufferedDecoder(d) - d.s.Flags.Set(jsonflags.AllowDuplicateNames | jsonflags.AllowInvalidUTF8 | 1) - mustReorderObjectsFromDecoder(d, &e2.s.Buf) // per RFC 8785, section 3.2.3 -} - -// mustReorderObjectsFromDecoder recursively reorders all object members in place -// according to the ordering specified in RFC 8785, section 3.2.3. -// -// Pre-conditions: -// - The value is valid (i.e., no decoder errors should ever occur). -// - Initial call is provided a Decoder reading from the start of v. -// -// Post-conditions: -// - Exactly one JSON value is read from the Decoder. -// - All fully-parsed JSON objects are reordered by directly moving -// the members in the value buffer. -// -// The runtime is approximately O(n·log(n)) + O(m·log(m)), -// where n is len(v) and m is the total number of object members. -func mustReorderObjectsFromDecoder(d *Decoder, scratch *[]byte) { - switch tok, err := d.ReadToken(); tok.Kind() { - case '{': - // Iterate and collect the name and offsets for every object member. - members := getObjectMembers() - defer putObjectMembers(members) - var prevMember objectMember - isSorted := true - - beforeBody := d.InputOffset() // offset after '{' - for d.PeekKind() != '}' { - beforeName := d.InputOffset() - var flags jsonwire.ValueFlags - name, _ := d.s.ReadValue(&flags) - name = jsonwire.UnquoteMayCopy(name, flags.IsVerbatim()) - mustReorderObjectsFromDecoder(d, scratch) - afterValue := d.InputOffset() - - currMember := objectMember{name, d.s.buf[beforeName:afterValue]} - if isSorted && len(*members) > 0 { - isSorted = objectMember.Compare(prevMember, currMember) < 0 - } - *members = append(*members, currMember) - prevMember = currMember - } - afterBody := d.InputOffset() // offset before '}' - d.ReadToken() - - // Sort the members; return early if it's already sorted. - if isSorted { - return - } - firstBufferBeforeSorting := (*members)[0].buffer - slices.SortFunc(*members, objectMember.Compare) - firstBufferAfterSorting := (*members)[0].buffer - - // Append the reordered members to a new buffer, - // then copy the reordered members back over the original members. - // Avoid swapping in place since each member may be a different size - // where moving a member over a smaller member may corrupt the data - // for subsequent members before they have been moved. - // - // The following invariant must hold: - // sum([m.after-m.before for m in members]) == afterBody-beforeBody - commaAndWhitespacePrefix := func(b []byte) []byte { - return b[:len(b)-len(bytes.TrimLeft(b, commaAndWhitespace))] - } - sorted := (*scratch)[:0] - for i, member := range *members { - switch { - case i == 0 && &member.buffer[0] != &firstBufferBeforeSorting[0]: - // First member after sorting is not the first member before sorting, - // so use the prefix of the first member before sorting. - sorted = append(sorted, commaAndWhitespacePrefix(firstBufferBeforeSorting)...) - sorted = append(sorted, bytes.TrimLeft(member.buffer, commaAndWhitespace)...) - case i != 0 && &member.buffer[0] == &firstBufferBeforeSorting[0]: - // Later member after sorting is the first member before sorting, - // so use the prefix of the first member after sorting. - sorted = append(sorted, commaAndWhitespacePrefix(firstBufferAfterSorting)...) - sorted = append(sorted, bytes.TrimLeft(member.buffer, commaAndWhitespace)...) - default: - sorted = append(sorted, member.buffer...) - } - } - if int(afterBody-beforeBody) != len(sorted) { - panic("BUG: length invariant violated") - } - copy(d.s.buf[beforeBody:afterBody], sorted) - - // Update scratch buffer to the largest amount ever used. - if len(sorted) > len(*scratch) { - *scratch = sorted - } - case '[': - for d.PeekKind() != ']' { - mustReorderObjectsFromDecoder(d, scratch) - } - d.ReadToken() - default: - if err != nil { - panic("BUG: " + err.Error()) - } - } -} diff --git a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/migrate.sh b/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/migrate.sh deleted file mode 100644 index 9c34f26eb..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/migrate.sh +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env bash - -GOROOT=${1:-../go} -JSONROOT="." - -cp $JSONROOT/alias_gen.go $JSONROOT/alias_gen.go.bak -rm -r $JSONROOT/*.go $JSONROOT/internal $JSONROOT/jsontext $JSONROOT/v1 -mv $JSONROOT/alias_gen.go.bak $JSONROOT/alias_gen.go -cp -r $GOROOT/src/encoding/json/v2/*.go $JSONROOT/ -cp -r $GOROOT/src/encoding/json/internal/ $JSONROOT/internal/ -cp -r $GOROOT/src/encoding/json/jsontext/ $JSONROOT/jsontext/ -mkdir $JSONROOT/v1 -for X in $GOROOT/src/encoding/json/v2_*.go; do - cp $X $JSONROOT/v1/$(basename $X | sed "s/v2_//") -done -cd $JSONROOT -for X in $(git ls-files --cached --others --exclude-standard | grep ".*[.]go$"); do - if [ ! -e "$X" ]; then - continue - fi - sed -i 's/go:build goexperiment.jsonv2$/go:build !goexperiment.jsonv2 || !go1.25/' $X - sed -i 's|"encoding/json/v2"|"github.com/go-json-experiment/json"|' $X - sed -i 's|"encoding/json/internal"|"github.com/go-json-experiment/json/internal"|' $X - sed -i 's|"encoding/json/internal/jsonflags"|"github.com/go-json-experiment/json/internal/jsonflags"|' $X - sed -i 's|"encoding/json/internal/jsonopts"|"github.com/go-json-experiment/json/internal/jsonopts"|' $X - sed -i 's|"encoding/json/internal/jsontest"|"github.com/go-json-experiment/json/internal/jsontest"|' $X - sed -i 's|"encoding/json/internal/jsonwire"|"github.com/go-json-experiment/json/internal/jsonwire"|' $X - sed -i 's|"encoding/json/jsontext"|"github.com/go-json-experiment/json/jsontext"|' $X - sed -i 's|"encoding/json"|"github.com/go-json-experiment/json/v1"|' $X - sed -i 's|"internal/zstd"|"github.com/go-json-experiment/json/internal/zstd"|' $X - goimports -w $X -done -sed -i 's/v2[.]struct/json.struct/' $JSONROOT/errors_test.go -sed -i 's|jsonv1 "github.com/go-json-experiment/json/v1"|jsonv1 "encoding/json"|' $JSONROOT/bench_test.go - -# TODO(go1.25): Remove test that relies on "synctest" that is not available yet. -sed -i '/Issue #73733/,+17d' $JSONROOT/v1/encode_test.go -goimports -w $JSONROOT/v1/encode_test.go - -# Remove documentation that only makes sense within the stdlib. -sed -i '/This package .* is experimental/,+4d' $JSONROOT/doc.go -sed -i '/This package .* is experimental/,+4d' $JSONROOT/jsontext/doc.go - -git checkout internal/zstd # we still need local copy of zstd for testing - -go run alias_gen.go "encoding/json" $JSONROOT/v1 -go run alias_gen.go "encoding/json/v2" $JSONROOT -go run alias_gen.go "encoding/json/jsontext" $JSONROOT/jsontext diff --git a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/options.go b/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/options.go deleted file mode 100644 index 2f4744980..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/options.go +++ /dev/null @@ -1,287 +0,0 @@ -// Copyright 2023 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package json - -import ( - "fmt" - - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonflags" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonopts" -) - -// Options configure [Marshal], [MarshalWrite], [MarshalEncode], -// [Unmarshal], [UnmarshalRead], and [UnmarshalDecode] with specific features. -// Each function takes in a variadic list of options, where properties -// set in later options override the value of previously set properties. -// -// The Options type is identical to [encoding/json.Options] and -// [encoding/json/jsontext.Options]. Options from the other packages can -// be used interchangeably with functionality in this package. -// -// Options represent either a singular option or a set of options. -// It can be functionally thought of as a Go map of option properties -// (even though the underlying implementation avoids Go maps for performance). -// -// The constructors (e.g., [Deterministic]) return a singular option value: -// -// opt := Deterministic(true) -// -// which is analogous to creating a single entry map: -// -// opt := Options{"Deterministic": true} -// -// [JoinOptions] composes multiple options values to together: -// -// out := JoinOptions(opts...) -// -// which is analogous to making a new map and copying the options over: -// -// out := make(Options) -// for _, m := range opts { -// for k, v := range m { -// out[k] = v -// } -// } -// -// [GetOption] looks up the value of options parameter: -// -// v, ok := GetOption(opts, Deterministic) -// -// which is analogous to a Go map lookup: -// -// v, ok := Options["Deterministic"] -// -// There is a single Options type, which is used with both marshal and unmarshal. -// Some options affect both operations, while others only affect one operation: -// -// - [StringifyNumbers] affects marshaling and unmarshaling -// - [Deterministic] affects marshaling only -// - [FormatNilSliceAsNull] affects marshaling only -// - [FormatNilMapAsNull] affects marshaling only -// - [OmitZeroStructFields] affects marshaling only -// - [MatchCaseInsensitiveNames] affects marshaling and unmarshaling -// - [DiscardUnknownMembers] affects marshaling only -// - [RejectUnknownMembers] affects unmarshaling only -// - [WithMarshalers] affects marshaling only -// - [WithUnmarshalers] affects unmarshaling only -// -// Options that do not affect a particular operation are ignored. -type Options = jsonopts.Options - -// JoinOptions coalesces the provided list of options into a single Options. -// Properties set in later options override the value of previously set properties. -func JoinOptions(srcs ...Options) Options { - var dst jsonopts.Struct - dst.Join(srcs...) - return &dst -} - -// GetOption returns the value stored in opts with the provided setter, -// reporting whether the value is present. -// -// Example usage: -// -// v, ok := json.GetOption(opts, json.Deterministic) -// -// Options are most commonly introspected to alter the JSON representation of -// [MarshalerTo.MarshalJSONTo] and [UnmarshalerFrom.UnmarshalJSONFrom] methods, and -// [MarshalToFunc] and [UnmarshalFromFunc] functions. -// In such cases, the presence bit should generally be ignored. -func GetOption[T any](opts Options, setter func(T) Options) (T, bool) { - return jsonopts.GetOption(opts, setter) -} - -// DefaultOptionsV2 is the full set of all options that define v2 semantics. -// It is equivalent to all options under [Options], [encoding/json.Options], -// and [encoding/json/jsontext.Options] being set to false or the zero value, -// except for the options related to whitespace formatting. -func DefaultOptionsV2() Options { - return &jsonopts.DefaultOptionsV2 -} - -// StringifyNumbers specifies that numeric Go types should be marshaled -// as a JSON string containing the equivalent JSON number value. -// When unmarshaling, numeric Go types are parsed from a JSON string -// containing the JSON number without any surrounding whitespace. -// -// According to RFC 8259, section 6, a JSON implementation may choose to -// limit the representation of a JSON number to an IEEE 754 binary64 value. -// This may cause decoders to lose precision for int64 and uint64 types. -// Quoting JSON numbers as a JSON string preserves the exact precision. -// -// This affects either marshaling or unmarshaling. -func StringifyNumbers(v bool) Options { - if v { - return jsonflags.StringifyNumbers | 1 - } else { - return jsonflags.StringifyNumbers | 0 - } -} - -// Deterministic specifies that the same input value will be serialized -// as the exact same output bytes. Different processes of -// the same program will serialize equal values to the same bytes, -// but different versions of the same program are not guaranteed -// to produce the exact same sequence of bytes. -// -// This only affects marshaling and is ignored when unmarshaling. -func Deterministic(v bool) Options { - if v { - return jsonflags.Deterministic | 1 - } else { - return jsonflags.Deterministic | 0 - } -} - -// FormatNilSliceAsNull specifies that a nil Go slice should marshal as a -// JSON null instead of the default representation as an empty JSON array -// (or an empty JSON string in the case of ~[]byte). -// Slice fields explicitly marked with `format:emitempty` still marshal -// as an empty JSON array. -// -// This only affects marshaling and is ignored when unmarshaling. -func FormatNilSliceAsNull(v bool) Options { - if v { - return jsonflags.FormatNilSliceAsNull | 1 - } else { - return jsonflags.FormatNilSliceAsNull | 0 - } -} - -// FormatNilMapAsNull specifies that a nil Go map should marshal as a -// JSON null instead of the default representation as an empty JSON object. -// Map fields explicitly marked with `format:emitempty` still marshal -// as an empty JSON object. -// -// This only affects marshaling and is ignored when unmarshaling. -func FormatNilMapAsNull(v bool) Options { - if v { - return jsonflags.FormatNilMapAsNull | 1 - } else { - return jsonflags.FormatNilMapAsNull | 0 - } -} - -// OmitZeroStructFields specifies that a Go struct should marshal in such a way -// that all struct fields that are zero are omitted from the marshaled output -// if the value is zero as determined by the "IsZero() bool" method if present, -// otherwise based on whether the field is the zero Go value. -// This is semantically equivalent to specifying the `omitzero` tag option -// on every field in a Go struct. -// -// This only affects marshaling and is ignored when unmarshaling. -func OmitZeroStructFields(v bool) Options { - if v { - return jsonflags.OmitZeroStructFields | 1 - } else { - return jsonflags.OmitZeroStructFields | 0 - } -} - -// MatchCaseInsensitiveNames specifies that JSON object members are matched -// against Go struct fields using a case-insensitive match of the name. -// Go struct fields explicitly marked with `case:strict` or `case:ignore` -// always use case-sensitive (or case-insensitive) name matching, -// regardless of the value of this option. -// -// This affects either marshaling or unmarshaling. -// For marshaling, this option may alter the detection of duplicate names -// (assuming [jsontext.AllowDuplicateNames] is false) from inlined fields -// if it matches one of the declared fields in the Go struct. -func MatchCaseInsensitiveNames(v bool) Options { - if v { - return jsonflags.MatchCaseInsensitiveNames | 1 - } else { - return jsonflags.MatchCaseInsensitiveNames | 0 - } -} - -// DiscardUnknownMembers specifies that marshaling should ignore any -// JSON object members stored in Go struct fields dedicated to storing -// unknown JSON object members. -// -// This only affects marshaling and is ignored when unmarshaling. -func DiscardUnknownMembers(v bool) Options { - if v { - return jsonflags.DiscardUnknownMembers | 1 - } else { - return jsonflags.DiscardUnknownMembers | 0 - } -} - -// RejectUnknownMembers specifies that unknown members should be rejected -// when unmarshaling a JSON object, regardless of whether there is a field -// to store unknown members. -// -// This only affects unmarshaling and is ignored when marshaling. -func RejectUnknownMembers(v bool) Options { - if v { - return jsonflags.RejectUnknownMembers | 1 - } else { - return jsonflags.RejectUnknownMembers | 0 - } -} - -// WithMarshalers specifies a list of type-specific marshalers to use, -// which can be used to override the default marshal behavior for values -// of particular types. -// -// This only affects marshaling and is ignored when unmarshaling. -func WithMarshalers(v *Marshalers) Options { - return (*marshalersOption)(v) -} - -// WithUnmarshalers specifies a list of type-specific unmarshalers to use, -// which can be used to override the default unmarshal behavior for values -// of particular types. -// -// This only affects unmarshaling and is ignored when marshaling. -func WithUnmarshalers(v *Unmarshalers) Options { - return (*unmarshalersOption)(v) -} - -// These option types are declared here instead of "jsonopts" -// to avoid a dependency on "reflect" from "jsonopts". -type ( - marshalersOption Marshalers - unmarshalersOption Unmarshalers -) - -func (*marshalersOption) JSONOptions(internal.NotForPublicUse) {} -func (*unmarshalersOption) JSONOptions(internal.NotForPublicUse) {} - -// Inject support into "jsonopts" to handle these types. -func init() { - jsonopts.GetUnknownOption = func(src jsonopts.Struct, zero jsonopts.Options) (any, bool) { - switch zero.(type) { - case *marshalersOption: - if !src.Flags.Has(jsonflags.Marshalers) { - return (*Marshalers)(nil), false - } - return src.Marshalers.(*Marshalers), true - case *unmarshalersOption: - if !src.Flags.Has(jsonflags.Unmarshalers) { - return (*Unmarshalers)(nil), false - } - return src.Unmarshalers.(*Unmarshalers), true - default: - panic(fmt.Sprintf("unknown option %T", zero)) - } - } - jsonopts.JoinUnknownOption = func(dst jsonopts.Struct, src jsonopts.Options) jsonopts.Struct { - switch src := src.(type) { - case *marshalersOption: - dst.Flags.Set(jsonflags.Marshalers | 1) - dst.Marshalers = (*Marshalers)(src) - case *unmarshalersOption: - dst.Flags.Set(jsonflags.Unmarshalers | 1) - dst.Unmarshalers = (*Unmarshalers)(src) - default: - panic(fmt.Sprintf("unknown option %T", src)) - } - return dst - } -} diff --git a/vendor/k8s.io/kube-openapi/pkg/schemaconv/openapi.go b/vendor/k8s.io/kube-openapi/pkg/schemaconv/openapi.go index 06bcf0c37..8f4e8f227 100644 --- a/vendor/k8s.io/kube-openapi/pkg/schemaconv/openapi.go +++ b/vendor/k8s.io/kube-openapi/pkg/schemaconv/openapi.go @@ -21,8 +21,9 @@ import ( "path" "strings" + "sigs.k8s.io/structured-merge-diff/v7/schema" + "k8s.io/kube-openapi/pkg/validation/spec" - "sigs.k8s.io/structured-merge-diff/v6/schema" ) // ToSchemaFromOpenAPI converts a directory of OpenAPI schemas to an smd Schema. diff --git a/vendor/k8s.io/kube-openapi/pkg/schemaconv/proto_models.go b/vendor/k8s.io/kube-openapi/pkg/schemaconv/proto_models.go index 6a8b9f44a..36695b32b 100644 --- a/vendor/k8s.io/kube-openapi/pkg/schemaconv/proto_models.go +++ b/vendor/k8s.io/kube-openapi/pkg/schemaconv/proto_models.go @@ -21,8 +21,9 @@ import ( "path" "strings" + "sigs.k8s.io/structured-merge-diff/v7/schema" + "k8s.io/kube-openapi/pkg/util/proto" - "sigs.k8s.io/structured-merge-diff/v6/schema" ) // ToSchema converts openapi definitions into a schema suitable for structured diff --git a/vendor/k8s.io/kube-openapi/pkg/schemaconv/smd.go b/vendor/k8s.io/kube-openapi/pkg/schemaconv/smd.go index c4a083cb4..c2fb1d524 100644 --- a/vendor/k8s.io/kube-openapi/pkg/schemaconv/smd.go +++ b/vendor/k8s.io/kube-openapi/pkg/schemaconv/smd.go @@ -20,7 +20,7 @@ import ( "fmt" "sort" - "sigs.k8s.io/structured-merge-diff/v6/schema" + "sigs.k8s.io/structured-merge-diff/v7/schema" ) const ( diff --git a/vendor/k8s.io/kube-openapi/pkg/spec3/encoding.go b/vendor/k8s.io/kube-openapi/pkg/spec3/encoding.go index 1b3dfff1d..62ae6d314 100644 --- a/vendor/k8s.io/kube-openapi/pkg/spec3/encoding.go +++ b/vendor/k8s.io/kube-openapi/pkg/spec3/encoding.go @@ -17,12 +17,10 @@ limitations under the License. package spec3 import ( - "encoding/json" + "encoding/json/jsontext" + jsonv2 "encoding/json/v2" - "github.com/go-openapi/swag" "k8s.io/kube-openapi/pkg/internal" - jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext" "k8s.io/kube-openapi/pkg/validation/spec" ) @@ -33,24 +31,13 @@ type Encoding struct { // MarshalJSON is a custom marshal function that knows how to encode Encoding as JSON func (e *Encoding) MarshalJSON() ([]byte, error) { - if internal.UseOptimizedJSONMarshalingV3 { - return internal.DeterministicMarshal(e) - } - b1, err := json.Marshal(e.EncodingProps) - if err != nil { - return nil, err - } - b2, err := json.Marshal(e.VendorExtensible) - if err != nil { - return nil, err - } - return swag.ConcatJSON(b1, b2), nil + return internal.DeterministicMarshal(e) } func (e *Encoding) MarshalJSONTo(enc *jsontext.Encoder) error { var x struct { - EncodingProps encodingPropsOmitZero `json:",inline"` - Extensions spec.Extensions `json:",inline"` + EncodingProps encodingPropsOmitZero `json:",embed"` + Extensions spec.Extensions `json:",embed"` } x.Extensions = internal.SanitizeExtensions(e.Extensions) x.EncodingProps = encodingPropsOmitZero(e.EncodingProps) @@ -58,21 +45,12 @@ func (e *Encoding) MarshalJSONTo(enc *jsontext.Encoder) error { } func (e *Encoding) UnmarshalJSON(data []byte) error { - if internal.UseOptimizedJSONUnmarshalingV3 { - return jsonv2.Unmarshal(data, e) - } - if err := json.Unmarshal(data, &e.EncodingProps); err != nil { - return err - } - if err := json.Unmarshal(data, &e.VendorExtensible); err != nil { - return err - } - return nil + return jsonv2.Unmarshal(data, e) } func (e *Encoding) UnmarshalJSONFrom(dec *jsontext.Decoder) error { var x struct { - Extensions spec.Extensions `json:",inline"` + Extensions spec.Extensions `json:",embed"` EncodingProps } if err := jsonv2.UnmarshalDecode(dec, &x); err != nil { diff --git a/vendor/k8s.io/kube-openapi/pkg/spec3/example.go b/vendor/k8s.io/kube-openapi/pkg/spec3/example.go index 3edb10492..a06b8399e 100644 --- a/vendor/k8s.io/kube-openapi/pkg/spec3/example.go +++ b/vendor/k8s.io/kube-openapi/pkg/spec3/example.go @@ -17,13 +17,10 @@ limitations under the License. package spec3 import ( - "encoding/json" + "encoding/json/jsontext" + jsonv2 "encoding/json/v2" - "github.com/go-openapi/swag" "k8s.io/kube-openapi/pkg/internal" - jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext" - "k8s.io/kube-openapi/pkg/validation/spec" ) @@ -37,28 +34,13 @@ type Example struct { // MarshalJSON is a custom marshal function that knows how to encode RequestBody as JSON func (e *Example) MarshalJSON() ([]byte, error) { - if internal.UseOptimizedJSONMarshalingV3 { - return internal.DeterministicMarshal(e) - } - b1, err := json.Marshal(e.Refable) - if err != nil { - return nil, err - } - b2, err := json.Marshal(e.ExampleProps) - if err != nil { - return nil, err - } - b3, err := json.Marshal(e.VendorExtensible) - if err != nil { - return nil, err - } - return swag.ConcatJSON(b1, b2, b3), nil + return internal.DeterministicMarshal(e) } func (e *Example) MarshalJSONTo(enc *jsontext.Encoder) error { var x struct { Ref string `json:"$ref,omitempty"` - ExampleProps `json:",inline"` - Extensions spec.Extensions `json:",inline"` + ExampleProps `json:",embed"` + Extensions spec.Extensions `json:",embed"` } x.Ref = e.Refable.Ref.String() x.Extensions = internal.SanitizeExtensions(e.Extensions) @@ -67,24 +49,12 @@ func (e *Example) MarshalJSONTo(enc *jsontext.Encoder) error { } func (e *Example) UnmarshalJSON(data []byte) error { - if internal.UseOptimizedJSONUnmarshalingV3 { - return jsonv2.Unmarshal(data, e) - } - if err := json.Unmarshal(data, &e.Refable); err != nil { - return err - } - if err := json.Unmarshal(data, &e.ExampleProps); err != nil { - return err - } - if err := json.Unmarshal(data, &e.VendorExtensible); err != nil { - return err - } - return nil + return jsonv2.Unmarshal(data, e) } func (e *Example) UnmarshalJSONFrom(dec *jsontext.Decoder) error { var x struct { - Extensions spec.Extensions `json:",inline"` + Extensions spec.Extensions `json:",embed"` ExampleProps } if err := jsonv2.UnmarshalDecode(dec, &x); err != nil { diff --git a/vendor/k8s.io/kube-openapi/pkg/spec3/external_documentation.go b/vendor/k8s.io/kube-openapi/pkg/spec3/external_documentation.go index 7a83c53c0..2c4b7e2dc 100644 --- a/vendor/k8s.io/kube-openapi/pkg/spec3/external_documentation.go +++ b/vendor/k8s.io/kube-openapi/pkg/spec3/external_documentation.go @@ -17,12 +17,10 @@ limitations under the License. package spec3 import ( - "encoding/json" + "encoding/json/jsontext" + jsonv2 "encoding/json/v2" - "github.com/go-openapi/swag" "k8s.io/kube-openapi/pkg/internal" - jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext" "k8s.io/kube-openapi/pkg/validation/spec" ) @@ -40,24 +38,13 @@ type ExternalDocumentationProps struct { // MarshalJSON is a custom marshal function that knows how to encode Responses as JSON func (e *ExternalDocumentation) MarshalJSON() ([]byte, error) { - if internal.UseOptimizedJSONMarshalingV3 { - return internal.DeterministicMarshal(e) - } - b1, err := json.Marshal(e.ExternalDocumentationProps) - if err != nil { - return nil, err - } - b2, err := json.Marshal(e.VendorExtensible) - if err != nil { - return nil, err - } - return swag.ConcatJSON(b1, b2), nil + return internal.DeterministicMarshal(e) } func (e *ExternalDocumentation) MarshalJSONTo(enc *jsontext.Encoder) error { var x struct { - ExternalDocumentationProps `json:",inline"` - Extensions spec.Extensions `json:",inline"` + ExternalDocumentationProps `json:",embed"` + Extensions spec.Extensions `json:",embed"` } x.Extensions = internal.SanitizeExtensions(e.Extensions) x.ExternalDocumentationProps = e.ExternalDocumentationProps @@ -65,21 +52,12 @@ func (e *ExternalDocumentation) MarshalJSONTo(enc *jsontext.Encoder) error { } func (e *ExternalDocumentation) UnmarshalJSON(data []byte) error { - if internal.UseOptimizedJSONUnmarshalingV3 { - return jsonv2.Unmarshal(data, e) - } - if err := json.Unmarshal(data, &e.ExternalDocumentationProps); err != nil { - return err - } - if err := json.Unmarshal(data, &e.VendorExtensible); err != nil { - return err - } - return nil + return jsonv2.Unmarshal(data, e) } func (e *ExternalDocumentation) UnmarshalJSONFrom(dec *jsontext.Decoder) error { var x struct { - Extensions spec.Extensions `json:",inline"` + Extensions spec.Extensions `json:",embed"` ExternalDocumentationProps } if err := jsonv2.UnmarshalDecode(dec, &x); err != nil { diff --git a/vendor/k8s.io/kube-openapi/pkg/spec3/header.go b/vendor/k8s.io/kube-openapi/pkg/spec3/header.go index 475817f66..0cf70aebd 100644 --- a/vendor/k8s.io/kube-openapi/pkg/spec3/header.go +++ b/vendor/k8s.io/kube-openapi/pkg/spec3/header.go @@ -17,12 +17,10 @@ limitations under the License. package spec3 import ( - "encoding/json" + "encoding/json/jsontext" + jsonv2 "encoding/json/v2" - "github.com/go-openapi/swag" "k8s.io/kube-openapi/pkg/internal" - jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext" "k8s.io/kube-openapi/pkg/validation/spec" ) @@ -37,29 +35,14 @@ type Header struct { // MarshalJSON is a custom marshal function that knows how to encode Header as JSON func (h *Header) MarshalJSON() ([]byte, error) { - if internal.UseOptimizedJSONMarshalingV3 { - return internal.DeterministicMarshal(h) - } - b1, err := json.Marshal(h.Refable) - if err != nil { - return nil, err - } - b2, err := json.Marshal(h.HeaderProps) - if err != nil { - return nil, err - } - b3, err := json.Marshal(h.VendorExtensible) - if err != nil { - return nil, err - } - return swag.ConcatJSON(b1, b2, b3), nil + return internal.DeterministicMarshal(h) } func (h *Header) MarshalJSONTo(enc *jsontext.Encoder) error { var x struct { Ref string `json:"$ref,omitempty"` - HeaderProps headerPropsOmitZero `json:",inline"` - Extensions spec.Extensions `json:",inline"` + HeaderProps headerPropsOmitZero `json:",embed"` + Extensions spec.Extensions `json:",embed"` } x.Ref = h.Refable.Ref.String() x.Extensions = internal.SanitizeExtensions(h.Extensions) @@ -68,25 +51,12 @@ func (h *Header) MarshalJSONTo(enc *jsontext.Encoder) error { } func (h *Header) UnmarshalJSON(data []byte) error { - if internal.UseOptimizedJSONUnmarshalingV3 { - return jsonv2.Unmarshal(data, h) - } - if err := json.Unmarshal(data, &h.Refable); err != nil { - return err - } - if err := json.Unmarshal(data, &h.HeaderProps); err != nil { - return err - } - if err := json.Unmarshal(data, &h.VendorExtensible); err != nil { - return err - } - - return nil + return jsonv2.Unmarshal(data, h) } func (h *Header) UnmarshalJSONFrom(dec *jsontext.Decoder) error { var x struct { - Extensions spec.Extensions `json:",inline"` + Extensions spec.Extensions `json:",embed"` HeaderProps } if err := jsonv2.UnmarshalDecode(dec, &x); err != nil { diff --git a/vendor/k8s.io/kube-openapi/pkg/spec3/media_type.go b/vendor/k8s.io/kube-openapi/pkg/spec3/media_type.go index c9062b238..9b6883b30 100644 --- a/vendor/k8s.io/kube-openapi/pkg/spec3/media_type.go +++ b/vendor/k8s.io/kube-openapi/pkg/spec3/media_type.go @@ -17,12 +17,10 @@ limitations under the License. package spec3 import ( - "encoding/json" + "encoding/json/jsontext" + jsonv2 "encoding/json/v2" - "github.com/go-openapi/swag" "k8s.io/kube-openapi/pkg/internal" - jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext" "k8s.io/kube-openapi/pkg/validation/spec" ) @@ -36,24 +34,13 @@ type MediaType struct { // MarshalJSON is a custom marshal function that knows how to encode MediaType as JSON func (m *MediaType) MarshalJSON() ([]byte, error) { - if internal.UseOptimizedJSONMarshalingV3 { - return internal.DeterministicMarshal(m) - } - b1, err := json.Marshal(m.MediaTypeProps) - if err != nil { - return nil, err - } - b2, err := json.Marshal(m.VendorExtensible) - if err != nil { - return nil, err - } - return swag.ConcatJSON(b1, b2), nil + return internal.DeterministicMarshal(m) } func (e *MediaType) MarshalJSONTo(enc *jsontext.Encoder) error { var x struct { - MediaTypeProps mediaTypePropsOmitZero `json:",inline"` - Extensions spec.Extensions `json:",inline"` + MediaTypeProps mediaTypePropsOmitZero `json:",embed"` + Extensions spec.Extensions `json:",embed"` } x.Extensions = internal.SanitizeExtensions(e.Extensions) x.MediaTypeProps = mediaTypePropsOmitZero(e.MediaTypeProps) @@ -61,21 +48,12 @@ func (e *MediaType) MarshalJSONTo(enc *jsontext.Encoder) error { } func (m *MediaType) UnmarshalJSON(data []byte) error { - if internal.UseOptimizedJSONUnmarshalingV3 { - return jsonv2.Unmarshal(data, m) - } - if err := json.Unmarshal(data, &m.MediaTypeProps); err != nil { - return err - } - if err := json.Unmarshal(data, &m.VendorExtensible); err != nil { - return err - } - return nil + return jsonv2.Unmarshal(data, m) } func (m *MediaType) UnmarshalJSONFrom(dec *jsontext.Decoder) error { var x struct { - Extensions spec.Extensions `json:",inline"` + Extensions spec.Extensions `json:",embed"` MediaTypeProps } if err := jsonv2.UnmarshalDecode(dec, &x); err != nil { diff --git a/vendor/k8s.io/kube-openapi/pkg/spec3/operation.go b/vendor/k8s.io/kube-openapi/pkg/spec3/operation.go index 8219b29d0..f84d8ad2d 100644 --- a/vendor/k8s.io/kube-openapi/pkg/spec3/operation.go +++ b/vendor/k8s.io/kube-openapi/pkg/spec3/operation.go @@ -17,12 +17,10 @@ limitations under the License. package spec3 import ( - "encoding/json" + "encoding/json/jsontext" + jsonv2 "encoding/json/v2" - "github.com/go-openapi/swag" "k8s.io/kube-openapi/pkg/internal" - jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext" "k8s.io/kube-openapi/pkg/validation/spec" ) @@ -36,24 +34,13 @@ type Operation struct { // MarshalJSON is a custom marshal function that knows how to encode Operation as JSON func (o *Operation) MarshalJSON() ([]byte, error) { - if internal.UseOptimizedJSONMarshalingV3 { - return internal.DeterministicMarshal(o) - } - b1, err := json.Marshal(o.OperationProps) - if err != nil { - return nil, err - } - b2, err := json.Marshal(o.VendorExtensible) - if err != nil { - return nil, err - } - return swag.ConcatJSON(b1, b2), nil + return internal.DeterministicMarshal(o) } func (o *Operation) MarshalJSONTo(enc *jsontext.Encoder) error { var x struct { - Extensions spec.Extensions `json:",inline"` - OperationProps operationPropsOmitZero `json:",inline"` + Extensions spec.Extensions `json:",embed"` + OperationProps operationPropsOmitZero `json:",embed"` } x.Extensions = internal.SanitizeExtensions(o.Extensions) x.OperationProps = operationPropsOmitZero(o.OperationProps) @@ -62,18 +49,12 @@ func (o *Operation) MarshalJSONTo(enc *jsontext.Encoder) error { // UnmarshalJSON hydrates this items instance with the data from JSON func (o *Operation) UnmarshalJSON(data []byte) error { - if internal.UseOptimizedJSONUnmarshalingV3 { - return jsonv2.Unmarshal(data, o) - } - if err := json.Unmarshal(data, &o.OperationProps); err != nil { - return err - } - return json.Unmarshal(data, &o.VendorExtensible) + return jsonv2.Unmarshal(data, o) } func (o *Operation) UnmarshalJSONFrom(dec *jsontext.Decoder) error { var x struct { - Extensions spec.Extensions `json:",inline"` + Extensions spec.Extensions `json:",embed"` OperationProps } if err := jsonv2.UnmarshalDecode(dec, &x); err != nil { diff --git a/vendor/k8s.io/kube-openapi/pkg/spec3/parameter.go b/vendor/k8s.io/kube-openapi/pkg/spec3/parameter.go index a5e7d46c4..7a8f7650b 100644 --- a/vendor/k8s.io/kube-openapi/pkg/spec3/parameter.go +++ b/vendor/k8s.io/kube-openapi/pkg/spec3/parameter.go @@ -17,12 +17,10 @@ limitations under the License. package spec3 import ( - "encoding/json" + "encoding/json/jsontext" + jsonv2 "encoding/json/v2" - "github.com/go-openapi/swag" "k8s.io/kube-openapi/pkg/internal" - jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext" "k8s.io/kube-openapi/pkg/validation/spec" ) @@ -37,29 +35,14 @@ type Parameter struct { // MarshalJSON is a custom marshal function that knows how to encode Parameter as JSON func (p *Parameter) MarshalJSON() ([]byte, error) { - if internal.UseOptimizedJSONMarshalingV3 { - return internal.DeterministicMarshal(p) - } - b1, err := json.Marshal(p.Refable) - if err != nil { - return nil, err - } - b2, err := json.Marshal(p.ParameterProps) - if err != nil { - return nil, err - } - b3, err := json.Marshal(p.VendorExtensible) - if err != nil { - return nil, err - } - return swag.ConcatJSON(b1, b2, b3), nil + return internal.DeterministicMarshal(p) } func (p *Parameter) MarshalJSONTo(enc *jsontext.Encoder) error { var x struct { Ref string `json:"$ref,omitempty"` - ParameterProps parameterPropsOmitZero `json:",inline"` - Extensions spec.Extensions `json:",inline"` + ParameterProps parameterPropsOmitZero `json:",embed"` + Extensions spec.Extensions `json:",embed"` } x.Ref = p.Refable.Ref.String() x.Extensions = internal.SanitizeExtensions(p.Extensions) @@ -68,26 +51,12 @@ func (p *Parameter) MarshalJSONTo(enc *jsontext.Encoder) error { } func (p *Parameter) UnmarshalJSON(data []byte) error { - if internal.UseOptimizedJSONUnmarshalingV3 { - return jsonv2.Unmarshal(data, p) - } - - if err := json.Unmarshal(data, &p.Refable); err != nil { - return err - } - if err := json.Unmarshal(data, &p.ParameterProps); err != nil { - return err - } - if err := json.Unmarshal(data, &p.VendorExtensible); err != nil { - return err - } - - return nil + return jsonv2.Unmarshal(data, p) } func (p *Parameter) UnmarshalJSONFrom(dec *jsontext.Decoder) error { var x struct { - Extensions spec.Extensions `json:",inline"` + Extensions spec.Extensions `json:",embed"` ParameterProps } if err := jsonv2.UnmarshalDecode(dec, &x); err != nil { diff --git a/vendor/k8s.io/kube-openapi/pkg/spec3/path.go b/vendor/k8s.io/kube-openapi/pkg/spec3/path.go index cb04cf0f9..f9767de4e 100644 --- a/vendor/k8s.io/kube-openapi/pkg/spec3/path.go +++ b/vendor/k8s.io/kube-openapi/pkg/spec3/path.go @@ -17,14 +17,12 @@ limitations under the License. package spec3 import ( - "encoding/json" + "encoding/json/jsontext" + jsonv2 "encoding/json/v2" "fmt" "strings" - "github.com/go-openapi/swag" "k8s.io/kube-openapi/pkg/internal" - jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext" "k8s.io/kube-openapi/pkg/validation/spec" ) @@ -36,26 +34,7 @@ type Paths struct { // MarshalJSON is a custom marshal function that knows how to encode Paths as JSON func (p *Paths) MarshalJSON() ([]byte, error) { - if internal.UseOptimizedJSONMarshalingV3 { - return internal.DeterministicMarshal(p) - } - b1, err := json.Marshal(p.VendorExtensible) - if err != nil { - return nil, err - } - - pths := make(map[string]*Path) - for k, v := range p.Paths { - if strings.HasPrefix(k, "/") { - pths[k] = v - } - } - b2, err := json.Marshal(pths) - if err != nil { - return nil, err - } - concated := swag.ConcatJSON(b1, b2) - return concated, nil + return internal.DeterministicMarshal(p) } func (p *Paths) MarshalJSONTo(enc *jsontext.Encoder) error { @@ -75,36 +54,7 @@ func (p *Paths) MarshalJSONTo(enc *jsontext.Encoder) error { // UnmarshalJSON hydrates this items instance with the data from JSON func (p *Paths) UnmarshalJSON(data []byte) error { - if internal.UseOptimizedJSONUnmarshalingV3 { - return jsonv2.Unmarshal(data, p) - } - var res map[string]json.RawMessage - if err := json.Unmarshal(data, &res); err != nil { - return err - } - for k, v := range res { - if strings.HasPrefix(strings.ToLower(k), "x-") { - if p.Extensions == nil { - p.Extensions = make(map[string]interface{}) - } - var d interface{} - if err := json.Unmarshal(v, &d); err != nil { - return err - } - p.Extensions[k] = d - } - if strings.HasPrefix(k, "/") { - if p.Paths == nil { - p.Paths = make(map[string]*Path) - } - var pi *Path - if err := json.Unmarshal(v, &pi); err != nil { - return err - } - p.Paths[k] = pi - } - } - return nil + return jsonv2.Unmarshal(data, p) } func (p *Paths) UnmarshalJSONFrom(dec *jsontext.Decoder) error { @@ -171,28 +121,13 @@ type Path struct { // MarshalJSON is a custom marshal function that knows how to encode Path as JSON func (p *Path) MarshalJSON() ([]byte, error) { - if internal.UseOptimizedJSONMarshalingV3 { - return internal.DeterministicMarshal(p) - } - b1, err := json.Marshal(p.Refable) - if err != nil { - return nil, err - } - b2, err := json.Marshal(p.PathProps) - if err != nil { - return nil, err - } - b3, err := json.Marshal(p.VendorExtensible) - if err != nil { - return nil, err - } - return swag.ConcatJSON(b1, b2, b3), nil + return internal.DeterministicMarshal(p) } func (p *Path) MarshalJSONTo(enc *jsontext.Encoder) error { var x struct { Ref string `json:"$ref,omitempty"` - Extensions spec.Extensions `json:",inline"` + Extensions spec.Extensions `json:",embed"` PathProps } x.Ref = p.Refable.Ref.String() @@ -202,24 +137,12 @@ func (p *Path) MarshalJSONTo(enc *jsontext.Encoder) error { } func (p *Path) UnmarshalJSON(data []byte) error { - if internal.UseOptimizedJSONUnmarshalingV3 { - return jsonv2.Unmarshal(data, p) - } - if err := json.Unmarshal(data, &p.Refable); err != nil { - return err - } - if err := json.Unmarshal(data, &p.PathProps); err != nil { - return err - } - if err := json.Unmarshal(data, &p.VendorExtensible); err != nil { - return err - } - return nil + return jsonv2.Unmarshal(data, p) } func (p *Path) UnmarshalJSONFrom(dec *jsontext.Decoder) error { var x struct { - Extensions spec.Extensions `json:",inline"` + Extensions spec.Extensions `json:",embed"` PathProps } diff --git a/vendor/k8s.io/kube-openapi/pkg/spec3/request_body.go b/vendor/k8s.io/kube-openapi/pkg/spec3/request_body.go index b39c0d4fe..0c65c1504 100644 --- a/vendor/k8s.io/kube-openapi/pkg/spec3/request_body.go +++ b/vendor/k8s.io/kube-openapi/pkg/spec3/request_body.go @@ -17,12 +17,10 @@ limitations under the License. package spec3 import ( - "encoding/json" + "encoding/json/jsontext" + jsonv2 "encoding/json/v2" - "github.com/go-openapi/swag" "k8s.io/kube-openapi/pkg/internal" - jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext" "k8s.io/kube-openapi/pkg/validation/spec" ) @@ -37,29 +35,14 @@ type RequestBody struct { // MarshalJSON is a custom marshal function that knows how to encode RequestBody as JSON func (r *RequestBody) MarshalJSON() ([]byte, error) { - if internal.UseOptimizedJSONMarshalingV3 { - return internal.DeterministicMarshal(r) - } - b1, err := json.Marshal(r.Refable) - if err != nil { - return nil, err - } - b2, err := json.Marshal(r.RequestBodyProps) - if err != nil { - return nil, err - } - b3, err := json.Marshal(r.VendorExtensible) - if err != nil { - return nil, err - } - return swag.ConcatJSON(b1, b2, b3), nil + return internal.DeterministicMarshal(r) } func (r *RequestBody) MarshalJSONTo(enc *jsontext.Encoder) error { var x struct { Ref string `json:"$ref,omitempty"` - RequestBodyProps requestBodyPropsOmitZero `json:",inline"` - Extensions spec.Extensions `json:",inline"` + RequestBodyProps requestBodyPropsOmitZero `json:",embed"` + Extensions spec.Extensions `json:",embed"` } x.Ref = r.Refable.Ref.String() x.Extensions = internal.SanitizeExtensions(r.Extensions) @@ -68,19 +51,7 @@ func (r *RequestBody) MarshalJSONTo(enc *jsontext.Encoder) error { } func (r *RequestBody) UnmarshalJSON(data []byte) error { - if internal.UseOptimizedJSONUnmarshalingV3 { - return jsonv2.Unmarshal(data, r) - } - if err := json.Unmarshal(data, &r.Refable); err != nil { - return err - } - if err := json.Unmarshal(data, &r.RequestBodyProps); err != nil { - return err - } - if err := json.Unmarshal(data, &r.VendorExtensible); err != nil { - return err - } - return nil + return jsonv2.Unmarshal(data, r) } // RequestBodyProps describes a single request body, more at https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#requestBodyObject @@ -101,7 +72,7 @@ type requestBodyPropsOmitZero struct { func (r *RequestBody) UnmarshalJSONFrom(dec *jsontext.Decoder) error { var x struct { - Extensions spec.Extensions `json:",inline"` + Extensions spec.Extensions `json:",embed"` RequestBodyProps } if err := jsonv2.UnmarshalDecode(dec, &x); err != nil { diff --git a/vendor/k8s.io/kube-openapi/pkg/spec3/response.go b/vendor/k8s.io/kube-openapi/pkg/spec3/response.go index 72ad9882d..571439c6f 100644 --- a/vendor/k8s.io/kube-openapi/pkg/spec3/response.go +++ b/vendor/k8s.io/kube-openapi/pkg/spec3/response.go @@ -18,13 +18,12 @@ package spec3 import ( "encoding/json" + "encoding/json/jsontext" + jsonv2 "encoding/json/v2" "fmt" "strconv" - "github.com/go-openapi/swag" "k8s.io/kube-openapi/pkg/internal" - jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext" "k8s.io/kube-openapi/pkg/validation/spec" ) @@ -38,24 +37,13 @@ type Responses struct { // MarshalJSON is a custom marshal function that knows how to encode Responses as JSON func (r *Responses) MarshalJSON() ([]byte, error) { - if internal.UseOptimizedJSONMarshalingV3 { - return internal.DeterministicMarshal(r) - } - b1, err := json.Marshal(r.ResponsesProps) - if err != nil { - return nil, err - } - b2, err := json.Marshal(r.VendorExtensible) - if err != nil { - return nil, err - } - return swag.ConcatJSON(b1, b2), nil + return internal.DeterministicMarshal(r) } func (r Responses) MarshalJSONTo(enc *jsontext.Encoder) error { type ArbitraryKeys map[string]interface{} var x struct { - ArbitraryKeys ArbitraryKeys `json:",inline"` + ArbitraryKeys ArbitraryKeys `json:",embed"` Default *Response `json:"default,omitzero"` } x.ArbitraryKeys = make(map[string]any, len(r.Extensions)+len(r.StatusCodeResponses)) @@ -72,16 +60,7 @@ func (r Responses) MarshalJSONTo(enc *jsontext.Encoder) error { } func (r *Responses) UnmarshalJSON(data []byte) error { - if internal.UseOptimizedJSONUnmarshalingV3 { - return jsonv2.Unmarshal(data, r) - } - if err := json.Unmarshal(data, &r.ResponsesProps); err != nil { - return err - } - if err := json.Unmarshal(data, &r.VendorExtensible); err != nil { - return err - } - return nil + return jsonv2.Unmarshal(data, r) } // ResponsesProps holds the list of possible responses as they are returned from executing this operation @@ -106,35 +85,7 @@ func (r ResponsesProps) MarshalJSON() ([]byte, error) { // UnmarshalJSON unmarshals responses from JSON func (r *ResponsesProps) UnmarshalJSON(data []byte) error { - if internal.UseOptimizedJSONUnmarshalingV3 { - return jsonv2.Unmarshal(data, r) - } - var res map[string]json.RawMessage - if err := json.Unmarshal(data, &res); err != nil { - return err - } - if v, ok := res["default"]; ok { - value := Response{} - if err := json.Unmarshal(v, &value); err != nil { - return err - } - r.Default = &value - delete(res, "default") - } - for k, v := range res { - // Take all integral keys - if nk, err := strconv.Atoi(k); err == nil { - if r.StatusCodeResponses == nil { - r.StatusCodeResponses = map[int]*Response{} - } - value := Response{} - if err := json.Unmarshal(v, &value); err != nil { - return err - } - r.StatusCodeResponses[nk] = &value - } - } - return nil + return jsonv2.Unmarshal(data, r) } func (r *Responses) UnmarshalJSONFrom(dec *jsontext.Decoder) (err error) { @@ -202,29 +153,14 @@ type Response struct { // MarshalJSON is a custom marshal function that knows how to encode Response as JSON func (r *Response) MarshalJSON() ([]byte, error) { - if internal.UseOptimizedJSONMarshalingV3 { - return internal.DeterministicMarshal(r) - } - b1, err := json.Marshal(r.Refable) - if err != nil { - return nil, err - } - b2, err := json.Marshal(r.ResponseProps) - if err != nil { - return nil, err - } - b3, err := json.Marshal(r.VendorExtensible) - if err != nil { - return nil, err - } - return swag.ConcatJSON(b1, b2, b3), nil + return internal.DeterministicMarshal(r) } func (r Response) MarshalJSONTo(enc *jsontext.Encoder) error { var x struct { Ref string `json:"$ref,omitempty"` - Extensions spec.Extensions `json:",inline"` - ResponseProps `json:",inline"` + Extensions spec.Extensions `json:",embed"` + ResponseProps `json:",embed"` } x.Ref = r.Refable.Ref.String() x.Extensions = internal.SanitizeExtensions(r.Extensions) @@ -233,24 +169,12 @@ func (r Response) MarshalJSONTo(enc *jsontext.Encoder) error { } func (r *Response) UnmarshalJSON(data []byte) error { - if internal.UseOptimizedJSONUnmarshalingV3 { - return jsonv2.Unmarshal(data, r) - } - if err := json.Unmarshal(data, &r.Refable); err != nil { - return err - } - if err := json.Unmarshal(data, &r.ResponseProps); err != nil { - return err - } - if err := json.Unmarshal(data, &r.VendorExtensible); err != nil { - return err - } - return nil + return jsonv2.Unmarshal(data, r) } func (r *Response) UnmarshalJSONFrom(dec *jsontext.Decoder) error { var x struct { - Extensions spec.Extensions `json:",inline"` + Extensions spec.Extensions `json:",embed"` ResponseProps } if err := jsonv2.UnmarshalDecode(dec, &x); err != nil { @@ -285,29 +209,14 @@ type Link struct { // MarshalJSON is a custom marshal function that knows how to encode Link as JSON func (r *Link) MarshalJSON() ([]byte, error) { - if internal.UseOptimizedJSONMarshalingV3 { - return internal.DeterministicMarshal(r) - } - b1, err := json.Marshal(r.Refable) - if err != nil { - return nil, err - } - b2, err := json.Marshal(r.LinkProps) - if err != nil { - return nil, err - } - b3, err := json.Marshal(r.VendorExtensible) - if err != nil { - return nil, err - } - return swag.ConcatJSON(b1, b2, b3), nil + return internal.DeterministicMarshal(r) } func (r *Link) MarshalJSONTo(enc *jsontext.Encoder) error { var x struct { Ref string `json:"$ref,omitempty"` - Extensions spec.Extensions `json:",inline"` - LinkProps `json:",inline"` + Extensions spec.Extensions `json:",embed"` + LinkProps `json:",embed"` } x.Ref = r.Refable.Ref.String() x.Extensions = internal.SanitizeExtensions(r.Extensions) @@ -316,25 +225,12 @@ func (r *Link) MarshalJSONTo(enc *jsontext.Encoder) error { } func (r *Link) UnmarshalJSON(data []byte) error { - if internal.UseOptimizedJSONUnmarshalingV3 { - return jsonv2.Unmarshal(data, r) - } - if err := json.Unmarshal(data, &r.Refable); err != nil { - return err - } - if err := json.Unmarshal(data, &r.LinkProps); err != nil { - return err - } - if err := json.Unmarshal(data, &r.VendorExtensible); err != nil { - return err - } - - return nil + return jsonv2.Unmarshal(data, r) } func (l *Link) UnmarshalJSONFrom(dec *jsontext.Decoder) error { var x struct { - Extensions spec.Extensions `json:",inline"` + Extensions spec.Extensions `json:",embed"` LinkProps } if err := jsonv2.UnmarshalDecode(dec, &x); err != nil { diff --git a/vendor/k8s.io/kube-openapi/pkg/spec3/security_scheme.go b/vendor/k8s.io/kube-openapi/pkg/spec3/security_scheme.go index 9bc180eaf..78109fb4d 100644 --- a/vendor/k8s.io/kube-openapi/pkg/spec3/security_scheme.go +++ b/vendor/k8s.io/kube-openapi/pkg/spec3/security_scheme.go @@ -18,11 +18,12 @@ package spec3 import ( "encoding/json" + "encoding/json/jsontext" + jsonv2 "encoding/json/v2" + + "github.com/go-openapi/swag/jsonutils" - "github.com/go-openapi/swag" "k8s.io/kube-openapi/pkg/internal" - jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext" "k8s.io/kube-openapi/pkg/validation/spec" ) @@ -35,29 +36,14 @@ type SecurityScheme struct { // MarshalJSON is a custom marshal function that knows how to encode SecurityScheme as JSON func (s *SecurityScheme) MarshalJSON() ([]byte, error) { - if internal.UseOptimizedJSONMarshalingV3 { - return internal.DeterministicMarshal(s) - } - b1, err := json.Marshal(s.SecuritySchemeProps) - if err != nil { - return nil, err - } - b2, err := json.Marshal(s.VendorExtensible) - if err != nil { - return nil, err - } - b3, err := json.Marshal(s.Refable) - if err != nil { - return nil, err - } - return swag.ConcatJSON(b1, b2, b3), nil + return internal.DeterministicMarshal(s) } func (s *SecurityScheme) MarshalJSONTo(enc *jsontext.Encoder) error { var x struct { Ref string `json:"$ref,omitempty"` - SecuritySchemeProps `json:",inline"` - Extensions spec.Extensions `json:",inline"` + SecuritySchemeProps `json:",embed"` + Extensions spec.Extensions `json:",embed"` } x.Ref = s.Refable.Ref.String() x.Extensions = internal.SanitizeExtensions(s.Extensions) @@ -112,7 +98,7 @@ func (o *OAuthFlow) MarshalJSON() ([]byte, error) { if err != nil { return nil, err } - return swag.ConcatJSON(b1, b2), nil + return jsonutils.ConcatJSON(b1, b2), nil } // UnmarshalJSON hydrates this items instance with the data from JSON diff --git a/vendor/k8s.io/kube-openapi/pkg/spec3/server.go b/vendor/k8s.io/kube-openapi/pkg/spec3/server.go index 3037fbce4..7c789f9fb 100644 --- a/vendor/k8s.io/kube-openapi/pkg/spec3/server.go +++ b/vendor/k8s.io/kube-openapi/pkg/spec3/server.go @@ -17,12 +17,10 @@ limitations under the License. package spec3 import ( - "encoding/json" + "encoding/json/jsontext" + jsonv2 "encoding/json/v2" - "github.com/go-openapi/swag" "k8s.io/kube-openapi/pkg/internal" - jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext" "k8s.io/kube-openapi/pkg/validation/spec" ) @@ -42,24 +40,13 @@ type ServerProps struct { // MarshalJSON is a custom marshal function that knows how to encode Responses as JSON func (s *Server) MarshalJSON() ([]byte, error) { - if internal.UseOptimizedJSONMarshalingV3 { - return internal.DeterministicMarshal(s) - } - b1, err := json.Marshal(s.ServerProps) - if err != nil { - return nil, err - } - b2, err := json.Marshal(s.VendorExtensible) - if err != nil { - return nil, err - } - return swag.ConcatJSON(b1, b2), nil + return internal.DeterministicMarshal(s) } func (s *Server) MarshalJSONTo(enc *jsontext.Encoder) error { var x struct { - ServerProps `json:",inline"` - Extensions spec.Extensions `json:",inline"` + ServerProps `json:",embed"` + Extensions spec.Extensions `json:",embed"` } x.Extensions = internal.SanitizeExtensions(s.Extensions) x.ServerProps = s.ServerProps @@ -67,22 +54,12 @@ func (s *Server) MarshalJSONTo(enc *jsontext.Encoder) error { } func (s *Server) UnmarshalJSON(data []byte) error { - if internal.UseOptimizedJSONUnmarshalingV3 { - return jsonv2.Unmarshal(data, s) - } - - if err := json.Unmarshal(data, &s.ServerProps); err != nil { - return err - } - if err := json.Unmarshal(data, &s.VendorExtensible); err != nil { - return err - } - return nil + return jsonv2.Unmarshal(data, s) } func (s *Server) UnmarshalJSONFrom(dec *jsontext.Decoder) error { var x struct { - Extensions spec.Extensions `json:",inline"` + Extensions spec.Extensions `json:",embed"` ServerProps } if err := jsonv2.UnmarshalDecode(dec, &x); err != nil { @@ -110,24 +87,13 @@ type ServerVariableProps struct { // MarshalJSON is a custom marshal function that knows how to encode Responses as JSON func (s *ServerVariable) MarshalJSON() ([]byte, error) { - if internal.UseOptimizedJSONMarshalingV3 { - return internal.DeterministicMarshal(s) - } - b1, err := json.Marshal(s.ServerVariableProps) - if err != nil { - return nil, err - } - b2, err := json.Marshal(s.VendorExtensible) - if err != nil { - return nil, err - } - return swag.ConcatJSON(b1, b2), nil + return internal.DeterministicMarshal(s) } func (s *ServerVariable) MarshalJSONTo(enc *jsontext.Encoder) error { var x struct { - ServerVariableProps `json:",inline"` - Extensions spec.Extensions `json:",inline"` + ServerVariableProps `json:",embed"` + Extensions spec.Extensions `json:",embed"` } x.Extensions = internal.SanitizeExtensions(s.Extensions) x.ServerVariableProps = s.ServerVariableProps @@ -135,21 +101,12 @@ func (s *ServerVariable) MarshalJSONTo(enc *jsontext.Encoder) error { } func (s *ServerVariable) UnmarshalJSON(data []byte) error { - if internal.UseOptimizedJSONUnmarshalingV3 { - return jsonv2.Unmarshal(data, s) - } - if err := json.Unmarshal(data, &s.ServerVariableProps); err != nil { - return err - } - if err := json.Unmarshal(data, &s.VendorExtensible); err != nil { - return err - } - return nil + return jsonv2.Unmarshal(data, s) } func (s *ServerVariable) UnmarshalJSONFrom(dec *jsontext.Decoder) error { var x struct { - Extensions spec.Extensions `json:",inline"` + Extensions spec.Extensions `json:",embed"` ServerVariableProps } if err := jsonv2.UnmarshalDecode(dec, &x); err != nil { diff --git a/vendor/k8s.io/kube-openapi/pkg/spec3/spec.go b/vendor/k8s.io/kube-openapi/pkg/spec3/spec.go index 91b1ae333..1d37a7de9 100644 --- a/vendor/k8s.io/kube-openapi/pkg/spec3/spec.go +++ b/vendor/k8s.io/kube-openapi/pkg/spec3/spec.go @@ -17,11 +17,10 @@ limitations under the License. package spec3 import ( - "encoding/json" + "encoding/json/jsontext" + jsonv2 "encoding/json/v2" "k8s.io/kube-openapi/pkg/internal" - jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext" "k8s.io/kube-openapi/pkg/validation/spec" ) @@ -46,19 +45,11 @@ type OpenAPI struct { func (o *OpenAPI) UnmarshalJSON(data []byte) error { type OpenAPIWithNoFunctions OpenAPI p := (*OpenAPIWithNoFunctions)(o) - if internal.UseOptimizedJSONUnmarshalingV3 { - return jsonv2.Unmarshal(data, &p) - } - return json.Unmarshal(data, &p) + return jsonv2.Unmarshal(data, &p) } func (o *OpenAPI) MarshalJSON() ([]byte, error) { - if internal.UseOptimizedJSONMarshalingV3 { - return internal.DeterministicMarshal(o) - } - type OpenAPIWithNoFunctions OpenAPI - p := (*OpenAPIWithNoFunctions)(o) - return json.Marshal(&p) + return internal.DeterministicMarshal(o) } func (o *OpenAPI) MarshalJSONTo(enc *jsontext.Encoder) error { diff --git a/vendor/k8s.io/kube-openapi/pkg/validation/spec/header.go b/vendor/k8s.io/kube-openapi/pkg/validation/spec/header.go index 5aa66ae25..5f8504144 100644 --- a/vendor/k8s.io/kube-openapi/pkg/validation/spec/header.go +++ b/vendor/k8s.io/kube-openapi/pkg/validation/spec/header.go @@ -15,12 +15,10 @@ package spec import ( - "encoding/json" + "encoding/json/jsontext" + jsonv2 "encoding/json/v2" - "github.com/go-openapi/swag" "k8s.io/kube-openapi/pkg/internal" - jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext" ) const ( @@ -44,33 +42,14 @@ type Header struct { // MarshalJSON marshal this to JSON func (h Header) MarshalJSON() ([]byte, error) { - if internal.UseOptimizedJSONMarshaling { - return internal.DeterministicMarshal(h) - } - b1, err := json.Marshal(h.CommonValidations) - if err != nil { - return nil, err - } - b2, err := json.Marshal(h.SimpleSchema) - if err != nil { - return nil, err - } - b3, err := json.Marshal(h.HeaderProps) - if err != nil { - return nil, err - } - b4, err := json.Marshal(h.VendorExtensible) - if err != nil { - return nil, err - } - return swag.ConcatJSON(b1, b2, b3, b4), nil + return internal.DeterministicMarshal(h) } func (h Header) MarshalJSONTo(enc *jsontext.Encoder) error { var x struct { - CommonValidations commonValidationsOmitZero `json:",inline"` - SimpleSchema simpleSchemaOmitZero `json:",inline"` - Extensions Extensions `json:",inline"` + CommonValidations commonValidationsOmitZero `json:",embed"` + SimpleSchema simpleSchemaOmitZero `json:",embed"` + Extensions Extensions `json:",embed"` HeaderProps } x.CommonValidations = commonValidationsOmitZero(h.CommonValidations) @@ -82,27 +61,14 @@ func (h Header) MarshalJSONTo(enc *jsontext.Encoder) error { // UnmarshalJSON unmarshals this header from JSON func (h *Header) UnmarshalJSON(data []byte) error { - if internal.UseOptimizedJSONUnmarshaling { - return jsonv2.Unmarshal(data, h) - } - - if err := json.Unmarshal(data, &h.CommonValidations); err != nil { - return err - } - if err := json.Unmarshal(data, &h.SimpleSchema); err != nil { - return err - } - if err := json.Unmarshal(data, &h.VendorExtensible); err != nil { - return err - } - return json.Unmarshal(data, &h.HeaderProps) + return jsonv2.Unmarshal(data, h) } func (h *Header) UnmarshalJSONFrom(dec *jsontext.Decoder) error { var x struct { CommonValidations SimpleSchema - Extensions Extensions `json:",inline"` + Extensions Extensions `json:",embed"` HeaderProps } diff --git a/vendor/k8s.io/kube-openapi/pkg/validation/spec/info.go b/vendor/k8s.io/kube-openapi/pkg/validation/spec/info.go index 8d002a1c5..b426f9e15 100644 --- a/vendor/k8s.io/kube-openapi/pkg/validation/spec/info.go +++ b/vendor/k8s.io/kube-openapi/pkg/validation/spec/info.go @@ -16,12 +16,11 @@ package spec import ( "encoding/json" + "encoding/json/jsontext" + jsonv2 "encoding/json/v2" "strings" - "github.com/go-openapi/swag" "k8s.io/kube-openapi/pkg/internal" - jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext" ) // Extensions vendor specific extensions @@ -170,23 +169,12 @@ type Info struct { // MarshalJSON marshal this to JSON func (i Info) MarshalJSON() ([]byte, error) { - if internal.UseOptimizedJSONMarshaling { - return internal.DeterministicMarshal(i) - } - b1, err := json.Marshal(i.InfoProps) - if err != nil { - return nil, err - } - b2, err := json.Marshal(i.VendorExtensible) - if err != nil { - return nil, err - } - return swag.ConcatJSON(b1, b2), nil + return internal.DeterministicMarshal(i) } func (i Info) MarshalJSONTo(enc *jsontext.Encoder) error { var x struct { - Extensions Extensions `json:",inline"` + Extensions Extensions `json:",embed"` InfoProps } x.Extensions = i.Extensions @@ -196,19 +184,12 @@ func (i Info) MarshalJSONTo(enc *jsontext.Encoder) error { // UnmarshalJSON marshal this from JSON func (i *Info) UnmarshalJSON(data []byte) error { - if internal.UseOptimizedJSONUnmarshaling { - return jsonv2.Unmarshal(data, i) - } - - if err := json.Unmarshal(data, &i.InfoProps); err != nil { - return err - } - return json.Unmarshal(data, &i.VendorExtensible) + return jsonv2.Unmarshal(data, i) } func (i *Info) UnmarshalJSONFrom(dec *jsontext.Decoder) error { var x struct { - Extensions Extensions `json:",inline"` + Extensions Extensions `json:",embed"` InfoProps } if err := jsonv2.UnmarshalDecode(dec, &x); err != nil { diff --git a/vendor/k8s.io/kube-openapi/pkg/validation/spec/items.go b/vendor/k8s.io/kube-openapi/pkg/validation/spec/items.go index 6fbb19a46..48b8e4775 100644 --- a/vendor/k8s.io/kube-openapi/pkg/validation/spec/items.go +++ b/vendor/k8s.io/kube-openapi/pkg/validation/spec/items.go @@ -15,12 +15,10 @@ package spec import ( - "encoding/json" + "encoding/json/jsontext" + jsonv2 "encoding/json/v2" - "github.com/go-openapi/swag" "k8s.io/kube-openapi/pkg/internal" - jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext" ) const ( @@ -96,38 +94,14 @@ type Items struct { // UnmarshalJSON hydrates this items instance with the data from JSON func (i *Items) UnmarshalJSON(data []byte) error { - if internal.UseOptimizedJSONUnmarshaling { - return jsonv2.Unmarshal(data, i) - } - - var validations CommonValidations - if err := json.Unmarshal(data, &validations); err != nil { - return err - } - var ref Refable - if err := json.Unmarshal(data, &ref); err != nil { - return err - } - var simpleSchema SimpleSchema - if err := json.Unmarshal(data, &simpleSchema); err != nil { - return err - } - var vendorExtensible VendorExtensible - if err := json.Unmarshal(data, &vendorExtensible); err != nil { - return err - } - i.Refable = ref - i.CommonValidations = validations - i.SimpleSchema = simpleSchema - i.VendorExtensible = vendorExtensible - return nil + return jsonv2.Unmarshal(data, i) } func (i *Items) UnmarshalJSONFrom(dec *jsontext.Decoder) error { var x struct { CommonValidations SimpleSchema - Extensions Extensions `json:",inline"` + Extensions Extensions `json:",embed"` } if err := jsonv2.UnmarshalDecode(dec, &x); err != nil { return err @@ -144,34 +118,15 @@ func (i *Items) UnmarshalJSONFrom(dec *jsontext.Decoder) error { // MarshalJSON converts this items object to JSON func (i Items) MarshalJSON() ([]byte, error) { - if internal.UseOptimizedJSONMarshaling { - return internal.DeterministicMarshal(i) - } - b1, err := json.Marshal(i.CommonValidations) - if err != nil { - return nil, err - } - b2, err := json.Marshal(i.SimpleSchema) - if err != nil { - return nil, err - } - b3, err := json.Marshal(i.Refable) - if err != nil { - return nil, err - } - b4, err := json.Marshal(i.VendorExtensible) - if err != nil { - return nil, err - } - return swag.ConcatJSON(b4, b3, b1, b2), nil + return internal.DeterministicMarshal(i) } func (i Items) MarshalJSONTo(enc *jsontext.Encoder) error { var x struct { - CommonValidations commonValidationsOmitZero `json:",inline"` - SimpleSchema simpleSchemaOmitZero `json:",inline"` + CommonValidations commonValidationsOmitZero `json:",embed"` + SimpleSchema simpleSchemaOmitZero `json:",embed"` Ref string `json:"$ref,omitempty"` - Extensions Extensions `json:",inline"` + Extensions Extensions `json:",embed"` } x.CommonValidations = commonValidationsOmitZero(i.CommonValidations) x.SimpleSchema = simpleSchemaOmitZero(i.SimpleSchema) diff --git a/vendor/k8s.io/kube-openapi/pkg/validation/spec/operation.go b/vendor/k8s.io/kube-openapi/pkg/validation/spec/operation.go index 99b620f94..6e30e933d 100644 --- a/vendor/k8s.io/kube-openapi/pkg/validation/spec/operation.go +++ b/vendor/k8s.io/kube-openapi/pkg/validation/spec/operation.go @@ -16,11 +16,10 @@ package spec import ( "encoding/json" + "encoding/json/jsontext" + jsonv2 "encoding/json/v2" - "github.com/go-openapi/swag" "k8s.io/kube-openapi/pkg/internal" - jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext" ) // OperationProps describes an operation @@ -95,20 +94,13 @@ type Operation struct { // UnmarshalJSON hydrates this items instance with the data from JSON func (o *Operation) UnmarshalJSON(data []byte) error { - if internal.UseOptimizedJSONUnmarshaling { - return jsonv2.Unmarshal(data, o) - } - - if err := json.Unmarshal(data, &o.OperationProps); err != nil { - return err - } - return json.Unmarshal(data, &o.VendorExtensible) + return jsonv2.Unmarshal(data, o) } func (o *Operation) UnmarshalJSONFrom(dec *jsontext.Decoder) error { type OperationPropsNoMethods OperationProps // strip MarshalJSON method var x struct { - Extensions Extensions `json:",inline"` + Extensions Extensions `json:",embed"` OperationPropsNoMethods } if err := jsonv2.UnmarshalDecode(dec, &x); err != nil { @@ -121,25 +113,13 @@ func (o *Operation) UnmarshalJSONFrom(dec *jsontext.Decoder) error { // MarshalJSON converts this items object to JSON func (o Operation) MarshalJSON() ([]byte, error) { - if internal.UseOptimizedJSONMarshaling { - return internal.DeterministicMarshal(o) - } - b1, err := json.Marshal(o.OperationProps) - if err != nil { - return nil, err - } - b2, err := json.Marshal(o.VendorExtensible) - if err != nil { - return nil, err - } - concated := swag.ConcatJSON(b1, b2) - return concated, nil + return internal.DeterministicMarshal(o) } func (o Operation) MarshalJSONTo(enc *jsontext.Encoder) error { var x struct { - Extensions Extensions `json:",inline"` - OperationProps operationPropsOmitZero `json:",inline"` + Extensions Extensions `json:",embed"` + OperationProps operationPropsOmitZero `json:",embed"` } x.Extensions = internal.SanitizeExtensions(o.Extensions) x.OperationProps = operationPropsOmitZero(o.OperationProps) diff --git a/vendor/k8s.io/kube-openapi/pkg/validation/spec/parameter.go b/vendor/k8s.io/kube-openapi/pkg/validation/spec/parameter.go index f2e61a721..27bf90dc0 100644 --- a/vendor/k8s.io/kube-openapi/pkg/validation/spec/parameter.go +++ b/vendor/k8s.io/kube-openapi/pkg/validation/spec/parameter.go @@ -15,12 +15,10 @@ package spec import ( - "encoding/json" + "encoding/json/jsontext" + jsonv2 "encoding/json/v2" - "github.com/go-openapi/swag" "k8s.io/kube-openapi/pkg/internal" - jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext" ) // ParamProps describes the specific attributes of an operation parameter @@ -89,30 +87,14 @@ type Parameter struct { // UnmarshalJSON hydrates this items instance with the data from JSON func (p *Parameter) UnmarshalJSON(data []byte) error { - if internal.UseOptimizedJSONUnmarshaling { - return jsonv2.Unmarshal(data, p) - } - - if err := json.Unmarshal(data, &p.CommonValidations); err != nil { - return err - } - if err := json.Unmarshal(data, &p.Refable); err != nil { - return err - } - if err := json.Unmarshal(data, &p.SimpleSchema); err != nil { - return err - } - if err := json.Unmarshal(data, &p.VendorExtensible); err != nil { - return err - } - return json.Unmarshal(data, &p.ParamProps) + return jsonv2.Unmarshal(data, p) } func (p *Parameter) UnmarshalJSONFrom(dec *jsontext.Decoder) error { var x struct { CommonValidations SimpleSchema - Extensions Extensions `json:",inline"` + Extensions Extensions `json:",embed"` ParamProps } if err := jsonv2.UnmarshalDecode(dec, &x); err != nil { @@ -130,39 +112,16 @@ func (p *Parameter) UnmarshalJSONFrom(dec *jsontext.Decoder) error { // MarshalJSON converts this items object to JSON func (p Parameter) MarshalJSON() ([]byte, error) { - if internal.UseOptimizedJSONMarshaling { - return internal.DeterministicMarshal(p) - } - b1, err := json.Marshal(p.CommonValidations) - if err != nil { - return nil, err - } - b2, err := json.Marshal(p.SimpleSchema) - if err != nil { - return nil, err - } - b3, err := json.Marshal(p.Refable) - if err != nil { - return nil, err - } - b4, err := json.Marshal(p.VendorExtensible) - if err != nil { - return nil, err - } - b5, err := json.Marshal(p.ParamProps) - if err != nil { - return nil, err - } - return swag.ConcatJSON(b3, b1, b2, b4, b5), nil + return internal.DeterministicMarshal(p) } func (p Parameter) MarshalJSONTo(enc *jsontext.Encoder) error { var x struct { - CommonValidations commonValidationsOmitZero `json:",inline"` - SimpleSchema simpleSchemaOmitZero `json:",inline"` - ParamProps paramPropsOmitZero `json:",inline"` + CommonValidations commonValidationsOmitZero `json:",embed"` + SimpleSchema simpleSchemaOmitZero `json:",embed"` + ParamProps paramPropsOmitZero `json:",embed"` Ref string `json:"$ref,omitempty"` - Extensions Extensions `json:",inline"` + Extensions Extensions `json:",embed"` } x.CommonValidations = commonValidationsOmitZero(p.CommonValidations) x.SimpleSchema = simpleSchemaOmitZero(p.SimpleSchema) diff --git a/vendor/k8s.io/kube-openapi/pkg/validation/spec/path_item.go b/vendor/k8s.io/kube-openapi/pkg/validation/spec/path_item.go index f2a0d9542..24cd5e431 100644 --- a/vendor/k8s.io/kube-openapi/pkg/validation/spec/path_item.go +++ b/vendor/k8s.io/kube-openapi/pkg/validation/spec/path_item.go @@ -15,12 +15,10 @@ package spec import ( - "encoding/json" + "encoding/json/jsontext" + jsonv2 "encoding/json/v2" - "github.com/go-openapi/swag" "k8s.io/kube-openapi/pkg/internal" - jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext" ) // PathItemProps the path item specific properties @@ -49,22 +47,12 @@ type PathItem struct { // UnmarshalJSON hydrates this items instance with the data from JSON func (p *PathItem) UnmarshalJSON(data []byte) error { - if internal.UseOptimizedJSONUnmarshaling { - return jsonv2.Unmarshal(data, p) - } - - if err := json.Unmarshal(data, &p.Refable); err != nil { - return err - } - if err := json.Unmarshal(data, &p.VendorExtensible); err != nil { - return err - } - return json.Unmarshal(data, &p.PathItemProps) + return jsonv2.Unmarshal(data, p) } func (p *PathItem) UnmarshalJSONFrom(dec *jsontext.Decoder) error { var x struct { - Extensions Extensions `json:",inline"` + Extensions Extensions `json:",embed"` PathItemProps } @@ -82,29 +70,13 @@ func (p *PathItem) UnmarshalJSONFrom(dec *jsontext.Decoder) error { // MarshalJSON converts this items object to JSON func (p PathItem) MarshalJSON() ([]byte, error) { - if internal.UseOptimizedJSONMarshaling { - return internal.DeterministicMarshal(p) - } - b3, err := json.Marshal(p.Refable) - if err != nil { - return nil, err - } - b4, err := json.Marshal(p.VendorExtensible) - if err != nil { - return nil, err - } - b5, err := json.Marshal(p.PathItemProps) - if err != nil { - return nil, err - } - concated := swag.ConcatJSON(b3, b4, b5) - return concated, nil + return internal.DeterministicMarshal(p) } func (p PathItem) MarshalJSONTo(enc *jsontext.Encoder) error { var x struct { Ref string `json:"$ref,omitempty"` - Extensions Extensions `json:",inline"` + Extensions Extensions `json:",embed"` PathItemProps } x.Ref = p.Refable.Ref.String() diff --git a/vendor/k8s.io/kube-openapi/pkg/validation/spec/paths.go b/vendor/k8s.io/kube-openapi/pkg/validation/spec/paths.go index 23b72ccce..c495163e0 100644 --- a/vendor/k8s.io/kube-openapi/pkg/validation/spec/paths.go +++ b/vendor/k8s.io/kube-openapi/pkg/validation/spec/paths.go @@ -15,14 +15,12 @@ package spec import ( - "encoding/json" + "encoding/json/jsontext" + jsonv2 "encoding/json/v2" "fmt" "strings" - "github.com/go-openapi/swag" "k8s.io/kube-openapi/pkg/internal" - jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext" ) // Paths holds the relative paths to the individual endpoints. @@ -38,37 +36,7 @@ type Paths struct { // UnmarshalJSON hydrates this items instance with the data from JSON func (p *Paths) UnmarshalJSON(data []byte) error { - if internal.UseOptimizedJSONUnmarshaling { - return jsonv2.Unmarshal(data, p) - } - - var res map[string]json.RawMessage - if err := json.Unmarshal(data, &res); err != nil { - return err - } - for k, v := range res { - if strings.HasPrefix(strings.ToLower(k), "x-") { - if p.Extensions == nil { - p.Extensions = make(map[string]interface{}) - } - var d interface{} - if err := json.Unmarshal(v, &d); err != nil { - return err - } - p.Extensions[k] = d - } - if strings.HasPrefix(k, "/") { - if p.Paths == nil { - p.Paths = make(map[string]PathItem) - } - var pi PathItem - if err := json.Unmarshal(v, &pi); err != nil { - return err - } - p.Paths[k] = pi - } - } - return nil + return jsonv2.Unmarshal(data, p) } func (p *Paths) UnmarshalJSONFrom(dec *jsontext.Decoder) error { @@ -127,26 +95,7 @@ func (p *Paths) UnmarshalJSONFrom(dec *jsontext.Decoder) error { // MarshalJSON converts this items object to JSON func (p Paths) MarshalJSON() ([]byte, error) { - if internal.UseOptimizedJSONMarshaling { - return internal.DeterministicMarshal(p) - } - b1, err := json.Marshal(p.VendorExtensible) - if err != nil { - return nil, err - } - - pths := make(map[string]PathItem) - for k, v := range p.Paths { - if strings.HasPrefix(k, "/") { - pths[k] = v - } - } - b2, err := json.Marshal(pths) - if err != nil { - return nil, err - } - concated := swag.ConcatJSON(b1, b2) - return concated, nil + return internal.DeterministicMarshal(p) } func (p Paths) MarshalJSONTo(enc *jsontext.Encoder) error { diff --git a/vendor/k8s.io/kube-openapi/pkg/validation/spec/response.go b/vendor/k8s.io/kube-openapi/pkg/validation/spec/response.go index 585a93acc..9886fe598 100644 --- a/vendor/k8s.io/kube-openapi/pkg/validation/spec/response.go +++ b/vendor/k8s.io/kube-openapi/pkg/validation/spec/response.go @@ -15,12 +15,10 @@ package spec import ( - "encoding/json" + "encoding/json/jsontext" + jsonv2 "encoding/json/v2" - "github.com/go-openapi/swag" "k8s.io/kube-openapi/pkg/internal" - jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext" ) // ResponseProps properties specific to a response @@ -51,27 +49,13 @@ type Response struct { // UnmarshalJSON hydrates this items instance with the data from JSON func (r *Response) UnmarshalJSON(data []byte) error { - if internal.UseOptimizedJSONUnmarshaling { - return jsonv2.Unmarshal(data, r) - } - - if err := json.Unmarshal(data, &r.ResponseProps); err != nil { - return err - } - if err := json.Unmarshal(data, &r.Refable); err != nil { - return err - } - if err := json.Unmarshal(data, &r.VendorExtensible); err != nil { - return err - } - - return nil + return jsonv2.Unmarshal(data, r) } func (r *Response) UnmarshalJSONFrom(dec *jsontext.Decoder) error { var x struct { ResponseProps - Extensions Extensions `json:",inline"` + Extensions Extensions `json:",embed"` } if err := jsonv2.UnmarshalDecode(dec, &x); err != nil { @@ -89,29 +73,14 @@ func (r *Response) UnmarshalJSONFrom(dec *jsontext.Decoder) error { // MarshalJSON converts this items object to JSON func (r Response) MarshalJSON() ([]byte, error) { - if internal.UseOptimizedJSONMarshaling { - return internal.DeterministicMarshal(r) - } - b1, err := json.Marshal(r.ResponseProps) - if err != nil { - return nil, err - } - b2, err := json.Marshal(r.Refable) - if err != nil { - return nil, err - } - b3, err := json.Marshal(r.VendorExtensible) - if err != nil { - return nil, err - } - return swag.ConcatJSON(b1, b2, b3), nil + return internal.DeterministicMarshal(r) } func (r Response) MarshalJSONTo(enc *jsontext.Encoder) error { var x struct { Ref string `json:"$ref,omitempty"` - Extensions Extensions `json:",inline"` - ResponseProps responsePropsOmitZero `json:",inline"` + Extensions Extensions `json:",embed"` + ResponseProps responsePropsOmitZero `json:",embed"` } x.Ref = r.Refable.Ref.String() x.Extensions = internal.SanitizeExtensions(r.Extensions) diff --git a/vendor/k8s.io/kube-openapi/pkg/validation/spec/responses.go b/vendor/k8s.io/kube-openapi/pkg/validation/spec/responses.go index a1a3d0fd5..dbddd62f6 100644 --- a/vendor/k8s.io/kube-openapi/pkg/validation/spec/responses.go +++ b/vendor/k8s.io/kube-openapi/pkg/validation/spec/responses.go @@ -16,14 +16,12 @@ package spec import ( "encoding/json" + "encoding/json/jsontext" + jsonv2 "encoding/json/v2" "fmt" - "reflect" "strconv" - "github.com/go-openapi/swag" "k8s.io/kube-openapi/pkg/internal" - jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext" ) // Responses is a container for the expected responses of an operation. @@ -46,43 +44,18 @@ type Responses struct { // UnmarshalJSON hydrates this items instance with the data from JSON func (r *Responses) UnmarshalJSON(data []byte) error { - if internal.UseOptimizedJSONUnmarshaling { - return jsonv2.Unmarshal(data, r) - } - - if err := json.Unmarshal(data, &r.ResponsesProps); err != nil { - return err - } - if err := json.Unmarshal(data, &r.VendorExtensible); err != nil { - return err - } - if reflect.DeepEqual(ResponsesProps{}, r.ResponsesProps) { - r.ResponsesProps = ResponsesProps{} - } - return nil + return jsonv2.Unmarshal(data, r) } // MarshalJSON converts this items object to JSON func (r Responses) MarshalJSON() ([]byte, error) { - if internal.UseOptimizedJSONMarshaling { - return internal.DeterministicMarshal(r) - } - b1, err := json.Marshal(r.ResponsesProps) - if err != nil { - return nil, err - } - b2, err := json.Marshal(r.VendorExtensible) - if err != nil { - return nil, err - } - concated := swag.ConcatJSON(b1, b2) - return concated, nil + return internal.DeterministicMarshal(r) } func (r Responses) MarshalJSONTo(enc *jsontext.Encoder) error { type ArbitraryKeys map[string]interface{} var x struct { - ArbitraryKeys ArbitraryKeys `json:",inline"` + ArbitraryKeys ArbitraryKeys `json:",embed"` Default *Response `json:"default,omitempty"` } x.ArbitraryKeys = make(map[string]any, len(r.Extensions)+len(r.StatusCodeResponses)) @@ -120,35 +93,7 @@ func (r ResponsesProps) MarshalJSON() ([]byte, error) { // UnmarshalJSON unmarshals responses from JSON func (r *ResponsesProps) UnmarshalJSON(data []byte) error { - if internal.UseOptimizedJSONUnmarshaling { - return jsonv2.Unmarshal(data, r) - } - var res map[string]json.RawMessage - if err := json.Unmarshal(data, &res); err != nil { - return err - } - if v, ok := res["default"]; ok { - value := Response{} - if err := json.Unmarshal(v, &value); err != nil { - return err - } - r.Default = &value - delete(res, "default") - } - for k, v := range res { - // Take all integral keys - if nk, err := strconv.Atoi(k); err == nil { - if r.StatusCodeResponses == nil { - r.StatusCodeResponses = map[int]Response{} - } - value := Response{} - if err := json.Unmarshal(v, &value); err != nil { - return err - } - r.StatusCodeResponses[nk] = value - } - } - return nil + return jsonv2.Unmarshal(data, r) } func (r *Responses) UnmarshalJSONFrom(dec *jsontext.Decoder) (err error) { diff --git a/vendor/k8s.io/kube-openapi/pkg/validation/spec/schema.go b/vendor/k8s.io/kube-openapi/pkg/validation/spec/schema.go index 6c0c6fc14..c282e1c8a 100644 --- a/vendor/k8s.io/kube-openapi/pkg/validation/spec/schema.go +++ b/vendor/k8s.io/kube-openapi/pkg/validation/spec/schema.go @@ -16,14 +16,11 @@ package spec import ( "encoding/json" - "fmt" + "encoding/json/jsontext" + jsonv2 "encoding/json/v2" "net/url" - "strings" - "github.com/go-openapi/swag" "k8s.io/kube-openapi/pkg/internal" - jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext" ) // BooleanProperty creates a boolean property @@ -484,121 +481,44 @@ func (s *Schema) WithExternalDocs(description, url string) *Schema { // MarshalJSON marshal this to JSON func (s Schema) MarshalJSON() ([]byte, error) { - if internal.UseOptimizedJSONMarshaling { - return internal.DeterministicMarshal(s) - } - b1, err := json.Marshal(s.SchemaProps) - if err != nil { - return nil, fmt.Errorf("schema props %v", err) - } - b2, err := json.Marshal(s.VendorExtensible) - if err != nil { - return nil, fmt.Errorf("vendor props %v", err) - } - b3, err := s.Ref.MarshalJSON() - if err != nil { - return nil, fmt.Errorf("ref prop %v", err) - } - b4, err := s.Schema.MarshalJSON() - if err != nil { - return nil, fmt.Errorf("schema prop %v", err) - } - b5, err := json.Marshal(s.SwaggerSchemaProps) - if err != nil { - return nil, fmt.Errorf("common validations %v", err) - } - var b6 []byte - if s.ExtraProps != nil { - jj, err := json.Marshal(s.ExtraProps) - if err != nil { - return nil, fmt.Errorf("extra props %v", err) - } - b6 = jj - } - return swag.ConcatJSON(b1, b2, b3, b4, b5, b6), nil + return internal.DeterministicMarshal(s) } func (s Schema) MarshalJSONTo(enc *jsontext.Encoder) error { type ArbitraryKeys map[string]interface{} var x struct { - ArbitraryKeys ArbitraryKeys `json:",inline"` - SchemaProps schemaPropsOmitZero `json:",inline"` - SwaggerSchemaProps swaggerSchemaPropsOmitZero `json:",inline"` + ArbitraryKeys ArbitraryKeys `json:",embed"` + SchemaProps schemaPropsOmitZero `json:",embed"` + SwaggerSchemaProps swaggerSchemaPropsOmitZero `json:",embed"` Schema string `json:"$schema,omitempty"` Ref string `json:"$ref,omitempty"` } - x.ArbitraryKeys = make(map[string]any, len(s.Extensions)+len(s.ExtraProps)) - for k, v := range s.Extensions { - if internal.IsExtensionKey(k) { + if len(s.Extensions) > 0 || len(s.ExtraProps) > 0 { + x.ArbitraryKeys = make(map[string]any, len(s.Extensions)+len(s.ExtraProps)) + for k, v := range s.Extensions { + if internal.IsExtensionKey(k) { + x.ArbitraryKeys[k] = v + } + } + for k, v := range s.ExtraProps { x.ArbitraryKeys[k] = v } } - for k, v := range s.ExtraProps { - x.ArbitraryKeys[k] = v - } x.SchemaProps = schemaPropsOmitZero(s.SchemaProps) x.SwaggerSchemaProps = swaggerSchemaPropsOmitZero(s.SwaggerSchemaProps) x.Ref = s.Ref.String() x.Schema = string(s.Schema) - return jsonv2.MarshalEncode(enc, x) + return jsonv2.MarshalEncode(enc, &x) } // UnmarshalJSON marshal this from JSON func (s *Schema) UnmarshalJSON(data []byte) error { - if internal.UseOptimizedJSONUnmarshaling { - return jsonv2.Unmarshal(data, s) - } - - props := struct { - SchemaProps - SwaggerSchemaProps - }{} - if err := json.Unmarshal(data, &props); err != nil { - return err - } - - sch := Schema{ - SchemaProps: props.SchemaProps, - SwaggerSchemaProps: props.SwaggerSchemaProps, - } - - var d map[string]interface{} - if err := json.Unmarshal(data, &d); err != nil { - return err - } - - _ = sch.Ref.fromMap(d) - _ = sch.Schema.fromMap(d) - - delete(d, "$ref") - delete(d, "$schema") - for _, pn := range swag.DefaultJSONNameProvider.GetJSONNames(s) { - delete(d, pn) - } - - for k, vv := range d { - lk := strings.ToLower(k) - if strings.HasPrefix(lk, "x-") { - if sch.Extensions == nil { - sch.Extensions = map[string]interface{}{} - } - sch.Extensions[k] = vv - continue - } - if sch.ExtraProps == nil { - sch.ExtraProps = map[string]interface{}{} - } - sch.ExtraProps[k] = vv - } - - *s = sch - - return nil + return jsonv2.Unmarshal(data, s) } func (s *Schema) UnmarshalJSONFrom(dec *jsontext.Decoder) error { var x struct { - Extensions Extensions `json:",inline"` + Extensions Extensions `json:",embed"` SchemaProps SwaggerSchemaProps } @@ -617,9 +537,6 @@ func (s *Schema) UnmarshalJSONFrom(dec *jsontext.Decoder) error { delete(x.Extensions, "$ref") delete(x.Extensions, "$schema") - for _, pn := range swag.DefaultJSONNameProvider.GetJSONNames(s) { - delete(x.Extensions, pn) - } if len(x.Extensions) == 0 { x.Extensions = nil } diff --git a/vendor/k8s.io/kube-openapi/pkg/validation/spec/security_scheme.go b/vendor/k8s.io/kube-openapi/pkg/validation/spec/security_scheme.go index 7c7b6bdd8..7f6bbda56 100644 --- a/vendor/k8s.io/kube-openapi/pkg/validation/spec/security_scheme.go +++ b/vendor/k8s.io/kube-openapi/pkg/validation/spec/security_scheme.go @@ -16,11 +16,10 @@ package spec import ( "encoding/json" + "encoding/json/jsontext" + jsonv2 "encoding/json/v2" - "github.com/go-openapi/swag" "k8s.io/kube-openapi/pkg/internal" - jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext" ) // SecuritySchemeProps describes a swagger security scheme in the securityDefinitions section @@ -47,23 +46,12 @@ type SecurityScheme struct { // MarshalJSON marshal this to JSON func (s SecurityScheme) MarshalJSON() ([]byte, error) { - if internal.UseOptimizedJSONMarshaling { - return internal.DeterministicMarshal(s) - } - b1, err := json.Marshal(s.SecuritySchemeProps) - if err != nil { - return nil, err - } - b2, err := json.Marshal(s.VendorExtensible) - if err != nil { - return nil, err - } - return swag.ConcatJSON(b1, b2), nil + return internal.DeterministicMarshal(s) } func (s SecurityScheme) MarshalJSONTo(enc *jsontext.Encoder) error { var x struct { - Extensions Extensions `json:",inline"` + Extensions Extensions `json:",embed"` SecuritySchemeProps } x.Extensions = internal.SanitizeExtensions(s.Extensions) @@ -81,7 +69,7 @@ func (s *SecurityScheme) UnmarshalJSON(data []byte) error { func (s *SecurityScheme) UnmarshalJSONFrom(dec *jsontext.Decoder) error { var x struct { - Extensions Extensions `json:",inline"` + Extensions Extensions `json:",embed"` SecuritySchemeProps } if err := jsonv2.UnmarshalDecode(dec, &x); err != nil { diff --git a/vendor/k8s.io/kube-openapi/pkg/validation/spec/swagger.go b/vendor/k8s.io/kube-openapi/pkg/validation/spec/swagger.go index 533b7cc83..690d6ff7d 100644 --- a/vendor/k8s.io/kube-openapi/pkg/validation/spec/swagger.go +++ b/vendor/k8s.io/kube-openapi/pkg/validation/spec/swagger.go @@ -16,12 +16,11 @@ package spec import ( "encoding/json" + "encoding/json/jsontext" + jsonv2 "encoding/json/v2" "fmt" - "github.com/go-openapi/swag" "k8s.io/kube-openapi/pkg/internal" - jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext" ) // Swagger this is the root document object for the API specification. @@ -36,24 +35,13 @@ type Swagger struct { // MarshalJSON marshals this swagger structure to json func (s Swagger) MarshalJSON() ([]byte, error) { - if internal.UseOptimizedJSONMarshaling { - return internal.DeterministicMarshal(s) - } - b1, err := json.Marshal(s.SwaggerProps) - if err != nil { - return nil, err - } - b2, err := json.Marshal(s.VendorExtensible) - if err != nil { - return nil, err - } - return swag.ConcatJSON(b1, b2), nil + return internal.DeterministicMarshal(s) } // MarshalJSON marshals this swagger structure to json func (s Swagger) MarshalJSONTo(enc *jsontext.Encoder) error { var x struct { - Extensions Extensions `json:",inline"` + Extensions Extensions `json:",embed"` SwaggerProps } x.Extensions = internal.SanitizeExtensions(s.Extensions) @@ -63,18 +51,7 @@ func (s Swagger) MarshalJSONTo(enc *jsontext.Encoder) error { // UnmarshalJSON unmarshals a swagger spec from json func (s *Swagger) UnmarshalJSON(data []byte) error { - if internal.UseOptimizedJSONUnmarshaling { - return jsonv2.Unmarshal(data, s) - } - var sw Swagger - if err := json.Unmarshal(data, &sw.SwaggerProps); err != nil { - return err - } - if err := json.Unmarshal(data, &sw.VendorExtensible); err != nil { - return err - } - *s = sw - return nil + return jsonv2.Unmarshal(data, s) } func (s *Swagger) UnmarshalJSONFrom(dec *jsontext.Decoder) error { @@ -82,7 +59,7 @@ func (s *Swagger) UnmarshalJSONFrom(dec *jsontext.Decoder) error { // optimize this and other usages of this pattern: // https://github.com/kubernetes/kube-openapi/pull/319#discussion_r983165948 var x struct { - Extensions Extensions `json:",inline"` + Extensions Extensions `json:",embed"` SwaggerProps } @@ -133,17 +110,7 @@ var jsFalse = []byte("false") // MarshalJSON convert this object to JSON func (s SchemaOrBool) MarshalJSON() ([]byte, error) { - if internal.UseOptimizedJSONMarshaling { - return internal.DeterministicMarshal(s) - } - if s.Schema != nil { - return json.Marshal(s.Schema) - } - - if s.Schema == nil && !s.Allows { - return jsFalse, nil - } - return jsTrue, nil + return internal.DeterministicMarshal(s) } // MarshalJSON convert this object to JSON @@ -160,23 +127,7 @@ func (s SchemaOrBool) MarshalJSONTo(enc *jsontext.Encoder) error { // UnmarshalJSON converts this bool or schema object from a JSON structure func (s *SchemaOrBool) UnmarshalJSON(data []byte) error { - if internal.UseOptimizedJSONUnmarshaling { - return jsonv2.Unmarshal(data, s) - } - - var nw SchemaOrBool - if len(data) > 0 && data[0] == '{' { - var sch Schema - if err := json.Unmarshal(data, &sch); err != nil { - return err - } - nw.Schema = &sch - nw.Allows = true - } else { - json.Unmarshal(data, &nw.Allows) - } - *s = nw - return nil + return jsonv2.Unmarshal(data, s) } func (s *SchemaOrBool) UnmarshalJSONFrom(dec *jsontext.Decoder) error { @@ -207,16 +158,7 @@ type SchemaOrStringArray struct { // MarshalJSON converts this schema object or array into JSON structure func (s SchemaOrStringArray) MarshalJSON() ([]byte, error) { - if internal.UseOptimizedJSONMarshaling { - return internal.DeterministicMarshal(s) - } - if len(s.Property) > 0 { - return json.Marshal(s.Property) - } - if s.Schema != nil { - return json.Marshal(s.Schema) - } - return []byte("null"), nil + return internal.DeterministicMarshal(s) } // MarshalJSON converts this schema object or array into JSON structure @@ -232,29 +174,7 @@ func (s SchemaOrStringArray) MarshalJSONTo(enc *jsontext.Encoder) error { // UnmarshalJSON converts this schema object or array from a JSON structure func (s *SchemaOrStringArray) UnmarshalJSON(data []byte) error { - if internal.UseOptimizedJSONUnmarshaling { - return jsonv2.Unmarshal(data, s) - } - - var first byte - if len(data) > 1 { - first = data[0] - } - var nw SchemaOrStringArray - if first == '{' { - var sch Schema - if err := json.Unmarshal(data, &sch); err != nil { - return err - } - nw.Schema = &sch - } - if first == '[' { - if err := json.Unmarshal(data, &nw.Property); err != nil { - return err - } - } - *s = nw - return nil + return jsonv2.Unmarshal(data, s) } func (s *SchemaOrStringArray) UnmarshalJSONFrom(dec *jsontext.Decoder) error { @@ -299,38 +219,7 @@ func (s StringOrArray) Contains(value string) bool { // UnmarshalJSON unmarshals this string or array object from a JSON array or JSON string func (s *StringOrArray) UnmarshalJSON(data []byte) error { - if internal.UseOptimizedJSONUnmarshaling { - return jsonv2.Unmarshal(data, s) - } - - var first byte - if len(data) > 1 { - first = data[0] - } - - if first == '[' { - var parsed []string - if err := json.Unmarshal(data, &parsed); err != nil { - return err - } - *s = StringOrArray(parsed) - return nil - } - - var single interface{} - if err := json.Unmarshal(data, &single); err != nil { - return err - } - if single == nil { - return nil - } - switch v := single.(type) { - case string: - *s = StringOrArray([]string{v}) - return nil - default: - return fmt.Errorf("only string or array is allowed, not %T", single) - } + return jsonv2.Unmarshal(data, s) } func (s *StringOrArray) UnmarshalJSONFrom(dec *jsontext.Decoder) error { @@ -383,13 +272,7 @@ func (s *SchemaOrArray) ContainsType(name string) bool { // MarshalJSON converts this schema object or array into JSON structure func (s SchemaOrArray) MarshalJSON() ([]byte, error) { - if internal.UseOptimizedJSONMarshaling { - return internal.DeterministicMarshal(s) - } - if s.Schemas != nil { - return json.Marshal(s.Schemas) - } - return json.Marshal(s.Schema) + return internal.DeterministicMarshal(s) } // MarshalJSON converts this schema object or array into JSON structure @@ -402,29 +285,7 @@ func (s SchemaOrArray) MarshalJSONTo(enc *jsontext.Encoder) error { // UnmarshalJSON converts this schema object or array from a JSON structure func (s *SchemaOrArray) UnmarshalJSON(data []byte) error { - if internal.UseOptimizedJSONUnmarshaling { - return jsonv2.Unmarshal(data, s) - } - - var nw SchemaOrArray - var first byte - if len(data) > 1 { - first = data[0] - } - if first == '{' { - var sch Schema - if err := json.Unmarshal(data, &sch); err != nil { - return err - } - nw.Schema = &sch - } - if first == '[' { - if err := json.Unmarshal(data, &nw.Schemas); err != nil { - return err - } - } - *s = nw - return nil + return jsonv2.Unmarshal(data, s) } func (s *SchemaOrArray) UnmarshalJSONFrom(dec *jsontext.Decoder) error { diff --git a/vendor/k8s.io/kube-openapi/pkg/validation/spec/tag.go b/vendor/k8s.io/kube-openapi/pkg/validation/spec/tag.go index 89c3d0d82..b3b57c60c 100644 --- a/vendor/k8s.io/kube-openapi/pkg/validation/spec/tag.go +++ b/vendor/k8s.io/kube-openapi/pkg/validation/spec/tag.go @@ -15,12 +15,10 @@ package spec import ( - "encoding/json" + "encoding/json/jsontext" + jsonv2 "encoding/json/v2" - "github.com/go-openapi/swag" "k8s.io/kube-openapi/pkg/internal" - jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json" - "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext" ) // TagProps describe a tag entry in the top level tags section of a swagger spec @@ -42,23 +40,12 @@ type Tag struct { // MarshalJSON marshal this to JSON func (t Tag) MarshalJSON() ([]byte, error) { - if internal.UseOptimizedJSONMarshaling { - return internal.DeterministicMarshal(t) - } - b1, err := json.Marshal(t.TagProps) - if err != nil { - return nil, err - } - b2, err := json.Marshal(t.VendorExtensible) - if err != nil { - return nil, err - } - return swag.ConcatJSON(b1, b2), nil + return internal.DeterministicMarshal(t) } func (t Tag) MarshalJSONTo(enc *jsontext.Encoder) error { var x struct { - Extensions Extensions `json:",inline"` + Extensions Extensions `json:",embed"` TagProps } x.Extensions = internal.SanitizeExtensions(t.Extensions) @@ -68,19 +55,12 @@ func (t Tag) MarshalJSONTo(enc *jsontext.Encoder) error { // UnmarshalJSON marshal this from JSON func (t *Tag) UnmarshalJSON(data []byte) error { - if internal.UseOptimizedJSONUnmarshaling { - return jsonv2.Unmarshal(data, t) - } - - if err := json.Unmarshal(data, &t.TagProps); err != nil { - return err - } - return json.Unmarshal(data, &t.VendorExtensible) + return jsonv2.Unmarshal(data, t) } func (t *Tag) UnmarshalJSONFrom(dec *jsontext.Decoder) error { var x struct { - Extensions Extensions `json:",inline"` + Extensions Extensions `json:",embed"` TagProps } if err := jsonv2.UnmarshalDecode(dec, &x); err != nil { diff --git a/vendor/modules.txt b/vendor/modules.txt index c632bb005..f6e9abbc6 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -278,10 +278,6 @@ github.com/distribution/reference ## explicit; go 1.13 github.com/dlclark/regexp2 github.com/dlclark/regexp2/syntax -# github.com/emicklei/go-restful/v3 v3.13.0 -## explicit; go 1.13 -github.com/emicklei/go-restful/v3 -github.com/emicklei/go-restful/v3/log # github.com/emirpasic/gods v1.18.1 ## explicit; go 1.2 github.com/emirpasic/gods/containers @@ -395,45 +391,21 @@ github.com/go-openapi/jsonpointer/jsonname ## explicit; go 1.25.0 github.com/go-openapi/jsonreference github.com/go-openapi/jsonreference/internal -# github.com/go-openapi/swag v0.28.0 -## explicit; go 1.25.0 -github.com/go-openapi/swag -# github.com/go-openapi/swag/cmdutils v0.28.0 -## explicit; go 1.25.0 -github.com/go-openapi/swag/cmdutils # github.com/go-openapi/swag/conv v0.28.0 ## explicit; go 1.25.0 github.com/go-openapi/swag/conv -# github.com/go-openapi/swag/fileutils v0.28.0 -## explicit; go 1.25.0 -github.com/go-openapi/swag/fileutils # github.com/go-openapi/swag/jsonutils v0.28.0 ## explicit; go 1.25.0 github.com/go-openapi/swag/jsonutils github.com/go-openapi/swag/jsonutils/adapters github.com/go-openapi/swag/jsonutils/adapters/ifaces github.com/go-openapi/swag/jsonutils/adapters/stdlib/json -# github.com/go-openapi/swag/loading v0.28.0 -## explicit; go 1.25.0 -github.com/go-openapi/swag/loading -# github.com/go-openapi/swag/mangling v0.28.0 -## explicit; go 1.25.0 -github.com/go-openapi/swag/mangling -# github.com/go-openapi/swag/netutils v0.28.0 -## explicit; go 1.25.0 -github.com/go-openapi/swag/netutils # github.com/go-openapi/swag/pools v0.28.0 ## explicit; go 1.25.0 github.com/go-openapi/swag/pools -# github.com/go-openapi/swag/stringutils v0.28.0 -## explicit; go 1.25.0 -github.com/go-openapi/swag/stringutils # github.com/go-openapi/swag/typeutils v0.28.0 ## explicit; go 1.25.0 github.com/go-openapi/swag/typeutils -# github.com/go-openapi/swag/yamlutils v0.28.0 -## explicit; go 1.25.0 -github.com/go-openapi/swag/yamlutils # github.com/go-redis/cache/v9 v9.0.0 ## explicit; go 1.13 github.com/go-redis/cache/v9 @@ -1593,18 +1565,12 @@ k8s.io/klog/v2/textlogger k8s.io/kube-aggregator/pkg/apis/apiregistration k8s.io/kube-aggregator/pkg/apis/apiregistration/v1 k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1 -# k8s.io/kube-openapi v0.0.0-20260721132016-d427ff9ee9ad -## explicit; go 1.25.0 +# k8s.io/kube-openapi v0.0.0-20261014044854-ca3452a79603 +## explicit; go 1.27.0 k8s.io/kube-openapi/pkg/cached k8s.io/kube-openapi/pkg/common k8s.io/kube-openapi/pkg/handler3 k8s.io/kube-openapi/pkg/internal -k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json -k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal -k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonflags -k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonopts -k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/internal/jsonwire -k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/jsontext k8s.io/kube-openapi/pkg/schemaconv k8s.io/kube-openapi/pkg/spec3 k8s.io/kube-openapi/pkg/util @@ -1974,6 +1940,9 @@ sigs.k8s.io/structured-merge-diff/v6/merge sigs.k8s.io/structured-merge-diff/v6/schema sigs.k8s.io/structured-merge-diff/v6/typed sigs.k8s.io/structured-merge-diff/v6/value +# sigs.k8s.io/structured-merge-diff/v7 v7.0.0 +## explicit; go 1.27 +sigs.k8s.io/structured-merge-diff/v7/schema # sigs.k8s.io/yaml v1.6.0 ## explicit; go 1.22 sigs.k8s.io/yaml diff --git a/vendor/github.com/go-openapi/swag/fileutils/LICENSE b/vendor/sigs.k8s.io/structured-merge-diff/v7/LICENSE similarity index 99% rename from vendor/github.com/go-openapi/swag/fileutils/LICENSE rename to vendor/sigs.k8s.io/structured-merge-diff/v7/LICENSE index d64569567..8dada3eda 100644 --- a/vendor/github.com/go-openapi/swag/fileutils/LICENSE +++ b/vendor/sigs.k8s.io/structured-merge-diff/v7/LICENSE @@ -1,4 +1,3 @@ - Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -179,7 +178,7 @@ 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 "[]" + 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 @@ -187,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + 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. diff --git a/vendor/sigs.k8s.io/structured-merge-diff/v7/schema/doc.go b/vendor/sigs.k8s.io/structured-merge-diff/v7/schema/doc.go new file mode 100644 index 000000000..9081ccbc7 --- /dev/null +++ b/vendor/sigs.k8s.io/structured-merge-diff/v7/schema/doc.go @@ -0,0 +1,28 @@ +/* +Copyright 2018 The Kubernetes Authors. + +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 schema defines a targeted schema language which allows one to +// represent all the schema information necessary to perform "structured" +// merges and diffs. +// +// Due to the targeted nature of the data model, the schema language can fit in +// just a few hundred lines of go code, making it much more understandable and +// concise than e.g. OpenAPI. +// +// This schema was derived by observing the API objects used by Kubernetes, and +// formalizing a model which allows certain operations ("apply") to be more +// well defined. It is currently missing one feature: one-of ("unions"). +package schema diff --git a/vendor/sigs.k8s.io/structured-merge-diff/v7/schema/elements.go b/vendor/sigs.k8s.io/structured-merge-diff/v7/schema/elements.go new file mode 100644 index 000000000..4c0e30b25 --- /dev/null +++ b/vendor/sigs.k8s.io/structured-merge-diff/v7/schema/elements.go @@ -0,0 +1,386 @@ +/* +Copyright 2018 The Kubernetes Authors. + +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 schema + +import ( + "sync" + "sync/atomic" +) + +// Schema is a list of named types. +// +// Schema types are indexed in a map before the first search so this type +// should be considered immutable. +type Schema struct { + Types []TypeDef `yaml:"types,omitempty"` + + once sync.Once + m atomic.Pointer[map[string]TypeDef] + + lock sync.Mutex + // Cached results of resolving type references to atoms. Only stores + // type references which require fields of Atom to be overriden. + resolvedTypes map[TypeRef]Atom +} + +// A TypeSpecifier references a particular type in a schema. +type TypeSpecifier struct { + Type TypeRef `yaml:"type,omitempty"` + Schema Schema `yaml:"schema,omitempty"` +} + +// TypeDef represents a named type in a schema. +type TypeDef struct { + // Top level types should be named. Every type must have a unique name. + Name string `yaml:"name,omitempty"` + + Atom `yaml:"atom,omitempty,inline"` +} + +// TypeRef either refers to a named type or declares an inlined type. +type TypeRef struct { + // Either the name or one member of Atom should be set. + NamedType *string `yaml:"namedType,omitempty"` + Inlined Atom `yaml:",inline,omitempty"` + + // If this reference refers to a map-type or list-type, this field overrides + // the `ElementRelationship` of the referred type when resolved. + // If this field is nil, then it has no effect. + // See `Map` and `List` for more information about `ElementRelationship` + ElementRelationship *ElementRelationship `yaml:"elementRelationship,omitempty"` + + // Nullable indicates that an explicit null is a valid value, + // corresponding to OpenAPI's `nullable: true`. + Nullable bool `yaml:"nullable,omitempty"` +} + +// Atom represents the smallest possible pieces of the type system. +// Each set field in the Atom represents a possible type for the object. +// If none of the fields are set, any object will fail validation against the atom. +type Atom struct { + *Scalar `yaml:"scalar,omitempty"` + *List `yaml:"list,omitempty"` + *Map `yaml:"map,omitempty"` +} + +// Scalar (AKA "primitive") represents a type which has a single value which is +// either numeric, string, or boolean, or untyped for any of them. +// +// TODO: split numeric into float/int? Something even more fine-grained? +type Scalar string + +const ( + Numeric = Scalar("numeric") + String = Scalar("string") + Boolean = Scalar("boolean") + Untyped = Scalar("untyped") +) + +// ElementRelationship is an enum of the different possible relationships +// between the elements of container types (maps, lists). +type ElementRelationship string + +const ( + // Associative only applies to lists (see the documentation there). + Associative = ElementRelationship("associative") + // Atomic makes container types (lists, maps) behave + // as scalars / leaf fields + Atomic = ElementRelationship("atomic") + // Separable means the items of the container type have no particular + // relationship (default behavior for maps). + Separable = ElementRelationship("separable") +) + +// Map is a key-value pair. Its default semantics are the same as an +// associative list, but: +// - It is serialized differently: +// map: {"k": {"value": "v"}} +// list: [{"key": "k", "value": "v"}] +// - Keys must be string typed. +// - Keys can't have multiple components. +// +// Optionally, maps may be atomic (for example, imagine representing an RGB +// color value--it doesn't make sense to have different actors own the R and G +// values). +// +// Maps may also represent a type which is composed of a number of different fields. +// Each field has a name and a type. +// +// Fields are indexed in a map before the first search so this type +// should be considered immutable. +type Map struct { + // Each struct field appears exactly once in this list. The order in + // this list defines the canonical field ordering. + Fields []StructField `yaml:"fields,omitempty"` + + // A Union is a grouping of fields with special rules. It may refer to + // one or more fields in the above list. A given field from the above + // list may be referenced in exactly 0 or 1 places in the below list. + // One can have multiple unions in the same struct, but the fields can't + // overlap between unions. + Unions []Union `yaml:"unions,omitempty"` + + // ElementType is the type of the structs's unknown fields. + ElementType TypeRef `yaml:"elementType,omitempty"` + + // ElementRelationship states the relationship between the map's items. + // * `separable` (or unset) implies that each element is 100% independent. + // * `atomic` implies that all elements depend on each other, and this + // is effectively a scalar / leaf field; it doesn't make sense for + // separate actors to set the elements. Example: an RGB color struct; + // it would never make sense to "own" only one component of the + // color. + // The default behavior for maps is `separable`; it's permitted to + // leave this unset to get the default behavior. + ElementRelationship ElementRelationship `yaml:"elementRelationship,omitempty"` + + once sync.Once + m atomic.Pointer[map[string]StructField] +} + +// FindField is a convenience function that returns the referenced StructField, +// if it exists, or (nil, false) if it doesn't. +func (m *Map) FindField(name string) (StructField, bool) { + m.once.Do(func() { + mm := make(map[string]StructField, len(m.Fields)) + for _, field := range m.Fields { + mm[field.Name] = field + } + m.m.Store(&mm) + }) + sf, ok := (*m.m.Load())[name] + return sf, ok +} + +// CopyInto clones this instance of Map into dst +// +// If dst is nil this method does nothing. +// If dst is already initialized, overwrites it with this instance. +// Warning: Not thread safe. Only use dst after this function returns. +func (m *Map) CopyInto(dst *Map) { + if dst == nil { + return + } + + // Map type is considered immutable so sharing references + dst.Fields = m.Fields + dst.ElementType = m.ElementType + dst.Unions = m.Unions + dst.ElementRelationship = m.ElementRelationship + + mm := m.m.Load() + if mm != nil { + // If cache is non-nil then the once token had been consumed. + // Must reset token and use it again to ensure same semantics. + dst.once = sync.Once{} + dst.once.Do(func() { + dst.m.Store(mm) + }) + } +} + +// UnionFields are mapping between the fields that are part of the union and +// their discriminated value. The discriminated value has to be set, and +// should not conflict with other discriminated value in the list. +type UnionField struct { + // FieldName is the name of the field that is part of the union. This + // is the serialized form of the field. + FieldName string `yaml:"fieldName"` + // Discriminatorvalue is the value of the discriminator to + // select that field. If the union doesn't have a discriminator, + // this field is ignored. + DiscriminatorValue string `yaml:"discriminatorValue"` +} + +// Union, or oneof, means that only one of multiple fields of a structure can be +// set at a time. Setting the discriminator helps clearing oher fields: +// - If discriminator changed to non-nil, and a new field has been added +// that doesn't match, an error is returned, +// - If discriminator hasn't changed and two fields or more are set, an +// error is returned, +// - If discriminator changed to non-nil, all other fields but the +// discriminated one will be cleared, +// - Otherwise, If only one field is left, update discriminator to that value. +type Union struct { + // Discriminator, if present, is the name of the field that + // discriminates fields in the union. The mapping between the value of + // the discriminator and the field is done by using the Fields list + // below. + Discriminator *string `yaml:"discriminator,omitempty"` + + // DeduceInvalidDiscriminator indicates if the discriminator + // should be updated automatically based on the fields set. This + // typically defaults to false since we don't want to deduce by + // default (the behavior exists to maintain compatibility on + // existing types and shouldn't be used for new types). + DeduceInvalidDiscriminator bool `yaml:"deduceInvalidDiscriminator,omitempty"` + + // This is the list of fields that belong to this union. All the + // fields present in here have to be part of the parent + // structure. Discriminator (if oneOf has one), is NOT included in + // this list. The value for field is how we map the name of the field + // to actual value for discriminator. + Fields []UnionField `yaml:"fields,omitempty"` +} + +// StructField pairs a field name with a field type. +type StructField struct { + // Name is the field name. + Name string `yaml:"name,omitempty"` + // Type is the field type. + Type TypeRef `yaml:"type,omitempty"` + // Default value for the field, nil if not present. + Default interface{} `yaml:"default,omitempty"` +} + +// List represents a type which contains a zero or more elements, all of the +// same subtype. Lists may be either associative: each element is more or less +// independent and could be managed by separate entities in the system; or +// atomic, where the elements are heavily dependent on each other: it is not +// sensible to change one element without considering the ramifications on all +// the other elements. +type List struct { + // ElementType is the type of the list's elements. + ElementType TypeRef `yaml:"elementType,omitempty"` + + // ElementRelationship states the relationship between the list's elements + // and must have one of these values: + // * `atomic`: the list is treated as a single entity, like a scalar. + // * `associative`: + // - If the list element is a scalar, the list is treated as a set. + // - If the list element is a map, the list is treated as a map. + // There is no default for this value for lists; all schemas must + // explicitly state the element relationship for all lists. + ElementRelationship ElementRelationship `yaml:"elementRelationship,omitempty"` + + // Iff ElementRelationship is `associative`, and the element type is + // map, then Keys must have non-zero length, and it lists the fields + // of the element's map type which are to be used as the keys of the + // list. + // + // TODO: change this to "non-atomic struct" above and make the code reflect this. + // + // Each key must refer to a single field name (no nesting, not JSONPath). + Keys []string `yaml:"keys,omitempty"` +} + +// FindNamedType is a convenience function that returns the referenced TypeDef, +// if it exists, or (nil, false) if it doesn't. +func (s *Schema) FindNamedType(name string) (TypeDef, bool) { + s.once.Do(func() { + sm := make(map[string]TypeDef, len(s.Types)) + for _, t := range s.Types { + sm[t.Name] = t + } + s.m.Store(&sm) + }) + t, ok := (*s.m.Load())[name] + return t, ok +} + +func (s *Schema) resolveNoOverrides(tr TypeRef) (Atom, bool) { + result := Atom{} + + if tr.NamedType != nil { + t, ok := s.FindNamedType(*tr.NamedType) + if !ok { + return Atom{}, false + } + + result = t.Atom + } else { + result = tr.Inlined + } + + return result, true +} + +// Resolve is a convenience function which returns the atom referenced, whether +// it is inline or named. Returns (Atom{}, false) if the type can't be resolved. +// +// This allows callers to not care about the difference between a (possibly +// inlined) reference and a definition. +func (s *Schema) Resolve(tr TypeRef) (Atom, bool) { + // If this is a plain reference with no overrides, just return the type + if tr.ElementRelationship == nil { + return s.resolveNoOverrides(tr) + } + + s.lock.Lock() + defer s.lock.Unlock() + + if s.resolvedTypes == nil { + s.resolvedTypes = make(map[TypeRef]Atom) + } + + var result Atom + var exists bool + + // Return cached result if available + // If not, calculate result and cache it + if result, exists = s.resolvedTypes[tr]; !exists { + if result, exists = s.resolveNoOverrides(tr); exists { + // Allow field-level electives to override the referred type's modifiers + switch { + case result.Map != nil: + mapCopy := Map{} + result.Map.CopyInto(&mapCopy) + mapCopy.ElementRelationship = *tr.ElementRelationship + result.Map = &mapCopy + case result.List != nil: + listCopy := *result.List + listCopy.ElementRelationship = *tr.ElementRelationship + result.List = &listCopy + case result.Scalar != nil: + return Atom{}, false + default: + return Atom{}, false + } + } else { + return Atom{}, false + } + + // Save result. If it is nil, that is also recorded as not existing. + s.resolvedTypes[tr] = result + } + + return result, true +} + +// CopyInto clones this instance of Schema into dst +// +// If dst is nil this method does nothing. +// If dst is already initialized, overwrites it with this instance. +// Warning: Not thread safe. Only use dst after this function returns. +func (s *Schema) CopyInto(dst *Schema) { + if dst == nil { + return + } + + // Schema type is considered immutable so sharing references + dst.Types = s.Types + + sm := s.m.Load() + if sm != nil { + // If cache is non-nil then the once token had been consumed. + // Must reset token and use it again to ensure same semantics. + dst.once = sync.Once{} + dst.once.Do(func() { + dst.m.Store(sm) + }) + } +} diff --git a/vendor/sigs.k8s.io/structured-merge-diff/v7/schema/equals.go b/vendor/sigs.k8s.io/structured-merge-diff/v7/schema/equals.go new file mode 100644 index 000000000..e1fa5c95d --- /dev/null +++ b/vendor/sigs.k8s.io/structured-merge-diff/v7/schema/equals.go @@ -0,0 +1,205 @@ +/* +Copyright 2019 The Kubernetes Authors. + +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 schema + +import "reflect" + +// Equals returns true iff the two Schemas are equal. +func (a *Schema) Equals(b *Schema) bool { + if a == nil || b == nil { + return a == nil && b == nil + } + + if len(a.Types) != len(b.Types) { + return false + } + for i := range a.Types { + if !a.Types[i].Equals(&b.Types[i]) { + return false + } + } + return true +} + +// Equals returns true iff the two TypeRefs are equal. +// +// Note that two typerefs that have an equivalent type but where one is +// inlined and the other is named, are not considered equal. +func (a *TypeRef) Equals(b *TypeRef) bool { + if a == nil || b == nil { + return a == nil && b == nil + } + if (a.NamedType == nil) != (b.NamedType == nil) { + return false + } + if a.NamedType != nil { + if *a.NamedType != *b.NamedType { + return false + } + //return true + } + if a.ElementRelationship != b.ElementRelationship { + return false + } + if a.Nullable != b.Nullable { + return false + } + return a.Inlined.Equals(&b.Inlined) +} + +// Equals returns true iff the two TypeDefs are equal. +func (a *TypeDef) Equals(b *TypeDef) bool { + if a == nil || b == nil { + return a == nil && b == nil + } + if a.Name != b.Name { + return false + } + return a.Atom.Equals(&b.Atom) +} + +// Equals returns true iff the two Atoms are equal. +func (a *Atom) Equals(b *Atom) bool { + if a == nil || b == nil { + return a == nil && b == nil + } + if (a.Scalar == nil) != (b.Scalar == nil) { + return false + } + if (a.List == nil) != (b.List == nil) { + return false + } + if (a.Map == nil) != (b.Map == nil) { + return false + } + switch { + case a.Scalar != nil: + return *a.Scalar == *b.Scalar + case a.List != nil: + return a.List.Equals(b.List) + case a.Map != nil: + return a.Map.Equals(b.Map) + } + return true +} + +// Equals returns true iff the two Maps are equal. +func (a *Map) Equals(b *Map) bool { + if a == nil || b == nil { + return a == nil && b == nil + } + if !a.ElementType.Equals(&b.ElementType) { + return false + } + if a.ElementRelationship != b.ElementRelationship { + return false + } + if len(a.Fields) != len(b.Fields) { + return false + } + for i := range a.Fields { + if !a.Fields[i].Equals(&b.Fields[i]) { + return false + } + } + if len(a.Unions) != len(b.Unions) { + return false + } + for i := range a.Unions { + if !a.Unions[i].Equals(&b.Unions[i]) { + return false + } + } + return true +} + +// Equals returns true iff the two Unions are equal. +func (a *Union) Equals(b *Union) bool { + if a == nil || b == nil { + return a == nil && b == nil + } + if (a.Discriminator == nil) != (b.Discriminator == nil) { + return false + } + if a.Discriminator != nil { + if *a.Discriminator != *b.Discriminator { + return false + } + } + if a.DeduceInvalidDiscriminator != b.DeduceInvalidDiscriminator { + return false + } + if len(a.Fields) != len(b.Fields) { + return false + } + for i := range a.Fields { + if !a.Fields[i].Equals(&b.Fields[i]) { + return false + } + } + return true +} + +// Equals returns true iff the two UnionFields are equal. +func (a *UnionField) Equals(b *UnionField) bool { + if a == nil || b == nil { + return a == nil && b == nil + } + if a.FieldName != b.FieldName { + return false + } + if a.DiscriminatorValue != b.DiscriminatorValue { + return false + } + return true +} + +// Equals returns true iff the two StructFields are equal. +func (a *StructField) Equals(b *StructField) bool { + if a == nil || b == nil { + return a == nil && b == nil + } + if a.Name != b.Name { + return false + } + if !reflect.DeepEqual(a.Default, b.Default) { + return false + } + return a.Type.Equals(&b.Type) +} + +// Equals returns true iff the two Lists are equal. +func (a *List) Equals(b *List) bool { + if a == nil || b == nil { + return a == nil && b == nil + } + if !a.ElementType.Equals(&b.ElementType) { + return false + } + if a.ElementRelationship != b.ElementRelationship { + return false + } + if len(a.Keys) != len(b.Keys) { + return false + } + for i := range a.Keys { + if a.Keys[i] != b.Keys[i] { + return false + } + } + return true +} diff --git a/vendor/sigs.k8s.io/structured-merge-diff/v7/schema/schemaschema.go b/vendor/sigs.k8s.io/structured-merge-diff/v7/schema/schemaschema.go new file mode 100644 index 000000000..4eb367b65 --- /dev/null +++ b/vendor/sigs.k8s.io/structured-merge-diff/v7/schema/schemaschema.go @@ -0,0 +1,168 @@ +/* +Copyright 2018 The Kubernetes Authors. + +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 schema + +// SchemaSchemaYAML is a schema against which you can validate other schemas. +// It will validate itself. It can be unmarshalled into a Schema type. +var SchemaSchemaYAML = `types: +- name: schema + map: + fields: + - name: types + type: + list: + elementRelationship: associative + elementType: + namedType: typeDef + keys: + - name +- name: typeDef + map: + fields: + - name: name + type: + scalar: string + - name: scalar + type: + scalar: string + - name: map + type: + namedType: map + - name: list + type: + namedType: list + - name: untyped + type: + namedType: untyped +- name: typeRef + map: + fields: + - name: namedType + type: + scalar: string + - name: scalar + type: + scalar: string + - name: map + type: + namedType: map + - name: list + type: + namedType: list + - name: untyped + type: + namedType: untyped + - name: elementRelationship + type: + scalar: string + - name: nullable + type: + scalar: boolean +- name: scalar + scalar: string +- name: map + map: + fields: + - name: fields + type: + list: + elementType: + namedType: structField + elementRelationship: associative + keys: [ "name" ] + - name: unions + type: + list: + elementType: + namedType: union + elementRelationship: atomic + - name: elementType + type: + namedType: typeRef + - name: elementRelationship + type: + scalar: string +- name: unionField + map: + fields: + - name: fieldName + type: + scalar: string + - name: discriminatorValue + type: + scalar: string +- name: union + map: + fields: + - name: discriminator + type: + scalar: string + - name: deduceInvalidDiscriminator + type: + scalar: boolean + - name: fields + type: + list: + elementRelationship: associative + elementType: + namedType: unionField + keys: + - fieldName +- name: structField + map: + fields: + - name: name + type: + scalar: string + - name: type + type: + namedType: typeRef + - name: default + type: + namedType: __untyped_atomic_ +- name: list + map: + fields: + - name: elementType + type: + namedType: typeRef + - name: elementRelationship + type: + scalar: string + - name: keys + type: + list: + elementType: + scalar: string + elementRelationship: atomic +- name: untyped + map: + fields: + - name: elementRelationship + type: + scalar: string +- name: __untyped_atomic_ + scalar: untyped + list: + elementType: + namedType: __untyped_atomic_ + elementRelationship: atomic + map: + elementType: + namedType: __untyped_atomic_ + elementRelationship: atomic +`