From 9838cc4840c37935050fc9133fc703612a390d00 Mon Sep 17 00:00:00 2001 From: "red-hat-konflux[bot]" <126015336+red-hat-konflux[bot]@users.noreply.github.com> Date: Tue, 13 Oct 2026 02:39:58 +0000 Subject: [PATCH] Update k8s.io/kube-openapi digest to e2e80c3 Signed-off-by: red-hat-konflux <126015336+red-hat-konflux[bot]@users.noreply.github.com> --- go.mod | 33 +- go.sum | 59 +- .../emicklei/go-restful/v3/.gitignore | 71 - .../emicklei/go-restful/v3/.goconvey | 1 - .../emicklei/go-restful/v3/CHANGES.md | 421 ----- .../github.com/emicklei/go-restful/v3/LICENSE | 22 - .../emicklei/go-restful/v3/Makefile | 8 - .../emicklei/go-restful/v3/README.md | 111 -- .../emicklei/go-restful/v3/SECURITY.md | 13 - .../github.com/emicklei/go-restful/v3/Srcfile | 1 - .../emicklei/go-restful/v3/bench_test.sh | 10 - .../emicklei/go-restful/v3/compress.go | 137 -- .../go-restful/v3/compressor_cache.go | 103 - .../go-restful/v3/compressor_pools.go | 91 - .../emicklei/go-restful/v3/compressors.go | 54 - .../emicklei/go-restful/v3/constants.go | 32 - .../emicklei/go-restful/v3/container.go | 450 ----- .../emicklei/go-restful/v3/cors_filter.go | 193 -- .../emicklei/go-restful/v3/coverage.sh | 2 - .../emicklei/go-restful/v3/curly.go | 225 --- .../emicklei/go-restful/v3/curly_route.go | 54 - .../emicklei/go-restful/v3/custom_verb.go | 59 - .../github.com/emicklei/go-restful/v3/doc.go | 181 -- .../go-restful/v3/entity_accessors.go | 169 -- .../emicklei/go-restful/v3/extensions.go | 21 - .../emicklei/go-restful/v3/filter.go | 37 - .../emicklei/go-restful/v3/filter_adapter.go | 21 - .../emicklei/go-restful/v3/jsr311.go | 313 ---- .../emicklei/go-restful/v3/log/log.go | 34 - .../emicklei/go-restful/v3/logger.go | 32 - .../github.com/emicklei/go-restful/v3/mime.go | 50 - .../emicklei/go-restful/v3/options_filter.go | 34 - .../emicklei/go-restful/v3/parameter.go | 242 --- .../emicklei/go-restful/v3/path_expression.go | 74 - .../emicklei/go-restful/v3/path_processor.go | 74 - .../emicklei/go-restful/v3/request.go | 133 -- .../emicklei/go-restful/v3/response.go | 259 --- .../emicklei/go-restful/v3/route.go | 193 -- .../emicklei/go-restful/v3/route_builder.go | 389 ---- .../emicklei/go-restful/v3/route_reader.go | 66 - .../emicklei/go-restful/v3/router.go | 20 - .../emicklei/go-restful/v3/service_error.go | 32 - .../emicklei/go-restful/v3/web_service.go | 305 --- .../go-restful/v3/web_service_container.go | 39 - .../go-openapi/jsonpointer/.gitignore | 6 +- .../go-openapi/jsonpointer/.golangci.yml | 31 +- .../go-openapi/jsonpointer/CODE_OF_CONDUCT.md | 6 +- .../go-openapi/jsonpointer/CONTRIBUTORS.md | 25 + .../github.com/go-openapi/jsonpointer/LICENSE | 1 - .../github.com/go-openapi/jsonpointer/NOTICE | 39 + .../go-openapi/jsonpointer/README.md | 177 +- .../go-openapi/jsonpointer/SECURITY.md | 37 + .../go-openapi/jsonpointer/errors.go | 50 +- .../go-openapi/jsonpointer/ifaces.go | 50 + .../go-openapi/jsonpointer/jsonname/doc.go | 5 + .../jsonpointer/jsonname/go_name_provider.go | 288 +++ .../go-openapi/jsonpointer/jsonname/ifaces.go | 16 + .../jsonname/name_provider.go | 47 +- .../go-openapi/jsonpointer/options.go | 85 + .../go-openapi/jsonpointer/pointer.go | 636 +++++-- .../{swag => jsonreference}/.editorconfig | 0 .../go-openapi/jsonreference/.gitignore | 6 +- .../go-openapi/jsonreference/.golangci.yml | 28 +- .../jsonreference/CODE_OF_CONDUCT.md | 6 +- .../go-openapi/jsonreference/CONTRIBUTORS.md | 21 + .../go-openapi/jsonreference/NOTICE | 9 +- .../go-openapi/jsonreference/README.md | 117 +- .../go-openapi/jsonreference/SECURITY.md | 37 + .../jsonreference/internal/normalize_url.go | 8 +- .../go-openapi/jsonreference/reference.go | 21 +- .../github.com/go-openapi/swag/.codecov.yml | 4 - .../github.com/go-openapi/swag/.gitattributes | 2 - vendor/github.com/go-openapi/swag/.gitignore | 5 - .../github.com/go-openapi/swag/.golangci.yml | 77 - .../github.com/go-openapi/swag/.mockery.yml | 30 - .../go-openapi/swag/CODE_OF_CONDUCT.md | 74 - vendor/github.com/go-openapi/swag/README.md | 192 -- vendor/github.com/go-openapi/swag/TODO.md | 1 - .../go-openapi/swag/cmdutils/LICENSE | 202 -- .../go-openapi/swag/cmdutils/cmd_utils.go | 24 - .../go-openapi/swag/cmdutils/doc.go | 16 - .../go-openapi/swag/cmdutils_iface.go | 22 - .../go-openapi/swag/conv/convert.go | 15 +- .../go-openapi/swag/conv/convert_types.go | 21 +- vendor/github.com/go-openapi/swag/conv/doc.go | 15 +- .../github.com/go-openapi/swag/conv/format.go | 15 +- .../github.com/go-openapi/swag/conv/sizeof.go | 3 + .../go-openapi/swag/conv/type_constraints.go | 15 +- .../github.com/go-openapi/swag/conv_iface.go | 497 ----- vendor/github.com/go-openapi/swag/doc.go | 58 - .../go-openapi/swag/fileutils/LICENSE | 202 -- .../go-openapi/swag/fileutils/doc.go | 21 - .../go-openapi/swag/fileutils/file.go | 33 - .../go-openapi/swag/fileutils/path.go | 63 - .../go-openapi/swag/fileutils_iface.go | 44 - vendor/github.com/go-openapi/swag/go.work | 20 - vendor/github.com/go-openapi/swag/go.work.sum | 4 - .../go-openapi/swag/jsonname/doc.go | 16 - .../go-openapi/swag/jsonname_iface.go | 35 - .../go-openapi/swag/jsonutils/README.md | 11 +- .../go-openapi/swag/jsonutils/adapters/doc.go | 15 +- .../swag/jsonutils/adapters/ifaces/doc.go | 3 + .../swag/jsonutils/adapters/ifaces/ifaces.go | 3 + .../adapters/ifaces/registry_iface.go | 3 + .../swag/jsonutils/adapters/registry.go | 15 +- .../jsonutils/adapters/stdlib/json/adapter.go | 101 +- .../jsonutils/adapters/stdlib/json/doc.go | 15 +- .../jsonutils/adapters/stdlib/json/lexer.go | 57 +- .../jsonutils/adapters/stdlib/json/options.go | 52 + .../adapters/stdlib/json/ordered_map.go | 64 +- .../jsonutils/adapters/stdlib/json/pool.go | 136 +- .../adapters/stdlib/json/register.go | 33 +- .../jsonutils/adapters/stdlib/json/writer.go | 42 +- .../go-openapi/swag/jsonutils/concat.go | 17 +- .../go-openapi/swag/jsonutils/doc.go | 15 +- .../go-openapi/swag/jsonutils/json.go | 15 +- .../go-openapi/swag/jsonutils/ordered_map.go | 15 +- .../go-openapi/swag/jsonutils_iface.go | 76 - .../go-openapi/swag/loading/LICENSE | 202 -- .../github.com/go-openapi/swag/loading/doc.go | 16 - .../go-openapi/swag/loading/errors.go | 26 - .../go-openapi/swag/loading/json.go | 22 - .../go-openapi/swag/loading/loading.go | 171 -- .../go-openapi/swag/loading/options.go | 136 -- .../go-openapi/swag/loading/yaml.go | 48 - .../go-openapi/swag/loading_iface.go | 102 - .../go-openapi/swag/mangling/BENCHMARK.md | 90 - .../go-openapi/swag/mangling/LICENSE | 202 -- .../go-openapi/swag/mangling/doc.go | 36 - .../swag/mangling/initialism_index.go | 268 --- .../go-openapi/swag/mangling/name_lexem.go | 197 -- .../go-openapi/swag/mangling/name_mangler.go | 381 ---- .../go-openapi/swag/mangling/options.go | 161 -- .../go-openapi/swag/mangling/pools.go | 134 -- .../go-openapi/swag/mangling/split.go | 312 ---- .../go-openapi/swag/mangling/string_bytes.go | 22 - .../go-openapi/swag/mangling/util.go | 129 -- .../go-openapi/swag/mangling_iface.go | 80 - .../go-openapi/swag/netutils/LICENSE | 202 -- .../go-openapi/swag/netutils/doc.go | 16 - .../go-openapi/swag/netutils/net.go | 42 - .../go-openapi/swag/netutils_iface.go | 24 - .../go-openapi/swag/{ => pools}/LICENSE | 0 .../go-openapi/swag/pools/README.md | 1 + .../github.com/go-openapi/swag/pools/debug.go | 17 + .../go-openapi/swag/pools/debug_off.go | 51 + .../go-openapi/swag/pools/debug_on.go | 237 +++ .../github.com/go-openapi/swag/pools/doc.go | 26 + .../github.com/go-openapi/swag/pools/pools.go | 410 ++++ .../go-openapi/swag/stringutils/LICENSE | 202 -- .../swag/stringutils/collection_formats.go | 85 - .../go-openapi/swag/stringutils/doc.go | 16 - .../go-openapi/swag/stringutils/strings.go | 34 - .../go-openapi/swag/stringutils_iface.go | 45 - .../go-openapi/swag/typeutils/doc.go | 15 +- .../go-openapi/swag/typeutils/types.go | 15 +- .../go-openapi/swag/typeutils_iface.go | 23 - .../go-openapi/swag/yamlutils/LICENSE | 202 -- .../go-openapi/swag/yamlutils/doc.go | 24 - .../go-openapi/swag/yamlutils/errors.go | 26 - .../go-openapi/swag/yamlutils/ordered_map.go | 313 ---- .../go-openapi/swag/yamlutils/yaml.go | 222 --- .../go-openapi/swag/yamlutils_iface.go | 31 - .../k8s.io/kube-openapi/pkg/common/common.go | 14 - .../k8s.io/kube-openapi/pkg/internal/flags.go | 25 - .../pkg/internal/serialization.go | 5 +- .../go-json-experiment/json/AUTHORS | 3 - .../go-json-experiment/json/CONTRIBUTORS | 3 - .../go-json-experiment/json/LICENSE | 27 - .../go-json-experiment/json/README.md | 321 ---- .../go-json-experiment/json/arshal.go | 513 ----- .../go-json-experiment/json/arshal_any.go | 238 --- .../go-json-experiment/json/arshal_default.go | 1485 --------------- .../go-json-experiment/json/arshal_funcs.go | 387 ---- .../go-json-experiment/json/arshal_inlined.go | 213 --- .../go-json-experiment/json/arshal_methods.go | 229 --- .../go-json-experiment/json/arshal_time.go | 241 --- .../go-json-experiment/json/decode.go | 1655 ----------------- .../go-json-experiment/json/doc.go | 182 -- .../go-json-experiment/json/encode.go | 1170 ------------ .../go-json-experiment/json/errors.go | 183 -- .../go-json-experiment/json/fields.go | 509 ----- .../go-json-experiment/json/fold.go | 56 - .../go-json-experiment/json/intern.go | 86 - .../go-json-experiment/json/pools.go | 182 -- .../go-json-experiment/json/state.go | 747 -------- .../go-json-experiment/json/token.go | 522 ------ .../go-json-experiment/json/value.go | 381 ---- .../kube-openapi/pkg/schemaconv/openapi.go | 14 +- .../pkg/schemaconv/proto_models.go | 13 +- .../k8s.io/kube-openapi/pkg/schemaconv/smd.go | 2 +- .../k8s.io/kube-openapi/pkg/spec3/encoding.go | 43 +- .../k8s.io/kube-openapi/pkg/spec3/example.go | 51 +- .../pkg/spec3/external_documentation.go | 43 +- .../k8s.io/kube-openapi/pkg/spec3/header.go | 51 +- .../kube-openapi/pkg/spec3/media_type.go | 43 +- .../kube-openapi/pkg/spec3/operation.go | 40 +- .../kube-openapi/pkg/spec3/parameter.go | 52 +- vendor/k8s.io/kube-openapi/pkg/spec3/path.go | 112 +- .../kube-openapi/pkg/spec3/request_body.go | 50 +- .../k8s.io/kube-openapi/pkg/spec3/response.go | 169 +- .../kube-openapi/pkg/spec3/security_scheme.go | 33 +- .../k8s.io/kube-openapi/pkg/spec3/server.go | 82 +- vendor/k8s.io/kube-openapi/pkg/spec3/spec.go | 20 +- .../pkg/validation/spec/header.go | 57 +- .../kube-openapi/pkg/validation/spec/info.go | 38 +- .../kube-openapi/pkg/validation/spec/items.go | 68 +- .../pkg/validation/spec/operation.go | 41 +- .../pkg/validation/spec/parameter.go | 66 +- .../pkg/validation/spec/path_item.go | 49 +- .../kube-openapi/pkg/validation/spec/paths.go | 68 +- .../kube-openapi/pkg/validation/spec/ref.go | 50 - .../pkg/validation/spec/response.go | 54 +- .../pkg/validation/spec/responses.go | 80 +- .../pkg/validation/spec/schema.go | 122 +- .../pkg/validation/spec/security_scheme.go | 29 +- .../pkg/validation/spec/swagger.go | 218 +-- .../kube-openapi/pkg/validation/spec/tag.go | 39 +- vendor/modules.txt | 63 +- .../structured-merge-diff/v7}/LICENSE | 5 +- .../structured-merge-diff/v7/schema/doc.go | 28 + .../v7/schema/elements.go | 386 ++++ .../structured-merge-diff/v7/schema/equals.go | 205 ++ .../v7/schema/schemaschema.go | 168 ++ 224 files changed, 3683 insertions(+), 22394 deletions(-) delete mode 100644 vendor/github.com/emicklei/go-restful/v3/.gitignore delete mode 100644 vendor/github.com/emicklei/go-restful/v3/.goconvey delete mode 100644 vendor/github.com/emicklei/go-restful/v3/CHANGES.md delete mode 100644 vendor/github.com/emicklei/go-restful/v3/LICENSE delete mode 100644 vendor/github.com/emicklei/go-restful/v3/Makefile delete mode 100644 vendor/github.com/emicklei/go-restful/v3/README.md delete mode 100644 vendor/github.com/emicklei/go-restful/v3/SECURITY.md delete mode 100644 vendor/github.com/emicklei/go-restful/v3/Srcfile delete mode 100644 vendor/github.com/emicklei/go-restful/v3/bench_test.sh delete mode 100644 vendor/github.com/emicklei/go-restful/v3/compress.go delete mode 100644 vendor/github.com/emicklei/go-restful/v3/compressor_cache.go delete mode 100644 vendor/github.com/emicklei/go-restful/v3/compressor_pools.go delete mode 100644 vendor/github.com/emicklei/go-restful/v3/compressors.go delete mode 100644 vendor/github.com/emicklei/go-restful/v3/constants.go delete mode 100644 vendor/github.com/emicklei/go-restful/v3/container.go delete mode 100644 vendor/github.com/emicklei/go-restful/v3/cors_filter.go delete mode 100644 vendor/github.com/emicklei/go-restful/v3/coverage.sh delete mode 100644 vendor/github.com/emicklei/go-restful/v3/curly.go delete mode 100644 vendor/github.com/emicklei/go-restful/v3/curly_route.go delete mode 100644 vendor/github.com/emicklei/go-restful/v3/custom_verb.go delete mode 100644 vendor/github.com/emicklei/go-restful/v3/doc.go delete mode 100644 vendor/github.com/emicklei/go-restful/v3/entity_accessors.go delete mode 100644 vendor/github.com/emicklei/go-restful/v3/extensions.go delete mode 100644 vendor/github.com/emicklei/go-restful/v3/filter.go delete mode 100644 vendor/github.com/emicklei/go-restful/v3/filter_adapter.go delete mode 100644 vendor/github.com/emicklei/go-restful/v3/jsr311.go delete mode 100644 vendor/github.com/emicklei/go-restful/v3/log/log.go delete mode 100644 vendor/github.com/emicklei/go-restful/v3/logger.go delete mode 100644 vendor/github.com/emicklei/go-restful/v3/mime.go delete mode 100644 vendor/github.com/emicklei/go-restful/v3/options_filter.go delete mode 100644 vendor/github.com/emicklei/go-restful/v3/parameter.go delete mode 100644 vendor/github.com/emicklei/go-restful/v3/path_expression.go delete mode 100644 vendor/github.com/emicklei/go-restful/v3/path_processor.go delete mode 100644 vendor/github.com/emicklei/go-restful/v3/request.go delete mode 100644 vendor/github.com/emicklei/go-restful/v3/response.go delete mode 100644 vendor/github.com/emicklei/go-restful/v3/route.go delete mode 100644 vendor/github.com/emicklei/go-restful/v3/route_builder.go delete mode 100644 vendor/github.com/emicklei/go-restful/v3/route_reader.go delete mode 100644 vendor/github.com/emicklei/go-restful/v3/router.go delete mode 100644 vendor/github.com/emicklei/go-restful/v3/service_error.go delete mode 100644 vendor/github.com/emicklei/go-restful/v3/web_service.go delete mode 100644 vendor/github.com/emicklei/go-restful/v3/web_service_container.go create mode 100644 vendor/github.com/go-openapi/jsonpointer/CONTRIBUTORS.md create mode 100644 vendor/github.com/go-openapi/jsonpointer/NOTICE create mode 100644 vendor/github.com/go-openapi/jsonpointer/SECURITY.md create mode 100644 vendor/github.com/go-openapi/jsonpointer/ifaces.go create mode 100644 vendor/github.com/go-openapi/jsonpointer/jsonname/doc.go create mode 100644 vendor/github.com/go-openapi/jsonpointer/jsonname/go_name_provider.go create mode 100644 vendor/github.com/go-openapi/jsonpointer/jsonname/ifaces.go rename vendor/github.com/go-openapi/{swag => jsonpointer}/jsonname/name_provider.go (66%) create mode 100644 vendor/github.com/go-openapi/jsonpointer/options.go rename vendor/github.com/go-openapi/{swag => jsonreference}/.editorconfig (100%) create mode 100644 vendor/github.com/go-openapi/jsonreference/CONTRIBUTORS.md create mode 100644 vendor/github.com/go-openapi/jsonreference/SECURITY.md delete mode 100644 vendor/github.com/go-openapi/swag/.codecov.yml delete mode 100644 vendor/github.com/go-openapi/swag/.gitattributes delete mode 100644 vendor/github.com/go-openapi/swag/.gitignore delete mode 100644 vendor/github.com/go-openapi/swag/.golangci.yml delete mode 100644 vendor/github.com/go-openapi/swag/.mockery.yml delete mode 100644 vendor/github.com/go-openapi/swag/CODE_OF_CONDUCT.md delete mode 100644 vendor/github.com/go-openapi/swag/README.md delete mode 100644 vendor/github.com/go-openapi/swag/TODO.md delete mode 100644 vendor/github.com/go-openapi/swag/cmdutils/LICENSE delete mode 100644 vendor/github.com/go-openapi/swag/cmdutils/cmd_utils.go delete mode 100644 vendor/github.com/go-openapi/swag/cmdutils/doc.go delete mode 100644 vendor/github.com/go-openapi/swag/cmdutils_iface.go delete mode 100644 vendor/github.com/go-openapi/swag/conv_iface.go delete mode 100644 vendor/github.com/go-openapi/swag/doc.go delete mode 100644 vendor/github.com/go-openapi/swag/fileutils/LICENSE delete mode 100644 vendor/github.com/go-openapi/swag/fileutils/doc.go delete mode 100644 vendor/github.com/go-openapi/swag/fileutils/file.go delete mode 100644 vendor/github.com/go-openapi/swag/fileutils/path.go delete mode 100644 vendor/github.com/go-openapi/swag/fileutils_iface.go delete mode 100644 vendor/github.com/go-openapi/swag/go.work delete mode 100644 vendor/github.com/go-openapi/swag/go.work.sum delete mode 100644 vendor/github.com/go-openapi/swag/jsonname/doc.go delete mode 100644 vendor/github.com/go-openapi/swag/jsonname_iface.go create mode 100644 vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/options.go delete mode 100644 vendor/github.com/go-openapi/swag/jsonutils_iface.go delete mode 100644 vendor/github.com/go-openapi/swag/loading/LICENSE delete mode 100644 vendor/github.com/go-openapi/swag/loading/doc.go delete mode 100644 vendor/github.com/go-openapi/swag/loading/errors.go delete mode 100644 vendor/github.com/go-openapi/swag/loading/json.go delete mode 100644 vendor/github.com/go-openapi/swag/loading/loading.go delete mode 100644 vendor/github.com/go-openapi/swag/loading/options.go delete mode 100644 vendor/github.com/go-openapi/swag/loading/yaml.go delete mode 100644 vendor/github.com/go-openapi/swag/loading_iface.go delete mode 100644 vendor/github.com/go-openapi/swag/mangling/BENCHMARK.md delete mode 100644 vendor/github.com/go-openapi/swag/mangling/LICENSE delete mode 100644 vendor/github.com/go-openapi/swag/mangling/doc.go delete mode 100644 vendor/github.com/go-openapi/swag/mangling/initialism_index.go delete mode 100644 vendor/github.com/go-openapi/swag/mangling/name_lexem.go delete mode 100644 vendor/github.com/go-openapi/swag/mangling/name_mangler.go delete mode 100644 vendor/github.com/go-openapi/swag/mangling/options.go delete mode 100644 vendor/github.com/go-openapi/swag/mangling/pools.go delete mode 100644 vendor/github.com/go-openapi/swag/mangling/split.go delete mode 100644 vendor/github.com/go-openapi/swag/mangling/string_bytes.go delete mode 100644 vendor/github.com/go-openapi/swag/mangling/util.go delete mode 100644 vendor/github.com/go-openapi/swag/mangling_iface.go delete mode 100644 vendor/github.com/go-openapi/swag/netutils/LICENSE delete mode 100644 vendor/github.com/go-openapi/swag/netutils/doc.go delete mode 100644 vendor/github.com/go-openapi/swag/netutils/net.go delete mode 100644 vendor/github.com/go-openapi/swag/netutils_iface.go rename vendor/github.com/go-openapi/swag/{ => pools}/LICENSE (100%) create mode 100644 vendor/github.com/go-openapi/swag/pools/README.md create mode 100644 vendor/github.com/go-openapi/swag/pools/debug.go create mode 100644 vendor/github.com/go-openapi/swag/pools/debug_off.go create mode 100644 vendor/github.com/go-openapi/swag/pools/debug_on.go create mode 100644 vendor/github.com/go-openapi/swag/pools/doc.go create mode 100644 vendor/github.com/go-openapi/swag/pools/pools.go delete mode 100644 vendor/github.com/go-openapi/swag/stringutils/LICENSE delete mode 100644 vendor/github.com/go-openapi/swag/stringutils/collection_formats.go delete mode 100644 vendor/github.com/go-openapi/swag/stringutils/doc.go delete mode 100644 vendor/github.com/go-openapi/swag/stringutils/strings.go delete mode 100644 vendor/github.com/go-openapi/swag/stringutils_iface.go delete mode 100644 vendor/github.com/go-openapi/swag/typeutils_iface.go delete mode 100644 vendor/github.com/go-openapi/swag/yamlutils/LICENSE delete mode 100644 vendor/github.com/go-openapi/swag/yamlutils/doc.go delete mode 100644 vendor/github.com/go-openapi/swag/yamlutils/errors.go delete mode 100644 vendor/github.com/go-openapi/swag/yamlutils/ordered_map.go delete mode 100644 vendor/github.com/go-openapi/swag/yamlutils/yaml.go delete mode 100644 vendor/github.com/go-openapi/swag/yamlutils_iface.go delete mode 100644 vendor/k8s.io/kube-openapi/pkg/internal/flags.go delete mode 100644 vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/AUTHORS delete mode 100644 vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/CONTRIBUTORS delete mode 100644 vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/LICENSE delete mode 100644 vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/README.md delete mode 100644 vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/arshal.go delete mode 100644 vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/arshal_any.go delete mode 100644 vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/arshal_default.go delete mode 100644 vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/arshal_funcs.go delete mode 100644 vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/arshal_inlined.go delete mode 100644 vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/arshal_methods.go delete mode 100644 vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/arshal_time.go delete mode 100644 vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/decode.go delete mode 100644 vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/doc.go delete mode 100644 vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/encode.go delete mode 100644 vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/errors.go delete mode 100644 vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/fields.go delete mode 100644 vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/fold.go delete mode 100644 vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/intern.go delete mode 100644 vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/pools.go delete mode 100644 vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/state.go delete mode 100644 vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/token.go delete mode 100644 vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/value.go rename vendor/{github.com/go-openapi/swag/jsonname => sigs.k8s.io/structured-merge-diff/v7}/LICENSE (99%) create mode 100644 vendor/sigs.k8s.io/structured-merge-diff/v7/schema/doc.go create mode 100644 vendor/sigs.k8s.io/structured-merge-diff/v7/schema/elements.go create mode 100644 vendor/sigs.k8s.io/structured-merge-diff/v7/schema/equals.go create mode 100644 vendor/sigs.k8s.io/structured-merge-diff/v7/schema/schemaschema.go diff --git a/go.mod b/go.mod index 1ab9f4a0c..8ac1cc3a8 100644 --- a/go.mod +++ b/go.mod @@ -1,11 +1,13 @@ module github.com/hybrid-cloud-patterns/patterns-operator -go 1.25.5 +go 1.27.0 require ( code.gitea.io/sdk/gitea v0.23.2 + dario.cat/mergo v1.0.2 github.com/Masterminds/semver/v3 v3.5.0 github.com/argoproj-labs/argocd-operator v0.17.0 + github.com/argoproj/argo-cd/v3 v3.3.15 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.2 @@ -26,11 +28,6 @@ require ( k8s.io/apimachinery v0.36.0-alpha.1 k8s.io/client-go v12.0.0+incompatible sigs.k8s.io/controller-runtime v0.21.0 -) - -require ( - dario.cat/mergo v1.0.2 - github.com/argoproj/argo-cd/v3 v3.3.15 sigs.k8s.io/controller-runtime/tools/setup-envtest v0.0.0-20250308055145-5fe7bb3edc86 sigs.k8s.io/controller-tools v0.16.4 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 @@ -83,20 +79,12 @@ require ( github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect github.com/go-git/go-billy/v5 v5.9.1 // indirect github.com/go-logr/zapr v1.3.0 // indirect - github.com/go-openapi/jsonpointer v0.22.1 // indirect - github.com/go-openapi/jsonreference v0.21.3 // indirect - github.com/go-openapi/swag v0.25.1 // indirect - github.com/go-openapi/swag/cmdutils v0.25.1 // indirect - github.com/go-openapi/swag/conv v0.25.1 // indirect - github.com/go-openapi/swag/fileutils v0.25.1 // indirect - github.com/go-openapi/swag/jsonname v0.25.1 // indirect - github.com/go-openapi/swag/jsonutils v0.25.1 // indirect - github.com/go-openapi/swag/loading v0.25.1 // indirect - github.com/go-openapi/swag/mangling v0.25.1 // indirect - github.com/go-openapi/swag/netutils v0.25.1 // indirect - github.com/go-openapi/swag/stringutils v0.25.1 // indirect - github.com/go-openapi/swag/typeutils v0.25.1 // indirect - github.com/go-openapi/swag/yamlutils v0.25.1 // indirect + github.com/go-openapi/jsonpointer v1.0.0 // indirect + github.com/go-openapi/jsonreference v1.0.0 // indirect + github.com/go-openapi/swag/conv v0.27.1 // indirect + github.com/go-openapi/swag/jsonutils v0.27.1 // indirect + github.com/go-openapi/swag/pools v0.27.1 // indirect + github.com/go-openapi/swag/typeutils v0.27.1 // 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 @@ -201,7 +189,7 @@ require ( k8s.io/controller-manager v0.34.0 // indirect k8s.io/klog/v2 v2.140.0 // indirect k8s.io/kube-aggregator v0.34.0 // indirect - k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 // indirect + k8s.io/kube-openapi v0.0.0-20261007072838-e2e80c32a35f // indirect k8s.io/kubectl v0.35.1 // indirect k8s.io/kubernetes v1.34.2 // indirect k8s.io/utils v0.0.0-20260707023825-cf1189d6abe3 // indirect @@ -211,6 +199,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 525cf4b7b..1fabf811a 100644 --- a/go.sum +++ b/go.sum @@ -111,8 +111,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= @@ -162,38 +160,25 @@ github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= -github.com/go-openapi/jsonpointer v0.22.1 h1:sHYI1He3b9NqJ4wXLoJDKmUmHkWy/L7rtEo92JUxBNk= -github.com/go-openapi/jsonpointer v0.22.1/go.mod h1:pQT9OsLkfz1yWoMgYFy4x3U5GY5nUlsOn1qSBH5MkCM= -github.com/go-openapi/jsonreference v0.21.3 h1:96Dn+MRPa0nYAR8DR1E03SblB5FJvh7W6krPI0Z7qMc= -github.com/go-openapi/jsonreference v0.21.3/go.mod h1:RqkUP0MrLf37HqxZxrIAtTWW4ZJIK1VzduhXYBEeGc4= -github.com/go-openapi/swag v0.25.1 h1:6uwVsx+/OuvFVPqfQmOOPsqTcm5/GkBhNwLqIR916n8= -github.com/go-openapi/swag v0.25.1/go.mod h1:bzONdGlT0fkStgGPd3bhZf1MnuPkf2YAys6h+jZipOo= -github.com/go-openapi/swag/cmdutils v0.25.1 h1:nDke3nAFDArAa631aitksFGj2omusks88GF1VwdYqPY= -github.com/go-openapi/swag/cmdutils v0.25.1/go.mod h1:pdae/AFo6WxLl5L0rq87eRzVPm/XRHM3MoYgRMvG4A0= -github.com/go-openapi/swag/conv v0.25.1 h1:+9o8YUg6QuqqBM5X6rYL/p1dpWeZRhoIt9x7CCP+he0= -github.com/go-openapi/swag/conv v0.25.1/go.mod h1:Z1mFEGPfyIKPu0806khI3zF+/EUXde+fdeksUl2NiDs= -github.com/go-openapi/swag/fileutils v0.25.1 h1:rSRXapjQequt7kqalKXdcpIegIShhTPXx7yw0kek2uU= -github.com/go-openapi/swag/fileutils v0.25.1/go.mod h1:+NXtt5xNZZqmpIpjqcujqojGFek9/w55b3ecmOdtg8M= -github.com/go-openapi/swag/jsonname v0.25.1 h1:Sgx+qbwa4ej6AomWC6pEfXrA6uP2RkaNjA9BR8a1RJU= -github.com/go-openapi/swag/jsonname v0.25.1/go.mod h1:71Tekow6UOLBD3wS7XhdT98g5J5GR13NOTQ9/6Q11Zo= -github.com/go-openapi/swag/jsonutils v0.25.1 h1:AihLHaD0brrkJoMqEZOBNzTLnk81Kg9cWr+SPtxtgl8= -github.com/go-openapi/swag/jsonutils v0.25.1/go.mod h1:JpEkAjxQXpiaHmRO04N1zE4qbUEg3b7Udll7AMGTNOo= -github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.1 h1:DSQGcdB6G0N9c/KhtpYc71PzzGEIc/fZ1no35x4/XBY= -github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.1/go.mod h1:kjmweouyPwRUEYMSrbAidoLMGeJ5p6zdHi9BgZiqmsg= -github.com/go-openapi/swag/loading v0.25.1 h1:6OruqzjWoJyanZOim58iG2vj934TysYVptyaoXS24kw= -github.com/go-openapi/swag/loading v0.25.1/go.mod h1:xoIe2EG32NOYYbqxvXgPzne989bWvSNoWoyQVWEZicc= -github.com/go-openapi/swag/mangling v0.25.1 h1:XzILnLzhZPZNtmxKaz/2xIGPQsBsvmCjrJOWGNz/ync= -github.com/go-openapi/swag/mangling v0.25.1/go.mod h1:CdiMQ6pnfAgyQGSOIYnZkXvqhnnwOn997uXZMAd/7mQ= -github.com/go-openapi/swag/netutils v0.25.1 h1:2wFLYahe40tDUHfKT1GRC4rfa5T1B4GWZ+msEFA4Fl4= -github.com/go-openapi/swag/netutils v0.25.1/go.mod h1:CAkkvqnUJX8NV96tNhEQvKz8SQo2KF0f7LleiJwIeRE= -github.com/go-openapi/swag/stringutils v0.25.1 h1:Xasqgjvk30eUe8VKdmyzKtjkVjeiXx1Iz0zDfMNpPbw= -github.com/go-openapi/swag/stringutils v0.25.1/go.mod h1:JLdSAq5169HaiDUbTvArA2yQxmgn4D6h4A+4HqVvAYg= -github.com/go-openapi/swag/typeutils v0.25.1 h1:rD/9HsEQieewNt6/k+JBwkxuAHktFtH3I3ysiFZqukA= -github.com/go-openapi/swag/typeutils v0.25.1/go.mod h1:9McMC/oCdS4BKwk2shEB7x17P6HmMmA6dQRtAkSnNb8= -github.com/go-openapi/swag/yamlutils v0.25.1 h1:mry5ez8joJwzvMbaTGLhw8pXUnhDK91oSJLDPF1bmGk= -github.com/go-openapi/swag/yamlutils v0.25.1/go.mod h1:cm9ywbzncy3y6uPm/97ysW8+wZ09qsks+9RS8fLWKqg= -github.com/go-openapi/testify/v2 v2.0.2 h1:X999g3jeLcoY8qctY/c/Z8iBHTbwLz7R2WXd6Ub6wls= -github.com/go-openapi/testify/v2 v2.0.2/go.mod h1:HCPmvFFnheKK2BuwSA0TbbdxJ3I16pjwMkYkP4Ywn54= +github.com/go-openapi/jsonpointer v1.0.0 h1:kR9tHqY0CtZaOPVFm622dPVNhrvYpwr4uCxgL3h1H8s= +github.com/go-openapi/jsonpointer v1.0.0/go.mod h1:Z3rw7dWu1p9IgitXCFamSlA5lmDiklEB6vkaxcNZW5Y= +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.23.1 h1:lpsStH0n2ittzTnbaSloVZLuB5+fvSY/+hnagBjSNZU= +github.com/go-openapi/swag/conv v0.27.1 h1:8wi9ZG+olmY1wXphl93EWniPtbSPkXM/feH7FgjsvrU= +github.com/go-openapi/swag/conv v0.27.1/go.mod h1:QbqMivkpKhC3g1B1GGGOJ6ANewI3S62dbzYu3Duowqs= +github.com/go-openapi/swag/jsonutils v0.27.1 h1:SVgK3i4USzCU5mibOOS/l4ea2h9UQXy7J7RNLTjuXjU= +github.com/go-openapi/swag/jsonutils v0.27.1/go.mod h1:tdlEpZqdcQ17uj6J4YdK9vd8It5qWMwjWXOs0tjpRlk= +github.com/go-openapi/swag/jsonutils/fixtures_test v0.27.1 h1:mJu3COL9WEaZVp/Kf2PRMi7tPszPEJfSr/OO75ynCs8= +github.com/go-openapi/swag/jsonutils/fixtures_test v0.27.1/go.mod h1:mofwUWx70wvskwESqRJ//k/9kURmCgyJl5m5Ppoh5kY= +github.com/go-openapi/swag/pools v0.27.1 h1:9LeadcMyb2GJCbXX5hVQDbZ2Lq9TL4dCs/nx1j5DO0E= +github.com/go-openapi/swag/pools v0.27.1/go.mod h1:kVQefhSK5RWuRe7BXsL8htgBPAMpN7HDGpGEknqugeE= +github.com/go-openapi/swag/typeutils v0.27.1 h1:KSTdFlfnse4r6dP9IrEnwMldjE+zs71UeEB3//PtVXc= +github.com/go-openapi/swag/typeutils v0.27.1/go.mod h1:Srm0xFNRZ1Y+vCxJclo5qzx8aj+1pAKda/YfFPrG0dQ= +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= +github.com/go-openapi/testify/v2 v2.6.0/go.mod h1:SgsVHtfooshd0tublTtJ50FPKhujf47YRqauXXOUxfw= github.com/go-playground/webhooks/v6 v6.4.0 h1:KLa6y7bD19N48rxJDHM0DpE3T4grV7GxMy1b/aHMWPY= github.com/go-playground/webhooks/v6 v6.4.0/go.mod h1:5lBxopx+cAJiBI4+kyRbuHrEi+hYRDdRHuRR4Ya5Ums= github.com/go-redis/cache/v9 v9.0.0 h1:0thdtFo0xJi0/WXbRVu8B066z8OvVymXTJGaXrVWnN0= @@ -696,8 +681,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.34.2 h1:Nn0Vksj67WHBL2x7bJ6vuxL44RbMTK6uRtXX+3vMVJk= k8s.io/kube-aggregator v0.34.2/go.mod h1:/tp4cc/1p2AvICsS4mjjSJakdrbhcGbRmj0mdHTdR2Q= -k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 h1:Y3gxNAuB0OBLImH611+UDZcmKS3g6CthxToOb37KgwE= -k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912/go.mod h1:kdmbQkyfwUagLfXIad1y2TdrjPFWp2Q89B3qkRwf/pQ= +k8s.io/kube-openapi v0.0.0-20261007072838-e2e80c32a35f h1:1auvWgWzQ2cfjBZfDMk9Zmuf/LCr9gUQBRaXBmQjRHI= +k8s.io/kube-openapi v0.0.0-20261007072838-e2e80c32a35f/go.mod h1:ijAJHxCK/9OftZdcKwI5BHyIeRUeoKe1ldIyM4JHMts= k8s.io/kubectl v0.34.2 h1:+fWGrVlDONMUmmQLDaGkQ9i91oszjjRAa94cr37hzqA= k8s.io/kubectl v0.34.2/go.mod h1:X2KTOdtZZNrTWmUD4oHApJ836pevSl+zvC5sI6oO2YQ= k8s.io/kubernetes v1.34.2 h1:WQdDvYJazkmkwSncgNwGvVtaCt4TYXIU3wSMRgvp3MI= @@ -722,5 +707,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/jsonpointer/.gitignore b/vendor/github.com/go-openapi/jsonpointer/.gitignore index 769c24400..d8f4186fe 100644 --- a/vendor/github.com/go-openapi/jsonpointer/.gitignore +++ b/vendor/github.com/go-openapi/jsonpointer/.gitignore @@ -1 +1,5 @@ -secrets.yml +*.out +*.cov +.idea +.env +.mcp.json diff --git a/vendor/github.com/go-openapi/jsonpointer/.golangci.yml b/vendor/github.com/go-openapi/jsonpointer/.golangci.yml index 7cea1af8b..9d2733176 100644 --- a/vendor/github.com/go-openapi/jsonpointer/.golangci.yml +++ b/vendor/github.com/go-openapi/jsonpointer/.golangci.yml @@ -2,25 +2,13 @@ version: "2" linters: default: all disable: - - cyclop - depguard - - errchkjson - - errorlint - - exhaustruct - - forcetypeassert - funlen - - gochecknoglobals - - gochecknoinits - - gocognit - - godot + - goconst - godox - - gosmopolitan - - inamedparam - #- intrange # disabled while < go1.22 - - ireturn - - lll - - musttag - - nestif + - gomodguard + - gomodguard_v2 + - exhaustruct - nlreturn - nonamedreturns - noinlineerr @@ -29,7 +17,6 @@ linters: - testpackage - thelper - tparallel - - unparam - varnamelen - whitespace - wrapcheck @@ -41,8 +28,15 @@ linters: goconst: min-len: 2 min-occurrences: 3 + cyclop: + max-complexity: 20 gocyclo: - min-complexity: 45 + min-complexity: 20 + exhaustive: + default-signifies-exhaustive: true + default-case-required: true + lll: + line-length: 180 exclusions: generated: lax presets: @@ -58,6 +52,7 @@ formatters: enable: - gofmt - goimports + - gofumpt exclusions: generated: lax paths: diff --git a/vendor/github.com/go-openapi/jsonpointer/CODE_OF_CONDUCT.md b/vendor/github.com/go-openapi/jsonpointer/CODE_OF_CONDUCT.md index 9322b065e..bac878f21 100644 --- a/vendor/github.com/go-openapi/jsonpointer/CODE_OF_CONDUCT.md +++ b/vendor/github.com/go-openapi/jsonpointer/CODE_OF_CONDUCT.md @@ -23,7 +23,9 @@ include: 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 @@ -55,7 +57,7 @@ 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 ivan+abuse@flanders.co.nz. All +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. @@ -68,7 +70,7 @@ members of the project's leadership. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, -available at [http://contributor-covenant.org/version/1/4][version] +available at [][version] [homepage]: http://contributor-covenant.org [version]: http://contributor-covenant.org/version/1/4/ diff --git a/vendor/github.com/go-openapi/jsonpointer/CONTRIBUTORS.md b/vendor/github.com/go-openapi/jsonpointer/CONTRIBUTORS.md new file mode 100644 index 000000000..de0bf5c04 --- /dev/null +++ b/vendor/github.com/go-openapi/jsonpointer/CONTRIBUTORS.md @@ -0,0 +1,25 @@ +# Contributors + +- Repository: ['go-openapi/jsonpointer'] + +| Total Contributors | Total Contributions | +| --- | --- | +| 13 | 132 | + +| Username | All Time Contribution Count | All Commits | +| --- | --- | --- | +| @fredbi | 83 | | +| @casualjim | 33 | | +| @magodo | 3 | | +| @youyuanwu | 3 | | +| @alexandear | 2 | | +| @gaiaz-iusipov | 1 | | +| @gbjk | 1 | | +| @gordallott | 1 | | +| @ianlancetaylor | 1 | | +| @mfleader | 1 | | +| @Neo2308 | 1 | | +| @olivierlemasle | 1 | | +| @testwill | 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/jsonpointer/LICENSE b/vendor/github.com/go-openapi/jsonpointer/LICENSE index d64569567..261eeb9e9 100644 --- a/vendor/github.com/go-openapi/jsonpointer/LICENSE +++ b/vendor/github.com/go-openapi/jsonpointer/LICENSE @@ -1,4 +1,3 @@ - Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ diff --git a/vendor/github.com/go-openapi/jsonpointer/NOTICE b/vendor/github.com/go-openapi/jsonpointer/NOTICE new file mode 100644 index 000000000..201908d2f --- /dev/null +++ b/vendor/github.com/go-openapi/jsonpointer/NOTICE @@ -0,0 +1,39 @@ +Copyright 2015-2025 go-swagger maintainers + +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +This software library, github.com/go-openapi/jsonpointer, includes software developed +by the go-swagger and go-openapi maintainers ("go-swagger maintainers"). + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this software except in compliance with the License. + +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0. + +This software is copied from, derived from, and inspired by other original software products. +It ships with copies of other software which license terms are recalled below. + +The original software was authored on 25-02-2013 by sigu-399 (https://github.com/sigu-399, sigu.399@gmail.com). + +github.com/sigu-399/jsonpointer +=========================== + +// SPDX-FileCopyrightText: Copyright 2013 sigu-399 ( https://github.com/sigu-399 ) +// SPDX-License-Identifier: Apache-2.0 + +Copyright 2013 sigu-399 ( https://github.com/sigu-399 ) + +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/jsonpointer/README.md b/vendor/github.com/go-openapi/jsonpointer/README.md index 45bd31b14..6e7929c64 100644 --- a/vendor/github.com/go-openapi/jsonpointer/README.md +++ b/vendor/github.com/go-openapi/jsonpointer/README.md @@ -1,26 +1,177 @@ -# gojsonpointer [![Build Status](https://github.com/go-openapi/jsonpointer/actions/workflows/go-test.yml/badge.svg)](https://github.com/go-openapi/jsonpointer/actions?query=workflow%3A"go+test") [![codecov](https://codecov.io/gh/go-openapi/jsonpointer/branch/master/graph/badge.svg)](https://codecov.io/gh/go-openapi/jsonpointer) +# jsonpointer -[![Slack Status](https://slackin.goswagger.io/badge.svg)](https://slackin.goswagger.io) -[![license](http://img.shields.io/badge/license-Apache%20v2-orange.svg)](https://raw.githubusercontent.com/go-openapi/jsonpointer/master/LICENSE) -[![Go Reference](https://pkg.go.dev/badge/github.com/go-openapi/jsonpointer.svg)](https://pkg.go.dev/github.com/go-openapi/jsonpointer) -[![Go Report Card](https://goreportcard.com/badge/github.com/go-openapi/jsonpointer)](https://goreportcard.com/report/github.com/go-openapi/jsonpointer) + +[![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] -An implementation of JSON Pointer - Go language +--- + +An implementation of JSON Pointer for golang, which supports go `struct`. + +## Announcements + +* **2026-07-07** : landing v1.0.0 + * stable API pledge + +* **2026-06-29** : reinsourced external dependency to swag (v0.24.0) + * module `github.com/go-openapi/swag/jsonname` is source directly here, so we no longer have any external dependency + * `jsonname` was never really used by any other package, so it makes sense to deprecate it away from the `swag` family + and retrofit its functionality here. `jsonpointer` no longer get external dependencies, besides test dependencies. + +* **2026-04-15** : added support for trailing "-" for arrays (v0.23.0) + * this brings full support of [RFC6901][RFC6901] + * this is supported for types relying on the reflection-based implemented + * API semantics remain essentially unaltered. Exception: `Pointer.Set(document any,value any) (document any, err error)` + can only perform a best-effort to mutate the input document in place. In the case of adding elements to an array with a + trailing "-", either pass a mutable array (`*[]T`) as the input document, or use the returned updated document instead. + * types that implement the `JSONSetable` interface may not implement the mutation implied by the trailing "-" + +* **2026-04-15** : added support for optional alternate JSON name providers + * for struct support the defaults might not suit all situations: there are known limitations + when it comes to handle untagged fields or embedded types. + * the default name provider in use is not fully aligned with go JSON stdlib + * exposed an option (or global setting) to change the provider that resolves a struct into json keys + * the default behavior is not altered ## Status -Completed YES -Tested YES +API is stable and feature-complete. + +The project continues to receive regular updates, bug fixes and hygiene maintenance (CI, linting, etc). + +## Import this library in your project + +```cmd +go get github.com/go-openapi/jsonpointer +``` + +## Basic usage + +See also some [examples](./examples_test.go) + +### Retrieving a value + +```go + import ( + "github.com/go-openapi/jsonpointer" + ) + + + var doc any + + ... + + pointer, err := jsonpointer.New("/foo/1") + if err != nil { + ... // error: e.g. invalid JSON pointer specification + } + + value, kind, err := pointer.Get(doc) + if err != nil { + ... // error: e.g. key not found, index out of bounds, etc. + } + + ... +``` + +### Setting a value + +```go + ... + var doc any + ... + pointer, err := jsonpointer.New("/foo/1") + if err != nil { + ... // error: e.g. invalid JSON pointer specification + } + + doc, err = p.Set(doc, "value") + if err != nil { + ... // error: e.g. key not found, index out of bounds, etc. + } +``` + +## Change log + +See ## References -also known as [RFC6901](https://www.rfc-editor.org/rfc/rfc6901) +also known as [RFC6901][RFC6901]. + +## Licensing + +This library ships under the [SPDX-License-Identifier: Apache-2.0](./LICENSE). + +See the license [NOTICE](./NOTICE), which recalls the licensing terms of all the pieces of software +on top of which it has been built. + +## Limitations + +* [RFC6901][RFC6901] is now fully supported, including trailing "-" semantics for arrays (for `Set` operations). +* Default behavior: JSON name detection in go `struct`s + - Unlike go standard marshaling, untagged fields do not default to the go field name and are ignored. + - anonymous fields are not traversed if untagged + - the above limitations may be overcome by calling `UseGoNameProvider()` at initialization time. + - alternatively, users may inject the desired custom behavior for naming fields as an option. + +## 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: -### Note +* running [this workflow](https://github.com/go-openapi/jsonpointer/actions/workflows/bump-release.yml) +* or pushing a semver tag + * signed tags are preferred + * The tag message is prepended to release notes -The 4.Evaluation part of the previous reference, starting with 'If the currently referenced value is a JSON array, the reference token MUST contain either...' is not implemented. + +[test-badge]: https://github.com/go-openapi/jsonpointer/actions/workflows/go-test.yml/badge.svg +[test-url]: https://github.com/go-openapi/jsonpointer/actions/workflows/go-test.yml +[cov-badge]: https://codecov.io/gh/go-openapi/jsonpointer/branch/master/graph/badge.svg +[cov-url]: https://codecov.io/gh/go-openapi/jsonpointer +[vuln-scan-badge]: https://github.com/go-openapi/jsonpointer/actions/workflows/scanner.yml/badge.svg +[vuln-scan-url]: https://github.com/go-openapi/jsonpointer/actions/workflows/scanner.yml +[codeql-badge]: https://github.com/go-openapi/jsonpointer/actions/workflows/codeql.yml/badge.svg +[codeql-url]: https://github.com/go-openapi/jsonpointer/actions/workflows/codeql.yml + +[release-badge]: https://badge.fury.io/gh/go-openapi%2Fjsonpointer.svg +[release-url]: https://badge.fury.io/gh/go-openapi%2Fjsonpointer + +[gocard-badge]: https://goreportcard.com/badge/github.com/go-openapi/jsonpointer +[gocard-url]: https://goreportcard.com/report/github.com/go-openapi/jsonpointer +[codefactor-badge]: https://img.shields.io/codefactor/grade/github/go-openapi/jsonpointer +[codefactor-url]: https://www.codefactor.io/repository/github/go-openapi/jsonpointer + +[godoc-badge]: https://pkg.go.dev/badge/github.com/go-openapi/jsonpointer +[godoc-url]: http://pkg.go.dev/github.com/go-openapi/jsonpointer +[discord-badge]: https://img.shields.io/discord/1446918742398341256?logo=discord&label=discord&color=blue +[discord-url]: https://discord.gg/FfnFYaC3k5 -That is because our implementation of the JSON pointer only supports explicit references to array elements: the provision in the spec -to resolve non-existent members as "the last element in the array", using the special trailing character "-". + +[license-badge]: http://img.shields.io/badge/license-Apache%20v2-orange.svg +[license-url]: https://github.com/go-openapi/jsonpointer/?tab=Apache-2.0-1-ov-file#readme + +[goversion-badge]: https://img.shields.io/github/go-mod/go-version/go-openapi/jsonpointer +[goversion-url]: https://github.com/go-openapi/jsonpointer/blob/master/go.mod +[top-badge]: https://img.shields.io/github/languages/top/go-openapi/jsonpointer +[commits-badge]: https://img.shields.io/github/commits-since/go-openapi/jsonpointer/latest +[RFC6901]: https://www.rfc-editor.org/rfc/rfc6901 + +[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/jsonpointer/SECURITY.md b/vendor/github.com/go-openapi/jsonpointer/SECURITY.md new file mode 100644 index 000000000..1fea2c573 --- /dev/null +++ b/vendor/github.com/go-openapi/jsonpointer/SECURITY.md @@ -0,0 +1,37 @@ +# 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/jsonpointer/errors.go b/vendor/github.com/go-openapi/jsonpointer/errors.go index b84343d9d..2ae6e3cfb 100644 --- a/vendor/github.com/go-openapi/jsonpointer/errors.go +++ b/vendor/github.com/go-openapi/jsonpointer/errors.go @@ -1,5 +1,10 @@ +// SPDX-FileCopyrightText: Copyright (c) 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + package jsonpointer +import "fmt" + type pointerError string func (e pointerError) Error() string { @@ -7,12 +12,49 @@ func (e pointerError) Error() string { } const ( - // ErrPointer is an error raised by the jsonpointer package + // ErrPointer is a sentinel error raised by all errors from this package. ErrPointer pointerError = "JSON pointer error" - // ErrInvalidStart states that a JSON pointer must start with a separator ("/") - ErrInvalidStart pointerError = `JSON pointer must be empty or start with a "` + pointerSeparator + // ErrInvalidStart states that a JSON pointer must start with a separator ("/"). + ErrInvalidStart pointerError = `JSON pointer must be empty or start with a "` + pointerSeparator + `"` - // ErrUnsupportedValueType indicates that a value of the wrong type is being set + // ErrUnsupportedValueType indicates that a value of the wrong type is being set. ErrUnsupportedValueType pointerError = "only structs, pointers, maps and slices are supported for setting values" + + // ErrDashToken indicates use of the RFC 6901 "-" reference token in a context where it cannot be + // resolved. + // + // Per RFC 6901 §4 the "-" token refers to the (nonexistent) element after the last array element. + // It may only be used as the terminal token of a [Pointer.Set] against a slice, where it means + // "append". + // + // Any other use (get, offset, intermediate traversal, non-slice target) is an error condition that + // wraps this sentinel. + ErrDashToken pointerError = `the "-" array token cannot be resolved here` //nolint:gosec // G101 false positive: this is a JSON Pointer reference token, not a credential. ) + +const dashToken = "-" + +func errNoKey(key string) error { + return fmt.Errorf("object has no key %q: %w", key, ErrPointer) +} + +func errOutOfBounds(length, idx int) error { + return fmt.Errorf("index out of bounds array[0,%d] index '%d': %w", length-1, idx, ErrPointer) +} + +func errInvalidReference(token string) error { + return fmt.Errorf("invalid token reference %q: %w", token, ErrPointer) +} + +func errDashOnGet() error { + return fmt.Errorf("cannot resolve %q token on get: %w: %w", dashToken, ErrDashToken, ErrPointer) +} + +func errDashIntermediate() error { + return fmt.Errorf("the %q token may only appear as the terminal token of a pointer: %w: %w", dashToken, ErrDashToken, ErrPointer) +} + +func errDashOnOffset() error { + return fmt.Errorf("cannot compute offset for %q token (nonexistent element): %w: %w", dashToken, ErrDashToken, ErrPointer) +} diff --git a/vendor/github.com/go-openapi/jsonpointer/ifaces.go b/vendor/github.com/go-openapi/jsonpointer/ifaces.go new file mode 100644 index 000000000..31359c48f --- /dev/null +++ b/vendor/github.com/go-openapi/jsonpointer/ifaces.go @@ -0,0 +1,50 @@ +// SPDX-FileCopyrightText: Copyright (c) 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package jsonpointer + +import "reflect" + +// JSONPointable is an interface for structs to implement, when they need to customize the json +// pointer process or want to avoid the use of reflection. +type JSONPointable interface { + // JSONLookup returns a value pointed at this (unescaped) key. + JSONLookup(key string) (any, error) +} + +// JSONSetable is an interface for structs to implement, when they need to customize the json +// pointer process or want to avoid the use of reflection. +// +// # Handling of the RFC 6901 "-" token +// +// When a type implementing JSONSetable is the terminal parent of a [Pointer.Set] call, the library +// passes the raw reference token to JSONSet without interpretation. +// +// In particular, the RFC 6901 "-" token (which conventionally means "append" for arrays, per RFC +// 6902) is forwarded verbatim as the key argument. +// +// Implementations that model an array-like container are expected to give "-" the append semantics; +// implementations that do not should return an error wrapping [ErrDashToken] (or [ErrPointer]) for +// clarity. +// +// Implementations are responsible for any in-place mutation: the library does not attempt to rebind +// the result of JSONSet into a parent container. +type JSONSetable interface { + // JSONSet sets the value pointed at the (unescaped) key. + // + // The key may be the RFC 6901 "-" token when the pointer targets a slice-like member; see the + // interface documentation for details. + JSONSet(key string, value any) error +} + +// NameProvider knows how to resolve go struct fields into json names. +// +// The default provider is brought by +// [github.com/go-openapi/jsonpointer/jsonname.DefaultJSONNameProvider]. +type NameProvider interface { + // GetGoName gets the go name for a json property name + GetGoName(subject any, name string) (string, bool) + + // GetGoNameForType gets the go name for a given type for a json property name + GetGoNameForType(tpe reflect.Type, name string) (string, bool) +} diff --git a/vendor/github.com/go-openapi/jsonpointer/jsonname/doc.go b/vendor/github.com/go-openapi/jsonpointer/jsonname/doc.go new file mode 100644 index 000000000..79232eaca --- /dev/null +++ b/vendor/github.com/go-openapi/jsonpointer/jsonname/doc.go @@ -0,0 +1,5 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +// Package jsonname is a provider of json property names from go properties. +package jsonname diff --git a/vendor/github.com/go-openapi/jsonpointer/jsonname/go_name_provider.go b/vendor/github.com/go-openapi/jsonpointer/jsonname/go_name_provider.go new file mode 100644 index 000000000..5eec18fbf --- /dev/null +++ b/vendor/github.com/go-openapi/jsonpointer/jsonname/go_name_provider.go @@ -0,0 +1,288 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package jsonname + +import ( + "reflect" + "strings" + "sync" +) + +var _ providerIface = (*GoNameProvider)(nil) + +// GoNameProvider resolves json property names to go struct field names following the same rules as +// the standard library's [encoding/json] package. +// +// Contrary to [NameProvider], it considers exported fields without a json tag, and promotes fields +// from anonymous embedded struct types. +// +// Rules (aligned with encoding/json): +// +// - unexported fields are ignored; +// - a field tagged `json:"-"` is ignored; +// - a field tagged `json:"-,"` is kept under the json name "-" (stdlib quirk); +// - a field tagged `json:""` or with no json tag at all keeps its Go name as json name; +// - anonymous struct fields without an explicit json tag have their fields +// promoted into the parent, following breadth-first depth rules: +// a shallower field wins over a deeper one; at equal depth, a conflict +// discards all conflicting fields unless exactly one has an explicit json tag. +// +// This type is safe for concurrent use. +type GoNameProvider struct { + lock sync.Mutex + index map[reflect.Type]nameIndex +} + +// NewGoNameProvider creates a new [GoNameProvider]. +func NewGoNameProvider() *GoNameProvider { + return &GoNameProvider{ + index: make(map[reflect.Type]nameIndex), + } +} + +// GetJSONNames gets all the json property names for a type. +func (n *GoNameProvider) GetJSONNames(subject any) []string { + n.lock.Lock() + defer n.lock.Unlock() + + tpe := reflect.Indirect(reflect.ValueOf(subject)).Type() + names := n.nameIndexFor(tpe) + + res := make([]string, 0, len(names.jsonNames)) + for k := range names.jsonNames { + res = append(res, k) + } + + return res +} + +// GetJSONName gets the json name for a go property name. +func (n *GoNameProvider) GetJSONName(subject any, name string) (string, bool) { + tpe := reflect.Indirect(reflect.ValueOf(subject)).Type() + + return n.GetJSONNameForType(tpe, name) +} + +// GetJSONNameForType gets the json name for a go property name on a given type. +func (n *GoNameProvider) GetJSONNameForType(tpe reflect.Type, name string) (string, bool) { + n.lock.Lock() + defer n.lock.Unlock() + + names := n.nameIndexFor(tpe) + nme, ok := names.goNames[name] + + return nme, ok +} + +// GetGoName gets the go name for a json property name. +func (n *GoNameProvider) GetGoName(subject any, name string) (string, bool) { + tpe := reflect.Indirect(reflect.ValueOf(subject)).Type() + + return n.GetGoNameForType(tpe, name) +} + +// GetGoNameForType gets the go name for a given type for a json property name. +func (n *GoNameProvider) GetGoNameForType(tpe reflect.Type, name string) (string, bool) { + n.lock.Lock() + defer n.lock.Unlock() + + names := n.nameIndexFor(tpe) + nme, ok := names.jsonNames[name] + + return nme, ok +} + +func (n *GoNameProvider) nameIndexFor(tpe reflect.Type) nameIndex { + if names, ok := n.index[tpe]; ok { + return names + } + + names := buildGoNameIndex(tpe) + n.index[tpe] = names + + return names +} + +// fieldEntry captures a candidate field discovered while walking a struct along with the +// indirection path from the root type (used to resolve conflicts by depth in the same way +// encoding/json does). +type fieldEntry struct { + goName string + jsonName string + index []int + tagged bool +} + +func buildGoNameIndex(tpe reflect.Type) nameIndex { + fields := collectGoFields(tpe) + + idx := make(map[string]string, len(fields)) + reverseIdx := make(map[string]string, len(fields)) + for _, f := range fields { + idx[f.jsonName] = f.goName + reverseIdx[f.goName] = f.jsonName + } + + return nameIndex{jsonNames: idx, goNames: reverseIdx} +} + +// collectGoFields walks tpe breadth-first along anonymous struct fields, +// reproducing the field selection performed by encoding/json.typeFields. +// +//nolint:gocognit // everything is inlined to help the compiler determine what escapes and what doesn't +func collectGoFields(tpe reflect.Type) []fieldEntry { + if tpe.Kind() != reflect.Struct { + return nil + } + + type queued struct { + typ reflect.Type + index []int + } + + current := []queued{} + next := []queued{{typ: tpe}} + visited := map[reflect.Type]bool{tpe: true} + + var ( + candidates []fieldEntry + count = map[string]int{} + nextCount = map[string]int{} + ) + + for len(next) > 0 { + current, next = next, current[:0] + count, nextCount = nextCount, count + for k := range nextCount { + delete(nextCount, k) + } + + for _, q := range current { + for i := range q.typ.NumField() { + sf := q.typ.Field(i) + + if sf.Anonymous { + ft := sf.Type + if ft.Kind() == reflect.Pointer { + ft = ft.Elem() + } + if !sf.IsExported() && ft.Kind() != reflect.Struct { + continue + } + } else if !sf.IsExported() { + continue + } + + tag := sf.Tag.Get("json") + if tag == "-" { + continue + } + jsonName, _ := parseJSONTag(tag) + tagged := jsonName != "" + + ft := sf.Type + if ft.Kind() == reflect.Pointer { + ft = ft.Elem() + } + + if sf.Anonymous && ft.Kind() == reflect.Struct && !tagged { + if visited[ft] { + continue + } + visited[ft] = true + + index := make([]int, len(q.index)+1) + copy(index, q.index) + index[len(q.index)] = i + next = append(next, queued{typ: ft, index: index}) + + continue + } + + name := jsonName + if name == "" { + name = sf.Name + } + + index := make([]int, len(q.index)+1) + copy(index, q.index) + index[len(q.index)] = i + + candidates = append(candidates, fieldEntry{ + goName: sf.Name, + jsonName: name, + index: index, + tagged: tagged, + }) + nextCount[name]++ + } + } + } + + return dominantFields(candidates) +} + +// dominantFields applies the Go encoding/json conflict resolution rules: at each JSON name, the +// shallowest field wins; at equal depth, a uniquely tagged candidate wins; otherwise all candidates +// for that name are dropped. +func dominantFields(candidates []fieldEntry) []fieldEntry { + byName := make(map[string][]fieldEntry, len(candidates)) + for _, c := range candidates { + byName[c.jsonName] = append(byName[c.jsonName], c) + } + + out := make([]fieldEntry, 0, len(byName)) + for _, group := range byName { + if len(group) == 1 { + out = append(out, group[0]) + + continue + } + + minDepth := len(group[0].index) + for _, c := range group[1:] { + if len(c.index) < minDepth { + minDepth = len(c.index) + } + } + + var shallow []fieldEntry + for _, c := range group { + if len(c.index) == minDepth { + shallow = append(shallow, c) + } + } + + if len(shallow) == 1 { + out = append(out, shallow[0]) + + continue + } + + var tagged []fieldEntry + for _, c := range shallow { + if c.tagged { + tagged = append(tagged, c) + } + } + if len(tagged) == 1 { + out = append(out, tagged[0]) + } + } + + return out +} + +// parseJSONTag returns the name component of a json struct tag and whether it carried any non-name +// option (kept for future-proofing, e.g. "omitempty"). +func parseJSONTag(tag string) (string, string) { + if tag == "" { + return "", "" + } + if before, after, ok := strings.Cut(tag, ","); ok { + return before, after + } + + return tag, "" +} diff --git a/vendor/github.com/go-openapi/jsonpointer/jsonname/ifaces.go b/vendor/github.com/go-openapi/jsonpointer/jsonname/ifaces.go new file mode 100644 index 000000000..64871f0d2 --- /dev/null +++ b/vendor/github.com/go-openapi/jsonpointer/jsonname/ifaces.go @@ -0,0 +1,16 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package jsonname + +import "reflect" + +// providerIface is an unexported compile-time contract that every name provider in this package is +// expected to satisfy. +// +// It mirrors the interface declared by the main consumer of this module: +// [github.com/go-openapi/jsonpointer.NameProvider]. +type providerIface interface { + GetGoName(subject any, name string) (string, bool) + GetGoNameForType(tpe reflect.Type, name string) (string, bool) +} diff --git a/vendor/github.com/go-openapi/swag/jsonname/name_provider.go b/vendor/github.com/go-openapi/jsonpointer/jsonname/name_provider.go similarity index 66% rename from vendor/github.com/go-openapi/swag/jsonname/name_provider.go rename to vendor/github.com/go-openapi/jsonpointer/jsonname/name_provider.go index e87aac2f7..1bec2406b 100644 --- a/vendor/github.com/go-openapi/swag/jsonname/name_provider.go +++ b/vendor/github.com/go-openapi/jsonpointer/jsonname/name_provider.go @@ -1,16 +1,5 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 package jsonname @@ -21,10 +10,12 @@ import ( ) // DefaultJSONNameProvider is the default cache for types. -var DefaultJSONNameProvider = NewNameProvider() +var DefaultJSONNameProvider = NewNameProvider() //nolint:gochecknoglobals // default settings, for backward compatible package-level settings + +var _ providerIface = (*NameProvider)(nil) -// NameProvider represents an object capable of translating from go property names -// to json property names. +// NameProvider represents an object capable of translating from go property names to json property +// names. // // This type is thread-safe. // @@ -39,7 +30,7 @@ type nameIndex struct { goNames map[string]string } -// NewNameProvider creates a new name provider +// NewNameProvider creates a new name provider. func NewNameProvider() *NameProvider { return &NameProvider{ lock: &sync.Mutex{}, @@ -48,7 +39,7 @@ func NewNameProvider() *NameProvider { } func buildnameIndex(tpe reflect.Type, idx, reverseIdx map[string]string) { - for i := 0; i < tpe.NumField(); i++ { + for i := range tpe.NumField() { targetDes := tpe.Field(i) if targetDes.PkgPath != "" { // unexported @@ -82,15 +73,15 @@ func buildnameIndex(tpe reflect.Type, idx, reverseIdx map[string]string) { } func newNameIndex(tpe reflect.Type) nameIndex { - var idx = make(map[string]string, tpe.NumField()) - var reverseIdx = make(map[string]string, tpe.NumField()) + idx := make(map[string]string, tpe.NumField()) + reverseIdx := make(map[string]string, tpe.NumField()) buildnameIndex(tpe, idx, reverseIdx) return nameIndex{jsonNames: idx, goNames: reverseIdx} } -// GetJSONNames gets all the json property names for a type -func (n *NameProvider) GetJSONNames(subject interface{}) []string { +// GetJSONNames gets all the json property names for a type. +func (n *NameProvider) GetJSONNames(subject any) []string { n.lock.Lock() defer n.lock.Unlock() tpe := reflect.Indirect(reflect.ValueOf(subject)).Type() @@ -106,13 +97,13 @@ func (n *NameProvider) GetJSONNames(subject interface{}) []string { return res } -// GetJSONName gets the json name for a go property name -func (n *NameProvider) GetJSONName(subject interface{}, name string) (string, bool) { +// GetJSONName gets the json name for a go property name. +func (n *NameProvider) GetJSONName(subject any, name string) (string, bool) { tpe := reflect.Indirect(reflect.ValueOf(subject)).Type() return n.GetJSONNameForType(tpe, name) } -// GetJSONNameForType gets the json name for a go property name on a given type +// GetJSONNameForType gets the json name for a go property name on a given type. func (n *NameProvider) GetJSONNameForType(tpe reflect.Type, name string) (string, bool) { n.lock.Lock() defer n.lock.Unlock() @@ -124,13 +115,13 @@ func (n *NameProvider) GetJSONNameForType(tpe reflect.Type, name string) (string return nme, ok } -// GetGoName gets the go name for a json property name -func (n *NameProvider) GetGoName(subject interface{}, name string) (string, bool) { +// GetGoName gets the go name for a json property name. +func (n *NameProvider) GetGoName(subject any, name string) (string, bool) { tpe := reflect.Indirect(reflect.ValueOf(subject)).Type() return n.GetGoNameForType(tpe, name) } -// GetGoNameForType gets the go name for a given type for a json property name +// GetGoNameForType gets the go name for a given type for a json property name. func (n *NameProvider) GetGoNameForType(tpe reflect.Type, name string) (string, bool) { n.lock.Lock() defer n.lock.Unlock() diff --git a/vendor/github.com/go-openapi/jsonpointer/options.go b/vendor/github.com/go-openapi/jsonpointer/options.go new file mode 100644 index 000000000..223c1e5ff --- /dev/null +++ b/vendor/github.com/go-openapi/jsonpointer/options.go @@ -0,0 +1,85 @@ +// SPDX-FileCopyrightText: Copyright (c) 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package jsonpointer + +import ( + "sync" + + "github.com/go-openapi/jsonpointer/jsonname" +) + +// Option to tune the behavior of a JSON [Pointer]. +type Option func(*options) + +var ( + //nolint:gochecknoglobals // package level defaults are provided as a convenient, backward-compatible way to adopt options. + defaultOptions = options{ + provider: jsonname.DefaultJSONNameProvider, + } + //nolint:gochecknoglobals // guards defaultOptions against concurrent SetDefaultNameProvider / read races (testing) + defaultOptionsMu sync.RWMutex +) + +// SetDefaultNameProvider sets the [NameProvider] as a package-level default. +// +// By default, the default provider is [jsonname.DefaultJSONNameProvider]. +// +// It is safe to call concurrently with [Pointer.Get], [Pointer.Set], [GetForToken] and +// [SetForToken]. +// The typical usage is to call it once at initialization time. +// +// A nil provider is ignored. +func SetDefaultNameProvider(provider NameProvider) { + if provider == nil { + return + } + + defaultOptionsMu.Lock() + defer defaultOptionsMu.Unlock() + + defaultOptions.provider = provider +} + +// UseGoNameProvider sets the [NameProvider] as a package-level default to the alternative provider +// [jsonname.GoNameProvider], that covers a few areas not supported by the default name provider. +// +// This implementation supports untagged exported fields and embedded types in go struct. +// It follows strictly the behavior of the JSON standard library regarding field naming conventions. +// +// It is safe to call concurrently with [Pointer.Get], [Pointer.Set], [GetForToken] and +// [SetForToken]. +// The typical usage is to call it once at initialization time. +func UseGoNameProvider() { + SetDefaultNameProvider(jsonname.NewGoNameProvider()) +} + +// DefaultNameProvider returns the current package-level [NameProvider]. +func DefaultNameProvider() NameProvider { //nolint:ireturn // returning the interface is the point — callers pick their own implementation. + defaultOptionsMu.RLock() + defer defaultOptionsMu.RUnlock() + + return defaultOptions.provider +} + +// WithNameProvider injects a custom [NameProvider] to resolve json names from go struct types. +func WithNameProvider(provider NameProvider) Option { + return func(o *options) { + o.provider = provider + } +} + +type options struct { + provider NameProvider +} + +func optionsWithDefaults(opts []Option) options { + var o options + o.provider = DefaultNameProvider() + + for _, apply := range opts { + apply(&o) + } + + return o +} diff --git a/vendor/github.com/go-openapi/jsonpointer/pointer.go b/vendor/github.com/go-openapi/jsonpointer/pointer.go index 7513c4763..05fc863ee 100644 --- a/vendor/github.com/go-openapi/jsonpointer/pointer.go +++ b/vendor/github.com/go-openapi/jsonpointer/pointer.go @@ -1,28 +1,7 @@ -// Copyright 2013 sigu-399 ( https://github.com/sigu-399 ) -// -// 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. - -// author sigu-399 -// author-github https://github.com/sigu-399 -// author-mail sigu.399@gmail.com -// -// repository-name jsonpointer -// repository-desc An implementation of JSON Pointer - Go language -// -// description Main and unique file. -// -// created 25-02-2013 +// SPDX-FileCopyrightText: Copyright (c) 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 +// Package jsonpointer provides a golang implementation for json pointers. package jsonpointer import ( @@ -32,8 +11,6 @@ import ( "reflect" "strconv" "strings" - - "github.com/go-openapi/swag/jsonname" ) const ( @@ -41,29 +18,34 @@ const ( pointerSeparator = `/` ) -var ( - jsonPointableType = reflect.TypeOf(new(JSONPointable)).Elem() - jsonSetableType = reflect.TypeOf(new(JSONSetable)).Elem() -) - -// JSONPointable is an interface for structs to implement when they need to customize the -// json pointer process -type JSONPointable interface { - JSONLookup(string) (any, error) -} - -// JSONSetable is an interface for structs to implement when they need to customize the -// json pointer process -type JSONSetable interface { - JSONSet(string, any) error -} - -// Pointer is a representation of a json pointer +// Pointer is a representation of a json pointer. +// +// Use [Pointer.Get] to retrieve a value or [Pointer.Set] to set a value. +// +// It works with any go type interpreted as a JSON document, which means: +// +// - if a type implements [JSONPointable], its [JSONPointable.JSONLookup] method is used to resolve [Pointer.Get] +// - if a type implements [JSONSetable], its [JSONSetable.JSONSet] method is used to resolve [Pointer.Set] +// - a go map[K]V is interpreted as an object, with type K assignable to a string +// - a go slice []T is interpreted as an array +// - a go struct is interpreted as an object, with exported fields interpreted as keys +// - promoted fields from an embedded struct are traversed +// - scalars (e.g. int, float64 ...), channels, functions and go arrays cannot be traversed +// +// For struct s resolved by reflection, key mappings honor the conventional struct tag `json`. +// +// Fields that do not specify a `json` tag, or specify an empty one, or are tagged as `json:"-"` are +// ignored. +// +// # Limitations +// +// - Unlike go standard marshaling, untagged fields do not default to the go field name and are ignored. +// - anonymous fields are not traversed if untagged type Pointer struct { referenceTokens []string } -// New creates a new json pointer for the given string +// New creates a new json pointer from its string representation. func New(jsonPointerString string) (Pointer, error) { var p Pointer err := p.parse(jsonPointerString) @@ -71,34 +53,60 @@ func New(jsonPointerString string) (Pointer, error) { return p, err } -// Get uses the pointer to retrieve a value from a JSON document -func (p *Pointer) Get(document any) (any, reflect.Kind, error) { - return p.get(document, jsonname.DefaultJSONNameProvider) +// Get uses the pointer to retrieve a value from a JSON document. +// +// It returns the value with its type as a [reflect.Kind] or an error. +func (p *Pointer) Get(document any, opts ...Option) (any, reflect.Kind, error) { + o := optionsWithDefaults(opts) + + return p.get(document, o.provider) } -// Set uses the pointer to set a value from a JSON document -func (p *Pointer) Set(document any, value any) (any, error) { - return document, p.set(document, value, jsonname.DefaultJSONNameProvider) +// Set uses the pointer to set a value from a data type that represent a JSON document. +// +// # Mutation contract +// +// Set mutates the provided document in place whenever Go's type system allows it: when document is +// a map, a pointer, or when the targeted value is reached through an addressable ancestor (e.g. a +// struct field traversed via a pointer, a slice element). +// +// Callers that rely on this in-place behavior may continue to ignore the returned document. +// +// The returned document is only load-bearing when Set cannot mutate in place. +// +// This happens in one specific case: appending to a top-level slice passed by value (e.g. document +// of type []T rather than *[]T) via the RFC 6901 "-" terminal token. reflect.Append produces a new +// slice header that the library cannot rebind into the caller's variable; the updated document is +// returned instead. +// +// Pass *[]T if you want in-place rebind for that case as well. +// +// See [ErrDashToken] for the semantics of the "-" token. +func (p *Pointer) Set(document any, value any, opts ...Option) (any, error) { + o := optionsWithDefaults(opts) + + return p.set(document, value, o.provider) } -// DecodedTokens returns the decoded tokens of this JSON pointer +// DecodedTokens returns the decoded (unescaped) tokens of this JSON pointer. func (p *Pointer) DecodedTokens() []string { result := make([]string, 0, len(p.referenceTokens)) - for _, t := range p.referenceTokens { - result = append(result, Unescape(t)) + for _, token := range p.referenceTokens { + result = append(result, Unescape(token)) } + return result } -// IsEmpty returns true if this is an empty json pointer -// this indicates that it points to the root document +// IsEmpty returns true if this is an empty json pointer. +// +// This indicates that it points to the root document. func (p *Pointer) IsEmpty() bool { return len(p.referenceTokens) == 0 } -// Pointer to string representation function +// String representation of a pointer. func (p *Pointer) String() string { - if len(p.referenceTokens) == 0 { return emptyPointer } @@ -106,6 +114,46 @@ func (p *Pointer) String() string { return pointerSeparator + strings.Join(p.referenceTokens, pointerSeparator) } +// Offset returns the byte offset, in the raw JSON text of document, of the location referenced by +// this pointer's terminal token. +// +// Unlike [Pointer.Get] and [Pointer.Set], which operate on a decoded Go value, Offset operates +// directly on the textual JSON source. +// +// It drives an [encoding/json.Decoder] over the string and stops at the terminal token, returning +// the position at which the decoder was about to read that token. +// +// It is primarily intended for tooling that needs to map a pointer back to a region of the original +// source: reporting line/column for validation or parse diagnostics, extracting a sub-document by +// slicing the raw bytes, or highlighting the referenced span in an editor. +// +// # Offset semantics +// +// The meaning of the returned offset depends on whether the terminal token addresses an object +// property or an array element: +// +// - Object property: the offset points to the first byte of the key (its +// opening quote character), not to the associated value. For example, +// pointer "/foo/bar" against {"foo": {"bar": 21}} returns 9, the index of +// the opening quote of "bar". +// - Array element: the offset points to the first byte of the value at that +// index. For example, pointer "/0/1" against [[1,2], [3,4]] returns 4, +// the index of the digit 2. +// +// # Errors +// +// Offset returns an error in any of these cases: +// +// - document is not syntactically valid JSON; +// - the structure of document does not match the pointer (e.g. traversing +// into a scalar, or a token that is neither a valid key nor a valid +// numeric index); +// - a referenced key or index does not exist in document; +// - the pointer's terminal token is the RFC 6901 "-" array token, which +// designates a nonexistent element and therefore has no offset in the +// source. The returned error wraps [ErrDashToken]. +// +// All errors wrap [ErrPointer]. func (p *Pointer) Offset(document string) (int64, error) { dec := json.NewDecoder(strings.NewReader(document)) var offset int64 @@ -134,33 +182,61 @@ func (p *Pointer) Offset(document string) (int64, error) { return 0, fmt.Errorf("invalid token %#v: %w", tk, ErrPointer) } } - return offset, nil + return skipJSONSeparator(document, offset), nil +} + +// skipJSONSeparator advances offset past trailing JSON whitespace and at most one value separator +// (comma) in document, so the result points at the first byte of the next JSON token. +// +// The streaming decoder's InputOffset sits right after the most recently consumed token, which +// between values is the comma (or whitespace) — not the following token. +// +// Normalizing here keeps Offset's contract uniform: for both object keys and array elements, and +// regardless of position within the parent container, the returned offset always points at the +// first byte of the addressed token. +func skipJSONSeparator(document string, offset int64) int64 { + n := int64(len(document)) + for offset < n && isJSONWhitespace(document[offset]) { + offset++ + } + if offset < n && document[offset] == ',' { + offset++ + } + for offset < n && isJSONWhitespace(document[offset]) { + offset++ + } + return offset } -// "Constructor", parses the given string JSON pointer +func isJSONWhitespace(c byte) bool { + return c == ' ' || c == '\t' || c == '\n' || c == '\r' +} + +// "Constructor", parses the given string JSON pointer. func (p *Pointer) parse(jsonPointerString string) error { - var err error + if jsonPointerString == emptyPointer { + return nil + } - if jsonPointerString != emptyPointer { - if !strings.HasPrefix(jsonPointerString, pointerSeparator) { - err = errors.Join(ErrInvalidStart, ErrPointer) - } else { - referenceTokens := strings.Split(jsonPointerString, pointerSeparator) - p.referenceTokens = append(p.referenceTokens, referenceTokens[1:]...) - } + if !strings.HasPrefix(jsonPointerString, pointerSeparator) { + // non empty pointer must start with "/" + return errors.Join(ErrInvalidStart, ErrPointer) } - return err + referenceTokens := strings.Split(jsonPointerString, pointerSeparator) + p.referenceTokens = append(p.referenceTokens, referenceTokens[1:]...) + + return nil } -func (p *Pointer) get(node any, nameProvider *jsonname.NameProvider) (any, reflect.Kind, error) { +func (p *Pointer) get(node any, nameProvider NameProvider) (any, reflect.Kind, error) { if nameProvider == nil { - nameProvider = jsonname.DefaultJSONNameProvider + nameProvider = defaultOptions.provider } kind := reflect.Invalid - // Full document when empty + // full document when empty if len(p.referenceTokens) == 0 { return node, kind, nil } @@ -181,106 +257,189 @@ func (p *Pointer) get(node any, nameProvider *jsonname.NameProvider) (any, refle return node, kind, nil } -func (p *Pointer) set(node, data any, nameProvider *jsonname.NameProvider) error { +func (p *Pointer) set(node, data any, nameProvider NameProvider) (any, error) { knd := reflect.ValueOf(node).Kind() if knd != reflect.Pointer && knd != reflect.Struct && knd != reflect.Map && knd != reflect.Slice && knd != reflect.Array { - return errors.Join( + return node, errors.Join( + fmt.Errorf("unexpected type: %T", node), //nolint:err113 // err wrapping is carried out by errors.Join, not fmt.Errorf. ErrUnsupportedValueType, ErrPointer, ) } + // full document when empty + if len(p.referenceTokens) == 0 { + return node, nil + } + if nameProvider == nil { - nameProvider = jsonname.DefaultJSONNameProvider + nameProvider = defaultOptions.provider } - // Full document when empty - if len(p.referenceTokens) == 0 { - return nil + return p.setAt(node, p.referenceTokens, data, nameProvider) +} + +// setAt recursively walks the token list, setting the data at the terminal token and rebinding any +// new child reference (e.g. a slice header returned by an "-" append) into its parent on the way +// back up. +// +// Returning the (possibly new) node at each level is what makes append work at any depth without +// requiring the caller to pass a pointer to the containing slice: the new slice header propagates +// up and each parent rebinds it via the appropriate kind-specific setter. +func (p *Pointer) setAt(node any, tokens []string, data any, nameProvider NameProvider) (any, error) { + decodedToken := Unescape(tokens[0]) + + if len(tokens) == 1 { + return setSingleImpl(node, data, decodedToken, nameProvider) } - lastI := len(p.referenceTokens) - 1 - for i, token := range p.referenceTokens { - isLastToken := i == lastI - decodedToken := Unescape(token) + child, err := p.resolveNodeForToken(node, decodedToken, nameProvider) + if err != nil { + return node, err + } + + newChild, err := p.setAt(child, tokens[1:], data, nameProvider) + if err != nil { + return node, err + } + + return rebindChild(node, decodedToken, newChild, nameProvider) +} + +// rebindChild writes newChild back into node at decodedToken. +// +// For cases where the child was already mutated in place (pointer aliasing, addressable slice +// elements) the rebind is a safe no-op. +// +// For cases where the child was returned by value (map entries holding a slice, slices reached +// through a non-addressable ancestor), the rebind propagates the new value into the parent. +// +// Parents implementing [JSONPointable] are left alone: they took ownership of the child via +// JSONLookup and did not opt into a JSONSet-based rebind on intermediate tokens. +func rebindChild(node any, decodedToken string, newChild any, nameProvider NameProvider) (any, error) { + if _, ok := node.(JSONPointable); ok { + return node, nil + } - if isLastToken { + rValue := reflect.Indirect(reflect.ValueOf(node)) - return setSingleImpl(node, data, decodedToken, nameProvider) + switch rValue.Kind() { + case reflect.Struct: + nm, ok := nameProvider.GetGoNameForType(rValue.Type(), decodedToken) + if !ok { + return node, fmt.Errorf("object has no field %q: %w", decodedToken, ErrPointer) } + fld := rValue.FieldByName(nm) + if !fld.CanSet() { + return node, nil + } + assignReflectValue(fld, newChild) + return node, nil + + case reflect.Map: + rValue.SetMapIndex(reflect.ValueOf(decodedToken), reflect.ValueOf(newChild)) + return node, nil - // Check for nil during traversal - if isNil(node) { - return fmt.Errorf("cannot traverse through nil value at %q: %w", decodedToken, ErrPointer) + case reflect.Slice: + if decodedToken == dashToken { + return node, errDashIntermediate() + } + idx, err := strconv.Atoi(decodedToken) + if err != nil { + return node, errors.Join(err, ErrPointer) } + elem := rValue.Index(idx) + if !elem.CanSet() { + return node, nil + } + assignReflectValue(elem, newChild) + return node, nil - rValue := reflect.Indirect(reflect.ValueOf(node)) - kind := rValue.Kind() + default: + return node, errInvalidReference(decodedToken) + } +} - if rValue.Type().Implements(jsonPointableType) { - r, err := node.(JSONPointable).JSONLookup(decodedToken) - if err != nil { - return err - } - fld := reflect.ValueOf(r) - if fld.CanAddr() && fld.Kind() != reflect.Interface && fld.Kind() != reflect.Map && fld.Kind() != reflect.Slice && fld.Kind() != reflect.Pointer { - node = fld.Addr().Interface() - continue - } - node = r - continue +// assignReflectValue assigns src into dst, unwrapping a pointer when dst expects the pointee type. +// +// This tolerates the pointer-wrapping performed by [typeFromValue] for addressable fields. +func assignReflectValue(dst reflect.Value, src any) { + nv := reflect.ValueOf(src) + if !nv.IsValid() { + return + } + if nv.Type().AssignableTo(dst.Type()) { + dst.Set(nv) + return + } + if nv.Kind() == reflect.Pointer && nv.Elem().Type().AssignableTo(dst.Type()) { + dst.Set(nv.Elem()) + } +} + +func (p *Pointer) resolveNodeForToken(node any, decodedToken string, nameProvider NameProvider) (next any, err error) { + // check for nil during traversal + if isNil(node) { + return nil, fmt.Errorf("cannot traverse through nil value at %q: %w", decodedToken, ErrPointer) + } + + pointable, ok := node.(JSONPointable) + if ok { + r, err := pointable.JSONLookup(decodedToken) + if err != nil { + return nil, err } - switch kind { //nolint:exhaustive - case reflect.Struct: - nm, ok := nameProvider.GetGoNameForType(rValue.Type(), decodedToken) - if !ok { - return fmt.Errorf("object has no field %q: %w", decodedToken, ErrPointer) - } - fld := rValue.FieldByName(nm) - if fld.CanAddr() && fld.Kind() != reflect.Interface && fld.Kind() != reflect.Map && fld.Kind() != reflect.Slice && fld.Kind() != reflect.Pointer { - node = fld.Addr().Interface() - continue - } - node = fld.Interface() + fld := reflect.ValueOf(r) + if fld.CanAddr() && fld.Kind() != reflect.Interface && fld.Kind() != reflect.Map && fld.Kind() != reflect.Slice && fld.Kind() != reflect.Pointer { + return fld.Addr().Interface(), nil + } - case reflect.Map: - kv := reflect.ValueOf(decodedToken) - mv := rValue.MapIndex(kv) + return r, nil + } - if !mv.IsValid() { - return fmt.Errorf("object has no key %q: %w", decodedToken, ErrPointer) - } - if mv.CanAddr() && mv.Kind() != reflect.Interface && mv.Kind() != reflect.Map && mv.Kind() != reflect.Slice && mv.Kind() != reflect.Pointer { - node = mv.Addr().Interface() - continue - } - node = mv.Interface() + rValue := reflect.Indirect(reflect.ValueOf(node)) + kind := rValue.Kind() - case reflect.Slice: - tokenIndex, err := strconv.Atoi(decodedToken) - if err != nil { - return err - } - sLength := rValue.Len() - if tokenIndex < 0 || tokenIndex >= sLength { - return fmt.Errorf("index out of bounds array[0,%d] index '%d': %w", sLength, tokenIndex, ErrPointer) - } + switch kind { + case reflect.Struct: + nm, ok := nameProvider.GetGoNameForType(rValue.Type(), decodedToken) + if !ok { + return nil, fmt.Errorf("object has no field %q: %w", decodedToken, ErrPointer) + } - elem := rValue.Index(tokenIndex) - if elem.CanAddr() && elem.Kind() != reflect.Interface && elem.Kind() != reflect.Map && elem.Kind() != reflect.Slice && elem.Kind() != reflect.Pointer { - node = elem.Addr().Interface() - continue - } - node = elem.Interface() + return typeFromValue(rValue.FieldByName(nm)), nil - default: - return fmt.Errorf("invalid token reference %q: %w", decodedToken, ErrPointer) + case reflect.Map: + kv := reflect.ValueOf(decodedToken) + mv := rValue.MapIndex(kv) + + if !mv.IsValid() { + return nil, errNoKey(decodedToken) } - } - return nil + return typeFromValue(mv), nil + + case reflect.Slice: + if decodedToken == dashToken { + return nil, errDashIntermediate() + } + tokenIndex, err := strconv.Atoi(decodedToken) + if err != nil { + return nil, errors.Join(err, ErrPointer) + } + + sLength := rValue.Len() + if tokenIndex < 0 || tokenIndex >= sLength { + return nil, errOutOfBounds(sLength, tokenIndex) + } + + return typeFromValue(rValue.Index(tokenIndex)), nil + + default: + return nil, errInvalidReference(decodedToken) + } } func isNil(input any) bool { @@ -289,7 +448,7 @@ func isNil(input any) bool { } kind := reflect.TypeOf(input).Kind() - switch kind { //nolint:exhaustive + switch kind { case reflect.Pointer, reflect.Map, reflect.Slice, reflect.Chan: return reflect.ValueOf(input).IsNil() default: @@ -297,17 +456,32 @@ func isNil(input any) bool { } } -// GetForToken gets a value for a json pointer token 1 level deep -func GetForToken(document any, decodedToken string) (any, reflect.Kind, error) { - return getSingleImpl(document, decodedToken, jsonname.DefaultJSONNameProvider) +func typeFromValue(v reflect.Value) any { + if v.CanAddr() && v.Kind() != reflect.Interface && v.Kind() != reflect.Map && v.Kind() != reflect.Slice && v.Kind() != reflect.Pointer { + return v.Addr().Interface() + } + + return v.Interface() } -// SetForToken gets a value for a json pointer token 1 level deep -func SetForToken(document any, decodedToken string, value any) (any, error) { - return document, setSingleImpl(document, value, decodedToken, jsonname.DefaultJSONNameProvider) +// GetForToken gets a value for a json pointer token 1 level deep. +func GetForToken(document any, decodedToken string, opts ...Option) (any, reflect.Kind, error) { + o := optionsWithDefaults(opts) + + return getSingleImpl(document, decodedToken, o.provider) +} + +// SetForToken sets a value for a json pointer token 1 level deep. +// +// See [Pointer.Set] for the mutation contract, in particular the handling of the RFC 6901 "-" token +// on slices. +func SetForToken(document any, decodedToken string, value any, opts ...Option) (any, error) { + o := optionsWithDefaults(opts) + + return setSingleImpl(document, value, decodedToken, o.provider) } -func getSingleImpl(node any, decodedToken string, nameProvider *jsonname.NameProvider) (any, reflect.Kind, error) { +func getSingleImpl(node any, decodedToken string, nameProvider NameProvider) (any, reflect.Kind, error) { rValue := reflect.Indirect(reflect.ValueOf(node)) kind := rValue.Kind() if isNil(node) { @@ -325,13 +499,15 @@ func getSingleImpl(node any, decodedToken string, nameProvider *jsonname.NamePro return getSingleImpl(*typed, decodedToken, nameProvider) } - switch kind { //nolint:exhaustive + switch kind { case reflect.Struct: nm, ok := nameProvider.GetGoNameForType(rValue.Type(), decodedToken) if !ok { return nil, kind, fmt.Errorf("object has no field %q: %w", decodedToken, ErrPointer) } + fld := rValue.FieldByName(nm) + return fld.Interface(), kind, nil case reflect.Map: @@ -341,78 +517,120 @@ func getSingleImpl(node any, decodedToken string, nameProvider *jsonname.NamePro if mv.IsValid() { return mv.Interface(), kind, nil } - return nil, kind, fmt.Errorf("object has no key %q: %w", decodedToken, ErrPointer) + + return nil, kind, errNoKey(decodedToken) case reflect.Slice: + if decodedToken == dashToken { + return nil, kind, errDashOnGet() + } tokenIndex, err := strconv.Atoi(decodedToken) if err != nil { - return nil, kind, err + return nil, kind, errors.Join(err, ErrPointer) } sLength := rValue.Len() if tokenIndex < 0 || tokenIndex >= sLength { - return nil, kind, fmt.Errorf("index out of bounds array[0,%d] index '%d': %w", sLength-1, tokenIndex, ErrPointer) + return nil, kind, errOutOfBounds(sLength, tokenIndex) } elem := rValue.Index(tokenIndex) return elem.Interface(), kind, nil default: - return nil, kind, fmt.Errorf("invalid token reference %q: %w", decodedToken, ErrPointer) + return nil, kind, errInvalidReference(decodedToken) } } -func setSingleImpl(node, data any, decodedToken string, nameProvider *jsonname.NameProvider) error { - rValue := reflect.Indirect(reflect.ValueOf(node)) - - // Check for nil to prevent panic when calling rValue.Type() +func setSingleImpl(node, data any, decodedToken string, nameProvider NameProvider) (any, error) { + // check for nil to prevent panic when calling rValue.Type() if isNil(node) { - return fmt.Errorf("cannot set field %q on nil value: %w", decodedToken, ErrPointer) + return node, fmt.Errorf("cannot set field %q on nil value: %w", decodedToken, ErrPointer) } - if ns, ok := node.(JSONSetable); ok { // pointer impl - return ns.JSONSet(decodedToken, data) + if ns, ok := node.(JSONSetable); ok { + return node, ns.JSONSet(decodedToken, data) } - if rValue.Type().Implements(jsonSetableType) { - return node.(JSONSetable).JSONSet(decodedToken, data) - } + rValue := reflect.Indirect(reflect.ValueOf(node)) - switch rValue.Kind() { //nolint:exhaustive + switch rValue.Kind() { case reflect.Struct: nm, ok := nameProvider.GetGoNameForType(rValue.Type(), decodedToken) if !ok { - return fmt.Errorf("object has no field %q: %w", decodedToken, ErrPointer) + return node, fmt.Errorf("object has no field %q: %w", decodedToken, ErrPointer) } + fld := rValue.FieldByName(nm) - if fld.IsValid() { - fld.Set(reflect.ValueOf(data)) + if !fld.CanSet() { + return node, fmt.Errorf("can't set struct field %s to %v: %w", nm, data, ErrPointer) } - return nil + + value := reflect.ValueOf(data) + valueType := value.Type() + assignedType := fld.Type() + + if !valueType.AssignableTo(assignedType) { + return node, fmt.Errorf("can't set value with type %T to field %s with type %v: %w", data, nm, assignedType, ErrPointer) + } + + fld.Set(value) + + return node, nil case reflect.Map: kv := reflect.ValueOf(decodedToken) rValue.SetMapIndex(kv, reflect.ValueOf(data)) - return nil + + return node, nil case reflect.Slice: + if decodedToken == dashToken { + // RFC 6901 §4 / RFC 6902 append semantics: terminal "-" appends the value to the slice. + // + // We rebind in place when the slice is reachable via an addressable ancestor; otherwise we + // return the new slice header for the parent (or the public Set) to rebind. + value := reflect.ValueOf(data) + elemType := rValue.Type().Elem() + if !value.Type().AssignableTo(elemType) { + return node, fmt.Errorf("can't append value of type %T to slice of %v: %w", data, elemType, ErrPointer) + } + newSlice := reflect.Append(rValue, value) + if rValue.CanSet() { + rValue.Set(newSlice) + return node, nil + } + return newSlice.Interface(), nil + } + tokenIndex, err := strconv.Atoi(decodedToken) if err != nil { - return err + return node, errors.Join(err, ErrPointer) } + sLength := rValue.Len() if tokenIndex < 0 || tokenIndex >= sLength { - return fmt.Errorf("index out of bounds array[0,%d] index '%d': %w", sLength, tokenIndex, ErrPointer) + return node, errOutOfBounds(sLength, tokenIndex) } elem := rValue.Index(tokenIndex) if !elem.CanSet() { - return fmt.Errorf("can't set slice index %s to %v: %w", decodedToken, data, ErrPointer) + return node, fmt.Errorf("can't set slice index %s to %v: %w", decodedToken, data, ErrPointer) } - elem.Set(reflect.ValueOf(data)) - return nil + + value := reflect.ValueOf(data) + valueType := value.Type() + assignedType := elem.Type() + + if !valueType.AssignableTo(assignedType) { + return node, fmt.Errorf("can't set value with type %T to slice element %d with type %v: %w", data, tokenIndex, assignedType, ErrPointer) + } + + elem.Set(value) + + return node, nil default: - return fmt.Errorf("invalid token reference %q: %w", decodedToken, ErrPointer) + return node, errInvalidReference(decodedToken) } } @@ -423,33 +641,40 @@ func offsetSingleObject(dec *json.Decoder, decodedToken string) (int64, error) { if err != nil { return 0, err } - switch tk := tk.(type) { - case json.Delim: - switch tk { - case '{': - if err = drainSingle(dec); err != nil { - return 0, err - } - case '[': + key, ok := tk.(string) + if !ok { + return 0, fmt.Errorf("invalid key token %#v: %w", tk, ErrPointer) + } + if key == decodedToken { + return offset, nil + } + + // Consume the associated value. + // Scalars are fully read by a single Token() call; composite values must be drained. + tk, err = dec.Token() + if err != nil { + return 0, err + } + if delim, isDelim := tk.(json.Delim); isDelim { + switch delim { + case '{', '[': if err = drainSingle(dec); err != nil { return 0, err } } - case string: - if tk == decodedToken { - return offset, nil - } - default: - return 0, fmt.Errorf("invalid token %#v: %w", tk, ErrPointer) } } + return 0, fmt.Errorf("token reference %q not found: %w", decodedToken, ErrPointer) } func offsetSingleArray(dec *json.Decoder, decodedToken string) (int64, error) { + if decodedToken == dashToken { + return 0, errDashOnOffset() + } idx, err := strconv.Atoi(decodedToken) if err != nil { - return 0, fmt.Errorf("token reference %q is not a number: %v: %w", decodedToken, err, ErrPointer) + return 0, fmt.Errorf("token reference %q is not a number: %w: %w", decodedToken, err, ErrPointer) } var i int for i = 0; i < idx && dec.More(); i++ { @@ -475,10 +700,12 @@ func offsetSingleArray(dec *json.Decoder, decodedToken string) (int64, error) { if !dec.More() { return 0, fmt.Errorf("token reference %q not found: %w", decodedToken, ErrPointer) } + return dec.InputOffset(), nil } // drainSingle drains a single level of object or array. +// // The decoder has to guarantee the beginning delim (i.e. '{' or '[') has been consumed. func drainSingle(dec *json.Decoder) error { for dec.More() { @@ -500,17 +727,15 @@ func drainSingle(dec *json.Decoder) error { } } - // Consumes the ending delim + // consumes the ending delim if _, err := dec.Token(); err != nil { return err } + return nil } -// Specific JSON pointer encoding here -// ~0 => ~ -// ~1 => / -// ... and vice versa +// JSON pointer encoding: ~0 => ~ ~1 => / ... and vice versa. const ( encRefTok0 = `~0` @@ -520,16 +745,23 @@ const ( ) var ( - encRefTokReplacer = strings.NewReplacer(encRefTok1, decRefTok1, encRefTok0, decRefTok0) - decRefTokReplacer = strings.NewReplacer(decRefTok1, encRefTok1, decRefTok0, encRefTok0) + encRefTokReplacer = strings.NewReplacer(encRefTok1, decRefTok1, encRefTok0, decRefTok0) //nolint:gochecknoglobals // it's okay to declare a replacer as a private global + decRefTokReplacer = strings.NewReplacer(decRefTok1, encRefTok1, decRefTok0, encRefTok0) //nolint:gochecknoglobals // it's okay to declare a replacer as a private global ) -// Unescape unescapes a json pointer reference token string to the original representation +// Unescape unescapes a json pointer reference token string to the original representation. func Unescape(token string) string { return encRefTokReplacer.Replace(token) } -// Escape escapes a pointer reference token string +// Escape escapes a pointer reference token string. +// +// The JSONPointer specification defines "/" as a separator and "~" as an escape prefix. +// +// Keys containing such characters are escaped with the following rules: +// +// - "~" is escaped as "~0" +// - "/" is escaped as "~1" func Escape(token string) string { return decRefTokReplacer.Replace(token) } diff --git a/vendor/github.com/go-openapi/swag/.editorconfig b/vendor/github.com/go-openapi/jsonreference/.editorconfig similarity index 100% rename from vendor/github.com/go-openapi/swag/.editorconfig rename to vendor/github.com/go-openapi/jsonreference/.editorconfig diff --git a/vendor/github.com/go-openapi/jsonreference/.gitignore b/vendor/github.com/go-openapi/jsonreference/.gitignore index 769c24400..d8f4186fe 100644 --- a/vendor/github.com/go-openapi/jsonreference/.gitignore +++ b/vendor/github.com/go-openapi/jsonreference/.gitignore @@ -1 +1,5 @@ -secrets.yml +*.out +*.cov +.idea +.env +.mcp.json diff --git a/vendor/github.com/go-openapi/jsonreference/.golangci.yml b/vendor/github.com/go-openapi/jsonreference/.golangci.yml index 7cea1af8b..dc7c96053 100644 --- a/vendor/github.com/go-openapi/jsonreference/.golangci.yml +++ b/vendor/github.com/go-openapi/jsonreference/.golangci.yml @@ -2,25 +2,10 @@ version: "2" linters: default: all disable: - - cyclop - depguard - - errchkjson - - errorlint - - exhaustruct - - forcetypeassert - funlen - - gochecknoglobals - - gochecknoinits - - gocognit - - godot - godox - - gosmopolitan - - inamedparam - #- intrange # disabled while < go1.22 - - ireturn - - lll - - musttag - - nestif + - exhaustruct - nlreturn - nonamedreturns - noinlineerr @@ -29,7 +14,6 @@ linters: - testpackage - thelper - tparallel - - unparam - varnamelen - whitespace - wrapcheck @@ -41,8 +25,15 @@ linters: goconst: min-len: 2 min-occurrences: 3 + cyclop: + max-complexity: 20 gocyclo: - min-complexity: 45 + min-complexity: 20 + exhaustive: + default-signifies-exhaustive: true + default-case-required: true + lll: + line-length: 180 exclusions: generated: lax presets: @@ -58,6 +49,7 @@ formatters: enable: - gofmt - goimports + - gofumpt exclusions: generated: lax paths: diff --git a/vendor/github.com/go-openapi/jsonreference/CODE_OF_CONDUCT.md b/vendor/github.com/go-openapi/jsonreference/CODE_OF_CONDUCT.md index 9322b065e..bac878f21 100644 --- a/vendor/github.com/go-openapi/jsonreference/CODE_OF_CONDUCT.md +++ b/vendor/github.com/go-openapi/jsonreference/CODE_OF_CONDUCT.md @@ -23,7 +23,9 @@ include: 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 @@ -55,7 +57,7 @@ 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 ivan+abuse@flanders.co.nz. All +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. @@ -68,7 +70,7 @@ members of the project's leadership. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, -available at [http://contributor-covenant.org/version/1/4][version] +available at [][version] [homepage]: http://contributor-covenant.org [version]: http://contributor-covenant.org/version/1/4/ diff --git a/vendor/github.com/go-openapi/jsonreference/CONTRIBUTORS.md b/vendor/github.com/go-openapi/jsonreference/CONTRIBUTORS.md new file mode 100644 index 000000000..d20737c94 --- /dev/null +++ b/vendor/github.com/go-openapi/jsonreference/CONTRIBUTORS.md @@ -0,0 +1,21 @@ +# Contributors + +- Repository: ['go-openapi/jsonreference'] + +| Total Contributors | Total Contributions | +| --- | --- | +| 9 | 83 | + +| Username | All Time Contribution Count | All Commits | +| --- | --- | --- | +| @fredbi | 46 | | +| @casualjim | 25 | | +| @youyuanwu | 5 | | +| @olivierlemasle | 2 | | +| @apelisse | 1 | | +| @gbjk | 1 | | +| @honza | 1 | | +| @Neo2308 | 1 | | +| @erraggy | 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/jsonreference/NOTICE b/vendor/github.com/go-openapi/jsonreference/NOTICE index f9ad7e0f7..814e87ef8 100644 --- a/vendor/github.com/go-openapi/jsonreference/NOTICE +++ b/vendor/github.com/go-openapi/jsonreference/NOTICE @@ -3,19 +3,22 @@ Copyright 2015-2025 go-swagger maintainers // SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers // SPDX-License-Identifier: Apache-2.0 -This software library, github.com/go-openapi/jsonpointer, includes software developed +This software library, github.com/go-openapi/jsonreference, includes software developed by the go-swagger and go-openapi maintainers ("go-swagger maintainers"). Licensed under the Apache License, Version 2.0 (the "License"); you may not use this software except in compliance with the License. + You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0. + This software is copied from, derived from, and inspired by other original software products. It ships with copies of other software which license terms are recalled below. -The original sofware was authored on 25-02-2013 by sigu-399 (https://github.com/sigu-399, sigu.399@gmail.com). +The original software was authored on 25-02-2013 by sigu-399 (https://github.com/sigu-399, sigu.399@gmail.com). -github.com/sigh-399/jsonpointer +github.com/sigh-399/jsonreference =========================== // SPDX-FileCopyrightText: Copyright 2013 sigu-399 ( https://github.com/sigu-399 ) diff --git a/vendor/github.com/go-openapi/jsonreference/README.md b/vendor/github.com/go-openapi/jsonreference/README.md index 2274a4b78..fbd16cf89 100644 --- a/vendor/github.com/go-openapi/jsonreference/README.md +++ b/vendor/github.com/go-openapi/jsonreference/README.md @@ -1,22 +1,63 @@ -# gojsonreference [![Build Status](https://github.com/go-openapi/jsonreference/actions/workflows/go-test.yml/badge.svg)](https://github.com/go-openapi/jsonreference/actions?query=workflow%3A"go+test") [![codecov](https://codecov.io/gh/go-openapi/jsonreference/branch/master/graph/badge.svg)](https://codecov.io/gh/go-openapi/jsonreference) +# jsonreference -[![Slack Status](https://slackin.goswagger.io/badge.svg)](https://slackin.goswagger.io) -[![license](http://img.shields.io/badge/license-Apache%20v2-orange.svg)](https://raw.githubusercontent.com/go-openapi/jsonreference/master/LICENSE) -[![Go Reference](https://pkg.go.dev/badge/github.com/go-openapi/jsonreference.svg)](https://pkg.go.dev/github.com/go-openapi/jsonreference) -[![Go Report Card](https://goreportcard.com/badge/github.com/go-openapi/jsonreference)](https://goreportcard.com/report/github.com/go-openapi/jsonreference) + +[![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] -An implementation of JSON Reference - Go language +--- + +An implementation of JSON Reference for golang. + +## Announcements + +* **2026-07-07** : landing v1.0.0 + * stable API pledge ## Status -Feature complete. Stable API + +API is stable. + +## Import this library in your project + +```cmd +go get github.com/go-openapi/jsonreference +``` ## Dependencies -* https://github.com/go-openapi/jsonpointer + +* + +## Basic usage + +```go +// Creating a new reference +ref, err := jsonreference.New("http://example.com/doc.json#/definitions/Pet") + +// Fragment-only reference +fragRef := jsonreference.MustCreateRef("#/definitions/Pet") + +// Resolving references +parent, _ := jsonreference.New("http://example.com/base.json") +child, _ := jsonreference.New("#/definitions/Pet") +resolved, _ := parent.Inherits(child) +// Result: "http://example.com/base.json#/definitions/Pet" +``` + + +## Change log + +See ## References -* http://tools.ietf.org/html/draft-ietf-appsawg-json-pointer-07 -* http://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03 +* +* ## Licensing @@ -24,3 +65,59 @@ This library ships under the [SPDX-License-Identifier: Apache-2.0](./LICENSE). See the license [NOTICE](./NOTICE), which recalls the licensing terms of all the pieces of software on top of which it has been built. + +## 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/jsonreference/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/jsonreference/actions/workflows/go-test.yml/badge.svg +[test-url]: https://github.com/go-openapi/jsonreference/actions/workflows/go-test.yml +[cov-badge]: https://codecov.io/gh/go-openapi/jsonreference/branch/master/graph/badge.svg +[cov-url]: https://codecov.io/gh/go-openapi/jsonreference +[vuln-scan-badge]: https://github.com/go-openapi/jsonreference/actions/workflows/scanner.yml/badge.svg +[vuln-scan-url]: https://github.com/go-openapi/jsonreference/actions/workflows/scanner.yml +[codeql-badge]: https://github.com/go-openapi/jsonreference/actions/workflows/codeql.yml/badge.svg +[codeql-url]: https://github.com/go-openapi/jsonreference/actions/workflows/codeql.yml + +[release-badge]: https://badge.fury.io/gh/go-openapi%2Fjsonreference.svg +[release-url]: https://badge.fury.io/gh/go-openapi%2Fjsonreference +[gomod-badge]: https://badge.fury.io/go/github.com%2Fgo-openapi%2Fjsonreference.svg +[gomod-url]: https://badge.fury.io/go/github.com%2Fgo-openapi%2Fjsonreference + +[gocard-badge]: https://goreportcard.com/badge/github.com/go-openapi/jsonreference +[gocard-url]: https://goreportcard.com/report/github.com/go-openapi/jsonreference +[codefactor-badge]: https://img.shields.io/codefactor/grade/github/go-openapi/jsonreference +[codefactor-url]: https://www.codefactor.io/repository/github/go-openapi/jsonreference + +[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/jsonreference +[godoc-url]: http://pkg.go.dev/github.com/go-openapi/jsonreference +[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/jsonreference/?tab=Apache-2.0-1-ov-file#readme + +[goversion-badge]: https://img.shields.io/github/go-mod/go-version/go-openapi/jsonreference +[goversion-url]: https://github.com/go-openapi/jsonreference/blob/master/go.mod +[top-badge]: https://img.shields.io/github/languages/top/go-openapi/jsonreference +[commits-badge]: https://img.shields.io/github/commits-since/go-openapi/jsonreference/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/jsonreference/SECURITY.md b/vendor/github.com/go-openapi/jsonreference/SECURITY.md new file mode 100644 index 000000000..1fea2c573 --- /dev/null +++ b/vendor/github.com/go-openapi/jsonreference/SECURITY.md @@ -0,0 +1,37 @@ +# 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/jsonreference/internal/normalize_url.go b/vendor/github.com/go-openapi/jsonreference/internal/normalize_url.go index ca79391dc..a08b47320 100644 --- a/vendor/github.com/go-openapi/jsonreference/internal/normalize_url.go +++ b/vendor/github.com/go-openapi/jsonreference/internal/normalize_url.go @@ -14,9 +14,11 @@ const ( defaultHTTPSPort = ":443" ) -// Regular expressions used by the normalizations -var rxPort = regexp.MustCompile(`(:\d+)/?$`) -var rxDupSlashes = regexp.MustCompile(`/{2,}`) +// Regular expressions used by the normalizations. +var ( + rxPort = regexp.MustCompile(`(:\d+)/?$`) + rxDupSlashes = regexp.MustCompile(`/{2,}`) +) // NormalizeURL will normalize the specified URL // This was added to replace a previous call to the no longer maintained purell library: diff --git a/vendor/github.com/go-openapi/jsonreference/reference.go b/vendor/github.com/go-openapi/jsonreference/reference.go index 33d4798ca..003ba7a83 100644 --- a/vendor/github.com/go-openapi/jsonreference/reference.go +++ b/vendor/github.com/go-openapi/jsonreference/reference.go @@ -16,9 +16,10 @@ const ( fragmentRune = `#` ) +// ErrChildURL is raised when there is no child. var ErrChildURL = errors.New("child url is nil") -// Ref represents a json reference object +// Ref represents a json reference object. type Ref struct { referenceURL *url.URL referencePointer jsonpointer.Pointer @@ -30,7 +31,7 @@ type Ref struct { HasFullFilePath bool } -// New creates a new reference for the given string +// New creates a new reference for the given string. func New(jsonReferenceString string) (Ref, error) { var r Ref err := r.parse(jsonReferenceString) @@ -38,7 +39,7 @@ func New(jsonReferenceString string) (Ref, error) { } // MustCreateRef parses the ref string and panics when it's invalid. -// Use the New method for a version that returns an error +// Use the New method for a version that returns an error. func MustCreateRef(ref string) Ref { r, err := New(ref) if err != nil { @@ -48,17 +49,17 @@ func MustCreateRef(ref string) Ref { return r } -// GetURL gets the URL for this reference +// GetURL gets the URL for this reference. func (r *Ref) GetURL() *url.URL { return r.referenceURL } -// GetPointer gets the json pointer for this reference +// GetPointer gets the json pointer for this reference. func (r *Ref) GetPointer() *jsonpointer.Pointer { return &r.referencePointer } -// String returns the best version of the url for this reference +// String returns the best version of the url for this reference. func (r *Ref) String() string { if r.referenceURL != nil { return r.referenceURL.String() @@ -71,7 +72,7 @@ func (r *Ref) String() string { return r.referencePointer.String() } -// IsRoot returns true if this reference is a root document +// IsRoot returns true if this reference is a root document. func (r *Ref) IsRoot() bool { return r.referenceURL != nil && !r.IsCanonical() && @@ -79,13 +80,13 @@ func (r *Ref) IsRoot() bool { r.referenceURL.Fragment == "" } -// IsCanonical returns true when this pointer starts with http(s):// or file:// +// IsCanonical returns true when this pointer starts with http(s):// or file://. func (r *Ref) IsCanonical() bool { return (r.HasFileScheme && r.HasFullFilePath) || (!r.HasFileScheme && r.HasFullURL) } // Inherits creates a new reference from a parent and a child -// If the child cannot inherit from the parent, an error is returned +// If the child cannot inherit from the parent, an error is returned. func (r *Ref) Inherits(child Ref) (*Ref, error) { childURL := child.GetURL() parentURL := r.GetURL() @@ -103,7 +104,7 @@ func (r *Ref) Inherits(child Ref) (*Ref, error) { return &ref, nil } -// "Constructor", parses the given string JSON reference +// "Constructor", parses the given string JSON reference. func (r *Ref) parse(jsonReferenceString string) error { parsed, err := url.Parse(jsonReferenceString) if err != nil { 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/.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 c4b1b64f0..000000000 --- a/vendor/github.com/go-openapi/swag/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -secrets.yml -vendor -Godeps -.idea -*.out 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 4129e7e57..000000000 --- a/vendor/github.com/go-openapi/swag/.golangci.yml +++ /dev/null @@ -1,77 +0,0 @@ -version: "2" -linters: - default: all - disable: - - cyclop - - depguard - - errchkjson - - errorlint - - exhaustruct - - forcetypeassert - - funlen - - gochecknoglobals - - gochecknoinits - - gocognit - - godot - - godox - - gomoddirectives - - gosmopolitan - - inamedparam - - intrange - - ireturn - - lll - - musttag - - 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 9322b065e..000000000 --- a/vendor/github.com/go-openapi/swag/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,74 +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 ivan+abuse@flanders.co.nz. 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 [http://contributor-covenant.org/version/1/4][version] - -[homepage]: http://contributor-covenant.org -[version]: http://contributor-covenant.org/version/1/4/ 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 786b92fd3..000000000 --- a/vendor/github.com/go-openapi/swag/README.md +++ /dev/null @@ -1,192 +0,0 @@ -# Swag [![Build Status](https://github.com/go-openapi/swag/actions/workflows/go-test.yml/badge.svg)](https://github.com/go-openapi/swag/actions?query=workflow%3A"go+test") [![codecov](https://codecov.io/gh/go-openapi/swag/branch/master/graph/badge.svg)](https://codecov.io/gh/go-openapi/swag) - -[![Slack Status](https://slackin.goswagger.io/badge.svg)](https://slackin.goswagger.io) -[![license](https://img.shields.io/badge/license-Apache%20v2-orange.svg)](https://raw.githubusercontent.com/go-openapi/swag/master/LICENSE) -[![Go Reference](https://pkg.go.dev/badge/github.com/go-openapi/swag.svg)](https://pkg.go.dev/github.com/go-openapi/swag) -[![Go Report Card](https://goreportcard.com/badge/github.com/go-openapi/swag)](https://goreportcard.com/report/github.com/go-openapi/swag) - -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** -> `swag` is one of the foundational building blocks of the go-openapi initiative. -> Most repositories in `github.com/go-openapi/...` depend on it in some way. -> And so does our CLI tool `github.com/go-swagger/go-swagger`, -> as well as the code generated by this tool. - -* [Contents](#contents) -* [Dependencies](#dependencies) -* [Release Notes](#release-notes) -* [Note to contributors](#note-to-contributors) -* [TODOs, suggestions and plans](#todos-suggestions-and-plans) - -## Contents - -`go-openapi/swag` exposes a collection of relatively independent modules. - -Moving forward, no additional feature will be added to the `swag` API directly at the root package level, -which remains there for backward-compatibility purposes. All exported top-level features are now deprecated. - -Child modules will continue to evolve and some new ones may be added in the future. - -| Module | Content | Main features | -|---------------|---------|---------------| -| `cmdutils` | utilities to work with CLIs || -| `conv` | type conversion utilities | convert between values and pointers for any types
convert from string to builtin types (wraps `strconv`)
require `./typeutils` (test dependency)
| -| `fileutils` | file utilities | | -| `jsonname` | JSON utilities | infer JSON names from `go` properties
| -| `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
| -| `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` - -## Release notes - -### v0.25.1 - -* fixes a data race that could occur when using the standard library implementation of a JSON ordered map - -### v0.25.0 - -**New with this release**: - -* requires `go1.24`, as iterators are being introduced -* removes the dependency to `mailru/easyjson` by default (#68) - * functionality remains the same, but performance may somewhat degrade for applications - that relied on `easyjson` - * users of the JSON or YAML utilities who want to use `easyjson` as their prefered JSON serializer library - will be able to do so by registering this the corresponding JSON adapter at runtime. See below. - * ordered keys in JSON and YAML objects: this feature used to rely solely on `easyjson`. - With this release, an implementation relying on the standard `encoding/json` is provided. - * an independent [benchmark](./jsonutils/adapters/testintegration/benchmarks/README.md) to compare the different adapters -* improves the "float is integer" check (`conv.IsFloat64AJSONInteger`) (#59) -* removes the _direct_ dependency to `gopkg.in/yaml.v3` (indirect dependency is still incurred through `stretchr/testify`) (#127) -* exposed `conv.IsNil()` (previously kept private): a safe nil check (accounting for the "non-nil interface with nil value" nonsensical go trick) - -**What coming next?** - -Moving forward, we want to : -* provide an implementation of the JSON adapter based on `encoding/json/v2`, for `go1.25` builds. -* provide similar implementations for `goccy/go-json` and `jsoniterator/go`, and perhaps some other - similar libraries may be interesting too. - - -**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/json" - - func init() { - json.Register() - } - ``` - -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. - -### v0.24.0 - -With this release, we have largely modernized the API of `swag`: - -* The traditional `swag` API is still supported: code that imports `swag` will still - compile and work the same. -* A deprecation notice is published to encourage consumers of this library to adopt - the newer API -* **Deprecation notice** - * configuration through global variables is now deprecated, in favor of options passed as parameters - * all helper functions are moved to more specialized packages, which are exposed as - go modules. Importing such a module would reduce the footprint of dependencies. - * _all_ functions, variables, constants exposed by the deprecated API have now moved, so - that consumers of the new API no longer need to import github.com/go-openapi/swag, but - should import the desired sub-module(s). - -**New with this release**: - -* [x] type converters and pointer to value helpers now support generic types -* [x] name mangling now support pluralized initialisms (issue #46) - Strings like "contact IDs" are now recognized as such a plural form and mangled as a linter would expect. -* [x] performance: small improvements to reduce the overhead of convert/format wrappers (see issues #110, or PR #108) -* [x] performance: name mangling utilities run ~ 10% faster (PR #115) - ---- - -## Note to contributors - -A mono-repo structure comes with some unavoidable extra pains... - -* Testing - -> The usual `go test ./...` command, run from the root of this repo won't work any longer to test all submodules. -> -> Each module constitutes an independant unit of test. So you have to run `go test` inside each module. -> Or you may take a look at how this is achieved by CI -> [here] https://github.com/go-openapi/swag/blob/master/.github/workflows/go-test.yml). -> -> There are also some alternative tricks using `go work`, for local development, if you feel comfortable with -> go workspaces. Perhaps some day, we'll have a `go work test` to run all tests without any hack. - -* Releasing - -> Each module follows its own independant module versioning. -> -> So you have tags like `mangling/v0.24.0`, `fileutils/v0.24.0` etc that are used by `go mod` and `go get` -> to refer to the tagged version of each module specifically. -> -> This means we may release patches etc to each module independently. -> -> We'd like to adopt the rule that modules in this repo would only differ by a patch version -> (e.g. `v0.24.5` vs `v0.24.3`), and we'll level all modules whenever a minor version is introduced. -> -> A script in `./hack` is provided to tag all modules with the same version in one go. - -* Continuous integration - -> At this moment, all tests in all modules are systematically run over the full test matrix (3 platform x 2 go releases). -> This generates quite a lot of jobs. -> -> We ought to reduce the number of jobs required to test a PR focused on only a few modules. - -## Todos, suggestions and plans - -All kinds of contributions are welcome. - -A few ideas: - -* [x] Complete the split of dependencies to isolate easyjson from the rest -* [x] Improve CI to reduce needed tests -* [x] Replace dependency to `gopkg.in/yaml.v3` (`yamlutil`) -* [ ] Improve mangling utilities (improve readability, support for capitalized words, - better word substitution for non-letter symbols...) -* [ ] Move back to this common shared pot a few of the technical features introduced by go-swagger independently - (e.g. mangle go package names, search package with go modules support, ...) -* [ ] Apply a similar mono-repo approach to go-openapi/strfmt which suffer from similar woes: bloated API, - imposed dependency to some database driver. -* [ ] Adapt `go-swagger` (incl. generated code) to the new `swag` API. -* [ ] Factorize some tests, as there is a lot of redundant testing code in `jsonutils` -* [ ] Benchmark & profiling: publish independently the tool built to analyze and chart benchmarks (e.g. similar to `benchvisual`) -* [ ] more thorough testing for nil / null case -* [ ] ci pipeline to manage releases -* [ ] cleaner mockery generation (doesn't work out of the box for all sub-modules) diff --git a/vendor/github.com/go-openapi/swag/TODO.md b/vendor/github.com/go-openapi/swag/TODO.md deleted file mode 100644 index 129888038..000000000 --- a/vendor/github.com/go-openapi/swag/TODO.md +++ /dev/null @@ -1 +0,0 @@ -fix data race https://github.com/go-openapi/swag/actions/runs/17989156861/job/51174860188 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 bc01ec2bb..000000000 --- a/vendor/github.com/go-openapi/swag/cmdutils/cmd_utils.go +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package 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 interface{} -} 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 63ac1d17e..000000000 --- a/vendor/github.com/go-openapi/swag/cmdutils/doc.go +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package 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 1eaf36f15..000000000 --- a/vendor/github.com/go-openapi/swag/cmdutils_iface.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package swag - -import "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/convert.go b/vendor/github.com/go-openapi/swag/conv/convert.go index b9b869854..f205c3913 100644 --- a/vendor/github.com/go-openapi/swag/conv/convert.go +++ b/vendor/github.com/go-openapi/swag/conv/convert.go @@ -1,16 +1,5 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 package conv diff --git a/vendor/github.com/go-openapi/swag/conv/convert_types.go b/vendor/github.com/go-openapi/swag/conv/convert_types.go index 423e8663f..cf4c6495e 100644 --- a/vendor/github.com/go-openapi/swag/conv/convert_types.go +++ b/vendor/github.com/go-openapi/swag/conv/convert_types.go @@ -1,20 +1,13 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 package conv -// The original version of this file, eons ago, was taken from the aws go sdk +// Unlicensed credits (idea, concept) +// +// The idea to convert values to pointers and the other way around, was inspired, eons ago, by the aws go sdk. +// +// Nowadays, all sensible API sdk's expose a similar functionality. // Pointer returns a pointer to the value passed in. func Pointer[T any](v T) *T { diff --git a/vendor/github.com/go-openapi/swag/conv/doc.go b/vendor/github.com/go-openapi/swag/conv/doc.go index b02711f42..1bd6ead6e 100644 --- a/vendor/github.com/go-openapi/swag/conv/doc.go +++ b/vendor/github.com/go-openapi/swag/conv/doc.go @@ -1,16 +1,5 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 // Package conv exposes utilities to convert types. // diff --git a/vendor/github.com/go-openapi/swag/conv/format.go b/vendor/github.com/go-openapi/swag/conv/format.go index db7562a4a..5b87b8e14 100644 --- a/vendor/github.com/go-openapi/swag/conv/format.go +++ b/vendor/github.com/go-openapi/swag/conv/format.go @@ -1,16 +1,5 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 package conv diff --git a/vendor/github.com/go-openapi/swag/conv/sizeof.go b/vendor/github.com/go-openapi/swag/conv/sizeof.go index 646f8be9a..494346557 100644 --- a/vendor/github.com/go-openapi/swag/conv/sizeof.go +++ b/vendor/github.com/go-openapi/swag/conv/sizeof.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + package conv import "unsafe" diff --git a/vendor/github.com/go-openapi/swag/conv/type_constraints.go b/vendor/github.com/go-openapi/swag/conv/type_constraints.go index 3c6149836..81135e827 100644 --- a/vendor/github.com/go-openapi/swag/conv/type_constraints.go +++ b/vendor/github.com/go-openapi/swag/conv/type_constraints.go @@ -1,16 +1,5 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 package conv 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 9991acb65..000000000 --- a/vendor/github.com/go-openapi/swag/conv_iface.go +++ /dev/null @@ -1,497 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package swag - -import ( - "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 a079fe810..000000000 --- a/vendor/github.com/go-openapi/swag/doc.go +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package swag 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/LICENSE b/vendor/github.com/go-openapi/swag/fileutils/LICENSE deleted file mode 100644 index d64569567..000000000 --- a/vendor/github.com/go-openapi/swag/fileutils/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/fileutils/doc.go b/vendor/github.com/go-openapi/swag/fileutils/doc.go deleted file mode 100644 index 4b48e7196..000000000 --- a/vendor/github.com/go-openapi/swag/fileutils/doc.go +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package 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 b17eaba58..000000000 --- a/vendor/github.com/go-openapi/swag/fileutils/file.go +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package 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 0de77e12d..000000000 --- a/vendor/github.com/go-openapi/swag/fileutils/path.go +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package 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 0c639e8c1..000000000 --- a/vendor/github.com/go-openapi/swag/fileutils_iface.go +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package swag - -import "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 1e537f074..000000000 --- a/vendor/github.com/go-openapi/swag/go.work +++ /dev/null @@ -1,20 +0,0 @@ -use ( - . - ./cmdutils - ./conv - ./fileutils - ./jsonname - ./jsonutils - ./jsonutils/adapters/easyjson - ./jsonutils/adapters/testintegration - ./jsonutils/adapters/testintegration/benchmarks - ./jsonutils/fixtures_test - ./loading - ./mangling - ./netutils - ./stringutils - ./typeutils - ./yamlutils -) - -go 1.24.0 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 bee4481a7..000000000 --- a/vendor/github.com/go-openapi/swag/go.work.sum +++ /dev/null @@ -1,4 +0,0 @@ -github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= -github.com/stretchr/testify v1.11.0/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= -go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= -go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= diff --git a/vendor/github.com/go-openapi/swag/jsonname/doc.go b/vendor/github.com/go-openapi/swag/jsonname/doc.go deleted file mode 100644 index b2e0c80fc..000000000 --- a/vendor/github.com/go-openapi/swag/jsonname/doc.go +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package jsonname is a provider of json property names from go properties. -package jsonname 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 555369d75..000000000 --- a/vendor/github.com/go-openapi/swag/jsonname_iface.go +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package swag - -import ( - "github.com/go-openapi/swag/jsonname" -) - -// DefaultJSONNameProvider is the default cache for types -// -// Deprecated: use [jsonname.DefaultJSONNameProvider] instead. -var DefaultJSONNameProvider = jsonname.DefaultJSONNameProvider - -// NameProvider represents an object capable of translating from go property names -// to json property names. -// -// Deprecated: use [jsonname.NameProvider] instead. -type NameProvider = jsonname.NameProvider - -// NewNameProvider creates a new name provider -// -// Deprecated: use [jsonname.NewNameProvider] instead. -func NewNameProvider() *NameProvider { return jsonname.NewNameProvider() } diff --git a/vendor/github.com/go-openapi/swag/jsonutils/README.md b/vendor/github.com/go-openapi/swag/jsonutils/README.md index c8d0cab67..07a2ca1d7 100644 --- a/vendor/github.com/go-openapi/swag/jsonutils/README.md +++ b/vendor/github.com/go-openapi/swag/jsonutils/README.md @@ -1,11 +1,11 @@ - # jsonutils +# jsonutils `jsonutils` exposes a few tools to work with JSON: - a fast, simple `Concat` to concatenate (not merge) JSON objects and arrays - `FromDynamicJSON` to convert a data structure into a "dynamic JSON" data structure - `ReadJSON` and `WriteJSON` behave like `json.Unmarshal` and `json.Marshal`, - with the ability to use another underlying serialization library through an `Adapter` + with the ability to use another underlying serialization library through an `Adapter` configured at runtime - a `JSONMapSlice` structure that may be used to store JSON objects with the order of keys maintained @@ -64,7 +64,7 @@ find a registered implementation that support ordered keys in objects. Our standard library implementation supports this. As of `v0.25.0`, we support through such an adapter the popular `mailru/easyjson` -library, which kicks in when the passed values support the `easyjson.Unmarshaler` +library, which kicks in when the passed values support the `easyjson.Unmarshaler` or `easyjson.Marshaler` interfaces. In the future, we plan to add more similar libraries that compete on the go JSON @@ -77,8 +77,9 @@ In package `github.com/go-openapi/swag/easyjson/adapters`, several adapters are Each adapter is an independent go module. Hence you'll pick its dependencies only if you import it. At this moment we provide: -* `stdlib`: JSON adapter based on the standard library -* `easyjson`: JSON adapter based on the `github.com/mailru/easyyjson` + +- `stdlib`: JSON adapter based on the standard library +- `easyjson`: JSON adapter based on the `github.com/mailru/easyjson` The adapters provide the basic `Marshal` and `Unmarshal` capabilities, plus an implementation of the `MapSlice` pattern. diff --git a/vendor/github.com/go-openapi/swag/jsonutils/adapters/doc.go b/vendor/github.com/go-openapi/swag/jsonutils/adapters/doc.go index dbb38c2f0..76d3898fc 100644 --- a/vendor/github.com/go-openapi/swag/jsonutils/adapters/doc.go +++ b/vendor/github.com/go-openapi/swag/jsonutils/adapters/doc.go @@ -1,16 +1,5 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 // Package adapters exposes a registry of adapters to multiple // JSON serialization libraries. diff --git a/vendor/github.com/go-openapi/swag/jsonutils/adapters/ifaces/doc.go b/vendor/github.com/go-openapi/swag/jsonutils/adapters/ifaces/doc.go index 49649859a..1fd43a1fa 100644 --- a/vendor/github.com/go-openapi/swag/jsonutils/adapters/ifaces/doc.go +++ b/vendor/github.com/go-openapi/swag/jsonutils/adapters/ifaces/doc.go @@ -1,2 +1,5 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + // Package ifaces exposes all interfaces to work with adapters. package ifaces diff --git a/vendor/github.com/go-openapi/swag/jsonutils/adapters/ifaces/ifaces.go b/vendor/github.com/go-openapi/swag/jsonutils/adapters/ifaces/ifaces.go index 4927d872d..7805e5e5e 100644 --- a/vendor/github.com/go-openapi/swag/jsonutils/adapters/ifaces/ifaces.go +++ b/vendor/github.com/go-openapi/swag/jsonutils/adapters/ifaces/ifaces.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + package ifaces import ( diff --git a/vendor/github.com/go-openapi/swag/jsonutils/adapters/ifaces/registry_iface.go b/vendor/github.com/go-openapi/swag/jsonutils/adapters/ifaces/registry_iface.go index d1fe6a0ad..2d6c69f4e 100644 --- a/vendor/github.com/go-openapi/swag/jsonutils/adapters/ifaces/registry_iface.go +++ b/vendor/github.com/go-openapi/swag/jsonutils/adapters/ifaces/registry_iface.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + package ifaces import ( diff --git a/vendor/github.com/go-openapi/swag/jsonutils/adapters/registry.go b/vendor/github.com/go-openapi/swag/jsonutils/adapters/registry.go index b34a23051..3062acaff 100644 --- a/vendor/github.com/go-openapi/swag/jsonutils/adapters/registry.go +++ b/vendor/github.com/go-openapi/swag/jsonutils/adapters/registry.go @@ -1,16 +1,5 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 package adapters diff --git a/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/adapter.go b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/adapter.go index 4df831b62..94185f79c 100644 --- a/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/adapter.go +++ b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/adapter.go @@ -1,21 +1,11 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 package json import ( stdjson "encoding/json" + "fmt" "github.com/go-openapi/swag/jsonutils/adapters/ifaces" "github.com/go-openapi/swag/typeutils" @@ -35,11 +25,16 @@ var ErrStdlib jsonError = "error from the JSON adapter stdlib" var _ ifaces.Adapter = &Adapter{} type Adapter struct { + options } // NewAdapter yields an [ifaces.Adapter] using the standard library. -func NewAdapter() *Adapter { - return &Adapter{} +func NewAdapter(opts ...Option) *Adapter { + var o options + + return &Adapter{ + options: buildOptions(o, opts), + } } func (a *Adapter) Marshal(value any) ([]byte, error) { @@ -51,45 +46,18 @@ func (a *Adapter) Unmarshal(data []byte, value any) error { } func (a *Adapter) OrderedMarshal(value ifaces.Ordered) ([]byte, error) { - w := poolOfWriters.Borrow() - defer func() { - poolOfWriters.Redeem(w) - }() - - if typeutils.IsNil(value) { - w.RawString("null") + w, redeem := poolOfWriters.BorrowWithRedeem() + defer redeem() + w.setBuf() - return w.BuildBytes() - } - - w.RawByte('{') - first := true - for k, v := range value.OrderedItems() { - if first { - first = false - } else { - w.RawByte(',') - } - - w.String(k) - w.RawByte(':') - - switch val := v.(type) { - case ifaces.Ordered: - w.Raw(a.OrderedMarshal(val)) - default: - w.Raw(stdjson.Marshal(v)) - } - } - - w.RawByte('}') + a.orderedMarshal(w, value, 1) return w.BuildBytes() } func (a *Adapter) OrderedUnmarshal(data []byte, value ifaces.SetOrdered) error { var m MapSlice - if err := m.OrderedUnmarshalJSON(data); err != nil { + if err := m.orderedUnmarshalJSON(data, a.maxDepth()); err != nil { return err } @@ -123,4 +91,43 @@ func (a *Adapter) Redeem() { } func (a *Adapter) Reset() { + a.options = options{} +} + +// orderedMarshal writes value to w, tracking the container nesting depth to guard +// against stack overflow on deeply nested structures. +func (a *Adapter) orderedMarshal(w *jwriter, value ifaces.Ordered, depth int) { + if typeutils.IsNil(value) { + w.RawString("null") + + return + } + + if maxDepth := a.maxDepth(); depth > maxDepth { + w.SetErr(fmt.Errorf("maximum nesting depth of %d exceeded: %w", maxDepth, ErrStdlib)) + + return + } + + w.RawByte('{') + first := true + for k, v := range value.OrderedItems() { + if first { + first = false + } else { + w.RawByte(',') + } + + w.String(k) + w.RawByte(':') + + switch val := v.(type) { + case ifaces.Ordered: + a.orderedMarshal(w, val, depth+1) + default: + w.Raw(stdjson.Marshal(v)) + } + } + + w.RawByte('}') } diff --git a/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/doc.go b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/doc.go index 2ff6b212f..5ea1b4404 100644 --- a/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/doc.go +++ b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/doc.go @@ -1,16 +1,5 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 // Package json implements an [ifaces.Adapter] using the standard library. package json diff --git a/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/lexer.go b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/lexer.go index 6d919199d..ac81cbc75 100644 --- a/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/lexer.go +++ b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/lexer.go @@ -1,16 +1,5 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 package json @@ -65,7 +54,7 @@ func (t token) Delim() byte { return 0 } - return byte(r) + return byte(r) //nolint:gosec // delimiter runes are single byte } type tokenKind uint8 @@ -102,6 +91,13 @@ type jlexer struct { // current token next token // started bool + + // depth tracks the current JSON container nesting level, and maxDepth caps it + // to guard against stack-overflow on adversarially deep documents. The standard + // library's streaming [encoding/json.Decoder.Token] API (used here) does not + // enforce the max-depth guard that [encoding/json.Unmarshal] provides, so we do. + depth int + maxDepth int } type bytesReader struct { @@ -141,7 +137,8 @@ var _ io.Reader = &bytesReader{} func newLexer(data []byte) *jlexer { l := &jlexer{ // current: undefToken, - next: undefToken, + next: undefToken, + maxDepth: defaultMaxNestingDepth, } l.buf = &bytesReader{ buf: data, @@ -154,7 +151,11 @@ func newLexer(data []byte) *jlexer { func (l *jlexer) Reset() { l.err = nil l.next = undefToken - // leave l.dec and l.buf alone, since they are replaced at every Borrow + l.depth = 0 + l.maxDepth = defaultMaxNestingDepth + l.dec = nil + // leave l.buf alone, since they are replaced at every Borrow + l.buf = nil } func (l *jlexer) Error() error { @@ -239,6 +240,21 @@ func (l *jlexer) Delim(c byte) { if tok.Delim() != c { l.err = fmt.Errorf("expected delimiter '%q' but got '%q': %w", c, tok.Delim(), ErrStdlib) + + return + } + + // Track container nesting depth centrally: every '{' or '[' opens a level and + // every '}' or ']' closes one. This guards the mutually-recursive unmarshal + // routines (unmarshalObject/unmarshalArray/asInterface) against stack overflow. + switch c { + case '{', '[': + l.depth++ + if l.maxDepth > 0 && l.depth > l.maxDepth { + l.err = fmt.Errorf("maximum nesting depth of %d exceeded: %w", l.maxDepth, ErrStdlib) + } + case '}', ']': + l.depth-- } } @@ -329,3 +345,12 @@ func (l *jlexer) fetchToken() token { return token{Token: jtok} } + +func (l *jlexer) setBuf(data []byte) func() { + rdr, redeemBuf := poolOfReaders.BorrowWithRedeem() + l.buf = rdr + l.buf.buf = data + l.dec = stdjson.NewDecoder(l.buf) // cannot pool, not exposed by the encoding/json API + + return redeemBuf +} diff --git a/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/options.go b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/options.go new file mode 100644 index 000000000..f114f1f1a --- /dev/null +++ b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/options.go @@ -0,0 +1,52 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package json + +// defaultMaxNestingDepth is the default maximum number of nested JSON containers +// ('{' or '[') that the ordered-JSON marshaler and unmarshaler will process before +// returning an error. +// +// It mirrors the limit enforced by the standard library's [encoding/json] decoder +// (see encoding/json's internal maxNestingDepth), which this adapter would otherwise +// not benefit from since it drives [encoding/json.Decoder.Token] directly. +const defaultMaxNestingDepth = 10000 + +// Option selects options for the stdlib adapter. +type Option func(o options) options + +type options struct { + maxNestingDepth int +} + +func buildOptions(o options, opts []Option) options { + for _, apply := range opts { + o = apply(o) + } + + return o +} + +// maxDepth returns the configured maximum nesting depth, or the default when unset. +func (o options) maxDepth() int { + if o.maxNestingDepth <= 0 { + return defaultMaxNestingDepth + } + + return o.maxNestingDepth +} + +// WithMaxNestingDepth sets the maximum number of nested JSON containers accepted +// when marshaling or unmarshaling ordered JSON. +// +// A value <= 0 selects the default (10,000). +// +// This guards against stack-overflow crashes on deeply nested (possibly adversarial) +// JSON documents or in-memory structures. +func WithMaxNestingDepth(depth int) Option { + return func(o options) options { + o.maxNestingDepth = depth + + return o + } +} diff --git a/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/ordered_map.go b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/ordered_map.go index 18e6294e5..a5a8f4b63 100644 --- a/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/ordered_map.go +++ b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/ordered_map.go @@ -1,16 +1,5 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 package json @@ -81,12 +70,11 @@ func (s MapSlice) MarshalJSON() ([]byte, error) { } func (s MapSlice) OrderedMarshalJSON() ([]byte, error) { - w := poolOfWriters.Borrow() - defer func() { - poolOfWriters.Redeem(w) - }() + w, redeem := poolOfWriters.BorrowWithRedeem() + defer redeem() + w.setBuf() - s.marshalObject(w) + s.marshalObject(w, 1) return w.BuildBytes() // this clones data, so it's okay to redeem the writer and its buffer } @@ -99,23 +87,38 @@ func (s *MapSlice) UnmarshalJSON(data []byte) error { } func (s *MapSlice) OrderedUnmarshalJSON(data []byte) error { - l := poolOfLexers.Borrow(data) - defer func() { - poolOfLexers.Redeem(l) - }() + return s.orderedUnmarshalJSON(data, defaultMaxNestingDepth) +} + +func (s *MapSlice) orderedUnmarshalJSON(data []byte, maxDepth int) error { + l, redeem := poolOfLexers.BorrowWithRedeem() + defer redeem() + + redeemBuf := l.setBuf(data) + defer redeemBuf() + + if maxDepth > 0 { + l.maxDepth = maxDepth + } s.unmarshalObject(l) return l.Error() } -func (s MapSlice) marshalObject(w *jwriter) { +func (s MapSlice) marshalObject(w *jwriter, depth int) { if s == nil { w.RawString("null") return } + if depth > defaultMaxNestingDepth { + w.SetErr(fmt.Errorf("maximum nesting depth of %d exceeded: %w", defaultMaxNestingDepth, ErrStdlib)) + + return + } + w.RawByte('{') if len(s) == 0 { @@ -124,11 +127,11 @@ func (s MapSlice) marshalObject(w *jwriter) { return } - s[0].marshalJSON(w) + s[0].marshalJSON(w, depth) for i := 1; i < len(s); i++ { w.RawByte(',') - s[i].marshalJSON(w) + s[i].marshalJSON(w, depth) } w.RawByte('}') @@ -173,9 +176,18 @@ type MapItem struct { Value any } -func (s MapItem) marshalJSON(w *jwriter) { +func (s MapItem) marshalJSON(w *jwriter, depth int) { w.String(s.Key) w.RawByte(':') + + // Recurse internally for nested ordered maps so the depth guard is not lost across + // the stdjson.Marshal boundary (which would reset it and re-enable stack overflow). + if nested, ok := s.Value.(MapSlice); ok { + nested.marshalObject(w, depth+1) + + return + } + w.Raw(stdjson.Marshal(s.Value)) } diff --git a/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/pool.go b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/pool.go index 0f51d3a20..2f06b88e8 100644 --- a/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/pool.go +++ b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/pool.go @@ -1,132 +1,18 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 package json import ( - "encoding/json" - "sync" - "github.com/go-openapi/swag/jsonutils/adapters/ifaces" + "github.com/go-openapi/swag/pools" ) -type adaptersPool struct { - sync.Pool -} - -func (p *adaptersPool) Borrow() *Adapter { - return p.Get().(*Adapter) -} - -func (p *adaptersPool) BorrowIface() ifaces.Adapter { - return p.Get().(*Adapter) -} - -func (p *adaptersPool) Redeem(a *Adapter) { - p.Put(a) -} - -type writersPool struct { - sync.Pool -} - -func (p *writersPool) Borrow() *jwriter { - ptr := p.Get() - - jw := ptr.(*jwriter) - jw.Reset() - - return jw -} - -func (p *writersPool) Redeem(w *jwriter) { - p.Put(w) -} - -type lexersPool struct { - sync.Pool -} - -func (p *lexersPool) Borrow(data []byte) *jlexer { - ptr := p.Get() - - l := ptr.(*jlexer) - l.buf = poolOfReaders.Borrow(data) - l.dec = json.NewDecoder(l.buf) // cannot pool, not exposed by the encoding/json API - l.Reset() - - return l -} - -func (p *lexersPool) Redeem(l *jlexer) { - l.dec = nil - discard := l.buf - l.buf = nil - poolOfReaders.Redeem(discard) - p.Put(l) -} - -type readersPool struct { - sync.Pool -} - -func (p *readersPool) Borrow(data []byte) *bytesReader { - ptr := p.Get() - - b := ptr.(*bytesReader) - b.Reset() - b.buf = data - - return b -} - -func (p *readersPool) Redeem(b *bytesReader) { - p.Put(b) -} - var ( - poolOfAdapters = &adaptersPool{ - Pool: sync.Pool{ - New: func() any { - return NewAdapter() - }, - }, - } - - poolOfWriters = &writersPool{ - Pool: sync.Pool{ - New: func() any { - return newJWriter() - }, - }, - } - - poolOfLexers = &lexersPool{ - Pool: sync.Pool{ - New: func() any { - return newLexer(nil) - }, - }, - } - - poolOfReaders = &readersPool{ - Pool: sync.Pool{ - New: func() any { - return &bytesReader{} - }, - }, - } + poolOfAdapters = pools.New[Adapter]() + poolOfWriters = pools.NewRedeemable[jwriter]() + poolOfLexers = pools.NewRedeemable[jlexer]() + poolOfReaders = pools.NewRedeemable[bytesReader]() ) // BorrowAdapter borrows an [Adapter] from the pool, recycling already allocated instances. @@ -135,10 +21,12 @@ func BorrowAdapter() *Adapter { } // BorrowAdapterIface borrows a stdlib [Adapter] and converts it directly -// to [ifaces.Adapter]. This is useful to avoid further allocations when -// translating the concrete type into an interface. +// to [ifaces.Adapter]. +// +// This is useful to avoid further allocations when translating the concrete type into +// an interface. func BorrowAdapterIface() ifaces.Adapter { - return poolOfAdapters.BorrowIface() + return poolOfAdapters.Borrow() } // RedeemAdapter redeems an [Adapter] to the pool, so it may be recycled. diff --git a/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/register.go b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/register.go index 18bbc3774..0dec85425 100644 --- a/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/register.go +++ b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/register.go @@ -1,16 +1,5 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 package json @@ -21,14 +10,22 @@ import ( "github.com/go-openapi/swag/jsonutils/adapters/ifaces" ) -func Register(dispatcher ifaces.Registrar) { +func Register(dispatcher ifaces.Registrar, opts ...Option) { t := reflect.TypeOf(Adapter{}) + var o options + o = buildOptions(o, opts) + dispatcher.RegisterFor( ifaces.RegistryEntry{ - Who: fmt.Sprintf("%s.%s", t.PkgPath(), t.Name()), - What: ifaces.AllCapabilities, - Constructor: BorrowAdapterIface, - Support: support, + Who: fmt.Sprintf("%s.%s", t.PkgPath(), t.Name()), + What: ifaces.AllCapabilities, + Constructor: func() ifaces.Adapter { + a := BorrowAdapter() + a.options = o + + return a + }, + Support: support, }) } diff --git a/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/writer.go b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/writer.go index 38e9b6e03..c84e02cd8 100644 --- a/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/writer.go +++ b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/writer.go @@ -1,16 +1,5 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 package json @@ -25,17 +14,21 @@ type jwriter struct { err error } -func newJWriter() *jwriter { - buf := make([]byte, 0, sensibleBufferSize) - - return &jwriter{buf: bytes.NewBuffer(buf)} -} - func (w *jwriter) Reset() { - w.buf.Reset() + if w.buf != nil { + w.buf.Reset() + } w.err = nil } +// SetErr records the first error encountered while building the JSON output. +func (w *jwriter) SetErr(err error) { + if w.err != nil { + return + } + w.err = err +} + func (w *jwriter) RawString(s string) { if w.err != nil { return @@ -84,3 +77,12 @@ func (w *jwriter) BuildBytes() ([]byte, error) { return bytes.Clone(w.buf.Bytes()), nil } + +func (w *jwriter) setBuf() { + if w.buf != nil { + return + } + + buf := make([]byte, 0, sensibleBufferSize) + w.buf = bytes.NewBuffer(buf) +} diff --git a/vendor/github.com/go-openapi/swag/jsonutils/concat.go b/vendor/github.com/go-openapi/swag/jsonutils/concat.go index 049d4698b..2068503af 100644 --- a/vendor/github.com/go-openapi/swag/jsonutils/concat.go +++ b/vendor/github.com/go-openapi/swag/jsonutils/concat.go @@ -1,16 +1,5 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 package jsonutils @@ -34,7 +23,7 @@ func init() { // ConcatJSON concatenates multiple json objects or arrays efficiently. // -// Note that [ConcatJSON] performs a very simmple (and fast) concatenation +// Note that [ConcatJSON] performs a very simple (and fast) concatenation // operation: it does not attempt to merge objects. func ConcatJSON(blobs ...[]byte) []byte { if len(blobs) == 0 { diff --git a/vendor/github.com/go-openapi/swag/jsonutils/doc.go b/vendor/github.com/go-openapi/swag/jsonutils/doc.go index 495ef8341..3926cc58d 100644 --- a/vendor/github.com/go-openapi/swag/jsonutils/doc.go +++ b/vendor/github.com/go-openapi/swag/jsonutils/doc.go @@ -1,16 +1,5 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 // Package jsonutils provides helpers to work with JSON. // diff --git a/vendor/github.com/go-openapi/swag/jsonutils/json.go b/vendor/github.com/go-openapi/swag/jsonutils/json.go index a33b89bd4..40753ce03 100644 --- a/vendor/github.com/go-openapi/swag/jsonutils/json.go +++ b/vendor/github.com/go-openapi/swag/jsonutils/json.go @@ -1,16 +1,5 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 package jsonutils diff --git a/vendor/github.com/go-openapi/swag/jsonutils/ordered_map.go b/vendor/github.com/go-openapi/swag/jsonutils/ordered_map.go index 931ce2559..38dd3e244 100644 --- a/vendor/github.com/go-openapi/swag/jsonutils/ordered_map.go +++ b/vendor/github.com/go-openapi/swag/jsonutils/ordered_map.go @@ -1,16 +1,5 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 package jsonutils 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 63e23f0b6..000000000 --- a/vendor/github.com/go-openapi/swag/jsonutils_iface.go +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package swag - -import ( - "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 interface{}) ([]byte, error) { return jsonutils.WriteJSON(data) } - -// ReadJSON reads json data. -// -// Deprecated: use [jsonutils.ReadJSON] instead. -func ReadJSON(data []byte, value interface{}) 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 interface{}, target interface{}) 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 interface{}) interface{} { - var res interface{} - 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 interface{}, -// i.e. objects are represented by map[string]interface{}, arrays by []interface{}, and all -// scalar values are interface{}. -// -// Deprecated: use [jsonutils.FromDynamicJSON] instead. -func FromDynamicJSON(data, target interface{}) 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 62585615e..000000000 --- a/vendor/github.com/go-openapi/swag/loading/doc.go +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package loading provides tools to load a file from http or from a local file system. -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 ca45732a7..000000000 --- a/vendor/github.com/go-openapi/swag/loading/errors.go +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package 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 aadf99913..000000000 --- a/vendor/github.com/go-openapi/swag/loading/json.go +++ /dev/null @@ -1,22 +0,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 bd955535f..000000000 --- a/vendor/github.com/go-openapi/swag/loading/loading.go +++ /dev/null @@ -1,171 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package 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 -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 strings.HasPrefix(pth, "http") { - return remote - } - o := optionsWithDefaults(opts) - _, isEmbedFS := o.fs.(embed.FS) - - return func(p string) ([]byte, error) { - upth, err := url.PathUnescape(p) - if err != nil { - return nil, err - } - - cpth, hasPrefix := strings.CutPrefix(upth, "file://") - if !hasPrefix || isEmbedFS || runtime.GOOS != "windows" { - // crude processing: trim the file:// prefix. This leaves full URIs with a host with a (mostly) unexpected result - // regular file path provided: just normalize slashes - if isEmbedFS { - // on windows, we need to slash the path if FS is an embed FS. - return local(strings.TrimLeft(filepath.ToSlash(cpth), "./")) // remove invalid leading characters for embed FS - } - - return local(filepath.FromSlash(cpth)) - } - - // 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)) - } -} - -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 a51329e93..000000000 --- a/vendor/github.com/go-openapi/swag/loading/options.go +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package loading - -import ( - "io/fs" - "net/http" - "os" - "time" -) - -type ( - // Option provides options for loading a file over HTTP or from a file. - Option func(*options) - - httpOptions struct { - httpTimeout time.Duration - basicAuthUsername string - basicAuthPassword string - customHeaders map[string]string - client *http.Client - } - - fileOptions struct { - fs fs.ReadFileFS - } - - options struct { - httpOptions - fileOptions - } -) - -func (fo fileOptions) ReadFileFunc() func(string) ([]byte, error) { - if fo.fs == nil { - return os.ReadFile - } - - return fo.fs.ReadFile -} - -// WithTimeout sets a timeout for the remote file loader. -// -// The default timeout is 30s. -func WithTimeout(timeout time.Duration) Option { - return func(o *options) { - o.httpTimeout = timeout - } -} - -// WithBasicAuth sets a basic authentication scheme for the remote file loader. -func WithBasicAuth(username, password string) Option { - return func(o *options) { - o.basicAuthUsername = username - o.basicAuthPassword = password - } -} - -// WithCustomHeaders sets custom headers for the remote file loader. -func WithCustomHeaders(headers map[string]string) Option { - return func(o *options) { - if o.customHeaders == nil { - o.customHeaders = make(map[string]string, len(headers)) - } - - for header, value := range headers { - o.customHeaders[header] = value - } - } -} - -// WithHTTClient 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 - } -} - -// WithFileFS sets a file system for the local file loader. -// -// If the provided file system is a [fs.ReadFileFS], the ReadFile function is used. -// Otherwise, ReadFile is wrapped using [fs.ReadFile]. -// -// By default, the file system is the one provided by the os package. -// -// For example, this may be set to consume from an embedded file system, or a rooted FS. -func WithFS(filesystem fs.FS) Option { - return func(o *options) { - if rfs, ok := filesystem.(fs.ReadFileFS); ok { - o.fs = rfs - - return - } - o.fs = readFileFS{FS: filesystem} - } -} - -type readFileFS struct { - fs.FS -} - -func (r readFileFS) ReadFile(name string) ([]byte, error) { - return fs.ReadFile(r.FS, name) -} - -func optionsWithDefaults(opts []Option) options { - const defaultTimeout = 30 * time.Second - - o := options{ - // package level defaults - httpOptions: httpOptions{ - httpTimeout: defaultTimeout, - client: http.DefaultClient, - }, - } - - for _, apply := range opts { - apply(&o) - } - - return o -} 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 40bd2a769..000000000 --- a/vendor/github.com/go-openapi/swag/loading/yaml.go +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package 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) (interface{}, 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 38d825bc5..000000000 --- a/vendor/github.com/go-openapi/swag/loading_iface.go +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package swag - -import ( - "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) (interface{}, error) { - return loading.YAMLData(path) -} - -// loadingOptionsWithDefaults bridges deprecated default settings that use package-level variables, -// with the recommended use of loading.Option. -func loadingOptionsWithDefaults(opts []loading.Option) []loading.Option { - o := []loading.Option{ - loading.WithTimeout(LoadHTTPTimeout), - loading.WithBasicAuth(LoadHTTPBasicAuthUsername, LoadHTTPBasicAuthPassword), - loading.WithCustomHeaders(LoadHTTPCustomHeaders), - } - o = append(o, opts...) - - return o -} 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 6674c63b7..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 dbe806828..000000000 --- a/vendor/github.com/go-openapi/swag/mangling/doc.go +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package 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 cf0786f81..000000000 --- a/vendor/github.com/go-openapi/swag/mangling/initialism_index.go +++ /dev/null @@ -1,268 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package 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 -) - -// 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 02004b4f3..000000000 --- a/vendor/github.com/go-openapi/swag/mangling/name_lexem.go +++ /dev/null @@ -1,197 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package 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 94ae555a7..000000000 --- a/vendor/github.com/go-openapi/swag/mangling/name_mangler.go +++ /dev/null @@ -1,381 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package 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 66ad2e46c..000000000 --- a/vendor/github.com/go-openapi/swag/mangling/options.go +++ /dev/null @@ -1,161 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package 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 d85b40387..000000000 --- a/vendor/github.com/go-openapi/swag/mangling/pools.go +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package 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 40e4a2e0e..000000000 --- a/vendor/github.com/go-openapi/swag/mangling/split.go +++ /dev/null @@ -1,312 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package mangling - -import ( - "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 -) - -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 { - var matches *initialismMatches - - for currentRunePosition, currentRune := range nameRunes { - // recycle these allocations as we loop over runes - // with such recycling, only 2 slices should be allocated per call - // instead of o(n). - newMatches := poolOfMatches.BorrowMatches() - - // check current initialism matches - if matches != nil { // skip first iteration - for _, match := range *matches { - if keepCompleteMatch := match.complete; keepCompleteMatch { - *newMatches = append(*newMatches, match) - - // the match is complete: keep it then move on to next rune - continue - } - - currentMatchRune := match.body[currentRunePosition-match.start] - if currentMatchRune != currentRune { - // failed match, move on to next rune - continue - } - - // try to complete ongoing 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 { - nextRune := nameRunes[currentRunePosition+1] - - // recognize a plural form for this initialism (only simple pluralization is supported) - if nextRune == 's' && match.hasPlural == simplePlural { - // detected a pluralized initialism - match.body = append(match.body, nextRune) - currentRunePosition++ - if currentRunePosition < len(nameRunes)-1 { - nextRune = nameRunes[currentRunePosition+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 - continue - } - } - - // this is a pluralized match: keep it - match.complete = true - match.hasPlural = simplePlural - match.end = currentRunePosition - *newMatches = append(*newMatches, match) - - // match is complete: keep it then move on to next rune - continue - } - - 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 (not necessarily complete) - *newMatches = append(*newMatches, match) - } - } - - // check for new initialism matches - for i, r := range s.initialismsRunes { - if r[0] == currentRune { - *newMatches = append(*newMatches, initialismMatch{ - start: currentRunePosition, - body: r, - complete: false, - hasPlural: s.initialismsPluralForm[i], - }) - } - } - - if matches != nil { - poolOfMatches.RedeemMatches(matches) - } - matches = newMatches - } - - // up to the caller to redeem this last slice - return matches -} - -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 06351434d..000000000 --- a/vendor/github.com/go-openapi/swag/mangling/string_bytes.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package 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 c289dc6bd..000000000 --- a/vendor/github.com/go-openapi/swag/mangling/util.go +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package 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 2d0d07ddb..000000000 --- a/vendor/github.com/go-openapi/swag/mangling_iface.go +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package swag - -import "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 ed6d8a022..000000000 --- a/vendor/github.com/go-openapi/swag/netutils/doc.go +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package 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 3d0182fc5..000000000 --- a/vendor/github.com/go-openapi/swag/netutils/net.go +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package 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 537314e36..000000000 --- a/vendor/github.com/go-openapi/swag/netutils_iface.go +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package swag - -import "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/LICENSE b/vendor/github.com/go-openapi/swag/pools/LICENSE similarity index 100% rename from vendor/github.com/go-openapi/swag/LICENSE rename to vendor/github.com/go-openapi/swag/pools/LICENSE diff --git a/vendor/github.com/go-openapi/swag/pools/README.md b/vendor/github.com/go-openapi/swag/pools/README.md new file mode 100644 index 000000000..1966461cb --- /dev/null +++ b/vendor/github.com/go-openapi/swag/pools/README.md @@ -0,0 +1 @@ +# pools diff --git a/vendor/github.com/go-openapi/swag/pools/debug.go b/vendor/github.com/go-openapi/swag/pools/debug.go new file mode 100644 index 000000000..94415e989 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/pools/debug.go @@ -0,0 +1,17 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package pools + +// TB is the subset of [testing.TB] used by [AssertNoLeaks]. +// +// It is satisfied by *[testing.T] and *[testing.B]. +// +// A local interface is used (rather than importing "testing") so that the +// release build does not pull the testing package — and its flags — into +// production binaries. +type TB interface { + Helper() + Errorf(format string, args ...any) + Logf(format string, args ...any) +} diff --git a/vendor/github.com/go-openapi/swag/pools/debug_off.go b/vendor/github.com/go-openapi/swag/pools/debug_off.go new file mode 100644 index 000000000..9163d6d60 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/pools/debug_off.go @@ -0,0 +1,51 @@ +//go:build !poolsdebug + +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package pools + +// This is the release implementation of the pool instrumentation: it does +// nothing. +// +// tracker is an empty struct, so it adds no field to the pool types and its +// methods inline away to nothing. +// +// Build with -tags poolsdebug to get the instrumented variant (see +// debug_on.go). + +// debugBuild reports whether the pool instrumentation is compiled in (the +// poolsdebug tag). +const debugBuild = false + +// DebugBuild reports whether the pool instrumentation is compiled in (the +// poolsdebug build tag). +// +// It lets a test that must run in both modes skip the parts that are invalid +// under instrumentation — e.g. an allocation-count assertion, since the +// instrumented build allocates a per-borrow tracker. +const DebugBuild = debugBuild + +type tracker[T any] struct{} + +func (tracker[T]) register() {} + +func (tracker[T]) onBorrow(*T) {} + +func (tracker[T]) onRedeem(*T) {} + +func (tracker[T]) borrowRedeemer(_ *T, cached func()) func() { return cached } + +// AssertNoLeaks reports whether every borrowed object has been redeemed across +// all pools. +// +// It is only meaningful in the instrumented build (-tags poolsdebug). +// +// In a release build it is a no-op that always reports true, so the same test +// can run in both modes. +func AssertNoLeaks(TB) bool { return true } + +// ResetTracking clears all recorded borrow/redeem tracking. +// +// This is a no-op in a release build. +func ResetTracking() {} diff --git a/vendor/github.com/go-openapi/swag/pools/debug_on.go b/vendor/github.com/go-openapi/swag/pools/debug_on.go new file mode 100644 index 000000000..64ccc57d3 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/pools/debug_on.go @@ -0,0 +1,237 @@ +//go:build poolsdebug + +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package pools + +import ( + "fmt" + "runtime" + "sync" +) + +// This is the instrumented implementation of the pool tracking, enabled with +// -tags poolsdebug. +// +// Each pool carries a tracker that records, per recycled pointer, whether it is +// currently borrowed or redeemed, together with the call sites of the last +// borrow and redeem. +// It panics loudly (with those call sites) when it detects misuse: +// +// - a double redeem (the same object returned to the pool twice — corrupts sync.Pool); +// - for the redeemable pools, a redeem of a stale borrow (the slot was re-borrowed since — the +// ABA case the production atomic guard cannot catch), thanks to a per-borrow generation; +// - a redeem of an object the pool never handed out; +// - a borrow of an object still checked out (a symptom of an earlier double-Put). +// +// Borrowed-but-never-redeemed objects (leaks) are reported by [AssertNoLeaks]. + +// debugBuild reports whether the pool instrumentation is compiled in (the +// poolsdebug tag). +const debugBuild = true + +// DebugBuild reports whether the pool instrumentation is compiled in (the +// poolsdebug build tag). +// +// See the release-build doc for usage. +const DebugBuild = debugBuild + +type trackStatus uint8 + +const ( + trackBorrowed trackStatus = iota + 1 + trackRedeemed +) + +type trackEntry struct { + status trackStatus + gen uint64 // identifies the current borrow, to detect a redeem racing a re-borrow (ABA) + borrowedAt string + redeemedAt string +} + +type tracker[T any] struct { + mu sync.Mutex + entries map[*T]*trackEntry + nextGen uint64 +} + +func (t *tracker[T]) register() { + t.mu.Lock() + if t.entries == nil { + t.entries = make(map[*T]*trackEntry) + } + t.mu.Unlock() + + registerLeakChecker(t) +} + +// markBorrow records a borrow of ptr and returns its generation. +// +// Caller must hold no lock. +func (t *tracker[T]) markBorrow(ptr *T, site string) uint64 { + t.mu.Lock() + defer t.mu.Unlock() + + e := t.entries[ptr] + if e == nil { + e = &trackEntry{} + t.entries[ptr] = e + } else if e.status == trackBorrowed { + panic(fmt.Sprintf( + "pools: borrow of an object still checked out (borrowed at %s); "+ + "this usually means it was redeemed twice earlier", e.borrowedAt)) + } + + t.nextGen++ + e.status = trackBorrowed + e.gen = t.nextGen + e.borrowedAt = site + + return t.nextGen +} + +// markRedeem validates and records a redeem of ptr. gen is the borrow +// generation the caller is redeeming, or 0 to skip the ABA check (plain +// Pool[T], which has no per-borrow token). +func (t *tracker[T]) markRedeem(ptr *T, gen uint64, site string) { + t.mu.Lock() + defer t.mu.Unlock() + + e := t.entries[ptr] + switch { + case e == nil: + panic("pools: redeem of an object this pool never handed out") + case e.status != trackBorrowed: + panic(fmt.Sprintf("pools: double redeem (first redeemed at %s)", e.redeemedAt)) + case gen != 0 && e.gen != gen: + panic(fmt.Sprintf( + "pools: redeem of a stale borrow (the slot was re-borrowed at %s since this borrow); "+ + "a redeem is racing a re-borrow of the same slot (ABA)", e.borrowedAt)) + } + + e.status = trackRedeemed + e.redeemedAt = site +} + +const stackOffset = 3 + +func (t *tracker[T]) onBorrow(ptr *T) { + t.markBorrow(ptr, caller(stackOffset)) +} + +func (t *tracker[T]) onRedeem(ptr *T) { + t.markRedeem(ptr, 0, caller(stackOffset)) +} + +// borrowRedeemer records the borrow and returns a generation-stamped redeemer +// that validates the redeem (catching double-redeem and ABA) before delegating +// to the cached redeemer. +func (t *tracker[T]) borrowRedeemer(ptr *T, cached func()) func() { + gen := t.markBorrow(ptr, caller(stackOffset)) + + return func() { + t.markRedeem(ptr, gen, caller(stackOffset-1)) + cached() + } +} + +func (t *tracker[T]) checkLeaks(tb TB) bool { + t.mu.Lock() + defer t.mu.Unlock() + + ok := true + for _, e := range t.entries { + if e.status != trackRedeemed { + tb.Logf("pools: object borrowed but never redeemed (borrowed at %s)", e.borrowedAt) + ok = false + } + } + + return ok +} + +func (t *tracker[T]) resetTracking() { + t.mu.Lock() + t.entries = make(map[*T]*trackEntry) + t.nextGen = 0 + t.mu.Unlock() +} + +// leakChecker is the build-erased view of a tracker that the global registry +// holds, so trackers of different element types can be checked uniformly. +type leakChecker interface { + checkLeaks(tb TB) bool + resetTracking() +} + +var ( + registryMu sync.Mutex + registry []leakChecker +) + +func registerLeakChecker(c leakChecker) { + registryMu.Lock() + registry = append(registry, c) + registryMu.Unlock() +} + +// AssertNoLeaks reports whether every borrowed object has been redeemed across +// all pools created so far. +// +// It logs the borrow call site of each leaked object and fails tb when any are +// found. +// +// Typical use, with [ResetTracking] to isolate the test from earlier ones: +// +// func TestX(t *testing.T) { +// pools.ResetTracking() +// t.Cleanup(func() { pools.AssertNoLeaks(t) }) +// // ... exercise code that borrows/redeems ... +// } +func AssertNoLeaks(tb TB) bool { + tb.Helper() + registryMu.Lock() + defer registryMu.Unlock() + + ok := true + for _, c := range registry { + if !c.checkLeaks(tb) { + ok = false + } + } + if !ok { + tb.Errorf("pools: leaked pooled objects detected (borrowed but never redeemed)") + } + + return ok +} + +// ResetTracking clears all recorded borrow/redeem tracking across every pool. +// +// Call it at the start of a test so leaks from earlier tests are not attributed +// to it. +func ResetTracking() { + registryMu.Lock() + defer registryMu.Unlock() + + for _, c := range registry { + c.resetTracking() + } +} + +// caller returns "file:line" of the frame skip levels above caller itself. +func caller(skip int) string { + pc, _, _, ok := runtime.Caller(skip) + if !ok { + return "unknown" + } + fn := runtime.FuncForPC(pc) + if fn == nil { + return "unknown" + } + file, line := fn.FileLine(pc) + + return fmt.Sprintf("%s:%d", file, line) +} diff --git a/vendor/github.com/go-openapi/swag/pools/doc.go b/vendor/github.com/go-openapi/swag/pools/doc.go new file mode 100644 index 000000000..395c24d29 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/pools/doc.go @@ -0,0 +1,26 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +// Package pools provide utilities to recycle allocated objects. +// +// This package provides: +// +// - a generic [Pool] type that wraps [sync.Pool], +// - a [PoolRedeemable] variant that hands out a cached redeem closure, +// - a [PoolSlice] for recycling slices without juggling pointers. +// +// # Debug build +// +// Building with the "poolsdebug" tag (go test -tags poolsdebug ./...) turns on +// instrumentation that tracks every borrow and redeem and panics on misuse: +// +// - double redeem (including the A -> B -> A case for the redeemable pools), +// - redeem of a foreign object, +// - borrow of an object still checked out +// +// It reports the offending call sites. +// +// [AssertNoLeaks] then reports any object borrowed but never redeemed. +// +// The instrumentation is a no-op with zero overhead when the tag is absent. +package pools diff --git a/vendor/github.com/go-openapi/swag/pools/pools.go b/vendor/github.com/go-openapi/swag/pools/pools.go new file mode 100644 index 000000000..d78ea5790 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/pools/pools.go @@ -0,0 +1,410 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package pools + +import ( + "iter" + "slices" + "sync" + "sync/atomic" +) + +// Resettable is an interface for types that want to recycle a clean instance +// from a [Pool]. +// +// When T (or rather *T) implements [Resettable], the pool calls Reset on an +// instance both when it is redeemed and when it is borrowed: +// +// - on redeem, so that no references held by the instance are retained while it sits idle in the +// pool (which would pin a reference graph alive across a GC cycle); +// - on borrow, so that the next borrower receives a clean object regardless of how the instance +// reached the pool. +// +// Reset must be safe to call more than once on the same instance (it runs at +// least twice per cycle). +type Resettable interface { + Reset() +} + +// resetIfResettable calls Reset on v when *T implements [Resettable]. +func resetIfResettable[T any](v *T) { + if r, ok := any(v).(Resettable); ok { + r.Reset() + } +} + +// borrow state of a [redeemable] wrapper, used to detect double-redeem. +const ( + stateIdle uint32 = iota // sitting in the pool (or freshly created), not checked out + stateBorrowed // checked out by a borrower +) + +type redeemable[T any] struct { + inner *T + redeemer func() + // state guards against a double-redeem (the same wrapper Put into the pool + // twice, which would let one object be handed to two borrowers). + // + // It is set to stateBorrowed on borrow and atomically flipped back to + // stateIdle on redeem; a redeem that finds it already idle panics. + state atomic.Uint32 +} + +// redeemPanic is the message raised when a slot is redeemed while already idle. +const redeemPanic = "pools: " + + "double redeem detected (object already returned to the pool); " + + "a borrowed object must be redeemed exactly once" + +// Pool wraps a [sync.Pool] to make it available for any type. +// +// T must be the value type of the pooled object (e.g. Pool[bytes.Buffer]): +// [Pool.Borrow] returns a *T. Using a pointer type as T (e.g. +// Pool[*bytes.Buffer]) would yield a **T and is almost certainly a mistake. +type Pool[T any] struct { + pool sync.Pool + tracker tracker[T] // empty (zero-cost) unless built with the poolsdebug tag +} + +// PoolRedeemable wraps a [sync.Pool] to make it available for any type. +// +// It differs from [Pool] in the way objects are redeemed to the pool: borrowing +// also yields a cached redeem closure, so no closure is allocated at redeem +// time. +type PoolRedeemable[T any] struct { + pool sync.Pool + tracker tracker[redeemable[T]] // empty (zero-cost) unless built with the poolsdebug tag +} + +// New builds a new [Pool] to recycle allocations of type T explicitly using +// [Pool.Redeem] and the allocated pointer. +// +// Freshly allocated instances of type T are set to their zero value; like +// recycled instances they are reset (if [Resettable]) when borrowed, so +// [Pool.Borrow] always yields a clean object. +func New[T any]() *Pool[T] { + p := &Pool[T]{} + p.pool = sync.Pool{ + New: func() any { + return new(T) + }, + } + p.tracker.register() + + return p +} + +// NewRedeemable builds a new redeemable [Pool] to recycle allocations of type +// T, and use the inner redeemer to relinquish objects to the pool. +func NewRedeemable[T any]() *PoolRedeemable[T] { + p := &PoolRedeemable[T]{} + p.pool = sync.Pool{ + New: func() any { + r := &redeemable[T]{inner: new(T)} + r.redeemer = func() { + if !r.state.CompareAndSwap(stateBorrowed, stateIdle) { + panic(redeemPanic) + } + resetIfResettable(r.inner) + p.pool.Put(r) + } + + return r + }, + } + p.tracker.register() + + return p +} + +// Borrow an instance from the pool. +// +// If the type implements [Resettable], the returned instance is reset before +// being handed out, so it is always clean. +func (p *Pool[T]) Borrow() *T { + target := p.pool.Get().(*T) + resetIfResettable(target) + p.tracker.onBorrow(target) + + return target +} + +// Redeem a borrowed instance to the pool. +// +// A nil pointer is ignored (it would otherwise corrupt the pool: a typed-nil +// boxed into an interface is not the nil interface that [sync.Pool.Put] skips). +// +// The instance is reset (if it implements [Resettable]) before being returned +// to the pool. +// After calling Redeem, the caller must drop its reference to ptr: continuing +// to use it is a use-after-redeem bug. +// +// Unlike [PoolRedeemable], this plain pool holds no per-object state, so it +// cannot detect a double-redeem of the same pointer (which corrupts the pool). +// +// Prefer [PoolRedeemable] when you want that guard, or the debug build for full +// tracking. +func (p *Pool[T]) Redeem(ptr *T) { + if ptr == nil { + return + } + p.tracker.onRedeem(ptr) + resetIfResettable(ptr) + p.pool.Put(ptr) +} + +// BorrowWithRedeem borrows an instance from the pool and provides the +// corresponding redeem function. +// +// This is useful for instance to use with defer. +// +// The instance is reset (if it implements [Resettable]) both when borrowed and +// when the returned redeem closure is called. +// After calling the redeem closure, the caller must drop its reference to the +// returned instance. +// +// Calling the redeem closure more than once panics (see [redeemable.state]): a +// borrowed instance must be redeemed exactly once. +func (p *PoolRedeemable[T]) BorrowWithRedeem() (*T, func()) { + container := p.pool.Get().(*redeemable[T]) + container.state.Store(stateBorrowed) + resetIfResettable(container.inner) + + // In release builds borrowRedeemer returns container.redeemer unchanged (zero + // cost). + // Under the poolsdebug tag it returns a generation-stamped wrapper that tracks + // the borrow and detects double-redeem (incl. + // + // ABA), foreign-redeem and leaks. + return container.inner, p.tracker.borrowRedeemer(container, container.redeemer) +} + +// Slice is a struct that wraps a slice []T. +// +// This is useful to borrow and redeem slices from a pool, without having to +// constantly manipulate pointers to the slice. +// +// The wrapper holds the authoritative slice header. +// +// Its mutating methods ([Slice.Append], [Slice.Concat], [Slice.Grow]) return +// the current backing slice for convenience, so it reads as an idiomatic []T. +// +// But the returned slice is only a snapshot of the wrapper's state at that +// moment: if you keep it and grow it yourself with the builtin append and it +// reallocates, the new backing array lives only in your local copy and is NOT +// tracked by the wrapper — it will not be recycled when the wrapper is +// redeemed (and a later borrower would get the old, smaller array). +// +// Rule of thumb: it is fine to read or pass the returned []T to a consumer; but +// if you plan to grow the slice, keep calling the wrapper's methods so the +// growth is tracked and recycled. +type Slice[T any] struct { + length int + inner []T +} + +// Slice returns the inner slice. +// +// Treat the result as a read-only view (for ranging or passing to a consumer), +// valid until the next mutation or redeem. +// To grow or append, use the wrapper methods so the new backing array is +// tracked and recycled (see [Slice]). +func (s *Slice[T]) Slice() []T { + return s.inner +} + +// Grow the inner slice so it can accommodate at least size more elements +// without reallocating, and return the current backing slice. +// +// Growth is tracked by the wrapper, so the enlarged backing array is recycled +// on redeem. +// See [Slice] for the caveat about growing the returned slice yourself. +func (s *Slice[T]) Grow(size int) []T { + s.inner = slices.Grow(s.inner, size) + + return s.inner +} + +func (s *Slice[T]) Len() int { + return len(s.inner) +} + +func (s *Slice[T]) Cap() int { + return cap(s.inner) +} + +// Append elements to the inner slice and return the current backing slice. +// +// This should be preferred to the append builtin if you plan that the slice will +// grow and you want the newly allocated space to be tracked and recycled. +// See [Slice] for the caveat about growing the returned slice yourself. +func (s *Slice[T]) Append(elems ...T) []T { + s.inner = append(s.inner, elems...) + + return s.inner +} + +// Concat another slice to the inner slice and return the current backing slice. +// +// Unlike [slices.Concat], this reuses the inner slice's capacity instead of +// always allocating a fresh backing array. +// See [Slice] for the caveat about growing the returned slice yourself. +func (s *Slice[T]) Concat(slice []T) []T { + s.inner = append(s.inner, slice...) + + return s.inner +} + +// IndexedElems iterates over the inner slice. +func (s *Slice[T]) IndexedElems() iter.Seq2[int, T] { + return func(yield func(int, T) bool) { + for i, elem := range s.inner { + if !yield(i, elem) { + return + } + } + } +} + +// Reset the inner slice to its configured initial length, keeping allocated +// capacity. +// +// All elements are zeroed, so the pool never retains stale element references +// (which would keep a referenced graph alive for slices of pointers) and so a +// [WithLength] slice is handed out clean rather than carrying data from a +// previous borrower. +func (s *Slice[T]) Reset() { + clear(s.inner) + if s.length > cap(s.inner) { + s.inner = slices.Grow(s.inner[:0], s.length) + } + s.inner = s.inner[:s.length] +} + +// Clip removes unused capacity from the inner slice. +func (s *Slice[T]) Clip() { + s.inner = slices.Clip(s.inner) +} + +// resetWithCapacity discards the current backing array and replaces it with a +// fresh one of the configured length and the given capacity. +// +// It is used by a capacity-capped pool to stop recycling an oversized backing +// array (the old array is left for the GC). +func (s *Slice[T]) resetWithCapacity(capacity int) { + s.inner = make([]T, s.length, max(s.length, capacity)) +} + +// PoolSlice is a pool of [Slice[T]]. +// +// [PoolSlice.BorrowWithRedeem] will return an empty inner slice by default. +// This default may be altered using [WithMinimumCapacity]. +// +// Use [PoolSlice.BorrowWithSizeAndRedeem] or [Slice.Grow] to grow the capacity +// of the inner slice. +type PoolSlice[T any] struct { + // redeemable is held as an unexported field rather than embedded, so the + // underlying [PoolRedeemable] and its [sync.Pool] are not part of PoolSlice's + // public surface. + redeemable *PoolRedeemable[Slice[T]] +} + +// PoolSliceOption alters the default settings to allocate new pooled slices +type PoolSliceOption func(*poolSliceOptions) + +type poolSliceOptions struct { + minCapacity int + length int + maxCapacity int +} + +func WithMinimumCapacity(size int) PoolSliceOption { + return func(o *poolSliceOptions) { + o.minCapacity = size + } +} + +// WithMaxCapacity bounds the capacity of recycled slices. +// +// When a borrowed slice has grown past size at redeem time, its (oversized) +// backing array is discarded and replaced with a fresh one sized to the minimum +// capacity, instead of being recycled. +// +// This stops the pool from accumulating large backing arrays after an +// occasional large request, keeping the steady-state memory bounded. +// +// The trade-off: a workload that genuinely needs slices larger than size will +// reallocate on every cycle. +// Set size from the high-water mark you actually expect, not below it. +// A size of 0 (the default) means no cap: grown slices are recycled as-is. +func WithMaxCapacity(size int) PoolSliceOption { + return func(o *poolSliceOptions) { + o.maxCapacity = size + } +} + +// WithLength ensures that the borrowed slices have a fixed given initial +// length. +// +// By default, the borrowed slices are reset to length 0. +func WithLength(size int) PoolSliceOption { + return func(o *poolSliceOptions) { + o.length = size + } +} + +// NewPoolSlice builds a pool to recycle slices of type []T. +func NewPoolSlice[T any](opts ...PoolSliceOption) *PoolSlice[T] { + var o poolSliceOptions + for _, apply := range opts { + apply(&o) + } + + rp := &PoolRedeemable[Slice[T]]{} + rp.pool = sync.Pool{ + New: func() any { + s := &redeemable[Slice[T]]{ + inner: &Slice[T]{ + length: o.length, + inner: make([]T, o.length, max(o.length, o.minCapacity)), + }, + } + + s.redeemer = func() { + if !s.state.CompareAndSwap(stateBorrowed, stateIdle) { + panic(redeemPanic) + } + if o.maxCapacity > 0 && s.inner.Cap() > o.maxCapacity { + s.inner.resetWithCapacity(o.minCapacity) + } else { + s.inner.Reset() + } + rp.pool.Put(s) + } + + return s + }, + } + rp.tracker.register() + + return &PoolSlice[T]{redeemable: rp} +} + +// BorrowWithRedeem returns the slice wrapper and the redeem closure to +// relinquish the allocated wrapper. +// +// The wrapper is reset (elements zeroed, length restored) both on borrow and +// when the redeem closure is called. +// Calling the redeem closure more than once panics. +func (p *PoolSlice[T]) BorrowWithRedeem() (*Slice[T], func()) { + return p.redeemable.BorrowWithRedeem() +} + +// BorrowWithSizeAndRedeem borrows a slice []T from the pool and ensures that +// its capacity is at least the provided size. +func (p *PoolSlice[T]) BorrowWithSizeAndRedeem(size int) (*Slice[T], func()) { + s, redeem := p.BorrowWithRedeem() + s.Grow(size) + + return s, redeem +} 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 1ff96dcbd..000000000 --- a/vendor/github.com/go-openapi/swag/stringutils/collection_formats.go +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package 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 b5d18e517..000000000 --- a/vendor/github.com/go-openapi/swag/stringutils/doc.go +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package 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 086592317..000000000 --- a/vendor/github.com/go-openapi/swag/stringutils/strings.go +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package 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 00d7e0212..000000000 --- a/vendor/github.com/go-openapi/swag/stringutils_iface.go +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package swag - -import "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/doc.go b/vendor/github.com/go-openapi/swag/typeutils/doc.go index 67e49d12e..66bed20df 100644 --- a/vendor/github.com/go-openapi/swag/typeutils/doc.go +++ b/vendor/github.com/go-openapi/swag/typeutils/doc.go @@ -1,16 +1,5 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 // Package typeutils exposes utilities to inspect generic types. package typeutils diff --git a/vendor/github.com/go-openapi/swag/typeutils/types.go b/vendor/github.com/go-openapi/swag/typeutils/types.go index f0ddd3cd3..55487a673 100644 --- a/vendor/github.com/go-openapi/swag/typeutils/types.go +++ b/vendor/github.com/go-openapi/swag/typeutils/types.go @@ -1,16 +1,5 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 package typeutils 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 b104a8040..000000000 --- a/vendor/github.com/go-openapi/swag/typeutils_iface.go +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package swag - -import "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 interface{}) 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 4aeadc224..000000000 --- a/vendor/github.com/go-openapi/swag/yamlutils/doc.go +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package 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 014f227d9..000000000 --- a/vendor/github.com/go-openapi/swag/yamlutils/errors.go +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package 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 af1d7bb51..000000000 --- a/vendor/github.com/go-openapi/swag/yamlutils/ordered_map.go +++ /dev/null @@ -1,313 +0,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) - 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 { - 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 { - 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 := yamlNode(node.Content[i+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) (*yaml.Node, error) { - if typeutils.IsNil(item) { - return &yaml.Node{ - Kind: yaml.ScalarNode, - Value: "null", - }, nil - } - - switch val := item.(type) { - case ifaces.Ordered: - return orderedYAML(val) - - 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) - 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]) - 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) (*yaml.Node, error) { - var n yaml.Node - n.Kind = yaml.MappingNode - for key, value := range val.OrderedItems() { - childNode, err := json2yaml(value) - 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 67fba8fd7..000000000 --- a/vendor/github.com/go-openapi/swag/yamlutils/yaml.go +++ /dev/null @@ -1,222 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package yamlutils - -import ( - json "encoding/json" - "fmt" - "strconv" - - "github.com/go-openapi/swag/jsonutils" - yaml "go.yaml.in/yaml/v3" -) - -// 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) - 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 yamlNode(root *yaml.Node) (any, error) { - switch root.Kind { - case yaml.DocumentNode: - return yamlDocument(root) - case yaml.SequenceNode: - return yamlSequence(root) - case yaml.MappingNode: - return yamlMapping(root) - case yaml.ScalarNode: - return yamlScalar(root) - case yaml.AliasNode: - return yamlNode(root.Alias) - default: - return nil, fmt.Errorf("unsupported YAML node type: %v: %w", root.Kind, ErrYAML) - } -} - -func yamlDocument(node *yaml.Node) (any, error) { - if len(node.Content) != 1 { - return nil, fmt.Errorf("unexpected YAML Document node content length: %d: %w", len(node.Content), ErrYAML) - } - return yamlNode(node.Content[0]) -} - -func yamlMapping(node *yaml.Node) (any, error) { - const sensibleAllocDivider = 2 // nodes concatenate (key,value) sequences - m := make(YAMLMapSlice, len(node.Content)/sensibleAllocDivider) - - if err := m.UnmarshalYAML(node); err != nil { - return nil, err - } - - return m, nil -} - -func yamlSequence(node *yaml.Node) (any, error) { - s := make([]any, 0) - - for i := range len(node.Content) { - v, err := yamlNode(node.Content[i]) - 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) (out any, err error) { - switch in := input.(type) { - case yaml.Node: - return yamlNode(&in) - case *yaml.Node: - return yamlNode(in) - 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) - 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]) - 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 49e646486..000000000 --- a/vendor/github.com/go-openapi/swag/yamlutils_iface.go +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package swag - -import ( - "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 interface{}) (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) (interface{}, 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 7393bacf7..91c369963 100644 --- a/vendor/k8s.io/kube-openapi/pkg/internal/serialization.go +++ b/vendor/k8s.io/kube-openapi/pkg/internal/serialization.go @@ -17,14 +17,15 @@ 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 // flag in order to have stable marshaling. func DeterministicMarshal(in any) ([]byte, error) { - return jsonv2.MarshalOptions{Deterministic: true}.Marshal(jsonv2.EncodeOptions{}, in) + return jsonv2.Marshal(in, jsonv2.Deterministic(true)) } // JSONRefFromMap populates a json reference object if the map v contains a $ref key. 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 0349adf69..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/README.md +++ /dev/null @@ -1,321 +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. - -## 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 the same 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. -We may provide options 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 `RawValue` 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`, `MarshalFull`, `MarshalNext`, `Unmarshal`, -`UnmarshalFull`, and `UnmarshalNext` 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` package. -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, while the upper half contains functionality that assigns -semantic meaning to syntactic data handled by the bottom half. - -In contrast to v1 `encoding/json`, options are represented as separate types -rather than being setter methods on the `Encoder` or `Decoder` types. - -## 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](/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](/diff_test.go#:~:text=TestOmitEmptyOption) | -| The `string` option **does affect** Go bools. | The `string` option **does not affect** Go bools. | [StringOption](/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](/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](/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](/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](/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](/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](/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](/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](/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](/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](/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](/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](/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](/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](/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](/diff_test.go#:~:text=TestMergeComposite) | -| A `time.Duration` is represented as a **JSON number containing the decimal number of nanoseconds**. | A `time.Duration` is represented as a **JSON string containing the formatted duration (e.g., "1h2m3.456s")**. | [TimeDurations](/diff_test.go#:~:text=TestTimeDurations) | -| Unmarshaling a JSON number into a Go float beyond its representation **results in an error**. | Unmarshaling a JSON number into a Go float beyond its representation **uses the closest representable value (e.g., ±`math.MaxFloat`)**. | [MaxFloats](/diff_test.go#:~:text=TestMaxFloats) | -| A Go struct with only unexported fields **can be serialized**. | A Go struct with only unexported fields **cannot be serialized**. | [EmptyStructs](/diff_test.go#:~:text=TestEmptyStructs) | -| A Go struct that embeds an unexported struct type **can sometimes be serialized**. | A Go struct that embeds an unexported struct type **cannot be serialized**. | [EmbedUnexported](/diff_test.go#:~:text=TestEmbedUnexported) | - -See [diff_test.go](/diff_test.go) for details about every change. - -## Performance - -One of the goals of the v2 module is to be more performant than v1. - -Each of the charts below show the performance across -several different JSON implementations: - -* `JSONv1` is `encoding/json` at `v1.18.2` -* `JSONv2` is `github.com/go-json-experiment/json` at `v0.0.0-20220524042235-dd8be80fc4a7` -* `JSONIterator` is `github.com/json-iterator/go` at `v1.1.12` -* `SegmentJSON` is `github.com/segmentio/encoding/json` at `v0.3.5` -* `GoJSON` is `github.com/goccy/go-json` at `v0.9.7` -* `SonicJSON` is `github.com/bytedance/sonic` at `v1.3.0` - -Benchmarks were run across various datasets: - -* `CanadaGeometry` is a GeoJSON (RFC 7946) representation of Canada. - It contains many JSON arrays of arrays of two-element arrays of numbers. -* `CITMCatalog` contains many JSON objects using numeric names. -* `SyntheaFHIR` is sample JSON data from the healthcare industry. - It contains many nested JSON objects with mostly string values, - where the set of unique string values is relatively small. -* `TwitterStatus` is the JSON response from the Twitter API. - It contains a mix of all different JSON kinds, where string values - are a mix of both single-byte ASCII and multi-byte Unicode. -* `GolangSource` is a simple tree representing the Go source code. - It contains many nested JSON objects, each with the same schema. -* `StringUnicode` contains many strings with multi-byte Unicode runes. - -All of the implementations other than `JSONv1` and `JSONv2` make -extensive use of `unsafe`. As such, we expect those to generally be faster, -but at the cost of memory and type safety. `SonicJSON` goes a step even further -and uses just-in-time compilation to generate machine code specialized -for the Go type being marshaled or unmarshaled. -Also, `SonicJSON` does not validate JSON strings for valid UTF-8, -and so gains a notable performance boost on datasets with multi-byte Unicode. -Benchmarks are performed based on the default marshal and unmarshal behavior -of each package. Note that `JSONv2` aims to be safe and correct by default, -which may not be the most performant strategy. - -`JSONv2` has several semantic changes relative to `JSONv1` that -impacts performance: - -1. When marshaling, `JSONv2` no longer sorts the keys of a Go map. - This will improve performance. -2. When marshaling or unmarshaling, `JSONv2` always checks - to make sure JSON object names are unique. - This will hurt performance, but is more correct. -3. When marshaling or unmarshaling, `JSONv2` always - shallow copies the underlying value for a Go interface and - shallow copies the key and value for entries in a Go map. - This is done to keep the value as addressable so that `JSONv2` can - call methods and functions that operate on a pointer receiver. - This will hurt performance, but is more correct. - -All of the charts are unit-less since the values are normalized -relative to `JSONv1`, which is why `JSONv1` always has a value of 1. -A lower value is better (i.e., runs faster). - -Benchmarks were performed on an AMD Ryzen 9 5900X. - -The code for the benchmarks is located at -https://github.com/go-json-experiment/jsonbench. - -### Marshal Performance - -#### Concrete types - -![Benchmark Marshal Concrete](benchmark-marshal-concrete.png) - -* This compares marshal performance when serializing - [from concrete types](/testdata_test.go). -* The `JSONv1` implementation is close to optimal (without the use of `unsafe`). -* Relative to `JSONv1`, `JSONv2` is generally as fast or slightly faster. -* Relative to `JSONIterator`, `JSONv2` is up to 1.3x faster. -* Relative to `SegmentJSON`, `JSONv2` is up to 1.8x slower. -* Relative to `GoJSON`, `JSONv2` is up to 2.0x slower. -* Relative to `SonicJSON`, `JSONv2` is about 1.8x to 3.2x slower - (ignoring `StringUnicode` since `SonicJSON` does not validate UTF-8). -* For `JSONv1` and `JSONv2`, marshaling from concrete types is - mostly limited by the performance of Go reflection. - -#### Interface types - -![Benchmark Marshal Interface](benchmark-marshal-interface.png) - -* This compares marshal performance when serializing from - `any`, `map[string]any`, and `[]any` types. -* Relative to `JSONv1`, `JSONv2` is about 1.5x to 4.2x faster. -* Relative to `JSONIterator`, `JSONv2` is about 1.1x to 2.4x faster. -* Relative to `SegmentJSON`, `JSONv2` is about 1.2x to 1.8x faster. -* Relative to `GoJSON`, `JSONv2` is about 1.1x to 2.5x faster. -* Relative to `SonicJSON`, `JSONv2` is up to 1.5x slower - (ignoring `StringUnicode` since `SonicJSON` does not validate UTF-8). -* `JSONv2` is faster than the alternatives. - One advantange is because it does not sort the keys for a `map[string]any`, - while alternatives (except `SonicJSON` and `JSONIterator`) do sort the keys. - -#### RawValue types - -![Benchmark Marshal Rawvalue](benchmark-marshal-rawvalue.png) - -* This compares performance when marshaling from a `json.RawValue`. - This mostly exercises the underlying encoder and - hides the cost of Go reflection. -* Relative to `JSONv1`, `JSONv2` is about 3.5x to 7.8x faster. -* `JSONIterator` is blazingly fast because - [it does not validate whether the raw value is valid](https://go.dev/play/p/bun9IXQCKRe) - and simply copies it to the output. -* Relative to `SegmentJSON`, `JSONv2` is about 1.5x to 2.7x faster. -* Relative to `GoJSON`, `JSONv2` is up to 2.2x faster. -* Relative to `SonicJSON`, `JSONv2` is up to 1.5x faster. -* Aside from `JSONIterator`, `JSONv2` is generally the fastest. - -### Unmarshal Performance - -#### Concrete types - -![Benchmark Unmarshal Concrete](benchmark-unmarshal-concrete.png) - -* This compares unmarshal performance when deserializing - [into concrete types](/testdata_test.go). -* Relative to `JSONv1`, `JSONv2` is about 1.8x to 5.7x faster. -* Relative to `JSONIterator`, `JSONv2` is about 1.1x to 1.6x slower. -* Relative to `SegmentJSON`, `JSONv2` is up to 2.5x slower. -* Relative to `GoJSON`, `JSONv2` is about 1.4x to 2.1x slower. -* Relative to `SonicJSON`, `JSONv2` is up to 4.0x slower - (ignoring `StringUnicode` since `SonicJSON` does not validate UTF-8). -* For `JSONv1` and `JSONv2`, unmarshaling into concrete types is - mostly limited by the performance of Go reflection. - -#### Interface types - -![Benchmark Unmarshal Interface](benchmark-unmarshal-interface.png) - -* This compares unmarshal performance when deserializing into - `any`, `map[string]any`, and `[]any` types. -* Relative to `JSONv1`, `JSONv2` is about 1.tx to 4.3x faster. -* Relative to `JSONIterator`, `JSONv2` is up to 1.5x faster. -* Relative to `SegmentJSON`, `JSONv2` is about 1.5 to 3.7x faster. -* Relative to `GoJSON`, `JSONv2` is up to 1.3x faster. -* Relative to `SonicJSON`, `JSONv2` is up to 1.5x slower - (ignoring `StringUnicode` since `SonicJSON` does not validate UTF-8). -* Aside from `SonicJSON`, `JSONv2` is generally just as fast - or faster than all the alternatives. - -#### RawValue types - -![Benchmark Unmarshal Rawvalue](benchmark-unmarshal-rawvalue.png) - -* This compares performance when unmarshaling into a `json.RawValue`. - This mostly exercises the underlying decoder and - hides away most of the cost of Go reflection. -* Relative to `JSONv1`, `JSONv2` is about 8.3x to 17.0x faster. -* Relative to `JSONIterator`, `JSONv2` is up to 2.0x faster. -* Relative to `SegmentJSON`, `JSONv2` is up to 1.6x faster or 1.7x slower. -* Relative to `GoJSON`, `JSONv2` is up to 1.9x faster or 2.1x slower. -* Relative to `SonicJSON`, `JSONv2` is up to 2.0x faster - (ignoring `StringUnicode` since `SonicJSON` does not validate UTF-8). -* `JSONv1` takes a - [lexical scanning approach](https://talks.golang.org/2011/lex.slide#1), - which performs a virtual function call for every byte of input. - In contrast, `JSONv2` makes heavy use of iterative and linear parsing logic - (with extra complexity to resume parsing when encountering segmented buffers). -* `JSONv2` is comparable to the alternatives that use `unsafe`. - Generally it is faster, but sometimes it is slower. 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 e6c6216ff..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/arshal.go +++ /dev/null @@ -1,513 +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" - "io" - "reflect" - "sync" -) - -// MarshalOptions configures how Go data is serialized as JSON data. -// The zero value is equivalent to the default marshal settings. -type MarshalOptions struct { - requireKeyedLiterals - nonComparable - - // Marshalers is a list of type-specific marshalers to use. - Marshalers *Marshalers - - // StringifyNumbers specifies that numeric Go types should be serialized - // as a JSON string containing the equivalent JSON number value. - // - // 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. - // Escaping JSON numbers as a JSON string preserves the exact precision. - StringifyNumbers bool - - // DiscardUnknownMembers specifies that marshaling should ignore any - // JSON object members stored in Go struct fields dedicated to storing - // unknown JSON object members. - DiscardUnknownMembers bool - - // 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. - Deterministic bool - - // formatDepth is the depth at which we respect the format flag. - formatDepth int - // format is custom formatting for the value at the specified depth. - format string -} - -// Marshal serializes a Go value as a []byte with default options. -// It is a thin wrapper over MarshalOptions.Marshal. -func Marshal(in any) (out []byte, err error) { - return MarshalOptions{}.Marshal(EncodeOptions{}, in) -} - -// MarshalFull serializes a Go value into an io.Writer with default options. -// It is a thin wrapper over MarshalOptions.MarshalFull. -func MarshalFull(out io.Writer, in any) error { - return MarshalOptions{}.MarshalFull(EncodeOptions{}, out, in) -} - -// Marshal serializes a Go value as a []byte according to the provided -// marshal and encode options. It does not terminate the output with a newline. -// See MarshalNext for details about the conversion of a Go value into JSON. -func (mo MarshalOptions) Marshal(eo EncodeOptions, in any) (out []byte, err error) { - enc := getBufferedEncoder(eo) - defer putBufferedEncoder(enc) - enc.options.omitTopLevelNewline = true - err = mo.MarshalNext(enc, in) - // TODO(https://go.dev/issue/45038): Use bytes.Clone. - return append([]byte(nil), enc.buf...), err -} - -// MarshalFull serializes a Go value into an io.Writer according to the provided -// marshal and encode options. It does not terminate the output with a newline. -// See MarshalNext for details about the conversion of a Go value into JSON. -func (mo MarshalOptions) MarshalFull(eo EncodeOptions, out io.Writer, in any) error { - enc := getStreamingEncoder(out, eo) - defer putStreamingEncoder(enc) - enc.options.omitTopLevelNewline = true - err := mo.MarshalNext(enc, in) - return err -} - -// MarshalNext encodes a Go value as the next JSON value according to -// the provided marshal options. -// -// 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. -// MarshalNext 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 MarshalNext 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 MarshalOptions.Marshalers 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 MarshalerV2, -// then the MarshalNextJSON method is called to encode the value. -// -// - If the value type implements MarshalerV1, -// then the MarshalJSON method is called to encode the value. -// -// - 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 MarshalOptions.StringifyNumbers is specified, 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 MarshalOptions.StringifyNumbers is specified, -// 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. When encoding keys, MarshalOptions.StringifyNumbers -// is automatically applied so that numeric keys encode as JSON strings. -// The Go map is traversed in a non-deterministic order. -// For deterministic encoding, consider using RawValue.Canonicalize. -// If the format is "emitnull", then a nil map is encoded as a JSON null. -// 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. -// 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 resolution. -// If the format matches one of the format constants declared -// in the time package (e.g., RFC1123), then that format is used. -// Otherwise, the format is used as-is with time.Time.Format if non-empty. -// -// - A Go time.Duration is encoded as a JSON string containing the duration -// formatted according to time.Duration.String. -// If the format is "nanos", it is encoded as a JSON number -// containing the number of nanoseconds in the duration. -// -// - 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 -// MarshalNext does not handle them. -// Passing cyclic structures will result in an error. -func (mo MarshalOptions) MarshalNext(out *Encoder, in any) error { - v := reflect.ValueOf(in) - if !v.IsValid() || (v.Kind() == reflect.Pointer && v.IsNil()) { - return out.WriteToken(Null) - } - // Shallow copy non-pointer values to obtain an addressable value. - // It is beneficial to performance to always pass pointers to avoid this. - if v.Kind() != reflect.Pointer { - v2 := reflect.New(v.Type()) - v2.Elem().Set(v) - v = v2 - } - va := addressableValue{v.Elem()} // 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.lookup(marshal, t) - } - if err := marshal(mo, out, va); err != nil { - if !out.options.AllowDuplicateNames { - out.tokens.invalidateDisabledNamespaces() - } - return err - } - return nil -} - -// UnmarshalOptions configures how JSON data is deserialized as Go data. -// The zero value is equivalent to the default unmarshal settings. -type UnmarshalOptions struct { - requireKeyedLiterals - nonComparable - - // Unmarshalers is a list of type-specific unmarshalers to use. - Unmarshalers *Unmarshalers - - // StringifyNumbers specifies that numeric Go types can be deserialized - // from either a JSON number or a JSON string containing a JSON number - // without any surrounding whitespace. - StringifyNumbers bool - - // RejectUnknownMembers specifies that unknown members should be rejected - // when unmarshaling a JSON object, regardless of whether there is a field - // to store unknown members. - RejectUnknownMembers bool - - // formatDepth is the depth at which we respect the format flag. - formatDepth int - // format is custom formatting for the value at the specified depth. - format string -} - -// Unmarshal deserializes a Go value from a []byte with default options. -// It is a thin wrapper over UnmarshalOptions.Unmarshal. -func Unmarshal(in []byte, out any) error { - return UnmarshalOptions{}.Unmarshal(DecodeOptions{}, in, out) -} - -// UnmarshalFull deserializes a Go value from an io.Reader with default options. -// It is a thin wrapper over UnmarshalOptions.UnmarshalFull. -func UnmarshalFull(in io.Reader, out any) error { - return UnmarshalOptions{}.UnmarshalFull(DecodeOptions{}, in, out) -} - -// Unmarshal deserializes a Go value from a []byte according to the -// provided unmarshal and decode options. The output must be a non-nil pointer. -// The input must be a single JSON value with optional whitespace interspersed. -// See UnmarshalNext for details about the conversion of JSON into a Go value. -func (uo UnmarshalOptions) Unmarshal(do DecodeOptions, in []byte, out any) error { - dec := getBufferedDecoder(in, do) - defer putBufferedDecoder(dec) - return uo.unmarshalFull(dec, out) -} - -// UnmarshalFull deserializes a Go value from an io.Reader according to the -// provided unmarshal and decode options. The output must be a non-nil pointer. -// The input must be a single JSON value with optional whitespace interspersed. -// It consumes the entirety of io.Reader until io.EOF is encountered. -// See UnmarshalNext for details about the conversion of JSON into a Go value. -func (uo UnmarshalOptions) UnmarshalFull(do DecodeOptions, in io.Reader, out any) error { - dec := getStreamingDecoder(in, do) - defer putStreamingDecoder(dec) - return uo.unmarshalFull(dec, out) -} -func (uo UnmarshalOptions) unmarshalFull(in *Decoder, out any) error { - switch err := uo.UnmarshalNext(in, out); err { - case nil: - return in.checkEOF() - case io.EOF: - return io.ErrUnexpectedEOF - default: - return err - } -} - -// UnmarshalNext decodes the next JSON value into a Go value according to -// the provided unmarshal options. 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. -// UnmarshalNext 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 UnmarshalOptions.Unmarshalers 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 UnmarshalerV2, -// then the UnmarshalNextJSON method is called to decode the JSON value. -// -// - If the value type implements UnmarshalerV1, -// 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 may also be decoded from a JSON string containing a JSON number -// if UnmarshalOptions.StringifyNumbers is specified. -// 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 may also be decoded from a JSON string containing a JSON number -// if UnmarshalOptions.StringifyNumbers is specified. -// The JSON number is parsed as the closest representable Go float value. -// 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. When decoding keys, -// UnmarshalOptions.StringifyNumbers is automatically applied so that -// numeric keys can decode from JSON strings. 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 only supported format is "emitnull" and has 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 only supported format is "emitnull" and has 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 resolution. -// If the format matches one of the format constants declared in -// the time package (e.g., RFC1123), then that format is used for parsing. -// Otherwise, the format is used as-is with time.Time.Parse if non-empty. -// -// - A Go time.Duration is decoded from a JSON string by -// passing the decoded string to time.ParseDuration. -// If the format is "nanos", it is instead decoded from a JSON number -// containing the number of nanoseconds in the duration. -// -// - 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 (uo UnmarshalOptions) UnmarshalNext(in *Decoder, out any) error { - v := reflect.ValueOf(out) - if !v.IsValid() || v.Kind() != reflect.Pointer || v.IsNil() { - var t reflect.Type - if v.IsValid() { - t = v.Type() - if t.Kind() == reflect.Pointer { - t = t.Elem() - } - } - err := errors.New("value must be passed as a non-nil pointer reference") - return &SemanticError{action: "unmarshal", GoType: t, Err: err} - } - va := addressableValue{v.Elem()} // dereferenced pointer is always addressable - t := va.Type() - - // Lookup and call the unmarshal function for this type. - unmarshal := lookupArshaler(t).unmarshal - if uo.Unmarshalers != nil { - unmarshal, _ = uo.Unmarshalers.lookup(unmarshal, t) - } - if err := unmarshal(uo, in, va); err != nil { - if !in.options.AllowDuplicateNames { - in.tokens.invalidateDisabledNamespaces() - } - return err - } - 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 } - -// newAddressableValue constructs a new addressable value of type t. -func newAddressableValue(t reflect.Type) addressableValue { - return addressableValue{reflect.New(t).Elem()} -} - -// All marshal and unmarshal behavior is implemented using these signatures. -type ( - marshaler = func(MarshalOptions, *Encoder, addressableValue) error - unmarshaler = func(UnmarshalOptions, *Decoder, addressableValue) 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) -} 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 c62b1f320..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/arshal_any.go +++ /dev/null @@ -1,238 +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 "reflect" - -// This files 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. - -func marshalValueAny(mo MarshalOptions, enc *Encoder, val any) error { - switch val := val.(type) { - case nil: - return enc.WriteToken(Null) - case bool: - return enc.WriteToken(Bool(val)) - case string: - return enc.WriteToken(String(val)) - case float64: - return enc.WriteToken(Float(val)) - case map[string]any: - return marshalObjectAny(mo, enc, val) - case []any: - return marshalArrayAny(mo, enc, val) - default: - v := newAddressableValue(reflect.TypeOf(val)) - v.Set(reflect.ValueOf(val)) - marshal := lookupArshaler(v.Type()).marshal - if mo.Marshalers != nil { - marshal, _ = mo.Marshalers.lookup(marshal, v.Type()) - } - return marshal(mo, enc, v) - } -} - -func unmarshalValueAny(uo UnmarshalOptions, dec *Decoder) (any, error) { - switch k := dec.PeekKind(); k { - case '{': - return unmarshalObjectAny(uo, dec) - case '[': - return unmarshalArrayAny(uo, dec) - default: - var flags valueFlags - val, err := dec.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 = unescapeStringMayCopy(val, flags.isVerbatim()) - if dec.stringCache == nil { - dec.stringCache = new(stringCache) - } - return dec.stringCache.make(val), nil - case '0': - fv, _ := parseFloat(val, 64) // ignore error since readValue guarantees val is valid - return fv, nil - default: - panic("BUG: invalid kind: " + k.String()) - } - } -} - -func marshalObjectAny(mo MarshalOptions, enc *Encoder, obj map[string]any) error { - // Check for cycles. - if enc.tokens.depth() > startDetectingCyclesAfter { - v := reflect.ValueOf(obj) - if err := enc.seenPointers.visit(v); err != nil { - return err - } - defer enc.seenPointers.leave(v) - } - - // Optimize for marshaling an empty map without any preceding whitespace. - if len(obj) == 0 && !enc.options.multiline && !enc.tokens.last.needObjectName() { - enc.buf = enc.tokens.mayAppendDelim(enc.buf, '{') - enc.buf = append(enc.buf, "{}"...) - enc.tokens.last.increment() - if enc.needFlush() { - return enc.flush() - } - return nil - } - - if err := enc.WriteToken(ObjectStart); 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 !enc.options.AllowInvalidUTF8 { - enc.tokens.last.disableNamespace() - } - if !mo.Deterministic || len(obj) <= 1 { - for name, val := range obj { - if err := enc.WriteToken(String(name)); err != nil { - return err - } - if err := marshalValueAny(mo, enc, val); 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(String(name)); err != nil { - return err - } - if err := marshalValueAny(mo, enc, obj[name]); err != nil { - return err - } - } - putStrings(names) - } - if err := enc.WriteToken(ObjectEnd); err != nil { - return err - } - return nil -} - -func unmarshalObjectAny(uo UnmarshalOptions, dec *Decoder) (map[string]any, error) { - tok, err := dec.ReadToken() - if err != nil { - return nil, err - } - k := tok.Kind() - switch k { - case 'n': - return nil, nil - case '{': - 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 !dec.options.AllowInvalidUTF8 { - dec.tokens.last.disableNamespace() - } - 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 { - name := dec.previousBuffer() - err := &SyntacticError{str: "duplicate name " + string(name) + " in object"} - return obj, err.withOffset(dec.InputOffset() - int64(len(name))) - } - - val, err := unmarshalValueAny(uo, dec) - obj[name] = val - if err != nil { - return obj, err - } - } - if _, err := dec.ReadToken(); err != nil { - return obj, err - } - return obj, nil - } - return nil, &SemanticError{action: "unmarshal", JSONKind: k, GoType: mapStringAnyType} -} - -func marshalArrayAny(mo MarshalOptions, enc *Encoder, arr []any) error { - // Check for cycles. - if enc.tokens.depth() > startDetectingCyclesAfter { - v := reflect.ValueOf(arr) - if err := enc.seenPointers.visit(v); err != nil { - return err - } - defer enc.seenPointers.leave(v) - } - - // Optimize for marshaling an empty slice without any preceding whitespace. - if len(arr) == 0 && !enc.options.multiline && !enc.tokens.last.needObjectName() { - enc.buf = enc.tokens.mayAppendDelim(enc.buf, '[') - enc.buf = append(enc.buf, "[]"...) - enc.tokens.last.increment() - if enc.needFlush() { - return enc.flush() - } - return nil - } - - if err := enc.WriteToken(ArrayStart); err != nil { - return err - } - for _, val := range arr { - if err := marshalValueAny(mo, enc, val); err != nil { - return err - } - } - if err := enc.WriteToken(ArrayEnd); err != nil { - return err - } - return nil -} - -func unmarshalArrayAny(uo UnmarshalOptions, dec *Decoder) ([]any, error) { - tok, err := dec.ReadToken() - if err != nil { - return nil, err - } - k := tok.Kind() - switch k { - case 'n': - return nil, nil - case '[': - arr := []any{} - for dec.PeekKind() != ']' { - val, err := unmarshalValueAny(uo, dec) - arr = append(arr, val) - if err != nil { - return arr, err - } - } - if _, err := dec.ReadToken(); err != nil { - return arr, err - } - return arr, nil - } - return nil, &SemanticError{action: "unmarshal", JSONKind: k, GoType: sliceAnyType} -} 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 fd26eba35..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/arshal_default.go +++ /dev/null @@ -1,1485 +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/base32" - "encoding/base64" - "encoding/hex" - "errors" - "fmt" - "math" - "reflect" - "sort" - "strconv" - "sync" -) - -// 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.TypeOf((*any)(nil)).Elem() // JSON value - boolType = reflect.TypeOf((*bool)(nil)).Elem() // JSON bool - stringType = reflect.TypeOf((*string)(nil)).Elem() // JSON string - float64Type = reflect.TypeOf((*float64)(nil)).Elem() // JSON number - mapStringAnyType = reflect.TypeOf((*map[string]any)(nil)).Elem() // JSON object - sliceAnyType = reflect.TypeOf((*[]any)(nil)).Elem() // JSON array - - bytesType = reflect.TypeOf((*[]byte)(nil)).Elem() - emptyStructType = reflect.TypeOf((*struct{})(nil)).Elem() -) - -const startDetectingCyclesAfter = 1000 - -type seenPointers map[typedPointer]struct{} - -type typedPointer struct { - typ reflect.Type - ptr any // always stores unsafe.Pointer, but avoids depending on unsafe -} - -// visit visits pointer p of type t, reporting an error if seen before. -// If successfully visited, then the caller must eventually call leave. -func (m *seenPointers) visit(v reflect.Value) error { - p := typedPointer{v.Type(), v.UnsafePointer()} - if _, ok := (*m)[p]; ok { - return &SemanticError{action: "marshal", GoType: p.typ, Err: errors.New("encountered a cycle")} - } - if *m == nil { - *m = make(map[typedPointer]struct{}) - } - (*m)[p] = struct{}{} - return nil -} -func (m *seenPointers) leave(v reflect.Value) { - p := typedPointer{v.Type(), v.UnsafePointer()} - delete(*m, p) -} - -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: - 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.AssignableTo(bytesType) { - return makeBytesArshaler(t, fncs) - } - return fncs - case reflect.Array: - fncs := makeArrayArshaler(t) - if reflect.SliceOf(t.Elem()).AssignableTo(bytesType) { - 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(mo MarshalOptions, enc *Encoder, va addressableValue) error { - if mo.format != "" && mo.formatDepth == enc.tokens.depth() { - return newInvalidFormatError("marshal", t, mo.format) - } - - // Optimize for marshaling without preceding whitespace. - if optimizeCommon && !enc.options.multiline && !enc.tokens.last.needObjectName() { - enc.buf = enc.tokens.mayAppendDelim(enc.buf, 't') - if va.Bool() { - enc.buf = append(enc.buf, "true"...) - } else { - enc.buf = append(enc.buf, "false"...) - } - enc.tokens.last.increment() - if enc.needFlush() { - return enc.flush() - } - return nil - } - - return enc.WriteToken(Bool(va.Bool())) - } - fncs.unmarshal = func(uo UnmarshalOptions, dec *Decoder, va addressableValue) error { - if uo.format != "" && uo.formatDepth == dec.tokens.depth() { - return newInvalidFormatError("unmarshal", t, uo.format) - } - tok, err := dec.ReadToken() - if err != nil { - return err - } - k := tok.Kind() - switch k { - case 'n': - va.SetBool(false) - return nil - case 't', 'f': - va.SetBool(tok.Bool()) - return nil - } - return &SemanticError{action: "unmarshal", JSONKind: k, GoType: t} - } - return &fncs -} - -func makeStringArshaler(t reflect.Type) *arshaler { - var fncs arshaler - fncs.marshal = func(mo MarshalOptions, enc *Encoder, va addressableValue) error { - if mo.format != "" && mo.formatDepth == enc.tokens.depth() { - return newInvalidFormatError("marshal", t, mo.format) - } - return enc.WriteToken(String(va.String())) - } - fncs.unmarshal = func(uo UnmarshalOptions, dec *Decoder, va addressableValue) error { - if uo.format != "" && uo.formatDepth == dec.tokens.depth() { - return newInvalidFormatError("unmarshal", t, uo.format) - } - var flags valueFlags - val, err := dec.readValue(&flags) - if err != nil { - return err - } - k := val.Kind() - switch k { - case 'n': - va.SetString("") - return nil - case '"': - val = unescapeStringMayCopy(val, flags.isVerbatim()) - if dec.stringCache == nil { - dec.stringCache = new(stringCache) - } - str := dec.stringCache.make(val) - va.SetString(str) - return nil - } - return &SemanticError{action: "unmarshal", JSONKind: k, GoType: t} - } - return &fncs -} - -var ( - encodeBase16 = func(dst, src []byte) { hex.Encode(dst, src) } - encodeBase32 = base32.StdEncoding.Encode - encodeBase32Hex = base32.HexEncoding.Encode - encodeBase64 = base64.StdEncoding.Encode - encodeBase64URL = base64.URLEncoding.Encode - encodedLenBase16 = hex.EncodedLen - encodedLenBase32 = base32.StdEncoding.EncodedLen - encodedLenBase32Hex = base32.HexEncoding.EncodedLen - encodedLenBase64 = base64.StdEncoding.EncodedLen - encodedLenBase64URL = base64.URLEncoding.EncodedLen - decodeBase16 = hex.Decode - decodeBase32 = base32.StdEncoding.Decode - decodeBase32Hex = base32.HexEncoding.Decode - decodeBase64 = base64.StdEncoding.Decode - decodeBase64URL = base64.URLEncoding.Decode - decodedLenBase16 = hex.DecodedLen - decodedLenBase32 = base32.StdEncoding.WithPadding(base32.NoPadding).DecodedLen - decodedLenBase32Hex = base32.HexEncoding.WithPadding(base32.NoPadding).DecodedLen - decodedLenBase64 = base64.StdEncoding.WithPadding(base64.NoPadding).DecodedLen - decodedLenBase64URL = base64.URLEncoding.WithPadding(base64.NoPadding).DecodedLen -) - -func makeBytesArshaler(t reflect.Type, fncs *arshaler) *arshaler { - // NOTE: This handles both []byte and [N]byte. - marshalDefault := fncs.marshal - fncs.marshal = func(mo MarshalOptions, enc *Encoder, va addressableValue) error { - encode, encodedLen := encodeBase64, encodedLenBase64 - if mo.format != "" && mo.formatDepth == enc.tokens.depth() { - switch mo.format { - case "base64": - encode, encodedLen = encodeBase64, encodedLenBase64 - case "base64url": - encode, encodedLen = encodeBase64URL, encodedLenBase64URL - case "base32": - encode, encodedLen = encodeBase32, encodedLenBase32 - case "base32hex": - encode, encodedLen = encodeBase32Hex, encodedLenBase32Hex - case "base16", "hex": - encode, encodedLen = encodeBase16, encodedLenBase16 - case "array": - mo.format = "" - return marshalDefault(mo, enc, va) - default: - return newInvalidFormatError("marshal", t, mo.format) - } - } - val := enc.UnusedBuffer() - b := va.Bytes() - n := len(`"`) + encodedLen(len(b)) + len(`"`) - if cap(val) < n { - val = make([]byte, n) - } else { - val = val[:n] - } - val[0] = '"' - encode(val[len(`"`):len(val)-len(`"`)], b) - val[len(val)-1] = '"' - return enc.WriteValue(val) - } - unmarshalDefault := fncs.unmarshal - fncs.unmarshal = func(uo UnmarshalOptions, dec *Decoder, va addressableValue) error { - decode, decodedLen, encodedLen := decodeBase64, decodedLenBase64, encodedLenBase64 - if uo.format != "" && uo.formatDepth == dec.tokens.depth() { - switch uo.format { - case "base64": - decode, decodedLen, encodedLen = decodeBase64, decodedLenBase64, encodedLenBase64 - case "base64url": - decode, decodedLen, encodedLen = decodeBase64URL, decodedLenBase64URL, encodedLenBase64URL - case "base32": - decode, decodedLen, encodedLen = decodeBase32, decodedLenBase32, encodedLenBase32 - case "base32hex": - decode, decodedLen, encodedLen = decodeBase32Hex, decodedLenBase32Hex, encodedLenBase32Hex - case "base16", "hex": - decode, decodedLen, encodedLen = decodeBase16, decodedLenBase16, encodedLenBase16 - case "array": - uo.format = "" - return unmarshalDefault(uo, dec, va) - default: - return newInvalidFormatError("unmarshal", t, uo.format) - } - } - var flags valueFlags - val, err := dec.readValue(&flags) - if err != nil { - return err - } - k := val.Kind() - switch k { - case 'n': - va.Set(reflect.Zero(t)) - return nil - case '"': - val = unescapeStringMayCopy(val, flags.isVerbatim()) - - // For base64 and base32, decodedLen computes the maximum output size - // when given the original input size. To compute the exact size, - // adjust the input size by excluding trailing padding characters. - // This is unnecessary for base16, but also harmless. - n := len(val) - for n > 0 && val[n-1] == '=' { - n-- - } - n = decodedLen(n) - b := va.Bytes() - if va.Kind() == reflect.Array { - if n != len(b) { - err := fmt.Errorf("decoded base64 length of %d mismatches array length of %d", n, len(b)) - return &SemanticError{action: "unmarshal", JSONKind: k, GoType: t, Err: err} - } - } else { - if b == nil || cap(b) < n { - b = make([]byte, n) - } else { - b = b[:n] - } - } - n2, err := decode(b, val) - if err == nil && len(val) != encodedLen(n2) { - // 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. - err = errors.New("illegal data at input byte " + strconv.Itoa(bytes.IndexAny(val, "\r\n"))) - } - if err != nil { - return &SemanticError{action: "unmarshal", JSONKind: k, GoType: t, Err: err} - } - if va.Kind() == reflect.Slice { - va.SetBytes(b) - } - return nil - } - return &SemanticError{action: "unmarshal", JSONKind: k, GoType: t} - } - return fncs -} - -func makeIntArshaler(t reflect.Type) *arshaler { - var fncs arshaler - bits := t.Bits() - fncs.marshal = func(mo MarshalOptions, enc *Encoder, va addressableValue) error { - if mo.format != "" && mo.formatDepth == enc.tokens.depth() { - return newInvalidFormatError("marshal", t, mo.format) - } - - // Optimize for marshaling without preceding whitespace or string escaping. - if optimizeCommon && !enc.options.multiline && !mo.StringifyNumbers && !enc.tokens.last.needObjectName() { - enc.buf = enc.tokens.mayAppendDelim(enc.buf, '0') - enc.buf = strconv.AppendInt(enc.buf, va.Int(), 10) - enc.tokens.last.increment() - if enc.needFlush() { - return enc.flush() - } - return nil - } - - x := math.Float64frombits(uint64(va.Int())) - return enc.writeNumber(x, rawIntNumber, mo.StringifyNumbers) - } - fncs.unmarshal = func(uo UnmarshalOptions, dec *Decoder, va addressableValue) error { - if uo.format != "" && uo.formatDepth == dec.tokens.depth() { - return newInvalidFormatError("unmarshal", t, uo.format) - } - var flags valueFlags - val, err := dec.readValue(&flags) - if err != nil { - return err - } - k := val.Kind() - switch k { - case 'n': - va.SetInt(0) - return nil - case '"': - if !uo.StringifyNumbers { - break - } - val = unescapeStringMayCopy(val, flags.isVerbatim()) - fallthrough - case '0': - var negOffset int - neg := val[0] == '-' - if neg { - negOffset = 1 - } - n, ok := parseDecUint(val[negOffset:]) - maxInt := uint64(1) << (bits - 1) - overflow := (neg && n > maxInt) || (!neg && n > maxInt-1) - if !ok { - if n != math.MaxUint64 { - err := fmt.Errorf("cannot parse %q as signed integer: %w", val, strconv.ErrSyntax) - return &SemanticError{action: "unmarshal", JSONKind: k, GoType: t, Err: err} - } - overflow = true - } - if overflow { - err := fmt.Errorf("cannot parse %q as signed integer: %w", val, strconv.ErrRange) - return &SemanticError{action: "unmarshal", JSONKind: k, GoType: t, Err: err} - } - if neg { - va.SetInt(int64(-n)) - } else { - va.SetInt(int64(+n)) - } - return nil - } - return &SemanticError{action: "unmarshal", JSONKind: k, GoType: t} - } - return &fncs -} - -func makeUintArshaler(t reflect.Type) *arshaler { - var fncs arshaler - bits := t.Bits() - fncs.marshal = func(mo MarshalOptions, enc *Encoder, va addressableValue) error { - if mo.format != "" && mo.formatDepth == enc.tokens.depth() { - return newInvalidFormatError("marshal", t, mo.format) - } - - // Optimize for marshaling without preceding whitespace or string escaping. - if optimizeCommon && !enc.options.multiline && !mo.StringifyNumbers && !enc.tokens.last.needObjectName() { - enc.buf = enc.tokens.mayAppendDelim(enc.buf, '0') - enc.buf = strconv.AppendUint(enc.buf, va.Uint(), 10) - enc.tokens.last.increment() - if enc.needFlush() { - return enc.flush() - } - return nil - } - - x := math.Float64frombits(va.Uint()) - return enc.writeNumber(x, rawUintNumber, mo.StringifyNumbers) - } - fncs.unmarshal = func(uo UnmarshalOptions, dec *Decoder, va addressableValue) error { - if uo.format != "" && uo.formatDepth == dec.tokens.depth() { - return newInvalidFormatError("unmarshal", t, uo.format) - } - var flags valueFlags - val, err := dec.readValue(&flags) - if err != nil { - return err - } - k := val.Kind() - switch k { - case 'n': - va.SetUint(0) - return nil - case '"': - if !uo.StringifyNumbers { - break - } - val = unescapeStringMayCopy(val, flags.isVerbatim()) - fallthrough - case '0': - n, ok := parseDecUint(val) - maxUint := uint64(1) << bits - overflow := n > maxUint-1 - if !ok { - if n != math.MaxUint64 { - err := fmt.Errorf("cannot parse %q as unsigned integer: %w", val, strconv.ErrSyntax) - return &SemanticError{action: "unmarshal", JSONKind: k, GoType: t, Err: err} - } - overflow = true - } - if overflow { - err := fmt.Errorf("cannot parse %q as unsigned integer: %w", val, strconv.ErrRange) - return &SemanticError{action: "unmarshal", JSONKind: k, GoType: t, Err: err} - } - va.SetUint(n) - return nil - } - return &SemanticError{action: "unmarshal", JSONKind: k, GoType: t} - } - return &fncs -} - -func makeFloatArshaler(t reflect.Type) *arshaler { - var fncs arshaler - bits := t.Bits() - fncs.marshal = func(mo MarshalOptions, enc *Encoder, va addressableValue) error { - var allowNonFinite bool - if mo.format != "" && mo.formatDepth == enc.tokens.depth() { - if mo.format == "nonfinite" { - allowNonFinite = true - } else { - return newInvalidFormatError("marshal", t, mo.format) - } - } - - fv := va.Float() - if math.IsNaN(fv) || math.IsInf(fv, 0) { - if !allowNonFinite { - err := fmt.Errorf("invalid value: %v", fv) - return &SemanticError{action: "marshal", GoType: t, Err: err} - } - return enc.WriteToken(Float(fv)) - } - - // Optimize for marshaling without preceding whitespace or string escaping. - if optimizeCommon && !enc.options.multiline && !mo.StringifyNumbers && !enc.tokens.last.needObjectName() { - enc.buf = enc.tokens.mayAppendDelim(enc.buf, '0') - enc.buf = appendNumber(enc.buf, fv, bits) - enc.tokens.last.increment() - if enc.needFlush() { - return enc.flush() - } - return nil - } - - return enc.writeNumber(fv, bits, mo.StringifyNumbers) - } - fncs.unmarshal = func(uo UnmarshalOptions, dec *Decoder, va addressableValue) error { - var allowNonFinite bool - if uo.format != "" && uo.formatDepth == dec.tokens.depth() { - if uo.format == "nonfinite" { - allowNonFinite = true - } else { - return newInvalidFormatError("unmarshal", t, uo.format) - } - } - var flags valueFlags - val, err := dec.readValue(&flags) - if err != nil { - return err - } - k := val.Kind() - switch k { - case 'n': - va.SetFloat(0) - return nil - case '"': - val = unescapeStringMayCopy(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 !uo.StringifyNumbers { - break - } - if n, err := consumeNumber(val); n != len(val) || err != nil { - err := fmt.Errorf("cannot parse %q as JSON number: %w", val, strconv.ErrSyntax) - return &SemanticError{action: "unmarshal", JSONKind: k, GoType: t, Err: err} - } - fallthrough - case '0': - // NOTE: Floating-point parsing is by nature a lossy operation. - // We never report an overflow condition since we can always - // round the input to the closest representable finite value. - // For extremely large numbers, the closest value is ±MaxFloat. - fv, _ := parseFloat(val, bits) - va.SetFloat(fv) - return nil - } - return &SemanticError{action: "unmarshal", JSONKind: k, GoType: t} - } - 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()) - } - fncs.marshal = func(mo MarshalOptions, enc *Encoder, va addressableValue) error { - // Check for cycles. - if enc.tokens.depth() > startDetectingCyclesAfter { - if err := enc.seenPointers.visit(va.Value); err != nil { - return err - } - defer enc.seenPointers.leave(va.Value) - } - - if mo.format != "" && mo.formatDepth == enc.tokens.depth() { - if mo.format == "emitnull" { - if va.IsNil() { - return enc.WriteToken(Null) - } - mo.format = "" - } else { - return newInvalidFormatError("marshal", t, mo.format) - } - } - - // Optimize for marshaling an empty map without any preceding whitespace. - n := va.Len() - if optimizeCommon && n == 0 && !enc.options.multiline && !enc.tokens.last.needObjectName() { - enc.buf = enc.tokens.mayAppendDelim(enc.buf, '{') - enc.buf = append(enc.buf, "{}"...) - enc.tokens.last.increment() - if enc.needFlush() { - return enc.flush() - } - return nil - } - - once.Do(init) - if err := enc.WriteToken(ObjectStart); err != nil { - return err - } - if n > 0 { - // Handle maps with numeric key types by stringifying them. - mko := mo - mko.StringifyNumbers = true - - nonDefaultKey := keyFncs.nonDefault - marshalKey := keyFncs.marshal - marshalVal := valFncs.marshal - if mo.Marshalers != nil { - var ok bool - marshalKey, ok = mo.Marshalers.lookup(marshalKey, t.Key()) - marshalVal, _ = mo.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(), enc.options.AllowInvalidUTF8) { - enc.tokens.last.disableNamespace() - } - - switch { - case !mo.Deterministic || n <= 1: - for iter := va.Value.MapRange(); iter.Next(); { - k.SetIterKey(iter) - if err := marshalKey(mko, enc, k); err != nil { - // TODO: If err is errMissingName, then wrap it as a - // SemanticError since this key type cannot be serialized - // as a JSON string. - return err - } - v.SetIterValue(iter) - if err := marshalVal(mo, enc, v); 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(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(mo, enc, v); err != nil { - return err - } - } - putStrings(names) - default: - type member struct { - name string // unquoted name - key addressableValue - } - members := make([]member, n) - keys := reflect.MakeSlice(reflect.SliceOf(t.Key()), n, n) - for i, iter := 0, va.Value.MapRange(); i < n && iter.Next(); i++ { - // Marshal the member name. - k := addressableValue{keys.Index(i)} // indexed slice element is always addressable - k.SetIterKey(iter) - if err := marshalKey(mko, enc, k); err != nil { - // TODO: If err is errMissingName, then wrap it as a - // SemanticError since this key type cannot be serialized - // as a JSON string. - return err - } - name := enc.unwriteOnlyObjectMemberName() - members[i] = member{name, k} - } - // TODO: If AllowDuplicateNames is enabled, then sort according - // to reflect.Value as well if the names are equal. - // See internal/fmtsort. - // TODO(https://go.dev/issue/47619): Use slices.SortFunc instead. - sort.Slice(members, func(i, j int) bool { - return lessUTF16(members[i].name, members[j].name) - }) - for _, member := range members { - if err := enc.WriteToken(String(member.name)); err != nil { - return err - } - // TODO(https://go.dev/issue/57061): Use v.SetMapIndexOf. - v.Set(va.MapIndex(member.key.Value)) - if err := marshalVal(mo, enc, v); err != nil { - return err - } - } - } - } - if err := enc.WriteToken(ObjectEnd); err != nil { - return err - } - return nil - } - fncs.unmarshal = func(uo UnmarshalOptions, dec *Decoder, va addressableValue) error { - if uo.format != "" && uo.formatDepth == dec.tokens.depth() { - if uo.format == "emitnull" { - uo.format = "" // only relevant for marshaling - } else { - return newInvalidFormatError("unmarshal", t, uo.format) - } - } - tok, err := dec.ReadToken() - if err != nil { - return err - } - k := tok.Kind() - switch k { - case 'n': - va.Set(reflect.Zero(t)) - return nil - case '{': - once.Do(init) - if va.IsNil() { - va.Set(reflect.MakeMap(t)) - } - - // Handle maps with numeric key types by stringifying them. - uko := uo - uko.StringifyNumbers = true - - nonDefaultKey := keyFncs.nonDefault - unmarshalKey := keyFncs.unmarshal - unmarshalVal := valFncs.unmarshal - if uo.Unmarshalers != nil { - var ok bool - unmarshalKey, ok = uo.Unmarshalers.lookup(unmarshalKey, t.Key()) - unmarshalVal, _ = uo.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(), dec.options.AllowInvalidUTF8) { - dec.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 !dec.options.AllowDuplicateNames && va.Len() > 0 { - seen = reflect.MakeMap(reflect.MapOf(k.Type(), emptyStructType)) - } - - for dec.PeekKind() != '}' { - k.Set(reflect.Zero(t.Key())) - if err := unmarshalKey(uko, dec, k); err != nil { - return err - } - if k.Kind() == reflect.Interface && !k.IsNil() && !k.Elem().Type().Comparable() { - err := fmt.Errorf("invalid incomparable key type %v", k.Elem().Type()) - return &SemanticError{action: "unmarshal", GoType: t, Err: err} - } - - if v2 := va.MapIndex(k.Value); v2.IsValid() { - if !dec.options.AllowDuplicateNames && (!seen.IsValid() || seen.MapIndex(k.Value).IsValid()) { - // TODO: Unread the object name. - name := dec.previousBuffer() - err := &SyntacticError{str: "duplicate name " + string(name) + " in object"} - return err.withOffset(dec.InputOffset() - int64(len(name))) - } - v.Set(v2) - } else { - v.Set(reflect.Zero(v.Type())) - } - err := unmarshalVal(uo, dec, v) - va.SetMapIndex(k.Value, v.Value) - if seen.IsValid() { - seen.SetMapIndex(k.Value, reflect.Zero(emptyStructType)) - } - if err != nil { - return err - } - } - if _, err := dec.ReadToken(); err != nil { - return err - } - return nil - } - return &SemanticError{action: "unmarshal", JSONKind: k, GoType: t} - } - 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: - 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 - } -} - -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(mo MarshalOptions, enc *Encoder, va addressableValue) error { - if mo.format != "" && mo.formatDepth == enc.tokens.depth() { - return newInvalidFormatError("marshal", t, mo.format) - } - once.Do(init) - if errInit != nil { - err := *errInit // shallow copy SemanticError - err.action = "marshal" - return &err - } - if err := enc.WriteToken(ObjectStart); err != nil { - return err - } - var seenIdxs uintSet - prevIdx := -1 - enc.tokens.last.disableNamespace() // we manually ensure unique names below - for i := range fields.flattened { - f := &fields.flattened[i] - v := addressableValue{va.Field(f.index[0])} // addressable if struct value is addressable - if len(f.index) > 1 { - v = v.fieldByIndex(f.index[1:], 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 && ((f.isZero == nil && v.IsZero()) || (f.isZero != nil && f.isZero(v))) { - continue - } - - marshal := f.fncs.marshal - nonDefault := f.fncs.nonDefault - if mo.Marshalers != nil { - var ok bool - marshal, ok = mo.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 && !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. - if enc.tokens.last.length() > 0 { - enc.buf = append(enc.buf, ',') - } - if enc.options.multiline { - enc.buf = enc.appendIndent(enc.buf, enc.tokens.needIndent('"')) - } - - // Append the token to the output and to the state machine. - n0 := len(enc.buf) // offset before calling appendString - if enc.options.EscapeRune == nil { - enc.buf = append(enc.buf, f.quotedName...) - } else { - enc.buf, _ = appendString(enc.buf, f.name, false, enc.options.EscapeRune) - } - if !enc.options.AllowDuplicateNames { - enc.names.replaceLastQuotedOffset(n0) - } - enc.tokens.last.increment() - } else { - if err := enc.WriteToken(String(f.name)); err != nil { - return err - } - } - - // Write the object member value. - mo2 := mo - if f.string { - mo2.StringifyNumbers = true - } - if f.format != "" { - mo2.formatDepth = enc.tokens.depth() - mo2.format = f.format - } - if err := marshal(mo2, enc, v); err != nil { - return err - } - - // Try unwriting the member if empty (slow path for omitempty). - if f.omitempty { - var prevName *string - if prevIdx >= 0 { - prevName = &fields.flattened[prevIdx].name - } - if enc.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 !enc.options.AllowDuplicateNames && fields.inlinedFallback != nil { - seenIdxs.insert(uint(f.id)) - } - prevIdx = f.id - } - if fields.inlinedFallback != nil && !(mo.DiscardUnknownMembers && fields.inlinedFallback.unknown) { - var insertUnquotedName func([]byte) bool - if !enc.options.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.byFoldedName[string(foldName(name))]; len(foldedFields) > 0 { - if f := fields.byActualName[string(name)]; f != nil { - return seenIdxs.insert(uint(f.id)) - } - for _, f := range foldedFields { - if f.nocase { - return seenIdxs.insert(uint(f.id)) - } - } - } - - // Check that the name does not match any other name - // previously marshaled from the inlined fallback. - return enc.namespaces.last().insertUnquoted(name) - } - } - if err := marshalInlinedFallbackAll(mo, enc, va, fields.inlinedFallback, insertUnquotedName); err != nil { - return err - } - } - if err := enc.WriteToken(ObjectEnd); err != nil { - return err - } - return nil - } - fncs.unmarshal = func(uo UnmarshalOptions, dec *Decoder, va addressableValue) error { - if uo.format != "" && uo.formatDepth == dec.tokens.depth() { - return newInvalidFormatError("unmarshal", t, uo.format) - } - tok, err := dec.ReadToken() - if err != nil { - return err - } - k := tok.Kind() - switch k { - case 'n': - va.Set(reflect.Zero(t)) - return nil - case '{': - once.Do(init) - if errInit != nil { - err := *errInit // shallow copy SemanticError - err.action = "unmarshal" - return &err - } - var seenIdxs uintSet - dec.tokens.last.disableNamespace() - for dec.PeekKind() != '}' { - // Process the object member name. - var flags valueFlags - val, err := dec.readValue(&flags) - if err != nil { - return err - } - name := unescapeStringMayCopy(val, flags.isVerbatim()) - f := fields.byActualName[string(name)] - if f == nil { - for _, f2 := range fields.byFoldedName[string(foldName(name))] { - if f2.nocase { - f = f2 - break - } - } - if f == nil { - if uo.RejectUnknownMembers && (fields.inlinedFallback == nil || fields.inlinedFallback.unknown) { - return &SemanticError{action: "unmarshal", GoType: t, Err: fmt.Errorf("unknown name %s", val)} - } - if !dec.options.AllowDuplicateNames && !dec.namespaces.last().insertUnquoted(name) { - // TODO: Unread the object name. - err := &SyntacticError{str: "duplicate name " + string(val) + " in object"} - return err.withOffset(dec.InputOffset() - int64(len(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(uo, dec, va, fields.inlinedFallback, val, name); err != nil { - return err - } - } - continue - } - } - if !dec.options.AllowDuplicateNames && !seenIdxs.insert(uint(f.id)) { - // TODO: Unread the object name. - err := &SyntacticError{str: "duplicate name " + string(val) + " in object"} - return err.withOffset(dec.InputOffset() - int64(len(val))) - } - - // Process the object member value. - unmarshal := f.fncs.unmarshal - if uo.Unmarshalers != nil { - unmarshal, _ = uo.Unmarshalers.lookup(unmarshal, f.typ) - } - uo2 := uo - if f.string { - uo2.StringifyNumbers = true - } - if f.format != "" { - uo2.formatDepth = dec.tokens.depth() - uo2.format = f.format - } - v := addressableValue{va.Field(f.index[0])} // addressable if struct value is addressable - if len(f.index) > 1 { - v = v.fieldByIndex(f.index[1:], true) - } - if err := unmarshal(uo2, dec, v); err != nil { - return err - } - } - if _, err := dec.ReadToken(); err != nil { - return err - } - return nil - } - return &SemanticError{action: "unmarshal", JSONKind: k, GoType: t} - } - 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)} // 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 { - return addressableValue{} - } - va.Set(reflect.New(va.Type().Elem())) - } - va = addressableValue{va.Elem()} // dereferenced pointer is always addressable - } - return va -} - -func makeSliceArshaler(t reflect.Type) *arshaler { - var fncs arshaler - var ( - once sync.Once - valFncs *arshaler - ) - init := func() { - valFncs = lookupArshaler(t.Elem()) - } - fncs.marshal = func(mo MarshalOptions, enc *Encoder, va addressableValue) error { - // Check for cycles. - if enc.tokens.depth() > startDetectingCyclesAfter { - if err := enc.seenPointers.visit(va.Value); err != nil { - return err - } - defer enc.seenPointers.leave(va.Value) - } - - if mo.format != "" && mo.formatDepth == enc.tokens.depth() { - if mo.format == "emitnull" { - if va.IsNil() { - return enc.WriteToken(Null) - } - mo.format = "" - } else { - return newInvalidFormatError("marshal", t, mo.format) - } - } - - // Optimize for marshaling an empty slice without any preceding whitespace. - n := va.Len() - if optimizeCommon && n == 0 && !enc.options.multiline && !enc.tokens.last.needObjectName() { - enc.buf = enc.tokens.mayAppendDelim(enc.buf, '[') - enc.buf = append(enc.buf, "[]"...) - enc.tokens.last.increment() - if enc.needFlush() { - return enc.flush() - } - return nil - } - - once.Do(init) - if err := enc.WriteToken(ArrayStart); err != nil { - return err - } - marshal := valFncs.marshal - if mo.Marshalers != nil { - marshal, _ = mo.Marshalers.lookup(marshal, t.Elem()) - } - for i := 0; i < n; i++ { - v := addressableValue{va.Index(i)} // indexed slice element is always addressable - if err := marshal(mo, enc, v); err != nil { - return err - } - } - if err := enc.WriteToken(ArrayEnd); err != nil { - return err - } - return nil - } - emptySlice := reflect.MakeSlice(t, 0, 0) - fncs.unmarshal = func(uo UnmarshalOptions, dec *Decoder, va addressableValue) error { - if uo.format != "" && uo.formatDepth == dec.tokens.depth() { - if uo.format == "emitnull" { - uo.format = "" // only relevant for marshaling - } else { - return newInvalidFormatError("unmarshal", t, uo.format) - } - } - - tok, err := dec.ReadToken() - if err != nil { - return err - } - k := tok.Kind() - switch k { - case 'n': - va.Set(reflect.Zero(t)) - return nil - case '[': - once.Do(init) - unmarshal := valFncs.unmarshal - if uo.Unmarshalers != nil { - unmarshal, _ = uo.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 - for dec.PeekKind() != ']' { - if i == cap { - // TODO(https://go.dev/issue/48000): Use reflect.Value.Append. - va.Set(reflect.Append(va.Value, reflect.Zero(t.Elem()))) - cap = va.Cap() - va.SetLen(cap) - mustZero = false // append guarantees that unused capacity is zero-initialized - } - v := addressableValue{va.Index(i)} // indexed slice element is always addressable - i++ - if mustZero { - v.Set(reflect.Zero(t.Elem())) - } - if err := unmarshal(uo, dec, v); err != nil { - va.SetLen(i) - return err - } - } - if i == 0 { - va.Set(emptySlice) - } else { - va.SetLen(i) - } - if _, err := dec.ReadToken(); err != nil { - return err - } - return nil - } - return &SemanticError{action: "unmarshal", JSONKind: k, GoType: t} - } - return &fncs -} - -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(mo MarshalOptions, enc *Encoder, va addressableValue) error { - if mo.format != "" && mo.formatDepth == enc.tokens.depth() { - return newInvalidFormatError("marshal", t, mo.format) - } - once.Do(init) - if err := enc.WriteToken(ArrayStart); err != nil { - return err - } - marshal := valFncs.marshal - if mo.Marshalers != nil { - marshal, _ = mo.Marshalers.lookup(marshal, t.Elem()) - } - for i := 0; i < n; i++ { - v := addressableValue{va.Index(i)} // indexed array element is addressable if array is addressable - if err := marshal(mo, enc, v); err != nil { - return err - } - } - if err := enc.WriteToken(ArrayEnd); err != nil { - return err - } - return nil - } - fncs.unmarshal = func(uo UnmarshalOptions, dec *Decoder, va addressableValue) error { - if uo.format != "" && uo.formatDepth == dec.tokens.depth() { - return newInvalidFormatError("unmarshal", t, uo.format) - } - tok, err := dec.ReadToken() - if err != nil { - return err - } - k := tok.Kind() - switch k { - case 'n': - va.Set(reflect.Zero(t)) - return nil - case '[': - once.Do(init) - unmarshal := valFncs.unmarshal - if uo.Unmarshalers != nil { - unmarshal, _ = uo.Unmarshalers.lookup(unmarshal, t.Elem()) - } - var i int - for dec.PeekKind() != ']' { - if i >= n { - err := errors.New("too many array elements") - return &SemanticError{action: "unmarshal", GoType: t, Err: err} - } - v := addressableValue{va.Index(i)} // indexed array element is addressable if array is addressable - v.Set(reflect.Zero(v.Type())) - if err := unmarshal(uo, dec, v); err != nil { - return err - } - i++ - } - if _, err := dec.ReadToken(); err != nil { - return err - } - if i < n { - err := errors.New("too few array elements") - return &SemanticError{action: "unmarshal", GoType: t, Err: err} - } - return nil - } - return &SemanticError{action: "unmarshal", JSONKind: k, GoType: t} - } - 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(mo MarshalOptions, enc *Encoder, va addressableValue) error { - // Check for cycles. - if enc.tokens.depth() > startDetectingCyclesAfter { - if err := enc.seenPointers.visit(va.Value); err != nil { - return err - } - defer enc.seenPointers.leave(va.Value) - } - - // NOTE: MarshalOptions.format is forwarded to underlying marshal. - if va.IsNil() { - return enc.WriteToken(Null) - } - once.Do(init) - marshal := valFncs.marshal - if mo.Marshalers != nil { - marshal, _ = mo.Marshalers.lookup(marshal, t.Elem()) - } - v := addressableValue{va.Elem()} // dereferenced pointer is always addressable - return marshal(mo, enc, v) - } - fncs.unmarshal = func(uo UnmarshalOptions, dec *Decoder, va addressableValue) error { - // NOTE: UnmarshalOptions.format is forwarded to underlying unmarshal. - if dec.PeekKind() == 'n' { - if _, err := dec.ReadToken(); err != nil { - return err - } - va.Set(reflect.Zero(t)) - return nil - } - once.Do(init) - unmarshal := valFncs.unmarshal - if uo.Unmarshalers != nil { - unmarshal, _ = uo.Unmarshalers.lookup(unmarshal, t.Elem()) - } - if va.IsNil() { - va.Set(reflect.New(t.Elem())) - } - v := addressableValue{va.Elem()} // dereferenced pointer is always addressable - return unmarshal(uo, dec, v) - } - 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 - fncs.marshal = func(mo MarshalOptions, enc *Encoder, va addressableValue) error { - if mo.format != "" && mo.formatDepth == enc.tokens.depth() { - return newInvalidFormatError("marshal", t, mo.format) - } - if va.IsNil() { - return enc.WriteToken(Null) - } - v := newAddressableValue(va.Elem().Type()) - v.Set(va.Elem()) - marshal := lookupArshaler(v.Type()).marshal - if mo.Marshalers != nil { - marshal, _ = mo.Marshalers.lookup(marshal, v.Type()) - } - // Optimize for the any type if there are no special options. - if optimizeCommon && t == anyType && !mo.StringifyNumbers && mo.format == "" && (mo.Marshalers == nil || !mo.Marshalers.fromAny) { - return marshalValueAny(mo, enc, va.Elem().Interface()) - } - return marshal(mo, enc, v) - } - fncs.unmarshal = func(uo UnmarshalOptions, dec *Decoder, va addressableValue) error { - if uo.format != "" && uo.formatDepth == dec.tokens.depth() { - return newInvalidFormatError("unmarshal", t, uo.format) - } - if dec.PeekKind() == 'n' { - if _, err := dec.ReadToken(); err != nil { - return err - } - va.Set(reflect.Zero(t)) - 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.format == "" && (uo.Unmarshalers == nil || !uo.Unmarshalers.fromAny) && !dec.options.AllowDuplicateNames { - v, err := unmarshalValueAny(uo, dec) - // 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) { - err := errors.New("cannot derive concrete type for non-empty interface") - return &SemanticError{action: "unmarshal", JSONKind: k, GoType: t, Err: err} - } - switch k { - case 'f', 't': - v = newAddressableValue(boolType) - case '"': - v = newAddressableValue(stringType) - case '0': - 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.lookup(unmarshal, v.Type()) - } - err := unmarshal(uo, dec, v) - 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(mo MarshalOptions, enc *Encoder, va addressableValue) error { - return &SemanticError{action: "marshal", GoType: t} - } - fncs.unmarshal = func(uo UnmarshalOptions, dec *Decoder, va addressableValue) error { - return &SemanticError{action: "unmarshal", GoType: t} - } - return &fncs -} - -func newInvalidFormatError(action string, t reflect.Type, format string) error { - err := fmt.Errorf("invalid format flag: %q", format) - return &SemanticError{action: action, GoType: t, Err: err} -} 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 8a4e70083..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/arshal_funcs.go +++ /dev/null @@ -1,387 +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" -) - -// SkipFunc may be returned by MarshalFuncV2 and UnmarshalFuncV2 functions. -// -// Any function that returns SkipFunc must not cause observable side effects -// on the provided Encoder or Decoder. For example, it is permissible to call -// Decoder.PeekKind, but not permissible to call Decoder.ReadToken or -// Encoder.WriteToken since such methods mutate the state. -const SkipFunc = jsonError("skip function") - -// Marshalers is a list of functions that may override the marshal behavior -// of specific types. Populate MarshalOptions.Marshalers to use it. -// A nil *Marshalers is equivalent to an empty list. -type Marshalers = typedMarshalers - -// NewMarshalers 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 := NewMarshalers(f1, f2) -// m2 := NewMarshalers(f0, m1, f3) // equivalent to m3 -// m3 := NewMarshalers(f0, f1, f2, f3) // equivalent to m2 -func NewMarshalers(ms ...*Marshalers) *Marshalers { - return newMarshalers(ms...) -} - -// Unmarshalers is a list of functions that may override the unmarshal behavior -// of specific types. Populate UnmarshalOptions.Unmarshalers to use it. -// A nil *Unmarshalers is equivalent to an empty list. -type Unmarshalers = typedUnmarshalers - -// NewUnmarshalers 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 := NewUnmarshalers(f1, f2) -// u2 := NewUnmarshalers(f0, u1, f3) // equivalent to u3 -// u3 := NewUnmarshalers(f0, f1, f2, f3) // equivalent to u2 -func NewUnmarshalers(us ...*Unmarshalers) *Unmarshalers { - return newUnmarshalers(us...) -} - -type typedMarshalers = typedArshalers[MarshalOptions, Encoder] -type typedUnmarshalers = typedArshalers[UnmarshalOptions, Decoder] -type typedArshalers[Options, Coder any] struct { - nonComparable - - fncVals []typedArshaler[Options, 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[MarshalOptions, Encoder] -type typedUnmarshaler = typedArshaler[UnmarshalOptions, Decoder] -type typedArshaler[Options, Coder any] struct { - typ reflect.Type - fnc func(Options, *Coder, addressableValue) error - maySkip bool -} - -func newMarshalers(ms ...*Marshalers) *Marshalers { return newTypedArshalers(ms...) } -func newUnmarshalers(us ...*Unmarshalers) *Unmarshalers { return newTypedArshalers(us...) } -func newTypedArshalers[Options, Coder any](as ...*typedArshalers[Options, Coder]) *typedArshalers[Options, Coder] { - var a typedArshalers[Options, 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[Options, Coder]) lookup(fnc func(Options, *Coder, addressableValue) error, t reflect.Type) (func(Options, *Coder, addressableValue) 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(Options, *Coder, addressableValue) 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(Options, *Coder, addressableValue) 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(o Options, c *Coder, v addressableValue) error { - for _, fnc := range fncs { - if err := fnc(o, c, v); err != SkipFunc { - return err // may be nil or non-nil - } - } - return fncDefault(o, c, v) - } - - // Use the first stored so duplicate work can be garbage collected. - v, _ := a.fncCache.LoadOrStore(t, fnc) - return v.(func(Options, *Coder, addressableValue) error), true -} - -// MarshalFuncV1 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 MarshalFuncV1[T any](fn func(T) ([]byte, error)) *Marshalers { - t := reflect.TypeOf((*T)(nil)).Elem() - assertCastableTo(t, true) - typFnc := typedMarshaler{ - typ: t, - fnc: func(mo MarshalOptions, enc *Encoder, va addressableValue) error { - val, err := fn(va.castTo(t).Interface().(T)) - if err != nil { - err = wrapSkipFunc(err, "marshal function of type func(T) ([]byte, error)") - // TODO: Avoid wrapping semantic errors. - return &SemanticError{action: "marshal", GoType: t, Err: err} - } - if err := enc.WriteValue(val); err != nil { - // TODO: Avoid wrapping semantic or I/O errors. - return &SemanticError{action: "marshal", JSONKind: RawValue(val).Kind(), GoType: t, Err: err} - } - return nil - }, - } - return &Marshalers{fncVals: []typedMarshaler{typFnc}, fromAny: castableToFromAny(t)} -} - -// MarshalFuncV2 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 Encoder and the value of T must not be retained -// outside the function call. -func MarshalFuncV2[T any](fn func(MarshalOptions, *Encoder, T) error) *Marshalers { - t := reflect.TypeOf((*T)(nil)).Elem() - assertCastableTo(t, true) - typFnc := typedMarshaler{ - typ: t, - fnc: func(mo MarshalOptions, enc *Encoder, va addressableValue) error { - prevDepth, prevLength := enc.tokens.depthLength() - err := fn(mo, enc, va.castTo(t).Interface().(T)) - currDepth, currLength := enc.tokens.depthLength() - if err == nil && (prevDepth != currDepth || prevLength+1 != currLength) { - err = errors.New("must write exactly one JSON value") - } - if err != nil { - if err == SkipFunc { - if prevDepth == currDepth && prevLength == currLength { - return SkipFunc - } - err = errors.New("must not write any JSON tokens when skipping") - } - // TODO: Avoid wrapping semantic or I/O errors. - return &SemanticError{action: "marshal", GoType: t, Err: err} - } - return nil - }, - maySkip: true, - } - return &Marshalers{fncVals: []typedMarshaler{typFnc}, fromAny: castableToFromAny(t)} -} - -// UnmarshalFuncV1 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 UnmarshalFuncV1[T any](fn func([]byte, T) error) *Unmarshalers { - t := reflect.TypeOf((*T)(nil)).Elem() - assertCastableTo(t, false) - typFnc := typedUnmarshaler{ - typ: t, - fnc: func(uo UnmarshalOptions, dec *Decoder, va addressableValue) 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") - // TODO: Avoid wrapping semantic, syntactic, or I/O errors. - return &SemanticError{action: "unmarshal", JSONKind: val.Kind(), GoType: t, Err: err} - } - return nil - }, - } - return &Unmarshalers{fncVals: []typedUnmarshaler{typFnc}, fromAny: castableToFromAny(t)} -} - -// UnmarshalFuncV2 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 Decoder and the value of T must not be retained -// outside the function call. -func UnmarshalFuncV2[T any](fn func(UnmarshalOptions, *Decoder, T) error) *Unmarshalers { - t := reflect.TypeOf((*T)(nil)).Elem() - assertCastableTo(t, false) - typFnc := typedUnmarshaler{ - typ: t, - fnc: func(uo UnmarshalOptions, dec *Decoder, va addressableValue) error { - prevDepth, prevLength := dec.tokens.depthLength() - err := fn(uo, dec, va.castTo(t).Interface().(T)) - currDepth, currLength := dec.tokens.depthLength() - if err == nil && (prevDepth != currDepth || prevLength+1 != currLength) { - err = errors.New("must read exactly one JSON value") - } - if err != nil { - if err == SkipFunc { - if prevDepth == currDepth && prevLength == currLength { - return SkipFunc - } - err = errors.New("must not read any JSON tokens when skipping") - } - // TODO: Avoid wrapping semantic, syntactic, or I/O errors. - return &SemanticError{action: "unmarshal", GoType: t, Err: 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 258a98247..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/arshal_inlined.go +++ /dev/null @@ -1,213 +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" - "reflect" -) - -// 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 RawValue. 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 rawValueType = reflect.TypeOf((*RawValue)(nil)).Elem() - -// marshalInlinedFallbackAll marshals all the members in an inlined fallback. -func marshalInlinedFallbackAll(mo MarshalOptions, enc *Encoder, va addressableValue, f *structField, insertUnquotedName func([]byte) bool) error { - v := addressableValue{va.Field(f.index[0])} // addressable if struct value is addressable - if len(f.index) > 1 { - v = v.fieldByIndex(f.index[1:], false) - if !v.IsValid() { - return nil // implies a nil inlined field - } - } - v = v.indirect(false) - if !v.IsValid() { - return nil - } - - if v.Type() == rawValueType { - b := v.Interface().(RawValue) - if len(b) == 0 { // TODO: Should this be nil? What if it were all whitespace? - return nil - } - - dec := getBufferedDecoder(b, DecodeOptions{AllowDuplicateNames: true, AllowInvalidUTF8: true}) - defer putBufferedDecoder(dec) - - tok, err := dec.ReadToken() - if err != nil { - return &SemanticError{action: "marshal", GoType: rawValueType, Err: err} - } - if tok.Kind() != '{' { - err := errors.New("inlined raw value must be a JSON object") - return &SemanticError{action: "marshal", JSONKind: tok.Kind(), GoType: rawValueType, Err: err} - } - for dec.PeekKind() != '}' { - // Parse the JSON object name. - var flags valueFlags - val, err := dec.readValue(&flags) - if err != nil { - return &SemanticError{action: "marshal", GoType: rawValueType, Err: err} - } - if insertUnquotedName != nil { - name := unescapeStringMayCopy(val, flags.isVerbatim()) - if !insertUnquotedName(name) { - return &SyntacticError{str: "duplicate name " + string(val) + " in object"} - } - } - if err := enc.WriteValue(val); err != nil { - return err - } - - // Parse the JSON object value. - val, err = dec.readValue(&flags) - if err != nil { - return &SemanticError{action: "marshal", GoType: rawValueType, Err: err} - } - if err := enc.WriteValue(val); err != nil { - return err - } - } - if _, err := dec.ReadToken(); err != nil { - return &SemanticError{action: "marshal", GoType: rawValueType, Err: err} - } - if err := dec.checkEOF(); err != nil { - return &SemanticError{action: "marshal", GoType: rawValueType, Err: err} - } - return nil - } else { - m := v // must be a map[string]V - n := m.Len() - if n == 0 { - return nil - } - mk := newAddressableValue(stringType) - mv := newAddressableValue(m.Type().Elem()) - marshalKey := func(mk addressableValue) error { - b, err := appendString(enc.UnusedBuffer(), mk.String(), !enc.options.AllowInvalidUTF8, nil) - if err != nil { - return err - } - if insertUnquotedName != nil { - isVerbatim := bytes.IndexByte(b, '\\') < 0 - name := unescapeStringMayCopy(b, isVerbatim) - if !insertUnquotedName(name) { - return &SyntacticError{str: "duplicate name " + string(b) + " in object"} - } - } - return enc.WriteValue(b) - } - marshalVal := f.fncs.marshal - if mo.Marshalers != nil { - marshalVal, _ = mo.Marshalers.lookup(marshalVal, mv.Type()) - } - if !mo.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(mo, enc, mv); 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(mo, enc, mv); err != nil { - return err - } - } - putStrings(names) - } - return nil - } -} - -// unmarshalInlinedFallbackNext unmarshals only the next member in an inlined fallback. -func unmarshalInlinedFallbackNext(uo UnmarshalOptions, dec *Decoder, va addressableValue, f *structField, quotedName, unquotedName []byte) error { - v := addressableValue{va.Field(f.index[0])} // addressable if struct value is addressable - if len(f.index) > 1 { - v = v.fieldByIndex(f.index[1:], true) - } - v = v.indirect(true) - - if v.Type() == rawValueType { - b := v.Addr().Interface().(*RawValue) - if len(*b) == 0 { // TODO: Should this be nil? What if it were all whitespace? - *b = append(*b, '{') - } else { - *b = trimSuffixWhitespace(*b) - if hasSuffixByte(*b, '}') { - // TODO: When merging into an object for the first time, - // should we verify that it is valid? - *b = trimSuffixByte(*b, '}') - *b = trimSuffixWhitespace(*b) - if !hasSuffixByte(*b, ',') && !hasSuffixByte(*b, '{') { - *b = append(*b, ',') - } - } else { - err := errors.New("inlined raw value must be a JSON object") - return &SemanticError{action: "unmarshal", GoType: rawValueType, Err: err} - } - } - *b = append(*b, quotedName...) - *b = append(*b, ':') - rawValue, err := dec.ReadValue() - if err != nil { - return err - } - *b = append(*b, rawValue...) - *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) - mv := newAddressableValue(v.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.lookup(unmarshal, mv.Type()) - } - err := unmarshal(uo, dec, mv) - 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 20899c868..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/arshal_methods.go +++ /dev/null @@ -1,229 +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" -) - -// Interfaces for custom serialization. -var ( - jsonMarshalerV1Type = reflect.TypeOf((*MarshalerV1)(nil)).Elem() - jsonMarshalerV2Type = reflect.TypeOf((*MarshalerV2)(nil)).Elem() - jsonUnmarshalerV1Type = reflect.TypeOf((*UnmarshalerV1)(nil)).Elem() - jsonUnmarshalerV2Type = reflect.TypeOf((*UnmarshalerV2)(nil)).Elem() - textMarshalerType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem() - textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem() -) - -// MarshalerV1 is implemented by types that can marshal themselves. -// It is recommended that types implement MarshalerV2 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 MarshalerV1 interface { - MarshalJSON() ([]byte, error) -} - -// MarshalerV2 is implemented by types that can marshal themselves. -// It is recommended that types implement MarshalerV2 instead of MarshalerV1 -// since this is both more performant and flexible. -// If a type implements both MarshalerV1 and MarshalerV2, -// then MarshalerV2 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 Encoder. -type MarshalerV2 interface { - MarshalNextJSON(MarshalOptions, *Encoder) error - - // TODO: Should users call the MarshalOptions.MarshalNext method or - // should/can they call this method directly? Does it matter? -} - -// UnmarshalerV1 is implemented by types that can unmarshal themselves. -// It is recommended that types implement UnmarshalerV2 unless -// the implementation is trying to avoid a hard dependency on this 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 UnmarshalerV1 interface { - UnmarshalJSON([]byte) error -} - -// UnmarshalerV2 is implemented by types that can unmarshal themselves. -// It is recommended that types implement UnmarshalerV2 instead of UnmarshalerV1 -// since this is both more performant and flexible. -// If a type implements both UnmarshalerV1 and UnmarshalerV2, -// then UnmarshalerV2 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 UnmarshalNextJSON implement merge semantics when -// unmarshaling into a pre-populated value. -// -// Implementations must not retain the pointer to Decoder. -type UnmarshalerV2 interface { - UnmarshalNextJSON(UnmarshalOptions, *Decoder) error - - // TODO: Should users call the UnmarshalOptions.UnmarshalNext method 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 - } - - // Handle custom marshaler. - switch which, needAddr := implementsWhich(t, jsonMarshalerV2Type, jsonMarshalerV1Type, textMarshalerType); which { - case jsonMarshalerV2Type: - fncs.nonDefault = true - fncs.marshal = func(mo MarshalOptions, enc *Encoder, va addressableValue) error { - prevDepth, prevLength := enc.tokens.depthLength() - err := va.addrWhen(needAddr).Interface().(MarshalerV2).MarshalNextJSON(mo, enc) - currDepth, currLength := enc.tokens.depthLength() - if (prevDepth != currDepth || prevLength+1 != currLength) && err == nil { - err = errors.New("must write exactly one JSON value") - } - if err != nil { - err = wrapSkipFunc(err, "marshal method") - // TODO: Avoid wrapping semantic or I/O errors. - return &SemanticError{action: "marshal", GoType: t, Err: err} - } - return nil - } - case jsonMarshalerV1Type: - fncs.nonDefault = true - fncs.marshal = func(mo MarshalOptions, enc *Encoder, va addressableValue) error { - marshaler := va.addrWhen(needAddr).Interface().(MarshalerV1) - val, err := marshaler.MarshalJSON() - if err != nil { - err = wrapSkipFunc(err, "marshal method") - // TODO: Avoid wrapping semantic errors. - return &SemanticError{action: "marshal", GoType: t, Err: err} - } - if err := enc.WriteValue(val); err != nil { - // TODO: Avoid wrapping semantic or I/O errors. - return &SemanticError{action: "marshal", JSONKind: RawValue(val).Kind(), GoType: t, Err: err} - } - return nil - } - case textMarshalerType: - fncs.nonDefault = true - fncs.marshal = func(mo MarshalOptions, enc *Encoder, va addressableValue) error { - marshaler := va.addrWhen(needAddr).Interface().(encoding.TextMarshaler) - s, err := marshaler.MarshalText() - if err != nil { - err = wrapSkipFunc(err, "marshal method") - // TODO: Avoid wrapping semantic errors. - return &SemanticError{action: "marshal", JSONKind: '"', GoType: t, Err: err} - } - val := enc.UnusedBuffer() - val, err = appendString(val, string(s), true, nil) - if err != nil { - return &SemanticError{action: "marshal", JSONKind: '"', GoType: t, Err: err} - } - if err := enc.WriteValue(val); err != nil { - // TODO: Avoid wrapping syntactic or I/O errors. - return &SemanticError{action: "marshal", JSONKind: '"', GoType: t, Err: err} - } - return nil - } - } - - // Handle custom unmarshaler. - switch which, needAddr := implementsWhich(t, jsonUnmarshalerV2Type, jsonUnmarshalerV1Type, textUnmarshalerType); which { - case jsonUnmarshalerV2Type: - fncs.nonDefault = true - fncs.unmarshal = func(uo UnmarshalOptions, dec *Decoder, va addressableValue) error { - prevDepth, prevLength := dec.tokens.depthLength() - err := va.addrWhen(needAddr).Interface().(UnmarshalerV2).UnmarshalNextJSON(uo, dec) - currDepth, currLength := dec.tokens.depthLength() - if (prevDepth != currDepth || prevLength+1 != currLength) && err == nil { - err = errors.New("must read exactly one JSON value") - } - if err != nil { - err = wrapSkipFunc(err, "unmarshal method") - // TODO: Avoid wrapping semantic, syntactic, or I/O errors. - return &SemanticError{action: "unmarshal", GoType: t, Err: err} - } - return nil - } - case jsonUnmarshalerV1Type: - fncs.nonDefault = true - fncs.unmarshal = func(uo UnmarshalOptions, dec *Decoder, va addressableValue) error { - val, err := dec.ReadValue() - if err != nil { - return err // must be a syntactic or I/O error - } - unmarshaler := va.addrWhen(needAddr).Interface().(UnmarshalerV1) - if err := unmarshaler.UnmarshalJSON(val); err != nil { - err = wrapSkipFunc(err, "unmarshal method") - // TODO: Avoid wrapping semantic, syntactic, or I/O errors. - return &SemanticError{action: "unmarshal", JSONKind: val.Kind(), GoType: t, Err: err} - } - return nil - } - case textUnmarshalerType: - fncs.nonDefault = true - fncs.unmarshal = func(uo UnmarshalOptions, dec *Decoder, va addressableValue) error { - var flags valueFlags - val, err := dec.readValue(&flags) - if err != nil { - return err // must be a syntactic or I/O error - } - if val.Kind() != '"' { - err = errors.New("JSON value must be string type") - return &SemanticError{action: "unmarshal", JSONKind: val.Kind(), GoType: t, Err: err} - } - s := unescapeStringMayCopy(val, flags.isVerbatim()) - unmarshaler := va.addrWhen(needAddr).Interface().(encoding.TextUnmarshaler) - if err := unmarshaler.UnmarshalText(s); err != nil { - err = wrapSkipFunc(err, "unmarshal method") - // TODO: Avoid wrapping semantic, syntactic, or I/O errors. - return &SemanticError{action: "unmarshal", JSONKind: val.Kind(), GoType: t, Err: err} - } - return nil - } - } - - return fncs -} - -// implementsWhich is like t.Implements(ifaceType) for a list of interfaces, -// but checks whether either t or reflect.PointerTo(t) implements the interface. -// It returns the first interface type that matches and whether a value of t -// needs to be addressed first before it implements the interface. -func implementsWhich(t reflect.Type, ifaceTypes ...reflect.Type) (which reflect.Type, needAddr bool) { - for _, ifaceType := range ifaceTypes { - switch { - case t.Implements(ifaceType): - return ifaceType, false - case reflect.PointerTo(t).Implements(ifaceType): - return ifaceType, true - } - } - return nil, false -} - -// addrWhen returns va.Addr if addr is specified, otherwise it returns itself. -func (va addressableValue) addrWhen(addr bool) reflect.Value { - if addr { - return va.Addr() - } - return va.Value -} 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 fc8d5b007..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/arshal_time.go +++ /dev/null @@ -1,241 +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" - "strings" - "time" -) - -var ( - timeDurationType = reflect.TypeOf((*time.Duration)(nil)).Elem() - timeTimeType = reflect.TypeOf((*time.Time)(nil)).Elem() -) - -func makeTimeArshaler(fncs *arshaler, t reflect.Type) *arshaler { - // Ideally, time types would implement MarshalerV2 and UnmarshalerV2, - // 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 - marshalNanos := fncs.marshal - fncs.marshal = func(mo MarshalOptions, enc *Encoder, va addressableValue) error { - if mo.format != "" && mo.formatDepth == enc.tokens.depth() { - if mo.format == "nanos" { - mo.format = "" - return marshalNanos(mo, enc, va) - } else { - return newInvalidFormatError("marshal", t, mo.format) - } - } - - td := va.Interface().(time.Duration) - b := enc.UnusedBuffer() - b = append(b, '"') - b = append(b, td.String()...) // never contains special characters - b = append(b, '"') - return enc.WriteValue(b) - } - unmarshalNanos := fncs.unmarshal - fncs.unmarshal = func(uo UnmarshalOptions, dec *Decoder, va addressableValue) error { - // TODO: Should there be a flag that specifies that we can unmarshal - // from either form since there would be no ambiguity? - if uo.format != "" && uo.formatDepth == dec.tokens.depth() { - if uo.format == "nanos" { - uo.format = "" - return unmarshalNanos(uo, dec, va) - } else { - return newInvalidFormatError("unmarshal", t, uo.format) - } - } - - var flags valueFlags - td := va.Addr().Interface().(*time.Duration) - val, err := dec.readValue(&flags) - if err != nil { - return err - } - switch k := val.Kind(); k { - case 'n': - *td = time.Duration(0) - return nil - case '"': - val = unescapeStringMayCopy(val, flags.isVerbatim()) - td2, err := time.ParseDuration(string(val)) - if err != nil { - return &SemanticError{action: "unmarshal", JSONKind: k, GoType: t, Err: err} - } - *td = td2 - return nil - default: - return &SemanticError{action: "unmarshal", JSONKind: k, GoType: t} - } - } - case timeTimeType: - fncs.nonDefault = true - fncs.marshal = func(mo MarshalOptions, enc *Encoder, va addressableValue) error { - format := time.RFC3339Nano - isRFC3339 := true - if mo.format != "" && mo.formatDepth == enc.tokens.depth() { - var err error - format, isRFC3339, err = checkTimeFormat(mo.format) - if err != nil { - return &SemanticError{action: "marshal", GoType: t, Err: err} - } - } - - tt := va.Interface().(time.Time) - b := enc.UnusedBuffer() - b = append(b, '"') - b = tt.AppendFormat(b, format) - b = append(b, '"') - if isRFC3339 { - // 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. - var err error - switch b := b[len(`"`) : len(b)-len(`"`)]; { - case b[len("9999")] != '-': // year must be exactly 4 digits wide - err = 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 { - err = errors.New("timezone hour outside of range [0,23]") - } - } - if err != nil { - return &SemanticError{action: "marshal", GoType: t, Err: err} - } - return enc.WriteValue(b) // RFC 3339 never needs JSON escaping - } - // The format may contain special characters that need escaping. - // Verify that the result is a valid JSON string (common case), - // otherwise escape the string correctly (slower case). - if consumeSimpleString(b) != len(b) { - b, _ = appendString(nil, string(b[len(`"`):len(b)-len(`"`)]), true, nil) - } - return enc.WriteValue(b) - } - fncs.unmarshal = func(uo UnmarshalOptions, dec *Decoder, va addressableValue) error { - format := time.RFC3339 - isRFC3339 := true - if uo.format != "" && uo.formatDepth == dec.tokens.depth() { - var err error - format, isRFC3339, err = checkTimeFormat(uo.format) - if err != nil { - return &SemanticError{action: "unmarshal", GoType: t, Err: err} - } - } - - var flags valueFlags - tt := va.Addr().Interface().(*time.Time) - val, err := dec.readValue(&flags) - if err != nil { - return err - } - k := val.Kind() - switch k { - case 'n': - *tt = time.Time{} - return nil - case '"': - val = unescapeStringMayCopy(val, flags.isVerbatim()) - tt2, err := time.Parse(format, string(val)) - if isRFC3339 && err == nil { - // TODO(https://go.dev/issue/54580): RFC 3339 specifies - // the exact grammar of 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 val[len("2006-01-02T")+1] == ':': // hour must be two digits - err = newParseError(format, string(val), "15", string(val[len("2006-01-02T"):][:1]), "") - case val[len("2006-01-02T15:04:05")] == ',': // sub-second separator must be a period - err = newParseError(format, string(val), ".", ",", "") - case val[len(val)-1] != 'Z': - switch { - case parseDec2(val[len(val)-len("07:00"):]) >= 24: // timezone hour must be in range - err = newParseError(format, string(val), "Z07:00", string(val[len(val)-len("Z07:00"):]), ": timezone hour out of range") - case parseDec2(val[len(val)-len("00"):]) >= 60: // timezone minute must be in range - err = newParseError(format, string(val), "Z07:00", string(val[len(val)-len("Z07:00"):]), ": timezone minute out of range") - } - } - } - if err != nil { - return &SemanticError{action: "unmarshal", JSONKind: k, GoType: t, Err: err} - } - *tt = tt2 - return nil - default: - return &SemanticError{action: "unmarshal", JSONKind: k, GoType: t} - } - } - } - return fncs -} - -func checkTimeFormat(format string) (string, bool, error) { - // We assume that an exported constant in the time package will - // always start with an uppercase ASCII letter. - if len(format) > 0 && 'A' <= format[0] && format[0] <= 'Z' { - switch format { - case "ANSIC": - return time.ANSIC, false, nil - case "UnixDate": - return time.UnixDate, false, nil - case "RubyDate": - return time.RubyDate, false, nil - case "RFC822": - return time.RFC822, false, nil - case "RFC822Z": - return time.RFC822Z, false, nil - case "RFC850": - return time.RFC850, false, nil - case "RFC1123": - return time.RFC1123, false, nil - case "RFC1123Z": - return time.RFC1123Z, false, nil - case "RFC3339": - return time.RFC3339, true, nil - case "RFC3339Nano": - return time.RFC3339Nano, true, nil - case "Kitchen": - return time.Kitchen, false, nil - case "Stamp": - return time.Stamp, false, nil - case "StampMilli": - return time.StampMilli, false, nil - case "StampMicro": - return time.StampMicro, false, nil - case "StampNano": - return time.StampNano, false, nil - default: - // Reject any format that is an exported Go identifier in case - // new format constants are added to the time package. - if strings.TrimFunc(format, isLetterOrDigit) == "" { - return "", false, fmt.Errorf("undefined format layout: %v", format) - } - } - } - return format, false, nil -} - -// parseDec2 parses b as an unsigned, base-10, 2-digit number. -// It panics if len(b) < 2. The result is undefined if digits are not base-10. -func parseDec2(b []byte) byte { - return 10*(b[0]-'0') + (b[1] - '0') -} diff --git a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/decode.go b/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/decode.go deleted file mode 100644 index 0d68b3233..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/decode.go +++ /dev/null @@ -1,1655 +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" - "math" - "strconv" - "unicode/utf16" - "unicode/utf8" -) - -// 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 inlineable. -// -// - 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 inlineable 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. - -// DecodeOptions configures how JSON decoding operates. -// The zero value is equivalent to the default settings, -// which is compliant with both RFC 7493 and RFC 8259. -type DecodeOptions struct { - requireKeyedLiterals - nonComparable - - // AllowDuplicateNames specifies that JSON objects may contain - // duplicate member names. Disabling the duplicate name check may provide - // computational and performance benefits, but breaks compliance with - // RFC 7493, section 2.3. The input will still be compliant with RFC 8259, - // which leaves the handling of duplicate names as unspecified behavior. - AllowDuplicateNames bool - - // AllowInvalidUTF8 specifies that JSON strings may contain invalid UTF-8, - // which will be mangled as the Unicode replacement character, U+FFFD. - // This causes the decoder to break compliance with - // RFC 7493, section 2.1, and RFC 8259, section 8.1. - AllowInvalidUTF8 bool -} - -// 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. -// -// ReadToken and 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 ReadToken to obtain a -// string token for object names. -type Decoder struct { - state - decodeBuffer - options DecodeOptions - - stringCache *stringCache // only used when unmarshaling -} - -// 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) *Decoder { - return DecodeOptions{}.NewDecoder(r) -} - -// NewDecoder constructs a new streaming decoder reading from r -// configured with the provided options. -func (o DecodeOptions) NewDecoder(r io.Reader) *Decoder { - d := new(Decoder) - o.ResetDecoder(d, r) - return d -} - -// ResetDecoder resets a decoder such that it is reading afresh from r and -// configured with the provided options. -func (o DecodeOptions) ResetDecoder(d *Decoder, r io.Reader) { - if d == nil { - panic("json: invalid nil Decoder") - } - if r == nil { - panic("json: invalid nil io.Reader") - } - d.reset(nil, r, o) -} - -func (d *Decoder) reset(b []byte, r io.Reader, o DecodeOptions) { - d.state.reset() - d.decodeBuffer = decodeBuffer{buf: b, rd: r} - d.options = o -} - -// Reset resets a decoder such that it is reading afresh from r but -// keep any pre-existing decoder options. -func (d *Decoder) Reset(r io.Reader) { - d.options.ResetDecoder(d, r) -} - -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 *Decoder) 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 inlineable. - return pos == len(d.buf) -} - -// injectSyntacticErrorWithPosition wraps a SyntacticError with the position, -// otherwise it returns the error as is. -// It takes a position relative to the start of the start of d.buf. -func (d *decodeBuffer) injectSyntacticErrorWithPosition(err error, pos int) error { - if serr, ok := err.(*SyntacticError); ok { - return serr.withOffset(d.baseOffset + int64(pos)) - } - return err -} - -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)] } - -// PeekKind retrieves the next token kind, but does not advance the read offset. -// It returns 0 if there are no more tokens. -func (d *Decoder) 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 += 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, err - return invalidKind - } - } - - // Consume colon or comma. - var delim byte - if c := d.buf[pos]; c == ':' || c == ',' { - delim = c - pos += 1 - pos += consumeWhitespace(d.buf[pos:]) - if d.needMore(pos) { - if pos, err = d.consumeWhitespace(pos); err != nil { - d.peekPos, d.peekErr = -1, err - return invalidKind - } - } - } - next := Kind(d.buf[pos]).normalize() - if d.tokens.needDelim(next) != delim { - pos = d.prevEnd // restore position to right after leading whitespace - pos += consumeWhitespace(d.buf[pos:]) - err = d.tokens.checkDelim(delim, next) - err = d.injectSyntacticErrorWithPosition(err, pos) - d.peekPos, d.peekErr = -1, err - 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 -} - -// SkipValue is semantically equivalent to calling ReadValue and discarding -// the result except that memory is not wasted trying to hold the entire result. -func (d *Decoder) 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. - if _, err := d.ReadValue(); 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) { - // 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 += 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{}, err - } - } - - // Consume colon or comma. - var delim byte - if c := d.buf[pos]; c == ':' || c == ',' { - delim = c - pos += 1 - pos += consumeWhitespace(d.buf[pos:]) - if d.needMore(pos) { - if pos, err = d.consumeWhitespace(pos); err != nil { - return Token{}, err - } - } - } - next = Kind(d.buf[pos]).normalize() - if d.tokens.needDelim(next) != delim { - pos = d.prevEnd // restore position to right after leading whitespace - pos += consumeWhitespace(d.buf[pos:]) - err = d.tokens.checkDelim(delim, next) - return Token{}, d.injectSyntacticErrorWithPosition(err, pos) - } - } - - // Handle the next token. - var n int - switch next { - case 'n': - if consumeNull(d.buf[pos:]) == 0 { - pos, err = d.consumeLiteral(pos, "null") - if err != nil { - return Token{}, d.injectSyntacticErrorWithPosition(err, pos) - } - } else { - pos += len("null") - } - if err = d.tokens.appendLiteral(); err != nil { - return Token{}, d.injectSyntacticErrorWithPosition(err, pos-len("null")) // report position at start of literal - } - d.prevStart, d.prevEnd = pos, pos - return Null, nil - - case 'f': - if consumeFalse(d.buf[pos:]) == 0 { - pos, err = d.consumeLiteral(pos, "false") - if err != nil { - return Token{}, d.injectSyntacticErrorWithPosition(err, pos) - } - } else { - pos += len("false") - } - if err = d.tokens.appendLiteral(); err != nil { - return Token{}, d.injectSyntacticErrorWithPosition(err, pos-len("false")) // report position at start of literal - } - d.prevStart, d.prevEnd = pos, pos - return False, nil - - case 't': - if consumeTrue(d.buf[pos:]) == 0 { - pos, err = d.consumeLiteral(pos, "true") - if err != nil { - return Token{}, d.injectSyntacticErrorWithPosition(err, pos) - } - } else { - pos += len("true") - } - if err = d.tokens.appendLiteral(); err != nil { - return Token{}, d.injectSyntacticErrorWithPosition(err, pos-len("true")) // report position at start of literal - } - d.prevStart, d.prevEnd = pos, pos - return True, nil - - case '"': - var flags valueFlags // TODO: Preserve this in Token? - if n = 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{}, d.injectSyntacticErrorWithPosition(err, pos) - } - } else { - pos += n - } - if !d.options.AllowDuplicateNames && d.tokens.last.needObjectName() { - if !d.tokens.last.isValidNamespace() { - return Token{}, errInvalidNamespace - } - if d.tokens.last.isActiveNamespace() && !d.namespaces.last().insertQuoted(d.buf[pos-n:pos], flags.isVerbatim()) { - err = &SyntacticError{str: "duplicate name " + string(d.buf[pos-n:pos]) + " in object"} - return Token{}, d.injectSyntacticErrorWithPosition(err, pos-n) // 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{}, d.injectSyntacticErrorWithPosition(err, pos-n) // 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 = 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{}, d.injectSyntacticErrorWithPosition(err, pos) - } - } else { - pos += n - } - if err = d.tokens.appendNumber(); err != nil { - return Token{}, d.injectSyntacticErrorWithPosition(err, pos-n) // 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{}, d.injectSyntacticErrorWithPosition(err, pos) - } - if !d.options.AllowDuplicateNames { - d.names.push() - d.namespaces.push() - } - pos += 1 - d.prevStart, d.prevEnd = pos, pos - return ObjectStart, nil - - case '}': - if err = d.tokens.popObject(); err != nil { - return Token{}, d.injectSyntacticErrorWithPosition(err, pos) - } - if !d.options.AllowDuplicateNames { - d.names.pop() - d.namespaces.pop() - } - pos += 1 - d.prevStart, d.prevEnd = pos, pos - return ObjectEnd, nil - - case '[': - if err = d.tokens.pushArray(); err != nil { - return Token{}, d.injectSyntacticErrorWithPosition(err, pos) - } - pos += 1 - d.prevStart, d.prevEnd = pos, pos - return ArrayStart, nil - - case ']': - if err = d.tokens.popArray(); err != nil { - return Token{}, d.injectSyntacticErrorWithPosition(err, pos) - } - pos += 1 - d.prevStart, d.prevEnd = pos, pos - return ArrayEnd, nil - - default: - err = newInvalidCharacterError(d.buf[pos:], "at start of token") - return Token{}, d.injectSyntacticErrorWithPosition(err, pos) - } -} - -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) set(f2 valueFlags) { *f |= f2 } -func (f valueFlags) isVerbatim() bool { return f&stringNonVerbatim == 0 } -func (f valueFlags) isCanonical() bool { return f&stringNonCanonical == 0 } - -// ReadValue returns the next raw JSON value, advancing the read offset. -// The value is stripped of any leading or trailing whitespace. -// 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() (RawValue, error) { - var flags valueFlags - return d.readValue(&flags) -} -func (d *Decoder) readValue(flags *valueFlags) (RawValue, 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 += 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, err - } - } - - // Consume colon or comma. - var delim byte - if c := d.buf[pos]; c == ':' || c == ',' { - delim = c - pos += 1 - pos += consumeWhitespace(d.buf[pos:]) - if d.needMore(pos) { - if pos, err = d.consumeWhitespace(pos); err != nil { - return nil, err - } - } - } - next = Kind(d.buf[pos]).normalize() - if d.tokens.needDelim(next) != delim { - pos = d.prevEnd // restore position to right after leading whitespace - pos += consumeWhitespace(d.buf[pos:]) - err = d.tokens.checkDelim(delim, next) - return nil, d.injectSyntacticErrorWithPosition(err, pos) - } - } - - // Handle the next value. - oldAbsPos := d.baseOffset + int64(pos) - pos, err = d.consumeValue(flags, pos) - newAbsPos := d.baseOffset + int64(pos) - n := int(newAbsPos - oldAbsPos) - if err != nil { - return nil, d.injectSyntacticErrorWithPosition(err, pos) - } - switch next { - case 'n', 't', 'f': - err = d.tokens.appendLiteral() - case '"': - if !d.options.AllowDuplicateNames && d.tokens.last.needObjectName() { - 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 = &SyntacticError{str: "duplicate name " + string(d.buf[pos-n:pos]) + " in object"} - 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, d.injectSyntacticErrorWithPosition(err, pos-n) // report position at start of value - } - d.prevEnd = pos - d.prevStart = pos - n - return d.buf[pos-n : pos : pos], nil -} - -// checkEOF verifies that the input has no more data. -func (d *Decoder) checkEOF() error { - switch pos, err := d.consumeWhitespace(d.prevEnd); err { - case nil: - return newInvalidCharacterError(d.buf[pos:], "after top-level value") - 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 += 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 *Decoder) consumeWhitespace(pos int) (newPos int, err error) { - for { - pos += 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 *Decoder) consumeValue(flags *valueFlags, pos int) (newPos int, err error) { - for { - var n int - var err error - switch next := Kind(d.buf[pos]).normalize(); next { - case 'n': - if n = consumeNull(d.buf[pos:]); n == 0 { - n, err = consumeLiteral(d.buf[pos:], "null") - } - case 'f': - if n = consumeFalse(d.buf[pos:]); n == 0 { - n, err = consumeLiteral(d.buf[pos:], "false") - } - case 't': - if n = consumeTrue(d.buf[pos:]); n == 0 { - n, err = consumeLiteral(d.buf[pos:], "true") - } - case '"': - if n = 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 = consumeSimpleNumber(d.buf[pos:]); n == 0 || d.needMore(pos+n) { - return d.consumeNumber(pos) - } - case '{': - return d.consumeObject(flags, pos) - case '[': - return d.consumeArray(flags, pos) - default: - return pos, 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, 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 *Decoder) consumeLiteral(pos int, lit string) (newPos int, err error) { - for { - n, err := 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, 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 *Decoder) consumeString(flags *valueFlags, pos int) (newPos int, err error) { - var n int - for { - n, err = consumeStringResumable(flags, d.buf[pos:], n, !d.options.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, 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 *Decoder) consumeNumber(pos int) (newPos int, err error) { - var n int - var state consumeNumberState - for { - n, state, err = 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 *Decoder) consumeObject(flags *valueFlags, pos int) (newPos int, err error) { - var n int - var names *objectNamespace - if !d.options.AllowDuplicateNames { - d.namespaces.push() - defer d.namespaces.pop() - names = d.namespaces.last() - } - - // Handle before start. - if d.buf[pos] != '{' { - panic("BUG: consumeObject must be called with a buffer that starts with '{'") - } - pos++ - - // Handle after start. - pos += 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 - } - - for { - // Handle before name. - pos += consumeWhitespace(d.buf[pos:]) - if d.needMore(pos) { - if pos, err = d.consumeWhitespace(pos); err != nil { - return pos, err - } - } - var flags2 valueFlags - if n = 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.set(flags2) - if err != nil { - return pos, err - } - } else { - pos += n - } - if !d.options.AllowDuplicateNames && !names.insertQuoted(d.buf[pos-n:pos], flags2.isVerbatim()) { - return pos - n, &SyntacticError{str: "duplicate name " + string(d.buf[pos-n:pos]) + " in object"} - } - - // Handle after name. - pos += consumeWhitespace(d.buf[pos:]) - if d.needMore(pos) { - if pos, err = d.consumeWhitespace(pos); err != nil { - return pos, err - } - } - if d.buf[pos] != ':' { - return pos, newInvalidCharacterError(d.buf[pos:], "after object name (expecting ':')") - } - pos++ - - // Handle before value. - pos += 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) - if err != nil { - return pos, err - } - - // Handle after value. - pos += 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, 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 *Decoder) consumeArray(flags *valueFlags, pos int) (newPos int, err error) { - // Handle before start. - if d.buf[pos] != '[' { - panic("BUG: consumeArray must be called with a buffer that starts with '['") - } - pos++ - - // Handle after start. - pos += 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 - } - - for { - // Handle before value. - pos += 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) - if err != nil { - return pos, err - } - - // Handle after value. - pos += 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, newInvalidCharacterError(d.buf[pos:], "after array value (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.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.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 ObjectStart or ArrayStart token is encountered -// and decremented whenever an ObjectEnd or ArrayEnd 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.tokens.depth() - 1 -} - -// StackIndex returns information about the specified stack level. -// It must be a number between 0 and 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, int) { - // NOTE: Keep in sync with Encoder.StackIndex. - switch s := d.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. -// Object names are only present if AllowDuplicateNames is false, otherwise -// object members are represented using their index within the object. -func (d *Decoder) StackPointer() string { - d.names.copyQuotedBuffer(d.buf) - return string(d.appendStackPointer(nil)) -} - -// 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 inlineable. - 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 inlineable. - 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 inlineable. - 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 inlineable. - 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:], "within 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. -func consumeSimpleString(b []byte) (n int) { - // NOTE: The arguments and logic are kept simple to keep this inlineable. - if len(b) > 0 && b[0] == '"' { - n++ - for len(b) > n && (' ' <= b[n] && b[n] != '\\' && b[n] != '"' && b[n] < utf8.RuneSelf) { - n++ - } - if len(b) > 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.set(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.set(stringNonCanonical) - n += 2 - case '"', '\\', 'b', 'f', 'n', 'r', 't': - n += 2 - case 'u': - if uint(len(b)) < uint(n+6) { - if !hasEscapeSequencePrefix(b[n:]) { - flags.set(stringNonCanonical) - return n, &SyntacticError{str: "invalid escape sequence " + strconv.Quote(string(b[n:])) + " within string"} - } - return resumeOffset, io.ErrUnexpectedEOF - } - v1, ok := parseHexUint16(b[n+2 : n+6]) - if !ok { - flags.set(stringNonCanonical) - return n, &SyntacticError{str: "invalid escape sequence " + strconv.Quote(string(b[n:n+6])) + " within string"} - } - // 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.set(stringNonCanonical) - default: - // \uFFFF notation only permitted for control characters. - if v1 >= ' ' { - flags.set(stringNonCanonical) - } else { - // \uFFFF notation must be lower case. - for _, c := range b[n+2 : n+6] { - if 'A' <= c && c <= 'F' { - flags.set(stringNonCanonical) - } - } - } - } - n += 6 - - if validateUTF8 && utf16.IsSurrogate(rune(v1)) { - if uint(len(b)) >= uint(n+2) && (b[n] != '\\' || b[n+1] != 'u') { - return n, &SyntacticError{str: "invalid unpaired surrogate half within string"} - } - if uint(len(b)) < uint(n+6) { - if !hasEscapeSequencePrefix(b[n:]) { - flags.set(stringNonCanonical) - return n, &SyntacticError{str: "invalid escape sequence " + strconv.Quote(string(b[n:])) + " within string"} - } - return resumeOffset, io.ErrUnexpectedEOF - } - v2, ok := parseHexUint16(b[n+2 : n+6]) - if !ok { - return n, &SyntacticError{str: "invalid escape sequence " + strconv.Quote(string(b[n:n+6])) + " within string"} - } - if utf16.DecodeRune(rune(v1), rune(v2)) == utf8.RuneError { - return n, &SyntacticError{str: "invalid surrogate pair in string"} - } - n += 6 - } - default: - flags.set(stringNonCanonical) - return n, &SyntacticError{str: "invalid escape sequence " + strconv.Quote(string(b[n:n+2])) + " within string"} - } - // Handle invalid UTF-8. - case r == utf8.RuneError: - if !utf8.FullRune(b[n:]) { - return n, io.ErrUnexpectedEOF - } - flags.set(stringNonVerbatim | stringNonCanonical) - if validateUTF8 { - return n, &SyntacticError{str: "invalid UTF-8 within string"} - } - n++ - // Handle invalid control characters. - case r < ' ': - flags.set(stringNonVerbatim | stringNonCanonical) - return n, newInvalidCharacterError(b[n:], "within string (expecting non-control character)") - default: - panic("BUG: unhandled character " + quoteRune(b[n:])) - } - } - return n, io.ErrUnexpectedEOF -} - -// hasEscapeSequencePrefix reports whether b is possibly -// the truncated prefix of a \uFFFF escape sequence. -func hasEscapeSequencePrefix(b []byte) bool { - for i, c := range b { - switch { - case i == 0 && c != '\\': - return false - case i == 1 && c != 'u': - return false - case i >= 2 && i < 6 && !('0' <= c && c <= '9') && !('a' <= c && c <= 'f') && !('A' <= c && c <= 'F'): - return false - } - } - return true -} - -// unescapeString 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. -// The input must be an entire JSON string with no surrounding whitespace. -func unescapeString(dst, src []byte) (v []byte, ok bool) { - // Consume leading double quote. - if uint(len(src)) == 0 || src[0] != '"' { - return dst, false - } - i, n := 1, 1 - - // Consume every character until completion. - 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) { - break - } - - // Check for terminating double quote. - if src[n] == '"' { - dst = append(dst, src[i:n]...) - n++ - return dst, len(src) == n - } - - switch r, rn := utf8.DecodeRune(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]...) - if r < ' ' { - return dst, false // invalid control character or unescaped quote - } - - // Handle escape sequence. - if uint(len(src)) < uint(n+2) { - return dst, false // truncated escape sequence - } - 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) { - return dst, false // truncated escape sequence - } - v1, ok := parseHexUint16(src[n+2 : n+6]) - if !ok { - return dst, false // invalid escape sequence - } - 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) && src[n+0] == '\\' && src[n+1] == 'u' { - if v2, ok := parseHexUint16(src[n+2 : n+6]); ok { - if r = utf16.DecodeRune(rune(v1), rune(v2)); r != utf8.RuneError { - n += 6 - } - } - } - } - - dst = utf8.AppendRune(dst, r) - default: - return dst, false // invalid escape sequence - } - i = n - // Handle invalid UTF-8. - case r == utf8.RuneError: - // NOTE: An unescaped string may be longer than the escaped string - // because invalid UTF-8 bytes are being replaced. - dst = append(dst, src[i:n]...) - dst = append(dst, "\uFFFD"...) - n += rn - i = n - // Handle invalid control characters. - case r < ' ': - dst = append(dst, src[i:n]...) - return dst, false // invalid control character or unescaped quote - default: - panic("BUG: unhandled character " + quoteRune(src[n:])) - } - } - dst = append(dst, src[i:n]...) - return dst, false // truncated input -} - -// unescapeStringMayCopy 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. -func unescapeStringMayCopy(b []byte, isVerbatim bool) []byte { - // NOTE: The arguments and logic are kept simple to keep this inlineable. - if isVerbatim { - return b[len(`"`) : len(b)-len(`"`)] - } - b, _ = unescapeString(make([]byte, 0, len(b)), 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 inlineable. - 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 len(b) == 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 len(b) > n && ('0' <= b[n] && b[n] <= '9') { - n++ - } - if len(b) == 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 len(b) > 0 && b[0] == '-' { - n++ - } - switch { - case len(b) == n: - return resumeOffset, beforeIntegerDigits, io.ErrUnexpectedEOF - case b[n] == '0': - n++ - state = beforeFractionalDigits - case '1' <= b[n] && b[n] <= '9': - n++ - for len(b) > n && ('0' <= b[n] && b[n] <= '9') { - n++ - } - state = withinIntegerDigits - default: - return n, state, newInvalidCharacterError(b[n:], "within number (expecting digit)") - } - - // Consume optional fractional component. -beforeFractional: - if len(b) > n && b[n] == '.' { - resumeOffset = n - n++ - switch { - case len(b) == n: - return resumeOffset, beforeFractionalDigits, io.ErrUnexpectedEOF - case '0' <= b[n] && b[n] <= '9': - n++ - default: - return n, state, newInvalidCharacterError(b[n:], "within number (expecting digit)") - } - for len(b) > n && ('0' <= b[n] && b[n] <= '9') { - n++ - } - state = withinFractionalDigits - } - - // Consume optional exponent component. -beforeExponent: - if len(b) > n && (b[n] == 'e' || b[n] == 'E') { - resumeOffset = n - n++ - if len(b) > n && (b[n] == '-' || b[n] == '+') { - n++ - } - switch { - case len(b) == n: - return resumeOffset, beforeExponentDigits, io.ErrUnexpectedEOF - case '0' <= b[n] && b[n] <= '9': - n++ - default: - return n, state, newInvalidCharacterError(b[n:], "within number (expecting digit)") - } - for len(b) > 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(b []byte) (v uint16, ok bool) { - if len(b) != 4 { - return 0, false - } - for _, c := range b[:4] { - 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 -} - -// parseDecUint is similar to strconv.ParseUint, -// but operates directly on []byte and is optimized for base-10. -// If the number is syntactically valid but overflows uint64, -// then it returns (math.MaxUint64, false). -// See https://go.dev/issue/42429. -func parseDecUint(b []byte) (v uint64, ok bool) { - // Overflow logic is based on strconv/atoi.go:138-149 from Go1.15, where: - // - cutoff is equal to math.MaxUint64/10+1, and - // - the n1 > maxVal check is unnecessary - // since maxVal is equivalent to math.MaxUint64. - var n int - var overflow bool - for len(b) > n && ('0' <= b[n] && b[n] <= '9') { - overflow = overflow || v >= math.MaxUint64/10+1 - v *= 10 - - v1 := v + uint64(b[n]-'0') - overflow = overflow || v1 < v - v = v1 - - n++ - } - if n == 0 || len(b) != n { - return 0, false - } - if overflow { - 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) { - // Fast path for exact integer numbers which fit in the - // 24-bit or 53-bit significand of a float32 or float64. - var negLen int // either 0 or 1 - if len(b) > 0 && b[0] == '-' { - negLen = 1 - } - u, ok := parseDecUint(b[negLen:]) - if ok && ((bits == 32 && u <= 1<<24) || (bits == 64 && u <= 1<<53)) { - return math.Copysign(float64(u), float64(-1*negLen)), true - } - - // Note that the []byte->string conversion unfortunately allocates. - // See https://go.dev/issue/42429 for more information. - fv, err := strconv.ParseFloat(string(b), bits) - if math.IsInf(fv, 0) { - switch { - case bits == 32 && math.IsInf(fv, +1): - return +math.MaxFloat32, true - case bits == 64 && math.IsInf(fv, +1): - return +math.MaxFloat64, true - case bits == 32 && math.IsInf(fv, -1): - return -math.MaxFloat32, true - case bits == 64 && math.IsInf(fv, -1): - return -math.MaxFloat64, true - } - } - return fv, err == nil -} 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 e4eefa3de..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/doc.go +++ /dev/null @@ -1,182 +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 serialization 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. -// -// # Terminology -// -// This package uses the terms "encode" and "decode" for syntactic functionality -// that is concerned with processing JSON based on its grammar, and -// uses the terms "marshal" and "unmarshal" for semantic functionality -// that determines the meaning of JSON values as Go values and vice-versa. -// It aims 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. -// -// # 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 UnmarshalOptions.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. -// -// 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 -// MarshalOptions.StringifyNumbers and UnmarshalOptions.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 either a JSON number or -// a JSON string containing a JSON number. -// This extra level of encoding is often necessary since -// many JSON parsers cannot precisely represent 64-bit integers. -// -// - nocase: When unmarshaling, the "nocase" option specifies that -// if the JSON object name does not exactly match the JSON name -// for any of the struct fields, then it attempts to match the struct field -// using a case-insensitive match that also ignores dashes and underscores. -// If multiple fields match, the first declared field in breadth-first order -// takes precedence. This option has no effect when marshaling. -// -// - 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), RawValue, 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 RawValue 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 RawValue, map[string]T, or an unnamed pointer to such types. -// If MarshalOptions.DiscardUnknownMembers is specified when marshaling, -// the contents of this field are ignored. -// If UnmarshalOptions.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., netip.Addr) or have an IsZero method (e.g., time.Time). -// -// 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, -// then all of those fields 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:"-"`. -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/encode.go b/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/encode.go deleted file mode 100644 index 5b81ca15a..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/encode.go +++ /dev/null @@ -1,1170 +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" - "io" - "math" - "math/bits" - "strconv" - "unicode/utf16" - "unicode/utf8" -) - -// EncodeOptions configures how JSON encoding operates. -// The zero value is equivalent to the default settings, -// which is compliant with both RFC 7493 and RFC 8259. -type EncodeOptions struct { - requireKeyedLiterals - nonComparable - - // multiline specifies whether the encoder should emit multiline output. - multiline bool - - // omitTopLevelNewline specifies whether to omit the newline - // that is appended after every top-level JSON value when streaming. - omitTopLevelNewline bool - - // 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 output will still be compliant with RFC 8259, - // which leaves the handling of duplicate names as unspecified behavior. - AllowDuplicateNames bool - - // 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 to break compliance with - // RFC 7493, section 2.1, and RFC 8259, section 8.1. - AllowInvalidUTF8 bool - - // preserveRawStrings specifies that WriteToken and WriteValue should not - // reformat any JSON string, but keep the formatting verbatim. - preserveRawStrings bool - - // canonicalizeNumbers specifies that WriteToken and WriteValue should - // reformat any JSON numbers according to RFC 8785, section 3.2.2.3. - canonicalizeNumbers bool - - // EscapeRune reports whether the provided character should be escaped - // as a hexadecimal Unicode codepoint (e.g., \ufffd). - // If nil, the shortest and simplest encoding will be used, - // which is also the formatting specified by RFC 8785, section 3.2.2.2. - EscapeRune func(rune) bool - - // Indent (if non-empty) 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 according to the indentation nesting. - // It may only be composed of space or tab characters. - Indent string - - // IndentPrefix is prepended to each line within a JSON object or array. - // The purpose of the indent prefix is to encode data that can more easily - // be embedded inside other formatted JSON data. - // It may only be composed of space or tab characters. - // It is ignored if Indent is empty. - IndentPrefix string -} - -// 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. -// -// WriteToken and 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(ObjectStart) // { -// e.WriteToken(String("name")) // "name" -// e.WriteToken(String("value")) // "value" -// e.WriteValue(RawValue(`"array"`)) // "array" -// e.WriteToken(ArrayStart) // [ -// e.WriteToken(Null) // null -// e.WriteToken(False) // false -// e.WriteValue(RawValue("true")) // true -// e.WriteToken(Float(3.14159)) // 3.14159 -// e.WriteToken(ArrayEnd) // ] -// e.WriteValue(RawValue(`"object"`)) // "object" -// e.WriteValue(RawValue(`{"k":"v"}`)) // {"k":"v"} -// e.WriteToken(ObjectEnd) // } -// -// 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 WriteToken with a string -// for object names. -type Encoder struct { - state - encodeBuffer - options EncodeOptions - - seenPointers seenPointers // only used when marshaling -} - -// 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 RawValue size passed to WriteValue. - maxValue int - // unusedCache is the buffer returned by the UnusedBuffer method. - unusedCache []byte - // 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. -func NewEncoder(w io.Writer) *Encoder { - return EncodeOptions{}.NewEncoder(w) -} - -// 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 (o EncodeOptions) NewEncoder(w io.Writer) *Encoder { - e := new(Encoder) - o.ResetEncoder(e, w) - return e -} - -// ResetEncoder resets an encoder such that it is writing afresh to w and -// configured with the provided options. -func (o EncodeOptions) ResetEncoder(e *Encoder, w io.Writer) { - if e == nil { - panic("json: invalid nil Encoder") - } - if w == nil { - panic("json: invalid nil io.Writer") - } - e.reset(nil, w, o) -} - -func (e *Encoder) reset(b []byte, w io.Writer, o EncodeOptions) { - if len(o.Indent) > 0 { - o.multiline = true - if s := trimLeftSpaceTab(o.IndentPrefix); len(s) > 0 { - panic("json: invalid character " + quoteRune([]byte(s)) + " in indent prefix") - } - if s := trimLeftSpaceTab(o.Indent); len(s) > 0 { - panic("json: invalid character " + quoteRune([]byte(s)) + " in indent") - } - } - e.state.reset() - e.encodeBuffer = encodeBuffer{buf: b, wr: w, bufStats: e.bufStats} - e.options = o - if bb, ok := w.(*bytes.Buffer); ok && bb != nil { - e.buf = bb.Bytes()[bb.Len():] // alias the unused buffer of bb - } -} - -// Reset resets an encoder such that it is writing afresh to w but -// keeps any pre-existing encoder options. -func (e *Encoder) Reset(w io.Writer) { - e.options.ResetEncoder(e, w) -} - -// needFlush determines whether to flush at this point. -func (e *Encoder) needFlush() bool { - // NOTE: This function is carefully written to be inlineable. - - // 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 *Encoder) 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.options.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.Cap() - bb.Len(); avail < bb.Len()/4 { - bb.Grow(avail + 1) - } - - e.buf = bb.Bytes()[bb.Len():] // alias the unused buffer of bb - 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 (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 *Encoder) avoidFlush() bool { - switch { - case e.tokens.last.length() == 0: - // Never flush after ObjectStart or ArrayStart 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 *Encoder) 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 = trimSuffixWhitespace(b) - b = trimSuffixByte(b, ':') - b = trimSuffixString(b) - b = trimSuffixWhitespace(b) - b = 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.options.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 *Encoder) 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 := trimSuffixString(e.buf) - isVerbatim := bytes.IndexByte(e.buf[len(b):], '\\') < 0 - name := string(unescapeStringMayCopy(e.buf[len(b):], isVerbatim)) - e.buf = trimSuffixWhitespace(b) - - // Undo state changes. - e.tokens.last.decrement() - if !e.options.AllowDuplicateNames { - if e.tokens.last.isActiveNamespace() { - e.namespaces.last().removeLast() - } - e.names.clearLast() - } - return name -} - -func trimSuffixWhitespace(b []byte) []byte { - // NOTE: The arguments and logic are kept simple to keep this inlineable. - n := len(b) - 1 - for n >= 0 && (b[n] == ' ' || b[n] == '\t' || b[n] == '\r' || b[n] == '\n') { - n-- - } - return b[:n+1] -} - -func trimSuffixString(b []byte) []byte { - // NOTE: The arguments and logic are kept simple to keep this inlineable. - 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 -} - -func hasSuffixByte(b []byte, c byte) bool { - // NOTE: The arguments and logic are kept simple to keep this inlineable. - return len(b) > 0 && b[len(b)-1] == c -} - -func trimSuffixByte(b []byte, c byte) []byte { - // NOTE: The arguments and logic are kept simple to keep this inlineable. - if len(b) > 0 && b[len(b)-1] == c { - return b[:len(b)-1] - } - return b -} - -// 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. -func (e *Encoder) 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.options.multiline { - b = e.appendWhitespace(b, k) - } - - // 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 '"': - n0 := len(b) // offset before calling t.appendString - if b, err = t.appendString(b, !e.options.AllowInvalidUTF8, e.options.preserveRawStrings, e.options.EscapeRune); err != nil { - break - } - if !e.options.AllowDuplicateNames && e.tokens.last.needObjectName() { - if !e.tokens.last.isValidNamespace() { - err = errInvalidNamespace - break - } - if e.tokens.last.isActiveNamespace() && !e.namespaces.last().insertQuoted(b[n0:], false) { - err = &SyntacticError{str: "duplicate name " + string(b[n0:]) + " in object"} - break - } - e.names.replaceLastQuotedOffset(n0) // only replace if insertQuoted succeeds - } - err = e.tokens.appendString() - case '0': - if b, err = t.appendNumber(b, e.options.canonicalizeNumbers); err != nil { - break - } - err = e.tokens.appendNumber() - case '{': - b = append(b, '{') - if err = e.tokens.pushObject(); err != nil { - break - } - if !e.options.AllowDuplicateNames { - e.names.push() - e.namespaces.push() - } - case '}': - b = append(b, '}') - if err = e.tokens.popObject(); err != nil { - break - } - if !e.options.AllowDuplicateNames { - e.names.pop() - e.namespaces.pop() - } - case '[': - b = append(b, '[') - err = e.tokens.pushArray() - case ']': - b = append(b, ']') - err = e.tokens.popArray() - default: - return &SyntacticError{str: "invalid json.Token"} - } - if err != nil { - return err - } - - // Finish off the buffer and store it back into e. - e.buf = b - if e.needFlush() { - return e.flush() - } - return nil -} - -const ( - rawIntNumber = -1 - rawUintNumber = -2 -) - -// writeNumber is specialized version of WriteToken, but optimized for numbers. -// As a special-case, if bits is -1 or -2, it will treat v as -// the raw-encoded bits of an int64 or uint64, respectively. -// It is only called from arshal_default.go. -func (e *Encoder) writeNumber(v float64, bits int, quote bool) 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, '0') - if e.options.multiline { - b = e.appendWhitespace(b, '0') - } - - if quote { - // Append the value to the output. - n0 := len(b) // offset before appending the number - b = append(b, '"') - switch bits { - case rawIntNumber: - b = strconv.AppendInt(b, int64(math.Float64bits(v)), 10) - case rawUintNumber: - b = strconv.AppendUint(b, uint64(math.Float64bits(v)), 10) - default: - b = appendNumber(b, v, bits) - } - b = append(b, '"') - - // Escape the string if necessary. - if e.options.EscapeRune != nil { - b2 := append(e.unusedCache, b[n0+len(`"`):len(b)-len(`"`)]...) - b, _ = appendString(b[:n0], string(b2), false, e.options.EscapeRune) - e.unusedCache = b2[:0] - } - - // Update the state machine. - if !e.options.AllowDuplicateNames && e.tokens.last.needObjectName() { - if !e.tokens.last.isValidNamespace() { - return errInvalidNamespace - } - if e.tokens.last.isActiveNamespace() && !e.namespaces.last().insertQuoted(b[n0:], false) { - return &SyntacticError{str: "duplicate name " + string(b[n0:]) + " in object"} - } - e.names.replaceLastQuotedOffset(n0) // only replace if insertQuoted succeeds - } - if err := e.tokens.appendString(); err != nil { - return err - } - } else { - switch bits { - case rawIntNumber: - b = strconv.AppendInt(b, int64(math.Float64bits(v)), 10) - case rawUintNumber: - b = strconv.AppendUint(b, uint64(math.Float64bits(v)), 10) - default: - b = appendNumber(b, v, bits) - } - if err := e.tokens.appendNumber(); err != nil { - return err - } - } - - // 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. -// -// 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. -func (e *Encoder) WriteValue(v RawValue) 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.options.multiline { - b = e.appendWhitespace(b, k) - } - - // Append the value the output. - var err error - v = v[consumeWhitespace(v):] - n0 := len(b) // offset before calling e.reformatValue - b, v, err = e.reformatValue(b, v, e.tokens.depth()) - if err != nil { - return err - } - v = v[consumeWhitespace(v):] - if len(v) > 0 { - return newInvalidCharacterError(v[0:], "after top-level value") - } - - // Append the kind to the state machine. - switch k { - case 'n', 'f', 't': - err = e.tokens.appendLiteral() - case '"': - if !e.options.AllowDuplicateNames && e.tokens.last.needObjectName() { - if !e.tokens.last.isValidNamespace() { - err = errInvalidNamespace - break - } - if e.tokens.last.isActiveNamespace() && !e.namespaces.last().insertQuoted(b[n0:], false) { - err = &SyntacticError{str: "duplicate name " + string(b[n0:]) + " in object"} - break - } - e.names.replaceLastQuotedOffset(n0) // 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()) - } - 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 err != nil { - return err - } - - // Finish off the buffer and store it back into e. - e.buf = b - if e.needFlush() { - return e.flush() - } - return nil -} - -// appendWhitespace appends whitespace that immediately precedes the next token. -func (e *Encoder) appendWhitespace(b []byte, next Kind) []byte { - if e.tokens.needDelim(next) == ':' { - return append(b, ' ') - } else { - return e.appendIndent(b, e.tokens.needIndent(next)) - } -} - -// appendIndent appends the appropriate number of indentation characters -// for the current nested level, n. -func (e *Encoder) appendIndent(b []byte, n int) []byte { - if n == 0 { - return b - } - b = append(b, '\n') - b = append(b, e.options.IndentPrefix...) - for ; n > 1; n-- { - b = append(b, e.options.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 updated versions of dst and src. -func (e *Encoder) reformatValue(dst []byte, src RawValue, depth int) ([]byte, RawValue, error) { - // TODO: Should this update valueFlags as input? - if len(src) == 0 { - return dst, src, io.ErrUnexpectedEOF - } - var n int - var err error - switch k := Kind(src[0]).normalize(); k { - case 'n': - if n = consumeNull(src); n == 0 { - n, err = consumeLiteral(src, "null") - } - case 'f': - if n = consumeFalse(src); n == 0 { - n, err = consumeLiteral(src, "false") - } - case 't': - if n = consumeTrue(src); n == 0 { - n, err = consumeLiteral(src, "true") - } - case '"': - if n := consumeSimpleString(src); n > 0 && e.options.EscapeRune == nil { - dst, src = append(dst, src[:n]...), src[n:] // copy simple strings verbatim - return dst, src, nil - } - return reformatString(dst, src, !e.options.AllowInvalidUTF8, e.options.preserveRawStrings, e.options.EscapeRune) - case '0': - if n := consumeSimpleNumber(src); n > 0 && !e.options.canonicalizeNumbers { - dst, src = append(dst, src[:n]...), src[n:] // copy simple numbers verbatim - return dst, src, nil - } - return reformatNumber(dst, src, e.options.canonicalizeNumbers) - case '{': - return e.reformatObject(dst, src, depth) - case '[': - return e.reformatArray(dst, src, depth) - default: - return dst, src, newInvalidCharacterError(src, "at start of value") - } - if err != nil { - return dst, src, err - } - dst, src = append(dst, src[:n]...), src[n:] - return dst, src, nil -} - -// 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 updated versions of dst and src. -func (e *Encoder) reformatObject(dst []byte, src RawValue, depth int) ([]byte, RawValue, error) { - // Append object start. - if src[0] != '{' { - panic("BUG: reformatObject must be called with a buffer that starts with '{'") - } - dst, src = append(dst, '{'), src[1:] - - // Append (possible) object end. - src = src[consumeWhitespace(src):] - if len(src) == 0 { - return dst, src, io.ErrUnexpectedEOF - } - if src[0] == '}' { - dst, src = append(dst, '}'), src[1:] - return dst, src, nil - } - - var err error - var names *objectNamespace - if !e.options.AllowDuplicateNames { - e.namespaces.push() - defer e.namespaces.pop() - names = e.namespaces.last() - } - depth++ - for { - // Append optional newline and indentation. - if e.options.multiline { - dst = e.appendIndent(dst, depth) - } - - // Append object name. - src = src[consumeWhitespace(src):] - if len(src) == 0 { - return dst, src, io.ErrUnexpectedEOF - } - n0 := len(dst) // offset before calling reformatString - n := consumeSimpleString(src) - if n > 0 && e.options.EscapeRune == nil { - dst, src = append(dst, src[:n]...), src[n:] // copy simple strings verbatim - } else { - dst, src, err = reformatString(dst, src, !e.options.AllowInvalidUTF8, e.options.preserveRawStrings, e.options.EscapeRune) - } - if err != nil { - return dst, src, err - } - if !e.options.AllowDuplicateNames && !names.insertQuoted(dst[n0:], false) { - return dst, src, &SyntacticError{str: "duplicate name " + string(dst[n0:]) + " in object"} - } - - // Append colon. - src = src[consumeWhitespace(src):] - if len(src) == 0 { - return dst, src, io.ErrUnexpectedEOF - } - if src[0] != ':' { - return dst, src, newInvalidCharacterError(src, "after object name (expecting ':')") - } - dst, src = append(dst, ':'), src[1:] - if e.options.multiline { - dst = append(dst, ' ') - } - - // Append object value. - src = src[consumeWhitespace(src):] - if len(src) == 0 { - return dst, src, io.ErrUnexpectedEOF - } - dst, src, err = e.reformatValue(dst, src, depth) - if err != nil { - return dst, src, err - } - - // Append comma or object end. - src = src[consumeWhitespace(src):] - if len(src) == 0 { - return dst, src, io.ErrUnexpectedEOF - } - switch src[0] { - case ',': - dst, src = append(dst, ','), src[1:] - continue - case '}': - if e.options.multiline { - dst = e.appendIndent(dst, depth-1) - } - dst, src = append(dst, '}'), src[1:] - return dst, src, nil - default: - return dst, src, newInvalidCharacterError(src, "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 updated versions of dst and src. -func (e *Encoder) reformatArray(dst []byte, src RawValue, depth int) ([]byte, RawValue, error) { - // Append array start. - if src[0] != '[' { - panic("BUG: reformatArray must be called with a buffer that starts with '['") - } - dst, src = append(dst, '['), src[1:] - - // Append (possible) array end. - src = src[consumeWhitespace(src):] - if len(src) == 0 { - return dst, src, io.ErrUnexpectedEOF - } - if src[0] == ']' { - dst, src = append(dst, ']'), src[1:] - return dst, src, nil - } - - var err error - depth++ - for { - // Append optional newline and indentation. - if e.options.multiline { - dst = e.appendIndent(dst, depth) - } - - // Append array value. - src = src[consumeWhitespace(src):] - if len(src) == 0 { - return dst, src, io.ErrUnexpectedEOF - } - dst, src, err = e.reformatValue(dst, src, depth) - if err != nil { - return dst, src, err - } - - // Append comma or array end. - src = src[consumeWhitespace(src):] - if len(src) == 0 { - return dst, src, io.ErrUnexpectedEOF - } - switch src[0] { - case ',': - dst, src = append(dst, ','), src[1:] - continue - case ']': - if e.options.multiline { - dst = e.appendIndent(dst, depth-1) - } - dst, src = append(dst, ']'), src[1:] - return dst, src, nil - default: - return dst, src, newInvalidCharacterError(src, "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.previousOffsetEnd() -} - -// UnusedBuffer returns a zero-length buffer with a possible non-zero capacity. -// This buffer is intended to be used to populate a RawValue -// being passed to an immediately succeeding WriteValue call. -// -// Example usage: -// -// b := d.UnusedBuffer() -// 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) UnusedBuffer() []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 RawValue 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.maxValue|63)) // fast approximation for max length - if cap(e.unusedCache) < n { - e.unusedCache = make([]byte, 0, n) - } - return e.unusedCache -} - -// 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 ObjectStart or ArrayStart token is encountered -// and decremented whenever an ObjectEnd or ArrayEnd 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.tokens.depth() - 1 -} - -// StackIndex returns information about the specified stack level. -// It must be a number between 0 and 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, int) { - // NOTE: Keep in sync with Decoder.StackIndex. - switch s := e.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. -// Object names are only present if AllowDuplicateNames is false, otherwise -// object members are represented using their index within the object. -func (e *Encoder) StackPointer() string { - e.names.copyQuotedBuffer(e.buf) - return string(e.appendStackPointer(nil)) -} - -// appendString appends src to dst as a JSON string per RFC 7159, section 7. -// -// If validateUTF8 is specified, this rejects input that contains invalid UTF-8 -// otherwise invalid bytes are replaced with the Unicode replacement character. -// If escapeRune is provided, it specifies which runes to escape using -// hexadecimal sequences. If nil, the shortest representable form is used, -// which is also the canonical form for strings (RFC 8785, section 3.2.2.2). -// -// Note that this API allows full control over the formatting of strings -// except for whether a forward solidus '/' may be formatted as '\/' and -// the casing of hexadecimal Unicode escape sequences. -func appendString(dst []byte, src string, validateUTF8 bool, escapeRune func(rune) bool) ([]byte, error) { - appendEscapedASCII := func(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 = append(dst, "\\u"...) - dst = appendHexUint16(dst, uint16(c)) - } - return dst - } - appendEscapedUnicode := func(dst []byte, r rune) []byte { - if r1, r2 := utf16.EncodeRune(r); r1 != '\ufffd' && r2 != '\ufffd' { - dst = append(dst, "\\u"...) - dst = appendHexUint16(dst, uint16(r1)) - dst = append(dst, "\\u"...) - dst = appendHexUint16(dst, uint16(r2)) - } else { - dst = append(dst, "\\u"...) - dst = appendHexUint16(dst, uint16(r)) - } - return dst - } - - // Optimize for when escapeRune is nil. - if escapeRune == nil { - var i, n int - dst = append(dst, '"') - for uint(len(src)) > uint(n) { - // Handle single-byte ASCII. - if c := src[n]; c < utf8.RuneSelf { - n++ - if c < ' ' || c == '"' || c == '\\' { - dst = append(dst, src[i:n-1]...) - dst = appendEscapedASCII(dst, c) - i = n - } - continue - } - - // Handle multi-byte Unicode. - _, rn := utf8.DecodeRuneInString(src[n:]) - n += rn - if rn == 1 { // must be utf8.RuneError since we already checked for single-byte ASCII - dst = append(dst, src[i:n-rn]...) - if validateUTF8 { - return dst, &SyntacticError{str: "invalid UTF-8 within string"} - } - dst = append(dst, "\ufffd"...) - i = n - } - } - dst = append(dst, src[i:n]...) - dst = append(dst, '"') - return dst, nil - } - - // Slower implementation for when escapeRune is non-nil. - var i, n int - dst = append(dst, '"') - for uint(len(src)) > uint(n) { - switch r, rn := utf8.DecodeRuneInString(src[n:]); { - case r == utf8.RuneError && rn == 1: - dst = append(dst, src[i:n]...) - if validateUTF8 { - return dst, &SyntacticError{str: "invalid UTF-8 within string"} - } - if escapeRune('\ufffd') { - dst = append(dst, `\ufffd`...) - } else { - dst = append(dst, "\ufffd"...) - } - n += rn - i = n - case escapeRune(r): - dst = append(dst, src[i:n]...) - dst = appendEscapedUnicode(dst, r) - n += rn - i = n - case r < ' ' || r == '"' || r == '\\': - dst = append(dst, src[i:n]...) - dst = appendEscapedASCII(dst, byte(r)) - n += rn - i = n - default: - n += rn - } - } - dst = append(dst, src[i:n]...) - dst = append(dst, '"') - return dst, nil -} - -// reformatString consumes a JSON string from src and appends it to dst, -// reformatting it if necessary for the given escapeRune parameter. -// It returns the appended output and the remainder of the input. -func reformatString(dst, src []byte, validateUTF8, preserveRaw bool, escapeRune func(rune) bool) ([]byte, []byte, error) { - // TODO: Should this update valueFlags as input? - var flags valueFlags - n, err := consumeString(&flags, src, validateUTF8) - if err != nil { - return dst, src[n:], err - } - if preserveRaw || (escapeRune == nil && flags.isCanonical()) { - dst = append(dst, src[:n]...) // copy the string verbatim - return dst, src[n:], nil - } - - // TODO: Implement a direct, raw-to-raw reformat for strings. - // If the escapeRune option would have resulted in no changes to the output, - // it would be faster to simply append src to dst without going through - // an intermediary representation in a separate buffer. - b, _ := unescapeString(make([]byte, 0, n), src[:n]) - dst, _ = appendString(dst, string(b), validateUTF8, escapeRune) - return dst, src[n:], nil -} - -// appendNumber 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 appendNumber(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 remainder of the input. -func reformatNumber(dst, src []byte, canonicalize bool) ([]byte, []byte, error) { - n, err := consumeNumber(src) - if err != nil { - return dst, src[n:], err - } - if !canonicalize { - dst = append(dst, src[:n]...) // copy the number verbatim - return dst, src[n:], nil - } - - // Canonicalize the number per RFC 8785, section 3.2.2.3. - // As an optimization, we can copy integer numbers below 2⁵³ verbatim. - const maxExactIntegerDigits = 16 // len(strconv.AppendUint(nil, 1<<53, 10)) - if n < maxExactIntegerDigits && consumeSimpleNumber(src[:n]) == n { - dst = append(dst, src[:n]...) // copy the number verbatim - return dst, src[n:], nil - } - 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 appendNumber(dst, fv, 64), src[n:], nil -} - -// appendHexUint16 appends src to dst as a 4-byte hexadecimal number. -func appendHexUint16(dst []byte, src uint16) []byte { - dst = append(dst, "0000"[1+(bits.Len16(src)-1)/4:]...) - dst = strconv.AppendUint(dst, uint64(src), 16) - return dst -} 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 35be8601e..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/errors.go +++ /dev/null @@ -1,183 +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" - "reflect" - "strconv" - "strings" - "unicode/utf8" -) - -const errorPrefix = "json: " - -// Error matches errors returned by this package according to errors.Is. -const Error = jsonError("json error") - -type jsonError string - -func (e jsonError) Error() string { - return string(e) -} -func (e jsonError) Is(target error) bool { - return e == target || target == Error -} - -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 -} -func (e *ioError) Is(target error) bool { - return e == target || target == Error || errors.Is(e.err, target) -} - -// 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 string - - // JSONKind is the JSON kind that could not be handled. - JSONKind Kind // may be zero if 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 -} - -func (e *SemanticError) Error() string { - var sb strings.Builder - sb.WriteString(errorPrefix) - - // Hyrum-proof the error message by deliberately switching between - // two equivalent renderings of the same error message. - // The randomization is tied to the Hyrum-proofing already applied - // on map iteration in Go. - for phrase := range map[string]struct{}{"cannot": {}, "unable to": {}} { - sb.WriteString(phrase) - break // use whichever phrase we get in the first iteration - } - - // 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. - var omitPreposition bool - 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: - omitPreposition = true - } - - // Format Go type. - if e.GoType != nil { - if !omitPreposition { - sb.WriteString(preposition) - } - sb.WriteString(" Go value of type ") - sb.WriteString(e.GoType.String()) - } - - // Format where. - switch { - case e.JSONPointer != "": - sb.WriteString(" within JSON value at ") - sb.WriteString(strconv.Quote(e.JSONPointer)) - case e.ByteOffset > 0: - sb.WriteString(" after byte offset ") - sb.WriteString(strconv.FormatInt(e.ByteOffset, 10)) - } - - // Format underlying error. - if e.Err != nil { - sb.WriteString(": ") - sb.WriteString(e.Err.Error()) - } - - return sb.String() -} -func (e *SemanticError) Is(target error) bool { - return e == target || target == Error || errors.Is(e.Err, target) -} -func (e *SemanticError) 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 - str string -} - -func (e *SyntacticError) Error() string { - return errorPrefix + e.str -} -func (e *SyntacticError) Is(target error) bool { - return e == target || target == Error -} -func (e *SyntacticError) withOffset(pos int64) error { - return &SyntacticError{ByteOffset: pos, str: e.str} -} - -func newInvalidCharacterError(prefix []byte, where string) *SyntacticError { - what := quoteRune(prefix) - return &SyntacticError{str: "invalid character " + what + " " + where} -} - -func quoteRune(b []byte) string { - r, n := utf8.DecodeRune(b) - if r == utf8.RuneError && n == 1 { - return `'\x` + strconv.FormatUint(uint64(b[0]), 16) + `'` - } - return strconv.QuoteRune(r) -} 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 c0ee36166..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/fields.go +++ /dev/null @@ -1,509 +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 ( - "errors" - "fmt" - "io" - "reflect" - "sort" - "strconv" - "strings" - "unicode" - "unicode/utf8" -) - -var errIgnoredField = errors.New("ignored field") - -type isZeroer interface { - IsZero() bool -} - -var isZeroerType = reflect.TypeOf((*isZeroer)(nil)).Elem() - -type structFields struct { - flattened []structField // listed in depth-first ordering - byActualName map[string]*structField - byFoldedName map[string][]*structField - inlinedFallback *structField -} - -type structField struct { - id int // unique numeric ID in breadth-first ordering - index []int // index into a struct according to reflect.Type.FieldByIndex - typ reflect.Type - fncs *arshaler - isZero func(addressableValue) bool - isEmpty func(addressableValue) bool - fieldOptions -} - -func makeStructFields(root reflect.Type) (structFields, *SemanticError) { - var fs structFields - fs.byActualName = make(map[string]*structField, root.NumField()) - fs.byFoldedName = make(map[string][]*structField, root.NumField()) - - // ambiguous is a sentinel value to indicate that at least two fields - // at the same depth have the same name, and thus cancel each other out. - // This follows the same rules as selecting a field on embedded structs - // where the shallowest field takes precedence. If more than one field - // exists at the shallowest depth, then the selection is illegal. - // See https://go.dev/ref/spec#Selectors. - ambiguous := new(structField) - - // 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. - 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 := 0; i < t.NumField(); i++ { - sf := t.Field(i) - _, hasTag := sf.Tag.Lookup("json") - hasAnyJSONTag = hasAnyJSONTag || hasTag - options, err := parseFieldOptions(sf) - if err != nil { - if err == errIgnoredField { - continue - } - return structFields{}, &SemanticError{GoType: t, Err: err} - } - 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 { - 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. - - if f.inline && f.unknown { - err := fmt.Errorf("Go struct field %s cannot have both `inline` and `unknown` specified", sf.Name) - return structFields{}, &SemanticError{GoType: t, Err: err} - } - switch f.fieldOptions { - case fieldOptions{name: f.name, quotedName: f.quotedName, inline: true}: - case fieldOptions{name: f.name, quotedName: f.quotedName, unknown: true}: - default: - err := fmt.Errorf("Go struct field %s cannot have any options other than `inline` or `unknown` specified", sf.Name) - return structFields{}, &SemanticError{GoType: t, Err: err} - } - - // Unwrap one level of pointer indirection similar to how Go - // only allows embedding either T or *T, but not **T. - tf := f.typ - if tf.Kind() == reflect.Pointer && tf.Name() == "" { - tf = tf.Elem() - } - // Reject any types with custom serialization otherwise - // it becomes impossible to know what sub-fields to inline. - if which, _ := implementsWhich(tf, - jsonMarshalerV2Type, jsonMarshalerV1Type, textMarshalerType, - jsonUnmarshalerV2Type, jsonUnmarshalerV1Type, textUnmarshalerType, - ); which != nil && tf != rawValueType { - err := fmt.Errorf("inlined Go struct field %s of type %s must not implement JSON marshal or unmarshal methods", sf.Name, tf) - return structFields{}, &SemanticError{GoType: t, Err: err} - } - - // 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 { - err := fmt.Errorf("inlined Go struct field %s of type %s with `unknown` tag must be a Go map of string key or a json.RawValue", sf.Name, tf) - return structFields{}, &SemanticError{GoType: t, Err: err} - } - if qe.visitChildren { - queue = append(queue, queueEntry{tf, f.index, !seen[tf]}) - } - seen[tf] = true - continue - } - - // Handle an inlined field that serializes to/from any number of - // JSON object members back by a Go map or RawValue. - switch { - case tf == rawValueType: - f.fncs = nil // specially handled in arshal_inlined.go - case tf.Kind() == reflect.Map && tf.Key() == stringType: - f.fncs = lookupArshaler(tf.Elem()) - default: - err := fmt.Errorf("inlined Go struct field %s of type %s must be a Go struct, Go map of string key, or json.RawValue", sf.Name, tf) - return structFields{}, &SemanticError{GoType: t, Err: err} - } - - // Reject multiple inlined fallback fields within the same struct. - if inlinedFallbackIndex >= 0 { - err := fmt.Errorf("inlined Go struct fields %s and %s cannot both be a Go map or json.RawValue", t.Field(inlinedFallbackIndex).Name, sf.Name) - return structFields{}, &SemanticError{GoType: t, Err: err} - } - inlinedFallbackIndex = i - - // Multiple inlined fallback fields across different structs - // follow the same precedence rules as Go struct embedding. - if fs.inlinedFallback == nil { - fs.inlinedFallback = &f // store first occurrence at lowest depth - } else if len(fs.inlinedFallback.index) == len(f.index) { - fs.inlinedFallback = ambiguous // at least two occurrences at same depth - } - } else { - // Handle normal Go struct field that serializes to/from - // a single JSON object member. - - // 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() } - } - - f.id = len(fs.flattened) - f.fncs = lookupArshaler(sf.Type) - fs.flattened = append(fs.flattened, f) - - // Reject user-specified names with invalid UTF-8. - if !utf8.ValidString(f.name) { - err := fmt.Errorf("Go struct field %s has JSON object name %q with invalid UTF-8", sf.Name, f.name) - return structFields{}, &SemanticError{GoType: t, Err: err} - } - // Reject multiple fields with same name within the same struct. - if j, ok := namesIndex[f.name]; ok { - err := fmt.Errorf("Go struct fields %s and %s conflict over JSON object name %q", t.Field(j).Name, sf.Name, f.name) - return structFields{}, &SemanticError{GoType: t, Err: err} - } - namesIndex[f.name] = i - - // Multiple fields of the same name across different structs - // follow the same precedence rules as Go struct embedding. - if f2 := fs.byActualName[f.name]; f2 == nil { - fs.byActualName[f.name] = &fs.flattened[len(fs.flattened)-1] // store first occurrence at lowest depth - } else if len(f2.index) == len(f.index) { - fs.byActualName[f.name] = ambiguous // at least two occurrences at same depth - } - } - } - - // 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 { - err := errors.New("Go struct has no exported fields") - return structFields{}, &SemanticError{GoType: t, Err: err} - } - } - - // Remove all fields that are duplicates. - // This may move elements forward to fill the holes from removed fields. - var n int - for _, f := range fs.flattened { - switch f2 := fs.byActualName[f.name]; { - case f2 == ambiguous: - delete(fs.byActualName, f.name) - case f2 == nil: - continue // may be nil due to previous delete - // TODO(https://go.dev/issue/45955): Use slices.Equal. - case reflect.DeepEqual(f.index, f2.index): - f.id = n - fs.flattened[n] = f - fs.byActualName[f.name] = &fs.flattened[n] // fix pointer to new location - n++ - } - } - fs.flattened = fs.flattened[:n] - if fs.inlinedFallback == ambiguous { - fs.inlinedFallback = nil - } - if len(fs.flattened) != len(fs.byActualName) { - panic(fmt.Sprintf("BUG: flattened list of fields mismatches fields mapped by name: %d != %d", len(fs.flattened), len(fs.byActualName))) - } - - // Sort the fields according to a depth-first ordering. - // This operation will cause pointers in byActualName to become incorrect, - // which we will correct in another loop shortly thereafter. - sort.Slice(fs.flattened, func(i, j int) bool { - si := fs.flattened[i].index - sj := fs.flattened[j].index - for len(si) > 0 && len(sj) > 0 { - switch { - case si[0] < sj[0]: - return true - case si[0] > sj[0]: - return false - default: - si = si[1:] - sj = sj[1:] - } - } - return len(si) < len(sj) - }) - - // Recompute the mapping of fields in the byActualName map. - // Pre-fold all names so that we can lookup folded names quickly. - 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 nocase names - // is by breadth-first order, rather than depth-first order. - sort.Slice(fields, func(i, j int) bool { - return fields[i].id < fields[j].id - }) - fs.byFoldedName[foldedName] = fields - } - } - - return fs, nil -} - -type fieldOptions struct { - name string - quotedName string // quoted name per RFC 8785, section 3.2.2.2. - hasName bool - nocase bool - 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. -// As a special case, it returns errIgnoredField if the field is ignored. -func parseFieldOptions(sf reflect.StructField) (out fieldOptions, err error) { - tag, hasTag := sf.Tag.Lookup("json") - - // Check whether this field is explicitly ignored. - if tag == "-" { - return fieldOptions{}, errIgnoredField - } - - // Check whether this field is unexported. - if !sf.IsExported() { - // In contrast to v1, v2 no longer forwards exported fields from - // embedded fields of unexported types since Go reflection does not - // allow the same set of operations that are available in normal cases - // of purely exported fields. - // See https://go.dev/issue/21357 and https://go.dev/issue/24153. - if sf.Anonymous { - return fieldOptions{}, fmt.Errorf("embedded Go struct field %s of an unexported type must be explicitly ignored with a `json:\"-\"` tag", sf.Type.Name()) - } - // Tag options specified on an unexported field suggests user error. - if hasTag { - return fieldOptions{}, fmt.Errorf("unexported Go struct field %s cannot have non-ignored `json:%q` tag", sf.Name, tag) - } - return fieldOptions{}, errIgnoredField - } - - // 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 - })) - opt := tag[:n] - if n == 0 { - // Allow a single quoted string for arbitrary names. - opt, n, err = consumeTagOption(tag) - if err != nil { - return fieldOptions{}, fmt.Errorf("Go struct field %s has malformed `json` tag: %v", sf.Name, err) - } - } - out.hasName = true - out.name = opt - tag = tag[n:] - } - b, _ := appendString(nil, out.name, false, nil) - out.quotedName = string(b) - - // 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] != ',' { - return fieldOptions{}, fmt.Errorf("Go struct field %s has malformed `json` tag: invalid character %q before next option (expecting ',')", sf.Name, tag[0]) - } - tag = tag[len(","):] - if len(tag) == 0 { - return fieldOptions{}, fmt.Errorf("Go struct field %s has malformed `json` tag: invalid trailing ',' character", sf.Name) - } - - // Consume and process the tag option. - opt, n, err := consumeTagOption(tag) - if err != nil { - return fieldOptions{}, fmt.Errorf("Go struct field %s has malformed `json` tag: %v", sf.Name, err) - } - rawOpt := tag[:n] - tag = tag[n:] - switch { - case wasFormat: - return fieldOptions{}, 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) == "": - return fieldOptions{}, fmt.Errorf("Go struct field %s has unnecessarily quoted appearance of `%s` tag option; specify `%s` instead", sf.Name, rawOpt, opt) - } - switch opt { - case "nocase": - out.nocase = true - 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, ":") { - return fieldOptions{}, fmt.Errorf("Go struct field %s is missing value for `format` tag option", sf.Name) - } - tag = tag[len(":"):] - opt, n, err := consumeTagOption(tag) - if err != nil { - return fieldOptions{}, fmt.Errorf("Go struct field %s has malformed value for `format` tag option: %v", sf.Name, err) - } - 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 "nocase", "inline", "unknown", "omitzero", "omitempty", "string", "format": - return fieldOptions{}, 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. - if seenOpts[opt] { - return fieldOptions{}, fmt.Errorf("Go struct field %s has duplicate appearance of `%s` tag option", sf.Name, rawOpt) - } - seenOpts[opt] = true - } - return out, nil -} - -func consumeTagOption(in string) (string, int, error) { - 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 "", 0, 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 "", 0, fmt.Errorf("single-quoted string not terminated: %s...", in[:n]) - case len(in) == 0: - return "", 0, io.ErrUnexpectedEOF - default: - return "", 0, 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) -} 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 700a56db0..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 - -// make 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 (c *stringCache) make(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/pools.go b/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/pools.go deleted file mode 100644 index 60e93270f..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/pools.go +++ /dev/null @@ -1,182 +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" - "io" - "math/bits" - "sort" - "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(o EncodeOptions) *Encoder { - e := bufferedEncoderPool.Get().(*Encoder) - if e.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.bufStats.prevLen|63)) - e.buf = make([]byte, 0, n) - } - e.reset(e.buf[:0], nil, o) - 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.buf) <= 4<<10: // always recycle buffers smaller than 4KiB - e.bufStats.strikes = 0 - case cap(e.buf)/4 <= len(e.buf): // at least 25% utilization - e.bufStats.strikes = 0 - case e.bufStats.strikes < 4: // at most 4 strikes - e.bufStats.strikes++ - default: // discard the buffer; too large and too often under-utilized - e.bufStats.strikes = 0 - e.bufStats.prevLen = len(e.buf) // heuristic for size to allocate next time - e.buf = nil - } - bufferedEncoderPool.Put(e) -} - -func getStreamingEncoder(w io.Writer, o EncodeOptions) *Encoder { - if _, ok := w.(*bytes.Buffer); ok { - e := bytesBufferEncoderPool.Get().(*Encoder) - e.reset(nil, w, o) // buffer taken from bytes.Buffer - return e - } else { - e := streamingEncoderPool.Get().(*Encoder) - e.reset(e.buf[:0], w, o) // preserve existing buffer - return e - } -} -func putStreamingEncoder(e *Encoder) { - if _, ok := e.wr.(*bytes.Buffer); ok { - bytesBufferEncoderPool.Put(e) - } else { - if cap(e.buf) > 64<<10 { - e.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, o DecodeOptions) *Decoder { - d := bufferedDecoderPool.Get().(*Decoder) - d.reset(b, nil, o) - return d -} -func putBufferedDecoder(d *Decoder) { - bufferedDecoderPool.Put(d) -} - -func getStreamingDecoder(r io.Reader, o DecodeOptions) *Decoder { - if _, ok := r.(*bytes.Buffer); ok { - d := bytesBufferDecoderPool.Get().(*Decoder) - d.reset(nil, r, o) // buffer taken from bytes.Buffer - return d - } else { - d := streamingDecoderPool.Get().(*Decoder) - d.reset(d.buf[:0], r, o) // preserve existing buffer - return d - } -} -func putStreamingDecoder(d *Decoder) { - if _, ok := d.rd.(*bytes.Buffer); ok { - bytesBufferDecoderPool.Put(d) - } else { - if cap(d.buf) > 64<<10 { - d.buf = nil // avoid pinning arbitrarily large amounts of memory - } - streamingDecoderPool.Put(d) - } -} - -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) -} - -// Sort sorts the string slice according to RFC 8785, section 3.2.3. -func (ss *stringSlice) Sort() { - // TODO(https://go.dev/issue/47619): Use slices.SortFunc instead. - sort.Sort(ss) -} - -func (ss *stringSlice) Len() int { return len(*ss) } -func (ss *stringSlice) Less(i, j int) bool { return lessUTF16((*ss)[i], (*ss)[j]) } -func (ss *stringSlice) Swap(i, j int) { (*ss)[i], (*ss)[j] = (*ss)[j], (*ss)[i] } diff --git a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/state.go b/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/state.go deleted file mode 100644 index ee14c753f..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/state.go +++ /dev/null @@ -1,747 +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 ( - "math" - "strconv" -) - -var ( - errMissingName = &SyntacticError{str: "missing string for object name"} - errMissingColon = &SyntacticError{str: "missing character ':' after object name"} - errMissingValue = &SyntacticError{str: "missing value after object name"} - errMissingComma = &SyntacticError{str: "missing character ',' after object or array value"} - errMismatchDelim = &SyntacticError{str: "mismatching structural token for object or array"} -) - -const errInvalidNamespace = jsonError("object namespace is in an invalid state") - -type state struct { - // tokens validates whether the next token kind is valid. - tokens stateMachine - - // names is a stack of object names. - // Not used if AllowDuplicateNames is true. - 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 -} - -func (s *state) reset() { - s.tokens.reset() - s.names.reset() - s.namespaces.reset() -} - -// appendStackPointer appends a JSON Pointer (RFC 6901) to the current value. -// The returned pointer is only accurate if s.names is populated, -// otherwise it uses the numeric index as the object member name. -// -// Invariant: Must call s.names.copyQuotedBuffer beforehand. -func (s state) appendStackPointer(b []byte) []byte { - var objectDepth int - for i := 1; i < s.tokens.depth(); i++ { - e := s.tokens.index(i) - if e.length() == 0 { - break // empty object or array - } - b = append(b, '/') - switch { - case e.isObject(): - if objectDepth < s.names.length() { - for _, c := range s.names.getUnquoted(objectDepth) { - // Per RFC 6901, section 3, escape '~' and '/' characters. - switch c { - case '~': - b = append(b, "~0"...) - case '/': - b = append(b, "~1"...) - default: - b = append(b, c) - } - } - } else { - // Since the names stack is unpopulated, the name is unknown. - // As a best-effort replacement, use the numeric member index. - // While inaccurate, it produces a syntactically valid pointer. - b = strconv.AppendUint(b, uint64((e.length()-1)/2), 10) - } - objectDepth++ - case e.isArray(): - b = strconv.AppendUint(b, uint64(e.length()-1), 10) - } - } - 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 inlineable. -// 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, int) { - 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 errMissingName - 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 start 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 errMissingName - case !m.last.isValidNamespace(): - return errInvalidNamespace - 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 start 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 errMissingName - case !m.last.isValidNamespace(): - return errInvalidNamespace - 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 - } -} - -// checkDelim reports whether the specified delimiter should be there given -// the kind of the next token that appears immediately afterwards. -func (m stateMachine) checkDelim(delim byte, next Kind) error { - switch needDelim := m.needDelim(next); { - case needDelim == delim: - return nil - case needDelim == ':': - return errMissingColon - case needDelim == ',': - return errMissingComma - default: - return newInvalidCharacterError([]byte{delim}, "before next token") - } -} - -// 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 := 0; i < m.depth(); i++ { - 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() int { - return int(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 namespace. -// 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 := consumeSimpleString(quotedName); n > 0 { - ns.unquotedNames = append(ns.unquotedNames[:startOffset], quotedName[len(`"`):n-len(`"`)]...) - } else { - ns.unquotedNames, _ = unescapeString(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, _ = unescapeString(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]] - } -} - -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 inlineable 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/token.go b/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/token.go deleted file mode 100644 index 9acba7dad..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/token.go +++ /dev/null @@ -1,522 +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 ( - "math" - "strconv" -) - -// 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 json.Token; it has been voided by a subsequent json.Decoder call" -) - -// 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 start or end delimiter for a JSON object (i.e., { or } ) -// - a start or end delimiter for a JSON array (i.e., [ or ] ) -// -// A Token cannot represent entire array or object values, while a RawValue 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") - - ObjectStart Token = rawToken("{") - ObjectEnd Token = rawToken("}") - ArrayStart Token = rawToken("[") - ArrayEnd 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 ObjectStart.raw: - return ObjectStart - case ObjectEnd.raw: - return ObjectEnd - case ArrayStart.raw: - return ArrayStart - case ArrayEnd.raw: - return ArrayEnd - } - } - - if uint64(raw.previousOffsetStart()) != t.num { - panic(invalidTokenPanic) - } - // TODO(https://go.dev/issue/45038): Use bytes.Clone. - buf := append([]byte(nil), 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, validateUTF8, preserveRaw bool, escapeRune func(rune) bool) ([]byte, error) { - if raw := t.raw; raw != nil { - // Handle raw string value. - buf := raw.previousBuffer() - if Kind(buf[0]) == '"' { - if escapeRune == nil && consumeSimpleString(buf) == len(buf) { - return append(dst, buf...), nil - } - dst, _, err := reformatString(dst, buf, validateUTF8, preserveRaw, escapeRune) - return dst, err - } - } else if len(t.str) != 0 && t.num == 0 { - // Handle exact string value. - return appendString(dst, t.str, validateUTF8, escapeRune) - } - - 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 := consumeSimpleString(buf) == len(buf) - return "", unescapeStringMayCopy(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(appendNumber(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, canonicalize bool) ([]byte, error) { - if raw := t.raw; raw != nil { - // Handle raw number value. - buf := raw.previousBuffer() - if Kind(buf[0]).normalize() == '0' { - if !canonicalize { - return append(dst, buf...), nil - } - dst, _, err := reformatNumber(dst, buf, canonicalize) - return dst, err - } - } else if t.num != 0 { - // Handle exact number value. - switch t.str[0] { - case 'f': - return appendNumber(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, _ := 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 := parseDecUint(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 := parseDecUint(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 start -// - '}': object end -// - '[': array start -// - ']': 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/value.go b/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/value.go deleted file mode 100644 index e0bd1b31d..000000000 --- a/vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/value.go +++ /dev/null @@ -1,381 +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" - "sort" - "sync" - "unicode/utf16" - "unicode/utf8" -) - -// NOTE: RawValue is analogous to v1 json.RawMessage. - -// RawValue 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] ) -// -// RawValue can represent entire array or object values, while Token cannot. -// RawValue may contain leading and/or trailing whitespace. -type RawValue []byte - -// Clone returns a copy of v. -func (v RawValue) Clone() RawValue { - if v == nil { - return nil - } - return append(RawValue{}, v...) -} - -// String returns the string formatting of v. -func (v RawValue) String() string { - if v == nil { - return "null" - } - return string(v) -} - -// IsValid reports whether the raw JSON value is syntactically valid -// 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). -func (v RawValue) IsValid() bool { - d := getBufferedDecoder(v, DecodeOptions{}) - defer putBufferedDecoder(d) - _, errVal := d.ReadValue() - _, errEOF := d.ReadToken() - return errVal == nil && errEOF == io.EOF -} - -// Compact removes all whitespace from the raw JSON value. -// -// It does not reformat JSON strings to use any other representation. -// It is guaranteed to succeed if the input is valid. -// If the value is already compacted, then the buffer is not mutated. -func (v *RawValue) Compact() error { - return v.reformat(false, false, "", "") -} - -// Indent reformats the whitespace in the raw JSON value so that each element -// in a JSON object or array begins on a new, indented line beginning with -// prefix followed by one or more copies of indent according to the nesting. -// The value does not begin with the prefix nor any indention, -// to make it easier to embed inside other formatted JSON data. -// -// It does not reformat JSON strings to use any other representation. -// It is guaranteed to succeed if the input is valid. -// If the value is already indented properly, then the buffer is not mutated. -func (v *RawValue) Indent(prefix, indent string) error { - return v.reformat(false, true, prefix, indent) -} - -// 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. -// -// 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. -// -// 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. It is recommended that -// int64 and uint64 data types be represented as a JSON string. -// -// It is guaranteed to succeed if the input is valid. -// If the value is already canonicalized, then the buffer is not mutated. -func (v *RawValue) Canonicalize() error { - return v.reformat(true, false, "", "") -} - -// TODO: Instead of implementing the v1 Marshaler/Unmarshaler, -// consider implementing the v2 versions instead. - -// 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 RawValue) 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 *RawValue) UnmarshalJSON(b []byte) error { - // NOTE: This matches the behavior of v1 json.RawMessage.UnmarshalJSON. - if v == nil { - return errors.New("json.RawValue: 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 RawValue) Kind() Kind { - if v := v[consumeWhitespace(v):]; len(v) > 0 { - return Kind(v[0]).normalize() - } - return invalidKind -} - -func (v *RawValue) reformat(canonical, multiline bool, prefix, indent string) error { - var eo EncodeOptions - if canonical { - eo.AllowInvalidUTF8 = false // per RFC 8785, section 3.2.4 - eo.AllowDuplicateNames = false // per RFC 8785, section 3.1 - eo.canonicalizeNumbers = true // per RFC 8785, section 3.2.2.3 - eo.EscapeRune = nil // per RFC 8785, section 3.2.2.2 - eo.multiline = false // per RFC 8785, section 3.2.1 - } else { - if s := trimLeftSpaceTab(prefix); len(s) > 0 { - panic("json: invalid character " + quoteRune([]byte(s)) + " in indent prefix") - } - if s := trimLeftSpaceTab(indent); len(s) > 0 { - panic("json: invalid character " + quoteRune([]byte(s)) + " in indent") - } - eo.AllowInvalidUTF8 = true - eo.AllowDuplicateNames = true - eo.preserveRawStrings = true - eo.multiline = multiline // in case indent is empty - eo.IndentPrefix = prefix - eo.Indent = indent - } - eo.omitTopLevelNewline = true - - // Write the entire value to reformat all tokens and whitespace. - e := getBufferedEncoder(eo) - defer putBufferedEncoder(e) - if err := e.WriteValue(*v); err != nil { - return err - } - - // For canonical output, we may need to reorder object members. - if canonical { - // Obtain a buffered encoder just to use its internal buffer as - // a scratch buffer in reorderObjects for reordering object members. - e2 := getBufferedEncoder(EncodeOptions{}) - defer putBufferedEncoder(e2) - - // Disable redundant checks performed earlier during encoding. - d := getBufferedDecoder(e.buf, DecodeOptions{AllowInvalidUTF8: true, AllowDuplicateNames: true}) - defer putBufferedDecoder(d) - reorderObjects(d, &e2.buf) // per RFC 8785, section 3.2.3 - } - - // Store the result back into the value if different. - if !bytes.Equal(*v, e.buf) { - *v = append((*v)[:0], e.buf...) - } - return nil -} - -func trimLeftSpaceTab(s string) string { - for i, r := range s { - switch r { - case ' ', '\t': - default: - return s[i:] - } - } - return "" -} - -type memberName struct { - // name is the unescaped name. - name []byte - // before and after are byte offsets into Decoder.buf that represents - // the entire name/value pair. It may contain leading commas. - before, after int64 -} - -var memberNamePool = sync.Pool{New: func() any { return new(memberNames) }} - -func getMemberNames() *memberNames { - ns := memberNamePool.Get().(*memberNames) - *ns = (*ns)[:0] - return ns -} -func putMemberNames(ns *memberNames) { - if cap(*ns) < 1<<10 { - for i := range *ns { - (*ns)[i] = memberName{} // avoid pinning name - } - memberNamePool.Put(ns) - } -} - -type memberNames []memberName - -func (m *memberNames) Len() int { return len(*m) } -func (m *memberNames) Less(i, j int) bool { return lessUTF16((*m)[i].name, (*m)[j].name) } -func (m *memberNames) Swap(i, j int) { (*m)[i], (*m)[j] = (*m)[j], (*m)[i] } - -// reorderObjects 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). -// - The value is compact (i.e., no whitespace is present). -// - 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 reorderObjects(d *Decoder, scratch *[]byte) { - switch tok, _ := d.ReadToken(); tok.Kind() { - case '{': - // Iterate and collect the name and offsets for every object member. - members := getMemberNames() - defer putMemberNames(members) - var prevName []byte - isSorted := true - - beforeBody := d.InputOffset() // offset after '{' - for d.PeekKind() != '}' { - beforeName := d.InputOffset() - var flags valueFlags - name, _ := d.readValue(&flags) - name = unescapeStringMayCopy(name, flags.isVerbatim()) - reorderObjects(d, scratch) - afterValue := d.InputOffset() - - if isSorted && len(*members) > 0 { - isSorted = lessUTF16(prevName, []byte(name)) - } - *members = append(*members, memberName{name, beforeName, afterValue}) - prevName = name - } - afterBody := d.InputOffset() // offset before '}' - d.ReadToken() - - // Sort the members; return early if it's already sorted. - if isSorted { - return - } - // TODO(https://go.dev/issue/47619): Use slices.Sort. - sort.Sort(members) - - // 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 - sorted := (*scratch)[:0] - for i, member := range *members { - if d.buf[member.before] == ',' { - member.before++ // trim leading comma - } - sorted = append(sorted, d.buf[member.before:member.after]...) - if i < len(*members)-1 { - sorted = append(sorted, ',') // append trailing comma - } - } - if int(afterBody-beforeBody) != len(sorted) { - panic("BUG: length invariant violated") - } - copy(d.buf[beforeBody:afterBody], sorted) - - // Update scratch buffer to the largest amount ever used. - if len(sorted) > len(*scratch) { - *scratch = sorted - } - case '[': - for d.PeekKind() != ']' { - reorderObjects(d, scratch) - } - d.ReadToken() - } -} - -// lessUTF16 reports whether x is lexicographically less than 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. -// The inputs must be valid UTF-8, otherwise this may panic. -func lessUTF16[Bytes []byte | string](x, y Bytes) bool { - // NOTE: This is an optimized, allocation-free implementation - // of lessUTF16Simple in fuzz_test.go. FuzzLessUTF16 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') - } - - var invalidUTF8 bool - x0, y0 := x, y - for { - if len(x) == 0 || len(y) == 0 { - if len(x) == len(y) && invalidUTF8 { - return string(x0) < string(y0) - } - return len(x) < len(y) - } - - // ASCII fast-path. - if x[0] < utf8.RuneSelf || y[0] < utf8.RuneSelf { - if x[0] != y[0] { - return x[0] < y[0] - } - x, y = x[1:], y[1:] - continue - } - - // Decode next pair of runes as UTF-8. - // TODO(https://go.dev/issue/56948): Use a generic implementation - // of utf8.DecodeRune, or rely on a compiler optimization to statically - // hide the cost of a type switch (https://go.dev/issue/57072). - var rx, ry rune - var nx, ny int - switch any(x).(type) { - case string: - rx, nx = utf8.DecodeRuneInString(string(x)) - ry, ny = utf8.DecodeRuneInString(string(y)) - case []byte: - rx, nx = utf8.DecodeRune([]byte(x)) - ry, ny = utf8.DecodeRune([]byte(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 rx < ry - } - invalidUTF8 = invalidUTF8 || (rx == utf8.RuneError && nx == 1) || (ry == utf8.RuneError && ny == 1) - x, y = x[nx:], y[ny:] - } -} diff --git a/vendor/k8s.io/kube-openapi/pkg/schemaconv/openapi.go b/vendor/k8s.io/kube-openapi/pkg/schemaconv/openapi.go index 81280aae6..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. @@ -140,18 +141,20 @@ func (c *convert) makeOpenAPIRef(specSchema *spec.Schema) schema.TypeRef { // to deduplicate) mapRelationship, err := getMapElementRelationship(specSchema.Extensions) if err != nil { - c.reportError(err.Error()) + c.reportError("%v", err) } if len(mapRelationship) > 0 { return schema.TypeRef{ NamedType: &n, ElementRelationship: &mapRelationship, + Nullable: specSchema.Nullable, } } return schema.TypeRef{ NamedType: &n, + Nullable: specSchema.Nullable, } } @@ -164,7 +167,8 @@ func (c *convert) makeOpenAPIRef(specSchema *spec.Schema) schema.TypeRef { c.pop(c2) return schema.TypeRef{ - Inlined: inlined, + Inlined: inlined, + Nullable: specSchema.Nullable, } } @@ -212,7 +216,7 @@ func (c *convert) parseObject(s *spec.Schema) *schema.Map { relationship, err := getMapElementRelationship(s.Extensions) if err != nil { - c.reportError(err.Error()) + c.reportError("%v", err) } return &schema.Map{ @@ -225,7 +229,7 @@ func (c *convert) parseObject(s *spec.Schema) *schema.Map { func (c *convert) parseList(s *spec.Schema) *schema.List { relationship, mapKeys, err := getListElementRelationship(s.Extensions) if err != nil { - c.reportError(err.Error()) + c.reportError("%v", err) } elementType := func() schema.TypeRef { if s.Items != nil { 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 e40f6056e..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 @@ -72,7 +73,7 @@ func (c *convert) makeRef(model proto.Schema, preserveUnknownFields bool) schema mapRelationship, err := getMapElementRelationship(model.GetExtensions()) if err != nil { - c.reportError(err.Error()) + c.reportError("%v", err) } // empty string means unset. @@ -114,7 +115,7 @@ func (c *convert) VisitKind(k *proto.Kind) { unions, err := makeUnions(k.GetExtensions()) if err != nil { - c.reportError(err.Error()) + c.reportError("%v", err) return } // TODO: We should check that the fields and discriminator @@ -129,14 +130,14 @@ func (c *convert) VisitKind(k *proto.Kind) { a.Map.ElementRelationship, err = getMapElementRelationship(k.GetExtensions()) if err != nil { - c.reportError(err.Error()) + c.reportError("%v", err) } } func (c *convert) VisitArray(a *proto.Array) { relationship, mapKeys, err := getListElementRelationship(a.GetExtensions()) if err != nil { - c.reportError(err.Error()) + c.reportError("%v", err) } atom := c.top() @@ -150,7 +151,7 @@ func (c *convert) VisitArray(a *proto.Array) { func (c *convert) VisitMap(m *proto.Map) { relationship, err := getMapElementRelationship(m.GetExtensions()) if err != nil { - c.reportError(err.Error()) + c.reportError("%v", err) } a := c.top() 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 1f62c6e77..62ae6d314 100644 --- a/vendor/k8s.io/kube-openapi/pkg/spec3/encoding.go +++ b/vendor/k8s.io/kube-openapi/pkg/spec3/encoding.go @@ -17,11 +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/validation/spec" ) @@ -32,49 +31,29 @@ 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) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error { +func (e *Encoding) MarshalJSONTo(enc *jsontext.Encoder) error { var x struct { - EncodingProps encodingPropsOmitZero `json:",inline"` - spec.Extensions + EncodingProps encodingPropsOmitZero `json:",embed"` + Extensions spec.Extensions `json:",embed"` } x.Extensions = internal.SanitizeExtensions(e.Extensions) x.EncodingProps = encodingPropsOmitZero(e.EncodingProps) - return opts.MarshalNext(enc, x) + return jsonv2.MarshalEncode(enc, x) } 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) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error { +func (e *Encoding) UnmarshalJSONFrom(dec *jsontext.Decoder) error { var x struct { - spec.Extensions + Extensions spec.Extensions `json:",embed"` EncodingProps } - if err := opts.UnmarshalNext(dec, &x); err != nil { + if err := jsonv2.UnmarshalDecode(dec, &x); err != nil { return err } diff --git a/vendor/k8s.io/kube-openapi/pkg/spec3/example.go b/vendor/k8s.io/kube-openapi/pkg/spec3/example.go index 8834a92e6..a06b8399e 100644 --- a/vendor/k8s.io/kube-openapi/pkg/spec3/example.go +++ b/vendor/k8s.io/kube-openapi/pkg/spec3/example.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/validation/spec" ) @@ -36,57 +34,30 @@ 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) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error { +func (e *Example) MarshalJSONTo(enc *jsontext.Encoder) error { var x struct { Ref string `json:"$ref,omitempty"` - ExampleProps `json:",inline"` - spec.Extensions + ExampleProps `json:",embed"` + Extensions spec.Extensions `json:",embed"` } x.Ref = e.Refable.Ref.String() x.Extensions = internal.SanitizeExtensions(e.Extensions) x.ExampleProps = e.ExampleProps - return opts.MarshalNext(enc, x) + return jsonv2.MarshalEncode(enc, x) } 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) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error { +func (e *Example) UnmarshalJSONFrom(dec *jsontext.Decoder) error { var x struct { - spec.Extensions + Extensions spec.Extensions `json:",embed"` ExampleProps } - if err := opts.UnmarshalNext(dec, &x); err != nil { + if err := jsonv2.UnmarshalDecode(dec, &x); err != nil { return err } if err := internal.JSONRefFromMap(&e.Ref.Ref, x.Extensions); 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 f0515496e..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,11 +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/validation/spec" ) @@ -39,49 +38,29 @@ 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) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error { +func (e *ExternalDocumentation) MarshalJSONTo(enc *jsontext.Encoder) error { var x struct { - ExternalDocumentationProps `json:",inline"` - spec.Extensions + ExternalDocumentationProps `json:",embed"` + Extensions spec.Extensions `json:",embed"` } x.Extensions = internal.SanitizeExtensions(e.Extensions) x.ExternalDocumentationProps = e.ExternalDocumentationProps - return opts.MarshalNext(enc, x) + return jsonv2.MarshalEncode(enc, x) } 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) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error { +func (e *ExternalDocumentation) UnmarshalJSONFrom(dec *jsontext.Decoder) error { var x struct { - spec.Extensions + Extensions spec.Extensions `json:",embed"` ExternalDocumentationProps } - if err := opts.UnmarshalNext(dec, &x); err != nil { + if err := jsonv2.UnmarshalDecode(dec, &x); err != nil { return err } e.Extensions = internal.SanitizeExtensions(x.Extensions) diff --git a/vendor/k8s.io/kube-openapi/pkg/spec3/header.go b/vendor/k8s.io/kube-openapi/pkg/spec3/header.go index 9ea30628c..0cf70aebd 100644 --- a/vendor/k8s.io/kube-openapi/pkg/spec3/header.go +++ b/vendor/k8s.io/kube-openapi/pkg/spec3/header.go @@ -17,11 +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/validation/spec" ) @@ -36,59 +35,31 @@ 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) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error { +func (h *Header) MarshalJSONTo(enc *jsontext.Encoder) error { var x struct { Ref string `json:"$ref,omitempty"` - HeaderProps headerPropsOmitZero `json:",inline"` - spec.Extensions + HeaderProps headerPropsOmitZero `json:",embed"` + Extensions spec.Extensions `json:",embed"` } x.Ref = h.Refable.Ref.String() x.Extensions = internal.SanitizeExtensions(h.Extensions) x.HeaderProps = headerPropsOmitZero(h.HeaderProps) - return opts.MarshalNext(enc, x) + return jsonv2.MarshalEncode(enc, x) } 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) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error { +func (h *Header) UnmarshalJSONFrom(dec *jsontext.Decoder) error { var x struct { - spec.Extensions + Extensions spec.Extensions `json:",embed"` HeaderProps } - if err := opts.UnmarshalNext(dec, &x); err != nil { + if err := jsonv2.UnmarshalDecode(dec, &x); err != nil { return err } if err := internal.JSONRefFromMap(&h.Ref.Ref, x.Extensions); 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 47eef1edb..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,11 +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/validation/spec" ) @@ -35,49 +34,29 @@ 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) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error { +func (e *MediaType) MarshalJSONTo(enc *jsontext.Encoder) error { var x struct { - MediaTypeProps mediaTypePropsOmitZero `json:",inline"` - spec.Extensions + MediaTypeProps mediaTypePropsOmitZero `json:",embed"` + Extensions spec.Extensions `json:",embed"` } x.Extensions = internal.SanitizeExtensions(e.Extensions) x.MediaTypeProps = mediaTypePropsOmitZero(e.MediaTypeProps) - return opts.MarshalNext(enc, x) + return jsonv2.MarshalEncode(enc, x) } 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) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error { +func (m *MediaType) UnmarshalJSONFrom(dec *jsontext.Decoder) error { var x struct { - spec.Extensions + Extensions spec.Extensions `json:",embed"` MediaTypeProps } - if err := opts.UnmarshalNext(dec, &x); err != nil { + if err := jsonv2.UnmarshalDecode(dec, &x); err != nil { return err } m.Extensions = internal.SanitizeExtensions(x.Extensions) diff --git a/vendor/k8s.io/kube-openapi/pkg/spec3/operation.go b/vendor/k8s.io/kube-openapi/pkg/spec3/operation.go index f1e102547..f84d8ad2d 100644 --- a/vendor/k8s.io/kube-openapi/pkg/spec3/operation.go +++ b/vendor/k8s.io/kube-openapi/pkg/spec3/operation.go @@ -17,11 +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/validation/spec" ) @@ -35,47 +34,30 @@ 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) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error { +func (o *Operation) MarshalJSONTo(enc *jsontext.Encoder) error { var x struct { - spec.Extensions - OperationProps operationPropsOmitZero `json:",inline"` + Extensions spec.Extensions `json:",embed"` + OperationProps operationPropsOmitZero `json:",embed"` } x.Extensions = internal.SanitizeExtensions(o.Extensions) x.OperationProps = operationPropsOmitZero(o.OperationProps) - return opts.MarshalNext(enc, x) + return jsonv2.MarshalEncode(enc, x) } // 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) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error { +func (o *Operation) UnmarshalJSONFrom(dec *jsontext.Decoder) error { var x struct { - spec.Extensions + Extensions spec.Extensions `json:",embed"` OperationProps } - if err := opts.UnmarshalNext(dec, &x); err != nil { + if err := jsonv2.UnmarshalDecode(dec, &x); err != nil { return err } o.Extensions = internal.SanitizeExtensions(x.Extensions) diff --git a/vendor/k8s.io/kube-openapi/pkg/spec3/parameter.go b/vendor/k8s.io/kube-openapi/pkg/spec3/parameter.go index ada7edb63..7a8f7650b 100644 --- a/vendor/k8s.io/kube-openapi/pkg/spec3/parameter.go +++ b/vendor/k8s.io/kube-openapi/pkg/spec3/parameter.go @@ -17,11 +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/validation/spec" ) @@ -36,60 +35,31 @@ 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) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error { +func (p *Parameter) MarshalJSONTo(enc *jsontext.Encoder) error { var x struct { Ref string `json:"$ref,omitempty"` - ParameterProps parameterPropsOmitZero `json:",inline"` - spec.Extensions + ParameterProps parameterPropsOmitZero `json:",embed"` + Extensions spec.Extensions `json:",embed"` } x.Ref = p.Refable.Ref.String() x.Extensions = internal.SanitizeExtensions(p.Extensions) x.ParameterProps = parameterPropsOmitZero(p.ParameterProps) - return opts.MarshalNext(enc, x) + return jsonv2.MarshalEncode(enc, x) } 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) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error { +func (p *Parameter) UnmarshalJSONFrom(dec *jsontext.Decoder) error { var x struct { - spec.Extensions + Extensions spec.Extensions `json:",embed"` ParameterProps } - if err := opts.UnmarshalNext(dec, &x); err != nil { + if err := jsonv2.UnmarshalDecode(dec, &x); err != nil { return err } if err := internal.JSONRefFromMap(&p.Ref.Ref, x.Extensions); 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 16fbbb4dd..f9767de4e 100644 --- a/vendor/k8s.io/kube-openapi/pkg/spec3/path.go +++ b/vendor/k8s.io/kube-openapi/pkg/spec3/path.go @@ -17,13 +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/validation/spec" ) @@ -35,29 +34,10 @@ 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) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error { +func (p *Paths) MarshalJSONTo(enc *jsontext.Encoder) error { m := make(map[string]any, len(p.Extensions)+len(p.Paths)) for k, v := range p.Extensions { if internal.IsExtensionKey(k) { @@ -69,44 +49,15 @@ func (p *Paths) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) m[k] = v } } - return opts.MarshalNext(enc, m) + return jsonv2.MarshalEncode(enc, m) } // 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) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error { +func (p *Paths) UnmarshalJSONFrom(dec *jsontext.Decoder) error { tok, err := dec.ReadToken() if err != nil { return err @@ -129,7 +80,7 @@ func (p *Paths) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Deco switch k := tok.String(); { case internal.IsExtensionKey(k): var ext any - if err := opts.UnmarshalNext(dec, &ext); err != nil { + if err := jsonv2.UnmarshalDecode(dec, &ext); err != nil { return err } @@ -139,7 +90,7 @@ func (p *Paths) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Deco p.Extensions[k] = ext case len(k) > 0 && k[0] == '/': pi := Path{} - if err := opts.UnmarshalNext(dec, &pi); err != nil { + if err := jsonv2.UnmarshalDecode(dec, &pi); err != nil { return err } @@ -170,59 +121,32 @@ 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) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error { +func (p *Path) MarshalJSONTo(enc *jsontext.Encoder) error { var x struct { - Ref string `json:"$ref,omitempty"` - spec.Extensions + Ref string `json:"$ref,omitempty"` + Extensions spec.Extensions `json:",embed"` PathProps } x.Ref = p.Refable.Ref.String() x.Extensions = internal.SanitizeExtensions(p.Extensions) x.PathProps = p.PathProps - return opts.MarshalNext(enc, x) + return jsonv2.MarshalEncode(enc, x) } 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) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error { +func (p *Path) UnmarshalJSONFrom(dec *jsontext.Decoder) error { var x struct { - spec.Extensions + Extensions spec.Extensions `json:",embed"` PathProps } - if err := opts.UnmarshalNext(dec, &x); err != nil { + if err := jsonv2.UnmarshalDecode(dec, &x); err != nil { return err } if err := internal.JSONRefFromMap(&p.Ref.Ref, x.Extensions); err != nil { 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 6f8607e40..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,11 +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/validation/spec" ) @@ -36,50 +35,23 @@ 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) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error { +func (r *RequestBody) MarshalJSONTo(enc *jsontext.Encoder) error { var x struct { Ref string `json:"$ref,omitempty"` - RequestBodyProps requestBodyPropsOmitZero `json:",inline"` - spec.Extensions + RequestBodyProps requestBodyPropsOmitZero `json:",embed"` + Extensions spec.Extensions `json:",embed"` } x.Ref = r.Refable.Ref.String() x.Extensions = internal.SanitizeExtensions(r.Extensions) x.RequestBodyProps = requestBodyPropsOmitZero(r.RequestBodyProps) - return opts.MarshalNext(enc, x) + return jsonv2.MarshalEncode(enc, x) } 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 @@ -98,12 +70,12 @@ type requestBodyPropsOmitZero struct { Required bool `json:"required,omitzero"` } -func (r *RequestBody) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error { +func (r *RequestBody) UnmarshalJSONFrom(dec *jsontext.Decoder) error { var x struct { - spec.Extensions + Extensions spec.Extensions `json:",embed"` RequestBodyProps } - if err := opts.UnmarshalNext(dec, &x); err != nil { + if err := jsonv2.UnmarshalDecode(dec, &x); err != nil { return err } if err := internal.JSONRefFromMap(&r.Ref.Ref, x.Extensions); 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 73e241fdc..571439c6f 100644 --- a/vendor/k8s.io/kube-openapi/pkg/spec3/response.go +++ b/vendor/k8s.io/kube-openapi/pkg/spec3/response.go @@ -18,12 +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/validation/spec" ) @@ -37,25 +37,14 @@ 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) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error { +func (r Responses) MarshalJSONTo(enc *jsontext.Encoder) error { type ArbitraryKeys map[string]interface{} var x struct { - ArbitraryKeys - Default *Response `json:"default,omitzero"` + ArbitraryKeys ArbitraryKeys `json:",embed"` + Default *Response `json:"default,omitzero"` } x.ArbitraryKeys = make(map[string]any, len(r.Extensions)+len(r.StatusCodeResponses)) for k, v := range r.Extensions { @@ -67,20 +56,11 @@ func (r Responses) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encod x.ArbitraryKeys[strconv.Itoa(k)] = v } x.Default = r.Default - return opts.MarshalNext(enc, x) + return jsonv2.MarshalEncode(enc, x) } 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 @@ -105,38 +85,10 @@ 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) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) (err error) { +func (r *Responses) UnmarshalJSONFrom(dec *jsontext.Decoder) (err error) { tok, err := dec.ReadToken() if err != nil { return err @@ -157,7 +109,7 @@ func (r *Responses) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2. switch k := tok.String(); { case internal.IsExtensionKey(k): var ext any - if err := opts.UnmarshalNext(dec, &ext); err != nil { + if err := jsonv2.UnmarshalDecode(dec, &ext); err != nil { return err } @@ -167,14 +119,14 @@ func (r *Responses) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2. r.Extensions[k] = ext case k == "default": resp := Response{} - if err := opts.UnmarshalNext(dec, &resp); err != nil { + if err := jsonv2.UnmarshalDecode(dec, &resp); err != nil { return err } r.ResponsesProps.Default = &resp default: if nk, err := strconv.Atoi(k); err == nil { resp := Response{} - if err := opts.UnmarshalNext(dec, &resp); err != nil { + if err := jsonv2.UnmarshalDecode(dec, &resp); err != nil { return err } @@ -201,58 +153,31 @@ 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) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error { +func (r Response) MarshalJSONTo(enc *jsontext.Encoder) error { var x struct { - Ref string `json:"$ref,omitempty"` - spec.Extensions - ResponseProps `json:",inline"` + Ref string `json:"$ref,omitempty"` + Extensions spec.Extensions `json:",embed"` + ResponseProps `json:",embed"` } x.Ref = r.Refable.Ref.String() x.Extensions = internal.SanitizeExtensions(r.Extensions) x.ResponseProps = r.ResponseProps - return opts.MarshalNext(enc, x) + return jsonv2.MarshalEncode(enc, x) } 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) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error { +func (r *Response) UnmarshalJSONFrom(dec *jsontext.Decoder) error { var x struct { - spec.Extensions + Extensions spec.Extensions `json:",embed"` ResponseProps } - if err := opts.UnmarshalNext(dec, &x); err != nil { + if err := jsonv2.UnmarshalDecode(dec, &x); err != nil { return err } if err := internal.JSONRefFromMap(&r.Ref.Ref, x.Extensions); err != nil { @@ -284,59 +209,31 @@ 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) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error { +func (r *Link) MarshalJSONTo(enc *jsontext.Encoder) error { var x struct { - Ref string `json:"$ref,omitempty"` - spec.Extensions - LinkProps `json:",inline"` + Ref string `json:"$ref,omitempty"` + Extensions spec.Extensions `json:",embed"` + LinkProps `json:",embed"` } x.Ref = r.Refable.Ref.String() x.Extensions = internal.SanitizeExtensions(r.Extensions) x.LinkProps = r.LinkProps - return opts.MarshalNext(enc, x) + return jsonv2.MarshalEncode(enc, x) } 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) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error { +func (l *Link) UnmarshalJSONFrom(dec *jsontext.Decoder) error { var x struct { - spec.Extensions + Extensions spec.Extensions `json:",embed"` LinkProps } - if err := opts.UnmarshalNext(dec, &x); err != nil { + if err := jsonv2.UnmarshalDecode(dec, &x); err != nil { return err } if err := internal.JSONRefFromMap(&l.Ref.Ref, x.Extensions); 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 dd1e98ed8..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,10 +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/validation/spec" ) @@ -34,34 +36,19 @@ 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) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error { +func (s *SecurityScheme) MarshalJSONTo(enc *jsontext.Encoder) error { var x struct { Ref string `json:"$ref,omitempty"` - SecuritySchemeProps `json:",inline"` - spec.Extensions + SecuritySchemeProps `json:",embed"` + Extensions spec.Extensions `json:",embed"` } x.Ref = s.Refable.Ref.String() x.Extensions = internal.SanitizeExtensions(s.Extensions) x.SecuritySchemeProps = s.SecuritySchemeProps - return opts.MarshalNext(enc, x) + return jsonv2.MarshalEncode(enc, x) } // UnmarshalJSON hydrates this items instance with the data from JSON @@ -111,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 654a42c06..7c789f9fb 100644 --- a/vendor/k8s.io/kube-openapi/pkg/spec3/server.go +++ b/vendor/k8s.io/kube-openapi/pkg/spec3/server.go @@ -17,11 +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/validation/spec" ) @@ -41,50 +40,29 @@ 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) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error { +func (s *Server) MarshalJSONTo(enc *jsontext.Encoder) error { var x struct { - ServerProps `json:",inline"` - spec.Extensions + ServerProps `json:",embed"` + Extensions spec.Extensions `json:",embed"` } x.Extensions = internal.SanitizeExtensions(s.Extensions) x.ServerProps = s.ServerProps - return opts.MarshalNext(enc, x) + return jsonv2.MarshalEncode(enc, x) } 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) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error { +func (s *Server) UnmarshalJSONFrom(dec *jsontext.Decoder) error { var x struct { - spec.Extensions + Extensions spec.Extensions `json:",embed"` ServerProps } - if err := opts.UnmarshalNext(dec, &x); err != nil { + if err := jsonv2.UnmarshalDecode(dec, &x); err != nil { return err } s.Extensions = internal.SanitizeExtensions(x.Extensions) @@ -109,49 +87,29 @@ 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) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error { +func (s *ServerVariable) MarshalJSONTo(enc *jsontext.Encoder) error { var x struct { - ServerVariableProps `json:",inline"` - spec.Extensions + ServerVariableProps `json:",embed"` + Extensions spec.Extensions `json:",embed"` } x.Extensions = internal.SanitizeExtensions(s.Extensions) x.ServerVariableProps = s.ServerVariableProps - return opts.MarshalNext(enc, x) + return jsonv2.MarshalEncode(enc, x) } 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) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error { +func (s *ServerVariable) UnmarshalJSONFrom(dec *jsontext.Decoder) error { var x struct { - spec.Extensions + Extensions spec.Extensions `json:",embed"` ServerVariableProps } - if err := opts.UnmarshalNext(dec, &x); err != nil { + if err := jsonv2.UnmarshalDecode(dec, &x); err != nil { return err } s.Extensions = internal.SanitizeExtensions(x.Extensions) diff --git a/vendor/k8s.io/kube-openapi/pkg/spec3/spec.go b/vendor/k8s.io/kube-openapi/pkg/spec3/spec.go index 5db819c7f..1d37a7de9 100644 --- a/vendor/k8s.io/kube-openapi/pkg/spec3/spec.go +++ b/vendor/k8s.io/kube-openapi/pkg/spec3/spec.go @@ -17,10 +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/validation/spec" ) @@ -45,22 +45,14 @@ 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) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error { +func (o *OpenAPI) MarshalJSONTo(enc *jsontext.Encoder) error { type OpenAPIOmitZero struct { Version string `json:"openapi"` Info *spec.Info `json:"info"` @@ -71,5 +63,5 @@ func (o *OpenAPI) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encode ExternalDocs *ExternalDocumentation `json:"externalDocs,omitzero"` } x := (*OpenAPIOmitZero)(o) - return opts.MarshalNext(enc, x) + return jsonv2.MarshalEncode(enc, x) } 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 05310c46b..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,11 +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" ) const ( @@ -43,69 +42,37 @@ 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) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error { +func (h Header) MarshalJSONTo(enc *jsontext.Encoder) error { var x struct { - CommonValidations commonValidationsOmitZero `json:",inline"` - SimpleSchema simpleSchemaOmitZero `json:",inline"` - Extensions + CommonValidations commonValidationsOmitZero `json:",embed"` + SimpleSchema simpleSchemaOmitZero `json:",embed"` + Extensions Extensions `json:",embed"` HeaderProps } x.CommonValidations = commonValidationsOmitZero(h.CommonValidations) x.SimpleSchema = simpleSchemaOmitZero(h.SimpleSchema) x.Extensions = internal.SanitizeExtensions(h.Extensions) x.HeaderProps = h.HeaderProps - return opts.MarshalNext(enc, x) + return jsonv2.MarshalEncode(enc, x) } // 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) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error { +func (h *Header) UnmarshalJSONFrom(dec *jsontext.Decoder) error { var x struct { CommonValidations SimpleSchema - Extensions + Extensions Extensions `json:",embed"` HeaderProps } - if err := opts.UnmarshalNext(dec, &x); err != nil { + if err := jsonv2.UnmarshalDecode(dec, &x); err != nil { return err } 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 d667b705b..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,11 +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" ) // Extensions vendor specific extensions @@ -169,48 +169,30 @@ 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) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error { +func (i Info) MarshalJSONTo(enc *jsontext.Encoder) error { var x struct { - Extensions + Extensions Extensions `json:",embed"` InfoProps } x.Extensions = i.Extensions x.InfoProps = i.InfoProps - return opts.MarshalNext(enc, x) + return jsonv2.MarshalEncode(enc, x) } // 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) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error { +func (i *Info) UnmarshalJSONFrom(dec *jsontext.Decoder) error { var x struct { - Extensions + Extensions Extensions `json:",embed"` InfoProps } - if err := opts.UnmarshalNext(dec, &x); err != nil { + if err := jsonv2.UnmarshalDecode(dec, &x); err != nil { return err } i.Extensions = internal.SanitizeExtensions(x.Extensions) 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 4132467d2..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,11 +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" ) const ( @@ -95,40 +94,16 @@ 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) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error { +func (i *Items) UnmarshalJSONFrom(dec *jsontext.Decoder) error { var x struct { CommonValidations SimpleSchema - Extensions + Extensions Extensions `json:",embed"` } - if err := opts.UnmarshalNext(dec, &x); err != nil { + if err := jsonv2.UnmarshalDecode(dec, &x); err != nil { return err } if err := i.Refable.Ref.fromMap(x.Extensions); err != nil { @@ -143,38 +118,19 @@ func (i *Items) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Deco // 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) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error { +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 Extensions `json:",embed"` } x.CommonValidations = commonValidationsOmitZero(i.CommonValidations) x.SimpleSchema = simpleSchemaOmitZero(i.SimpleSchema) x.Ref = i.Refable.Ref.String() x.Extensions = internal.SanitizeExtensions(i.Extensions) - return opts.MarshalNext(enc, x) + return jsonv2.MarshalEncode(enc, x) } 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 63eed3460..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,10 +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" ) // OperationProps describes an operation @@ -94,23 +94,16 @@ 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) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error { +func (o *Operation) UnmarshalJSONFrom(dec *jsontext.Decoder) error { type OperationPropsNoMethods OperationProps // strip MarshalJSON method var x struct { - Extensions + Extensions Extensions `json:",embed"` OperationPropsNoMethods } - if err := opts.UnmarshalNext(dec, &x); err != nil { + if err := jsonv2.UnmarshalDecode(dec, &x); err != nil { return err } o.Extensions = internal.SanitizeExtensions(x.Extensions) @@ -120,27 +113,15 @@ func (o *Operation) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2. // 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) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error { +func (o Operation) MarshalJSONTo(enc *jsontext.Encoder) error { var x struct { - Extensions - OperationProps operationPropsOmitZero `json:",inline"` + Extensions Extensions `json:",embed"` + OperationProps operationPropsOmitZero `json:",embed"` } x.Extensions = internal.SanitizeExtensions(o.Extensions) x.OperationProps = operationPropsOmitZero(o.OperationProps) - return opts.MarshalNext(enc, x) + return jsonv2.MarshalEncode(enc, x) } 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 53d1e0aa9..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,11 +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" ) // ParamProps describes the specific attributes of an operation parameter @@ -88,33 +87,17 @@ 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) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error { +func (p *Parameter) UnmarshalJSONFrom(dec *jsontext.Decoder) error { var x struct { CommonValidations SimpleSchema - Extensions + Extensions Extensions `json:",embed"` ParamProps } - if err := opts.UnmarshalNext(dec, &x); err != nil { + if err := jsonv2.UnmarshalDecode(dec, &x); err != nil { return err } if err := p.Refable.Ref.fromMap(x.Extensions); err != nil { @@ -129,44 +112,21 @@ func (p *Parameter) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2. // 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) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error { +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 Extensions `json:",embed"` } x.CommonValidations = commonValidationsOmitZero(p.CommonValidations) x.SimpleSchema = simpleSchemaOmitZero(p.SimpleSchema) x.Extensions = internal.SanitizeExtensions(p.Extensions) x.ParamProps = paramPropsOmitZero(p.ParamProps) x.Ref = p.Refable.Ref.String() - return opts.MarshalNext(enc, x) + return jsonv2.MarshalEncode(enc, x) } 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 1d1588cb9..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,11 +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" ) // PathItemProps the path item specific properties @@ -48,26 +47,16 @@ 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) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error { +func (p *PathItem) UnmarshalJSONFrom(dec *jsontext.Decoder) error { var x struct { - Extensions + Extensions Extensions `json:",embed"` PathItemProps } - if err := opts.UnmarshalNext(dec, &x); err != nil { + if err := jsonv2.UnmarshalDecode(dec, &x); err != nil { return err } if err := p.Refable.Ref.fromMap(x.Extensions); err != nil { @@ -81,33 +70,17 @@ func (p *PathItem) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.D // 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) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error { +func (p PathItem) MarshalJSONTo(enc *jsontext.Encoder) error { var x struct { - Ref string `json:"$ref,omitempty"` - Extensions + Ref string `json:"$ref,omitempty"` + Extensions Extensions `json:",embed"` PathItemProps } x.Ref = p.Refable.Ref.String() x.Extensions = internal.SanitizeExtensions(p.Extensions) x.PathItemProps = p.PathItemProps - return opts.MarshalNext(enc, x) + return jsonv2.MarshalEncode(enc, x) } 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 18f6a9f42..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,13 +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" ) // Paths holds the relative paths to the individual endpoints. @@ -37,40 +36,10 @@ 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) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error { +func (p *Paths) UnmarshalJSONFrom(dec *jsontext.Decoder) error { tok, err := dec.ReadToken() if err != nil { return err @@ -94,7 +63,7 @@ func (p *Paths) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Deco switch k := tok.String(); { case internal.IsExtensionKey(k): ext = nil - if err := opts.UnmarshalNext(dec, &ext); err != nil { + if err := jsonv2.UnmarshalDecode(dec, &ext); err != nil { return err } @@ -104,7 +73,7 @@ func (p *Paths) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Deco p.Extensions[k] = ext case len(k) > 0 && k[0] == '/': pi = PathItem{} - if err := opts.UnmarshalNext(dec, &pi); err != nil { + if err := jsonv2.UnmarshalDecode(dec, &pi); err != nil { return err } @@ -126,29 +95,10 @@ func (p *Paths) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Deco // 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) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error { +func (p Paths) MarshalJSONTo(enc *jsontext.Encoder) error { m := make(map[string]any, len(p.Extensions)+len(p.Paths)) for k, v := range p.Extensions { if internal.IsExtensionKey(k) { @@ -160,5 +110,5 @@ func (p Paths) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) m[k] = v } } - return opts.MarshalNext(enc, m) + return jsonv2.MarshalEncode(enc, m) } diff --git a/vendor/k8s.io/kube-openapi/pkg/validation/spec/ref.go b/vendor/k8s.io/kube-openapi/pkg/validation/spec/ref.go index 775b3b0c3..29cec6193 100644 --- a/vendor/k8s.io/kube-openapi/pkg/validation/spec/ref.go +++ b/vendor/k8s.io/kube-openapi/pkg/validation/spec/ref.go @@ -16,10 +16,6 @@ package spec import ( "encoding/json" - "net/http" - "os" - "path/filepath" - "github.com/go-openapi/jsonreference" "k8s.io/kube-openapi/pkg/internal" @@ -56,52 +52,6 @@ func (r *Ref) RemoteURI() string { return u.String() } -// IsValidURI returns true when the url the ref points to can be found -func (r *Ref) IsValidURI(basepaths ...string) bool { - if r.String() == "" { - return true - } - - v := r.RemoteURI() - if v == "" { - return true - } - - if r.HasFullURL { - rr, err := http.Get(v) - if err != nil { - return false - } - - return rr.StatusCode/100 == 2 - } - - if !(r.HasFileScheme || r.HasFullFilePath || r.HasURLPathOnly) { - return false - } - - // check for local file - pth := v - if r.HasURLPathOnly { - base := "." - if len(basepaths) > 0 { - base = filepath.Dir(filepath.Join(basepaths...)) - } - p, e := filepath.Abs(filepath.ToSlash(filepath.Join(base, pth))) - if e != nil { - return false - } - pth = p - } - - fi, err := os.Stat(filepath.ToSlash(pth)) - if err != nil { - return false - } - - return !fi.IsDir() -} - // Inherits creates a new reference from a parent and a child // If the child cannot inherit from the parent, an error is returned func (r *Ref) Inherits(child Ref) (*Ref, 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 3ff1fe132..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,11 +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" ) // ResponseProps properties specific to a response @@ -50,30 +49,16 @@ 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) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error { +func (r *Response) UnmarshalJSONFrom(dec *jsontext.Decoder) error { var x struct { ResponseProps - Extensions + Extensions Extensions `json:",embed"` } - if err := opts.UnmarshalNext(dec, &x); err != nil { + if err := jsonv2.UnmarshalDecode(dec, &x); err != nil { return err } @@ -88,34 +73,19 @@ func (r *Response) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.D // 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) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error { +func (r Response) MarshalJSONTo(enc *jsontext.Encoder) error { var x struct { - Ref string `json:"$ref,omitempty"` - Extensions - ResponseProps responsePropsOmitZero `json:",inline"` + Ref string `json:"$ref,omitempty"` + Extensions Extensions `json:",embed"` + ResponseProps responsePropsOmitZero `json:",embed"` } x.Ref = r.Refable.Ref.String() x.Extensions = internal.SanitizeExtensions(r.Extensions) x.ResponseProps = responsePropsOmitZero(r.ResponseProps) - return opts.MarshalNext(enc, x) + return jsonv2.MarshalEncode(enc, x) } // NewResponse creates a new response instance 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 d9ad760a4..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,13 +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" ) // Responses is a container for the expected responses of an operation. @@ -45,44 +44,19 @@ 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) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error { +func (r Responses) MarshalJSONTo(enc *jsontext.Encoder) error { type ArbitraryKeys map[string]interface{} var x struct { - ArbitraryKeys - Default *Response `json:"default,omitempty"` + ArbitraryKeys ArbitraryKeys `json:",embed"` + Default *Response `json:"default,omitempty"` } x.ArbitraryKeys = make(map[string]any, len(r.Extensions)+len(r.StatusCodeResponses)) for k, v := range r.Extensions { @@ -94,7 +68,7 @@ func (r Responses) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encod x.ArbitraryKeys[strconv.Itoa(k)] = v } x.Default = r.Default - return opts.MarshalNext(enc, x) + return jsonv2.MarshalEncode(enc, x) } // ResponsesProps describes all responses for an operation. @@ -119,38 +93,10 @@ 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) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) (err error) { +func (r *Responses) UnmarshalJSONFrom(dec *jsontext.Decoder) (err error) { tok, err := dec.ReadToken() if err != nil { return err @@ -172,7 +118,7 @@ func (r *Responses) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2. switch k := tok.String(); { case internal.IsExtensionKey(k): ext = nil - if err := opts.UnmarshalNext(dec, &ext); err != nil { + if err := jsonv2.UnmarshalDecode(dec, &ext); err != nil { return err } @@ -182,7 +128,7 @@ func (r *Responses) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2. r.Extensions[k] = ext case k == "default": resp = Response{} - if err := opts.UnmarshalNext(dec, &resp); err != nil { + if err := jsonv2.UnmarshalDecode(dec, &resp); err != nil { return err } @@ -191,7 +137,7 @@ func (r *Responses) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2. default: if nk, err := strconv.Atoi(k); err == nil { resp = Response{} - if err := opts.UnmarshalNext(dec, &resp); err != nil { + if err := jsonv2.UnmarshalDecode(dec, &resp); err != nil { return err } 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 dfbb2e05c..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,13 +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" ) // BooleanProperty creates a boolean property @@ -483,125 +481,48 @@ 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) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error { +func (s Schema) MarshalJSONTo(enc *jsontext.Encoder) error { type ArbitraryKeys map[string]interface{} var x struct { - ArbitraryKeys - 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 opts.MarshalNext(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) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error { +func (s *Schema) UnmarshalJSONFrom(dec *jsontext.Decoder) error { var x struct { - Extensions + Extensions Extensions `json:",embed"` SchemaProps SwaggerSchemaProps } - if err := opts.UnmarshalNext(dec, &x); err != nil { + if err := jsonv2.UnmarshalDecode(dec, &x); err != nil { return err } @@ -616,9 +537,6 @@ func (s *Schema) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Dec 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 e2b7da14c..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,10 +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" ) // SecuritySchemeProps describes a swagger security scheme in the securityDefinitions section @@ -46,28 +46,17 @@ 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) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error { +func (s SecurityScheme) MarshalJSONTo(enc *jsontext.Encoder) error { var x struct { - Extensions + Extensions Extensions `json:",embed"` SecuritySchemeProps } x.Extensions = internal.SanitizeExtensions(s.Extensions) x.SecuritySchemeProps = s.SecuritySchemeProps - return opts.MarshalNext(enc, x) + return jsonv2.MarshalEncode(enc, x) } // UnmarshalJSON marshal this from JSON @@ -78,12 +67,12 @@ func (s *SecurityScheme) UnmarshalJSON(data []byte) error { return json.Unmarshal(data, &s.VendorExtensible) } -func (s *SecurityScheme) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error { +func (s *SecurityScheme) UnmarshalJSONFrom(dec *jsontext.Decoder) error { var x struct { - Extensions + Extensions Extensions `json:",embed"` SecuritySchemeProps } - if err := opts.UnmarshalNext(dec, &x); err != nil { + if err := jsonv2.UnmarshalDecode(dec, &x); err != nil { return err } s.Extensions = internal.SanitizeExtensions(x.Extensions) 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 c8f3beaa3..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,11 +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" ) // Swagger this is the root document object for the API specification. @@ -35,57 +35,35 @@ 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) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error { +func (s Swagger) MarshalJSONTo(enc *jsontext.Encoder) error { var x struct { - Extensions + Extensions Extensions `json:",embed"` SwaggerProps } x.Extensions = internal.SanitizeExtensions(s.Extensions) x.SwaggerProps = s.SwaggerProps - return opts.MarshalNext(enc, x) + return jsonv2.MarshalEncode(enc, x) } // 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) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error { +func (s *Swagger) UnmarshalJSONFrom(dec *jsontext.Decoder) error { // Note: If you're willing to make breaking changes, it is possible to // optimize this and other usages of this pattern: // https://github.com/kubernetes/kube-openapi/pull/319#discussion_r983165948 var x struct { - Extensions + Extensions Extensions `json:",embed"` SwaggerProps } - if err := opts.UnmarshalNext(dec, &x); err != nil { + if err := jsonv2.UnmarshalDecode(dec, &x); err != nil { return err } s.Extensions = internal.SanitizeExtensions(x.Extensions) @@ -132,63 +110,37 @@ 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 -func (s SchemaOrBool) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error { +func (s SchemaOrBool) MarshalJSONTo(enc *jsontext.Encoder) error { if s.Schema != nil { - return opts.MarshalNext(enc, s.Schema) + return jsonv2.MarshalEncode(enc, s.Schema) } if s.Schema == nil && !s.Allows { - return enc.WriteToken(jsonv2.False) + return enc.WriteToken(jsontext.False) } - return enc.WriteToken(jsonv2.True) + return enc.WriteToken(jsontext.True) } // 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) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error { +func (s *SchemaOrBool) UnmarshalJSONFrom(dec *jsontext.Decoder) error { switch k := dec.PeekKind(); k { case '{': - err := opts.UnmarshalNext(dec, &s.Schema) + err := jsonv2.UnmarshalDecode(dec, &s.Schema) if err != nil { return err } s.Allows = true return nil case 't', 'f': - err := opts.UnmarshalNext(dec, &s.Allows) + err := jsonv2.UnmarshalDecode(dec, &s.Allows) if err != nil { return err } @@ -206,62 +158,31 @@ 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 -func (s SchemaOrStringArray) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error { +func (s SchemaOrStringArray) MarshalJSONTo(enc *jsontext.Encoder) error { if len(s.Property) > 0 { - return opts.MarshalNext(enc, s.Property) + return jsonv2.MarshalEncode(enc, s.Property) } if s.Schema != nil { - return opts.MarshalNext(enc, s.Schema) + return jsonv2.MarshalEncode(enc, s.Schema) } - return enc.WriteToken(jsonv2.Null) + return enc.WriteToken(jsontext.Null) } // 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) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error { +func (s *SchemaOrStringArray) UnmarshalJSONFrom(dec *jsontext.Decoder) error { switch dec.PeekKind() { case '{': - return opts.UnmarshalNext(dec, &s.Schema) + return jsonv2.UnmarshalDecode(dec, &s.Schema) case '[': - return opts.UnmarshalNext(dec, &s.Property) + return jsonv2.UnmarshalDecode(dec, &s.Property) default: _, err := dec.ReadValue() return err @@ -298,48 +219,17 @@ 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) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error { +func (s *StringOrArray) UnmarshalJSONFrom(dec *jsontext.Decoder) error { switch k := dec.PeekKind(); k { case '[': *s = StringOrArray{} - return opts.UnmarshalNext(dec, (*[]string)(s)) + return jsonv2.UnmarshalDecode(dec, (*[]string)(s)) case '"': *s = StringOrArray{""} - return opts.UnmarshalNext(dec, &(*s)[0]) + return jsonv2.UnmarshalDecode(dec, &(*s)[0]) case 'n': // Throw out null token _, _ = dec.ReadToken() @@ -382,56 +272,28 @@ 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 -func (s SchemaOrArray) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error { +func (s SchemaOrArray) MarshalJSONTo(enc *jsontext.Encoder) error { if s.Schemas != nil { - return opts.MarshalNext(enc, s.Schemas) + return jsonv2.MarshalEncode(enc, s.Schemas) } - return opts.MarshalNext(enc, s.Schema) + return jsonv2.MarshalEncode(enc, s.Schema) } // 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) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error { +func (s *SchemaOrArray) UnmarshalJSONFrom(dec *jsontext.Decoder) error { switch dec.PeekKind() { case '{': - return opts.UnmarshalNext(dec, &s.Schema) + return jsonv2.UnmarshalDecode(dec, &s.Schema) case '[': - return opts.UnmarshalNext(dec, &s.Schemas) + return jsonv2.UnmarshalDecode(dec, &s.Schemas) default: _, err := dec.ReadValue() return err 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 d105d52ca..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,11 +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" ) // TagProps describe a tag entry in the top level tags section of a swagger spec @@ -41,48 +40,30 @@ 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) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error { +func (t Tag) MarshalJSONTo(enc *jsontext.Encoder) error { var x struct { - Extensions + Extensions Extensions `json:",embed"` TagProps } x.Extensions = internal.SanitizeExtensions(t.Extensions) x.TagProps = t.TagProps - return opts.MarshalNext(enc, x) + return jsonv2.MarshalEncode(enc, x) } // 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) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error { +func (t *Tag) UnmarshalJSONFrom(dec *jsontext.Decoder) error { var x struct { - Extensions + Extensions Extensions `json:",embed"` TagProps } - if err := opts.UnmarshalNext(dec, &x); err != nil { + if err := jsonv2.UnmarshalDecode(dec, &x); err != nil { return err } t.Extensions = internal.SanitizeExtensions(x.Extensions) diff --git a/vendor/modules.txt b/vendor/modules.txt index 20fe39289..7fcaac767 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -280,10 +280,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 @@ -389,52 +385,29 @@ github.com/go-logr/logr/slogr # github.com/go-logr/zapr v1.3.0 ## explicit; go 1.18 github.com/go-logr/zapr -# github.com/go-openapi/jsonpointer v0.22.1 -## explicit; go 1.24.0 +# github.com/go-openapi/jsonpointer v1.0.0 +## explicit; go 1.25.0 github.com/go-openapi/jsonpointer -# github.com/go-openapi/jsonreference v0.21.3 -## explicit; go 1.24.0 +github.com/go-openapi/jsonpointer/jsonname +# github.com/go-openapi/jsonreference v1.0.0 +## explicit; go 1.25.0 github.com/go-openapi/jsonreference github.com/go-openapi/jsonreference/internal -# github.com/go-openapi/swag v0.25.1 -## explicit; go 1.24.0 -github.com/go-openapi/swag -# github.com/go-openapi/swag/cmdutils v0.25.1 -## explicit; go 1.24.0 -github.com/go-openapi/swag/cmdutils -# github.com/go-openapi/swag/conv v0.25.1 -## explicit; go 1.24.0 +# github.com/go-openapi/swag/conv v0.27.1 +## explicit; go 1.25.0 github.com/go-openapi/swag/conv -# github.com/go-openapi/swag/fileutils v0.25.1 -## explicit; go 1.24.0 -github.com/go-openapi/swag/fileutils -# github.com/go-openapi/swag/jsonname v0.25.1 -## explicit; go 1.24.0 -github.com/go-openapi/swag/jsonname -# github.com/go-openapi/swag/jsonutils v0.25.1 -## explicit; go 1.24.0 +# github.com/go-openapi/swag/jsonutils v0.27.1 +## 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.25.1 -## explicit; go 1.24.0 -github.com/go-openapi/swag/loading -# github.com/go-openapi/swag/mangling v0.25.1 -## explicit; go 1.24.0 -github.com/go-openapi/swag/mangling -# github.com/go-openapi/swag/netutils v0.25.1 -## explicit; go 1.24.0 -github.com/go-openapi/swag/netutils -# github.com/go-openapi/swag/stringutils v0.25.1 -## explicit; go 1.24.0 -github.com/go-openapi/swag/stringutils -# github.com/go-openapi/swag/typeutils v0.25.1 -## explicit; go 1.24.0 +# github.com/go-openapi/swag/pools v0.27.1 +## explicit; go 1.25.0 +github.com/go-openapi/swag/pools +# github.com/go-openapi/swag/typeutils v0.27.1 +## explicit; go 1.25.0 github.com/go-openapi/swag/typeutils -# github.com/go-openapi/swag/yamlutils v0.25.1 -## explicit; go 1.24.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 @@ -1606,13 +1579,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-20250910181357-589584f1c912 -## explicit; go 1.23.0 +# k8s.io/kube-openapi v0.0.0-20261007072838-e2e80c32a35f +## 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/schemaconv k8s.io/kube-openapi/pkg/spec3 k8s.io/kube-openapi/pkg/util/proto @@ -1978,6 +1950,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/jsonname/LICENSE b/vendor/sigs.k8s.io/structured-merge-diff/v7/LICENSE similarity index 99% rename from vendor/github.com/go-openapi/swag/jsonname/LICENSE rename to vendor/sigs.k8s.io/structured-merge-diff/v7/LICENSE index d64569567..8dada3eda 100644 --- a/vendor/github.com/go-openapi/swag/jsonname/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 +`