diff --git a/go.mod b/go.mod index b6e0231f66..2cc74d8df5 100644 --- a/go.mod +++ b/go.mod @@ -17,9 +17,9 @@ require ( github.com/Azure/go-autorest/autorest v0.11.29 github.com/Azure/go-autorest/autorest/mocks v0.4.2 github.com/Azure/go-autorest/autorest/to v0.4.0 - github.com/IBM/go-sdk-core/v5 v5.14.1 + github.com/IBM/go-sdk-core/v5 v5.17.4 github.com/IBM/ibm-cos-sdk-go v1.10.0 - github.com/IBM/platform-services-go-sdk v0.55.0 + github.com/IBM/platform-services-go-sdk v0.67.0 github.com/aws/aws-sdk-go v1.50.35 github.com/davecgh/go-spew v1.1.1 github.com/ghodss/yaml v1.0.0 @@ -81,16 +81,17 @@ require ( github.com/evanphx/json-patch v4.12.0+incompatible // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/gabriel-vasile/mimetype v1.4.3 // indirect github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/go-openapi/errors v0.20.3 // indirect + github.com/go-openapi/errors v0.21.0 // indirect github.com/go-openapi/jsonpointer v0.19.6 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect - github.com/go-openapi/strfmt v0.21.5 // indirect + github.com/go-openapi/strfmt v0.22.1 // indirect github.com/go-openapi/swag v0.22.3 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/go-playground/validator/v10 v10.13.0 // indirect + github.com/go-playground/validator/v10 v10.19.0 // indirect github.com/gofrs/uuid/v5 v5.2.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v4 v4.5.0 // indirect @@ -112,7 +113,7 @@ require ( github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/kylelemons/godebug v1.1.0 // indirect - github.com/leodido/go-urn v1.2.3 // indirect + github.com/leodido/go-urn v1.4.0 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-ieproxy v0.0.1 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect @@ -133,7 +134,7 @@ require ( go.etcd.io/etcd/api/v3 v3.5.10 // indirect go.etcd.io/etcd/client/pkg/v3 v3.5.10 // indirect go.etcd.io/etcd/client/v3 v3.5.10 // indirect - go.mongodb.org/mongo-driver v1.11.3 // indirect + go.mongodb.org/mongo-driver v1.14.0 // indirect go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect diff --git a/go.sum b/go.sum index 667147527f..f46515bd25 100644 --- a/go.sum +++ b/go.sum @@ -573,12 +573,12 @@ github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 h1:XHOnouVk1mx github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/IBM/go-sdk-core/v5 v5.14.1 h1:WR1r0zz+gDW++xzZjF41r9ueY4JyjS2vgZjiYs8lO3c= -github.com/IBM/go-sdk-core/v5 v5.14.1/go.mod h1:MUvIr/1mgGh198ZXL+ByKz9Qs1JoEh80v/96x8jPXNY= +github.com/IBM/go-sdk-core/v5 v5.17.4 h1:VGb9+mRrnS2HpHZFM5hy4J6ppIWnwNrw0G+tLSgcJLc= +github.com/IBM/go-sdk-core/v5 v5.17.4/go.mod h1:KsAAI7eStAWwQa4F96MLy+whYSh39JzNjklZRbN/8ns= github.com/IBM/ibm-cos-sdk-go v1.10.0 h1:/2VIev2/jBei39OqU2+nSZQnoWJ+KtkiSAIDkqsd7uU= github.com/IBM/ibm-cos-sdk-go v1.10.0/go.mod h1:C8KRTRaoD3CWPPBOa6FCOpdh0ZMlUjKAAA4i3F+Q/sc= -github.com/IBM/platform-services-go-sdk v0.55.0 h1:W598xZanL61bwd8O2DQexr4qjIr+/tP0Y845zoms5yA= -github.com/IBM/platform-services-go-sdk v0.55.0/go.mod h1:CWSprvsCsXWvujmBzbtoJSmbRZS9FVV3O594b0t/GiM= +github.com/IBM/platform-services-go-sdk v0.67.0 h1:AGu3NiCUyvyFUqbgtmsFRh74kyXrmNbSu1yG/qwGLIM= +github.com/IBM/platform-services-go-sdk v0.67.0/go.mod h1:6rYd3stLSnotYmZlxclw45EJPaQuLmh5f7c+Mg7rOg4= github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk= github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I= github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= @@ -596,7 +596,6 @@ github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df h github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df/go.mod h1:pSwJ0fSY5KhvocuWSx4fz3BA8OrA1bQn+K1Eli3BRwM= github.com/apache/arrow/go/v10 v10.0.1/go.mod h1:YvhnlEePVnBS4+0z3fhPfUy7W1Ikj0Ih0vcRo/gZ1M0= github.com/apache/thrift v0.16.0/go.mod h1:PHK3hniurgQaNMZYaCLEqXKsYK8upmhPbmdP2FXSqgU= -github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/aws/aws-sdk-go v1.50.35 h1:llQnNddBI/64pK7pwUFBoWYmg8+XGQUCs214eMbSDZc= @@ -655,6 +654,8 @@ github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/ github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= +github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g= @@ -674,15 +675,14 @@ 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/errors v0.20.2/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= -github.com/go-openapi/errors v0.20.3 h1:rz6kiC84sqNQoqrtulzaL/VERgkoCyB6WdEkc2ujzUc= -github.com/go-openapi/errors v0.20.3/go.mod h1:Z3FlZ4I8jEGxjUK+bugx3on2mIAk4txuAOhlsB1FSgk= +github.com/go-openapi/errors v0.21.0 h1:FhChC/duCnfoLj1gZ0BgaBmzhJC2SL/sJr8a2vAobSY= +github.com/go-openapi/errors v0.21.0/go.mod h1:jxNTMUxRCKj65yb/okJGEtahVd7uvWnuWfj53bse4ho= github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= -github.com/go-openapi/strfmt v0.21.5 h1:Z/algjpXIZpbvdN+6KbVTkpO75RuedMrqpn1GN529h4= -github.com/go-openapi/strfmt v0.21.5/go.mod h1:k+RzNO0Da+k3FrrynSNN8F7n/peCmQQqbbXjtDfvmGg= +github.com/go-openapi/strfmt v0.22.1 h1:5Ky8cybT4576C6Ffc+8gYji/wRXCo6Ozm8RaWjPI6jc= +github.com/go-openapi/strfmt v0.22.1/go.mod h1:OfVoytIXJasDkkGvkb1Cceb3BPyMOwk1FgmyyEw7NYg= github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/go-pdf/fpdf v0.5.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= @@ -693,8 +693,8 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.13.0 h1:cFRQdfaSMCOSfGCCLB20MHvuoHb/s5G8L5pu2ppK5AQ= -github.com/go-playground/validator/v10 v10.13.0/go.mod h1:dwu7+CG8/CtBiJFZDz4e+5Upb6OLw04gtBYw0mcG/z4= +github.com/go-playground/validator/v10 v10.19.0 h1:ol+5Fu+cSq9JD7SoSqe04GMI92cbn0+wvQ3bZ8b/AU4= +github.com/go-playground/validator/v10 v10.19.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= @@ -748,7 +748,6 @@ github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -806,7 +805,6 @@ github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLe github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= @@ -887,7 +885,6 @@ github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:C github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/asmfmt v1.3.2/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j0HLHbNSE= -github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= @@ -902,8 +899,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/leodido/go-urn v1.2.3 h1:6BE2vPT0lqoz3fmOesHZiaiFh7889ssCo2GMvLCfiuA= -github.com/leodido/go-urn v1.2.3/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= +github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= +github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/lyft/protoc-gen-star v0.6.1/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= github.com/lyft/protoc-gen-star/v2 v2.0.1/go.mod h1:RcCdONR2ScXaYnQC5tUzxzlpA3WVYF7/opLeUgcQs/o= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= @@ -924,7 +921,6 @@ github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcs github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8IeTMnF8JTXieKnO4Z6JCsikNEzj0DwauVzE= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -932,10 +928,8 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= @@ -944,8 +938,8 @@ github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/ginkgo/v2 v2.15.0 h1:79HwNRBAZHOEwrczrgSOPy+eFTTlIGELKy5as+ClttY= github.com/onsi/ginkgo/v2 v2.15.0/go.mod h1:HlxMHtYF57y6Dpf+mc5529KKmSq9h2FpCF+/ZkwUxKM= -github.com/onsi/gomega v1.31.0 h1:54UJxxj6cPInHS3a35wm6BK/F9nHYueZ1NVujHDrnXE= -github.com/onsi/gomega v1.31.0/go.mod h1:DW9aCi7U6Yi40wNVAvT6kzFnEVEI5n3DloYBiKiT6zk= +github.com/onsi/gomega v1.31.1 h1:KYppCUK+bUgAZwHOu7EXVBKyQA6ILvOESHkn/tgoqvo= +github.com/onsi/gomega v1.31.1/go.mod h1:y40C95dwAD1Nz36SsEnxvfFe8FFfNxzI5eJ0EYGyAy0= github.com/openshift/api v0.0.0-20240816151955-65532e7f773e h1:xypovjFuxCGdcxu2E1WJsBS47ZXyI8wQyEaeHQXrhFY= github.com/openshift/api v0.0.0-20240816151955-65532e7f773e/go.mod h1:OOh6Qopf21pSzqNVCB5gomomBXb8o5sGKZxG2KNpaXM= github.com/openshift/build-machinery-go v0.0.0-20240419090851-af9c868bcf52 h1:bqBwrXG7sbJUqP1Og1bR8FvVh7qb7CrMgy9saKmOZFs= @@ -1021,16 +1015,10 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= -github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75 h1:6fotK7otjonDflCTK0BCfls4SPy3NcCVb5dqqmbRknE= github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75/go.mod h1:KO6IkyS8Y3j8OdNO85qEYBsRPuteD+YciPomcXdrMnk= -github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= -github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= -github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -1056,9 +1044,8 @@ go.etcd.io/etcd/raft/v3 v3.5.10 h1:cgNAYe7xrsrn/5kXMSaH8kM/Ky8mAdMqGOxyYwpP0LA= go.etcd.io/etcd/raft/v3 v3.5.10/go.mod h1:odD6kr8XQXTy9oQnyMPBOr0TVe+gT0neQhElQ6jbGRc= go.etcd.io/etcd/server/v3 v3.5.10 h1:4NOGyOwD5sUZ22PiWYKmfxqoeh72z6EhYjNosKGLmZg= go.etcd.io/etcd/server/v3 v3.5.10/go.mod h1:gBplPHfs6YI0L+RpGkTQO7buDbHv5HJGG/Bst0/zIPo= -go.mongodb.org/mongo-driver v1.10.0/go.mod h1:wsihk0Kdgv8Kqu1Anit4sfK+22vSFbUrAVEYRhCXrA8= -go.mongodb.org/mongo-driver v1.11.3 h1:Ql6K6qYHEzB6xvu4+AU0BoRoqf9vFPcc4o7MUIdPW8Y= -go.mongodb.org/mongo-driver v1.11.3/go.mod h1:PTSz5yu21bkT/wXpkS7WR5f0ddqw5quethTUn9WM+2g= +go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd80= +go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -1103,7 +1090,6 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= @@ -1674,7 +1660,6 @@ google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGm google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= @@ -1690,7 +1675,6 @@ gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/vendor/github.com/IBM/go-sdk-core/v5/core/authentication_error.go b/vendor/github.com/IBM/go-sdk-core/v5/core/authentication_error.go new file mode 100644 index 0000000000..77f8dda2e7 --- /dev/null +++ b/vendor/github.com/IBM/go-sdk-core/v5/core/authentication_error.go @@ -0,0 +1,57 @@ +package core + +// (C) Copyright IBM Corp. 2024. +// +// 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. + +import ( + "errors" +) + +// AuthenticationError describes the problem returned when +// authentication over HTTP fails. +type AuthenticationError struct { + Err error + *HTTPProblem +} + +// NewAuthenticationError is a deprecated function that was previously used for creating new +// AuthenticationError structs. HTTPProblem types should be used instead of AuthenticationError types. +func NewAuthenticationError(response *DetailedResponse, err error) *AuthenticationError { + GetLogger().Warn("NewAuthenticationError is deprecated and should not be used.") + authError := authenticationErrorf(err, response, "unknown", NewProblemComponent("unknown", "unknown")) + return authError +} + +// authenticationErrorf creates and returns a new instance of "AuthenticationError". +func authenticationErrorf(err error, response *DetailedResponse, operationID string, component *ProblemComponent) *AuthenticationError { + // This function should always be called with non-nil error instances. + if err == nil { + return nil + } + + var httpErr *HTTPProblem + if !errors.As(err, &httpErr) { + if response == nil { + return nil + } + httpErr = httpErrorf(err.Error(), response) + } + + enrichHTTPProblem(httpErr, operationID, component) + + return &AuthenticationError{ + HTTPProblem: httpErr, + Err: err, + } +} diff --git a/vendor/github.com/IBM/go-sdk-core/v5/core/authenticator.go b/vendor/github.com/IBM/go-sdk-core/v5/core/authenticator.go index e580c65061..8292490ee8 100644 --- a/vendor/github.com/IBM/go-sdk-core/v5/core/authenticator.go +++ b/vendor/github.com/IBM/go-sdk-core/v5/core/authenticator.go @@ -24,20 +24,3 @@ type Authenticator interface { Authenticate(*http.Request) error Validate() error } - -// AuthenticationError describes the error returned when authentication fails -type AuthenticationError struct { - Response *DetailedResponse - Err error -} - -func (e *AuthenticationError) Error() string { - return e.Err.Error() -} - -func NewAuthenticationError(response *DetailedResponse, err error) *AuthenticationError { - return &AuthenticationError{ - Response: response, - Err: err, - } -} diff --git a/vendor/github.com/IBM/go-sdk-core/v5/core/authenticator_factory.go b/vendor/github.com/IBM/go-sdk-core/v5/core/authenticator_factory.go index b02bc1efcc..455fba064c 100644 --- a/vendor/github.com/IBM/go-sdk-core/v5/core/authenticator_factory.go +++ b/vendor/github.com/IBM/go-sdk-core/v5/core/authenticator_factory.go @@ -1,6 +1,6 @@ package core -// (C) Copyright IBM Corp. 2019, 2021. +// (C) Copyright IBM Corp. 2019, 2023. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -58,10 +58,17 @@ func GetAuthenticatorFromEnvironment(credentialKey string) (authenticator Authen authenticator, err = newVpcInstanceAuthenticatorFromMap(properties) } else if strings.EqualFold(authType, AUTHTYPE_CP4D) { authenticator, err = newCloudPakForDataAuthenticatorFromMap(properties) + } else if strings.EqualFold(authType, AUTHTYPE_MCSP) { + authenticator, err = newMCSPAuthenticatorFromMap(properties) } else if strings.EqualFold(authType, AUTHTYPE_NOAUTH) { authenticator, err = NewNoAuthAuthenticator() } else { - err = fmt.Errorf(ERRORMSG_AUTHTYPE_UNKNOWN, authType) + err = SDKErrorf( + nil, + fmt.Sprintf(ERRORMSG_AUTHTYPE_UNKNOWN, authType), + "unknown-auth-type", + getComponentInfo(), + ) } return diff --git a/vendor/github.com/IBM/go-sdk-core/v5/core/base_service.go b/vendor/github.com/IBM/go-sdk-core/v5/core/base_service.go index defeef2e6b..6a9f85a72b 100644 --- a/vendor/github.com/IBM/go-sdk-core/v5/core/base_service.go +++ b/vendor/github.com/IBM/go-sdk-core/v5/core/base_service.go @@ -20,6 +20,7 @@ import ( "crypto/tls" "crypto/x509" "encoding/json" + "errors" "fmt" "io" "net/http" @@ -84,14 +85,17 @@ type BaseService struct { // parameters and service options will be performed before instance creation. func NewBaseService(options *ServiceOptions) (*BaseService, error) { if HasBadFirstOrLastChar(options.URL) { - return nil, fmt.Errorf(ERRORMSG_PROP_INVALID, "URL") + err := fmt.Errorf(ERRORMSG_PROP_INVALID, "URL") + return nil, SDKErrorf(err, "", "bad-char", getComponentInfo()) } if IsNil(options.Authenticator) { - return nil, fmt.Errorf(ERRORMSG_NO_AUTHENTICATOR) + err := fmt.Errorf(ERRORMSG_NO_AUTHENTICATOR) + return nil, SDKErrorf(err, "", "missing-auth", getComponentInfo()) } if err := options.Authenticator.Validate(); err != nil { + err = RepurposeSDKProblem(err, "auth-validation-failed") return nil, err } @@ -130,6 +134,7 @@ func (service *BaseService) ConfigureService(serviceName string) error { // Try to load service properties from external config. serviceProps, err := getServiceProperties(serviceName) if err != nil { + err = RepurposeSDKProblem(err, "get-props-error") return err } @@ -141,6 +146,7 @@ func (service *BaseService) ConfigureService(serviceName string) error { if url, ok := serviceProps[PROPNAME_SVC_URL]; ok && url != "" { err := service.SetURL(url) if err != nil { + err = RepurposeSDKProblem(err, "set-url-fail") return err } } @@ -204,13 +210,14 @@ func (service *BaseService) ConfigureService(serviceName string) error { // // Deprecated: use SetServiceURL instead. func (service *BaseService) SetURL(url string) error { - return service.SetServiceURL(url) + return RepurposeSDKProblem(service.SetServiceURL(url), "set-url-fail") } // SetServiceURL sets the service URL. func (service *BaseService) SetServiceURL(url string) error { if HasBadFirstOrLastChar(url) { - return fmt.Errorf(ERRORMSG_PROP_INVALID, "URL") + err := fmt.Errorf(ERRORMSG_PROP_INVALID, "URL") + return SDKErrorf(err, "", "bad-char", getComponentInfo()) } service.Options.URL = url @@ -372,15 +379,26 @@ func (service *BaseService) Request(req *http.Request, result interface{}) (deta // Add authentication to the outbound request. if IsNil(service.Options.Authenticator) { err = fmt.Errorf(ERRORMSG_NO_AUTHENTICATOR) + err = SDKErrorf(err, "", "missing-auth", getComponentInfo()) return } - authError := service.Options.Authenticator.Authenticate(req) - if authError != nil { - err = fmt.Errorf(ERRORMSG_AUTHENTICATE_ERROR, authError.Error()) - castErr, ok := authError.(*AuthenticationError) - if ok { - detailedResponse = castErr.Response + authenticateError := service.Options.Authenticator.Authenticate(req) + if authenticateError != nil { + var authErr *AuthenticationError + var sdkErr *SDKProblem + if errors.As(authenticateError, &authErr) { + detailedResponse = authErr.Response + err = SDKErrorf(authErr.HTTPProblem, fmt.Sprintf(ERRORMSG_AUTHENTICATE_ERROR, authErr.Error()), "auth-request-failed", getComponentInfo()) + } else if errors.As(authenticateError, &sdkErr) { + sdkErr := RepurposeSDKProblem(authenticateError, "auth-failed") + // For compatibility. + sdkErr.(*SDKProblem).Summary = fmt.Sprintf(ERRORMSG_AUTHENTICATE_ERROR, authenticateError.Error()) + err = sdkErr + } else { + // External authenticators that implement the core interface might return a standard error. + // Handle that by wrapping it here. + err = SDKErrorf(err, fmt.Sprintf(ERRORMSG_AUTHENTICATE_ERROR, authenticateError.Error()), "custom-auth-failed", getComponentInfo()) } return } @@ -398,10 +416,12 @@ func (service *BaseService) Request(req *http.Request, result interface{}) (deta // Invoke the request, then check for errors during the invocation. var httpResponse *http.Response httpResponse, err = service.Client.Do(req) + if err != nil { if strings.Contains(err.Error(), SSL_CERTIFICATION_ERROR) { err = fmt.Errorf(ERRORMSG_SSL_VERIFICATION_FAILED + "\n" + err.Error()) } + err = SDKErrorf(err, "", "no-connection-made", getComponentInfo()) return } @@ -415,59 +435,16 @@ func (service *BaseService) Request(req *http.Request, result interface{}) (deta } } - // Start to populate the DetailedResponse. - detailedResponse = &DetailedResponse{ - StatusCode: httpResponse.StatusCode, - Headers: httpResponse.Header, - } - - contentType := httpResponse.Header.Get(CONTENT_TYPE) - - // If the operation was unsuccessful, then set up the DetailedResponse - // and error objects appropriately. + // If the operation was unsuccessful, then set up and return + // the DetailedResponse and error objects appropriately. if httpResponse.StatusCode < 200 || httpResponse.StatusCode >= 300 { - - var responseBody []byte - - // First, read the response body into a byte array. - if !IsNil(httpResponse.Body) { - var readErr error - - defer httpResponse.Body.Close() // #nosec G307 - responseBody, readErr = io.ReadAll(httpResponse.Body) - if readErr != nil { - err = fmt.Errorf(ERRORMSG_READ_RESPONSE_BODY, readErr.Error()) - return - } - } - - // If the responseBody is empty, then just return a generic error based on the status code. - if len(responseBody) == 0 { - err = fmt.Errorf(http.StatusText(httpResponse.StatusCode)) - return - } - - // For a JSON-based error response body, decode it into a map (generic JSON object). - if IsJSONMimeType(contentType) { - // Return the error response body as a map, along with an - // error object containing our best guess at an error message. - responseMap, decodeErr := decodeAsMap(responseBody) - if decodeErr == nil { - detailedResponse.Result = responseMap - err = fmt.Errorf(getErrorMessage(responseMap, detailedResponse.StatusCode)) - return - } - } - - // For a non-JSON response or if we tripped while decoding the JSON response, - // just return the response body byte array in the RawResult field along with - // an error object that contains the generic error message for the status code. - detailedResponse.RawResult = responseBody - err = fmt.Errorf(http.StatusText(httpResponse.StatusCode)) + detailedResponse, err = processErrorResponse(httpResponse) + err = RepurposeSDKProblem(err, "error-response") return } // Operation was successful and we are expecting a response, so process the response. + detailedResponse, contentType := getDetailedResponseAndContentType(httpResponse) if !IsNil(result) { resultType := reflect.TypeOf(result).String() @@ -484,6 +461,7 @@ func (service *BaseService) Request(req *http.Request, result interface{}) (deta responseBody, readErr := io.ReadAll(httpResponse.Body) if readErr != nil { err = fmt.Errorf(ERRORMSG_READ_RESPONSE_BODY, readErr.Error()) + err = SDKErrorf(err, "", "cant-read-success-res-body", getComponentInfo()) return } @@ -500,6 +478,7 @@ func (service *BaseService) Request(req *http.Request, result interface{}) (deta // Error decoding the response body. // Return the response body in RawResult, along with an error. err = fmt.Errorf(ERRORMSG_UNMARSHAL_RESPONSE_BODY, decodeErr.Error()) + err = SDKErrorf(err, "", "res-body-decode-error", getComponentInfo()) detailedResponse.RawResult = responseBody return } @@ -530,6 +509,7 @@ func (service *BaseService) Request(req *http.Request, result interface{}) (deta // But make sure we save the bytes we read in the DetailedResponse for debugging purposes detailedResponse.Result = responseBody err = fmt.Errorf(ERRORMSG_UNEXPECTED_RESPONSE, contentType, resultType) + err = SDKErrorf(err, "", "unparsable-result-field", getComponentInfo()) return } } @@ -542,6 +522,67 @@ func (service *BaseService) Request(req *http.Request, result interface{}) (deta return } +// getDetailedResponseAndContentType starts to populate the DetailedResponse +// and extracts the Content-Type header value from the response. +func getDetailedResponseAndContentType(httpResponse *http.Response) (detailedResponse *DetailedResponse, contentType string) { + if httpResponse != nil { + contentType = httpResponse.Header.Get(CONTENT_TYPE) + detailedResponse = &DetailedResponse{ + StatusCode: httpResponse.StatusCode, + Headers: httpResponse.Header, + } + } + return +} + +func processErrorResponse(httpResponse *http.Response) (detailedResponse *DetailedResponse, err *SDKProblem) { + detailedResponse, contentType := getDetailedResponseAndContentType(httpResponse) + + var responseBody []byte + + // First, read the response body into a byte array. + if !IsNil(httpResponse.Body) { + var readErr error + + defer httpResponse.Body.Close() // #nosec G307 + responseBody, readErr = io.ReadAll(httpResponse.Body) + if readErr != nil { + httpErr := httpErrorf(http.StatusText(httpResponse.StatusCode), detailedResponse) + err = SDKErrorf(httpErr, fmt.Sprintf(ERRORMSG_READ_RESPONSE_BODY, readErr.Error()), "cant-read-error-body", getComponentInfo()) + return + } + } + + // If the responseBody is empty, then just return a generic error based on the status code. + if len(responseBody) == 0 { + httpErr := httpErrorf(http.StatusText(httpResponse.StatusCode), detailedResponse) + err = SDKErrorf(httpErr, "", "no-error-body", getComponentInfo()) + return + } + + // For a JSON-based error response body, decode it into a map (generic JSON object). + if IsJSONMimeType(contentType) { + // Return the error response body as a map, along with an + // error object containing our best guess at an error message. + responseMap, decodeErr := decodeAsMap(responseBody) + if decodeErr == nil { + detailedResponse.Result = responseMap + errorMsg := getErrorMessage(responseMap, detailedResponse.StatusCode) + httpErr := httpErrorf(errorMsg, detailedResponse) + err = SDKErrorf(httpErr, "", "json-error-body", getComponentInfo()) + return + } + } + + // For a non-JSON response or if we tripped while decoding the JSON response, + // just return the response body byte array in the RawResult field along with + // an error object that contains the generic error message for the status code. + detailedResponse.RawResult = responseBody + httpErr := httpErrorf(http.StatusText(httpResponse.StatusCode), detailedResponse) + err = SDKErrorf(httpErr, "", "non-json-error-body", getComponentInfo()) + return +} + // Errors is a struct used to hold an array of errors received in an operation // response. type Errors struct { @@ -552,6 +593,7 @@ type Errors struct { // response. type Error struct { Message string `json:"message,omitempty"` + Code string `json:"code,omitempty"` } // decodeAsMap: Decode the specified JSON byte-stream into a map (akin to a generic JSON object). @@ -567,6 +609,9 @@ type Error struct { // 3. This function will close the io.ReadCloser before returning. func decodeAsMap(byteBuffer []byte) (result map[string]interface{}, err error) { err = json.NewDecoder(bytes.NewReader(byteBuffer)).Decode(&result) + if err != nil { + err = SDKErrorf(err, "", "decode-error", getComponentInfo()) + } return } @@ -612,6 +657,39 @@ func getErrorMessage(responseMap map[string]interface{}, statusCode int) string return http.StatusText(statusCode) } +// getErrorCode tries to retrieve an error code from the decoded response body (map). +func getErrorCode(responseMap map[string]interface{}) string { + + // If the response contained the "errors" field, then try to deserialize responseMap + // into an array of Error structs, then return the first entry's "Message" field. + if _, ok := responseMap["errors"]; ok { + var errors Errors + responseBuffer, _ := json.Marshal(responseMap) + if err := json.Unmarshal(responseBuffer, &errors); err == nil { + return errors.Errors[0].Code + } + } + + // Return the "code" field if present and is a string. + if val, ok := responseMap["code"]; ok { + errorCode, ok := val.(string) + if ok { + return errorCode + } + } + + // Return the "errorCode" field if present and is a string. + if val, ok := responseMap["errorCode"]; ok { + errorCode, ok := val.(string) + if ok { + return errorCode + } + } + + // If we couldn't find a code, return an empty string + return "" +} + // isRetryableClient() will return true if and only if "client" is // an http.Client instance that is configured for automatic retries. // A retryable client is a client whose transport is a @@ -766,17 +844,17 @@ func IBMCloudSDKRetryPolicy(ctx context.Context, resp *http.Response, err error) if v, ok := err.(*url.Error); ok { // Don't retry if the error was due to too many redirects. if redirectsErrorRe.MatchString(v.Error()) { - return false, v + return false, SDKErrorf(v, "", "too-many-redirects", getComponentInfo()) } // Don't retry if the error was due to an invalid protocol scheme. if schemeErrorRe.MatchString(v.Error()) { - return false, v + return false, SDKErrorf(v, "", "invalid-scheme", getComponentInfo()) } // Don't retry if the error was due to TLS cert verification failure. if _, ok := v.Err.(x509.UnknownAuthorityError); ok { - return false, v + return false, SDKErrorf(v, "", "cert-failure", getComponentInfo()) } } diff --git a/vendor/github.com/IBM/go-sdk-core/v5/core/basic_authenticator.go b/vendor/github.com/IBM/go-sdk-core/v5/core/basic_authenticator.go index 43b5796871..b0c12eb9bf 100644 --- a/vendor/github.com/IBM/go-sdk-core/v5/core/basic_authenticator.go +++ b/vendor/github.com/IBM/go-sdk-core/v5/core/basic_authenticator.go @@ -37,6 +37,7 @@ func NewBasicAuthenticator(username string, password string) (*BasicAuthenticato Password: password, } if err := obj.Validate(); err != nil { + err = RepurposeSDKProblem(err, "validation-failed") return nil, err } return obj, nil @@ -46,7 +47,8 @@ func NewBasicAuthenticator(username string, password string) (*BasicAuthenticato // from a map. func newBasicAuthenticatorFromMap(properties map[string]string) (*BasicAuthenticator, error) { if properties == nil { - return nil, fmt.Errorf(ERRORMSG_PROPS_MAP_NIL) + err := fmt.Errorf(ERRORMSG_PROPS_MAP_NIL) + return nil, SDKErrorf(err, "", "missing-props", getComponentInfo()) } return NewBasicAuthenticator(properties[PROPNAME_USERNAME], properties[PROPNAME_PASSWORD]) @@ -73,19 +75,23 @@ func (this *BasicAuthenticator) Authenticate(request *http.Request) error { // they do not contain invalid characters. func (this BasicAuthenticator) Validate() error { if this.Username == "" { - return fmt.Errorf(ERRORMSG_PROP_MISSING, "Username") + err := fmt.Errorf(ERRORMSG_PROP_MISSING, "Username") + return SDKErrorf(err, "", "no-user", getComponentInfo()) } if this.Password == "" { - return fmt.Errorf(ERRORMSG_PROP_MISSING, "Password") + err := fmt.Errorf(ERRORMSG_PROP_MISSING, "Password") + return SDKErrorf(err, "", "no-pass", getComponentInfo()) } if HasBadFirstOrLastChar(this.Username) { - return fmt.Errorf(ERRORMSG_PROP_INVALID, "Username") + err := fmt.Errorf(ERRORMSG_PROP_INVALID, "Username") + return SDKErrorf(err, "", "bad-user", getComponentInfo()) } if HasBadFirstOrLastChar(this.Password) { - return fmt.Errorf(ERRORMSG_PROP_INVALID, "Password") + err := fmt.Errorf(ERRORMSG_PROP_INVALID, "Password") + return SDKErrorf(err, "", "bad-pass", getComponentInfo()) } return nil diff --git a/vendor/github.com/IBM/go-sdk-core/v5/core/bearer_token_authenticator.go b/vendor/github.com/IBM/go-sdk-core/v5/core/bearer_token_authenticator.go index cb987a622a..ab26448da1 100644 --- a/vendor/github.com/IBM/go-sdk-core/v5/core/bearer_token_authenticator.go +++ b/vendor/github.com/IBM/go-sdk-core/v5/core/bearer_token_authenticator.go @@ -35,6 +35,7 @@ func NewBearerTokenAuthenticator(bearerToken string) (*BearerTokenAuthenticator, BearerToken: bearerToken, } if err := obj.Validate(); err != nil { + err = RepurposeSDKProblem(err, "validation-failed") return nil, err } return obj, nil @@ -43,7 +44,8 @@ func NewBearerTokenAuthenticator(bearerToken string) (*BearerTokenAuthenticator, // newBearerTokenAuthenticator : Constructs a new BearerTokenAuthenticator instance from a map. func newBearerTokenAuthenticatorFromMap(properties map[string]string) (*BearerTokenAuthenticator, error) { if properties == nil { - return nil, fmt.Errorf(ERRORMSG_PROPS_MAP_NIL) + err := fmt.Errorf(ERRORMSG_PROPS_MAP_NIL) + return nil, SDKErrorf(err, "", "missing-props", getComponentInfo()) } return NewBearerTokenAuthenticator(properties[PROPNAME_BEARER_TOKEN]) @@ -69,7 +71,8 @@ func (this *BearerTokenAuthenticator) Authenticate(request *http.Request) error // Ensures the bearer token is not Nil. func (this BearerTokenAuthenticator) Validate() error { if this.BearerToken == "" { - return fmt.Errorf(ERRORMSG_PROP_MISSING, "BearerToken") + err := fmt.Errorf(ERRORMSG_PROP_MISSING, "BearerToken") + return SDKErrorf(err, "", "no-token", getComponentInfo()) } return nil } diff --git a/vendor/github.com/IBM/go-sdk-core/v5/core/config_utils.go b/vendor/github.com/IBM/go-sdk-core/v5/core/config_utils.go index 8dc059e4cd..24d535dd96 100644 --- a/vendor/github.com/IBM/go-sdk-core/v5/core/config_utils.go +++ b/vendor/github.com/IBM/go-sdk-core/v5/core/config_utils.go @@ -45,7 +45,9 @@ const ( // passed in as "my_service", then configuration properties whose names begin with "MY_SERVICE_" // will be returned in the map. func GetServiceProperties(serviceName string) (serviceProps map[string]string, err error) { - return getServiceProperties(serviceName) + serviceProps, err = getServiceProperties(serviceName) + err = RepurposeSDKProblem(err, "get-props-error") + return } // getServiceProperties: This function will retrieve configuration properties for the specified service @@ -57,6 +59,7 @@ func getServiceProperties(serviceName string) (serviceProps map[string]string, e if serviceName == "" { err = fmt.Errorf("serviceName was not specified") + err = SDKErrorf(err, "", "no-service-name", getComponentInfo()) return } diff --git a/vendor/github.com/IBM/go-sdk-core/v5/core/constants.go b/vendor/github.com/IBM/go-sdk-core/v5/core/constants.go index ca4ba8a133..9be71785ed 100644 --- a/vendor/github.com/IBM/go-sdk-core/v5/core/constants.go +++ b/vendor/github.com/IBM/go-sdk-core/v5/core/constants.go @@ -1,6 +1,6 @@ package core -// (C) Copyright IBM Corp. 2019, 2022. +// (C) Copyright IBM Corp. 2019, 2023. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -23,6 +23,7 @@ const ( AUTHTYPE_CP4D = "cp4d" AUTHTYPE_CONTAINER = "container" AUTHTYPE_VPC = "vpc" + AUTHTYPE_MCSP = "mcsp" // Names of properties that can be defined as part of an external configuration (credential file, env vars, etc.). // Example: export MYSERVICE_URL=https://myurl @@ -82,4 +83,7 @@ const ( ERRORMSG_IAM_GETTOKEN_ERROR = "IAM 'get token' error, status code %d received from '%s': %s" // #nosec G101 ERRORMSG_UNABLE_RETRIEVE_IITOKEN = "unable to retrieve instance identity token value: %s" // #nosec G101 ERRORMSG_VPCMDS_OPERATION_ERROR = "VPC metadata service error, status code %d received from '%s': %s" + + // The name of this module - matches the value in the go.mod file. + MODULE_NAME = "github.com/IBM/go-sdk-core/v5" ) diff --git a/vendor/github.com/IBM/go-sdk-core/v5/core/container_authenticator.go b/vendor/github.com/IBM/go-sdk-core/v5/core/container_authenticator.go index b289881fd2..2d7c3f5617 100644 --- a/vendor/github.com/IBM/go-sdk-core/v5/core/container_authenticator.go +++ b/vendor/github.com/IBM/go-sdk-core/v5/core/container_authenticator.go @@ -1,6 +1,6 @@ package core -// (C) Copyright IBM Corp. 2021, 2023.. +// (C) Copyright IBM Corp. 2021, 2024. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,7 +15,6 @@ package core // limitations under the License. import ( - "bytes" "crypto/tls" "encoding/json" "fmt" @@ -87,6 +86,10 @@ type ContainerAuthenticator struct { Client *http.Client clientInit sync.Once + // The User-Agent header value to be included with each token request. + userAgent string + userAgentInit sync.Once + // The cached IAM access token and its expiration time. tokenData *iamTokenData @@ -174,7 +177,7 @@ func (builder *ContainerAuthenticatorBuilder) Build() (*ContainerAuthenticator, // Make sure the config is valid. err := builder.ContainerAuthenticator.Validate() if err != nil { - return nil, err + return nil, RepurposeSDKProblem(err, "validation-failed") } return &builder.ContainerAuthenticator, nil @@ -200,11 +203,20 @@ func (authenticator *ContainerAuthenticator) client() *http.Client { return authenticator.Client } +// getUserAgent returns the User-Agent header value to be included in each token request invoked by the authenticator. +func (authenticator *ContainerAuthenticator) getUserAgent() string { + authenticator.userAgentInit.Do(func() { + authenticator.userAgent = fmt.Sprintf("%s/%s-%s %s", sdkName, "container-authenticator", __VERSION__, SystemInfo()) + }) + return authenticator.userAgent +} + // newContainerAuthenticatorFromMap constructs a new ContainerAuthenticator instance from a map containing // configuration properties. func newContainerAuthenticatorFromMap(properties map[string]string) (authenticator *ContainerAuthenticator, err error) { if properties == nil { - return nil, fmt.Errorf(ERRORMSG_PROPS_MAP_NIL) + err = fmt.Errorf(ERRORMSG_PROPS_MAP_NIL) + return nil, SDKErrorf(err, "", "missing-props", getComponentInfo()) } // Grab the AUTH_DISABLE_SSL string property and convert to a boolean value. @@ -239,7 +251,7 @@ func (*ContainerAuthenticator) AuthenticationType() string { func (authenticator *ContainerAuthenticator) Authenticate(request *http.Request) error { token, err := authenticator.GetToken() if err != nil { - return err + return RepurposeSDKProblem(err, "get-token-fail") } request.Header.Set("Authorization", "Bearer "+token) @@ -284,7 +296,8 @@ func (authenticator *ContainerAuthenticator) Validate() error { // Check to make sure that one of IAMProfileName or IAMProfileID are specified. if authenticator.IAMProfileName == "" && authenticator.IAMProfileID == "" { - return fmt.Errorf(ERRORMSG_ATLEAST_ONE_PROP_ERROR, "IAMProfileName", "IAMProfileID") + err := fmt.Errorf(ERRORMSG_ATLEAST_ONE_PROP_ERROR, "IAMProfileName", "IAMProfileID") + return SDKErrorf(err, "", "both-props", getComponentInfo()) } // Validate ClientId and ClientSecret. They must both be specified togther or neither should be specified. @@ -293,11 +306,13 @@ func (authenticator *ContainerAuthenticator) Validate() error { } else { // Since it is NOT the case that both properties are empty, make sure BOTH are specified. if authenticator.ClientID == "" { - return fmt.Errorf(ERRORMSG_PROP_MISSING, "ClientID") + err := fmt.Errorf(ERRORMSG_PROP_MISSING, "ClientID") + return SDKErrorf(err, "", "missing-id", getComponentInfo()) } if authenticator.ClientSecret == "" { - return fmt.Errorf(ERRORMSG_PROP_MISSING, "ClientSecret") + err := fmt.Errorf(ERRORMSG_PROP_MISSING, "ClientSecret") + return SDKErrorf(err, "", "missing-secret", getComponentInfo()) } } @@ -313,7 +328,7 @@ func (authenticator *ContainerAuthenticator) GetToken() (string, error) { // synchronously request the token err := authenticator.synchronizedRequestToken() if err != nil { - return "", err + return "", RepurposeSDKProblem(err, "request-token-fail") } } else if authenticator.getTokenData().needsRefresh() { GetLogger().Debug("Performing background asynchronous token fetch...") @@ -326,7 +341,8 @@ func (authenticator *ContainerAuthenticator) GetToken() (string, error) { // return an error if the access token is not valid or was not fetched if authenticator.getTokenData() == nil || authenticator.getTokenData().AccessToken == "" { - return "", fmt.Errorf("Error while trying to get access token") + err := fmt.Errorf("Error while trying to get access token") + return "", SDKErrorf(err, "", "no-token", getComponentInfo()) } return authenticator.getTokenData().AccessToken, nil @@ -376,18 +392,19 @@ func (authenticator *ContainerAuthenticator) RequestToken() (*IamTokenServerResp if err == nil { err = fmt.Errorf(ERRORMSG_UNABLE_RETRIEVE_CRTOKEN, "reason unknown") } - return nil, NewAuthenticationError(&DetailedResponse{}, err) + return nil, authenticationErrorf(err, &DetailedResponse{}, "noop", getComponentInfo()) } // Set up the request for the IAM "get token" invocation. builder := NewRequestBuilder(POST) _, err = builder.ResolveRequestURL(authenticator.url(), iamAuthOperationPathGetToken, nil) if err != nil { - return nil, NewAuthenticationError(&DetailedResponse{}, err) + return nil, authenticationErrorf(err, &DetailedResponse{}, "noop", getComponentInfo()) } builder.AddHeader(CONTENT_TYPE, FORM_URL_ENCODED_HEADER) builder.AddHeader(Accept, APPLICATION_JSON) + builder.AddHeader(headerNameUserAgent, authenticator.getUserAgent()) builder.AddFormData("grant_type", "", "", iamGrantTypeCRToken) // #nosec G101 builder.AddFormData("cr_token", "", "", crToken) @@ -413,7 +430,7 @@ func (authenticator *ContainerAuthenticator) RequestToken() (*IamTokenServerResp req, err := builder.Build() if err != nil { - return nil, NewAuthenticationError(&DetailedResponse{}, err) + return nil, authenticationErrorf(err, &DetailedResponse{}, "noop", getComponentInfo()) } // If client id and secret were configured by the user, then set them on the request @@ -435,7 +452,7 @@ func (authenticator *ContainerAuthenticator) RequestToken() (*IamTokenServerResp GetLogger().Debug("Invoking IAM 'get token' operation: %s", builder.URL) resp, err := authenticator.client().Do(req) if err != nil { - return nil, NewAuthenticationError(&DetailedResponse{}, err) + return nil, authenticationErrorf(err, &DetailedResponse{}, "noop", getComponentInfo()) } GetLogger().Debug("Returned from IAM 'get token' operation, received status code %d", resp.StatusCode) @@ -451,23 +468,24 @@ func (authenticator *ContainerAuthenticator) RequestToken() (*IamTokenServerResp // Check for a bad status code and handle an operation error. if resp.StatusCode < 200 || resp.StatusCode >= 300 { - buff := new(bytes.Buffer) - _, _ = buff.ReadFrom(resp.Body) - resp.Body.Close() // #nosec G104 - - // Create a DetailedResponse to be included in the error below. - detailedResponse := &DetailedResponse{ - StatusCode: resp.StatusCode, - Headers: resp.Header, - RawResult: buff.Bytes(), + detailedResponse, err := processErrorResponse(resp) + authError := authenticationErrorf(err, detailedResponse, "get_token", authenticator.getComponentInfo()) + + // The err Summary is typically the message computed for the HTTPError instance in + // processErrorResponse(). If the response body is non-JSON, the message will be generic + // text based on the status code but authenticators have always used the stringified + // RawResult, so update that here for compatilibility. + iamErrorMsg := err.Summary + if detailedResponse.RawResult != nil { + // RawResult is only populated if the response body is + // non-JSON and we couldn't extract a message. + iamErrorMsg = string(detailedResponse.RawResult) } - iamErrorMsg := string(detailedResponse.RawResult) - if iamErrorMsg == "" { - iamErrorMsg = "IAM error response not available" - } - err = fmt.Errorf(ERRORMSG_IAM_GETTOKEN_ERROR, detailedResponse.StatusCode, builder.URL, iamErrorMsg) - return nil, NewAuthenticationError(detailedResponse, err) + authError.Summary = + fmt.Sprintf(ERRORMSG_IAM_GETTOKEN_ERROR, detailedResponse.StatusCode, builder.URL, iamErrorMsg) + + return nil, authError } // Good response, so unmarshal the response body into an IamTokenServerResponse instance. @@ -494,7 +512,9 @@ func (authenticator *ContainerAuthenticator) retrieveCRToken() (crToken string, if err != nil { err = fmt.Errorf(ERRORMSG_UNABLE_RETRIEVE_CRTOKEN, err.Error()) - GetLogger().Debug(err.Error()) + sdkErr := SDKErrorf(err, "", "no-cr-token", getComponentInfo()) + GetLogger().Debug(sdkErr.GetDebugMessage()) + err = sdkErr return } @@ -509,7 +529,8 @@ func (authenticator *ContainerAuthenticator) readFile(filename string) (crToken var bytes []byte bytes, err = os.ReadFile(filename) // #nosec G304 if err != nil { - GetLogger().Debug(err.Error()) + err = SDKErrorf(err, "", "read-file-error", getComponentInfo()) + GetLogger().Debug(err.(*SDKProblem).GetDebugMessage()) return } @@ -519,3 +540,10 @@ func (authenticator *ContainerAuthenticator) readFile(filename string) (crToken return } + +// This should only be used for AuthenticationError instances that actually deal with +// an HTTP error (i.e. do not have a blank DetailedResponse object - they can be scoped +// to the SDK core system). +func (authenticator *ContainerAuthenticator) getComponentInfo() *ProblemComponent { + return NewProblemComponent("iam_identity_services", "") +} diff --git a/vendor/github.com/IBM/go-sdk-core/v5/core/cp4d_authenticator.go b/vendor/github.com/IBM/go-sdk-core/v5/core/cp4d_authenticator.go index 8cc7c545e9..8f9a8117e7 100644 --- a/vendor/github.com/IBM/go-sdk-core/v5/core/cp4d_authenticator.go +++ b/vendor/github.com/IBM/go-sdk-core/v5/core/cp4d_authenticator.go @@ -1,6 +1,6 @@ package core -// (C) Copyright IBM Corp. 2019, 2021. +// (C) Copyright IBM Corp. 2019, 2024. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,7 +15,6 @@ package core // limitations under the License. import ( - "bytes" "crypto/tls" "encoding/json" "fmt" @@ -58,6 +57,10 @@ type CloudPakForDataAuthenticator struct { Client *http.Client clientInit sync.Once + // The User-Agent header value to be included with each token request. + userAgent string + userAgentInit sync.Once + // The cached token and expiration time. tokenData *cp4dTokenData @@ -74,21 +77,24 @@ var cp4dNeedsRefreshMutex sync.Mutex // the NewCloudPakForDataAuthenticatorUsingPassword() function func NewCloudPakForDataAuthenticator(url string, username string, password string, disableSSLVerification bool, headers map[string]string) (*CloudPakForDataAuthenticator, error) { - return NewCloudPakForDataAuthenticatorUsingPassword(url, username, password, disableSSLVerification, headers) + auth, err := NewCloudPakForDataAuthenticatorUsingPassword(url, username, password, disableSSLVerification, headers) + return auth, RepurposeSDKProblem(err, "new-auth-fail") } // NewCloudPakForDataAuthenticatorUsingPassword constructs a new CloudPakForDataAuthenticator // instance from a username/password pair. func NewCloudPakForDataAuthenticatorUsingPassword(url string, username string, password string, disableSSLVerification bool, headers map[string]string) (*CloudPakForDataAuthenticator, error) { - return newAuthenticator(url, username, password, "", disableSSLVerification, headers) + auth, err := newAuthenticator(url, username, password, "", disableSSLVerification, headers) + return auth, RepurposeSDKProblem(err, "new-auth-password-fail") } // NewCloudPakForDataAuthenticatorUsingAPIKey constructs a new CloudPakForDataAuthenticator // instance from a username/apikey pair. func NewCloudPakForDataAuthenticatorUsingAPIKey(url string, username string, apikey string, disableSSLVerification bool, headers map[string]string) (*CloudPakForDataAuthenticator, error) { - return newAuthenticator(url, username, "", apikey, disableSSLVerification, headers) + auth, err := newAuthenticator(url, username, "", apikey, disableSSLVerification, headers) + return auth, RepurposeSDKProblem(err, "new-auth-apikey-fail") } func newAuthenticator(url string, username string, password string, apikey string, @@ -115,7 +121,8 @@ func newAuthenticator(url string, username string, password string, apikey strin // newCloudPakForDataAuthenticatorFromMap : Constructs a new CloudPakForDataAuthenticator instance from a map. func newCloudPakForDataAuthenticatorFromMap(properties map[string]string) (*CloudPakForDataAuthenticator, error) { if properties == nil { - return nil, fmt.Errorf(ERRORMSG_PROPS_MAP_NIL) + err := fmt.Errorf(ERRORMSG_PROPS_MAP_NIL) + return nil, SDKErrorf(err, "", "missing-props", getComponentInfo()) } disableSSL, err := strconv.ParseBool(properties[PROPNAME_AUTH_DISABLE_SSL]) @@ -140,17 +147,20 @@ func (*CloudPakForDataAuthenticator) AuthenticationType() string { func (authenticator *CloudPakForDataAuthenticator) Validate() error { if authenticator.Username == "" { - return fmt.Errorf(ERRORMSG_PROP_MISSING, "Username") + err := fmt.Errorf(ERRORMSG_PROP_MISSING, "Username") + return SDKErrorf(err, "", "no-user", getComponentInfo()) } // The user should specify exactly one of APIKey or Password. if (authenticator.APIKey == "" && authenticator.Password == "") || (authenticator.APIKey != "" && authenticator.Password != "") { - return fmt.Errorf(ERRORMSG_EXCLUSIVE_PROPS_ERROR, "APIKey", "Password") + err := fmt.Errorf(ERRORMSG_EXCLUSIVE_PROPS_ERROR, "APIKey", "Password") + return SDKErrorf(err, "", "exc-props", getComponentInfo()) } if authenticator.URL == "" { - return fmt.Errorf(ERRORMSG_PROP_MISSING, "URL") + err := fmt.Errorf(ERRORMSG_PROP_MISSING, "URL") + return SDKErrorf(err, "", "no-url", getComponentInfo()) } return nil @@ -176,6 +186,14 @@ func (authenticator *CloudPakForDataAuthenticator) client() *http.Client { return authenticator.Client } +// getUserAgent returns the User-Agent header value to be included in each token request invoked by the authenticator. +func (authenticator *CloudPakForDataAuthenticator) getUserAgent() string { + authenticator.userAgentInit.Do(func() { + authenticator.userAgent = fmt.Sprintf("%s/%s-%s %s", sdkName, "cp4d-authenticator", __VERSION__, SystemInfo()) + }) + return authenticator.userAgent +} + // Authenticate adds the bearer token (obtained from the token server) to the // specified request. // @@ -185,7 +203,7 @@ func (authenticator *CloudPakForDataAuthenticator) client() *http.Client { func (authenticator *CloudPakForDataAuthenticator) Authenticate(request *http.Request) error { token, err := authenticator.GetToken() if err != nil { - return err + return RepurposeSDKProblem(err, "get-token-fail") } request.Header.Set("Authorization", fmt.Sprintf(`Bearer %s`, token)) @@ -216,7 +234,7 @@ func (authenticator *CloudPakForDataAuthenticator) GetToken() (string, error) { // synchronously request the token err := authenticator.synchronizedRequestToken() if err != nil { - return "", err + return "", RepurposeSDKProblem(err, "request-token-fail") } } else if authenticator.getTokenData().needsRefresh() { // If refresh needed, kick off a go routine in the background to get a new token @@ -226,7 +244,8 @@ func (authenticator *CloudPakForDataAuthenticator) GetToken() (string, error) { // return an error if the access token is not valid or was not fetched if authenticator.getTokenData() == nil || authenticator.getTokenData().AccessToken == "" { - return "", fmt.Errorf("Error while trying to get access token") + err := fmt.Errorf("Error while trying to get access token") + return "", SDKErrorf(err, "", "no-token", getComponentInfo()) } return authenticator.getTokenData().AccessToken, nil @@ -297,8 +316,9 @@ func (authenticator *CloudPakForDataAuthenticator) requestToken() (tokenResponse builder.AddHeader(headerName, headerValue) } - // Add the Content-Type header. + // Add the Content-Type and User-Agent headers. builder.AddHeader("Content-Type", "application/json") + builder.AddHeader(headerNameUserAgent, authenticator.getUserAgent()) // Add the request body to request. _, err = builder.SetBodyContentJSON(body) @@ -325,6 +345,7 @@ func (authenticator *CloudPakForDataAuthenticator) requestToken() (tokenResponse GetLogger().Debug("Invoking CP4D token service operation: %s", builder.URL) resp, err := authenticator.client().Do(req) if err != nil { + err = SDKErrorf(err, "", "cp4d-request-error", getComponentInfo()) return } GetLogger().Debug("Returned from CP4D token service operation, received status code %d", resp.StatusCode) @@ -340,17 +361,22 @@ func (authenticator *CloudPakForDataAuthenticator) requestToken() (tokenResponse } if resp.StatusCode < 200 || resp.StatusCode >= 300 { - buff := new(bytes.Buffer) - _, _ = buff.ReadFrom(resp.Body) - - // Create a DetailedResponse to be included in the error below. - detailedResponse := &DetailedResponse{ - StatusCode: resp.StatusCode, - Headers: resp.Header, - RawResult: buff.Bytes(), + detailedResponse, responseError := processErrorResponse(resp) + err = authenticationErrorf(responseError, detailedResponse, "authorize", authenticator.getComponentInfo()) + + // The err Summary is typically the message computed for the HTTPError instance in + // processErrorResponse(). If the response body is non-JSON, the message will be generic + // text based on the status code but authenticators have always used the stringified + // RawResult, so update that here for compatilibility. + errorMsg := responseError.Summary + if detailedResponse.RawResult != nil { + // RawResult is only populated if the response body is + // non-JSON and we couldn't extract a message. + errorMsg = string(detailedResponse.RawResult) } - err = NewAuthenticationError(detailedResponse, fmt.Errorf(buff.String())) + err.(*AuthenticationError).Summary = errorMsg + return } @@ -359,6 +385,7 @@ func (authenticator *CloudPakForDataAuthenticator) requestToken() (tokenResponse defer resp.Body.Close() // #nosec G307 if err != nil { err = fmt.Errorf(ERRORMSG_UNMARSHAL_AUTH_RESPONSE, err.Error()) + err = SDKErrorf(err, "", "cp4d-res-unmarshal-error", getComponentInfo()) tokenResponse = nil return } @@ -366,6 +393,10 @@ func (authenticator *CloudPakForDataAuthenticator) requestToken() (tokenResponse return } +func (authenticator *CloudPakForDataAuthenticator) getComponentInfo() *ProblemComponent { + return NewProblemComponent("cp4d_token_service", "v1") +} + // cp4dTokenServerResponse is a struct that models a response received from the token server. type cp4dTokenServerResponse struct { Token string `json:"token,omitempty"` diff --git a/vendor/github.com/IBM/go-sdk-core/v5/core/datetime.go b/vendor/github.com/IBM/go-sdk-core/v5/core/datetime.go index 0a8bcf839d..cc1352f911 100644 --- a/vendor/github.com/IBM/go-sdk-core/v5/core/datetime.go +++ b/vendor/github.com/IBM/go-sdk-core/v5/core/datetime.go @@ -82,6 +82,8 @@ func ParseDate(dateString string) (fmtDate strfmt.Date, err error) { formattedTime, err := time.Parse(strfmt.RFC3339FullDate, dateString) if err == nil { fmtDate = strfmt.Date(formattedTime) + } else { + err = SDKErrorf(err, "", "date-parse-error", getComponentInfo()) } return } @@ -89,5 +91,9 @@ func ParseDate(dateString string) (fmtDate strfmt.Date, err error) { // ParseDateTime parses the specified date-time string and returns a strfmt.DateTime instance. // If the string is empty the return value will be the unix epoch (1970-01-01T00:00:00.000Z). func ParseDateTime(dateString string) (strfmt.DateTime, error) { - return strfmt.ParseDateTime(dateString) + dt, err := strfmt.ParseDateTime(dateString) + if err != nil { + err = SDKErrorf(err, "", "datetime-parse-error", getComponentInfo()) + } + return dt, err } diff --git a/vendor/github.com/IBM/go-sdk-core/v5/core/detailed_response.go b/vendor/github.com/IBM/go-sdk-core/v5/core/detailed_response.go index 4100204945..5163af70bb 100644 --- a/vendor/github.com/IBM/go-sdk-core/v5/core/detailed_response.go +++ b/vendor/github.com/IBM/go-sdk-core/v5/core/detailed_response.go @@ -1,6 +1,6 @@ package core -// (C) Copyright IBM Corp. 2019. +// (C) Copyright IBM Corp. 2019, 2024. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -24,10 +24,10 @@ import ( type DetailedResponse struct { // The HTTP status code associated with the response. - StatusCode int + StatusCode int `yaml:"status_code"` // The HTTP headers contained in the response. - Headers http.Header + Headers http.Header `yaml:"headers"` // Result - this field will contain the result of the operation (obtained from the response body). // @@ -50,13 +50,13 @@ type DetailedResponse struct { // response body as a "generic" JSON object. // If the JSON response for an unsuccessful operation could not be properly un-marshalled, then the // RawResult field will contain the raw response body. - Result interface{} + Result interface{} `yaml:"result,omitempty"` // This field will contain the raw response body as a byte array under these conditions: // 1) there was a problem un-marshalling a JSON response body - // either for a successful or unsuccessful operation. // 2) the operation was unsuccessful, and the response body contains a non-JSON response. - RawResult []byte + RawResult []byte `yaml:"raw_result,omitempty"` } // GetHeaders returns the headers diff --git a/vendor/github.com/IBM/go-sdk-core/v5/core/file_with_metadata.go b/vendor/github.com/IBM/go-sdk-core/v5/core/file_with_metadata.go index 578c59bec9..5118a2e7f1 100644 --- a/vendor/github.com/IBM/go-sdk-core/v5/core/file_with_metadata.go +++ b/vendor/github.com/IBM/go-sdk-core/v5/core/file_with_metadata.go @@ -38,7 +38,7 @@ func NewFileWithMetadata(data io.ReadCloser) (model *FileWithMetadata, err error model = &FileWithMetadata{ Data: data, } - err = ValidateStruct(model, "required parameters") + err = RepurposeSDKProblem(ValidateStruct(model, "required parameters"), "validation-failed") return } @@ -52,22 +52,23 @@ func UnmarshalFileWithMetadata(m map[string]json.RawMessage, result interface{}) // then explicitly set the Data field to the contents of the file var data io.ReadCloser var pathToData string - err = UnmarshalPrimitive(m, "data", &pathToData) + err = RepurposeSDKProblem(UnmarshalPrimitive(m, "data", &pathToData), "unmarshal-fail") if err != nil { return } data, err = os.Open(pathToData) // #nosec G304 if err != nil { + err = SDKErrorf(err, "", "file-open-error", getComponentInfo()) return } obj.Data = data // unmarshal the other fields as usual - err = UnmarshalPrimitive(m, "filename", &obj.Filename) + err = RepurposeSDKProblem(UnmarshalPrimitive(m, "filename", &obj.Filename), "unmarshal-file-fail") if err != nil { return } - err = UnmarshalPrimitive(m, "content_type", &obj.ContentType) + err = RepurposeSDKProblem(UnmarshalPrimitive(m, "content_type", &obj.ContentType), "unmarshal-content-type-fail") if err != nil { return } diff --git a/vendor/github.com/IBM/go-sdk-core/v5/core/gzip.go b/vendor/github.com/IBM/go-sdk-core/v5/core/gzip.go index 347847b1b6..cb831cf7f8 100644 --- a/vendor/github.com/IBM/go-sdk-core/v5/core/gzip.go +++ b/vendor/github.com/IBM/go-sdk-core/v5/core/gzip.go @@ -42,7 +42,8 @@ func NewGzipCompressionReader(uncompressedReader io.Reader) (io.Reader, error) { // to the pipe only when the pipe reader is called to retrieve more bytes. _, err := io.Copy(compressedWriter, uncompressedReader) if err != nil { - _ = pipeWriter.CloseWithError(err) + sdkErr := SDKErrorf(err, "", "compression-failed", getComponentInfo()) + _ = pipeWriter.CloseWithError(sdkErr) } }() return pipeReader, nil @@ -51,5 +52,9 @@ func NewGzipCompressionReader(uncompressedReader io.Reader) (io.Reader, error) { // NewGzipDecompressionReader will return an io.Reader instance that will deliver // the gzip-decompressed version of the "compressedReader" argument. func NewGzipDecompressionReader(compressedReader io.Reader) (io.Reader, error) { - return gzip.NewReader(compressedReader) + res, err := gzip.NewReader(compressedReader) + if err != nil { + err = SDKErrorf(err, "", "decompress-read-error", getComponentInfo()) + } + return res, err } diff --git a/vendor/github.com/IBM/go-sdk-core/v5/core/http_problem.go b/vendor/github.com/IBM/go-sdk-core/v5/core/http_problem.go new file mode 100644 index 0000000000..c6e2ac7001 --- /dev/null +++ b/vendor/github.com/IBM/go-sdk-core/v5/core/http_problem.go @@ -0,0 +1,181 @@ +package core + +// (C) Copyright IBM Corp. 2024. +// +// 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. + +import ( + "errors" + "fmt" +) + +// HTTPProblem provides a type suited to problems that +// occur as the result of an HTTP request. It extends +// the base "IBMProblem" type with fields to store +// information about the HTTP request/response. +type HTTPProblem struct { + *IBMProblem + + // OperationID identifies the operation of an API + // that the failed request was made to. + OperationID string + + // Response contains the full HTTP error response + // returned as a result of the failed request, + // including the body and all headers. + Response *DetailedResponse +} + +// GetConsoleMessage returns all public fields of +// the problem, formatted in YAML. +func (e *HTTPProblem) GetConsoleMessage() string { + return ComputeConsoleMessage(e) +} + +// GetDebugMessage returns all information about +// the problem, formatted in YAML. +func (e *HTTPProblem) GetDebugMessage() string { + return ComputeDebugMessage(e) +} + +// GetID returns the computed identifier, computed from the +// "Component", "discriminator", and "OperationID" fields, +// as well as the status code of the stored response and the +// identifier of the "causedBy" problem, if it exists. +func (e *HTTPProblem) GetID() string { + // TODO: add the error code to the hash once we have the ability to enumerate error codes in an API. + return CreateIDHash("http", e.GetBaseSignature(), e.OperationID, fmt.Sprint(e.Response.GetStatusCode())) +} + +// Is allows an HTTPProblem instance to be compared against another error for equality. +// An HTTPProblem is considered equal to another error if 1) the error is also a Problem and +// 2) it has the same ID (i.e. it is the same problem scenario). +func (e *HTTPProblem) Is(target error) bool { + return is(target, e.GetID()) +} + +func (e *HTTPProblem) getErrorCode() string { + // If the error response was a standard JSON body, the result will + // be a map and we can do a decent job of guessing the code. + if e.Response.Result != nil { + if resultMap, ok := e.Response.Result.(map[string]interface{}); ok { + return getErrorCode(resultMap) + } + } + + return "" +} + +func (e *HTTPProblem) getHeader(key string) (string, bool) { + value := e.Response.Headers.Get(key) + return value, value != "" +} + +// GetConsoleOrderedMaps returns an ordered-map representation +// of an HTTPProblem instance suited for a console message. +func (e *HTTPProblem) GetConsoleOrderedMaps() *OrderedMaps { + orderedMaps := NewOrderedMaps() + + orderedMaps.Add("id", e.GetID()) + orderedMaps.Add("summary", e.Summary) + orderedMaps.Add("severity", e.Severity) + orderedMaps.Add("operation_id", e.OperationID) + orderedMaps.Add("status_code", e.Response.GetStatusCode()) + errorCode := e.getErrorCode() + if errorCode != "" { + orderedMaps.Add("error_code", errorCode) + } + orderedMaps.Add("component", e.Component) + + // Conditionally add the request ID and correlation ID header values. + + if header, ok := e.getHeader("x-request-id"); ok { + orderedMaps.Add("request_id", header) + } + + if header, ok := e.getHeader("x-correlation-id"); ok { + orderedMaps.Add("correlation_id", header) + } + + return orderedMaps +} + +// GetDebugOrderedMaps returns an ordered-map representation +// of an HTTPProblem instance, with additional information +// suited for a debug message. +func (e *HTTPProblem) GetDebugOrderedMaps() *OrderedMaps { + orderedMaps := e.GetConsoleOrderedMaps() + + // The RawResult is never helpful in the printed message. Create a hard copy + // (de-referenced pointer) to remove the raw result from so we don't alter + // the response stored in the problem object. + printableResponse := *e.Response + if printableResponse.Result == nil { + printableResponse.Result = string(printableResponse.RawResult) + } + printableResponse.RawResult = nil + orderedMaps.Add("response", printableResponse) + + var orderableCausedBy OrderableProblem + if errors.As(e.GetCausedBy(), &orderableCausedBy) { + orderedMaps.Add("caused_by", orderableCausedBy.GetDebugOrderedMaps().GetMaps()) + } + + return orderedMaps +} + +// httpErrorf creates and returns a new instance of "HTTPProblem" with "error" level severity. +func httpErrorf(summary string, response *DetailedResponse) *HTTPProblem { + httpProb := &HTTPProblem{ + IBMProblem: IBMErrorf(nil, NewProblemComponent("", ""), summary, ""), + Response: response, + } + + return httpProb +} + +// EnrichHTTPProblem takes an problem and, if it originated as an HTTPProblem, populates +// the fields of the underlying HTTP problem with the given service/operation information. +func EnrichHTTPProblem(err error, operationID string, component *ProblemComponent) { + // If the problem originated from an HTTP error response, populate the + // HTTPProblem instance with details from the SDK that weren't available + // in the core at problem creation time. + var httpProb *HTTPProblem + + // In the case of an SDKProblem instance originating in the core, + // it will not track an HTTPProblem instance in its "caused by" + // chain, but we still want to be able to enrich it. It will be + // stored in the private "httpProblem" field. + var sdkProb *SDKProblem + + if errors.As(err, &httpProb) { + enrichHTTPProblem(httpProb, operationID, component) + } else if errors.As(err, &sdkProb) && sdkProb.httpProblem != nil { + enrichHTTPProblem(sdkProb.httpProblem, operationID, component) + } +} + +// enrichHTTPProblem takes an HTTPProblem instance alongside information about the request +// and adds the extra info to the instance. It also loosely deserializes the response +// in order to set additional information, like the error code. +func enrichHTTPProblem(httpProb *HTTPProblem, operationID string, component *ProblemComponent) { + // If this problem is already populated with service-level information, + // we should not enrich it any further. Most likely, this is an authentication + // error passed from the core to the SDK. + if httpProb.Component.Name != "" { + return + } + + httpProb.Component = component + httpProb.OperationID = operationID +} diff --git a/vendor/github.com/IBM/go-sdk-core/v5/core/iam_authenticator.go b/vendor/github.com/IBM/go-sdk-core/v5/core/iam_authenticator.go index ef51920468..da9feb6014 100644 --- a/vendor/github.com/IBM/go-sdk-core/v5/core/iam_authenticator.go +++ b/vendor/github.com/IBM/go-sdk-core/v5/core/iam_authenticator.go @@ -1,6 +1,6 @@ package core -// (C) Copyright IBM Corp. 2019, 2021. +// (C) Copyright IBM Corp. 2019, 2024. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,7 +15,6 @@ package core // limitations under the License. import ( - "bytes" "crypto/tls" "encoding/json" "fmt" @@ -77,6 +76,10 @@ type IamAuthenticator struct { Client *http.Client clientInit sync.Once + // The User-Agent header value to be included with each token request. + userAgent string + userAgentInit sync.Once + // The cached token and expiration time. tokenData *iamTokenData @@ -93,6 +96,10 @@ const ( iamAuthOperationPathGetToken = "/identity/token" iamAuthGrantTypeApiKey = "urn:ibm:params:oauth:grant-type:apikey" // #nosec G101 iamAuthGrantTypeRefreshToken = "refresh_token" // #nosec G101 + + // The number of seconds before the IAM server-assigned (official) expiration time + // when we'll treat an otherwise valid access token as "expired". + iamExpirationWindow = 10 ) // IamAuthenticatorBuilder is used to construct an IamAuthenticator instance. @@ -161,7 +168,7 @@ func (builder *IamAuthenticatorBuilder) Build() (*IamAuthenticator, error) { // Make sure the config is valid. err := builder.IamAuthenticator.Validate() if err != nil { - return nil, err + return nil, RepurposeSDKProblem(err, "validation-failed") } return &builder.IamAuthenticator, nil @@ -187,6 +194,14 @@ func (authenticator *IamAuthenticator) client() *http.Client { return authenticator.Client } +// getUserAgent returns the User-Agent header value to be included in each token request invoked by the authenticator. +func (authenticator *IamAuthenticator) getUserAgent() string { + authenticator.userAgentInit.Do(func() { + authenticator.userAgent = fmt.Sprintf("%s/%s-%s %s", sdkName, "iam-authenticator", __VERSION__, SystemInfo()) + }) + return authenticator.userAgent +} + // NewIamAuthenticator constructs a new IamAuthenticator instance. // Deprecated - use the IamAuthenticatorBuilder instead. func NewIamAuthenticator(apiKey string, url string, clientId string, clientSecret string, @@ -200,13 +215,14 @@ func NewIamAuthenticator(apiKey string, url string, clientId string, clientSecre SetHeaders(headers). Build() - return authenticator, err + return authenticator, RepurposeSDKProblem(err, "auth-builder-fail") } // newIamAuthenticatorFromMap constructs a new IamAuthenticator instance from a map. func newIamAuthenticatorFromMap(properties map[string]string) (authenticator *IamAuthenticator, err error) { if properties == nil { - return nil, fmt.Errorf(ERRORMSG_PROPS_MAP_NIL) + err := fmt.Errorf(ERRORMSG_PROPS_MAP_NIL) + return nil, SDKErrorf(err, "", "missing-props", getComponentInfo()) } disableSSL, err := strconv.ParseBool(properties[PROPNAME_AUTH_DISABLE_SSL]) @@ -239,7 +255,7 @@ func (*IamAuthenticator) AuthenticationType() string { func (authenticator *IamAuthenticator) Authenticate(request *http.Request) error { token, err := authenticator.GetToken() if err != nil { - return err + return RepurposeSDKProblem(err, "get-token-fail") } request.Header.Set("Authorization", "Bearer "+token) @@ -292,7 +308,7 @@ func (authenticator *IamAuthenticator) setTokenData(tokenData *iamTokenData) { // // Ensures that the ApiKey and RefreshToken properties are mutually exclusive, // and that the ClientId and ClientSecret properties are mutually inclusive. -func (this *IamAuthenticator) Validate() error { +func (authenticator *IamAuthenticator) Validate() error { // The user should specify at least one of ApiKey or RefreshToken. // Note: We'll allow both ApiKey and RefreshToken to be specified, @@ -311,26 +327,30 @@ func (this *IamAuthenticator) Validate() error { // instance of the authenticator doesn't become invalidated simply through // normal use. // - if this.ApiKey == "" && this.RefreshToken == "" { - return fmt.Errorf(ERRORMSG_EXCLUSIVE_PROPS_ERROR, "ApiKey", "RefreshToken") + if authenticator.ApiKey == "" && authenticator.RefreshToken == "" { + err := fmt.Errorf(ERRORMSG_EXCLUSIVE_PROPS_ERROR, "ApiKey", "RefreshToken") + return SDKErrorf(err, "", "exc-props", getComponentInfo()) } - if this.ApiKey != "" && HasBadFirstOrLastChar(this.ApiKey) { - return fmt.Errorf(ERRORMSG_PROP_INVALID, "ApiKey") + if authenticator.ApiKey != "" && HasBadFirstOrLastChar(authenticator.ApiKey) { + err := fmt.Errorf(ERRORMSG_PROP_INVALID, "ApiKey") + return SDKErrorf(err, "", "bad-prop", getComponentInfo()) } // Validate ClientId and ClientSecret. // Either both or neither should be specified. - if this.ClientId == "" && this.ClientSecret == "" { + if authenticator.ClientId == "" && authenticator.ClientSecret == "" { // Do nothing as this is the valid scenario. } else { // Since it is NOT the case that both properties are empty, make sure BOTH are specified. - if this.ClientId == "" { - return fmt.Errorf(ERRORMSG_PROP_MISSING, "ClientId") + if authenticator.ClientId == "" { + err := fmt.Errorf(ERRORMSG_PROP_MISSING, "ClientId") + return SDKErrorf(err, "", "missing-id", getComponentInfo()) } - if this.ClientSecret == "" { - return fmt.Errorf(ERRORMSG_PROP_MISSING, "ClientSecret") + if authenticator.ClientSecret == "" { + err := fmt.Errorf(ERRORMSG_PROP_MISSING, "ClientSecret") + return SDKErrorf(err, "", "missing-secret", getComponentInfo()) } } @@ -345,7 +365,7 @@ func (authenticator *IamAuthenticator) GetToken() (string, error) { // synchronously request the token err := authenticator.synchronizedRequestToken() if err != nil { - return "", err + return "", RepurposeSDKProblem(err, "request-token-fail") } } else if authenticator.getTokenData().needsRefresh() { // If refresh needed, kick off a go routine in the background to get a new token @@ -355,7 +375,8 @@ func (authenticator *IamAuthenticator) GetToken() (string, error) { // return an error if the access token is not valid or was not fetched if authenticator.getTokenData() == nil || authenticator.getTokenData().AccessToken == "" { - return "", fmt.Errorf("Error while trying to get access token") + err := fmt.Errorf("Error while trying to get access token") + return "", SDKErrorf(err, "", "no-token", getComponentInfo()) } return authenticator.getTokenData().AccessToken, nil @@ -399,11 +420,12 @@ func (authenticator *IamAuthenticator) RequestToken() (*IamTokenServerResponse, builder := NewRequestBuilder(POST) _, err := builder.ResolveRequestURL(authenticator.url(), iamAuthOperationPathGetToken, nil) if err != nil { - return nil, err + return nil, RepurposeSDKProblem(err, "url-resolve-error") } builder.AddHeader(CONTENT_TYPE, "application/x-www-form-urlencoded") builder.AddHeader(Accept, APPLICATION_JSON) + builder.AddHeader(headerNameUserAgent, authenticator.getUserAgent()) builder.AddFormData("response_type", "", "", "cloud_iam") if authenticator.ApiKey != "" { @@ -416,7 +438,8 @@ func (authenticator *IamAuthenticator) RequestToken() (*IamTokenServerResponse, builder.AddFormData("refresh_token", "", "", authenticator.RefreshToken) } else { // We shouldn't ever get here due to prior validations, but just in case, let's log an error. - return nil, fmt.Errorf(ERRORMSG_EXCLUSIVE_PROPS_ERROR, "ApiKey", "RefreshToken") + err := fmt.Errorf(ERRORMSG_EXCLUSIVE_PROPS_ERROR, "ApiKey", "RefreshToken") + return nil, SDKErrorf(err, "", "iam-exc-props", getComponentInfo()) } // Add any optional parameters to the request. @@ -431,7 +454,7 @@ func (authenticator *IamAuthenticator) RequestToken() (*IamTokenServerResponse, req, err := builder.Build() if err != nil { - return nil, err + return nil, RepurposeSDKProblem(err, "request-build-error") } // If client id and secret were configured by the user, then set them on the request @@ -455,6 +478,7 @@ func (authenticator *IamAuthenticator) RequestToken() (*IamTokenServerResponse, GetLogger().Debug("Invoking IAM 'get token' operation: %s", builder.URL) resp, err := authenticator.client().Do(req) if err != nil { + err = SDKErrorf(err, "", "request-error", getComponentInfo()) return nil, err } GetLogger().Debug("Returned from IAM 'get token' operation, received status code %d", resp.StatusCode) @@ -470,22 +494,23 @@ func (authenticator *IamAuthenticator) RequestToken() (*IamTokenServerResponse, } if resp.StatusCode < 200 || resp.StatusCode >= 300 { - buff := new(bytes.Buffer) - _, _ = buff.ReadFrom(resp.Body) - - // Create a DetailedResponse to be included in the error below. - detailedResponse := &DetailedResponse{ - StatusCode: resp.StatusCode, - Headers: resp.Header, - RawResult: buff.Bytes(), + detailedResponse, err := processErrorResponse(resp) + authError := authenticationErrorf(err, detailedResponse, "get_token", authenticator.getComponentInfo()) + + // The err Summary is typically the message computed for the HTTPError instance in + // processErrorResponse(). If the response body is non-JSON, the message will be generic + // text based on the status code but authenticators have always used the stringified + // RawResult, so update that here for compatilibility. + iamErrorMsg := err.Summary + if detailedResponse.RawResult != nil { + // RawResult is only populated if the response body is + // non-JSON and we couldn't extract a message. + iamErrorMsg = string(detailedResponse.RawResult) } - iamErrorMsg := string(detailedResponse.RawResult) - if iamErrorMsg == "" { - iamErrorMsg = - fmt.Sprintf("unexpected status code %d received from IAM token server %s", detailedResponse.StatusCode, builder.URL) - } - return nil, NewAuthenticationError(detailedResponse, fmt.Errorf(iamErrorMsg)) + authError.Summary = iamErrorMsg + + return nil, authError } tokenResponse := &IamTokenServerResponse{} @@ -494,6 +519,10 @@ func (authenticator *IamAuthenticator) RequestToken() (*IamTokenServerResponse, return tokenResponse, nil } +func (authenticator *IamAuthenticator) getComponentInfo() *ProblemComponent { + return NewProblemComponent("iam_identity_services", "") +} + // IamTokenServerResponse : This struct models a response received from the token server. type IamTokenServerResponse struct { AccessToken string `json:"access_token"` @@ -515,7 +544,8 @@ type iamTokenData struct { func newIamTokenData(tokenResponse *IamTokenServerResponse) (*iamTokenData, error) { if tokenResponse == nil { - return nil, fmt.Errorf("Error while trying to parse access token!") + err := fmt.Errorf("Error while trying to parse access token!") + return nil, SDKErrorf(err, "", "token-parse", getComponentInfo()) } // Compute the adjusted refresh time (expiration time - 20% of timeToLive) timeToLive := tokenResponse.ExpiresIn @@ -533,23 +563,28 @@ func newIamTokenData(tokenResponse *IamTokenServerResponse) (*iamTokenData, erro } // isTokenValid: returns true iff the IamTokenData instance represents a valid (non-expired) access token. -func (this *iamTokenData) isTokenValid() bool { - if this.AccessToken != "" && GetCurrentTime() < this.Expiration { +func (td *iamTokenData) isTokenValid() bool { + // We'll use "exp - 10" so that we'll treat an otherwise valid (unexpired) access token + // to be expired if we're within 10 seconds of its TTL. + // This is because some IBM Cloud services reject valid access tokens with a short + // TTL remaining (TTL < 5 secs) because the access token might be used in a longer-running + // transaction and could potentially expire in the middle of the transaction. + if td.AccessToken != "" && GetCurrentTime() < (td.Expiration-iamExpirationWindow) { return true } return false } -// needsRefresh: synchronously returns true iff the currently stored access token should be refreshed. This method also -// updates the refresh time if it determines the token needs refreshed to prevent other threads from -// making multiple refresh calls. -func (this *iamTokenData) needsRefresh() bool { +// needsRefresh: synchronously returns true iff the currently stored access token should be refreshed. +// This method also updates the refresh time if it determines the token needs to be refreshed +// to prevent other threads from making multiple refresh calls. +func (td *iamTokenData) needsRefresh() bool { iamNeedsRefreshMutex.Lock() defer iamNeedsRefreshMutex.Unlock() // Advance refresh by one minute - if this.RefreshTime >= 0 && GetCurrentTime() > this.RefreshTime { - this.RefreshTime = GetCurrentTime() + 60 + if td.RefreshTime >= 0 && GetCurrentTime() > td.RefreshTime { + td.RefreshTime = GetCurrentTime() + 60 return true } diff --git a/vendor/github.com/IBM/go-sdk-core/v5/core/ibm_problem.go b/vendor/github.com/IBM/go-sdk-core/v5/core/ibm_problem.go new file mode 100644 index 0000000000..f83040d081 --- /dev/null +++ b/vendor/github.com/IBM/go-sdk-core/v5/core/ibm_problem.go @@ -0,0 +1,174 @@ +package core + +// (C) Copyright IBM Corp. 2024. +// +// 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. + +import ( + "errors" + "fmt" +) + +// problemSeverity simulates an enum by defining the only string values that are +// supported for the Severity field of an IBMProblem: "error" and "warning". +type problemSeverity string + +const ( + ErrorSeverity problemSeverity = "error" + WarningSeverity problemSeverity = "warning" +) + +// ProblemComponent is a structure that holds information about a given component. +type ProblemComponent struct { + Name string + Version string +} + +func NewProblemComponent(name, version string) *ProblemComponent { + return &ProblemComponent{ + Name: name, + Version: version, + } +} + +// IBMProblem holds the base set of fields that all problem types +// should include. It is geared more towards embedding in other +// structs than towards use on its own. +type IBMProblem struct { + + // Summary is the informative, user-friendly message that describes + // the problem and what caused it. + Summary string + + // Component is a structure providing information about the actual + // component that the problem occurred in: the name of the component + // and the version of the component being used with the problem occurred. + // Examples of components include cloud services, SDK clients, the IBM + // Terraform Provider, etc. For programming libraries, the Component name + // should match the module name for the library (i.e. the name a user + // would use to install it). + Component *ProblemComponent + + // Severity represents the severity level of the problem, + // e.g. error, warning, or info. + Severity problemSeverity + + // discriminator is a private property that is not ever meant to be + // seen by the end user. It's sole purpose is to enforce uniqueness + // for the computed ID of problems that would otherwise have the same + // ID. For example, if two SDKProblem instances are created with the + // same Component and Function values, they would end up with the same + // ID. This property allows us to "discriminate" between such problems. + discriminator string + + // causedBy allows for the storage of a problem from a previous component, + // if there is one. + causedBy Problem + + // nativeCausedBy allows for the storage of an error that is the cause of + // the problem instance but is not a part of the official chain of problem + // types. By including these errors in the "Unwrap" chain, the problem type + // changes become compatible with downstream code that uses error checking + // methods like "Is" and "As". + nativeCausedBy error +} + +// Error returns the problem's message and implements the native +// "error" interface. +func (e *IBMProblem) Error() string { + return e.Summary +} + +// GetBaseSignature provides a convenient way of +// retrieving the fields needed to compute the +// hash that are common to every kind of problem. +func (e *IBMProblem) GetBaseSignature() string { + causedByID := "" + if e.causedBy != nil { + causedByID = e.causedBy.GetID() + } + return fmt.Sprintf("%s%s%s%s", e.Component.Name, e.Severity, e.discriminator, causedByID) +} + +// GetCausedBy returns the underlying "causedBy" problem, if it exists. +func (e *IBMProblem) GetCausedBy() Problem { + return e.causedBy +} + +// Unwrap implements an interface the native Go "errors" package uses to +// check for embedded problems in a given problem instance. IBM problem types +// are not embedded in the traditional sense, but they chain previous +// problem instances together with the "causedBy" field. This allows error +// interface instances to be cast into any of the problem types in the chain +// using the native "errors.As" function. This can be useful for, as an +// example, extracting an HTTPProblem from the chain if it exists. +// Note that this Unwrap method returns only the chain of "caused by" problems; +// it does not include the error instance the method is called on - that is +// looked at separately by the "errors" package in functions like "As". +func (e *IBMProblem) Unwrap() []error { + var errs []error + + // Include native (i.e. non-Problem) caused by errors in the + // chain for compatibility with respect to downstream methods + // like "errors.Is" or "errors.As". + if e.nativeCausedBy != nil { + errs = append(errs, e.nativeCausedBy) + } + + causedBy := e.GetCausedBy() + if causedBy == nil { + return errs + } + + errs = append(errs, causedBy) + + var toUnwrap interface{ Unwrap() []error } + if errors.As(causedBy, &toUnwrap) { + causedByChain := toUnwrap.Unwrap() + if causedByChain != nil { + errs = append(errs, causedByChain...) + } + } + + return errs +} + +func ibmProblemf(err error, severity problemSeverity, component *ProblemComponent, summary, discriminator string) *IBMProblem { + // Leaving summary blank is a convenient way to + // use the message from the underlying problem. + if summary == "" && err != nil { + summary = err.Error() + } + + newError := &IBMProblem{ + Summary: summary, + Component: component, + discriminator: discriminator, + Severity: severity, + } + + var causedBy Problem + if errors.As(err, &causedBy) { + newError.causedBy = causedBy + } else { + newError.nativeCausedBy = err + } + + return newError +} + +// IBMErrorf creates and returns a new instance of an IBMProblem struct with "error" +// level severity. It is primarily meant for embedding IBMProblem structs in other types. +func IBMErrorf(err error, component *ProblemComponent, summary, discriminator string) *IBMProblem { + return ibmProblemf(err, ErrorSeverity, component, summary, discriminator) +} diff --git a/vendor/github.com/IBM/go-sdk-core/v5/core/jwt_utils.go b/vendor/github.com/IBM/go-sdk-core/v5/core/jwt_utils.go index 117669eb9e..93a9e317b8 100644 --- a/vendor/github.com/IBM/go-sdk-core/v5/core/jwt_utils.go +++ b/vendor/github.com/IBM/go-sdk-core/v5/core/jwt_utils.go @@ -33,6 +33,7 @@ func parseJWT(tokenString string) (claims *coreJWTClaims, err error) { segments := strings.Split(tokenString, ".") if len(segments) != 3 { err = fmt.Errorf("token contains an invalid number of segments") + err = SDKErrorf(err, "", "need-3-segs", getComponentInfo()) return } @@ -40,7 +41,6 @@ func parseJWT(tokenString string) (claims *coreJWTClaims, err error) { var claimBytes []byte claimBytes, err = decodeSegment(segments[1]) if err != nil { - err = fmt.Errorf("error decoding claims segment: %s", err.Error()) return } @@ -49,6 +49,7 @@ func parseJWT(tokenString string) (claims *coreJWTClaims, err error) { err = json.Unmarshal(claimBytes, claims) if err != nil { err = fmt.Errorf("error unmarshalling token: %s", err.Error()) + err = SDKErrorf(err, "", "bad-token", getComponentInfo()) return } @@ -62,5 +63,9 @@ func decodeSegment(seg string) ([]byte, error) { seg += strings.Repeat("=", 4-l) } - return base64.URLEncoding.DecodeString(seg) + res, err := base64.URLEncoding.DecodeString(seg) + if err != nil { + err = SDKErrorf(err, fmt.Sprintf("error decoding claims segment: %s", err.Error()), "bad-claim-seg", getComponentInfo()) + } + return res, err } diff --git a/vendor/github.com/IBM/go-sdk-core/v5/core/mcsp_authenticator.go b/vendor/github.com/IBM/go-sdk-core/v5/core/mcsp_authenticator.go new file mode 100644 index 0000000000..3bd2a2f4f0 --- /dev/null +++ b/vendor/github.com/IBM/go-sdk-core/v5/core/mcsp_authenticator.go @@ -0,0 +1,439 @@ +package core + +// (C) Copyright IBM Corp. 2023, 2024. +// +// 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. + +import ( + "crypto/tls" + "encoding/json" + "fmt" + "net/http" + "net/http/httputil" + "strconv" + "sync" + "time" +) + +// MCSPAuthenticator uses an apikey to obtain an access token, +// and adds the access token to requests via an Authorization header +// of the form: "Authorization: Bearer " +type MCSPAuthenticator struct { + + // [Required] The apikey used to fetch the bearer token from the token server. + ApiKey string + + // [Required] The endpoint base URL for the token server. + URL string + + // [Optional] A flag that indicates whether verification of the token server's SSL certificate + // should be disabled; defaults to false. + DisableSSLVerification bool + + // [Optional] A set of key/value pairs that will be sent as HTTP headers in requests + // made to the token server. + Headers map[string]string + + // [Optional] The http.Client object used to invoke token server requests. + // If not specified by the user, a suitable default Client will be constructed. + Client *http.Client + clientInit sync.Once + + // The User-Agent header value to be included with each token request. + userAgent string + userAgentInit sync.Once + + // The cached token and expiration time. + tokenData *mcspTokenData + + // Mutex to make the tokenData field thread safe. + tokenDataMutex sync.Mutex +} + +var mcspRequestTokenMutex sync.Mutex +var mcspNeedsRefreshMutex sync.Mutex + +const ( + mcspAuthOperationPath = "/siusermgr/api/1.0/apikeys/token" +) + +// MCSPAuthenticatorBuilder is used to construct an MCSPAuthenticator instance. +type MCSPAuthenticatorBuilder struct { + MCSPAuthenticator +} + +// NewMCSPAuthenticatorBuilder returns a new builder struct that +// can be used to construct an MCSPAuthenticator instance. +func NewMCSPAuthenticatorBuilder() *MCSPAuthenticatorBuilder { + return &MCSPAuthenticatorBuilder{} +} + +// SetApiKey sets the ApiKey field in the builder. +func (builder *MCSPAuthenticatorBuilder) SetApiKey(s string) *MCSPAuthenticatorBuilder { + builder.MCSPAuthenticator.ApiKey = s + return builder +} + +// SetURL sets the URL field in the builder. +func (builder *MCSPAuthenticatorBuilder) SetURL(s string) *MCSPAuthenticatorBuilder { + builder.MCSPAuthenticator.URL = s + return builder +} + +// SetDisableSSLVerification sets the DisableSSLVerification field in the builder. +func (builder *MCSPAuthenticatorBuilder) SetDisableSSLVerification(b bool) *MCSPAuthenticatorBuilder { + builder.MCSPAuthenticator.DisableSSLVerification = b + return builder +} + +// SetHeaders sets the Headers field in the builder. +func (builder *MCSPAuthenticatorBuilder) SetHeaders(headers map[string]string) *MCSPAuthenticatorBuilder { + builder.MCSPAuthenticator.Headers = headers + return builder +} + +// SetClient sets the Client field in the builder. +func (builder *MCSPAuthenticatorBuilder) SetClient(client *http.Client) *MCSPAuthenticatorBuilder { + builder.MCSPAuthenticator.Client = client + return builder +} + +// Build() returns a validated instance of the MCSPAuthenticator with the config that was set in the builder. +func (builder *MCSPAuthenticatorBuilder) Build() (*MCSPAuthenticator, error) { + + // Make sure the config is valid. + err := builder.MCSPAuthenticator.Validate() + if err != nil { + return nil, RepurposeSDKProblem(err, "validation-failed") + } + + return &builder.MCSPAuthenticator, nil +} + +// client returns the authenticator's http client after potentially initializing it. +func (authenticator *MCSPAuthenticator) client() *http.Client { + authenticator.clientInit.Do(func() { + if authenticator.Client == nil { + authenticator.Client = DefaultHTTPClient() + authenticator.Client.Timeout = time.Second * 30 + + // If the user told us to disable SSL verification, then do it now. + if authenticator.DisableSSLVerification { + transport := &http.Transport{ + // #nosec G402 + TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, + } + authenticator.Client.Transport = transport + } + } + }) + return authenticator.Client +} + +// getUserAgent returns the User-Agent header value to be included in each token request invoked by the authenticator. +func (authenticator *MCSPAuthenticator) getUserAgent() string { + authenticator.userAgentInit.Do(func() { + authenticator.userAgent = fmt.Sprintf("%s/%s-%s %s", sdkName, "mcsp-authenticator", __VERSION__, SystemInfo()) + }) + return authenticator.userAgent +} + +// newMCSPAuthenticatorFromMap constructs a new MCSPAuthenticator instance from a map. +func newMCSPAuthenticatorFromMap(properties map[string]string) (authenticator *MCSPAuthenticator, err error) { + if properties == nil { + err = fmt.Errorf(ERRORMSG_PROPS_MAP_NIL) + return nil, SDKErrorf(err, "", "missing-props", getComponentInfo()) + } + + disableSSL, err := strconv.ParseBool(properties[PROPNAME_AUTH_DISABLE_SSL]) + if err != nil { + disableSSL = false + } + + authenticator, err = NewMCSPAuthenticatorBuilder(). + SetApiKey(properties[PROPNAME_APIKEY]). + SetURL(properties[PROPNAME_AUTH_URL]). + SetDisableSSLVerification(disableSSL). + Build() + + return +} + +// AuthenticationType returns the authentication type for this authenticator. +func (*MCSPAuthenticator) AuthenticationType() string { + return AUTHTYPE_MCSP +} + +// Authenticate adds the Authorization header to the request. +// The value will be of the form: "Authorization: Bearer "" +func (authenticator *MCSPAuthenticator) Authenticate(request *http.Request) error { + token, err := authenticator.GetToken() + if err != nil { + return RepurposeSDKProblem(err, "get-token-fail") + } + + request.Header.Set("Authorization", "Bearer "+token) + return nil +} + +// getTokenData returns the tokenData field from the authenticator. +func (authenticator *MCSPAuthenticator) getTokenData() *mcspTokenData { + authenticator.tokenDataMutex.Lock() + defer authenticator.tokenDataMutex.Unlock() + + return authenticator.tokenData +} + +// setTokenData sets the given mcspTokenData to the tokenData field of the authenticator. +func (authenticator *MCSPAuthenticator) setTokenData(tokenData *mcspTokenData) { + authenticator.tokenDataMutex.Lock() + defer authenticator.tokenDataMutex.Unlock() + + authenticator.tokenData = tokenData + GetLogger().Info("setTokenData: expiration=%d, refreshTime=%d", + authenticator.tokenData.Expiration, authenticator.tokenData.RefreshTime) +} + +// Validate the authenticator's configuration. +// +// Ensures that the ApiKey and URL properties are both specified. +func (authenticator *MCSPAuthenticator) Validate() error { + + if authenticator.ApiKey == "" { + err := fmt.Errorf(ERRORMSG_PROP_MISSING, "ApiKey") + return SDKErrorf(err, "", "missing-api-key", getComponentInfo()) + } + + if authenticator.URL == "" { + err := fmt.Errorf(ERRORMSG_PROP_MISSING, "URL") + return SDKErrorf(err, "", "missing-url", getComponentInfo()) + } + + return nil +} + +// GetToken: returns an access token to be used in an Authorization header. +// Whenever a new token is needed (when a token doesn't yet exist, needs to be refreshed, +// or the existing token has expired), a new access token is fetched from the token server. +func (authenticator *MCSPAuthenticator) GetToken() (string, error) { + if authenticator.getTokenData() == nil || !authenticator.getTokenData().isTokenValid() { + // synchronously request the token + err := authenticator.synchronizedRequestToken() + if err != nil { + return "", RepurposeSDKProblem(err, "request-token-fail") + } + } else if authenticator.getTokenData().needsRefresh() { + // If refresh needed, kick off a go routine in the background to get a new token. + //nolint: errcheck + go authenticator.invokeRequestTokenData() + } + + // return an error if the access token is not valid or was not fetched + if authenticator.getTokenData() == nil || authenticator.getTokenData().AccessToken == "" { + err := fmt.Errorf("Error while trying to get access token") + return "", SDKErrorf(err, "", "no-token", getComponentInfo()) + } + + return authenticator.getTokenData().AccessToken, nil +} + +// synchronizedRequestToken: synchronously checks if the current token in cache +// is valid. If token is not valid or does not exist, it will fetch a new token. +func (authenticator *MCSPAuthenticator) synchronizedRequestToken() error { + mcspRequestTokenMutex.Lock() + defer mcspRequestTokenMutex.Unlock() + // if cached token is still valid, then just continue to use it + if authenticator.getTokenData() != nil && authenticator.getTokenData().isTokenValid() { + return nil + } + + return authenticator.invokeRequestTokenData() +} + +// invokeRequestTokenData: requests a new token from the access server and +// unmarshals the token information to the tokenData cache. Returns +// an error if the token was unable to be fetched, otherwise returns nil +func (authenticator *MCSPAuthenticator) invokeRequestTokenData() error { + tokenResponse, err := authenticator.RequestToken() + if err != nil { + return err + } + + GetLogger().Info("invokeRequestTokenData(): RequestToken returned tokenResponse:\n%+v", *tokenResponse) + tokenData, err := newMCSPTokenData(tokenResponse) + if err != nil { + tokenData = &mcspTokenData{} + } + + authenticator.setTokenData(tokenData) + + return nil +} + +// RequestToken fetches a new access token from the token server. +func (authenticator *MCSPAuthenticator) RequestToken() (*MCSPTokenServerResponse, error) { + + builder := NewRequestBuilder(POST) + _, err := builder.ResolveRequestURL(authenticator.URL, mcspAuthOperationPath, nil) + if err != nil { + err = RepurposeSDKProblem(err, "url-resolve-error") + return nil, err + } + + builder.AddHeader(CONTENT_TYPE, APPLICATION_JSON) + builder.AddHeader(Accept, APPLICATION_JSON) + builder.AddHeader(headerNameUserAgent, authenticator.getUserAgent()) + requestBody := fmt.Sprintf(`{"apikey":"%s"}`, authenticator.ApiKey) + _, _ = builder.SetBodyContentString(requestBody) + + // Add user-defined headers to request. + for headerName, headerValue := range authenticator.Headers { + builder.AddHeader(headerName, headerValue) + } + + req, err := builder.Build() + if err != nil { + return nil, RepurposeSDKProblem(err, "request-build-error") + } + + // If debug is enabled, then dump the request. + if GetLogger().IsLogLevelEnabled(LevelDebug) { + buf, dumpErr := httputil.DumpRequestOut(req, req.Body != nil) + if dumpErr == nil { + GetLogger().Debug("Request:\n%s\n", RedactSecrets(string(buf))) + } else { + GetLogger().Debug(fmt.Sprintf("error while attempting to log outbound request: %s", dumpErr.Error())) + } + } + + GetLogger().Debug("Invoking MCSP 'get token' operation: %s", builder.URL) + resp, err := authenticator.client().Do(req) + if err != nil { + err = SDKErrorf(err, "", "request-error", getComponentInfo()) + return nil, err + } + GetLogger().Debug("Returned from MCSP 'get token' operation, received status code %d", resp.StatusCode) + + // If debug is enabled, then dump the response. + if GetLogger().IsLogLevelEnabled(LevelDebug) { + buf, dumpErr := httputil.DumpResponse(resp, req.Body != nil) + if dumpErr == nil { + GetLogger().Debug("Response:\n%s\n", RedactSecrets(string(buf))) + } else { + GetLogger().Debug(fmt.Sprintf("error while attempting to log inbound response: %s", dumpErr.Error())) + } + } + + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + detailedResponse, err := processErrorResponse(resp) + authError := authenticationErrorf(err, detailedResponse, "get_token", authenticator.getComponentInfo()) + + // The err Summary is typically the message computed for the HTTPError instance in + // processErrorResponse(). If the response body is non-JSON, the message will be generic + // text based on the status code but authenticators have always used the stringified + // RawResult, so update that here for compatilibility. + errorMsg := err.Summary + if detailedResponse.RawResult != nil { + // RawResult is only populated if the response body is + // non-JSON and we couldn't extract a message. + errorMsg = string(detailedResponse.RawResult) + } + + authError.Summary = errorMsg + + return nil, authError + } + + tokenResponse := &MCSPTokenServerResponse{} + _ = json.NewDecoder(resp.Body).Decode(tokenResponse) + defer resp.Body.Close() // #nosec G307 + + return tokenResponse, nil +} + +func (authenticator *MCSPAuthenticator) getComponentInfo() *ProblemComponent { + return NewProblemComponent("mscp_token_server", "1.0") +} + +// MCSPTokenServerResponse : This struct models a response received from the token server. +type MCSPTokenServerResponse struct { + Token string `json:"token"` + TokenType string `json:"token_type"` + ExpiresIn int64 `json:"expires_in"` +} + +// mcspTokenData : This struct represents the cached information related to a fetched access token. +type mcspTokenData struct { + AccessToken string + RefreshTime int64 + Expiration int64 +} + +// newMCSPTokenData: constructs a new mcspTokenData instance from the specified +// MCSPTokenServerResponse instance. +func newMCSPTokenData(tokenResponse *MCSPTokenServerResponse) (*mcspTokenData, error) { + if tokenResponse == nil || tokenResponse.Token == "" { + err := fmt.Errorf("Error while trying to parse access token!") + return nil, SDKErrorf(err, "", "token-parse", getComponentInfo()) + } + + // Need to crack open the access token (a JWT) to get the expiration and issued-at times + // so that we can compute the refresh time. + claims, err := parseJWT(tokenResponse.Token) + if err != nil { + return nil, err + } + + // Compute the adjusted refresh time (expiration time - 20% of timeToLive) + timeToLive := claims.ExpiresAt - claims.IssuedAt + expireTime := claims.ExpiresAt + refreshTime := expireTime - int64(float64(timeToLive)*0.2) + + tokenData := &mcspTokenData{ + AccessToken: tokenResponse.Token, + Expiration: expireTime, + RefreshTime: refreshTime, + } + + GetLogger().Info("newMCSPTokenData: expiration=%d, refreshTime=%d", tokenData.Expiration, tokenData.RefreshTime) + + return tokenData, nil +} + +// isTokenValid: returns true iff the mcspTokenData instance represents a valid (non-expired) access token. +func (tokenData *mcspTokenData) isTokenValid() bool { + if tokenData.AccessToken != "" && GetCurrentTime() < tokenData.Expiration { + GetLogger().Info("isTokenValid: Token is valid!") + return true + } + GetLogger().Info("isTokenValid: Token is NOT valid!") + GetLogger().Info("isTokenValid: expiration=%d, refreshTime=%d", tokenData.Expiration, tokenData.RefreshTime) + GetLogger().Info("GetCurrentTime(): %d\n", GetCurrentTime()) + return false +} + +// needsRefresh: synchronously returns true iff the currently stored access token should be refreshed. This method also +// updates the refresh time if it determines the token needs refreshed to prevent other threads from +// making multiple refresh calls. +func (tokenData *mcspTokenData) needsRefresh() bool { + mcspNeedsRefreshMutex.Lock() + defer mcspNeedsRefreshMutex.Unlock() + + // Advance refresh by one minute + if tokenData.RefreshTime >= 0 && GetCurrentTime() > tokenData.RefreshTime { + tokenData.RefreshTime = GetCurrentTime() + 60 + return true + } + + return false +} diff --git a/vendor/github.com/IBM/go-sdk-core/v5/core/ordered_maps.go b/vendor/github.com/IBM/go-sdk-core/v5/core/ordered_maps.go new file mode 100644 index 0000000000..b837923424 --- /dev/null +++ b/vendor/github.com/IBM/go-sdk-core/v5/core/ordered_maps.go @@ -0,0 +1,49 @@ +package core + +// (C) Copyright IBM Corp. 2024. +// +// 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. + +import ( + "gopkg.in/yaml.v2" +) + +// OrderedMaps provides a wrapper around the yaml package's +// MapItem type and provides convenience functionality beyond +// what would be available with the MapSlice type, which is similar. +// It enables the ordering of fields in a map for controlling the +// order of keys in the printed YAML strings. +type OrderedMaps struct { + maps []yaml.MapItem +} + +// Add appends a key/value pair to the ordered list of maps. +func (m *OrderedMaps) Add(key string, value interface{}) { + m.maps = append(m.maps, yaml.MapItem{ + Key: key, + Value: value, + }) +} + +// GetMaps returns the actual list of ordered maps stored in +// the OrderedMaps instance. Each element is MapItem type, +// which will be serialized by the yaml package in a special +// way that allows the ordering of fields in the YAML. +func (m *OrderedMaps) GetMaps() []yaml.MapItem { + return m.maps +} + +// NewOrderedMaps initializes and returns a new instance of OrderedMaps. +func NewOrderedMaps() *OrderedMaps { + return &OrderedMaps{} +} diff --git a/vendor/github.com/IBM/go-sdk-core/v5/core/problem.go b/vendor/github.com/IBM/go-sdk-core/v5/core/problem.go new file mode 100644 index 0000000000..3b52a6b3b4 --- /dev/null +++ b/vendor/github.com/IBM/go-sdk-core/v5/core/problem.go @@ -0,0 +1,47 @@ +package core + +// (C) Copyright IBM Corp. 2024. +// +// 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. + +// Problem is an interface that describes the common +// behavior of custom IBM problem message types. +type Problem interface { + + // GetConsoleMessage returns a message suited to the practitioner + // or end user. It should tell the user what went wrong, and why, + // without unnecessary implementation details. + GetConsoleMessage() string + + // GetDebugMessage returns a message suited to the developer, in + // order to assist in debugging. It should give enough information + // for the developer to identify the root cause of the issue. + GetDebugMessage() string + + // GetID returns an identifier or code for a given problem. It is computed + // from the attributes of the problem, so that the same problem scenario + // will always have the same ID, even when encountered by different users. + GetID() string + + // Error returns the message associated with a given problem and guarantees + // every instance of Problem also implements the native "error" interface. + Error() string +} + +// OrderableProblem provides an interface for retrieving ordered +// representations of problems in order to print YAML messages +// with a controlled ordering of the fields. +type OrderableProblem interface { + GetConsoleOrderedMaps() *OrderedMaps + GetDebugOrderedMaps() *OrderedMaps +} diff --git a/vendor/github.com/IBM/go-sdk-core/v5/core/problem_utils.go b/vendor/github.com/IBM/go-sdk-core/v5/core/problem_utils.go new file mode 100644 index 0000000000..bd54070959 --- /dev/null +++ b/vendor/github.com/IBM/go-sdk-core/v5/core/problem_utils.go @@ -0,0 +1,67 @@ +package core + +// (C) Copyright IBM Corp. 2024. +// +// 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. + +import ( + "crypto/sha256" + "encoding/hex" + "errors" + "fmt" + "strings" + + "gopkg.in/yaml.v2" +) + +func ComputeConsoleMessage(o OrderableProblem) string { + return getProblemInfoAsYAML(o.GetConsoleOrderedMaps()) +} + +func ComputeDebugMessage(o OrderableProblem) string { + return getProblemInfoAsYAML(o.GetDebugOrderedMaps()) +} + +// CreateIDHash computes a unique ID based on a given prefix +// and problem attribute fields. +func CreateIDHash(prefix string, fields ...string) string { + signature := strings.Join(fields, "") + hash := sha256.Sum256([]byte(signature)) + return fmt.Sprintf("%s-%s", prefix, hex.EncodeToString(hash[:4])) +} + +// getProblemInfoAsYAML formats the ordered problem data as +// YAML for human/machine readable printing. +func getProblemInfoAsYAML(orderedMaps *OrderedMaps) string { + asYaml, err := yaml.Marshal(orderedMaps.GetMaps()) + + if err != nil { + return fmt.Sprintf("Error serializing the problem information: %s", err.Error()) + } + return fmt.Sprintf("---\n%s---\n", asYaml) +} + +// getComponentInfo is a convenient way to access the name of the +// component alongside the current semantic version of the component. +func getComponentInfo() *ProblemComponent { + return NewProblemComponent(MODULE_NAME, __VERSION__) +} + +// is provides a simple utility function that assists problem types +// implement an "Is" function for checking error equality. Error types +// are treated as equivalent if they are both Problem types and their +// IDs match. +func is(target error, id string) bool { + var problem Problem + return errors.As(target, &problem) && problem.GetID() == id +} diff --git a/vendor/github.com/IBM/go-sdk-core/v5/core/request_builder.go b/vendor/github.com/IBM/go-sdk-core/v5/core/request_builder.go index 002a4fc5ed..e0c7f283ce 100644 --- a/vendor/github.com/IBM/go-sdk-core/v5/core/request_builder.go +++ b/vendor/github.com/IBM/go-sdk-core/v5/core/request_builder.go @@ -105,13 +105,14 @@ func (requestBuilder *RequestBuilder) WithContext(ctx context.Context) *RequestB // invalid URL string (e.g. ":"). func (requestBuilder *RequestBuilder) ConstructHTTPURL(serviceURL string, pathSegments []string, pathParameters []string) (*RequestBuilder, error) { if serviceURL == "" { - return requestBuilder, fmt.Errorf(ERRORMSG_SERVICE_URL_MISSING) + return requestBuilder, SDKErrorf(fmt.Errorf(ERRORMSG_SERVICE_URL_MISSING), "", "no-url", getComponentInfo()) } var URL *url.URL URL, err := url.Parse(serviceURL) if err != nil { - return requestBuilder, fmt.Errorf(ERRORMSG_SERVICE_URL_INVALID, err.Error()) + err := fmt.Errorf(ERRORMSG_SERVICE_URL_INVALID, err.Error()) + return requestBuilder, SDKErrorf(err, "", "bad-url", getComponentInfo()) } for i, pathSegment := range pathSegments { @@ -121,7 +122,8 @@ func (requestBuilder *RequestBuilder) ConstructHTTPURL(serviceURL string, pathSe if pathParameters != nil && i < len(pathParameters) { if pathParameters[i] == "" { - return requestBuilder, fmt.Errorf(ERRORMSG_PATH_PARAM_EMPTY, fmt.Sprintf("[%d]", i)) + err := fmt.Errorf(ERRORMSG_PATH_PARAM_EMPTY, fmt.Sprintf("[%d]", i)) + return requestBuilder, SDKErrorf(err, "", "empty-path-param", getComponentInfo()) } URL.Path += "/" + pathParameters[i] } @@ -141,7 +143,8 @@ func (requestBuilder *RequestBuilder) ConstructHTTPURL(serviceURL string, pathSe // The resulting request URL: "https://myservice.cloud.ibm.com/resource/res-123-456-789-abc/type/type-1" func (requestBuilder *RequestBuilder) ResolveRequestURL(serviceURL string, path string, pathParams map[string]string) (*RequestBuilder, error) { if serviceURL == "" { - return requestBuilder, fmt.Errorf(ERRORMSG_SERVICE_URL_MISSING) + err := fmt.Errorf(ERRORMSG_SERVICE_URL_MISSING) + return requestBuilder, SDKErrorf(err, "", "service-url-missing", getComponentInfo()) } urlString := serviceURL @@ -149,12 +152,21 @@ func (requestBuilder *RequestBuilder) ResolveRequestURL(serviceURL string, path // If we have a non-empty "path" input parameter, then process it for possible path param references. if path != "" { + // Encode the unresolved path string. This will convert all special characters to their + // "%" encoding counterparts. Then we need to revert the encodings for '/', '{' and '}' characters + // to retain the original path segments and to make it easy to insert the encoded path param values below. + path = url.PathEscape(path) + path = strings.ReplaceAll(path, "%2F", "/") + path = strings.ReplaceAll(path, "%7B", "{") + path = strings.ReplaceAll(path, "%7D", "}") + // If path parameter values were passed in, then for each one, replace any references to it // within "path" with the path parameter's encoded value. if len(pathParams) > 0 { for k, v := range pathParams { if v == "" { - return requestBuilder, fmt.Errorf(ERRORMSG_PATH_PARAM_EMPTY, k) + err := fmt.Errorf(ERRORMSG_PATH_PARAM_EMPTY, k) + return requestBuilder, SDKErrorf(err, "", "empty-path-param", getComponentInfo()) } encodedValue := url.PathEscape(v) ref := fmt.Sprintf("{%s}", k) @@ -183,7 +195,8 @@ func (requestBuilder *RequestBuilder) ResolveRequestURL(serviceURL string, path URL, err := url.Parse(urlString) if err != nil { - return requestBuilder, fmt.Errorf(ERRORMSG_SERVICE_URL_INVALID, err.Error()) + err = fmt.Errorf(ERRORMSG_SERVICE_URL_INVALID, err.Error()) + return requestBuilder, SDKErrorf(err, "", "bad-url", getComponentInfo()) } requestBuilder.URL = URL @@ -226,6 +239,10 @@ func (requestBuilder *RequestBuilder) AddFormData(fieldName string, fileName str func (requestBuilder *RequestBuilder) SetBodyContentJSON(bodyContent interface{}) (*RequestBuilder, error) { requestBuilder.Body = new(bytes.Buffer) err := json.NewEncoder(requestBuilder.Body.(io.Writer)).Encode(bodyContent) + if err != nil { + err = fmt.Errorf("Could not encode JSON body:\n%s", err.Error()) + err = SDKErrorf(err, "", "bad-encode", getComponentInfo()) + } return requestBuilder, err } @@ -255,7 +272,11 @@ func createFormFile(formWriter *multipart.Writer, fieldname string, filename str h.Set(CONTENT_TYPE, contentType) } - return formWriter.CreatePart(h) + res, err := formWriter.CreatePart(h) + if err != nil { + err = SDKErrorf(err, "", "create-part-error", getComponentInfo()) + } + return res, err } // SetBodyContentForMultipart sets the body content for a part in a multi-part form. @@ -263,17 +284,63 @@ func (requestBuilder *RequestBuilder) SetBodyContentForMultipart(contentType str var err error if stream, ok := content.(io.Reader); ok { _, err = io.Copy(writer, stream) + if err != nil { + err = SDKErrorf( + nil, + fmt.Sprintf("Could not set body content in form:\n%s", err.Error()), + "reader-error", + getComponentInfo(), + ) + } } else if stream, ok := content.(*io.ReadCloser); ok { _, err = io.Copy(writer, *stream) + if err != nil { + err = SDKErrorf( + nil, + fmt.Sprintf("Could not set body content in form:\n%s", err.Error()), + "readcloser-error", + getComponentInfo(), + ) + } } else if IsJSONMimeType(contentType) || IsJSONPatchMimeType(contentType) { err = json.NewEncoder(writer).Encode(content) + if err != nil { + err = SDKErrorf( + nil, + fmt.Sprintf("Could not set body content in form:\n%s", err.Error()), + "json-error", + getComponentInfo(), + ) + } } else if str, ok := content.(string); ok { _, err = writer.Write([]byte(str)) + if err != nil { + err = SDKErrorf( + nil, + fmt.Sprintf("Could not set body content in form:\n%s", err.Error()), + "string-error", + getComponentInfo(), + ) + } } else if strPtr, ok := content.(*string); ok { _, err = writer.Write([]byte(*strPtr)) + if err != nil { + err = SDKErrorf( + nil, + fmt.Sprintf("Could not set body content in form:\n%s", err.Error()), + "string-ptr-error", + getComponentInfo(), + ) + } } else { - err = fmt.Errorf("Error: unable to determine the type of 'content' provided") + err = SDKErrorf( + nil, + "Error: unable to determine the type of 'content' provided", + "undetermined-type", + getComponentInfo(), + ) } + return err } @@ -292,8 +359,10 @@ func (requestBuilder *RequestBuilder) Build() (req *http.Request, err error) { data.Add(fieldName, v.contents.(string)) } } + // This function cannot actually return an error but check anyway _, err = requestBuilder.SetBodyContentString(data.Encode()) if err != nil { + err = RepurposeSDKProblem(err, "set-content-string-error") return } } else { @@ -301,6 +370,7 @@ func (requestBuilder *RequestBuilder) Build() (req *http.Request, err error) { var formBody io.ReadCloser formBody, contentType, err = requestBuilder.createMultipartFormRequestBody() if err != nil { + err = RepurposeSDKProblem(err, "create-multipart-error") return } @@ -315,6 +385,7 @@ func (requestBuilder *RequestBuilder) Build() (req *http.Request, err error) { !SliceContains(requestBuilder.Header[CONTENT_ENCODING], "gzip") { newBody, err := NewGzipCompressionReader(requestBuilder.Body) if err != nil { + err = RepurposeSDKProblem(err, "gzip-reader-error") return nil, err } requestBuilder.Body = newBody @@ -324,6 +395,7 @@ func (requestBuilder *RequestBuilder) Build() (req *http.Request, err error) { // Create the request req, err = http.NewRequest(requestBuilder.Method, requestBuilder.URL.String(), requestBuilder.Body) if err != nil { + err = SDKErrorf(err, fmt.Sprintf("Failed to build request:\n%s", err.Error()), "new-request-error", getComponentInfo()) return } @@ -399,6 +471,7 @@ func (requestBuilder *RequestBuilder) createMultipartFormRequestBody() (bodyRead // We're done adding parts to the form, so close the form writer. if err = formWriter.Close(); err != nil { + err = SDKErrorf(err, err.Error(), "form-close-error", getComponentInfo()) return } @@ -416,11 +489,13 @@ func (requestBuilder *RequestBuilder) SetBodyContent(contentType string, jsonCon if !IsNil(jsonContent) { builder, err = requestBuilder.SetBodyContentJSON(jsonContent) if err != nil { + err = RepurposeSDKProblem(err, "set-json-body-error") return } } else if !IsNil(jsonPatchContent) { builder, err = requestBuilder.SetBodyContentJSON(jsonPatchContent) if err != nil { + err = RepurposeSDKProblem(err, "set-json-patch-body-error") return } } else if !IsNil(nonJSONContent) { @@ -428,20 +503,27 @@ func (requestBuilder *RequestBuilder) SetBodyContent(contentType string, jsonCon // which should be a "string", "*string" or an "io.Reader" if str, ok := nonJSONContent.(string); ok { builder, err = requestBuilder.SetBodyContentString(str) + err = RepurposeSDKProblem(err, "set-body-string-error") } else if strPtr, ok := nonJSONContent.(*string); ok { builder, err = requestBuilder.SetBodyContentString(*strPtr) + err = RepurposeSDKProblem(err, "set-body-strptr-error") } else if stream, ok := nonJSONContent.(io.Reader); ok { builder, err = requestBuilder.SetBodyContentStream(stream) + err = RepurposeSDKProblem(err, "set-body-reader-error") } else if stream, ok := nonJSONContent.(*io.ReadCloser); ok { builder, err = requestBuilder.SetBodyContentStream(*stream) + err = RepurposeSDKProblem(err, "set-body-readerptr-error") } else { builder = requestBuilder err = fmt.Errorf("Invalid type for non-JSON body content: %s", reflect.TypeOf(nonJSONContent).String()) + err = SDKErrorf(err, "", "bad-nonjson-body-content", getComponentInfo()) } } else { builder = requestBuilder err = fmt.Errorf("No body content provided") + err = SDKErrorf(err, "", "no-body-content", getComponentInfo()) } + return } @@ -451,6 +533,7 @@ func (requestBuilder *RequestBuilder) SetBodyContent(contentType string, jsonCon func (requestBuilder *RequestBuilder) AddQuerySlice(param string, slice interface{}) (err error) { convertedSlice, err := ConvertSlice(slice) if err != nil { + err = RepurposeSDKProblem(err, "convert-slice-error") return } diff --git a/vendor/github.com/IBM/go-sdk-core/v5/core/sdk_problem.go b/vendor/github.com/IBM/go-sdk-core/v5/core/sdk_problem.go new file mode 100644 index 0000000000..b4b6727527 --- /dev/null +++ b/vendor/github.com/IBM/go-sdk-core/v5/core/sdk_problem.go @@ -0,0 +1,188 @@ +package core + +// (C) Copyright IBM Corp. 2024. +// +// 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. + +import ( + "errors" +) + +// SDKProblem provides a type suited to problems that +// occur in SDK projects. It extends the base +// "IBMProblem" type with a field to store the +// function being called when the problem occurs. +type SDKProblem struct { + *IBMProblem + + // Function provides the name of the in-code + // function or method in which the problem + // occurred. + Function string + + // A computed stack trace including the relevant + // function names, files, and line numbers invoked + // leading up to the origination of the problem. + stack []sdkStackFrame + + // If the problem instance originated in the core, we + // want to keep track of the information for debugging + // purposes (even though we aren't using the problem + // as a "caused by" problem). + coreProblem *sparseSDKProblem + + // If the problem instance originated in the core and + // was caused by an HTTP request, we don't use the + // HTTPProblem instance as a "caused by" but we need + // to store the instance to pass it to a downstream + // SDKProblem instance. + httpProblem *HTTPProblem +} + +// GetConsoleMessage returns all public fields of +// the problem, formatted in YAML. +func (e *SDKProblem) GetConsoleMessage() string { + return ComputeConsoleMessage(e) +} + +// GetDebugMessage returns all information +// about the problem, formatted in YAML. +func (e *SDKProblem) GetDebugMessage() string { + return ComputeDebugMessage(e) +} + +// GetID returns the computed identifier, computed from the +// "Component", "discriminator", and "Function" fields, as well as the +// identifier of the "causedBy" problem, if it exists. +func (e *SDKProblem) GetID() string { + return CreateIDHash("sdk", e.GetBaseSignature(), e.Function) +} + +// Is allows an SDKProblem instance to be compared against another error for equality. +// An SDKProblem is considered equal to another error if 1) the error is also a Problem and +// 2) it has the same ID (i.e. it is the same problem scenario). +func (e *SDKProblem) Is(target error) bool { + return is(target, e.GetID()) +} + +// GetConsoleOrderedMaps returns an ordered-map representation +// of an SDKProblem instance suited for a console message. +func (e *SDKProblem) GetConsoleOrderedMaps() *OrderedMaps { + orderedMaps := NewOrderedMaps() + + orderedMaps.Add("id", e.GetID()) + orderedMaps.Add("summary", e.Summary) + orderedMaps.Add("severity", e.Severity) + orderedMaps.Add("function", e.Function) + orderedMaps.Add("component", e.Component) + + return orderedMaps +} + +// GetDebugOrderedMaps returns an ordered-map representation +// of an SDKProblem instance, with additional information +// suited for a debug message. +func (e *SDKProblem) GetDebugOrderedMaps() *OrderedMaps { + orderedMaps := e.GetConsoleOrderedMaps() + + orderedMaps.Add("stack", e.stack) + + if e.coreProblem != nil { + orderedMaps.Add("core_problem", e.coreProblem) + } + + var orderableCausedBy OrderableProblem + if errors.As(e.GetCausedBy(), &orderableCausedBy) { + orderedMaps.Add("caused_by", orderableCausedBy.GetDebugOrderedMaps().GetMaps()) + } + + return orderedMaps +} + +// SDKErrorf creates and returns a new instance of "SDKProblem" with "error" level severity. +func SDKErrorf(err error, summary, discriminator string, component *ProblemComponent) *SDKProblem { + function := computeFunctionName(component.Name) + stack := getStackInfo(component.Name) + + ibmProb := IBMErrorf(err, component, summary, discriminator) + newSDKProb := &SDKProblem{ + IBMProblem: ibmProb, + Function: function, + stack: stack, + } + + // Flatten chains of SDKProblem instances in order to present a single, + // unique error scenario for the SDK context. Multiple Golang components + // can invoke each other, but we only want to track "caused by" problems + // through context boundaries (like API, SDK, Terraform, etc.). This + // eliminates unnecessary granularity of problem scenarios for the SDK + // context. If the problem originated in this library (the Go SDK Core), + // we still want to track that info for debugging purposes. + var sdkCausedBy *SDKProblem + if errors.As(err, &sdkCausedBy) { + // Not a "native" caused by but allows us to maintain compatibility through "Unwrap". + newSDKProb.nativeCausedBy = sdkCausedBy + newSDKProb.causedBy = nil + + if isCoreProblem(sdkCausedBy) { + newSDKProb.coreProblem = newSparseSDKProblem(sdkCausedBy) + + // If we stored an HTTPProblem instance in the core, we'll want to use + // it as the actual "caused by" problem for the new SDK problem. + if sdkCausedBy.httpProblem != nil { + newSDKProb.causedBy = sdkCausedBy.httpProblem + } + } + } + + // We can't use HTTPProblem instances as "caused by" problems for Go SDK Core + // problems because 1) it prevents us from enumerating hashes in the core and + // 2) core problems will almost never be the instances that users interact with + // and the HTTPProblem will need to be used as the "caused by" of the problems + // coming from actual service SDK libraries. + var httpCausedBy *HTTPProblem + if errors.As(err, &httpCausedBy) && isCoreProblem(newSDKProb) { + newSDKProb.httpProblem = httpCausedBy + newSDKProb.causedBy = nil + } + + return newSDKProb +} + +// RepurposeSDKProblem provides a convenient way to take a problem from +// another function in the same component and contextualize it to the current +// function. Should only be used in public (exported) functions. +func RepurposeSDKProblem(err error, discriminator string) error { + if err == nil { + return nil + } + + // It only makes sense to carry out this logic with SDK Errors. + var sdkErr *SDKProblem + if !errors.As(err, &sdkErr) { + return err + } + + // Special behavior to allow SDK problems coming from a method that wraps a + // "*WithContext" method to maintain the discriminator of the originating + // problem. Otherwise, we would lose all of that data in the wrap. + if discriminator != "" { + sdkErr.discriminator = discriminator + } + + // Recompute the function to reflect this public boundary (but let the stack + // remain as it is - it is the path to the original problem origination point). + sdkErr.Function = computeFunctionName(sdkErr.Component.Name) + + return sdkErr +} diff --git a/vendor/github.com/IBM/go-sdk-core/v5/core/sdk_problem_utils.go b/vendor/github.com/IBM/go-sdk-core/v5/core/sdk_problem_utils.go new file mode 100644 index 0000000000..4883833375 --- /dev/null +++ b/vendor/github.com/IBM/go-sdk-core/v5/core/sdk_problem_utils.go @@ -0,0 +1,124 @@ +package core + +// (C) Copyright IBM Corp. 2024. +// +// 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. + +import ( + "runtime" + "strings" +) + +// computeFunctionName investigates the program counter at a fixed +// skip number (aka point in the stack) of 2, which gives us the +// information about the function the problem was created in, and +// returns the name of the function. +func computeFunctionName(componentName string) string { + if pc, _, _, ok := runtime.Caller(2); ok { + // The function names will have the component name as a prefix. + // To avoid redundancy, since we are including the component name + // with the problem, trim that prefix here. + return strings.TrimPrefix(runtime.FuncForPC(pc).Name(), componentName+"/") + } + + return "" +} + +// sdkStackFrame is a convenience struct for formatting +// frame data to be printed as YAML. +type sdkStackFrame struct { + Function string + File string + Line int +} + +// getStackInfo invokes helper methods to curate a limited, formatted +// version of the stack trace with only the component-scoped function +// invocations that lead to the creation of the problem. +func getStackInfo(componentName string) []sdkStackFrame { + if frames, ok := makeFrames(); ok { + return formatFrames(frames, componentName) + } + + return nil +} + +// makeFrames populates a program counter list with data at a +// fixed skip number (4), which gives us the stack information +// at the point in the program that the problem was created. This +// function adjusts the list as needed, since the necessary +// list size is not known at first. +func makeFrames() ([]uintptr, bool) { + pcs := make([]uintptr, 10) + for { + n := runtime.Callers(4, pcs) + if n == 0 { + return pcs, false + } + if n < len(pcs) { + return pcs[:n], true + } + pcs = make([]uintptr, 2*len(pcs)) + } +} + +// formatFrames takes a program counter list and formats them +// into a readable format for including in debug messages. +func formatFrames(pcs []uintptr, componentName string) []sdkStackFrame { + result := make([]sdkStackFrame, 0) + + if len(pcs) == 0 { + return result + } + + // Loop to get frames. + // A fixed number of PCs can expand to an indefinite number of Frames. + frames := runtime.CallersFrames(pcs) + for { + frame, more := frames.Next() + + // Only the frames in the same component as the problem are relevant. + if strings.HasPrefix(frame.Function, componentName) { + stackFrame := sdkStackFrame{ + Function: frame.Function, + File: frame.File, + Line: frame.Line, + } + + result = append(result, stackFrame) + } + + // Check whether there are more frames to process after this one. + if !more { + break + } + } + + return result +} + +type sparseSDKProblem struct { + ID string + Function string +} + +func newSparseSDKProblem(prob *SDKProblem) *sparseSDKProblem { + return &sparseSDKProblem{ + ID: prob.GetID(), + Function: prob.Function, + } +} + +func isCoreProblem(prob *SDKProblem) bool { + return prob.Component != nil && prob.Component.Name == MODULE_NAME +} diff --git a/vendor/github.com/IBM/go-sdk-core/v5/core/unmarshal_v2.go b/vendor/github.com/IBM/go-sdk-core/v5/core/unmarshal_v2.go index c46a40d019..f25cce88d0 100644 --- a/vendor/github.com/IBM/go-sdk-core/v5/core/unmarshal_v2.go +++ b/vendor/github.com/IBM/go-sdk-core/v5/core/unmarshal_v2.go @@ -79,6 +79,7 @@ const ( func UnmarshalPrimitive(rawInput map[string]json.RawMessage, propertyName string, result interface{}) (err error) { if propertyName == "" { err = fmt.Errorf(errorPropertyNameMissing) + err = SDKErrorf(err, "", "no-prop-name", getComponentInfo()) } rawMsg, foundIt := rawInput[propertyName] @@ -86,6 +87,7 @@ func UnmarshalPrimitive(rawInput map[string]json.RawMessage, propertyName string err = json.Unmarshal(rawMsg, result) if err != nil { err = fmt.Errorf(errorUnmarshalPrimitive, propertyName, err.Error()) + err = SDKErrorf(err, "", "json-unmarshal-error", getComponentInfo()) } } return @@ -188,6 +190,7 @@ func UnmarshalModel(rawInput interface{}, propertyName string, result interface{ // Make sure some input is provided. Otherwise return an error. if IsNil(rawInput) { err = fmt.Errorf(errorUnmarshallInputIsNil) + err = SDKErrorf(err, "", "no-input", getComponentInfo()) return } @@ -221,10 +224,12 @@ func UnmarshalModel(rawInput interface{}, propertyName string, result interface{ default: err = fmt.Errorf(errorUnsupportedResultType, rResultType.String()) + err = SDKErrorf(err, "", "bad-slice-elem-slice-type", getComponentInfo()) } default: err = fmt.Errorf(errorUnsupportedResultType, rResultType.String()) + err = SDKErrorf(err, "", "bad-slice-elem-type", getComponentInfo()) return } @@ -246,17 +251,23 @@ func UnmarshalModel(rawInput interface{}, propertyName string, result interface{ default: err = fmt.Errorf(errorUnsupportedResultType, rResultType.String()) + err = SDKErrorf(err, "", "bad-slice-elem-map-type", getComponentInfo()) return } default: err = fmt.Errorf(errorUnsupportedResultType, rResultType.String()) + err = SDKErrorf(err, "", "bad-map-entry-type", getComponentInfo()) return } default: err = fmt.Errorf(errorUnsupportedResultType, rResultType.String()) + err = SDKErrorf(err, "", "bad-model-type", getComponentInfo()) return } + + err = RepurposeSDKProblem(err, "unmarshal-fail") + return } @@ -282,6 +293,7 @@ func unmarshalModelInstance(rawInput interface{}, propertyName string, result in foundInput, rawMap, err = getUnmarshalInputSourceMap(rawInput, propertyName) if err != nil { err = fmt.Errorf(errorUnmarshalModel, propInsert(propertyName), getModelResultType(result), err.Error()) + err = SDKErrorf(err, "", "input-source-error", getComponentInfo()) return } @@ -299,6 +311,7 @@ func unmarshalModelInstance(rawInput interface{}, propertyName string, result in err = unmarshaller(rawMap, result) if err != nil { err = fmt.Errorf(errorUnmarshalModel, propInsert(propertyName), getModelResultType(result), err.Error()) + err = SDKErrorf(err, "", "unmarshaller-error", getComponentInfo()) return } } @@ -336,6 +349,7 @@ func unmarshalModelSlice(rawInput interface{}, propertyName string, result inter if err != nil { err = fmt.Errorf(errorUnmarshalModel, propInsert(propertyName), reflect.TypeOf(result).Elem().String(), err.Error()) + err = SDKErrorf(err, "", "input-source-error", getComponentInfo()) return } @@ -363,6 +377,7 @@ func unmarshalModelSlice(rawInput interface{}, propertyName string, result inter if err != nil { err = fmt.Errorf(errorUnmarshalModel, propInsert(propertyName), reflect.TypeOf(result).Elem().String(), err.Error()) + err = SDKErrorf(err, "", "result-type-error", getComponentInfo()) return } @@ -373,6 +388,7 @@ func unmarshalModelSlice(rawInput interface{}, propertyName string, result inter if err != nil { err = fmt.Errorf(errorUnmarshalModel, propInsert(propertyName), reflect.TypeOf(result).Elem().String(), err.Error()) + err = SDKErrorf(err, "", "json-unmarshal-error", getComponentInfo()) return } @@ -384,6 +400,7 @@ func unmarshalModelSlice(rawInput interface{}, propertyName string, result inter if err != nil { err = fmt.Errorf(errorUnmarshalModel, propInsert(propertyName), reflect.TypeOf(result).Elem().String(), err.Error()) + err = SDKErrorf(err, "", "unmarshaller-error", getComponentInfo()) return } @@ -425,6 +442,7 @@ func unmarshalModelSliceSlice(rawInput interface{}, propertyName string, result if err != nil { err = fmt.Errorf(errorUnmarshalModel, propInsert(propertyName), reflect.TypeOf(result).Elem().String(), err.Error()) + err = SDKErrorf(err, "", "input-source-error", getComponentInfo()) return } @@ -455,6 +473,7 @@ func unmarshalModelSliceSlice(rawInput interface{}, propertyName string, result if err != nil { err = fmt.Errorf(errorUnmarshalModel, propInsert(propertyName), reflect.TypeOf(result).Elem().String(), err.Error()) + err = SDKErrorf(err, "", "json-unmarshal-error", getComponentInfo()) return } @@ -466,6 +485,7 @@ func unmarshalModelSliceSlice(rawInput interface{}, propertyName string, result if err != nil { err = fmt.Errorf(errorUnmarshalModel, propInsert(propertyName), reflect.TypeOf(result).Elem().String(), err.Error()) + err = SDKErrorf(err, "", "unmarshaller-error", getComponentInfo()) return } @@ -500,6 +520,7 @@ func unmarshalModelMap(rawInput interface{}, propertyName string, result interfa if err != nil { err = fmt.Errorf(errorUnmarshalModel, propInsert(propertyName), reflect.TypeOf(result).Elem().String(), err.Error()) + err = SDKErrorf(err, "", "input-source-error", getComponentInfo()) return } @@ -520,6 +541,7 @@ func unmarshalModelMap(rawInput interface{}, propertyName string, result interfa if err != nil { err = fmt.Errorf(errorUnmarshalModel, propInsert(propertyName), reflect.TypeOf(result).Elem().String(), err.Error()) + err = SDKErrorf(err, "", "result-type-error", getComponentInfo()) return } @@ -531,6 +553,7 @@ func unmarshalModelMap(rawInput interface{}, propertyName string, result interfa if err != nil { err = fmt.Errorf(errorUnmarshalModel, propInsert(propertyName), reflect.TypeOf(result).Elem().String(), err.Error()) + err = SDKErrorf(err, "", "json-unmarshal-error", getComponentInfo()) return } @@ -542,6 +565,7 @@ func unmarshalModelMap(rawInput interface{}, propertyName string, result interfa if err != nil { err = fmt.Errorf(errorUnmarshalModel, propInsert(propertyName), reflect.TypeOf(result).Elem().String(), err.Error()) + err = SDKErrorf(err, "", "unmarshaller-error", getComponentInfo()) return } @@ -577,6 +601,7 @@ func unmarshalModelSliceMap(rawInput interface{}, propertyName string, result in if err != nil { err = fmt.Errorf(errorUnmarshalModel, propInsert(propertyName), reflect.TypeOf(result).Elem().String(), err.Error()) + err = SDKErrorf(err, "", "input-source-error", getComponentInfo()) return } @@ -601,6 +626,7 @@ func unmarshalModelSliceMap(rawInput interface{}, propertyName string, result in if err != nil { err = fmt.Errorf(errorUnmarshalModel, propInsert(propertyName), reflect.TypeOf(result).Elem().String(), err.Error()) + err = SDKErrorf(err, "", "json-unmarshal-error", getComponentInfo()) return } @@ -612,6 +638,7 @@ func unmarshalModelSliceMap(rawInput interface{}, propertyName string, result in if err != nil { err = fmt.Errorf(errorUnmarshalModel, propInsert(propertyName), reflect.TypeOf(result).Elem().String(), err.Error()) + err = SDKErrorf(err, "", "unmarshaller-error", getComponentInfo()) return } @@ -639,6 +666,7 @@ func getUnmarshalInputSourceMap(rawInput interface{}, propertyName string) (foun if !ok { foundInput = false err = fmt.Errorf(errorIncorrectInputType, "map[string]json.RawMessage", reflect.TypeOf(rawInput).String()) + err = SDKErrorf(err, "", "non-json-source-map", getComponentInfo()) return } @@ -654,6 +682,7 @@ func getUnmarshalInputSourceMap(rawInput interface{}, propertyName string) (foun err = json.Unmarshal(rawMsg, &rawMap) if err != nil { foundInput = false + err = SDKErrorf(err, "", "json-unmarshal-error", getComponentInfo()) return } } @@ -681,6 +710,7 @@ func getUnmarshalInputSourceSlice(rawInput interface{}, propertyName string) (fo rawMap, ok := rawInput.(map[string]json.RawMessage) if !ok { err = fmt.Errorf(errorIncorrectInputType, "map[string]json.RawMessage", reflect.TypeOf(rawInput).String()) + err = SDKErrorf(err, "", "raw-input-error", getComponentInfo()) return } @@ -696,6 +726,7 @@ func getUnmarshalInputSourceSlice(rawInput interface{}, propertyName string) (fo err = json.Unmarshal(rawMsg, &rawSlice) if err != nil { err = fmt.Errorf(errorIncorrectInputType, "map[string][]json.RawMessage", reflect.TypeOf(rawInput).String()) + err = SDKErrorf(err, "", "json-unmarshal-error", getComponentInfo()) return } @@ -708,6 +739,7 @@ func getUnmarshalInputSourceSlice(rawInput interface{}, propertyName string) (fo rawSlice, ok := rawInput.([]json.RawMessage) if !ok { err = fmt.Errorf(errorIncorrectInputType, "[]json.RawMessage", reflect.TypeOf(rawInput).String()) + err = SDKErrorf(err, "", "no-name-raw-input-error", getComponentInfo()) return } @@ -748,6 +780,7 @@ func getUnmarshalResultType(result interface{}) (ptrType reflect.Type, err error default: err = fmt.Errorf(errorUnsupportedResultType, rResultType.String()) + err = SDKErrorf(err, "", "unsupported-type", getComponentInfo()) } return } diff --git a/vendor/github.com/IBM/go-sdk-core/v5/core/utils.go b/vendor/github.com/IBM/go-sdk-core/v5/core/utils.go index 070cae669f..e0426a1414 100644 --- a/vendor/github.com/IBM/go-sdk-core/v5/core/utils.go +++ b/vendor/github.com/IBM/go-sdk-core/v5/core/utils.go @@ -16,7 +16,6 @@ package core import ( "encoding/json" - "errors" "fmt" "net/url" "os" @@ -60,7 +59,8 @@ func IsNil(object interface{}) bool { // ValidateNotNil returns the specified error if 'object' is nil, nil otherwise. func ValidateNotNil(object interface{}, errorMsg string) error { if IsNil(object) { - return errors.New(errorMsg) + err := fmt.Errorf(errorMsg) + return SDKErrorf(err, "", "obj-is-nil", getComponentInfo()) } return nil } @@ -70,6 +70,7 @@ func ValidateNotNil(object interface{}, errorMsg string) error { func ValidateStruct(param interface{}, paramName string) error { err := ValidateNotNil(param, paramName+" cannot be nil") if err != nil { + err = RepurposeSDKProblem(err, "struct-is-nil") return err } @@ -77,9 +78,10 @@ func ValidateStruct(param interface{}, paramName string) error { if err != nil { // If there were validation errors then return an error containing the field errors if fieldErrors, ok := err.(validator.ValidationErrors); ok { - return fmt.Errorf("%s failed validation:\n%s", paramName, fieldErrors.Error()) + err = fmt.Errorf("%s failed validation:\n%s", paramName, fieldErrors.Error()) + return SDKErrorf(err, "", "struct-validation-errors", getComponentInfo()) } - return err + return SDKErrorf(err, "", "struct-validate-unknown-error", getComponentInfo()) } return nil @@ -206,6 +208,7 @@ func ConvertSlice(slice interface{}) (s []string, err error) { if IsNil(slice) { err = fmt.Errorf(ERRORMSG_NIL_SLICE) + err = SDKErrorf(err, "", "nil-slice", getComponentInfo()) return } @@ -221,6 +224,7 @@ func ConvertSlice(slice interface{}) (s []string, err error) { // If it's not a slice, just return an error if !inputIsSlice { err = fmt.Errorf(ERRORMSG_PARAM_NOT_SLICE) + err = SDKErrorf(err, "", "param-not-slice", getComponentInfo()) return } else if reflect.ValueOf(slice).Len() == 0 { s = []string{} @@ -230,6 +234,7 @@ func ConvertSlice(slice interface{}) (s []string, err error) { jsonBuffer, err := json.Marshal(slice) if err != nil { err = fmt.Errorf(ERRORMSG_MARSHAL_SLICE, err.Error()) + err = SDKErrorf(err, "", "slice-marshal-error", getComponentInfo()) return } @@ -258,7 +263,8 @@ func ConvertSlice(slice interface{}) (s []string, err error) { return } - return nil, fmt.Errorf(ERRORMSG_CONVERT_SLICE) + err = fmt.Errorf(ERRORMSG_CONVERT_SLICE) + return nil, SDKErrorf(err, "", "cant-convert-slice", getComponentInfo()) } // SliceContains returns true iff "contains" is an element of "slice" @@ -280,11 +286,13 @@ func GetQueryParam(urlStr *string, param string) (value *string, err error) { urlObj, err := url.Parse(*urlStr) if err != nil { + err = SDKErrorf(err, "", "url-parse-error", getComponentInfo()) return } query, err := url.ParseQuery(urlObj.RawQuery) if err != nil { + err = SDKErrorf(err, "", "url-parse-query-error", getComponentInfo()) return } @@ -302,12 +310,18 @@ func GetQueryParam(urlStr *string, param string) (value *string, err error) { // converted to an int64 value, or nil if not found. func GetQueryParamAsInt(urlStr *string, param string) (value *int64, err error) { strValue, err := GetQueryParam(urlStr, param) - if err != nil || strValue == nil { + if err != nil { + err = RepurposeSDKProblem(err, "get-query-error") + return + } + + if strValue == nil { return } intValue, err := strconv.ParseInt(*strValue, 10, 64) if err != nil { + err = SDKErrorf(err, "", "parse-int-query-error", getComponentInfo()) return nil, err } diff --git a/vendor/github.com/IBM/go-sdk-core/v5/core/version.go b/vendor/github.com/IBM/go-sdk-core/v5/core/version.go index 5be9fefb70..b786918038 100644 --- a/vendor/github.com/IBM/go-sdk-core/v5/core/version.go +++ b/vendor/github.com/IBM/go-sdk-core/v5/core/version.go @@ -15,4 +15,4 @@ package core // limitations under the License. // Version of the SDK -const __VERSION__ = "5.14.1" +const __VERSION__ = "5.17.4" diff --git a/vendor/github.com/IBM/go-sdk-core/v5/core/vpc_instance_authenticator.go b/vendor/github.com/IBM/go-sdk-core/v5/core/vpc_instance_authenticator.go index e3f3c77755..562318b2ce 100644 --- a/vendor/github.com/IBM/go-sdk-core/v5/core/vpc_instance_authenticator.go +++ b/vendor/github.com/IBM/go-sdk-core/v5/core/vpc_instance_authenticator.go @@ -1,6 +1,6 @@ package core -// (C) Copyright IBM Corp. 2021, 2023. +// (C) Copyright IBM Corp. 2021, 2024. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,7 +15,6 @@ package core // limitations under the License. import ( - "bytes" "encoding/json" "fmt" "net/http" @@ -59,6 +58,10 @@ type VpcInstanceAuthenticator struct { Client *http.Client clientInit sync.Once + // The User-Agent header value to be included with each token request. + userAgent string + userAgentInit sync.Once + // The cached IAM access token and its expiration time. tokenData *iamTokenData @@ -117,7 +120,7 @@ func (builder *VpcInstanceAuthenticatorBuilder) Build() (*VpcInstanceAuthenticat // Make sure the config is valid. err := builder.VpcInstanceAuthenticator.Validate() if err != nil { - return nil, err + return nil, RepurposeSDKProblem(err, "validation-failed") } return &builder.VpcInstanceAuthenticator, nil @@ -134,6 +137,14 @@ func (authenticator *VpcInstanceAuthenticator) client() *http.Client { return authenticator.Client } +// getUserAgent returns the User-Agent header value to be included in each token request invoked by the authenticator. +func (authenticator *VpcInstanceAuthenticator) getUserAgent() string { + authenticator.userAgentInit.Do(func() { + authenticator.userAgent = fmt.Sprintf("%s/%s-%s %s", sdkName, "vpc-instance-authenticator", __VERSION__, SystemInfo()) + }) + return authenticator.userAgent +} + // url returns the authenticator's URL property after potentially initializing it. func (authenticator *VpcInstanceAuthenticator) url() string { authenticator.urlInit.Do(func() { @@ -148,7 +159,8 @@ func (authenticator *VpcInstanceAuthenticator) url() string { // configuration properties. func newVpcInstanceAuthenticatorFromMap(properties map[string]string) (authenticator *VpcInstanceAuthenticator, err error) { if properties == nil { - return nil, fmt.Errorf(ERRORMSG_PROPS_MAP_NIL) + err = fmt.Errorf(ERRORMSG_PROPS_MAP_NIL) + return nil, SDKErrorf(err, "", "missing-props", getComponentInfo()) } authenticator, err = NewVpcInstanceAuthenticatorBuilder(). @@ -173,7 +185,7 @@ func (*VpcInstanceAuthenticator) AuthenticationType() string { func (authenticator *VpcInstanceAuthenticator) Authenticate(request *http.Request) error { token, err := authenticator.GetToken() if err != nil { - return err + return RepurposeSDKProblem(err, "get-token-fail") } request.Header.Set("Authorization", "Bearer "+token) @@ -204,7 +216,8 @@ func (authenticator *VpcInstanceAuthenticator) Validate() error { // Check to make sure that at most one of IAMProfileCRN or IAMProfileID are specified. if authenticator.IAMProfileCRN != "" && authenticator.IAMProfileID != "" { - return fmt.Errorf(ERRORMSG_ATMOST_ONE_PROP_ERROR, "IAMProfileCRN", "IAMProfileID") + err := fmt.Errorf(ERRORMSG_ATMOST_ONE_PROP_ERROR, "IAMProfileCRN", "IAMProfileID") + return SDKErrorf(err, "", "both-props", getComponentInfo()) } return nil @@ -219,7 +232,7 @@ func (authenticator *VpcInstanceAuthenticator) GetToken() (string, error) { // synchronously request the token err := authenticator.synchronizedRequestToken() if err != nil { - return "", err + return "", RepurposeSDKProblem(err, "request-token-fail") } } else if authenticator.getTokenData().needsRefresh() { GetLogger().Debug("Performing background asynchronous token fetch...") @@ -232,7 +245,8 @@ func (authenticator *VpcInstanceAuthenticator) GetToken() (string, error) { // return an error if the access token is not valid or was not fetched if authenticator.getTokenData() == nil || authenticator.getTokenData().AccessToken == "" { - return "", fmt.Errorf("Error while trying to get access token") + err := fmt.Errorf("Error while trying to get access token") + return "", SDKErrorf(err, "", "no-token", getComponentInfo()) } return authenticator.getTokenData().AccessToken, nil @@ -281,12 +295,14 @@ func (authenticator *VpcInstanceAuthenticator) RequestToken() (iamTokenResponse // Retrieve the instance identity token from the VPC Instance Metadata Service. instanceIdentityToken, err := authenticator.retrieveInstanceIdentityToken() if err != nil { + err = RepurposeSDKProblem(err, "get-ii-token-error") return } // Next, exchange the instance identity token for an IAM access token. iamTokenResponse, err = authenticator.retrieveIamAccessToken(instanceIdentityToken) if err != nil { + err = RepurposeSDKProblem(err, "get-ia-token-error") return } @@ -320,7 +336,7 @@ func (authenticator *VpcInstanceAuthenticator) retrieveIamAccessToken( builder := NewRequestBuilder(POST) _, err = builder.ResolveRequestURL(authenticator.url(), vpcauthOperationPathCreateIamToken, nil) if err != nil { - err = NewAuthenticationError(&DetailedResponse{}, err) + err = authenticationErrorf(err, &DetailedResponse{}, "noop", getComponentInfo()) return } @@ -328,6 +344,7 @@ func (authenticator *VpcInstanceAuthenticator) retrieveIamAccessToken( builder.AddQuery("version", vpcauthMetadataServiceVersion) builder.AddHeader(CONTENT_TYPE, APPLICATION_JSON) builder.AddHeader(Accept, APPLICATION_JSON) + builder.AddHeader(headerNameUserAgent, authenticator.getUserAgent()) builder.AddHeader("Authorization", "Bearer "+instanceIdentityToken) // Next, construct the optional request body to specify the linked IAM profile. @@ -348,7 +365,7 @@ func (authenticator *VpcInstanceAuthenticator) retrieveIamAccessToken( // Build the request. req, err := builder.Build() if err != nil { - return nil, NewAuthenticationError(&DetailedResponse{}, err) + return nil, authenticationErrorf(err, &DetailedResponse{}, "noop", getComponentInfo()) } // If debug is enabled, then dump the request. @@ -364,7 +381,7 @@ func (authenticator *VpcInstanceAuthenticator) retrieveIamAccessToken( GetLogger().Debug("Invoking VPC 'create_iam_token' operation: %s", builder.URL) resp, err := authenticator.client().Do(req) if err != nil { - return nil, NewAuthenticationError(&DetailedResponse{}, err) + return nil, authenticationErrorf(err, &DetailedResponse{}, "noop", getComponentInfo()) } GetLogger().Debug("Returned from VPC 'create_iam_token' operation, received status code %d", resp.StatusCode) @@ -380,23 +397,23 @@ func (authenticator *VpcInstanceAuthenticator) retrieveIamAccessToken( // Check for a bad status code and handle an operation error. if resp.StatusCode < 200 || resp.StatusCode >= 300 { - buff := new(bytes.Buffer) - _, _ = buff.ReadFrom(resp.Body) - resp.Body.Close() // #nosec G104 - - // Create a DetailedResponse to be included in the error below. - detailedResponse := &DetailedResponse{ - StatusCode: resp.StatusCode, - Headers: resp.Header, - RawResult: buff.Bytes(), + detailedResponse, responseError := processErrorResponse(resp) + err = authenticationErrorf(responseError, detailedResponse, "create_iam_token", authenticator.getComponentInfo()) + + // The err Summary is typically the message computed for the HTTPError instance in + // processErrorResponse(). If the response body is non-JSON, the message will be generic + // text based on the status code but authenticators have always used the stringified + // RawResult, so update that here for compatilibility. + vpcErrorMsg := responseError.Summary + if detailedResponse.RawResult != nil { + // RawResult is only populated if the response body is + // non-JSON and we couldn't extract a message. + vpcErrorMsg = string(detailedResponse.RawResult) } - vpcErrorMsg := string(detailedResponse.RawResult) - if vpcErrorMsg == "" { - vpcErrorMsg = "Operation 'create_iam_token' error response not available" - } - err = fmt.Errorf(ERRORMSG_VPCMDS_OPERATION_ERROR, detailedResponse.StatusCode, builder.URL, vpcErrorMsg) - return nil, NewAuthenticationError(detailedResponse, err) + err.(*AuthenticationError).Summary = fmt.Sprintf(ERRORMSG_VPCMDS_OPERATION_ERROR, detailedResponse.StatusCode, builder.URL, vpcErrorMsg) + + return } // Good response, so unmarshal the response body into a vpcTokenResponse instance. @@ -423,7 +440,7 @@ func (authenticator *VpcInstanceAuthenticator) retrieveInstanceIdentityToken() ( builder := NewRequestBuilder(PUT) _, err = builder.ResolveRequestURL(authenticator.url(), vpcauthOperationPathCreateAccessToken, nil) if err != nil { - err = NewAuthenticationError(&DetailedResponse{}, err) + err = authenticationErrorf(err, &DetailedResponse{}, "noop", getComponentInfo()) return } @@ -439,7 +456,7 @@ func (authenticator *VpcInstanceAuthenticator) retrieveInstanceIdentityToken() ( // Build the request. req, err := builder.Build() if err != nil { - err = NewAuthenticationError(&DetailedResponse{}, err) + err = authenticationErrorf(err, &DetailedResponse{}, "noop", getComponentInfo()) return } @@ -457,7 +474,7 @@ func (authenticator *VpcInstanceAuthenticator) retrieveInstanceIdentityToken() ( GetLogger().Debug("Invoking VPC 'create_access_token' operation: %s", builder.URL) resp, err := authenticator.client().Do(req) if err != nil { - err = NewAuthenticationError(&DetailedResponse{}, err) + err = authenticationErrorf(err, &DetailedResponse{}, "noop", getComponentInfo()) return } GetLogger().Debug("Returned from VPC 'create_access_token' operation, received status code %d", resp.StatusCode) @@ -474,24 +491,22 @@ func (authenticator *VpcInstanceAuthenticator) retrieveInstanceIdentityToken() ( // Check for a bad status code and handle the operation error. if resp.StatusCode < 200 || resp.StatusCode >= 300 { - buff := new(bytes.Buffer) - _, _ = buff.ReadFrom(resp.Body) - resp.Body.Close() // #nosec G104 - - // Create a DetailedResponse to be included in the error below. - detailedResponse := &DetailedResponse{ - StatusCode: resp.StatusCode, - Headers: resp.Header, - RawResult: buff.Bytes(), + detailedResponse, responseError := processErrorResponse(resp) + err = authenticationErrorf(responseError, detailedResponse, "create_access_token", authenticator.getComponentInfo()) + + // The err Summary is typically the message computed for the HTTPError instance in + // processErrorResponse(). If the response body is non-JSON, the message will be generic + // text based on the status code but authenticators have always used the stringified + // RawResult, so update that here for compatilibility. + vpcErrorMsg := responseError.Summary + if detailedResponse.RawResult != nil { + // RawResult is only populated if the response body is + // non-JSON and we couldn't extract a message. + vpcErrorMsg = string(detailedResponse.RawResult) } - vpcErrorMsg := string(detailedResponse.RawResult) - if vpcErrorMsg == "" { - vpcErrorMsg = "Operation 'create_access_token' error response not available" - } + err.(*AuthenticationError).Summary = fmt.Sprintf(ERRORMSG_VPCMDS_OPERATION_ERROR, detailedResponse.StatusCode, builder.URL, vpcErrorMsg) - err = NewAuthenticationError(detailedResponse, - fmt.Errorf(ERRORMSG_VPCMDS_OPERATION_ERROR, detailedResponse.StatusCode, builder.URL, vpcErrorMsg)) return } @@ -506,3 +521,10 @@ func (authenticator *VpcInstanceAuthenticator) retrieveInstanceIdentityToken() ( return } + +// This should only be used for AuthenticationError instances that actually deal with +// an HTTP error (i.e. do not have a blank DetailedResponse object - they can be scoped +// to the SDK core system). +func (authenticator *VpcInstanceAuthenticator) getComponentInfo() *ProblemComponent { + return NewProblemComponent("vpc_instance_metadata", vpcauthMetadataServiceVersion) +} diff --git a/vendor/github.com/IBM/platform-services-go-sdk/common/headers.go b/vendor/github.com/IBM/platform-services-go-sdk/common/headers.go index 44afd10cad..fadd6b2a51 100644 --- a/vendor/github.com/IBM/platform-services-go-sdk/common/headers.go +++ b/vendor/github.com/IBM/platform-services-go-sdk/common/headers.go @@ -1,5 +1,5 @@ /** - * (C) Copyright IBM Corp. 2020. + * (C) Copyright IBM Corp. 2020 - 2024. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,14 +19,15 @@ package common import ( "fmt" "runtime" + + "github.com/IBM/go-sdk-core/v5/core" ) const ( - sdkName = "platform-services-go-sdk" + sdkName = "platform-services-go-sdk" headerNameUserAgent = "User-Agent" ) -// // GetSdkHeaders - returns the set of SDK-specific headers to be included in an outgoing request. // // This function is invoked by generated service methods (i.e. methods which implement the REST API operations @@ -40,13 +41,14 @@ const ( // as in the example below. // // Parameters: -// serviceName - the name of the service as defined in the API definition (e.g. "MyService1") -// serviceVersion - the version of the service as defined in the API definition (e.g. "V1") -// operationId - the operationId as defined in the API definition (e.g. getContext) +// +// serviceName - the name of the service as defined in the API definition (e.g. "MyService1") +// serviceVersion - the version of the service as defined in the API definition (e.g. "V1") +// operationId - the operationId as defined in the API definition (e.g. getContext) // // Returns: -// a Map which contains the set of headers to be included in the REST API request // +// a Map which contains the set of headers to be included in the REST API request func GetSdkHeaders(serviceName string, serviceVersion string, operationId string) map[string]string { sdkHeaders := make(map[string]string) sdkHeaders[headerNameUserAgent] = GetUserAgentInfo() @@ -64,3 +66,8 @@ var systemInfo = fmt.Sprintf("(lang=go; arch=%s; os=%s; go.version=%s)", runtime func GetSystemInfo() string { return systemInfo } + +func GetComponentInfo() *core.ProblemComponent { + // This should match the module name in go.mod. + return core.NewProblemComponent("github.com/IBM/platform-services-go-sdk", Version) +} diff --git a/vendor/github.com/IBM/platform-services-go-sdk/common/version.go b/vendor/github.com/IBM/platform-services-go-sdk/common/version.go index 862d731aa5..abae4886b7 100644 --- a/vendor/github.com/IBM/platform-services-go-sdk/common/version.go +++ b/vendor/github.com/IBM/platform-services-go-sdk/common/version.go @@ -17,4 +17,4 @@ package common // Version of the SDK -const Version = "0.55.0" +const Version = "0.67.0" diff --git a/vendor/github.com/IBM/platform-services-go-sdk/resourcecontrollerv2/resource_controller_v2.go b/vendor/github.com/IBM/platform-services-go-sdk/resourcecontrollerv2/resource_controller_v2.go index d52425641f..9193c13e73 100644 --- a/vendor/github.com/IBM/platform-services-go-sdk/resourcecontrollerv2/resource_controller_v2.go +++ b/vendor/github.com/IBM/platform-services-go-sdk/resourcecontrollerv2/resource_controller_v2.go @@ -1,5 +1,5 @@ /** - * (C) Copyright IBM Corp. 2023. + * (C) Copyright IBM Corp. 2024. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,7 +15,7 @@ */ /* - * IBM OpenAPI SDK Code Generator Version: 3.72.1-43bf8bf6-20230525-193151 + * IBM OpenAPI SDK Code Generator Version: 3.91.0-d9755c53-20240605-153412 */ // Package resourcecontrollerv2 : Operations and models for the ResourceControllerV2 service @@ -65,22 +65,26 @@ func NewResourceControllerV2UsingExternalConfig(options *ResourceControllerV2Opt if options.Authenticator == nil { options.Authenticator, err = core.GetAuthenticatorFromEnvironment(options.ServiceName) if err != nil { + err = core.SDKErrorf(err, "", "env-auth-error", common.GetComponentInfo()) return } } resourceController, err = NewResourceControllerV2(options) + err = core.RepurposeSDKProblem(err, "new-client-error") if err != nil { return } err = resourceController.Service.ConfigureService(options.ServiceName) if err != nil { + err = core.SDKErrorf(err, "", "client-config-error", common.GetComponentInfo()) return } if options.URL != "" { err = resourceController.Service.SetServiceURL(options.URL) + err = core.RepurposeSDKProblem(err, "url-set-error") } return } @@ -94,12 +98,14 @@ func NewResourceControllerV2(options *ResourceControllerV2Options) (service *Res baseService, err := core.NewBaseService(serviceOptions) if err != nil { + err = core.SDKErrorf(err, "", "new-base-error", common.GetComponentInfo()) return } if options.URL != "" { err = baseService.SetServiceURL(options.URL) if err != nil { + err = core.SDKErrorf(err, "", "set-url-error", common.GetComponentInfo()) return } } @@ -113,7 +119,7 @@ func NewResourceControllerV2(options *ResourceControllerV2Options) (service *Res // GetServiceURLForRegion returns the service URL to be used for the specified region func GetServiceURLForRegion(region string) (string, error) { - return "", fmt.Errorf("service does not support regional URLs") + return "", core.SDKErrorf(nil, "service does not support regional URLs", "no-regional-support", common.GetComponentInfo()) } // Clone makes a copy of "resourceController" suitable for processing requests. @@ -128,7 +134,11 @@ func (resourceController *ResourceControllerV2) Clone() *ResourceControllerV2 { // SetServiceURL sets the service URL func (resourceController *ResourceControllerV2) SetServiceURL(url string) error { - return resourceController.Service.SetServiceURL(url) + err := resourceController.Service.SetServiceURL(url) + if err != nil { + err = core.SDKErrorf(err, "", "url-set-error", common.GetComponentInfo()) + } + return err } // GetServiceURL returns the service URL @@ -166,13 +176,16 @@ func (resourceController *ResourceControllerV2) DisableRetries() { // View a list of all available resource instances. Resources is a broad term that could mean anything from a service // instance to a virtual machine associated with the customer account. func (resourceController *ResourceControllerV2) ListResourceInstances(listResourceInstancesOptions *ListResourceInstancesOptions) (result *ResourceInstancesList, response *core.DetailedResponse, err error) { - return resourceController.ListResourceInstancesWithContext(context.Background(), listResourceInstancesOptions) + result, response, err = resourceController.ListResourceInstancesWithContext(context.Background(), listResourceInstancesOptions) + err = core.RepurposeSDKProblem(err, "") + return } // ListResourceInstancesWithContext is an alternate form of the ListResourceInstances method which supports a Context parameter func (resourceController *ResourceControllerV2) ListResourceInstancesWithContext(ctx context.Context, listResourceInstancesOptions *ListResourceInstancesOptions) (result *ResourceInstancesList, response *core.DetailedResponse, err error) { err = core.ValidateStruct(listResourceInstancesOptions, "listResourceInstancesOptions") if err != nil { + err = core.SDKErrorf(err, "", "struct-validation-error", common.GetComponentInfo()) return } @@ -181,6 +194,7 @@ func (resourceController *ResourceControllerV2) ListResourceInstancesWithContext builder.EnableGzipCompression = resourceController.GetEnableGzipCompression() _, err = builder.ResolveRequestURL(resourceController.Service.Options.URL, `/v2/resource_instances`, nil) if err != nil { + err = core.SDKErrorf(err, "", "url-resolve-error", common.GetComponentInfo()) return } @@ -233,17 +247,21 @@ func (resourceController *ResourceControllerV2) ListResourceInstancesWithContext request, err := builder.Build() if err != nil { + err = core.SDKErrorf(err, "", "build-error", common.GetComponentInfo()) return } var rawResponse map[string]json.RawMessage response, err = resourceController.Service.Request(request, &rawResponse) if err != nil { + core.EnrichHTTPProblem(err, "list_resource_instances", getServiceComponentInfo()) + err = core.SDKErrorf(err, "", "http-request-err", common.GetComponentInfo()) return } if rawResponse != nil { err = core.UnmarshalModel(rawResponse, "", &result, UnmarshalResourceInstancesList) if err != nil { + err = core.SDKErrorf(err, "", "unmarshal-resp-error", common.GetComponentInfo()) return } response.Result = result @@ -256,17 +274,21 @@ func (resourceController *ResourceControllerV2) ListResourceInstancesWithContext // When you provision a service you get an instance of that service. An instance represents the resource with which you // create, and additionally, represents a chargeable record of which billing can occur. func (resourceController *ResourceControllerV2) CreateResourceInstance(createResourceInstanceOptions *CreateResourceInstanceOptions) (result *ResourceInstance, response *core.DetailedResponse, err error) { - return resourceController.CreateResourceInstanceWithContext(context.Background(), createResourceInstanceOptions) + result, response, err = resourceController.CreateResourceInstanceWithContext(context.Background(), createResourceInstanceOptions) + err = core.RepurposeSDKProblem(err, "") + return } // CreateResourceInstanceWithContext is an alternate form of the CreateResourceInstance method which supports a Context parameter func (resourceController *ResourceControllerV2) CreateResourceInstanceWithContext(ctx context.Context, createResourceInstanceOptions *CreateResourceInstanceOptions) (result *ResourceInstance, response *core.DetailedResponse, err error) { err = core.ValidateNotNil(createResourceInstanceOptions, "createResourceInstanceOptions cannot be nil") if err != nil { + err = core.SDKErrorf(err, "", "unexpected-nil-param", common.GetComponentInfo()) return } err = core.ValidateStruct(createResourceInstanceOptions, "createResourceInstanceOptions") if err != nil { + err = core.SDKErrorf(err, "", "struct-validation-error", common.GetComponentInfo()) return } @@ -275,6 +297,7 @@ func (resourceController *ResourceControllerV2) CreateResourceInstanceWithContex builder.EnableGzipCompression = resourceController.GetEnableGzipCompression() _, err = builder.ResolveRequestURL(resourceController.Service.Options.URL, `/v2/resource_instances`, nil) if err != nil { + err = core.SDKErrorf(err, "", "url-resolve-error", common.GetComponentInfo()) return } @@ -316,22 +339,27 @@ func (resourceController *ResourceControllerV2) CreateResourceInstanceWithContex } _, err = builder.SetBodyContentJSON(body) if err != nil { + err = core.SDKErrorf(err, "", "set-json-body-error", common.GetComponentInfo()) return } request, err := builder.Build() if err != nil { + err = core.SDKErrorf(err, "", "build-error", common.GetComponentInfo()) return } var rawResponse map[string]json.RawMessage response, err = resourceController.Service.Request(request, &rawResponse) if err != nil { + core.EnrichHTTPProblem(err, "create_resource_instance", getServiceComponentInfo()) + err = core.SDKErrorf(err, "", "http-request-err", common.GetComponentInfo()) return } if rawResponse != nil { err = core.UnmarshalModel(rawResponse, "", &result, UnmarshalResourceInstance) if err != nil { + err = core.SDKErrorf(err, "", "unmarshal-resp-error", common.GetComponentInfo()) return } response.Result = result @@ -344,17 +372,21 @@ func (resourceController *ResourceControllerV2) CreateResourceInstanceWithContex // Retrieve a resource instance by URL-encoded CRN or GUID. Find more details on a particular instance, like when it was // provisioned and who provisioned it. func (resourceController *ResourceControllerV2) GetResourceInstance(getResourceInstanceOptions *GetResourceInstanceOptions) (result *ResourceInstance, response *core.DetailedResponse, err error) { - return resourceController.GetResourceInstanceWithContext(context.Background(), getResourceInstanceOptions) + result, response, err = resourceController.GetResourceInstanceWithContext(context.Background(), getResourceInstanceOptions) + err = core.RepurposeSDKProblem(err, "") + return } // GetResourceInstanceWithContext is an alternate form of the GetResourceInstance method which supports a Context parameter func (resourceController *ResourceControllerV2) GetResourceInstanceWithContext(ctx context.Context, getResourceInstanceOptions *GetResourceInstanceOptions) (result *ResourceInstance, response *core.DetailedResponse, err error) { err = core.ValidateNotNil(getResourceInstanceOptions, "getResourceInstanceOptions cannot be nil") if err != nil { + err = core.SDKErrorf(err, "", "unexpected-nil-param", common.GetComponentInfo()) return } err = core.ValidateStruct(getResourceInstanceOptions, "getResourceInstanceOptions") if err != nil { + err = core.SDKErrorf(err, "", "struct-validation-error", common.GetComponentInfo()) return } @@ -367,6 +399,7 @@ func (resourceController *ResourceControllerV2) GetResourceInstanceWithContext(c builder.EnableGzipCompression = resourceController.GetEnableGzipCompression() _, err = builder.ResolveRequestURL(resourceController.Service.Options.URL, `/v2/resource_instances/{id}`, pathParamsMap) if err != nil { + err = core.SDKErrorf(err, "", "url-resolve-error", common.GetComponentInfo()) return } @@ -382,17 +415,21 @@ func (resourceController *ResourceControllerV2) GetResourceInstanceWithContext(c request, err := builder.Build() if err != nil { + err = core.SDKErrorf(err, "", "build-error", common.GetComponentInfo()) return } var rawResponse map[string]json.RawMessage response, err = resourceController.Service.Request(request, &rawResponse) if err != nil { + core.EnrichHTTPProblem(err, "get_resource_instance", getServiceComponentInfo()) + err = core.SDKErrorf(err, "", "http-request-err", common.GetComponentInfo()) return } if rawResponse != nil { err = core.UnmarshalModel(rawResponse, "", &result, UnmarshalResourceInstance) if err != nil { + err = core.SDKErrorf(err, "", "unmarshal-resp-error", common.GetComponentInfo()) return } response.Result = result @@ -405,17 +442,21 @@ func (resourceController *ResourceControllerV2) GetResourceInstanceWithContext(c // Delete a resource instance by URL-encoded CRN or GUID. If the resource instance has any resource keys or aliases // associated with it, use the `recursive=true` parameter to delete it. func (resourceController *ResourceControllerV2) DeleteResourceInstance(deleteResourceInstanceOptions *DeleteResourceInstanceOptions) (response *core.DetailedResponse, err error) { - return resourceController.DeleteResourceInstanceWithContext(context.Background(), deleteResourceInstanceOptions) + response, err = resourceController.DeleteResourceInstanceWithContext(context.Background(), deleteResourceInstanceOptions) + err = core.RepurposeSDKProblem(err, "") + return } // DeleteResourceInstanceWithContext is an alternate form of the DeleteResourceInstance method which supports a Context parameter func (resourceController *ResourceControllerV2) DeleteResourceInstanceWithContext(ctx context.Context, deleteResourceInstanceOptions *DeleteResourceInstanceOptions) (response *core.DetailedResponse, err error) { err = core.ValidateNotNil(deleteResourceInstanceOptions, "deleteResourceInstanceOptions cannot be nil") if err != nil { + err = core.SDKErrorf(err, "", "unexpected-nil-param", common.GetComponentInfo()) return } err = core.ValidateStruct(deleteResourceInstanceOptions, "deleteResourceInstanceOptions") if err != nil { + err = core.SDKErrorf(err, "", "struct-validation-error", common.GetComponentInfo()) return } @@ -428,6 +469,7 @@ func (resourceController *ResourceControllerV2) DeleteResourceInstanceWithContex builder.EnableGzipCompression = resourceController.GetEnableGzipCompression() _, err = builder.ResolveRequestURL(resourceController.Service.Options.URL, `/v2/resource_instances/{id}`, pathParamsMap) if err != nil { + err = core.SDKErrorf(err, "", "url-resolve-error", common.GetComponentInfo()) return } @@ -446,10 +488,16 @@ func (resourceController *ResourceControllerV2) DeleteResourceInstanceWithContex request, err := builder.Build() if err != nil { + err = core.SDKErrorf(err, "", "build-error", common.GetComponentInfo()) return } response, err = resourceController.Service.Request(request, nil) + if err != nil { + core.EnrichHTTPProblem(err, "delete_resource_instance", getServiceComponentInfo()) + err = core.SDKErrorf(err, "", "http-request-err", common.GetComponentInfo()) + return + } return } @@ -458,17 +506,21 @@ func (resourceController *ResourceControllerV2) DeleteResourceInstanceWithContex // Use the resource instance URL-encoded CRN or GUID to make updates to the resource instance, like changing the name or // plan. func (resourceController *ResourceControllerV2) UpdateResourceInstance(updateResourceInstanceOptions *UpdateResourceInstanceOptions) (result *ResourceInstance, response *core.DetailedResponse, err error) { - return resourceController.UpdateResourceInstanceWithContext(context.Background(), updateResourceInstanceOptions) + result, response, err = resourceController.UpdateResourceInstanceWithContext(context.Background(), updateResourceInstanceOptions) + err = core.RepurposeSDKProblem(err, "") + return } // UpdateResourceInstanceWithContext is an alternate form of the UpdateResourceInstance method which supports a Context parameter func (resourceController *ResourceControllerV2) UpdateResourceInstanceWithContext(ctx context.Context, updateResourceInstanceOptions *UpdateResourceInstanceOptions) (result *ResourceInstance, response *core.DetailedResponse, err error) { err = core.ValidateNotNil(updateResourceInstanceOptions, "updateResourceInstanceOptions cannot be nil") if err != nil { + err = core.SDKErrorf(err, "", "unexpected-nil-param", common.GetComponentInfo()) return } err = core.ValidateStruct(updateResourceInstanceOptions, "updateResourceInstanceOptions") if err != nil { + err = core.SDKErrorf(err, "", "struct-validation-error", common.GetComponentInfo()) return } @@ -481,6 +533,7 @@ func (resourceController *ResourceControllerV2) UpdateResourceInstanceWithContex builder.EnableGzipCompression = resourceController.GetEnableGzipCompression() _, err = builder.ResolveRequestURL(resourceController.Service.Options.URL, `/v2/resource_instances/{id}`, pathParamsMap) if err != nil { + err = core.SDKErrorf(err, "", "url-resolve-error", common.GetComponentInfo()) return } @@ -510,22 +563,27 @@ func (resourceController *ResourceControllerV2) UpdateResourceInstanceWithContex } _, err = builder.SetBodyContentJSON(body) if err != nil { + err = core.SDKErrorf(err, "", "set-json-body-error", common.GetComponentInfo()) return } request, err := builder.Build() if err != nil { + err = core.SDKErrorf(err, "", "build-error", common.GetComponentInfo()) return } var rawResponse map[string]json.RawMessage response, err = resourceController.Service.Request(request, &rawResponse) if err != nil { + core.EnrichHTTPProblem(err, "update_resource_instance", getServiceComponentInfo()) + err = core.SDKErrorf(err, "", "http-request-err", common.GetComponentInfo()) return } if rawResponse != nil { err = core.UnmarshalModel(rawResponse, "", &result, UnmarshalResourceInstance) if err != nil { + err = core.SDKErrorf(err, "", "unmarshal-resp-error", common.GetComponentInfo()) return } response.Result = result @@ -537,17 +595,21 @@ func (resourceController *ResourceControllerV2) UpdateResourceInstanceWithContex // ListResourceAliasesForInstance : Get a list of all resource aliases for the instance // Retrieving a list of all resource aliases can help you find out who's using the resource instance. func (resourceController *ResourceControllerV2) ListResourceAliasesForInstance(listResourceAliasesForInstanceOptions *ListResourceAliasesForInstanceOptions) (result *ResourceAliasesList, response *core.DetailedResponse, err error) { - return resourceController.ListResourceAliasesForInstanceWithContext(context.Background(), listResourceAliasesForInstanceOptions) + result, response, err = resourceController.ListResourceAliasesForInstanceWithContext(context.Background(), listResourceAliasesForInstanceOptions) + err = core.RepurposeSDKProblem(err, "") + return } // ListResourceAliasesForInstanceWithContext is an alternate form of the ListResourceAliasesForInstance method which supports a Context parameter func (resourceController *ResourceControllerV2) ListResourceAliasesForInstanceWithContext(ctx context.Context, listResourceAliasesForInstanceOptions *ListResourceAliasesForInstanceOptions) (result *ResourceAliasesList, response *core.DetailedResponse, err error) { err = core.ValidateNotNil(listResourceAliasesForInstanceOptions, "listResourceAliasesForInstanceOptions cannot be nil") if err != nil { + err = core.SDKErrorf(err, "", "unexpected-nil-param", common.GetComponentInfo()) return } err = core.ValidateStruct(listResourceAliasesForInstanceOptions, "listResourceAliasesForInstanceOptions") if err != nil { + err = core.SDKErrorf(err, "", "struct-validation-error", common.GetComponentInfo()) return } @@ -560,6 +622,7 @@ func (resourceController *ResourceControllerV2) ListResourceAliasesForInstanceWi builder.EnableGzipCompression = resourceController.GetEnableGzipCompression() _, err = builder.ResolveRequestURL(resourceController.Service.Options.URL, `/v2/resource_instances/{id}/resource_aliases`, pathParamsMap) if err != nil { + err = core.SDKErrorf(err, "", "url-resolve-error", common.GetComponentInfo()) return } @@ -582,17 +645,21 @@ func (resourceController *ResourceControllerV2) ListResourceAliasesForInstanceWi request, err := builder.Build() if err != nil { + err = core.SDKErrorf(err, "", "build-error", common.GetComponentInfo()) return } var rawResponse map[string]json.RawMessage response, err = resourceController.Service.Request(request, &rawResponse) if err != nil { + core.EnrichHTTPProblem(err, "list_resource_aliases_for_instance", getServiceComponentInfo()) + err = core.SDKErrorf(err, "", "http-request-err", common.GetComponentInfo()) return } if rawResponse != nil { err = core.UnmarshalModel(rawResponse, "", &result, UnmarshalResourceAliasesList) if err != nil { + err = core.SDKErrorf(err, "", "unmarshal-resp-error", common.GetComponentInfo()) return } response.Result = result @@ -605,17 +672,21 @@ func (resourceController *ResourceControllerV2) ListResourceAliasesForInstanceWi // You may have many resource keys for one resource instance. For example, you may have a different resource key for // each user or each role. func (resourceController *ResourceControllerV2) ListResourceKeysForInstance(listResourceKeysForInstanceOptions *ListResourceKeysForInstanceOptions) (result *ResourceKeysList, response *core.DetailedResponse, err error) { - return resourceController.ListResourceKeysForInstanceWithContext(context.Background(), listResourceKeysForInstanceOptions) + result, response, err = resourceController.ListResourceKeysForInstanceWithContext(context.Background(), listResourceKeysForInstanceOptions) + err = core.RepurposeSDKProblem(err, "") + return } // ListResourceKeysForInstanceWithContext is an alternate form of the ListResourceKeysForInstance method which supports a Context parameter func (resourceController *ResourceControllerV2) ListResourceKeysForInstanceWithContext(ctx context.Context, listResourceKeysForInstanceOptions *ListResourceKeysForInstanceOptions) (result *ResourceKeysList, response *core.DetailedResponse, err error) { err = core.ValidateNotNil(listResourceKeysForInstanceOptions, "listResourceKeysForInstanceOptions cannot be nil") if err != nil { + err = core.SDKErrorf(err, "", "unexpected-nil-param", common.GetComponentInfo()) return } err = core.ValidateStruct(listResourceKeysForInstanceOptions, "listResourceKeysForInstanceOptions") if err != nil { + err = core.SDKErrorf(err, "", "struct-validation-error", common.GetComponentInfo()) return } @@ -628,6 +699,7 @@ func (resourceController *ResourceControllerV2) ListResourceKeysForInstanceWithC builder.EnableGzipCompression = resourceController.GetEnableGzipCompression() _, err = builder.ResolveRequestURL(resourceController.Service.Options.URL, `/v2/resource_instances/{id}/resource_keys`, pathParamsMap) if err != nil { + err = core.SDKErrorf(err, "", "url-resolve-error", common.GetComponentInfo()) return } @@ -650,17 +722,21 @@ func (resourceController *ResourceControllerV2) ListResourceKeysForInstanceWithC request, err := builder.Build() if err != nil { + err = core.SDKErrorf(err, "", "build-error", common.GetComponentInfo()) return } var rawResponse map[string]json.RawMessage response, err = resourceController.Service.Request(request, &rawResponse) if err != nil { + core.EnrichHTTPProblem(err, "list_resource_keys_for_instance", getServiceComponentInfo()) + err = core.SDKErrorf(err, "", "http-request-err", common.GetComponentInfo()) return } if rawResponse != nil { err = core.UnmarshalModel(rawResponse, "", &result, UnmarshalResourceKeysList) if err != nil { + err = core.SDKErrorf(err, "", "unmarshal-resp-error", common.GetComponentInfo()) return } response.Result = result @@ -673,17 +749,21 @@ func (resourceController *ResourceControllerV2) ListResourceKeysForInstanceWithC // Locks a resource instance. A locked instance can not be updated or deleted. It does not affect actions performed on // child resources like aliases, bindings, or keys. func (resourceController *ResourceControllerV2) LockResourceInstance(lockResourceInstanceOptions *LockResourceInstanceOptions) (result *ResourceInstance, response *core.DetailedResponse, err error) { - return resourceController.LockResourceInstanceWithContext(context.Background(), lockResourceInstanceOptions) + result, response, err = resourceController.LockResourceInstanceWithContext(context.Background(), lockResourceInstanceOptions) + err = core.RepurposeSDKProblem(err, "") + return } // LockResourceInstanceWithContext is an alternate form of the LockResourceInstance method which supports a Context parameter func (resourceController *ResourceControllerV2) LockResourceInstanceWithContext(ctx context.Context, lockResourceInstanceOptions *LockResourceInstanceOptions) (result *ResourceInstance, response *core.DetailedResponse, err error) { err = core.ValidateNotNil(lockResourceInstanceOptions, "lockResourceInstanceOptions cannot be nil") if err != nil { + err = core.SDKErrorf(err, "", "unexpected-nil-param", common.GetComponentInfo()) return } err = core.ValidateStruct(lockResourceInstanceOptions, "lockResourceInstanceOptions") if err != nil { + err = core.SDKErrorf(err, "", "struct-validation-error", common.GetComponentInfo()) return } @@ -696,6 +776,7 @@ func (resourceController *ResourceControllerV2) LockResourceInstanceWithContext( builder.EnableGzipCompression = resourceController.GetEnableGzipCompression() _, err = builder.ResolveRequestURL(resourceController.Service.Options.URL, `/v2/resource_instances/{id}/lock`, pathParamsMap) if err != nil { + err = core.SDKErrorf(err, "", "url-resolve-error", common.GetComponentInfo()) return } @@ -711,17 +792,21 @@ func (resourceController *ResourceControllerV2) LockResourceInstanceWithContext( request, err := builder.Build() if err != nil { + err = core.SDKErrorf(err, "", "build-error", common.GetComponentInfo()) return } var rawResponse map[string]json.RawMessage response, err = resourceController.Service.Request(request, &rawResponse) if err != nil { + core.EnrichHTTPProblem(err, "lock_resource_instance", getServiceComponentInfo()) + err = core.SDKErrorf(err, "", "http-request-err", common.GetComponentInfo()) return } if rawResponse != nil { err = core.UnmarshalModel(rawResponse, "", &result, UnmarshalResourceInstance) if err != nil { + err = core.SDKErrorf(err, "", "unmarshal-resp-error", common.GetComponentInfo()) return } response.Result = result @@ -734,17 +819,21 @@ func (resourceController *ResourceControllerV2) LockResourceInstanceWithContext( // Unlock a resource instance to update or delete it. Unlocking a resource instance does not affect child resources like // aliases, bindings or keys. func (resourceController *ResourceControllerV2) UnlockResourceInstance(unlockResourceInstanceOptions *UnlockResourceInstanceOptions) (result *ResourceInstance, response *core.DetailedResponse, err error) { - return resourceController.UnlockResourceInstanceWithContext(context.Background(), unlockResourceInstanceOptions) + result, response, err = resourceController.UnlockResourceInstanceWithContext(context.Background(), unlockResourceInstanceOptions) + err = core.RepurposeSDKProblem(err, "") + return } // UnlockResourceInstanceWithContext is an alternate form of the UnlockResourceInstance method which supports a Context parameter func (resourceController *ResourceControllerV2) UnlockResourceInstanceWithContext(ctx context.Context, unlockResourceInstanceOptions *UnlockResourceInstanceOptions) (result *ResourceInstance, response *core.DetailedResponse, err error) { err = core.ValidateNotNil(unlockResourceInstanceOptions, "unlockResourceInstanceOptions cannot be nil") if err != nil { + err = core.SDKErrorf(err, "", "unexpected-nil-param", common.GetComponentInfo()) return } err = core.ValidateStruct(unlockResourceInstanceOptions, "unlockResourceInstanceOptions") if err != nil { + err = core.SDKErrorf(err, "", "struct-validation-error", common.GetComponentInfo()) return } @@ -757,6 +846,7 @@ func (resourceController *ResourceControllerV2) UnlockResourceInstanceWithContex builder.EnableGzipCompression = resourceController.GetEnableGzipCompression() _, err = builder.ResolveRequestURL(resourceController.Service.Options.URL, `/v2/resource_instances/{id}/lock`, pathParamsMap) if err != nil { + err = core.SDKErrorf(err, "", "url-resolve-error", common.GetComponentInfo()) return } @@ -772,17 +862,21 @@ func (resourceController *ResourceControllerV2) UnlockResourceInstanceWithContex request, err := builder.Build() if err != nil { + err = core.SDKErrorf(err, "", "build-error", common.GetComponentInfo()) return } var rawResponse map[string]json.RawMessage response, err = resourceController.Service.Request(request, &rawResponse) if err != nil { + core.EnrichHTTPProblem(err, "unlock_resource_instance", getServiceComponentInfo()) + err = core.SDKErrorf(err, "", "http-request-err", common.GetComponentInfo()) return } if rawResponse != nil { err = core.UnmarshalModel(rawResponse, "", &result, UnmarshalResourceInstance) if err != nil { + err = core.SDKErrorf(err, "", "unmarshal-resp-error", common.GetComponentInfo()) return } response.Result = result @@ -795,17 +889,21 @@ func (resourceController *ResourceControllerV2) UnlockResourceInstanceWithContex // Cancel the in progress last operation of the resource instance. After successful cancellation, the resource instance // is removed. func (resourceController *ResourceControllerV2) CancelLastopResourceInstance(cancelLastopResourceInstanceOptions *CancelLastopResourceInstanceOptions) (result *ResourceInstance, response *core.DetailedResponse, err error) { - return resourceController.CancelLastopResourceInstanceWithContext(context.Background(), cancelLastopResourceInstanceOptions) + result, response, err = resourceController.CancelLastopResourceInstanceWithContext(context.Background(), cancelLastopResourceInstanceOptions) + err = core.RepurposeSDKProblem(err, "") + return } // CancelLastopResourceInstanceWithContext is an alternate form of the CancelLastopResourceInstance method which supports a Context parameter func (resourceController *ResourceControllerV2) CancelLastopResourceInstanceWithContext(ctx context.Context, cancelLastopResourceInstanceOptions *CancelLastopResourceInstanceOptions) (result *ResourceInstance, response *core.DetailedResponse, err error) { err = core.ValidateNotNil(cancelLastopResourceInstanceOptions, "cancelLastopResourceInstanceOptions cannot be nil") if err != nil { + err = core.SDKErrorf(err, "", "unexpected-nil-param", common.GetComponentInfo()) return } err = core.ValidateStruct(cancelLastopResourceInstanceOptions, "cancelLastopResourceInstanceOptions") if err != nil { + err = core.SDKErrorf(err, "", "struct-validation-error", common.GetComponentInfo()) return } @@ -818,6 +916,7 @@ func (resourceController *ResourceControllerV2) CancelLastopResourceInstanceWith builder.EnableGzipCompression = resourceController.GetEnableGzipCompression() _, err = builder.ResolveRequestURL(resourceController.Service.Options.URL, `/v2/resource_instances/{id}/last_operation`, pathParamsMap) if err != nil { + err = core.SDKErrorf(err, "", "url-resolve-error", common.GetComponentInfo()) return } @@ -833,17 +932,21 @@ func (resourceController *ResourceControllerV2) CancelLastopResourceInstanceWith request, err := builder.Build() if err != nil { + err = core.SDKErrorf(err, "", "build-error", common.GetComponentInfo()) return } var rawResponse map[string]json.RawMessage response, err = resourceController.Service.Request(request, &rawResponse) if err != nil { + core.EnrichHTTPProblem(err, "cancel_lastop_resource_instance", getServiceComponentInfo()) + err = core.SDKErrorf(err, "", "http-request-err", common.GetComponentInfo()) return } if rawResponse != nil { err = core.UnmarshalModel(rawResponse, "", &result, UnmarshalResourceInstance) if err != nil { + err = core.SDKErrorf(err, "", "unmarshal-resp-error", common.GetComponentInfo()) return } response.Result = result @@ -855,13 +958,16 @@ func (resourceController *ResourceControllerV2) CancelLastopResourceInstanceWith // ListResourceKeys : Get a list of all of the resource keys // View all of the resource keys that exist for all of your resource instances. func (resourceController *ResourceControllerV2) ListResourceKeys(listResourceKeysOptions *ListResourceKeysOptions) (result *ResourceKeysList, response *core.DetailedResponse, err error) { - return resourceController.ListResourceKeysWithContext(context.Background(), listResourceKeysOptions) + result, response, err = resourceController.ListResourceKeysWithContext(context.Background(), listResourceKeysOptions) + err = core.RepurposeSDKProblem(err, "") + return } // ListResourceKeysWithContext is an alternate form of the ListResourceKeys method which supports a Context parameter func (resourceController *ResourceControllerV2) ListResourceKeysWithContext(ctx context.Context, listResourceKeysOptions *ListResourceKeysOptions) (result *ResourceKeysList, response *core.DetailedResponse, err error) { err = core.ValidateStruct(listResourceKeysOptions, "listResourceKeysOptions") if err != nil { + err = core.SDKErrorf(err, "", "struct-validation-error", common.GetComponentInfo()) return } @@ -870,6 +976,7 @@ func (resourceController *ResourceControllerV2) ListResourceKeysWithContext(ctx builder.EnableGzipCompression = resourceController.GetEnableGzipCompression() _, err = builder.ResolveRequestURL(resourceController.Service.Options.URL, `/v2/resource_keys`, nil) if err != nil { + err = core.SDKErrorf(err, "", "url-resolve-error", common.GetComponentInfo()) return } @@ -910,17 +1017,21 @@ func (resourceController *ResourceControllerV2) ListResourceKeysWithContext(ctx request, err := builder.Build() if err != nil { + err = core.SDKErrorf(err, "", "build-error", common.GetComponentInfo()) return } var rawResponse map[string]json.RawMessage response, err = resourceController.Service.Request(request, &rawResponse) if err != nil { + core.EnrichHTTPProblem(err, "list_resource_keys", getServiceComponentInfo()) + err = core.SDKErrorf(err, "", "http-request-err", common.GetComponentInfo()) return } if rawResponse != nil { err = core.UnmarshalModel(rawResponse, "", &result, UnmarshalResourceKeysList) if err != nil { + err = core.SDKErrorf(err, "", "unmarshal-resp-error", common.GetComponentInfo()) return } response.Result = result @@ -932,17 +1043,21 @@ func (resourceController *ResourceControllerV2) ListResourceKeysWithContext(ctx // CreateResourceKey : Create a new resource key // A resource key is a saved credential you can use to authenticate with a resource instance. func (resourceController *ResourceControllerV2) CreateResourceKey(createResourceKeyOptions *CreateResourceKeyOptions) (result *ResourceKey, response *core.DetailedResponse, err error) { - return resourceController.CreateResourceKeyWithContext(context.Background(), createResourceKeyOptions) + result, response, err = resourceController.CreateResourceKeyWithContext(context.Background(), createResourceKeyOptions) + err = core.RepurposeSDKProblem(err, "") + return } // CreateResourceKeyWithContext is an alternate form of the CreateResourceKey method which supports a Context parameter func (resourceController *ResourceControllerV2) CreateResourceKeyWithContext(ctx context.Context, createResourceKeyOptions *CreateResourceKeyOptions) (result *ResourceKey, response *core.DetailedResponse, err error) { err = core.ValidateNotNil(createResourceKeyOptions, "createResourceKeyOptions cannot be nil") if err != nil { + err = core.SDKErrorf(err, "", "unexpected-nil-param", common.GetComponentInfo()) return } err = core.ValidateStruct(createResourceKeyOptions, "createResourceKeyOptions") if err != nil { + err = core.SDKErrorf(err, "", "struct-validation-error", common.GetComponentInfo()) return } @@ -951,6 +1066,7 @@ func (resourceController *ResourceControllerV2) CreateResourceKeyWithContext(ctx builder.EnableGzipCompression = resourceController.GetEnableGzipCompression() _, err = builder.ResolveRequestURL(resourceController.Service.Options.URL, `/v2/resource_keys`, nil) if err != nil { + err = core.SDKErrorf(err, "", "url-resolve-error", common.GetComponentInfo()) return } @@ -980,22 +1096,27 @@ func (resourceController *ResourceControllerV2) CreateResourceKeyWithContext(ctx } _, err = builder.SetBodyContentJSON(body) if err != nil { + err = core.SDKErrorf(err, "", "set-json-body-error", common.GetComponentInfo()) return } request, err := builder.Build() if err != nil { + err = core.SDKErrorf(err, "", "build-error", common.GetComponentInfo()) return } var rawResponse map[string]json.RawMessage response, err = resourceController.Service.Request(request, &rawResponse) if err != nil { + core.EnrichHTTPProblem(err, "create_resource_key", getServiceComponentInfo()) + err = core.SDKErrorf(err, "", "http-request-err", common.GetComponentInfo()) return } if rawResponse != nil { err = core.UnmarshalModel(rawResponse, "", &result, UnmarshalResourceKey) if err != nil { + err = core.SDKErrorf(err, "", "unmarshal-resp-error", common.GetComponentInfo()) return } response.Result = result @@ -1007,17 +1128,21 @@ func (resourceController *ResourceControllerV2) CreateResourceKeyWithContext(ctx // GetResourceKey : Get resource key // View the details of a resource key by URL-encoded CRN or GUID, like the credentials for the key and who created it. func (resourceController *ResourceControllerV2) GetResourceKey(getResourceKeyOptions *GetResourceKeyOptions) (result *ResourceKey, response *core.DetailedResponse, err error) { - return resourceController.GetResourceKeyWithContext(context.Background(), getResourceKeyOptions) + result, response, err = resourceController.GetResourceKeyWithContext(context.Background(), getResourceKeyOptions) + err = core.RepurposeSDKProblem(err, "") + return } // GetResourceKeyWithContext is an alternate form of the GetResourceKey method which supports a Context parameter func (resourceController *ResourceControllerV2) GetResourceKeyWithContext(ctx context.Context, getResourceKeyOptions *GetResourceKeyOptions) (result *ResourceKey, response *core.DetailedResponse, err error) { err = core.ValidateNotNil(getResourceKeyOptions, "getResourceKeyOptions cannot be nil") if err != nil { + err = core.SDKErrorf(err, "", "unexpected-nil-param", common.GetComponentInfo()) return } err = core.ValidateStruct(getResourceKeyOptions, "getResourceKeyOptions") if err != nil { + err = core.SDKErrorf(err, "", "struct-validation-error", common.GetComponentInfo()) return } @@ -1030,6 +1155,7 @@ func (resourceController *ResourceControllerV2) GetResourceKeyWithContext(ctx co builder.EnableGzipCompression = resourceController.GetEnableGzipCompression() _, err = builder.ResolveRequestURL(resourceController.Service.Options.URL, `/v2/resource_keys/{id}`, pathParamsMap) if err != nil { + err = core.SDKErrorf(err, "", "url-resolve-error", common.GetComponentInfo()) return } @@ -1045,17 +1171,21 @@ func (resourceController *ResourceControllerV2) GetResourceKeyWithContext(ctx co request, err := builder.Build() if err != nil { + err = core.SDKErrorf(err, "", "build-error", common.GetComponentInfo()) return } var rawResponse map[string]json.RawMessage response, err = resourceController.Service.Request(request, &rawResponse) if err != nil { + core.EnrichHTTPProblem(err, "get_resource_key", getServiceComponentInfo()) + err = core.SDKErrorf(err, "", "http-request-err", common.GetComponentInfo()) return } if rawResponse != nil { err = core.UnmarshalModel(rawResponse, "", &result, UnmarshalResourceKey) if err != nil { + err = core.SDKErrorf(err, "", "unmarshal-resp-error", common.GetComponentInfo()) return } response.Result = result @@ -1067,17 +1197,21 @@ func (resourceController *ResourceControllerV2) GetResourceKeyWithContext(ctx co // DeleteResourceKey : Delete a resource key // Deleting a resource key does not affect any resource instance or resource alias associated with the key. func (resourceController *ResourceControllerV2) DeleteResourceKey(deleteResourceKeyOptions *DeleteResourceKeyOptions) (response *core.DetailedResponse, err error) { - return resourceController.DeleteResourceKeyWithContext(context.Background(), deleteResourceKeyOptions) + response, err = resourceController.DeleteResourceKeyWithContext(context.Background(), deleteResourceKeyOptions) + err = core.RepurposeSDKProblem(err, "") + return } // DeleteResourceKeyWithContext is an alternate form of the DeleteResourceKey method which supports a Context parameter func (resourceController *ResourceControllerV2) DeleteResourceKeyWithContext(ctx context.Context, deleteResourceKeyOptions *DeleteResourceKeyOptions) (response *core.DetailedResponse, err error) { err = core.ValidateNotNil(deleteResourceKeyOptions, "deleteResourceKeyOptions cannot be nil") if err != nil { + err = core.SDKErrorf(err, "", "unexpected-nil-param", common.GetComponentInfo()) return } err = core.ValidateStruct(deleteResourceKeyOptions, "deleteResourceKeyOptions") if err != nil { + err = core.SDKErrorf(err, "", "struct-validation-error", common.GetComponentInfo()) return } @@ -1090,6 +1224,7 @@ func (resourceController *ResourceControllerV2) DeleteResourceKeyWithContext(ctx builder.EnableGzipCompression = resourceController.GetEnableGzipCompression() _, err = builder.ResolveRequestURL(resourceController.Service.Options.URL, `/v2/resource_keys/{id}`, pathParamsMap) if err != nil { + err = core.SDKErrorf(err, "", "url-resolve-error", common.GetComponentInfo()) return } @@ -1104,10 +1239,16 @@ func (resourceController *ResourceControllerV2) DeleteResourceKeyWithContext(ctx request, err := builder.Build() if err != nil { + err = core.SDKErrorf(err, "", "build-error", common.GetComponentInfo()) return } response, err = resourceController.Service.Request(request, nil) + if err != nil { + core.EnrichHTTPProblem(err, "delete_resource_key", getServiceComponentInfo()) + err = core.SDKErrorf(err, "", "http-request-err", common.GetComponentInfo()) + return + } return } @@ -1115,17 +1256,21 @@ func (resourceController *ResourceControllerV2) DeleteResourceKeyWithContext(ctx // UpdateResourceKey : Update a resource key // Use the resource key URL-encoded CRN or GUID to update the resource key. func (resourceController *ResourceControllerV2) UpdateResourceKey(updateResourceKeyOptions *UpdateResourceKeyOptions) (result *ResourceKey, response *core.DetailedResponse, err error) { - return resourceController.UpdateResourceKeyWithContext(context.Background(), updateResourceKeyOptions) + result, response, err = resourceController.UpdateResourceKeyWithContext(context.Background(), updateResourceKeyOptions) + err = core.RepurposeSDKProblem(err, "") + return } // UpdateResourceKeyWithContext is an alternate form of the UpdateResourceKey method which supports a Context parameter func (resourceController *ResourceControllerV2) UpdateResourceKeyWithContext(ctx context.Context, updateResourceKeyOptions *UpdateResourceKeyOptions) (result *ResourceKey, response *core.DetailedResponse, err error) { err = core.ValidateNotNil(updateResourceKeyOptions, "updateResourceKeyOptions cannot be nil") if err != nil { + err = core.SDKErrorf(err, "", "unexpected-nil-param", common.GetComponentInfo()) return } err = core.ValidateStruct(updateResourceKeyOptions, "updateResourceKeyOptions") if err != nil { + err = core.SDKErrorf(err, "", "struct-validation-error", common.GetComponentInfo()) return } @@ -1138,6 +1283,7 @@ func (resourceController *ResourceControllerV2) UpdateResourceKeyWithContext(ctx builder.EnableGzipCompression = resourceController.GetEnableGzipCompression() _, err = builder.ResolveRequestURL(resourceController.Service.Options.URL, `/v2/resource_keys/{id}`, pathParamsMap) if err != nil { + err = core.SDKErrorf(err, "", "url-resolve-error", common.GetComponentInfo()) return } @@ -1158,22 +1304,27 @@ func (resourceController *ResourceControllerV2) UpdateResourceKeyWithContext(ctx } _, err = builder.SetBodyContentJSON(body) if err != nil { + err = core.SDKErrorf(err, "", "set-json-body-error", common.GetComponentInfo()) return } request, err := builder.Build() if err != nil { + err = core.SDKErrorf(err, "", "build-error", common.GetComponentInfo()) return } var rawResponse map[string]json.RawMessage response, err = resourceController.Service.Request(request, &rawResponse) if err != nil { + core.EnrichHTTPProblem(err, "update_resource_key", getServiceComponentInfo()) + err = core.SDKErrorf(err, "", "http-request-err", common.GetComponentInfo()) return } if rawResponse != nil { err = core.UnmarshalModel(rawResponse, "", &result, UnmarshalResourceKey) if err != nil { + err = core.SDKErrorf(err, "", "unmarshal-resp-error", common.GetComponentInfo()) return } response.Result = result @@ -1185,13 +1336,16 @@ func (resourceController *ResourceControllerV2) UpdateResourceKeyWithContext(ctx // ListResourceBindings : Get a list of all resource bindings // View all of the resource bindings that exist for all of your resource aliases. func (resourceController *ResourceControllerV2) ListResourceBindings(listResourceBindingsOptions *ListResourceBindingsOptions) (result *ResourceBindingsList, response *core.DetailedResponse, err error) { - return resourceController.ListResourceBindingsWithContext(context.Background(), listResourceBindingsOptions) + result, response, err = resourceController.ListResourceBindingsWithContext(context.Background(), listResourceBindingsOptions) + err = core.RepurposeSDKProblem(err, "") + return } // ListResourceBindingsWithContext is an alternate form of the ListResourceBindings method which supports a Context parameter func (resourceController *ResourceControllerV2) ListResourceBindingsWithContext(ctx context.Context, listResourceBindingsOptions *ListResourceBindingsOptions) (result *ResourceBindingsList, response *core.DetailedResponse, err error) { err = core.ValidateStruct(listResourceBindingsOptions, "listResourceBindingsOptions") if err != nil { + err = core.SDKErrorf(err, "", "struct-validation-error", common.GetComponentInfo()) return } @@ -1200,6 +1354,7 @@ func (resourceController *ResourceControllerV2) ListResourceBindingsWithContext( builder.EnableGzipCompression = resourceController.GetEnableGzipCompression() _, err = builder.ResolveRequestURL(resourceController.Service.Options.URL, `/v2/resource_bindings`, nil) if err != nil { + err = core.SDKErrorf(err, "", "url-resolve-error", common.GetComponentInfo()) return } @@ -1243,17 +1398,21 @@ func (resourceController *ResourceControllerV2) ListResourceBindingsWithContext( request, err := builder.Build() if err != nil { + err = core.SDKErrorf(err, "", "build-error", common.GetComponentInfo()) return } var rawResponse map[string]json.RawMessage response, err = resourceController.Service.Request(request, &rawResponse) if err != nil { + core.EnrichHTTPProblem(err, "list_resource_bindings", getServiceComponentInfo()) + err = core.SDKErrorf(err, "", "http-request-err", common.GetComponentInfo()) return } if rawResponse != nil { err = core.UnmarshalModel(rawResponse, "", &result, UnmarshalResourceBindingsList) if err != nil { + err = core.SDKErrorf(err, "", "unmarshal-resp-error", common.GetComponentInfo()) return } response.Result = result @@ -1265,17 +1424,21 @@ func (resourceController *ResourceControllerV2) ListResourceBindingsWithContext( // CreateResourceBinding : Create a new resource binding // A resource binding connects credentials to a resource alias. The credentials are in the form of a resource key. func (resourceController *ResourceControllerV2) CreateResourceBinding(createResourceBindingOptions *CreateResourceBindingOptions) (result *ResourceBinding, response *core.DetailedResponse, err error) { - return resourceController.CreateResourceBindingWithContext(context.Background(), createResourceBindingOptions) + result, response, err = resourceController.CreateResourceBindingWithContext(context.Background(), createResourceBindingOptions) + err = core.RepurposeSDKProblem(err, "") + return } // CreateResourceBindingWithContext is an alternate form of the CreateResourceBinding method which supports a Context parameter func (resourceController *ResourceControllerV2) CreateResourceBindingWithContext(ctx context.Context, createResourceBindingOptions *CreateResourceBindingOptions) (result *ResourceBinding, response *core.DetailedResponse, err error) { err = core.ValidateNotNil(createResourceBindingOptions, "createResourceBindingOptions cannot be nil") if err != nil { + err = core.SDKErrorf(err, "", "unexpected-nil-param", common.GetComponentInfo()) return } err = core.ValidateStruct(createResourceBindingOptions, "createResourceBindingOptions") if err != nil { + err = core.SDKErrorf(err, "", "struct-validation-error", common.GetComponentInfo()) return } @@ -1284,6 +1447,7 @@ func (resourceController *ResourceControllerV2) CreateResourceBindingWithContext builder.EnableGzipCompression = resourceController.GetEnableGzipCompression() _, err = builder.ResolveRequestURL(resourceController.Service.Options.URL, `/v2/resource_bindings`, nil) if err != nil { + err = core.SDKErrorf(err, "", "url-resolve-error", common.GetComponentInfo()) return } @@ -1316,22 +1480,27 @@ func (resourceController *ResourceControllerV2) CreateResourceBindingWithContext } _, err = builder.SetBodyContentJSON(body) if err != nil { + err = core.SDKErrorf(err, "", "set-json-body-error", common.GetComponentInfo()) return } request, err := builder.Build() if err != nil { + err = core.SDKErrorf(err, "", "build-error", common.GetComponentInfo()) return } var rawResponse map[string]json.RawMessage response, err = resourceController.Service.Request(request, &rawResponse) if err != nil { + core.EnrichHTTPProblem(err, "create_resource_binding", getServiceComponentInfo()) + err = core.SDKErrorf(err, "", "http-request-err", common.GetComponentInfo()) return } if rawResponse != nil { err = core.UnmarshalModel(rawResponse, "", &result, UnmarshalResourceBinding) if err != nil { + err = core.SDKErrorf(err, "", "unmarshal-resp-error", common.GetComponentInfo()) return } response.Result = result @@ -1344,17 +1513,21 @@ func (resourceController *ResourceControllerV2) CreateResourceBindingWithContext // View a resource binding and all of its details, like who created it, the credential, and the resource alias that the // binding is associated with. func (resourceController *ResourceControllerV2) GetResourceBinding(getResourceBindingOptions *GetResourceBindingOptions) (result *ResourceBinding, response *core.DetailedResponse, err error) { - return resourceController.GetResourceBindingWithContext(context.Background(), getResourceBindingOptions) + result, response, err = resourceController.GetResourceBindingWithContext(context.Background(), getResourceBindingOptions) + err = core.RepurposeSDKProblem(err, "") + return } // GetResourceBindingWithContext is an alternate form of the GetResourceBinding method which supports a Context parameter func (resourceController *ResourceControllerV2) GetResourceBindingWithContext(ctx context.Context, getResourceBindingOptions *GetResourceBindingOptions) (result *ResourceBinding, response *core.DetailedResponse, err error) { err = core.ValidateNotNil(getResourceBindingOptions, "getResourceBindingOptions cannot be nil") if err != nil { + err = core.SDKErrorf(err, "", "unexpected-nil-param", common.GetComponentInfo()) return } err = core.ValidateStruct(getResourceBindingOptions, "getResourceBindingOptions") if err != nil { + err = core.SDKErrorf(err, "", "struct-validation-error", common.GetComponentInfo()) return } @@ -1367,6 +1540,7 @@ func (resourceController *ResourceControllerV2) GetResourceBindingWithContext(ct builder.EnableGzipCompression = resourceController.GetEnableGzipCompression() _, err = builder.ResolveRequestURL(resourceController.Service.Options.URL, `/v2/resource_bindings/{id}`, pathParamsMap) if err != nil { + err = core.SDKErrorf(err, "", "url-resolve-error", common.GetComponentInfo()) return } @@ -1382,17 +1556,21 @@ func (resourceController *ResourceControllerV2) GetResourceBindingWithContext(ct request, err := builder.Build() if err != nil { + err = core.SDKErrorf(err, "", "build-error", common.GetComponentInfo()) return } var rawResponse map[string]json.RawMessage response, err = resourceController.Service.Request(request, &rawResponse) if err != nil { + core.EnrichHTTPProblem(err, "get_resource_binding", getServiceComponentInfo()) + err = core.SDKErrorf(err, "", "http-request-err", common.GetComponentInfo()) return } if rawResponse != nil { err = core.UnmarshalModel(rawResponse, "", &result, UnmarshalResourceBinding) if err != nil { + err = core.SDKErrorf(err, "", "unmarshal-resp-error", common.GetComponentInfo()) return } response.Result = result @@ -1404,17 +1582,21 @@ func (resourceController *ResourceControllerV2) GetResourceBindingWithContext(ct // DeleteResourceBinding : Delete a resource binding // Deleting a resource binding does not affect the resource alias that the binding is associated with. func (resourceController *ResourceControllerV2) DeleteResourceBinding(deleteResourceBindingOptions *DeleteResourceBindingOptions) (response *core.DetailedResponse, err error) { - return resourceController.DeleteResourceBindingWithContext(context.Background(), deleteResourceBindingOptions) + response, err = resourceController.DeleteResourceBindingWithContext(context.Background(), deleteResourceBindingOptions) + err = core.RepurposeSDKProblem(err, "") + return } // DeleteResourceBindingWithContext is an alternate form of the DeleteResourceBinding method which supports a Context parameter func (resourceController *ResourceControllerV2) DeleteResourceBindingWithContext(ctx context.Context, deleteResourceBindingOptions *DeleteResourceBindingOptions) (response *core.DetailedResponse, err error) { err = core.ValidateNotNil(deleteResourceBindingOptions, "deleteResourceBindingOptions cannot be nil") if err != nil { + err = core.SDKErrorf(err, "", "unexpected-nil-param", common.GetComponentInfo()) return } err = core.ValidateStruct(deleteResourceBindingOptions, "deleteResourceBindingOptions") if err != nil { + err = core.SDKErrorf(err, "", "struct-validation-error", common.GetComponentInfo()) return } @@ -1427,6 +1609,7 @@ func (resourceController *ResourceControllerV2) DeleteResourceBindingWithContext builder.EnableGzipCompression = resourceController.GetEnableGzipCompression() _, err = builder.ResolveRequestURL(resourceController.Service.Options.URL, `/v2/resource_bindings/{id}`, pathParamsMap) if err != nil { + err = core.SDKErrorf(err, "", "url-resolve-error", common.GetComponentInfo()) return } @@ -1441,10 +1624,16 @@ func (resourceController *ResourceControllerV2) DeleteResourceBindingWithContext request, err := builder.Build() if err != nil { + err = core.SDKErrorf(err, "", "build-error", common.GetComponentInfo()) return } response, err = resourceController.Service.Request(request, nil) + if err != nil { + core.EnrichHTTPProblem(err, "delete_resource_binding", getServiceComponentInfo()) + err = core.SDKErrorf(err, "", "http-request-err", common.GetComponentInfo()) + return + } return } @@ -1452,17 +1641,21 @@ func (resourceController *ResourceControllerV2) DeleteResourceBindingWithContext // UpdateResourceBinding : Update a resource binding // Use the resource binding URL-encoded CRN or GUID to update the resource binding. func (resourceController *ResourceControllerV2) UpdateResourceBinding(updateResourceBindingOptions *UpdateResourceBindingOptions) (result *ResourceBinding, response *core.DetailedResponse, err error) { - return resourceController.UpdateResourceBindingWithContext(context.Background(), updateResourceBindingOptions) + result, response, err = resourceController.UpdateResourceBindingWithContext(context.Background(), updateResourceBindingOptions) + err = core.RepurposeSDKProblem(err, "") + return } // UpdateResourceBindingWithContext is an alternate form of the UpdateResourceBinding method which supports a Context parameter func (resourceController *ResourceControllerV2) UpdateResourceBindingWithContext(ctx context.Context, updateResourceBindingOptions *UpdateResourceBindingOptions) (result *ResourceBinding, response *core.DetailedResponse, err error) { err = core.ValidateNotNil(updateResourceBindingOptions, "updateResourceBindingOptions cannot be nil") if err != nil { + err = core.SDKErrorf(err, "", "unexpected-nil-param", common.GetComponentInfo()) return } err = core.ValidateStruct(updateResourceBindingOptions, "updateResourceBindingOptions") if err != nil { + err = core.SDKErrorf(err, "", "struct-validation-error", common.GetComponentInfo()) return } @@ -1475,6 +1668,7 @@ func (resourceController *ResourceControllerV2) UpdateResourceBindingWithContext builder.EnableGzipCompression = resourceController.GetEnableGzipCompression() _, err = builder.ResolveRequestURL(resourceController.Service.Options.URL, `/v2/resource_bindings/{id}`, pathParamsMap) if err != nil { + err = core.SDKErrorf(err, "", "url-resolve-error", common.GetComponentInfo()) return } @@ -1495,22 +1689,27 @@ func (resourceController *ResourceControllerV2) UpdateResourceBindingWithContext } _, err = builder.SetBodyContentJSON(body) if err != nil { + err = core.SDKErrorf(err, "", "set-json-body-error", common.GetComponentInfo()) return } request, err := builder.Build() if err != nil { + err = core.SDKErrorf(err, "", "build-error", common.GetComponentInfo()) return } var rawResponse map[string]json.RawMessage response, err = resourceController.Service.Request(request, &rawResponse) if err != nil { + core.EnrichHTTPProblem(err, "update_resource_binding", getServiceComponentInfo()) + err = core.SDKErrorf(err, "", "http-request-err", common.GetComponentInfo()) return } if rawResponse != nil { err = core.UnmarshalModel(rawResponse, "", &result, UnmarshalResourceBinding) if err != nil { + err = core.SDKErrorf(err, "", "unmarshal-resp-error", common.GetComponentInfo()) return } response.Result = result @@ -1522,13 +1721,16 @@ func (resourceController *ResourceControllerV2) UpdateResourceBindingWithContext // ListResourceAliases : Get a list of all resource aliases // View all of the resource aliases that exist for every resource instance. func (resourceController *ResourceControllerV2) ListResourceAliases(listResourceAliasesOptions *ListResourceAliasesOptions) (result *ResourceAliasesList, response *core.DetailedResponse, err error) { - return resourceController.ListResourceAliasesWithContext(context.Background(), listResourceAliasesOptions) + result, response, err = resourceController.ListResourceAliasesWithContext(context.Background(), listResourceAliasesOptions) + err = core.RepurposeSDKProblem(err, "") + return } // ListResourceAliasesWithContext is an alternate form of the ListResourceAliases method which supports a Context parameter func (resourceController *ResourceControllerV2) ListResourceAliasesWithContext(ctx context.Context, listResourceAliasesOptions *ListResourceAliasesOptions) (result *ResourceAliasesList, response *core.DetailedResponse, err error) { err = core.ValidateStruct(listResourceAliasesOptions, "listResourceAliasesOptions") if err != nil { + err = core.SDKErrorf(err, "", "struct-validation-error", common.GetComponentInfo()) return } @@ -1537,6 +1739,7 @@ func (resourceController *ResourceControllerV2) ListResourceAliasesWithContext(c builder.EnableGzipCompression = resourceController.GetEnableGzipCompression() _, err = builder.ResolveRequestURL(resourceController.Service.Options.URL, `/v2/resource_aliases`, nil) if err != nil { + err = core.SDKErrorf(err, "", "url-resolve-error", common.GetComponentInfo()) return } @@ -1583,17 +1786,21 @@ func (resourceController *ResourceControllerV2) ListResourceAliasesWithContext(c request, err := builder.Build() if err != nil { + err = core.SDKErrorf(err, "", "build-error", common.GetComponentInfo()) return } var rawResponse map[string]json.RawMessage response, err = resourceController.Service.Request(request, &rawResponse) if err != nil { + core.EnrichHTTPProblem(err, "list_resource_aliases", getServiceComponentInfo()) + err = core.SDKErrorf(err, "", "http-request-err", common.GetComponentInfo()) return } if rawResponse != nil { err = core.UnmarshalModel(rawResponse, "", &result, UnmarshalResourceAliasesList) if err != nil { + err = core.SDKErrorf(err, "", "unmarshal-resp-error", common.GetComponentInfo()) return } response.Result = result @@ -1605,17 +1812,21 @@ func (resourceController *ResourceControllerV2) ListResourceAliasesWithContext(c // CreateResourceAlias : Create a new resource alias // Alias a resource instance into a targeted environment's (name)space. func (resourceController *ResourceControllerV2) CreateResourceAlias(createResourceAliasOptions *CreateResourceAliasOptions) (result *ResourceAlias, response *core.DetailedResponse, err error) { - return resourceController.CreateResourceAliasWithContext(context.Background(), createResourceAliasOptions) + result, response, err = resourceController.CreateResourceAliasWithContext(context.Background(), createResourceAliasOptions) + err = core.RepurposeSDKProblem(err, "") + return } // CreateResourceAliasWithContext is an alternate form of the CreateResourceAlias method which supports a Context parameter func (resourceController *ResourceControllerV2) CreateResourceAliasWithContext(ctx context.Context, createResourceAliasOptions *CreateResourceAliasOptions) (result *ResourceAlias, response *core.DetailedResponse, err error) { err = core.ValidateNotNil(createResourceAliasOptions, "createResourceAliasOptions cannot be nil") if err != nil { + err = core.SDKErrorf(err, "", "unexpected-nil-param", common.GetComponentInfo()) return } err = core.ValidateStruct(createResourceAliasOptions, "createResourceAliasOptions") if err != nil { + err = core.SDKErrorf(err, "", "struct-validation-error", common.GetComponentInfo()) return } @@ -1624,6 +1835,7 @@ func (resourceController *ResourceControllerV2) CreateResourceAliasWithContext(c builder.EnableGzipCompression = resourceController.GetEnableGzipCompression() _, err = builder.ResolveRequestURL(resourceController.Service.Options.URL, `/v2/resource_aliases`, nil) if err != nil { + err = core.SDKErrorf(err, "", "url-resolve-error", common.GetComponentInfo()) return } @@ -1650,22 +1862,27 @@ func (resourceController *ResourceControllerV2) CreateResourceAliasWithContext(c } _, err = builder.SetBodyContentJSON(body) if err != nil { + err = core.SDKErrorf(err, "", "set-json-body-error", common.GetComponentInfo()) return } request, err := builder.Build() if err != nil { + err = core.SDKErrorf(err, "", "build-error", common.GetComponentInfo()) return } var rawResponse map[string]json.RawMessage response, err = resourceController.Service.Request(request, &rawResponse) if err != nil { + core.EnrichHTTPProblem(err, "create_resource_alias", getServiceComponentInfo()) + err = core.SDKErrorf(err, "", "http-request-err", common.GetComponentInfo()) return } if rawResponse != nil { err = core.UnmarshalModel(rawResponse, "", &result, UnmarshalResourceAlias) if err != nil { + err = core.SDKErrorf(err, "", "unmarshal-resp-error", common.GetComponentInfo()) return } response.Result = result @@ -1678,17 +1895,21 @@ func (resourceController *ResourceControllerV2) CreateResourceAliasWithContext(c // View a resource alias and all of its details, like who created it and the resource instance that it's associated // with. func (resourceController *ResourceControllerV2) GetResourceAlias(getResourceAliasOptions *GetResourceAliasOptions) (result *ResourceAlias, response *core.DetailedResponse, err error) { - return resourceController.GetResourceAliasWithContext(context.Background(), getResourceAliasOptions) + result, response, err = resourceController.GetResourceAliasWithContext(context.Background(), getResourceAliasOptions) + err = core.RepurposeSDKProblem(err, "") + return } // GetResourceAliasWithContext is an alternate form of the GetResourceAlias method which supports a Context parameter func (resourceController *ResourceControllerV2) GetResourceAliasWithContext(ctx context.Context, getResourceAliasOptions *GetResourceAliasOptions) (result *ResourceAlias, response *core.DetailedResponse, err error) { err = core.ValidateNotNil(getResourceAliasOptions, "getResourceAliasOptions cannot be nil") if err != nil { + err = core.SDKErrorf(err, "", "unexpected-nil-param", common.GetComponentInfo()) return } err = core.ValidateStruct(getResourceAliasOptions, "getResourceAliasOptions") if err != nil { + err = core.SDKErrorf(err, "", "struct-validation-error", common.GetComponentInfo()) return } @@ -1701,6 +1922,7 @@ func (resourceController *ResourceControllerV2) GetResourceAliasWithContext(ctx builder.EnableGzipCompression = resourceController.GetEnableGzipCompression() _, err = builder.ResolveRequestURL(resourceController.Service.Options.URL, `/v2/resource_aliases/{id}`, pathParamsMap) if err != nil { + err = core.SDKErrorf(err, "", "url-resolve-error", common.GetComponentInfo()) return } @@ -1716,17 +1938,21 @@ func (resourceController *ResourceControllerV2) GetResourceAliasWithContext(ctx request, err := builder.Build() if err != nil { + err = core.SDKErrorf(err, "", "build-error", common.GetComponentInfo()) return } var rawResponse map[string]json.RawMessage response, err = resourceController.Service.Request(request, &rawResponse) if err != nil { + core.EnrichHTTPProblem(err, "get_resource_alias", getServiceComponentInfo()) + err = core.SDKErrorf(err, "", "http-request-err", common.GetComponentInfo()) return } if rawResponse != nil { err = core.UnmarshalModel(rawResponse, "", &result, UnmarshalResourceAlias) if err != nil { + err = core.SDKErrorf(err, "", "unmarshal-resp-error", common.GetComponentInfo()) return } response.Result = result @@ -1739,17 +1965,21 @@ func (resourceController *ResourceControllerV2) GetResourceAliasWithContext(ctx // Delete a resource alias by URL-encoded CRN or GUID. If the resource alias has any resource keys or bindings // associated with it, use the `recursive=true` parameter to delete it. func (resourceController *ResourceControllerV2) DeleteResourceAlias(deleteResourceAliasOptions *DeleteResourceAliasOptions) (response *core.DetailedResponse, err error) { - return resourceController.DeleteResourceAliasWithContext(context.Background(), deleteResourceAliasOptions) + response, err = resourceController.DeleteResourceAliasWithContext(context.Background(), deleteResourceAliasOptions) + err = core.RepurposeSDKProblem(err, "") + return } // DeleteResourceAliasWithContext is an alternate form of the DeleteResourceAlias method which supports a Context parameter func (resourceController *ResourceControllerV2) DeleteResourceAliasWithContext(ctx context.Context, deleteResourceAliasOptions *DeleteResourceAliasOptions) (response *core.DetailedResponse, err error) { err = core.ValidateNotNil(deleteResourceAliasOptions, "deleteResourceAliasOptions cannot be nil") if err != nil { + err = core.SDKErrorf(err, "", "unexpected-nil-param", common.GetComponentInfo()) return } err = core.ValidateStruct(deleteResourceAliasOptions, "deleteResourceAliasOptions") if err != nil { + err = core.SDKErrorf(err, "", "struct-validation-error", common.GetComponentInfo()) return } @@ -1762,6 +1992,7 @@ func (resourceController *ResourceControllerV2) DeleteResourceAliasWithContext(c builder.EnableGzipCompression = resourceController.GetEnableGzipCompression() _, err = builder.ResolveRequestURL(resourceController.Service.Options.URL, `/v2/resource_aliases/{id}`, pathParamsMap) if err != nil { + err = core.SDKErrorf(err, "", "url-resolve-error", common.GetComponentInfo()) return } @@ -1780,10 +2011,16 @@ func (resourceController *ResourceControllerV2) DeleteResourceAliasWithContext(c request, err := builder.Build() if err != nil { + err = core.SDKErrorf(err, "", "build-error", common.GetComponentInfo()) return } response, err = resourceController.Service.Request(request, nil) + if err != nil { + core.EnrichHTTPProblem(err, "delete_resource_alias", getServiceComponentInfo()) + err = core.SDKErrorf(err, "", "http-request-err", common.GetComponentInfo()) + return + } return } @@ -1791,17 +2028,21 @@ func (resourceController *ResourceControllerV2) DeleteResourceAliasWithContext(c // UpdateResourceAlias : Update a resource alias // Use the resource alias URL-encoded CRN or GUID to update the resource alias. func (resourceController *ResourceControllerV2) UpdateResourceAlias(updateResourceAliasOptions *UpdateResourceAliasOptions) (result *ResourceAlias, response *core.DetailedResponse, err error) { - return resourceController.UpdateResourceAliasWithContext(context.Background(), updateResourceAliasOptions) + result, response, err = resourceController.UpdateResourceAliasWithContext(context.Background(), updateResourceAliasOptions) + err = core.RepurposeSDKProblem(err, "") + return } // UpdateResourceAliasWithContext is an alternate form of the UpdateResourceAlias method which supports a Context parameter func (resourceController *ResourceControllerV2) UpdateResourceAliasWithContext(ctx context.Context, updateResourceAliasOptions *UpdateResourceAliasOptions) (result *ResourceAlias, response *core.DetailedResponse, err error) { err = core.ValidateNotNil(updateResourceAliasOptions, "updateResourceAliasOptions cannot be nil") if err != nil { + err = core.SDKErrorf(err, "", "unexpected-nil-param", common.GetComponentInfo()) return } err = core.ValidateStruct(updateResourceAliasOptions, "updateResourceAliasOptions") if err != nil { + err = core.SDKErrorf(err, "", "struct-validation-error", common.GetComponentInfo()) return } @@ -1814,6 +2055,7 @@ func (resourceController *ResourceControllerV2) UpdateResourceAliasWithContext(c builder.EnableGzipCompression = resourceController.GetEnableGzipCompression() _, err = builder.ResolveRequestURL(resourceController.Service.Options.URL, `/v2/resource_aliases/{id}`, pathParamsMap) if err != nil { + err = core.SDKErrorf(err, "", "url-resolve-error", common.GetComponentInfo()) return } @@ -1834,22 +2076,27 @@ func (resourceController *ResourceControllerV2) UpdateResourceAliasWithContext(c } _, err = builder.SetBodyContentJSON(body) if err != nil { + err = core.SDKErrorf(err, "", "set-json-body-error", common.GetComponentInfo()) return } request, err := builder.Build() if err != nil { + err = core.SDKErrorf(err, "", "build-error", common.GetComponentInfo()) return } var rawResponse map[string]json.RawMessage response, err = resourceController.Service.Request(request, &rawResponse) if err != nil { + core.EnrichHTTPProblem(err, "update_resource_alias", getServiceComponentInfo()) + err = core.SDKErrorf(err, "", "http-request-err", common.GetComponentInfo()) return } if rawResponse != nil { err = core.UnmarshalModel(rawResponse, "", &result, UnmarshalResourceAlias) if err != nil { + err = core.SDKErrorf(err, "", "unmarshal-resp-error", common.GetComponentInfo()) return } response.Result = result @@ -1861,17 +2108,21 @@ func (resourceController *ResourceControllerV2) UpdateResourceAliasWithContext(c // ListResourceBindingsForAlias : Get a list of all resource bindings for the alias // View all of the resource bindings associated with a specific resource alias. func (resourceController *ResourceControllerV2) ListResourceBindingsForAlias(listResourceBindingsForAliasOptions *ListResourceBindingsForAliasOptions) (result *ResourceBindingsList, response *core.DetailedResponse, err error) { - return resourceController.ListResourceBindingsForAliasWithContext(context.Background(), listResourceBindingsForAliasOptions) + result, response, err = resourceController.ListResourceBindingsForAliasWithContext(context.Background(), listResourceBindingsForAliasOptions) + err = core.RepurposeSDKProblem(err, "") + return } // ListResourceBindingsForAliasWithContext is an alternate form of the ListResourceBindingsForAlias method which supports a Context parameter func (resourceController *ResourceControllerV2) ListResourceBindingsForAliasWithContext(ctx context.Context, listResourceBindingsForAliasOptions *ListResourceBindingsForAliasOptions) (result *ResourceBindingsList, response *core.DetailedResponse, err error) { err = core.ValidateNotNil(listResourceBindingsForAliasOptions, "listResourceBindingsForAliasOptions cannot be nil") if err != nil { + err = core.SDKErrorf(err, "", "unexpected-nil-param", common.GetComponentInfo()) return } err = core.ValidateStruct(listResourceBindingsForAliasOptions, "listResourceBindingsForAliasOptions") if err != nil { + err = core.SDKErrorf(err, "", "struct-validation-error", common.GetComponentInfo()) return } @@ -1884,6 +2135,7 @@ func (resourceController *ResourceControllerV2) ListResourceBindingsForAliasWith builder.EnableGzipCompression = resourceController.GetEnableGzipCompression() _, err = builder.ResolveRequestURL(resourceController.Service.Options.URL, `/v2/resource_aliases/{id}/resource_bindings`, pathParamsMap) if err != nil { + err = core.SDKErrorf(err, "", "url-resolve-error", common.GetComponentInfo()) return } @@ -1906,17 +2158,21 @@ func (resourceController *ResourceControllerV2) ListResourceBindingsForAliasWith request, err := builder.Build() if err != nil { + err = core.SDKErrorf(err, "", "build-error", common.GetComponentInfo()) return } var rawResponse map[string]json.RawMessage response, err = resourceController.Service.Request(request, &rawResponse) if err != nil { + core.EnrichHTTPProblem(err, "list_resource_bindings_for_alias", getServiceComponentInfo()) + err = core.SDKErrorf(err, "", "http-request-err", common.GetComponentInfo()) return } if rawResponse != nil { err = core.UnmarshalModel(rawResponse, "", &result, UnmarshalResourceBindingsList) if err != nil { + err = core.SDKErrorf(err, "", "unmarshal-resp-error", common.GetComponentInfo()) return } response.Result = result @@ -1928,13 +2184,16 @@ func (resourceController *ResourceControllerV2) ListResourceBindingsForAliasWith // ListReclamations : Get a list of all reclamations // View all of the resource reclamations that exist for every resource instance. func (resourceController *ResourceControllerV2) ListReclamations(listReclamationsOptions *ListReclamationsOptions) (result *ReclamationsList, response *core.DetailedResponse, err error) { - return resourceController.ListReclamationsWithContext(context.Background(), listReclamationsOptions) + result, response, err = resourceController.ListReclamationsWithContext(context.Background(), listReclamationsOptions) + err = core.RepurposeSDKProblem(err, "") + return } // ListReclamationsWithContext is an alternate form of the ListReclamations method which supports a Context parameter func (resourceController *ResourceControllerV2) ListReclamationsWithContext(ctx context.Context, listReclamationsOptions *ListReclamationsOptions) (result *ReclamationsList, response *core.DetailedResponse, err error) { err = core.ValidateStruct(listReclamationsOptions, "listReclamationsOptions") if err != nil { + err = core.SDKErrorf(err, "", "struct-validation-error", common.GetComponentInfo()) return } @@ -1943,6 +2202,7 @@ func (resourceController *ResourceControllerV2) ListReclamationsWithContext(ctx builder.EnableGzipCompression = resourceController.GetEnableGzipCompression() _, err = builder.ResolveRequestURL(resourceController.Service.Options.URL, `/v1/reclamations`, nil) if err != nil { + err = core.SDKErrorf(err, "", "url-resolve-error", common.GetComponentInfo()) return } @@ -1968,17 +2228,21 @@ func (resourceController *ResourceControllerV2) ListReclamationsWithContext(ctx request, err := builder.Build() if err != nil { + err = core.SDKErrorf(err, "", "build-error", common.GetComponentInfo()) return } var rawResponse map[string]json.RawMessage response, err = resourceController.Service.Request(request, &rawResponse) if err != nil { + core.EnrichHTTPProblem(err, "list_reclamations", getServiceComponentInfo()) + err = core.SDKErrorf(err, "", "http-request-err", common.GetComponentInfo()) return } if rawResponse != nil { err = core.UnmarshalModel(rawResponse, "", &result, UnmarshalReclamationsList) if err != nil { + err = core.SDKErrorf(err, "", "unmarshal-resp-error", common.GetComponentInfo()) return } response.Result = result @@ -1991,17 +2255,21 @@ func (resourceController *ResourceControllerV2) ListReclamationsWithContext(ctx // Reclaim a resource instance so that it can no longer be used, or restore the resource instance so that it's usable // again. func (resourceController *ResourceControllerV2) RunReclamationAction(runReclamationActionOptions *RunReclamationActionOptions) (result *Reclamation, response *core.DetailedResponse, err error) { - return resourceController.RunReclamationActionWithContext(context.Background(), runReclamationActionOptions) + result, response, err = resourceController.RunReclamationActionWithContext(context.Background(), runReclamationActionOptions) + err = core.RepurposeSDKProblem(err, "") + return } // RunReclamationActionWithContext is an alternate form of the RunReclamationAction method which supports a Context parameter func (resourceController *ResourceControllerV2) RunReclamationActionWithContext(ctx context.Context, runReclamationActionOptions *RunReclamationActionOptions) (result *Reclamation, response *core.DetailedResponse, err error) { err = core.ValidateNotNil(runReclamationActionOptions, "runReclamationActionOptions cannot be nil") if err != nil { + err = core.SDKErrorf(err, "", "unexpected-nil-param", common.GetComponentInfo()) return } err = core.ValidateStruct(runReclamationActionOptions, "runReclamationActionOptions") if err != nil { + err = core.SDKErrorf(err, "", "struct-validation-error", common.GetComponentInfo()) return } @@ -2015,6 +2283,7 @@ func (resourceController *ResourceControllerV2) RunReclamationActionWithContext( builder.EnableGzipCompression = resourceController.GetEnableGzipCompression() _, err = builder.ResolveRequestURL(resourceController.Service.Options.URL, `/v1/reclamations/{id}/actions/{action_name}`, pathParamsMap) if err != nil { + err = core.SDKErrorf(err, "", "url-resolve-error", common.GetComponentInfo()) return } @@ -2038,22 +2307,27 @@ func (resourceController *ResourceControllerV2) RunReclamationActionWithContext( } _, err = builder.SetBodyContentJSON(body) if err != nil { + err = core.SDKErrorf(err, "", "set-json-body-error", common.GetComponentInfo()) return } request, err := builder.Build() if err != nil { + err = core.SDKErrorf(err, "", "build-error", common.GetComponentInfo()) return } var rawResponse map[string]json.RawMessage response, err = resourceController.Service.Request(request, &rawResponse) if err != nil { + core.EnrichHTTPProblem(err, "run_reclamation_action", getServiceComponentInfo()) + err = core.SDKErrorf(err, "", "http-request-err", common.GetComponentInfo()) return } if rawResponse != nil { err = core.UnmarshalModel(rawResponse, "", &result, UnmarshalReclamation) if err != nil { + err = core.SDKErrorf(err, "", "unmarshal-resp-error", common.GetComponentInfo()) return } response.Result = result @@ -2061,6 +2335,9 @@ func (resourceController *ResourceControllerV2) RunReclamationActionWithContext( return } +func getServiceComponentInfo() *core.ProblemComponent { + return core.NewProblemComponent(DefaultServiceName, "2.0") +} // CancelLastopResourceInstanceOptions : The CancelLastopResourceInstance options. type CancelLastopResourceInstanceOptions struct { @@ -2230,7 +2507,9 @@ type CreateResourceInstanceOptions struct { // instance delete call. AllowCleanup *bool `json:"allow_cleanup,omitempty"` - // Configuration options represented as key-value pairs that are passed through to the target resource brokers. + // Configuration options represented as key-value pairs that are passed through to the target resource brokers. Set the + // `onetime_credentials` property to specify whether newly created resource key credentials can be retrieved by using + // get resource key or get a list of all of the resource keys requests. Parameters map[string]interface{} `json:"parameters,omitempty"` // Indicates if the resource instance is locked for further update or delete operations. It does not affect actions @@ -2453,6 +2732,9 @@ func (o *Credentials) MarshalJSON() (buffer []byte, err error) { m["iam_serviceid_crn"] = o.IamServiceidCRN } buffer, err = json.Marshal(m) + if err != nil { + err = core.SDKErrorf(err, "", "model-marshal", common.GetComponentInfo()) + } return } @@ -2461,31 +2743,37 @@ func UnmarshalCredentials(m map[string]json.RawMessage, result interface{}) (err obj := new(Credentials) err = core.UnmarshalPrimitive(m, "REDACTED", &obj.Redacted) if err != nil { + err = core.SDKErrorf(err, "", "REDACTED-error", common.GetComponentInfo()) return } delete(m, "REDACTED") err = core.UnmarshalPrimitive(m, "apikey", &obj.Apikey) if err != nil { + err = core.SDKErrorf(err, "", "apikey-error", common.GetComponentInfo()) return } delete(m, "apikey") err = core.UnmarshalPrimitive(m, "iam_apikey_description", &obj.IamApikeyDescription) if err != nil { + err = core.SDKErrorf(err, "", "iam_apikey_description-error", common.GetComponentInfo()) return } delete(m, "iam_apikey_description") err = core.UnmarshalPrimitive(m, "iam_apikey_name", &obj.IamApikeyName) if err != nil { + err = core.SDKErrorf(err, "", "iam_apikey_name-error", common.GetComponentInfo()) return } delete(m, "iam_apikey_name") err = core.UnmarshalPrimitive(m, "iam_role_crn", &obj.IamRoleCRN) if err != nil { + err = core.SDKErrorf(err, "", "iam_role_crn-error", common.GetComponentInfo()) return } delete(m, "iam_role_crn") err = core.UnmarshalPrimitive(m, "iam_serviceid_crn", &obj.IamServiceidCRN) if err != nil { + err = core.SDKErrorf(err, "", "iam_serviceid_crn-error", common.GetComponentInfo()) return } delete(m, "iam_serviceid_crn") @@ -2493,7 +2781,7 @@ func UnmarshalCredentials(m map[string]json.RawMessage, result interface{}) (err var v interface{} e := core.UnmarshalPrimitive(m, k, &v) if e != nil { - err = e + err = core.SDKErrorf(e, "", "additional-properties-error", common.GetComponentInfo()) return } obj.SetProperty(k, v) @@ -3417,14 +3705,17 @@ func UnmarshalPlanHistoryItem(m map[string]json.RawMessage, result interface{}) obj := new(PlanHistoryItem) err = core.UnmarshalPrimitive(m, "resource_plan_id", &obj.ResourcePlanID) if err != nil { + err = core.SDKErrorf(err, "", "resource_plan_id-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "start_date", &obj.StartDate) if err != nil { + err = core.SDKErrorf(err, "", "start_date-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "requestor_id", &obj.RequestorID) if err != nil { + err = core.SDKErrorf(err, "", "requestor_id-error", common.GetComponentInfo()) return } reflect.ValueOf(result).Elem().Set(reflect.ValueOf(obj)) @@ -3485,62 +3776,77 @@ func UnmarshalReclamation(m map[string]json.RawMessage, result interface{}) (err obj := new(Reclamation) err = core.UnmarshalPrimitive(m, "id", &obj.ID) if err != nil { + err = core.SDKErrorf(err, "", "id-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "entity_id", &obj.EntityID) if err != nil { + err = core.SDKErrorf(err, "", "entity_id-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "entity_type_id", &obj.EntityTypeID) if err != nil { + err = core.SDKErrorf(err, "", "entity_type_id-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "entity_crn", &obj.EntityCRN) if err != nil { + err = core.SDKErrorf(err, "", "entity_crn-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "resource_instance_id", &obj.ResourceInstanceID) if err != nil { + err = core.SDKErrorf(err, "", "resource_instance_id-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "resource_group_id", &obj.ResourceGroupID) if err != nil { + err = core.SDKErrorf(err, "", "resource_group_id-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "account_id", &obj.AccountID) if err != nil { + err = core.SDKErrorf(err, "", "account_id-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "policy_id", &obj.PolicyID) if err != nil { + err = core.SDKErrorf(err, "", "policy_id-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "state", &obj.State) if err != nil { + err = core.SDKErrorf(err, "", "state-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "target_time", &obj.TargetTime) if err != nil { + err = core.SDKErrorf(err, "", "target_time-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "custom_properties", &obj.CustomProperties) if err != nil { + err = core.SDKErrorf(err, "", "custom_properties-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "created_at", &obj.CreatedAt) if err != nil { + err = core.SDKErrorf(err, "", "created_at-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "created_by", &obj.CreatedBy) if err != nil { + err = core.SDKErrorf(err, "", "created_by-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "updated_at", &obj.UpdatedAt) if err != nil { + err = core.SDKErrorf(err, "", "updated_at-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "updated_by", &obj.UpdatedBy) if err != nil { + err = core.SDKErrorf(err, "", "updated_by-error", common.GetComponentInfo()) return } reflect.ValueOf(result).Elem().Set(reflect.ValueOf(obj)) @@ -3558,6 +3864,7 @@ func UnmarshalReclamationsList(m map[string]json.RawMessage, result interface{}) obj := new(ReclamationsList) err = core.UnmarshalModel(m, "resources", &obj.Resources, UnmarshalReclamation) if err != nil { + err = core.SDKErrorf(err, "", "resources-error", common.GetComponentInfo()) return } reflect.ValueOf(result).Elem().Set(reflect.ValueOf(obj)) @@ -3643,94 +3950,117 @@ func UnmarshalResourceAlias(m map[string]json.RawMessage, result interface{}) (e obj := new(ResourceAlias) err = core.UnmarshalPrimitive(m, "id", &obj.ID) if err != nil { + err = core.SDKErrorf(err, "", "id-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "guid", &obj.GUID) if err != nil { + err = core.SDKErrorf(err, "", "guid-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "url", &obj.URL) if err != nil { + err = core.SDKErrorf(err, "", "url-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "created_at", &obj.CreatedAt) if err != nil { + err = core.SDKErrorf(err, "", "created_at-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "updated_at", &obj.UpdatedAt) if err != nil { + err = core.SDKErrorf(err, "", "updated_at-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "deleted_at", &obj.DeletedAt) if err != nil { + err = core.SDKErrorf(err, "", "deleted_at-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "created_by", &obj.CreatedBy) if err != nil { + err = core.SDKErrorf(err, "", "created_by-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "updated_by", &obj.UpdatedBy) if err != nil { + err = core.SDKErrorf(err, "", "updated_by-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "deleted_by", &obj.DeletedBy) if err != nil { + err = core.SDKErrorf(err, "", "deleted_by-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "name", &obj.Name) if err != nil { + err = core.SDKErrorf(err, "", "name-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "resource_instance_id", &obj.ResourceInstanceID) if err != nil { + err = core.SDKErrorf(err, "", "resource_instance_id-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "target_crn", &obj.TargetCRN) if err != nil { + err = core.SDKErrorf(err, "", "target_crn-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "account_id", &obj.AccountID) if err != nil { + err = core.SDKErrorf(err, "", "account_id-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "resource_id", &obj.ResourceID) if err != nil { + err = core.SDKErrorf(err, "", "resource_id-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "resource_group_id", &obj.ResourceGroupID) if err != nil { + err = core.SDKErrorf(err, "", "resource_group_id-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "crn", &obj.CRN) if err != nil { + err = core.SDKErrorf(err, "", "crn-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "region_instance_id", &obj.RegionInstanceID) if err != nil { + err = core.SDKErrorf(err, "", "region_instance_id-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "region_instance_crn", &obj.RegionInstanceCRN) if err != nil { + err = core.SDKErrorf(err, "", "region_instance_crn-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "state", &obj.State) if err != nil { + err = core.SDKErrorf(err, "", "state-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "migrated", &obj.Migrated) if err != nil { + err = core.SDKErrorf(err, "", "migrated-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "resource_instance_url", &obj.ResourceInstanceURL) if err != nil { + err = core.SDKErrorf(err, "", "resource_instance_url-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "resource_bindings_url", &obj.ResourceBindingsURL) if err != nil { + err = core.SDKErrorf(err, "", "resource_bindings_url-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "resource_keys_url", &obj.ResourceKeysURL) if err != nil { + err = core.SDKErrorf(err, "", "resource_keys_url-error", common.GetComponentInfo()) return } reflect.ValueOf(result).Elem().Set(reflect.ValueOf(obj)) @@ -3754,14 +4084,17 @@ func UnmarshalResourceAliasesList(m map[string]json.RawMessage, result interface obj := new(ResourceAliasesList) err = core.UnmarshalPrimitive(m, "rows_count", &obj.RowsCount) if err != nil { + err = core.SDKErrorf(err, "", "rows_count-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "next_url", &obj.NextURL) if err != nil { + err = core.SDKErrorf(err, "", "next_url-error", common.GetComponentInfo()) return } err = core.UnmarshalModel(m, "resources", &obj.Resources, UnmarshalResourceAlias) if err != nil { + err = core.SDKErrorf(err, "", "resources-error", common.GetComponentInfo()) return } reflect.ValueOf(result).Elem().Set(reflect.ValueOf(obj)) @@ -3774,8 +4107,11 @@ func (resp *ResourceAliasesList) GetNextStart() (*string, error) { return nil, nil } start, err := core.GetQueryParam(resp.NextURL, "start") - if err != nil || start == nil { + if err != nil { + err = core.SDKErrorf(err, "", "read-query-param-error", common.GetComponentInfo()) return nil, err + } else if start == nil { + return nil, nil } return start, nil } @@ -3863,94 +4199,117 @@ func UnmarshalResourceBinding(m map[string]json.RawMessage, result interface{}) obj := new(ResourceBinding) err = core.UnmarshalPrimitive(m, "id", &obj.ID) if err != nil { + err = core.SDKErrorf(err, "", "id-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "guid", &obj.GUID) if err != nil { + err = core.SDKErrorf(err, "", "guid-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "url", &obj.URL) if err != nil { + err = core.SDKErrorf(err, "", "url-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "created_at", &obj.CreatedAt) if err != nil { + err = core.SDKErrorf(err, "", "created_at-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "updated_at", &obj.UpdatedAt) if err != nil { + err = core.SDKErrorf(err, "", "updated_at-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "deleted_at", &obj.DeletedAt) if err != nil { + err = core.SDKErrorf(err, "", "deleted_at-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "created_by", &obj.CreatedBy) if err != nil { + err = core.SDKErrorf(err, "", "created_by-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "updated_by", &obj.UpdatedBy) if err != nil { + err = core.SDKErrorf(err, "", "updated_by-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "deleted_by", &obj.DeletedBy) if err != nil { + err = core.SDKErrorf(err, "", "deleted_by-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "source_crn", &obj.SourceCRN) if err != nil { + err = core.SDKErrorf(err, "", "source_crn-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "target_crn", &obj.TargetCRN) if err != nil { + err = core.SDKErrorf(err, "", "target_crn-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "crn", &obj.CRN) if err != nil { + err = core.SDKErrorf(err, "", "crn-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "region_binding_id", &obj.RegionBindingID) if err != nil { + err = core.SDKErrorf(err, "", "region_binding_id-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "region_binding_crn", &obj.RegionBindingCRN) if err != nil { + err = core.SDKErrorf(err, "", "region_binding_crn-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "name", &obj.Name) if err != nil { + err = core.SDKErrorf(err, "", "name-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "account_id", &obj.AccountID) if err != nil { + err = core.SDKErrorf(err, "", "account_id-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "resource_group_id", &obj.ResourceGroupID) if err != nil { + err = core.SDKErrorf(err, "", "resource_group_id-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "state", &obj.State) if err != nil { + err = core.SDKErrorf(err, "", "state-error", common.GetComponentInfo()) return } err = core.UnmarshalModel(m, "credentials", &obj.Credentials, UnmarshalCredentials) if err != nil { + err = core.SDKErrorf(err, "", "credentials-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "iam_compatible", &obj.IamCompatible) if err != nil { + err = core.SDKErrorf(err, "", "iam_compatible-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "resource_id", &obj.ResourceID) if err != nil { + err = core.SDKErrorf(err, "", "resource_id-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "migrated", &obj.Migrated) if err != nil { + err = core.SDKErrorf(err, "", "migrated-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "resource_alias_url", &obj.ResourceAliasURL) if err != nil { + err = core.SDKErrorf(err, "", "resource_alias_url-error", common.GetComponentInfo()) return } reflect.ValueOf(result).Elem().Set(reflect.ValueOf(obj)) @@ -4005,6 +4364,9 @@ func (o *ResourceBindingPostParameters) MarshalJSON() (buffer []byte, err error) m["serviceid_crn"] = o.ServiceidCRN } buffer, err = json.Marshal(m) + if err != nil { + err = core.SDKErrorf(err, "", "model-marshal", common.GetComponentInfo()) + } return } @@ -4013,6 +4375,7 @@ func UnmarshalResourceBindingPostParameters(m map[string]json.RawMessage, result obj := new(ResourceBindingPostParameters) err = core.UnmarshalPrimitive(m, "serviceid_crn", &obj.ServiceidCRN) if err != nil { + err = core.SDKErrorf(err, "", "serviceid_crn-error", common.GetComponentInfo()) return } delete(m, "serviceid_crn") @@ -4020,7 +4383,7 @@ func UnmarshalResourceBindingPostParameters(m map[string]json.RawMessage, result var v interface{} e := core.UnmarshalPrimitive(m, k, &v) if e != nil { - err = e + err = core.SDKErrorf(e, "", "additional-properties-error", common.GetComponentInfo()) return } obj.SetProperty(k, v) @@ -4046,14 +4409,17 @@ func UnmarshalResourceBindingsList(m map[string]json.RawMessage, result interfac obj := new(ResourceBindingsList) err = core.UnmarshalPrimitive(m, "rows_count", &obj.RowsCount) if err != nil { + err = core.SDKErrorf(err, "", "rows_count-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "next_url", &obj.NextURL) if err != nil { + err = core.SDKErrorf(err, "", "next_url-error", common.GetComponentInfo()) return } err = core.UnmarshalModel(m, "resources", &obj.Resources, UnmarshalResourceBinding) if err != nil { + err = core.SDKErrorf(err, "", "resources-error", common.GetComponentInfo()) return } reflect.ValueOf(result).Elem().Set(reflect.ValueOf(obj)) @@ -4066,8 +4432,11 @@ func (resp *ResourceBindingsList) GetNextStart() (*string, error) { return nil, nil } start, err := core.GetQueryParam(resp.NextURL, "start") - if err != nil || start == nil { + if err != nil { + err = core.SDKErrorf(err, "", "read-query-param-error", common.GetComponentInfo()) return nil, err + } else if start == nil { + return nil, nil } return start, nil } @@ -4138,6 +4507,10 @@ type ResourceInstance struct { // the instance is provisioned. TargetCRN *string `json:"target_crn,omitempty"` + // Whether newly created resource key credentials can be retrieved by using get resource key or get a list of all of + // the resource keys requests. + OnetimeCredentials *bool `json:"onetime_credentials,omitempty"` + // The current configuration parameters of the instance. Parameters map[string]interface{} `json:"parameters,omitempty"` @@ -4210,154 +4583,197 @@ func UnmarshalResourceInstance(m map[string]json.RawMessage, result interface{}) obj := new(ResourceInstance) err = core.UnmarshalPrimitive(m, "id", &obj.ID) if err != nil { + err = core.SDKErrorf(err, "", "id-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "guid", &obj.GUID) if err != nil { + err = core.SDKErrorf(err, "", "guid-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "url", &obj.URL) if err != nil { + err = core.SDKErrorf(err, "", "url-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "created_at", &obj.CreatedAt) if err != nil { + err = core.SDKErrorf(err, "", "created_at-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "updated_at", &obj.UpdatedAt) if err != nil { + err = core.SDKErrorf(err, "", "updated_at-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "deleted_at", &obj.DeletedAt) if err != nil { + err = core.SDKErrorf(err, "", "deleted_at-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "created_by", &obj.CreatedBy) if err != nil { + err = core.SDKErrorf(err, "", "created_by-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "updated_by", &obj.UpdatedBy) if err != nil { + err = core.SDKErrorf(err, "", "updated_by-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "deleted_by", &obj.DeletedBy) if err != nil { + err = core.SDKErrorf(err, "", "deleted_by-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "scheduled_reclaim_at", &obj.ScheduledReclaimAt) if err != nil { + err = core.SDKErrorf(err, "", "scheduled_reclaim_at-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "restored_at", &obj.RestoredAt) if err != nil { + err = core.SDKErrorf(err, "", "restored_at-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "restored_by", &obj.RestoredBy) if err != nil { + err = core.SDKErrorf(err, "", "restored_by-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "scheduled_reclaim_by", &obj.ScheduledReclaimBy) if err != nil { + err = core.SDKErrorf(err, "", "scheduled_reclaim_by-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "name", &obj.Name) if err != nil { + err = core.SDKErrorf(err, "", "name-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "region_id", &obj.RegionID) if err != nil { + err = core.SDKErrorf(err, "", "region_id-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "account_id", &obj.AccountID) if err != nil { + err = core.SDKErrorf(err, "", "account_id-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "reseller_channel_id", &obj.ResellerChannelID) if err != nil { + err = core.SDKErrorf(err, "", "reseller_channel_id-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "resource_plan_id", &obj.ResourcePlanID) if err != nil { + err = core.SDKErrorf(err, "", "resource_plan_id-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "resource_group_id", &obj.ResourceGroupID) if err != nil { + err = core.SDKErrorf(err, "", "resource_group_id-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "resource_group_crn", &obj.ResourceGroupCRN) if err != nil { + err = core.SDKErrorf(err, "", "resource_group_crn-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "target_crn", &obj.TargetCRN) if err != nil { + err = core.SDKErrorf(err, "", "target_crn-error", common.GetComponentInfo()) + return + } + err = core.UnmarshalPrimitive(m, "onetime_credentials", &obj.OnetimeCredentials) + if err != nil { + err = core.SDKErrorf(err, "", "onetime_credentials-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "parameters", &obj.Parameters) if err != nil { + err = core.SDKErrorf(err, "", "parameters-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "allow_cleanup", &obj.AllowCleanup) if err != nil { + err = core.SDKErrorf(err, "", "allow_cleanup-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "crn", &obj.CRN) if err != nil { + err = core.SDKErrorf(err, "", "crn-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "state", &obj.State) if err != nil { + err = core.SDKErrorf(err, "", "state-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "type", &obj.Type) if err != nil { + err = core.SDKErrorf(err, "", "type-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "sub_type", &obj.SubType) if err != nil { + err = core.SDKErrorf(err, "", "sub_type-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "resource_id", &obj.ResourceID) if err != nil { + err = core.SDKErrorf(err, "", "resource_id-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "dashboard_url", &obj.DashboardURL) if err != nil { + err = core.SDKErrorf(err, "", "dashboard_url-error", common.GetComponentInfo()) return } err = core.UnmarshalModel(m, "last_operation", &obj.LastOperation, UnmarshalResourceInstanceLastOperation) if err != nil { + err = core.SDKErrorf(err, "", "last_operation-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "resource_aliases_url", &obj.ResourceAliasesURL) if err != nil { + err = core.SDKErrorf(err, "", "resource_aliases_url-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "resource_bindings_url", &obj.ResourceBindingsURL) if err != nil { + err = core.SDKErrorf(err, "", "resource_bindings_url-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "resource_keys_url", &obj.ResourceKeysURL) if err != nil { + err = core.SDKErrorf(err, "", "resource_keys_url-error", common.GetComponentInfo()) return } err = core.UnmarshalModel(m, "plan_history", &obj.PlanHistory, UnmarshalPlanHistoryItem) if err != nil { + err = core.SDKErrorf(err, "", "plan_history-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "migrated", &obj.Migrated) if err != nil { + err = core.SDKErrorf(err, "", "migrated-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "extensions", &obj.Extensions) if err != nil { + err = core.SDKErrorf(err, "", "extensions-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "controlled_by", &obj.ControlledBy) if err != nil { + err = core.SDKErrorf(err, "", "controlled_by-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "locked", &obj.Locked) if err != nil { + err = core.SDKErrorf(err, "", "locked-error", common.GetComponentInfo()) return } reflect.ValueOf(result).Elem().Set(reflect.ValueOf(obj)) @@ -4469,6 +4885,9 @@ func (o *ResourceInstanceLastOperation) MarshalJSON() (buffer []byte, err error) m["poll"] = o.Poll } buffer, err = json.Marshal(m) + if err != nil { + err = core.SDKErrorf(err, "", "model-marshal", common.GetComponentInfo()) + } return } @@ -4477,46 +4896,55 @@ func UnmarshalResourceInstanceLastOperation(m map[string]json.RawMessage, result obj := new(ResourceInstanceLastOperation) err = core.UnmarshalPrimitive(m, "type", &obj.Type) if err != nil { + err = core.SDKErrorf(err, "", "type-error", common.GetComponentInfo()) return } delete(m, "type") err = core.UnmarshalPrimitive(m, "state", &obj.State) if err != nil { + err = core.SDKErrorf(err, "", "state-error", common.GetComponentInfo()) return } delete(m, "state") err = core.UnmarshalPrimitive(m, "sub_type", &obj.SubType) if err != nil { + err = core.SDKErrorf(err, "", "sub_type-error", common.GetComponentInfo()) return } delete(m, "sub_type") err = core.UnmarshalPrimitive(m, "async", &obj.Async) if err != nil { + err = core.SDKErrorf(err, "", "async-error", common.GetComponentInfo()) return } delete(m, "async") err = core.UnmarshalPrimitive(m, "description", &obj.Description) if err != nil { + err = core.SDKErrorf(err, "", "description-error", common.GetComponentInfo()) return } delete(m, "description") err = core.UnmarshalPrimitive(m, "reason_code", &obj.ReasonCode) if err != nil { + err = core.SDKErrorf(err, "", "reason_code-error", common.GetComponentInfo()) return } delete(m, "reason_code") err = core.UnmarshalPrimitive(m, "poll_after", &obj.PollAfter) if err != nil { + err = core.SDKErrorf(err, "", "poll_after-error", common.GetComponentInfo()) return } delete(m, "poll_after") err = core.UnmarshalPrimitive(m, "cancelable", &obj.Cancelable) if err != nil { + err = core.SDKErrorf(err, "", "cancelable-error", common.GetComponentInfo()) return } delete(m, "cancelable") err = core.UnmarshalPrimitive(m, "poll", &obj.Poll) if err != nil { + err = core.SDKErrorf(err, "", "poll-error", common.GetComponentInfo()) return } delete(m, "poll") @@ -4524,7 +4952,7 @@ func UnmarshalResourceInstanceLastOperation(m map[string]json.RawMessage, result var v interface{} e := core.UnmarshalPrimitive(m, k, &v) if e != nil { - err = e + err = core.SDKErrorf(e, "", "additional-properties-error", common.GetComponentInfo()) return } obj.SetProperty(k, v) @@ -4550,14 +4978,17 @@ func UnmarshalResourceInstancesList(m map[string]json.RawMessage, result interfa obj := new(ResourceInstancesList) err = core.UnmarshalPrimitive(m, "rows_count", &obj.RowsCount) if err != nil { + err = core.SDKErrorf(err, "", "rows_count-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "next_url", &obj.NextURL) if err != nil { + err = core.SDKErrorf(err, "", "next_url-error", common.GetComponentInfo()) return } err = core.UnmarshalModel(m, "resources", &obj.Resources, UnmarshalResourceInstance) if err != nil { + err = core.SDKErrorf(err, "", "resources-error", common.GetComponentInfo()) return } reflect.ValueOf(result).Elem().Set(reflect.ValueOf(obj)) @@ -4570,8 +5001,11 @@ func (resp *ResourceInstancesList) GetNextStart() (*string, error) { return nil, nil } start, err := core.GetQueryParam(resp.NextURL, "start") - if err != nil || start == nil { + if err != nil { + err = core.SDKErrorf(err, "", "read-query-param-error", common.GetComponentInfo()) return nil, err + } else if start == nil { + return nil, nil } return start, nil } @@ -4627,6 +5061,10 @@ type ResourceKey struct { // The unique ID of the offering. This value is provided by and stored in the global catalog. ResourceID *string `json:"resource_id,omitempty"` + // Whether newly created resource key credentials can be retrieved by using get resource key or get a list of all of + // the resource keys requests. + OnetimeCredentials *bool `json:"onetime_credentials,omitempty"` + // The credentials for the key. Additional key-value pairs are passed through from the resource brokers. After a // credential is created for a service, it can be viewed at any time for users that need the API key value. However, // all users must have the correct level of access to see the details of a credential that includes the API key value. @@ -4653,86 +5091,112 @@ func UnmarshalResourceKey(m map[string]json.RawMessage, result interface{}) (err obj := new(ResourceKey) err = core.UnmarshalPrimitive(m, "id", &obj.ID) if err != nil { + err = core.SDKErrorf(err, "", "id-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "guid", &obj.GUID) if err != nil { + err = core.SDKErrorf(err, "", "guid-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "url", &obj.URL) if err != nil { + err = core.SDKErrorf(err, "", "url-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "created_at", &obj.CreatedAt) if err != nil { + err = core.SDKErrorf(err, "", "created_at-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "updated_at", &obj.UpdatedAt) if err != nil { + err = core.SDKErrorf(err, "", "updated_at-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "deleted_at", &obj.DeletedAt) if err != nil { + err = core.SDKErrorf(err, "", "deleted_at-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "created_by", &obj.CreatedBy) if err != nil { + err = core.SDKErrorf(err, "", "created_by-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "updated_by", &obj.UpdatedBy) if err != nil { + err = core.SDKErrorf(err, "", "updated_by-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "deleted_by", &obj.DeletedBy) if err != nil { + err = core.SDKErrorf(err, "", "deleted_by-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "source_crn", &obj.SourceCRN) if err != nil { + err = core.SDKErrorf(err, "", "source_crn-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "name", &obj.Name) if err != nil { + err = core.SDKErrorf(err, "", "name-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "crn", &obj.CRN) if err != nil { + err = core.SDKErrorf(err, "", "crn-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "state", &obj.State) if err != nil { + err = core.SDKErrorf(err, "", "state-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "account_id", &obj.AccountID) if err != nil { + err = core.SDKErrorf(err, "", "account_id-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "resource_group_id", &obj.ResourceGroupID) if err != nil { + err = core.SDKErrorf(err, "", "resource_group_id-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "resource_id", &obj.ResourceID) if err != nil { + err = core.SDKErrorf(err, "", "resource_id-error", common.GetComponentInfo()) + return + } + err = core.UnmarshalPrimitive(m, "onetime_credentials", &obj.OnetimeCredentials) + if err != nil { + err = core.SDKErrorf(err, "", "onetime_credentials-error", common.GetComponentInfo()) return } err = core.UnmarshalModel(m, "credentials", &obj.Credentials, UnmarshalCredentials) if err != nil { + err = core.SDKErrorf(err, "", "credentials-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "iam_compatible", &obj.IamCompatible) if err != nil { + err = core.SDKErrorf(err, "", "iam_compatible-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "migrated", &obj.Migrated) if err != nil { + err = core.SDKErrorf(err, "", "migrated-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "resource_instance_url", &obj.ResourceInstanceURL) if err != nil { + err = core.SDKErrorf(err, "", "resource_instance_url-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "resource_alias_url", &obj.ResourceAliasURL) if err != nil { + err = core.SDKErrorf(err, "", "resource_alias_url-error", common.GetComponentInfo()) return } reflect.ValueOf(result).Elem().Set(reflect.ValueOf(obj)) @@ -4787,6 +5251,9 @@ func (o *ResourceKeyPostParameters) MarshalJSON() (buffer []byte, err error) { m["serviceid_crn"] = o.ServiceidCRN } buffer, err = json.Marshal(m) + if err != nil { + err = core.SDKErrorf(err, "", "model-marshal", common.GetComponentInfo()) + } return } @@ -4795,6 +5262,7 @@ func UnmarshalResourceKeyPostParameters(m map[string]json.RawMessage, result int obj := new(ResourceKeyPostParameters) err = core.UnmarshalPrimitive(m, "serviceid_crn", &obj.ServiceidCRN) if err != nil { + err = core.SDKErrorf(err, "", "serviceid_crn-error", common.GetComponentInfo()) return } delete(m, "serviceid_crn") @@ -4802,7 +5270,7 @@ func UnmarshalResourceKeyPostParameters(m map[string]json.RawMessage, result int var v interface{} e := core.UnmarshalPrimitive(m, k, &v) if e != nil { - err = e + err = core.SDKErrorf(e, "", "additional-properties-error", common.GetComponentInfo()) return } obj.SetProperty(k, v) @@ -4828,14 +5296,17 @@ func UnmarshalResourceKeysList(m map[string]json.RawMessage, result interface{}) obj := new(ResourceKeysList) err = core.UnmarshalPrimitive(m, "rows_count", &obj.RowsCount) if err != nil { + err = core.SDKErrorf(err, "", "rows_count-error", common.GetComponentInfo()) return } err = core.UnmarshalPrimitive(m, "next_url", &obj.NextURL) if err != nil { + err = core.SDKErrorf(err, "", "next_url-error", common.GetComponentInfo()) return } err = core.UnmarshalModel(m, "resources", &obj.Resources, UnmarshalResourceKey) if err != nil { + err = core.SDKErrorf(err, "", "resources-error", common.GetComponentInfo()) return } reflect.ValueOf(result).Elem().Set(reflect.ValueOf(obj)) @@ -4848,8 +5319,11 @@ func (resp *ResourceKeysList) GetNextStart() (*string, error) { return nil, nil } start, err := core.GetQueryParam(resp.NextURL, "start") - if err != nil || start == nil { + if err != nil { + err = core.SDKErrorf(err, "", "read-query-param-error", common.GetComponentInfo()) return nil, err + } else if start == nil { + return nil, nil } return start, nil } @@ -5025,7 +5499,9 @@ type UpdateResourceInstanceOptions struct { // `(space) - . _ :`. Name *string `json:"name,omitempty"` - // The new configuration options for the instance. + // The new configuration options for the instance. Set the `onetime_credentials` property to specify whether newly + // created resource key credentials can be retrieved by using get resource key or get a list of all of the resource + // keys requests. Parameters map[string]interface{} `json:"parameters,omitempty"` // The unique ID of the plan associated with the offering. This value is provided by and stored in the global catalog. @@ -5134,7 +5610,7 @@ type ResourceInstancesPager struct { // NewResourceInstancesPager returns a new ResourceInstancesPager instance. func (resourceController *ResourceControllerV2) NewResourceInstancesPager(options *ListResourceInstancesOptions) (pager *ResourceInstancesPager, err error) { if options.Start != nil && *options.Start != "" { - err = fmt.Errorf("the 'options.Start' field should not be set") + err = core.SDKErrorf(nil, "the 'options.Start' field should not be set", "no-query-setting", common.GetComponentInfo()) return } @@ -5162,6 +5638,7 @@ func (pager *ResourceInstancesPager) GetNextWithContext(ctx context.Context) (pa result, _, err := pager.client.ListResourceInstancesWithContext(ctx, pager.options) if err != nil { + err = core.RepurposeSDKProblem(err, "error-getting-next-page") return } @@ -5170,7 +5647,8 @@ func (pager *ResourceInstancesPager) GetNextWithContext(ctx context.Context) (pa var start *string start, err = core.GetQueryParam(result.NextURL, "start") if err != nil { - err = fmt.Errorf("error retrieving 'start' query parameter from URL '%s': %s", *result.NextURL, err.Error()) + errMsg := fmt.Sprintf("error retrieving 'start' query parameter from URL '%s': %s", *result.NextURL, err.Error()) + err = core.SDKErrorf(err, errMsg, "get-query-error", common.GetComponentInfo()) return } next = start @@ -5189,6 +5667,7 @@ func (pager *ResourceInstancesPager) GetAllWithContext(ctx context.Context) (all var nextPage []ResourceInstance nextPage, err = pager.GetNextWithContext(ctx) if err != nil { + err = core.RepurposeSDKProblem(err, "error-getting-next-page") return } allItems = append(allItems, nextPage...) @@ -5198,12 +5677,16 @@ func (pager *ResourceInstancesPager) GetAllWithContext(ctx context.Context) (all // GetNext invokes GetNextWithContext() using context.Background() as the Context parameter. func (pager *ResourceInstancesPager) GetNext() (page []ResourceInstance, err error) { - return pager.GetNextWithContext(context.Background()) + page, err = pager.GetNextWithContext(context.Background()) + err = core.RepurposeSDKProblem(err, "") + return } // GetAll invokes GetAllWithContext() using context.Background() as the Context parameter. func (pager *ResourceInstancesPager) GetAll() (allItems []ResourceInstance, err error) { - return pager.GetAllWithContext(context.Background()) + allItems, err = pager.GetAllWithContext(context.Background()) + err = core.RepurposeSDKProblem(err, "") + return } // ResourceAliasesForInstancePager can be used to simplify the use of the "ListResourceAliasesForInstance" method. @@ -5219,7 +5702,7 @@ type ResourceAliasesForInstancePager struct { // NewResourceAliasesForInstancePager returns a new ResourceAliasesForInstancePager instance. func (resourceController *ResourceControllerV2) NewResourceAliasesForInstancePager(options *ListResourceAliasesForInstanceOptions) (pager *ResourceAliasesForInstancePager, err error) { if options.Start != nil && *options.Start != "" { - err = fmt.Errorf("the 'options.Start' field should not be set") + err = core.SDKErrorf(nil, "the 'options.Start' field should not be set", "no-query-setting", common.GetComponentInfo()) return } @@ -5247,6 +5730,7 @@ func (pager *ResourceAliasesForInstancePager) GetNextWithContext(ctx context.Con result, _, err := pager.client.ListResourceAliasesForInstanceWithContext(ctx, pager.options) if err != nil { + err = core.RepurposeSDKProblem(err, "error-getting-next-page") return } @@ -5255,7 +5739,8 @@ func (pager *ResourceAliasesForInstancePager) GetNextWithContext(ctx context.Con var start *string start, err = core.GetQueryParam(result.NextURL, "start") if err != nil { - err = fmt.Errorf("error retrieving 'start' query parameter from URL '%s': %s", *result.NextURL, err.Error()) + errMsg := fmt.Sprintf("error retrieving 'start' query parameter from URL '%s': %s", *result.NextURL, err.Error()) + err = core.SDKErrorf(err, errMsg, "get-query-error", common.GetComponentInfo()) return } next = start @@ -5274,6 +5759,7 @@ func (pager *ResourceAliasesForInstancePager) GetAllWithContext(ctx context.Cont var nextPage []ResourceAlias nextPage, err = pager.GetNextWithContext(ctx) if err != nil { + err = core.RepurposeSDKProblem(err, "error-getting-next-page") return } allItems = append(allItems, nextPage...) @@ -5283,12 +5769,16 @@ func (pager *ResourceAliasesForInstancePager) GetAllWithContext(ctx context.Cont // GetNext invokes GetNextWithContext() using context.Background() as the Context parameter. func (pager *ResourceAliasesForInstancePager) GetNext() (page []ResourceAlias, err error) { - return pager.GetNextWithContext(context.Background()) + page, err = pager.GetNextWithContext(context.Background()) + err = core.RepurposeSDKProblem(err, "") + return } // GetAll invokes GetAllWithContext() using context.Background() as the Context parameter. func (pager *ResourceAliasesForInstancePager) GetAll() (allItems []ResourceAlias, err error) { - return pager.GetAllWithContext(context.Background()) + allItems, err = pager.GetAllWithContext(context.Background()) + err = core.RepurposeSDKProblem(err, "") + return } // ResourceKeysForInstancePager can be used to simplify the use of the "ListResourceKeysForInstance" method. @@ -5304,7 +5794,7 @@ type ResourceKeysForInstancePager struct { // NewResourceKeysForInstancePager returns a new ResourceKeysForInstancePager instance. func (resourceController *ResourceControllerV2) NewResourceKeysForInstancePager(options *ListResourceKeysForInstanceOptions) (pager *ResourceKeysForInstancePager, err error) { if options.Start != nil && *options.Start != "" { - err = fmt.Errorf("the 'options.Start' field should not be set") + err = core.SDKErrorf(nil, "the 'options.Start' field should not be set", "no-query-setting", common.GetComponentInfo()) return } @@ -5332,6 +5822,7 @@ func (pager *ResourceKeysForInstancePager) GetNextWithContext(ctx context.Contex result, _, err := pager.client.ListResourceKeysForInstanceWithContext(ctx, pager.options) if err != nil { + err = core.RepurposeSDKProblem(err, "error-getting-next-page") return } @@ -5340,7 +5831,8 @@ func (pager *ResourceKeysForInstancePager) GetNextWithContext(ctx context.Contex var start *string start, err = core.GetQueryParam(result.NextURL, "start") if err != nil { - err = fmt.Errorf("error retrieving 'start' query parameter from URL '%s': %s", *result.NextURL, err.Error()) + errMsg := fmt.Sprintf("error retrieving 'start' query parameter from URL '%s': %s", *result.NextURL, err.Error()) + err = core.SDKErrorf(err, errMsg, "get-query-error", common.GetComponentInfo()) return } next = start @@ -5359,6 +5851,7 @@ func (pager *ResourceKeysForInstancePager) GetAllWithContext(ctx context.Context var nextPage []ResourceKey nextPage, err = pager.GetNextWithContext(ctx) if err != nil { + err = core.RepurposeSDKProblem(err, "error-getting-next-page") return } allItems = append(allItems, nextPage...) @@ -5368,12 +5861,16 @@ func (pager *ResourceKeysForInstancePager) GetAllWithContext(ctx context.Context // GetNext invokes GetNextWithContext() using context.Background() as the Context parameter. func (pager *ResourceKeysForInstancePager) GetNext() (page []ResourceKey, err error) { - return pager.GetNextWithContext(context.Background()) + page, err = pager.GetNextWithContext(context.Background()) + err = core.RepurposeSDKProblem(err, "") + return } // GetAll invokes GetAllWithContext() using context.Background() as the Context parameter. func (pager *ResourceKeysForInstancePager) GetAll() (allItems []ResourceKey, err error) { - return pager.GetAllWithContext(context.Background()) + allItems, err = pager.GetAllWithContext(context.Background()) + err = core.RepurposeSDKProblem(err, "") + return } // ResourceKeysPager can be used to simplify the use of the "ListResourceKeys" method. @@ -5389,7 +5886,7 @@ type ResourceKeysPager struct { // NewResourceKeysPager returns a new ResourceKeysPager instance. func (resourceController *ResourceControllerV2) NewResourceKeysPager(options *ListResourceKeysOptions) (pager *ResourceKeysPager, err error) { if options.Start != nil && *options.Start != "" { - err = fmt.Errorf("the 'options.Start' field should not be set") + err = core.SDKErrorf(nil, "the 'options.Start' field should not be set", "no-query-setting", common.GetComponentInfo()) return } @@ -5417,6 +5914,7 @@ func (pager *ResourceKeysPager) GetNextWithContext(ctx context.Context) (page [] result, _, err := pager.client.ListResourceKeysWithContext(ctx, pager.options) if err != nil { + err = core.RepurposeSDKProblem(err, "error-getting-next-page") return } @@ -5425,7 +5923,8 @@ func (pager *ResourceKeysPager) GetNextWithContext(ctx context.Context) (page [] var start *string start, err = core.GetQueryParam(result.NextURL, "start") if err != nil { - err = fmt.Errorf("error retrieving 'start' query parameter from URL '%s': %s", *result.NextURL, err.Error()) + errMsg := fmt.Sprintf("error retrieving 'start' query parameter from URL '%s': %s", *result.NextURL, err.Error()) + err = core.SDKErrorf(err, errMsg, "get-query-error", common.GetComponentInfo()) return } next = start @@ -5444,6 +5943,7 @@ func (pager *ResourceKeysPager) GetAllWithContext(ctx context.Context) (allItems var nextPage []ResourceKey nextPage, err = pager.GetNextWithContext(ctx) if err != nil { + err = core.RepurposeSDKProblem(err, "error-getting-next-page") return } allItems = append(allItems, nextPage...) @@ -5453,12 +5953,16 @@ func (pager *ResourceKeysPager) GetAllWithContext(ctx context.Context) (allItems // GetNext invokes GetNextWithContext() using context.Background() as the Context parameter. func (pager *ResourceKeysPager) GetNext() (page []ResourceKey, err error) { - return pager.GetNextWithContext(context.Background()) + page, err = pager.GetNextWithContext(context.Background()) + err = core.RepurposeSDKProblem(err, "") + return } // GetAll invokes GetAllWithContext() using context.Background() as the Context parameter. func (pager *ResourceKeysPager) GetAll() (allItems []ResourceKey, err error) { - return pager.GetAllWithContext(context.Background()) + allItems, err = pager.GetAllWithContext(context.Background()) + err = core.RepurposeSDKProblem(err, "") + return } // ResourceBindingsPager can be used to simplify the use of the "ListResourceBindings" method. @@ -5474,7 +5978,7 @@ type ResourceBindingsPager struct { // NewResourceBindingsPager returns a new ResourceBindingsPager instance. func (resourceController *ResourceControllerV2) NewResourceBindingsPager(options *ListResourceBindingsOptions) (pager *ResourceBindingsPager, err error) { if options.Start != nil && *options.Start != "" { - err = fmt.Errorf("the 'options.Start' field should not be set") + err = core.SDKErrorf(nil, "the 'options.Start' field should not be set", "no-query-setting", common.GetComponentInfo()) return } @@ -5502,6 +6006,7 @@ func (pager *ResourceBindingsPager) GetNextWithContext(ctx context.Context) (pag result, _, err := pager.client.ListResourceBindingsWithContext(ctx, pager.options) if err != nil { + err = core.RepurposeSDKProblem(err, "error-getting-next-page") return } @@ -5510,7 +6015,8 @@ func (pager *ResourceBindingsPager) GetNextWithContext(ctx context.Context) (pag var start *string start, err = core.GetQueryParam(result.NextURL, "start") if err != nil { - err = fmt.Errorf("error retrieving 'start' query parameter from URL '%s': %s", *result.NextURL, err.Error()) + errMsg := fmt.Sprintf("error retrieving 'start' query parameter from URL '%s': %s", *result.NextURL, err.Error()) + err = core.SDKErrorf(err, errMsg, "get-query-error", common.GetComponentInfo()) return } next = start @@ -5529,6 +6035,7 @@ func (pager *ResourceBindingsPager) GetAllWithContext(ctx context.Context) (allI var nextPage []ResourceBinding nextPage, err = pager.GetNextWithContext(ctx) if err != nil { + err = core.RepurposeSDKProblem(err, "error-getting-next-page") return } allItems = append(allItems, nextPage...) @@ -5538,12 +6045,16 @@ func (pager *ResourceBindingsPager) GetAllWithContext(ctx context.Context) (allI // GetNext invokes GetNextWithContext() using context.Background() as the Context parameter. func (pager *ResourceBindingsPager) GetNext() (page []ResourceBinding, err error) { - return pager.GetNextWithContext(context.Background()) + page, err = pager.GetNextWithContext(context.Background()) + err = core.RepurposeSDKProblem(err, "") + return } // GetAll invokes GetAllWithContext() using context.Background() as the Context parameter. func (pager *ResourceBindingsPager) GetAll() (allItems []ResourceBinding, err error) { - return pager.GetAllWithContext(context.Background()) + allItems, err = pager.GetAllWithContext(context.Background()) + err = core.RepurposeSDKProblem(err, "") + return } // ResourceAliasesPager can be used to simplify the use of the "ListResourceAliases" method. @@ -5559,7 +6070,7 @@ type ResourceAliasesPager struct { // NewResourceAliasesPager returns a new ResourceAliasesPager instance. func (resourceController *ResourceControllerV2) NewResourceAliasesPager(options *ListResourceAliasesOptions) (pager *ResourceAliasesPager, err error) { if options.Start != nil && *options.Start != "" { - err = fmt.Errorf("the 'options.Start' field should not be set") + err = core.SDKErrorf(nil, "the 'options.Start' field should not be set", "no-query-setting", common.GetComponentInfo()) return } @@ -5587,6 +6098,7 @@ func (pager *ResourceAliasesPager) GetNextWithContext(ctx context.Context) (page result, _, err := pager.client.ListResourceAliasesWithContext(ctx, pager.options) if err != nil { + err = core.RepurposeSDKProblem(err, "error-getting-next-page") return } @@ -5595,7 +6107,8 @@ func (pager *ResourceAliasesPager) GetNextWithContext(ctx context.Context) (page var start *string start, err = core.GetQueryParam(result.NextURL, "start") if err != nil { - err = fmt.Errorf("error retrieving 'start' query parameter from URL '%s': %s", *result.NextURL, err.Error()) + errMsg := fmt.Sprintf("error retrieving 'start' query parameter from URL '%s': %s", *result.NextURL, err.Error()) + err = core.SDKErrorf(err, errMsg, "get-query-error", common.GetComponentInfo()) return } next = start @@ -5614,6 +6127,7 @@ func (pager *ResourceAliasesPager) GetAllWithContext(ctx context.Context) (allIt var nextPage []ResourceAlias nextPage, err = pager.GetNextWithContext(ctx) if err != nil { + err = core.RepurposeSDKProblem(err, "error-getting-next-page") return } allItems = append(allItems, nextPage...) @@ -5623,12 +6137,16 @@ func (pager *ResourceAliasesPager) GetAllWithContext(ctx context.Context) (allIt // GetNext invokes GetNextWithContext() using context.Background() as the Context parameter. func (pager *ResourceAliasesPager) GetNext() (page []ResourceAlias, err error) { - return pager.GetNextWithContext(context.Background()) + page, err = pager.GetNextWithContext(context.Background()) + err = core.RepurposeSDKProblem(err, "") + return } // GetAll invokes GetAllWithContext() using context.Background() as the Context parameter. func (pager *ResourceAliasesPager) GetAll() (allItems []ResourceAlias, err error) { - return pager.GetAllWithContext(context.Background()) + allItems, err = pager.GetAllWithContext(context.Background()) + err = core.RepurposeSDKProblem(err, "") + return } // ResourceBindingsForAliasPager can be used to simplify the use of the "ListResourceBindingsForAlias" method. @@ -5644,7 +6162,7 @@ type ResourceBindingsForAliasPager struct { // NewResourceBindingsForAliasPager returns a new ResourceBindingsForAliasPager instance. func (resourceController *ResourceControllerV2) NewResourceBindingsForAliasPager(options *ListResourceBindingsForAliasOptions) (pager *ResourceBindingsForAliasPager, err error) { if options.Start != nil && *options.Start != "" { - err = fmt.Errorf("the 'options.Start' field should not be set") + err = core.SDKErrorf(nil, "the 'options.Start' field should not be set", "no-query-setting", common.GetComponentInfo()) return } @@ -5672,6 +6190,7 @@ func (pager *ResourceBindingsForAliasPager) GetNextWithContext(ctx context.Conte result, _, err := pager.client.ListResourceBindingsForAliasWithContext(ctx, pager.options) if err != nil { + err = core.RepurposeSDKProblem(err, "error-getting-next-page") return } @@ -5680,7 +6199,8 @@ func (pager *ResourceBindingsForAliasPager) GetNextWithContext(ctx context.Conte var start *string start, err = core.GetQueryParam(result.NextURL, "start") if err != nil { - err = fmt.Errorf("error retrieving 'start' query parameter from URL '%s': %s", *result.NextURL, err.Error()) + errMsg := fmt.Sprintf("error retrieving 'start' query parameter from URL '%s': %s", *result.NextURL, err.Error()) + err = core.SDKErrorf(err, errMsg, "get-query-error", common.GetComponentInfo()) return } next = start @@ -5699,6 +6219,7 @@ func (pager *ResourceBindingsForAliasPager) GetAllWithContext(ctx context.Contex var nextPage []ResourceBinding nextPage, err = pager.GetNextWithContext(ctx) if err != nil { + err = core.RepurposeSDKProblem(err, "error-getting-next-page") return } allItems = append(allItems, nextPage...) @@ -5708,10 +6229,14 @@ func (pager *ResourceBindingsForAliasPager) GetAllWithContext(ctx context.Contex // GetNext invokes GetNextWithContext() using context.Background() as the Context parameter. func (pager *ResourceBindingsForAliasPager) GetNext() (page []ResourceBinding, err error) { - return pager.GetNextWithContext(context.Background()) + page, err = pager.GetNextWithContext(context.Background()) + err = core.RepurposeSDKProblem(err, "") + return } // GetAll invokes GetAllWithContext() using context.Background() as the Context parameter. func (pager *ResourceBindingsForAliasPager) GetAll() (allItems []ResourceBinding, err error) { - return pager.GetAllWithContext(context.Background()) + allItems, err = pager.GetAllWithContext(context.Background()) + err = core.RepurposeSDKProblem(err, "") + return } diff --git a/vendor/github.com/gabriel-vasile/mimetype/.gitattributes b/vendor/github.com/gabriel-vasile/mimetype/.gitattributes new file mode 100644 index 0000000000..0cc26ec01c --- /dev/null +++ b/vendor/github.com/gabriel-vasile/mimetype/.gitattributes @@ -0,0 +1 @@ +testdata/* linguist-vendored diff --git a/vendor/github.com/gabriel-vasile/mimetype/CODE_OF_CONDUCT.md b/vendor/github.com/gabriel-vasile/mimetype/CODE_OF_CONDUCT.md new file mode 100644 index 0000000000..8479cd87d6 --- /dev/null +++ b/vendor/github.com/gabriel-vasile/mimetype/CODE_OF_CONDUCT.md @@ -0,0 +1,76 @@ +# 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, sex characteristics, gender identity and expression, +level of experience, education, socio-economic status, 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 vasile.gabriel@email.com. 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 https://www.contributor-covenant.org/version/1/4/code-of-conduct.html + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see +https://www.contributor-covenant.org/faq diff --git a/vendor/github.com/gabriel-vasile/mimetype/CONTRIBUTING.md b/vendor/github.com/gabriel-vasile/mimetype/CONTRIBUTING.md new file mode 100644 index 0000000000..56ae4e57c6 --- /dev/null +++ b/vendor/github.com/gabriel-vasile/mimetype/CONTRIBUTING.md @@ -0,0 +1,12 @@ +## Contribute +Contributions to **mimetype** are welcome. If you find an issue and you consider +contributing, you can use the [Github issues tracker](https://github.com/gabriel-vasile/mimetype/issues) +in order to report it, or better yet, open a pull request. + +Code contributions must respect these rules: + - code must be test covered + - code must be formatted using gofmt tool + - exported names must be documented + +**Important**: By submitting a pull request, you agree to allow the project +owner to license your work under the same license as that used by the project. diff --git a/vendor/github.com/gabriel-vasile/mimetype/LICENSE b/vendor/github.com/gabriel-vasile/mimetype/LICENSE new file mode 100644 index 0000000000..6aac070c78 --- /dev/null +++ b/vendor/github.com/gabriel-vasile/mimetype/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018-2020 Gabriel Vasile + +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. diff --git a/vendor/github.com/gabriel-vasile/mimetype/README.md b/vendor/github.com/gabriel-vasile/mimetype/README.md new file mode 100644 index 0000000000..231b29190f --- /dev/null +++ b/vendor/github.com/gabriel-vasile/mimetype/README.md @@ -0,0 +1,105 @@ +

+ mimetype +

+ +

+ A package for detecting MIME types and extensions based on magic numbers +

+
+ Goroutine safe, extensible, no C bindings +
+ +

+ + Go Reference + + + Go report card + + + Code coverage + + + License + +

+ +## Features +- fast and precise MIME type and file extension detection +- long list of [supported MIME types](supported_mimes.md) +- possibility to [extend](https://pkg.go.dev/github.com/gabriel-vasile/mimetype#example-package-Extend) with other file formats +- common file formats are prioritized +- [text vs. binary files differentiation](https://pkg.go.dev/github.com/gabriel-vasile/mimetype#example-package-TextVsBinary) +- safe for concurrent usage + +## Install +```bash +go get github.com/gabriel-vasile/mimetype +``` + +## Usage +```go +mtype := mimetype.Detect([]byte) +// OR +mtype, err := mimetype.DetectReader(io.Reader) +// OR +mtype, err := mimetype.DetectFile("/path/to/file") +fmt.Println(mtype.String(), mtype.Extension()) +``` +See the [runnable Go Playground examples](https://pkg.go.dev/github.com/gabriel-vasile/mimetype#pkg-overview). + +## Usage' +Only use libraries like **mimetype** as a last resort. Content type detection +using magic numbers is slow, inaccurate, and non-standard. Most of the times +protocols have methods for specifying such metadata; e.g., `Content-Type` header +in HTTP and SMTP. + +## FAQ +Q: My file is in the list of [supported MIME types](supported_mimes.md) but +it is not correctly detected. What should I do? + +A: Some file formats (often Microsoft Office documents) keep their signatures +towards the end of the file. Try increasing the number of bytes used for detection +with: +```go +mimetype.SetLimit(1024*1024) // Set limit to 1MB. +// or +mimetype.SetLimit(0) // No limit, whole file content used. +mimetype.DetectFile("file.doc") +``` +If increasing the limit does not help, please +[open an issue](https://github.com/gabriel-vasile/mimetype/issues/new?assignees=&labels=&template=mismatched-mime-type-detected.md&title=). + +## Structure +**mimetype** uses a hierarchical structure to keep the MIME type detection logic. +This reduces the number of calls needed for detecting the file type. The reason +behind this choice is that there are file formats used as containers for other +file formats. For example, Microsoft Office files are just zip archives, +containing specific metadata files. Once a file has been identified as a +zip, there is no need to check if it is a text file, but it is worth checking if +it is an Microsoft Office file. + +To prevent loading entire files into memory, when detecting from a +[reader](https://pkg.go.dev/github.com/gabriel-vasile/mimetype#DetectReader) +or from a [file](https://pkg.go.dev/github.com/gabriel-vasile/mimetype#DetectFile) +**mimetype** limits itself to reading only the header of the input. +
+ structure +
+ +## Performance +Thanks to the hierarchical structure, searching for common formats first, +and limiting itself to file headers, **mimetype** matches the performance of +stdlib `http.DetectContentType` while outperforming the alternative package. + +```bash + mimetype http.DetectContentType filetype +BenchmarkMatchTar-24 250 ns/op 400 ns/op 3778 ns/op +BenchmarkMatchZip-24 524 ns/op 351 ns/op 4884 ns/op +BenchmarkMatchJpeg-24 103 ns/op 228 ns/op 839 ns/op +BenchmarkMatchGif-24 139 ns/op 202 ns/op 751 ns/op +BenchmarkMatchPng-24 165 ns/op 221 ns/op 1176 ns/op +``` + +## Contributing +See [CONTRIBUTING.md](CONTRIBUTING.md). diff --git a/vendor/github.com/gabriel-vasile/mimetype/internal/charset/charset.go b/vendor/github.com/gabriel-vasile/mimetype/internal/charset/charset.go new file mode 100644 index 0000000000..0647f730e5 --- /dev/null +++ b/vendor/github.com/gabriel-vasile/mimetype/internal/charset/charset.go @@ -0,0 +1,309 @@ +package charset + +import ( + "bytes" + "encoding/xml" + "strings" + "unicode/utf8" + + "golang.org/x/net/html" +) + +const ( + F = 0 /* character never appears in text */ + T = 1 /* character appears in plain ASCII text */ + I = 2 /* character appears in ISO-8859 text */ + X = 3 /* character appears in non-ISO extended ASCII (Mac, IBM PC) */ +) + +var ( + boms = []struct { + bom []byte + enc string + }{ + {[]byte{0xEF, 0xBB, 0xBF}, "utf-8"}, + {[]byte{0x00, 0x00, 0xFE, 0xFF}, "utf-32be"}, + {[]byte{0xFF, 0xFE, 0x00, 0x00}, "utf-32le"}, + {[]byte{0xFE, 0xFF}, "utf-16be"}, + {[]byte{0xFF, 0xFE}, "utf-16le"}, + } + + // https://github.com/file/file/blob/fa93fb9f7d21935f1c7644c47d2975d31f12b812/src/encoding.c#L241 + textChars = [256]byte{ + /* BEL BS HT LF VT FF CR */ + F, F, F, F, F, F, F, T, T, T, T, T, T, T, F, F, /* 0x0X */ + /* ESC */ + F, F, F, F, F, F, F, F, F, F, F, T, F, F, F, F, /* 0x1X */ + T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x2X */ + T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x3X */ + T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x4X */ + T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x5X */ + T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x6X */ + T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, F, /* 0x7X */ + /* NEL */ + X, X, X, X, X, T, X, X, X, X, X, X, X, X, X, X, /* 0x8X */ + X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, /* 0x9X */ + I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xaX */ + I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xbX */ + I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xcX */ + I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xdX */ + I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xeX */ + I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xfX */ + } +) + +// FromBOM returns the charset declared in the BOM of content. +func FromBOM(content []byte) string { + for _, b := range boms { + if bytes.HasPrefix(content, b.bom) { + return b.enc + } + } + return "" +} + +// FromPlain returns the charset of a plain text. It relies on BOM presence +// and it falls back on checking each byte in content. +func FromPlain(content []byte) string { + if len(content) == 0 { + return "" + } + if cset := FromBOM(content); cset != "" { + return cset + } + origContent := content + // Try to detect UTF-8. + // First eliminate any partial rune at the end. + for i := len(content) - 1; i >= 0 && i > len(content)-4; i-- { + b := content[i] + if b < 0x80 { + break + } + if utf8.RuneStart(b) { + content = content[:i] + break + } + } + hasHighBit := false + for _, c := range content { + if c >= 0x80 { + hasHighBit = true + break + } + } + if hasHighBit && utf8.Valid(content) { + return "utf-8" + } + + // ASCII is a subset of UTF8. Follow W3C recommendation and replace with UTF8. + if ascii(origContent) { + return "utf-8" + } + + return latin(origContent) +} + +func latin(content []byte) string { + hasControlBytes := false + for _, b := range content { + t := textChars[b] + if t != T && t != I { + return "" + } + if b >= 0x80 && b <= 0x9F { + hasControlBytes = true + } + } + // Code range 0x80 to 0x9F is reserved for control characters in ISO-8859-1 + // (so-called C1 Controls). Windows 1252, however, has printable punctuation + // characters in this range. + if hasControlBytes { + return "windows-1252" + } + return "iso-8859-1" +} + +func ascii(content []byte) bool { + for _, b := range content { + if textChars[b] != T { + return false + } + } + return true +} + +// FromXML returns the charset of an XML document. It relies on the XML +// header and falls back on the plain +// text content. +func FromXML(content []byte) string { + if cset := fromXML(content); cset != "" { + return cset + } + return FromPlain(content) +} +func fromXML(content []byte) string { + content = trimLWS(content) + dec := xml.NewDecoder(bytes.NewReader(content)) + rawT, err := dec.RawToken() + if err != nil { + return "" + } + + t, ok := rawT.(xml.ProcInst) + if !ok { + return "" + } + + return strings.ToLower(xmlEncoding(string(t.Inst))) +} + +// FromHTML returns the charset of an HTML document. It first looks if a BOM is +// present and if so uses it to determine the charset. If no BOM is present, +// it relies on the meta tag and falls back on the +// plain text content. +func FromHTML(content []byte) string { + if cset := FromBOM(content); cset != "" { + return cset + } + if cset := fromHTML(content); cset != "" { + return cset + } + return FromPlain(content) +} + +func fromHTML(content []byte) string { + z := html.NewTokenizer(bytes.NewReader(content)) + for { + switch z.Next() { + case html.ErrorToken: + return "" + + case html.StartTagToken, html.SelfClosingTagToken: + tagName, hasAttr := z.TagName() + if !bytes.Equal(tagName, []byte("meta")) { + continue + } + attrList := make(map[string]bool) + gotPragma := false + + const ( + dontKnow = iota + doNeedPragma + doNotNeedPragma + ) + needPragma := dontKnow + + name := "" + for hasAttr { + var key, val []byte + key, val, hasAttr = z.TagAttr() + ks := string(key) + if attrList[ks] { + continue + } + attrList[ks] = true + for i, c := range val { + if 'A' <= c && c <= 'Z' { + val[i] = c + 0x20 + } + } + + switch ks { + case "http-equiv": + if bytes.Equal(val, []byte("content-type")) { + gotPragma = true + } + + case "content": + name = fromMetaElement(string(val)) + if name != "" { + needPragma = doNeedPragma + } + + case "charset": + name = string(val) + needPragma = doNotNeedPragma + } + } + + if needPragma == dontKnow || needPragma == doNeedPragma && !gotPragma { + continue + } + + if strings.HasPrefix(name, "utf-16") { + name = "utf-8" + } + + return name + } + } +} + +func fromMetaElement(s string) string { + for s != "" { + csLoc := strings.Index(s, "charset") + if csLoc == -1 { + return "" + } + s = s[csLoc+len("charset"):] + s = strings.TrimLeft(s, " \t\n\f\r") + if !strings.HasPrefix(s, "=") { + continue + } + s = s[1:] + s = strings.TrimLeft(s, " \t\n\f\r") + if s == "" { + return "" + } + if q := s[0]; q == '"' || q == '\'' { + s = s[1:] + closeQuote := strings.IndexRune(s, rune(q)) + if closeQuote == -1 { + return "" + } + return s[:closeQuote] + } + + end := strings.IndexAny(s, "; \t\n\f\r") + if end == -1 { + end = len(s) + } + return s[:end] + } + return "" +} + +func xmlEncoding(s string) string { + param := "encoding=" + idx := strings.Index(s, param) + if idx == -1 { + return "" + } + v := s[idx+len(param):] + if v == "" { + return "" + } + if v[0] != '\'' && v[0] != '"' { + return "" + } + idx = strings.IndexRune(v[1:], rune(v[0])) + if idx == -1 { + return "" + } + return v[1 : idx+1] +} + +// trimLWS trims whitespace from beginning of the input. +// TODO: find a way to call trimLWS once per detection instead of once in each +// detector which needs the trimmed input. +func trimLWS(in []byte) []byte { + firstNonWS := 0 + for ; firstNonWS < len(in) && isWS(in[firstNonWS]); firstNonWS++ { + } + + return in[firstNonWS:] +} + +func isWS(b byte) bool { + return b == '\t' || b == '\n' || b == '\x0c' || b == '\r' || b == ' ' +} diff --git a/vendor/github.com/gabriel-vasile/mimetype/internal/json/json.go b/vendor/github.com/gabriel-vasile/mimetype/internal/json/json.go new file mode 100644 index 0000000000..ee39349aef --- /dev/null +++ b/vendor/github.com/gabriel-vasile/mimetype/internal/json/json.go @@ -0,0 +1,544 @@ +// Copyright (c) 2009 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. + +// Package json provides a JSON value parser state machine. +// This package is almost entirely copied from the Go stdlib. +// Changes made to it permit users of the package to tell +// if some slice of bytes is a valid beginning of a json string. +package json + +import ( + "fmt" +) + +type ( + scanStatus int +) + +const ( + parseObjectKey = iota // parsing object key (before colon) + parseObjectValue // parsing object value (after colon) + parseArrayValue // parsing array value + + scanContinue scanStatus = iota // uninteresting byte + scanBeginLiteral // end implied by next result != scanContinue + scanBeginObject // begin object + scanObjectKey // just finished object key (string) + scanObjectValue // just finished non-last object value + scanEndObject // end object (implies scanObjectValue if possible) + scanBeginArray // begin array + scanArrayValue // just finished array value + scanEndArray // end array (implies scanArrayValue if possible) + scanSkipSpace // space byte; can skip; known to be last "continue" result + scanEnd // top-level value ended *before* this byte; known to be first "stop" result + scanError // hit an error, scanner.err. + + // This limits the max nesting depth to prevent stack overflow. + // This is permitted by https://tools.ietf.org/html/rfc7159#section-9 + maxNestingDepth = 10000 +) + +type ( + scanner struct { + step func(*scanner, byte) scanStatus + parseState []int + endTop bool + err error + index int + } +) + +// Scan returns the number of bytes scanned and if there was any error +// in trying to reach the end of data. +func Scan(data []byte) (int, error) { + s := &scanner{} + _ = checkValid(data, s) + return s.index, s.err +} + +// checkValid verifies that data is valid JSON-encoded data. +// scan is passed in for use by checkValid to avoid an allocation. +func checkValid(data []byte, scan *scanner) error { + scan.reset() + for _, c := range data { + scan.index++ + if scan.step(scan, c) == scanError { + return scan.err + } + } + if scan.eof() == scanError { + return scan.err + } + return nil +} + +func isSpace(c byte) bool { + return c == ' ' || c == '\t' || c == '\r' || c == '\n' +} + +func (s *scanner) reset() { + s.step = stateBeginValue + s.parseState = s.parseState[0:0] + s.err = nil +} + +// eof tells the scanner that the end of input has been reached. +// It returns a scan status just as s.step does. +func (s *scanner) eof() scanStatus { + if s.err != nil { + return scanError + } + if s.endTop { + return scanEnd + } + s.step(s, ' ') + if s.endTop { + return scanEnd + } + if s.err == nil { + s.err = fmt.Errorf("unexpected end of JSON input") + } + return scanError +} + +// pushParseState pushes a new parse state p onto the parse stack. +// an error state is returned if maxNestingDepth was exceeded, otherwise successState is returned. +func (s *scanner) pushParseState(c byte, newParseState int, successState scanStatus) scanStatus { + s.parseState = append(s.parseState, newParseState) + if len(s.parseState) <= maxNestingDepth { + return successState + } + return s.error(c, "exceeded max depth") +} + +// popParseState pops a parse state (already obtained) off the stack +// and updates s.step accordingly. +func (s *scanner) popParseState() { + n := len(s.parseState) - 1 + s.parseState = s.parseState[0:n] + if n == 0 { + s.step = stateEndTop + s.endTop = true + } else { + s.step = stateEndValue + } +} + +// stateBeginValueOrEmpty is the state after reading `[`. +func stateBeginValueOrEmpty(s *scanner, c byte) scanStatus { + if c <= ' ' && isSpace(c) { + return scanSkipSpace + } + if c == ']' { + return stateEndValue(s, c) + } + return stateBeginValue(s, c) +} + +// stateBeginValue is the state at the beginning of the input. +func stateBeginValue(s *scanner, c byte) scanStatus { + if c <= ' ' && isSpace(c) { + return scanSkipSpace + } + switch c { + case '{': + s.step = stateBeginStringOrEmpty + return s.pushParseState(c, parseObjectKey, scanBeginObject) + case '[': + s.step = stateBeginValueOrEmpty + return s.pushParseState(c, parseArrayValue, scanBeginArray) + case '"': + s.step = stateInString + return scanBeginLiteral + case '-': + s.step = stateNeg + return scanBeginLiteral + case '0': // beginning of 0.123 + s.step = state0 + return scanBeginLiteral + case 't': // beginning of true + s.step = stateT + return scanBeginLiteral + case 'f': // beginning of false + s.step = stateF + return scanBeginLiteral + case 'n': // beginning of null + s.step = stateN + return scanBeginLiteral + } + if '1' <= c && c <= '9' { // beginning of 1234.5 + s.step = state1 + return scanBeginLiteral + } + return s.error(c, "looking for beginning of value") +} + +// stateBeginStringOrEmpty is the state after reading `{`. +func stateBeginStringOrEmpty(s *scanner, c byte) scanStatus { + if c <= ' ' && isSpace(c) { + return scanSkipSpace + } + if c == '}' { + n := len(s.parseState) + s.parseState[n-1] = parseObjectValue + return stateEndValue(s, c) + } + return stateBeginString(s, c) +} + +// stateBeginString is the state after reading `{"key": value,`. +func stateBeginString(s *scanner, c byte) scanStatus { + if c <= ' ' && isSpace(c) { + return scanSkipSpace + } + if c == '"' { + s.step = stateInString + return scanBeginLiteral + } + return s.error(c, "looking for beginning of object key string") +} + +// stateEndValue is the state after completing a value, +// such as after reading `{}` or `true` or `["x"`. +func stateEndValue(s *scanner, c byte) scanStatus { + n := len(s.parseState) + if n == 0 { + // Completed top-level before the current byte. + s.step = stateEndTop + s.endTop = true + return stateEndTop(s, c) + } + if c <= ' ' && isSpace(c) { + s.step = stateEndValue + return scanSkipSpace + } + ps := s.parseState[n-1] + switch ps { + case parseObjectKey: + if c == ':' { + s.parseState[n-1] = parseObjectValue + s.step = stateBeginValue + return scanObjectKey + } + return s.error(c, "after object key") + case parseObjectValue: + if c == ',' { + s.parseState[n-1] = parseObjectKey + s.step = stateBeginString + return scanObjectValue + } + if c == '}' { + s.popParseState() + return scanEndObject + } + return s.error(c, "after object key:value pair") + case parseArrayValue: + if c == ',' { + s.step = stateBeginValue + return scanArrayValue + } + if c == ']' { + s.popParseState() + return scanEndArray + } + return s.error(c, "after array element") + } + return s.error(c, "") +} + +// stateEndTop is the state after finishing the top-level value, +// such as after reading `{}` or `[1,2,3]`. +// Only space characters should be seen now. +func stateEndTop(s *scanner, c byte) scanStatus { + if c != ' ' && c != '\t' && c != '\r' && c != '\n' { + // Complain about non-space byte on next call. + s.error(c, "after top-level value") + } + return scanEnd +} + +// stateInString is the state after reading `"`. +func stateInString(s *scanner, c byte) scanStatus { + if c == '"' { + s.step = stateEndValue + return scanContinue + } + if c == '\\' { + s.step = stateInStringEsc + return scanContinue + } + if c < 0x20 { + return s.error(c, "in string literal") + } + return scanContinue +} + +// stateInStringEsc is the state after reading `"\` during a quoted string. +func stateInStringEsc(s *scanner, c byte) scanStatus { + switch c { + case 'b', 'f', 'n', 'r', 't', '\\', '/', '"': + s.step = stateInString + return scanContinue + case 'u': + s.step = stateInStringEscU + return scanContinue + } + return s.error(c, "in string escape code") +} + +// stateInStringEscU is the state after reading `"\u` during a quoted string. +func stateInStringEscU(s *scanner, c byte) scanStatus { + if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' { + s.step = stateInStringEscU1 + return scanContinue + } + // numbers + return s.error(c, "in \\u hexadecimal character escape") +} + +// stateInStringEscU1 is the state after reading `"\u1` during a quoted string. +func stateInStringEscU1(s *scanner, c byte) scanStatus { + if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' { + s.step = stateInStringEscU12 + return scanContinue + } + // numbers + return s.error(c, "in \\u hexadecimal character escape") +} + +// stateInStringEscU12 is the state after reading `"\u12` during a quoted string. +func stateInStringEscU12(s *scanner, c byte) scanStatus { + if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' { + s.step = stateInStringEscU123 + return scanContinue + } + // numbers + return s.error(c, "in \\u hexadecimal character escape") +} + +// stateInStringEscU123 is the state after reading `"\u123` during a quoted string. +func stateInStringEscU123(s *scanner, c byte) scanStatus { + if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' { + s.step = stateInString + return scanContinue + } + // numbers + return s.error(c, "in \\u hexadecimal character escape") +} + +// stateNeg is the state after reading `-` during a number. +func stateNeg(s *scanner, c byte) scanStatus { + if c == '0' { + s.step = state0 + return scanContinue + } + if '1' <= c && c <= '9' { + s.step = state1 + return scanContinue + } + return s.error(c, "in numeric literal") +} + +// state1 is the state after reading a non-zero integer during a number, +// such as after reading `1` or `100` but not `0`. +func state1(s *scanner, c byte) scanStatus { + if '0' <= c && c <= '9' { + s.step = state1 + return scanContinue + } + return state0(s, c) +} + +// state0 is the state after reading `0` during a number. +func state0(s *scanner, c byte) scanStatus { + if c == '.' { + s.step = stateDot + return scanContinue + } + if c == 'e' || c == 'E' { + s.step = stateE + return scanContinue + } + return stateEndValue(s, c) +} + +// stateDot is the state after reading the integer and decimal point in a number, +// such as after reading `1.`. +func stateDot(s *scanner, c byte) scanStatus { + if '0' <= c && c <= '9' { + s.step = stateDot0 + return scanContinue + } + return s.error(c, "after decimal point in numeric literal") +} + +// stateDot0 is the state after reading the integer, decimal point, and subsequent +// digits of a number, such as after reading `3.14`. +func stateDot0(s *scanner, c byte) scanStatus { + if '0' <= c && c <= '9' { + return scanContinue + } + if c == 'e' || c == 'E' { + s.step = stateE + return scanContinue + } + return stateEndValue(s, c) +} + +// stateE is the state after reading the mantissa and e in a number, +// such as after reading `314e` or `0.314e`. +func stateE(s *scanner, c byte) scanStatus { + if c == '+' || c == '-' { + s.step = stateESign + return scanContinue + } + return stateESign(s, c) +} + +// stateESign is the state after reading the mantissa, e, and sign in a number, +// such as after reading `314e-` or `0.314e+`. +func stateESign(s *scanner, c byte) scanStatus { + if '0' <= c && c <= '9' { + s.step = stateE0 + return scanContinue + } + return s.error(c, "in exponent of numeric literal") +} + +// stateE0 is the state after reading the mantissa, e, optional sign, +// and at least one digit of the exponent in a number, +// such as after reading `314e-2` or `0.314e+1` or `3.14e0`. +func stateE0(s *scanner, c byte) scanStatus { + if '0' <= c && c <= '9' { + return scanContinue + } + return stateEndValue(s, c) +} + +// stateT is the state after reading `t`. +func stateT(s *scanner, c byte) scanStatus { + if c == 'r' { + s.step = stateTr + return scanContinue + } + return s.error(c, "in literal true (expecting 'r')") +} + +// stateTr is the state after reading `tr`. +func stateTr(s *scanner, c byte) scanStatus { + if c == 'u' { + s.step = stateTru + return scanContinue + } + return s.error(c, "in literal true (expecting 'u')") +} + +// stateTru is the state after reading `tru`. +func stateTru(s *scanner, c byte) scanStatus { + if c == 'e' { + s.step = stateEndValue + return scanContinue + } + return s.error(c, "in literal true (expecting 'e')") +} + +// stateF is the state after reading `f`. +func stateF(s *scanner, c byte) scanStatus { + if c == 'a' { + s.step = stateFa + return scanContinue + } + return s.error(c, "in literal false (expecting 'a')") +} + +// stateFa is the state after reading `fa`. +func stateFa(s *scanner, c byte) scanStatus { + if c == 'l' { + s.step = stateFal + return scanContinue + } + return s.error(c, "in literal false (expecting 'l')") +} + +// stateFal is the state after reading `fal`. +func stateFal(s *scanner, c byte) scanStatus { + if c == 's' { + s.step = stateFals + return scanContinue + } + return s.error(c, "in literal false (expecting 's')") +} + +// stateFals is the state after reading `fals`. +func stateFals(s *scanner, c byte) scanStatus { + if c == 'e' { + s.step = stateEndValue + return scanContinue + } + return s.error(c, "in literal false (expecting 'e')") +} + +// stateN is the state after reading `n`. +func stateN(s *scanner, c byte) scanStatus { + if c == 'u' { + s.step = stateNu + return scanContinue + } + return s.error(c, "in literal null (expecting 'u')") +} + +// stateNu is the state after reading `nu`. +func stateNu(s *scanner, c byte) scanStatus { + if c == 'l' { + s.step = stateNul + return scanContinue + } + return s.error(c, "in literal null (expecting 'l')") +} + +// stateNul is the state after reading `nul`. +func stateNul(s *scanner, c byte) scanStatus { + if c == 'l' { + s.step = stateEndValue + return scanContinue + } + return s.error(c, "in literal null (expecting 'l')") +} + +// stateError is the state after reaching a syntax error, +// such as after reading `[1}` or `5.1.2`. +func stateError(s *scanner, c byte) scanStatus { + return scanError +} + +// error records an error and switches to the error state. +func (s *scanner) error(c byte, context string) scanStatus { + s.step = stateError + s.err = fmt.Errorf("invalid character <<%c>> %s", c, context) + return scanError +} diff --git a/vendor/github.com/gabriel-vasile/mimetype/internal/magic/archive.go b/vendor/github.com/gabriel-vasile/mimetype/internal/magic/archive.go new file mode 100644 index 0000000000..fec11f080a --- /dev/null +++ b/vendor/github.com/gabriel-vasile/mimetype/internal/magic/archive.go @@ -0,0 +1,124 @@ +package magic + +import ( + "bytes" + "encoding/binary" +) + +var ( + // SevenZ matches a 7z archive. + SevenZ = prefix([]byte{0x37, 0x7A, 0xBC, 0xAF, 0x27, 0x1C}) + // Gzip matches gzip files based on http://www.zlib.org/rfc-gzip.html#header-trailer. + Gzip = prefix([]byte{0x1f, 0x8b}) + // Fits matches an Flexible Image Transport System file. + Fits = prefix([]byte{ + 0x53, 0x49, 0x4D, 0x50, 0x4C, 0x45, 0x20, 0x20, 0x3D, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x54, + }) + // Xar matches an eXtensible ARchive format file. + Xar = prefix([]byte{0x78, 0x61, 0x72, 0x21}) + // Bz2 matches a bzip2 file. + Bz2 = prefix([]byte{0x42, 0x5A, 0x68}) + // Ar matches an ar (Unix) archive file. + Ar = prefix([]byte{0x21, 0x3C, 0x61, 0x72, 0x63, 0x68, 0x3E}) + // Deb matches a Debian package file. + Deb = offset([]byte{ + 0x64, 0x65, 0x62, 0x69, 0x61, 0x6E, 0x2D, + 0x62, 0x69, 0x6E, 0x61, 0x72, 0x79, + }, 8) + // Warc matches a Web ARChive file. + Warc = prefix([]byte("WARC/1.0"), []byte("WARC/1.1")) + // Cab matches a Microsoft Cabinet archive file. + Cab = prefix([]byte("MSCF\x00\x00\x00\x00")) + // Xz matches an xz compressed stream based on https://tukaani.org/xz/xz-file-format.txt. + Xz = prefix([]byte{0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00}) + // Lzip matches an Lzip compressed file. + Lzip = prefix([]byte{0x4c, 0x5a, 0x49, 0x50}) + // RPM matches an RPM or Delta RPM package file. + RPM = prefix([]byte{0xed, 0xab, 0xee, 0xdb}, []byte("drpm")) + // Cpio matches a cpio archive file. + Cpio = prefix([]byte("070707"), []byte("070701"), []byte("070702")) + // RAR matches a RAR archive file. + RAR = prefix([]byte("Rar!\x1A\x07\x00"), []byte("Rar!\x1A\x07\x01\x00")) +) + +// InstallShieldCab matches an InstallShield Cabinet archive file. +func InstallShieldCab(raw []byte, _ uint32) bool { + return len(raw) > 7 && + bytes.Equal(raw[0:4], []byte("ISc(")) && + raw[6] == 0 && + (raw[7] == 1 || raw[7] == 2 || raw[7] == 4) +} + +// Zstd matches a Zstandard archive file. +func Zstd(raw []byte, limit uint32) bool { + return len(raw) >= 4 && + (0x22 <= raw[0] && raw[0] <= 0x28 || raw[0] == 0x1E) && // Different Zstandard versions. + bytes.HasPrefix(raw[1:], []byte{0xB5, 0x2F, 0xFD}) +} + +// CRX matches a Chrome extension file: a zip archive prepended by a package header. +func CRX(raw []byte, limit uint32) bool { + const minHeaderLen = 16 + if len(raw) < minHeaderLen || !bytes.HasPrefix(raw, []byte("Cr24")) { + return false + } + pubkeyLen := binary.LittleEndian.Uint32(raw[8:12]) + sigLen := binary.LittleEndian.Uint32(raw[12:16]) + zipOffset := minHeaderLen + pubkeyLen + sigLen + if uint32(len(raw)) < zipOffset { + return false + } + return Zip(raw[zipOffset:], limit) +} + +// Tar matches a (t)ape (ar)chive file. +func Tar(raw []byte, _ uint32) bool { + // The "magic" header field for files in in UStar (POSIX IEEE P1003.1) archives + // has the prefix "ustar". The values of the remaining bytes in this field vary + // by archiver implementation. + if len(raw) >= 512 && bytes.HasPrefix(raw[257:], []byte{0x75, 0x73, 0x74, 0x61, 0x72}) { + return true + } + + if len(raw) < 256 { + return false + } + + // The older v7 format has no "magic" field, and therefore must be identified + // with heuristics based on legal ranges of values for other header fields: + // https://www.nationalarchives.gov.uk/PRONOM/Format/proFormatSearch.aspx?status=detailReport&id=385&strPageToDisplay=signatures + rules := []struct { + min, max uint8 + i int + }{ + {0x21, 0xEF, 0}, + {0x30, 0x37, 105}, + {0x20, 0x37, 106}, + {0x00, 0x00, 107}, + {0x30, 0x37, 113}, + {0x20, 0x37, 114}, + {0x00, 0x00, 115}, + {0x30, 0x37, 121}, + {0x20, 0x37, 122}, + {0x00, 0x00, 123}, + {0x30, 0x37, 134}, + {0x30, 0x37, 146}, + {0x30, 0x37, 153}, + {0x00, 0x37, 154}, + } + for _, r := range rules { + if raw[r.i] < r.min || raw[r.i] > r.max { + return false + } + } + + for _, i := range []uint8{135, 147, 155} { + if raw[i] != 0x00 && raw[i] != 0x20 { + return false + } + } + + return true +} diff --git a/vendor/github.com/gabriel-vasile/mimetype/internal/magic/audio.go b/vendor/github.com/gabriel-vasile/mimetype/internal/magic/audio.go new file mode 100644 index 0000000000..d17e32482c --- /dev/null +++ b/vendor/github.com/gabriel-vasile/mimetype/internal/magic/audio.go @@ -0,0 +1,76 @@ +package magic + +import ( + "bytes" + "encoding/binary" +) + +var ( + // Flac matches a Free Lossless Audio Codec file. + Flac = prefix([]byte("\x66\x4C\x61\x43\x00\x00\x00\x22")) + // Midi matches a Musical Instrument Digital Interface file. + Midi = prefix([]byte("\x4D\x54\x68\x64")) + // Ape matches a Monkey's Audio file. + Ape = prefix([]byte("\x4D\x41\x43\x20\x96\x0F\x00\x00\x34\x00\x00\x00\x18\x00\x00\x00\x90\xE3")) + // MusePack matches a Musepack file. + MusePack = prefix([]byte("MPCK")) + // Au matches a Sun Microsystems au file. + Au = prefix([]byte("\x2E\x73\x6E\x64")) + // Amr matches an Adaptive Multi-Rate file. + Amr = prefix([]byte("\x23\x21\x41\x4D\x52")) + // Voc matches a Creative Voice file. + Voc = prefix([]byte("Creative Voice File")) + // M3u matches a Playlist file. + M3u = prefix([]byte("#EXTM3U")) + // AAC matches an Advanced Audio Coding file. + AAC = prefix([]byte{0xFF, 0xF1}, []byte{0xFF, 0xF9}) +) + +// Mp3 matches an mp3 file. +func Mp3(raw []byte, limit uint32) bool { + if len(raw) < 3 { + return false + } + + if bytes.HasPrefix(raw, []byte("ID3")) { + // MP3s with an ID3v2 tag will start with "ID3" + // ID3v1 tags, however appear at the end of the file. + return true + } + + // Match MP3 files without tags + switch binary.BigEndian.Uint16(raw[:2]) & 0xFFFE { + case 0xFFFA: + // MPEG ADTS, layer III, v1 + return true + case 0xFFF2: + // MPEG ADTS, layer III, v2 + return true + case 0xFFE2: + // MPEG ADTS, layer III, v2.5 + return true + } + + return false +} + +// Wav matches a Waveform Audio File Format file. +func Wav(raw []byte, limit uint32) bool { + return len(raw) > 12 && + bytes.Equal(raw[:4], []byte("RIFF")) && + bytes.Equal(raw[8:12], []byte{0x57, 0x41, 0x56, 0x45}) +} + +// Aiff matches Audio Interchange File Format file. +func Aiff(raw []byte, limit uint32) bool { + return len(raw) > 12 && + bytes.Equal(raw[:4], []byte{0x46, 0x4F, 0x52, 0x4D}) && + bytes.Equal(raw[8:12], []byte{0x41, 0x49, 0x46, 0x46}) +} + +// Qcp matches a Qualcomm Pure Voice file. +func Qcp(raw []byte, limit uint32) bool { + return len(raw) > 12 && + bytes.Equal(raw[:4], []byte("RIFF")) && + bytes.Equal(raw[8:12], []byte("QLCM")) +} diff --git a/vendor/github.com/gabriel-vasile/mimetype/internal/magic/binary.go b/vendor/github.com/gabriel-vasile/mimetype/internal/magic/binary.go new file mode 100644 index 0000000000..f1e944987c --- /dev/null +++ b/vendor/github.com/gabriel-vasile/mimetype/internal/magic/binary.go @@ -0,0 +1,198 @@ +package magic + +import ( + "bytes" + "debug/macho" + "encoding/binary" +) + +var ( + // Lnk matches Microsoft lnk binary format. + Lnk = prefix([]byte{0x4C, 0x00, 0x00, 0x00, 0x01, 0x14, 0x02, 0x00}) + // Wasm matches a web assembly File Format file. + Wasm = prefix([]byte{0x00, 0x61, 0x73, 0x6D}) + // Exe matches a Windows/DOS executable file. + Exe = prefix([]byte{0x4D, 0x5A}) + // Elf matches an Executable and Linkable Format file. + Elf = prefix([]byte{0x7F, 0x45, 0x4C, 0x46}) + // Nes matches a Nintendo Entertainment system ROM file. + Nes = prefix([]byte{0x4E, 0x45, 0x53, 0x1A}) + // SWF matches an Adobe Flash swf file. + SWF = prefix([]byte("CWS"), []byte("FWS"), []byte("ZWS")) + // Torrent has bencoded text in the beginning. + Torrent = prefix([]byte("d8:announce")) +) + +// Java bytecode and Mach-O binaries share the same magic number. +// More info here https://github.com/threatstack/libmagic/blob/master/magic/Magdir/cafebabe +func classOrMachOFat(in []byte) bool { + // There should be at least 8 bytes for both of them because the only way to + // quickly distinguish them is by comparing byte at position 7 + if len(in) < 8 { + return false + } + + return bytes.HasPrefix(in, []byte{0xCA, 0xFE, 0xBA, 0xBE}) +} + +// Class matches a java class file. +func Class(raw []byte, limit uint32) bool { + return classOrMachOFat(raw) && raw[7] > 30 +} + +// MachO matches Mach-O binaries format. +func MachO(raw []byte, limit uint32) bool { + if classOrMachOFat(raw) && raw[7] < 20 { + return true + } + + if len(raw) < 4 { + return false + } + + be := binary.BigEndian.Uint32(raw) + le := binary.LittleEndian.Uint32(raw) + + return be == macho.Magic32 || + le == macho.Magic32 || + be == macho.Magic64 || + le == macho.Magic64 +} + +// Dbf matches a dBase file. +// https://www.dbase.com/Knowledgebase/INT/db7_file_fmt.htm +func Dbf(raw []byte, limit uint32) bool { + if len(raw) < 68 { + return false + } + + // 3rd and 4th bytes contain the last update month and day of month. + if !(0 < raw[2] && raw[2] < 13 && 0 < raw[3] && raw[3] < 32) { + return false + } + + // 12, 13, 30, 31 are reserved bytes and always filled with 0x00. + if raw[12] != 0x00 || raw[13] != 0x00 || raw[30] != 0x00 || raw[31] != 0x00 { + return false + } + // Production MDX flag; + // 0x01 if a production .MDX file exists for this table; + // 0x00 if no .MDX file exists. + if raw[28] > 0x01 { + return false + } + + // dbf type is dictated by the first byte. + dbfTypes := []byte{ + 0x02, 0x03, 0x04, 0x05, 0x30, 0x31, 0x32, 0x42, 0x62, 0x7B, 0x82, + 0x83, 0x87, 0x8A, 0x8B, 0x8E, 0xB3, 0xCB, 0xE5, 0xF5, 0xF4, 0xFB, + } + for _, b := range dbfTypes { + if raw[0] == b { + return true + } + } + + return false +} + +// ElfObj matches an object file. +func ElfObj(raw []byte, limit uint32) bool { + return len(raw) > 17 && ((raw[16] == 0x01 && raw[17] == 0x00) || + (raw[16] == 0x00 && raw[17] == 0x01)) +} + +// ElfExe matches an executable file. +func ElfExe(raw []byte, limit uint32) bool { + return len(raw) > 17 && ((raw[16] == 0x02 && raw[17] == 0x00) || + (raw[16] == 0x00 && raw[17] == 0x02)) +} + +// ElfLib matches a shared library file. +func ElfLib(raw []byte, limit uint32) bool { + return len(raw) > 17 && ((raw[16] == 0x03 && raw[17] == 0x00) || + (raw[16] == 0x00 && raw[17] == 0x03)) +} + +// ElfDump matches a core dump file. +func ElfDump(raw []byte, limit uint32) bool { + return len(raw) > 17 && ((raw[16] == 0x04 && raw[17] == 0x00) || + (raw[16] == 0x00 && raw[17] == 0x04)) +} + +// Dcm matches a DICOM medical format file. +func Dcm(raw []byte, limit uint32) bool { + return len(raw) > 131 && + bytes.Equal(raw[128:132], []byte{0x44, 0x49, 0x43, 0x4D}) +} + +// Marc matches a MARC21 (MAchine-Readable Cataloging) file. +func Marc(raw []byte, limit uint32) bool { + // File is at least 24 bytes ("leader" field size). + if len(raw) < 24 { + return false + } + + // Fixed bytes at offset 20. + if !bytes.Equal(raw[20:24], []byte("4500")) { + return false + } + + // First 5 bytes are ASCII digits. + for i := 0; i < 5; i++ { + if raw[i] < '0' || raw[i] > '9' { + return false + } + } + + // Field terminator is present in first 2048 bytes. + return bytes.Contains(raw[:min(2048, len(raw))], []byte{0x1E}) +} + +// Glb matches a glTF model format file. +// GLB is the binary file format representation of 3D models saved in +// the GL transmission Format (glTF). +// GLB uses little endian and its header structure is as follows: +// +// <-- 12-byte header --> +// | magic | version | length | +// | (uint32) | (uint32) | (uint32) | +// | \x67\x6C\x54\x46 | \x01\x00\x00\x00 | ... | +// | g l T F | 1 | ... | +// +// Visit [glTF specification] and [IANA glTF entry] for more details. +// +// [glTF specification]: https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html +// [IANA glTF entry]: https://www.iana.org/assignments/media-types/model/gltf-binary +var Glb = prefix([]byte("\x67\x6C\x54\x46\x02\x00\x00\x00"), + []byte("\x67\x6C\x54\x46\x01\x00\x00\x00")) + +// TzIf matches a Time Zone Information Format (TZif) file. +// See more: https://tools.ietf.org/id/draft-murchison-tzdist-tzif-00.html#rfc.section.3 +// Its header structure is shown below: +// +---------------+---+ +// | magic (4) | <-+-- version (1) +// +---------------+---+---------------------------------------+ +// | [unused - reserved for future use] (15) | +// +---------------+---------------+---------------+-----------+ +// | isutccnt (4) | isstdcnt (4) | leapcnt (4) | +// +---------------+---------------+---------------+ +// | timecnt (4) | typecnt (4) | charcnt (4) | +func TzIf(raw []byte, limit uint32) bool { + // File is at least 44 bytes (header size). + if len(raw) < 44 { + return false + } + + if !bytes.HasPrefix(raw, []byte("TZif")) { + return false + } + + // Field "typecnt" MUST not be zero. + if binary.BigEndian.Uint32(raw[36:40]) == 0 { + return false + } + + // Version has to be NUL (0x00), '2' (0x32) or '3' (0x33). + return raw[4] == 0x00 || raw[4] == 0x32 || raw[4] == 0x33 +} diff --git a/vendor/github.com/gabriel-vasile/mimetype/internal/magic/database.go b/vendor/github.com/gabriel-vasile/mimetype/internal/magic/database.go new file mode 100644 index 0000000000..cb1fed12f7 --- /dev/null +++ b/vendor/github.com/gabriel-vasile/mimetype/internal/magic/database.go @@ -0,0 +1,13 @@ +package magic + +var ( + // Sqlite matches an SQLite database file. + Sqlite = prefix([]byte{ + 0x53, 0x51, 0x4c, 0x69, 0x74, 0x65, 0x20, 0x66, + 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x20, 0x33, 0x00, + }) + // MsAccessAce matches Microsoft Access dababase file. + MsAccessAce = offset([]byte("Standard ACE DB"), 4) + // MsAccessMdb matches legacy Microsoft Access database file (JET, 2003 and earlier). + MsAccessMdb = offset([]byte("Standard Jet DB"), 4) +) diff --git a/vendor/github.com/gabriel-vasile/mimetype/internal/magic/document.go b/vendor/github.com/gabriel-vasile/mimetype/internal/magic/document.go new file mode 100644 index 0000000000..b3b26d5a12 --- /dev/null +++ b/vendor/github.com/gabriel-vasile/mimetype/internal/magic/document.go @@ -0,0 +1,62 @@ +package magic + +import "bytes" + +var ( + // Pdf matches a Portable Document Format file. + // https://github.com/file/file/blob/11010cc805546a3e35597e67e1129a481aed40e8/magic/Magdir/pdf + Pdf = prefix( + // usual pdf signature + []byte("%PDF-"), + // new-line prefixed signature + []byte("\012%PDF-"), + // UTF-8 BOM prefixed signature + []byte("\xef\xbb\xbf%PDF-"), + ) + // Fdf matches a Forms Data Format file. + Fdf = prefix([]byte("%FDF")) + // Mobi matches a Mobi file. + Mobi = offset([]byte("BOOKMOBI"), 60) + // Lit matches a Microsoft Lit file. + Lit = prefix([]byte("ITOLITLS")) +) + +// DjVu matches a DjVu file. +func DjVu(raw []byte, limit uint32) bool { + if len(raw) < 12 { + return false + } + if !bytes.HasPrefix(raw, []byte{0x41, 0x54, 0x26, 0x54, 0x46, 0x4F, 0x52, 0x4D}) { + return false + } + return bytes.HasPrefix(raw[12:], []byte("DJVM")) || + bytes.HasPrefix(raw[12:], []byte("DJVU")) || + bytes.HasPrefix(raw[12:], []byte("DJVI")) || + bytes.HasPrefix(raw[12:], []byte("THUM")) +} + +// P7s matches an .p7s signature File (PEM, Base64). +func P7s(raw []byte, limit uint32) bool { + // Check for PEM Encoding. + if bytes.HasPrefix(raw, []byte("-----BEGIN PKCS7")) { + return true + } + // Check if DER Encoding is long enough. + if len(raw) < 20 { + return false + } + // Magic Bytes for the signedData ASN.1 encoding. + startHeader := [][]byte{{0x30, 0x80}, {0x30, 0x81}, {0x30, 0x82}, {0x30, 0x83}, {0x30, 0x84}} + signedDataMatch := []byte{0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07} + // Check if Header is correct. There are multiple valid headers. + for i, match := range startHeader { + // If first bytes match, then check for ASN.1 Object Type. + if bytes.HasPrefix(raw, match) { + if bytes.HasPrefix(raw[i+2:], signedDataMatch) { + return true + } + } + } + + return false +} diff --git a/vendor/github.com/gabriel-vasile/mimetype/internal/magic/font.go b/vendor/github.com/gabriel-vasile/mimetype/internal/magic/font.go new file mode 100644 index 0000000000..43af28212e --- /dev/null +++ b/vendor/github.com/gabriel-vasile/mimetype/internal/magic/font.go @@ -0,0 +1,39 @@ +package magic + +import ( + "bytes" +) + +var ( + // Woff matches a Web Open Font Format file. + Woff = prefix([]byte("wOFF")) + // Woff2 matches a Web Open Font Format version 2 file. + Woff2 = prefix([]byte("wOF2")) + // Otf matches an OpenType font file. + Otf = prefix([]byte{0x4F, 0x54, 0x54, 0x4F, 0x00}) +) + +// Ttf matches a TrueType font file. +func Ttf(raw []byte, limit uint32) bool { + if !bytes.HasPrefix(raw, []byte{0x00, 0x01, 0x00, 0x00}) { + return false + } + return !MsAccessAce(raw, limit) && !MsAccessMdb(raw, limit) +} + +// Eot matches an Embedded OpenType font file. +func Eot(raw []byte, limit uint32) bool { + return len(raw) > 35 && + bytes.Equal(raw[34:36], []byte{0x4C, 0x50}) && + (bytes.Equal(raw[8:11], []byte{0x02, 0x00, 0x01}) || + bytes.Equal(raw[8:11], []byte{0x01, 0x00, 0x00}) || + bytes.Equal(raw[8:11], []byte{0x02, 0x00, 0x02})) +} + +// Ttc matches a TrueType Collection font file. +func Ttc(raw []byte, limit uint32) bool { + return len(raw) > 7 && + bytes.HasPrefix(raw, []byte("ttcf")) && + (bytes.Equal(raw[4:8], []byte{0x00, 0x01, 0x00, 0x00}) || + bytes.Equal(raw[4:8], []byte{0x00, 0x02, 0x00, 0x00})) +} diff --git a/vendor/github.com/gabriel-vasile/mimetype/internal/magic/ftyp.go b/vendor/github.com/gabriel-vasile/mimetype/internal/magic/ftyp.go new file mode 100644 index 0000000000..6575b4aecd --- /dev/null +++ b/vendor/github.com/gabriel-vasile/mimetype/internal/magic/ftyp.go @@ -0,0 +1,88 @@ +package magic + +import "bytes" + +var ( + // AVIF matches an AV1 Image File Format still or animated. + // Wikipedia page seems outdated listing image/avif-sequence for animations. + // https://github.com/AOMediaCodec/av1-avif/issues/59 + AVIF = ftyp([]byte("avif"), []byte("avis")) + // Mp4 matches an MP4 file. + Mp4 = ftyp( + []byte("avc1"), []byte("dash"), []byte("iso2"), []byte("iso3"), + []byte("iso4"), []byte("iso5"), []byte("iso6"), []byte("isom"), + []byte("mmp4"), []byte("mp41"), []byte("mp42"), []byte("mp4v"), + []byte("mp71"), []byte("MSNV"), []byte("NDAS"), []byte("NDSC"), + []byte("NSDC"), []byte("NSDH"), []byte("NDSM"), []byte("NDSP"), + []byte("NDSS"), []byte("NDXC"), []byte("NDXH"), []byte("NDXM"), + []byte("NDXP"), []byte("NDXS"), []byte("F4V "), []byte("F4P "), + ) + // ThreeGP matches a 3GPP file. + ThreeGP = ftyp( + []byte("3gp1"), []byte("3gp2"), []byte("3gp3"), []byte("3gp4"), + []byte("3gp5"), []byte("3gp6"), []byte("3gp7"), []byte("3gs7"), + []byte("3ge6"), []byte("3ge7"), []byte("3gg6"), + ) + // ThreeG2 matches a 3GPP2 file. + ThreeG2 = ftyp( + []byte("3g24"), []byte("3g25"), []byte("3g26"), []byte("3g2a"), + []byte("3g2b"), []byte("3g2c"), []byte("KDDI"), + ) + // AMp4 matches an audio MP4 file. + AMp4 = ftyp( + // audio for Adobe Flash Player 9+ + []byte("F4A "), []byte("F4B "), + // Apple iTunes AAC-LC (.M4A) Audio + []byte("M4B "), []byte("M4P "), + // MPEG-4 (.MP4) for SonyPSP + []byte("MSNV"), + // Nero Digital AAC Audio + []byte("NDAS"), + ) + // Mqv matches a Sony / Mobile QuickTime file. + Mqv = ftyp([]byte("mqt ")) + // M4a matches an audio M4A file. + M4a = ftyp([]byte("M4A ")) + // M4v matches an Appl4 M4V video file. + M4v = ftyp([]byte("M4V "), []byte("M4VH"), []byte("M4VP")) + // Heic matches a High Efficiency Image Coding (HEIC) file. + Heic = ftyp([]byte("heic"), []byte("heix")) + // HeicSequence matches a High Efficiency Image Coding (HEIC) file sequence. + HeicSequence = ftyp([]byte("hevc"), []byte("hevx")) + // Heif matches a High Efficiency Image File Format (HEIF) file. + Heif = ftyp([]byte("mif1"), []byte("heim"), []byte("heis"), []byte("avic")) + // HeifSequence matches a High Efficiency Image File Format (HEIF) file sequence. + HeifSequence = ftyp([]byte("msf1"), []byte("hevm"), []byte("hevs"), []byte("avcs")) + // TODO: add support for remaining video formats at ftyps.com. +) + +// QuickTime matches a QuickTime File Format file. +// https://www.loc.gov/preservation/digital/formats/fdd/fdd000052.shtml +// https://developer.apple.com/library/archive/documentation/QuickTime/QTFF/QTFFChap1/qtff1.html#//apple_ref/doc/uid/TP40000939-CH203-38190 +// https://github.com/apache/tika/blob/0f5570691133c75ac4472c3340354a6c4080b104/tika-core/src/main/resources/org/apache/tika/mime/tika-mimetypes.xml#L7758-L7777 +func QuickTime(raw []byte, _ uint32) bool { + if len(raw) < 12 { + return false + } + // First 4 bytes represent the size of the atom as unsigned int. + // Next 4 bytes are the type of the atom. + // For `ftyp` atoms check if first byte in size is 0, otherwise, a text file + // which happens to contain 'ftypqt ' at index 4 will trigger a false positive. + if bytes.Equal(raw[4:12], []byte("ftypqt ")) || + bytes.Equal(raw[4:12], []byte("ftypmoov")) { + return raw[0] == 0x00 + } + basicAtomTypes := [][]byte{ + []byte("moov\x00"), + []byte("mdat\x00"), + []byte("free\x00"), + []byte("skip\x00"), + []byte("pnot\x00"), + } + for _, a := range basicAtomTypes { + if bytes.Equal(raw[4:9], a) { + return true + } + } + return bytes.Equal(raw[:8], []byte("\x00\x00\x00\x08wide")) +} diff --git a/vendor/github.com/gabriel-vasile/mimetype/internal/magic/geo.go b/vendor/github.com/gabriel-vasile/mimetype/internal/magic/geo.go new file mode 100644 index 0000000000..f077e16724 --- /dev/null +++ b/vendor/github.com/gabriel-vasile/mimetype/internal/magic/geo.go @@ -0,0 +1,55 @@ +package magic + +import ( + "bytes" + "encoding/binary" +) + +// Shp matches a shape format file. +// https://www.esri.com/library/whitepapers/pdfs/shapefile.pdf +func Shp(raw []byte, limit uint32) bool { + if len(raw) < 112 { + return false + } + + if !(binary.BigEndian.Uint32(raw[0:4]) == 9994 && + binary.BigEndian.Uint32(raw[4:8]) == 0 && + binary.BigEndian.Uint32(raw[8:12]) == 0 && + binary.BigEndian.Uint32(raw[12:16]) == 0 && + binary.BigEndian.Uint32(raw[16:20]) == 0 && + binary.BigEndian.Uint32(raw[20:24]) == 0 && + binary.LittleEndian.Uint32(raw[28:32]) == 1000) { + return false + } + + shapeTypes := []int{ + 0, // Null shape + 1, // Point + 3, // Polyline + 5, // Polygon + 8, // MultiPoint + 11, // PointZ + 13, // PolylineZ + 15, // PolygonZ + 18, // MultiPointZ + 21, // PointM + 23, // PolylineM + 25, // PolygonM + 28, // MultiPointM + 31, // MultiPatch + } + + for _, st := range shapeTypes { + if st == int(binary.LittleEndian.Uint32(raw[108:112])) { + return true + } + } + + return false +} + +// Shx matches a shape index format file. +// https://www.esri.com/library/whitepapers/pdfs/shapefile.pdf +func Shx(raw []byte, limit uint32) bool { + return bytes.HasPrefix(raw, []byte{0x00, 0x00, 0x27, 0x0A}) +} diff --git a/vendor/github.com/gabriel-vasile/mimetype/internal/magic/image.go b/vendor/github.com/gabriel-vasile/mimetype/internal/magic/image.go new file mode 100644 index 0000000000..0eb7e95f37 --- /dev/null +++ b/vendor/github.com/gabriel-vasile/mimetype/internal/magic/image.go @@ -0,0 +1,110 @@ +package magic + +import "bytes" + +var ( + // Png matches a Portable Network Graphics file. + // https://www.w3.org/TR/PNG/ + Png = prefix([]byte{0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A}) + // Apng matches an Animated Portable Network Graphics file. + // https://wiki.mozilla.org/APNG_Specification + Apng = offset([]byte("acTL"), 37) + // Jpg matches a Joint Photographic Experts Group file. + Jpg = prefix([]byte{0xFF, 0xD8, 0xFF}) + // Jp2 matches a JPEG 2000 Image file (ISO 15444-1). + Jp2 = jpeg2k([]byte{0x6a, 0x70, 0x32, 0x20}) + // Jpx matches a JPEG 2000 Image file (ISO 15444-2). + Jpx = jpeg2k([]byte{0x6a, 0x70, 0x78, 0x20}) + // Jpm matches a JPEG 2000 Image file (ISO 15444-6). + Jpm = jpeg2k([]byte{0x6a, 0x70, 0x6D, 0x20}) + // Gif matches a Graphics Interchange Format file. + Gif = prefix([]byte("GIF87a"), []byte("GIF89a")) + // Bmp matches a bitmap image file. + Bmp = prefix([]byte{0x42, 0x4D}) + // Ps matches a PostScript file. + Ps = prefix([]byte("%!PS-Adobe-")) + // Psd matches a Photoshop Document file. + Psd = prefix([]byte("8BPS")) + // Ico matches an ICO file. + Ico = prefix([]byte{0x00, 0x00, 0x01, 0x00}, []byte{0x00, 0x00, 0x02, 0x00}) + // Icns matches an ICNS (Apple Icon Image format) file. + Icns = prefix([]byte("icns")) + // Tiff matches a Tagged Image File Format file. + Tiff = prefix([]byte{0x49, 0x49, 0x2A, 0x00}, []byte{0x4D, 0x4D, 0x00, 0x2A}) + // Bpg matches a Better Portable Graphics file. + Bpg = prefix([]byte{0x42, 0x50, 0x47, 0xFB}) + // Xcf matches GIMP image data. + Xcf = prefix([]byte("gimp xcf")) + // Pat matches GIMP pattern data. + Pat = offset([]byte("GPAT"), 20) + // Gbr matches GIMP brush data. + Gbr = offset([]byte("GIMP"), 20) + // Hdr matches Radiance HDR image. + // https://web.archive.org/web/20060913152809/http://local.wasp.uwa.edu.au/~pbourke/dataformats/pic/ + Hdr = prefix([]byte("#?RADIANCE\n")) + // Xpm matches X PixMap image data. + Xpm = prefix([]byte{0x2F, 0x2A, 0x20, 0x58, 0x50, 0x4D, 0x20, 0x2A, 0x2F}) + // Jxs matches a JPEG XS coded image file (ISO/IEC 21122-3). + Jxs = prefix([]byte{0x00, 0x00, 0x00, 0x0C, 0x4A, 0x58, 0x53, 0x20, 0x0D, 0x0A, 0x87, 0x0A}) + // Jxr matches Microsoft HD JXR photo file. + Jxr = prefix([]byte{0x49, 0x49, 0xBC, 0x01}) +) + +func jpeg2k(sig []byte) Detector { + return func(raw []byte, _ uint32) bool { + if len(raw) < 24 { + return false + } + + if !bytes.Equal(raw[4:8], []byte{0x6A, 0x50, 0x20, 0x20}) && + !bytes.Equal(raw[4:8], []byte{0x6A, 0x50, 0x32, 0x20}) { + return false + } + return bytes.Equal(raw[20:24], sig) + } +} + +// Webp matches a WebP file. +func Webp(raw []byte, _ uint32) bool { + return len(raw) > 12 && + bytes.Equal(raw[0:4], []byte("RIFF")) && + bytes.Equal(raw[8:12], []byte{0x57, 0x45, 0x42, 0x50}) +} + +// Dwg matches a CAD drawing file. +func Dwg(raw []byte, _ uint32) bool { + if len(raw) < 6 || raw[0] != 0x41 || raw[1] != 0x43 { + return false + } + dwgVersions := [][]byte{ + {0x31, 0x2E, 0x34, 0x30}, + {0x31, 0x2E, 0x35, 0x30}, + {0x32, 0x2E, 0x31, 0x30}, + {0x31, 0x30, 0x30, 0x32}, + {0x31, 0x30, 0x30, 0x33}, + {0x31, 0x30, 0x30, 0x34}, + {0x31, 0x30, 0x30, 0x36}, + {0x31, 0x30, 0x30, 0x39}, + {0x31, 0x30, 0x31, 0x32}, + {0x31, 0x30, 0x31, 0x34}, + {0x31, 0x30, 0x31, 0x35}, + {0x31, 0x30, 0x31, 0x38}, + {0x31, 0x30, 0x32, 0x31}, + {0x31, 0x30, 0x32, 0x34}, + {0x31, 0x30, 0x33, 0x32}, + } + + for _, d := range dwgVersions { + if bytes.Equal(raw[2:6], d) { + return true + } + } + + return false +} + +// Jxl matches JPEG XL image file. +func Jxl(raw []byte, _ uint32) bool { + return bytes.HasPrefix(raw, []byte{0xFF, 0x0A}) || + bytes.HasPrefix(raw, []byte("\x00\x00\x00\x0cJXL\x20\x0d\x0a\x87\x0a")) +} diff --git a/vendor/github.com/gabriel-vasile/mimetype/internal/magic/magic.go b/vendor/github.com/gabriel-vasile/mimetype/internal/magic/magic.go new file mode 100644 index 0000000000..34b84f401b --- /dev/null +++ b/vendor/github.com/gabriel-vasile/mimetype/internal/magic/magic.go @@ -0,0 +1,241 @@ +// Package magic holds the matching functions used to find MIME types. +package magic + +import ( + "bytes" + "fmt" +) + +type ( + // Detector receiveѕ the raw data of a file and returns whether the data + // meets any conditions. The limit parameter is an upper limit to the number + // of bytes received and is used to tell if the byte slice represents the + // whole file or is just the header of a file: len(raw) < limit or len(raw)>limit. + Detector func(raw []byte, limit uint32) bool + xmlSig struct { + // the local name of the root tag + localName []byte + // the namespace of the XML document + xmlns []byte + } +) + +// prefix creates a Detector which returns true if any of the provided signatures +// is the prefix of the raw input. +func prefix(sigs ...[]byte) Detector { + return func(raw []byte, limit uint32) bool { + for _, s := range sigs { + if bytes.HasPrefix(raw, s) { + return true + } + } + return false + } +} + +// offset creates a Detector which returns true if the provided signature can be +// found at offset in the raw input. +func offset(sig []byte, offset int) Detector { + return func(raw []byte, limit uint32) bool { + return len(raw) > offset && bytes.HasPrefix(raw[offset:], sig) + } +} + +// ciPrefix is like prefix but the check is case insensitive. +func ciPrefix(sigs ...[]byte) Detector { + return func(raw []byte, limit uint32) bool { + for _, s := range sigs { + if ciCheck(s, raw) { + return true + } + } + return false + } +} +func ciCheck(sig, raw []byte) bool { + if len(raw) < len(sig)+1 { + return false + } + // perform case insensitive check + for i, b := range sig { + db := raw[i] + if 'A' <= b && b <= 'Z' { + db &= 0xDF + } + if b != db { + return false + } + } + + return true +} + +// xml creates a Detector which returns true if any of the provided XML signatures +// matches the raw input. +func xml(sigs ...xmlSig) Detector { + return func(raw []byte, limit uint32) bool { + raw = trimLWS(raw) + if len(raw) == 0 { + return false + } + for _, s := range sigs { + if xmlCheck(s, raw) { + return true + } + } + return false + } +} +func xmlCheck(sig xmlSig, raw []byte) bool { + raw = raw[:min(len(raw), 512)] + + if len(sig.localName) == 0 { + return bytes.Index(raw, sig.xmlns) > 0 + } + if len(sig.xmlns) == 0 { + return bytes.Index(raw, sig.localName) > 0 + } + + localNameIndex := bytes.Index(raw, sig.localName) + return localNameIndex != -1 && localNameIndex < bytes.Index(raw, sig.xmlns) +} + +// markup creates a Detector which returns true is any of the HTML signatures +// matches the raw input. +func markup(sigs ...[]byte) Detector { + return func(raw []byte, limit uint32) bool { + if bytes.HasPrefix(raw, []byte{0xEF, 0xBB, 0xBF}) { + // We skip the UTF-8 BOM if present to ensure we correctly + // process any leading whitespace. The presence of the BOM + // is taken into account during charset detection in charset.go. + raw = trimLWS(raw[3:]) + } else { + raw = trimLWS(raw) + } + if len(raw) == 0 { + return false + } + for _, s := range sigs { + if markupCheck(s, raw) { + return true + } + } + return false + } +} +func markupCheck(sig, raw []byte) bool { + if len(raw) < len(sig)+1 { + return false + } + + // perform case insensitive check + for i, b := range sig { + db := raw[i] + if 'A' <= b && b <= 'Z' { + db &= 0xDF + } + if b != db { + return false + } + } + // Next byte must be space or right angle bracket. + if db := raw[len(sig)]; db != ' ' && db != '>' { + return false + } + + return true +} + +// ftyp creates a Detector which returns true if any of the FTYP signatures +// matches the raw input. +func ftyp(sigs ...[]byte) Detector { + return func(raw []byte, limit uint32) bool { + if len(raw) < 12 { + return false + } + for _, s := range sigs { + if bytes.Equal(raw[4:12], append([]byte("ftyp"), s...)) { + return true + } + } + return false + } +} + +func newXMLSig(localName, xmlns string) xmlSig { + ret := xmlSig{xmlns: []byte(xmlns)} + if localName != "" { + ret.localName = []byte(fmt.Sprintf("<%s", localName)) + } + + return ret +} + +// A valid shebang starts with the "#!" characters, +// followed by any number of spaces, +// followed by the path to the interpreter, +// and, optionally, followed by the arguments for the interpreter. +// +// Ex: +// +// #! /usr/bin/env php +// +// /usr/bin/env is the interpreter, php is the first and only argument. +func shebang(sigs ...[]byte) Detector { + return func(raw []byte, limit uint32) bool { + for _, s := range sigs { + if shebangCheck(s, firstLine(raw)) { + return true + } + } + return false + } +} + +func shebangCheck(sig, raw []byte) bool { + if len(raw) < len(sig)+2 { + return false + } + if raw[0] != '#' || raw[1] != '!' { + return false + } + + return bytes.Equal(trimLWS(trimRWS(raw[2:])), sig) +} + +// trimLWS trims whitespace from beginning of the input. +func trimLWS(in []byte) []byte { + firstNonWS := 0 + for ; firstNonWS < len(in) && isWS(in[firstNonWS]); firstNonWS++ { + } + + return in[firstNonWS:] +} + +// trimRWS trims whitespace from the end of the input. +func trimRWS(in []byte) []byte { + lastNonWS := len(in) - 1 + for ; lastNonWS > 0 && isWS(in[lastNonWS]); lastNonWS-- { + } + + return in[:lastNonWS+1] +} + +func firstLine(in []byte) []byte { + lineEnd := 0 + for ; lineEnd < len(in) && in[lineEnd] != '\n'; lineEnd++ { + } + + return in[:lineEnd] +} + +func isWS(b byte) bool { + return b == '\t' || b == '\n' || b == '\x0c' || b == '\r' || b == ' ' +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} diff --git a/vendor/github.com/gabriel-vasile/mimetype/internal/magic/ms_office.go b/vendor/github.com/gabriel-vasile/mimetype/internal/magic/ms_office.go new file mode 100644 index 0000000000..5964ce596c --- /dev/null +++ b/vendor/github.com/gabriel-vasile/mimetype/internal/magic/ms_office.go @@ -0,0 +1,225 @@ +package magic + +import ( + "bytes" + "encoding/binary" +) + +var ( + xlsxSigFiles = []string{ + "xl/worksheets/", + "xl/drawings/", + "xl/theme/", + "xl/_rels/", + "xl/styles.xml", + "xl/workbook.xml", + "xl/sharedStrings.xml", + } + docxSigFiles = []string{ + "word/media/", + "word/_rels/document.xml.rels", + "word/document.xml", + "word/styles.xml", + "word/fontTable.xml", + "word/settings.xml", + "word/numbering.xml", + "word/header", + "word/footer", + } + pptxSigFiles = []string{ + "ppt/slides/", + "ppt/media/", + "ppt/slideLayouts/", + "ppt/theme/", + "ppt/slideMasters/", + "ppt/tags/", + "ppt/notesMasters/", + "ppt/_rels/", + "ppt/handoutMasters/", + "ppt/notesSlides/", + "ppt/presentation.xml", + "ppt/tableStyles.xml", + "ppt/presProps.xml", + "ppt/viewProps.xml", + } +) + +// Xlsx matches a Microsoft Excel 2007 file. +func Xlsx(raw []byte, limit uint32) bool { + return zipContains(raw, xlsxSigFiles...) +} + +// Docx matches a Microsoft Word 2007 file. +func Docx(raw []byte, limit uint32) bool { + return zipContains(raw, docxSigFiles...) +} + +// Pptx matches a Microsoft PowerPoint 2007 file. +func Pptx(raw []byte, limit uint32) bool { + return zipContains(raw, pptxSigFiles...) +} + +// Ole matches an Open Linking and Embedding file. +// +// https://en.wikipedia.org/wiki/Object_Linking_and_Embedding +func Ole(raw []byte, limit uint32) bool { + return bytes.HasPrefix(raw, []byte{0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1}) +} + +// Aaf matches an Advanced Authoring Format file. +// See: https://pyaaf.readthedocs.io/en/latest/about.html +// See: https://en.wikipedia.org/wiki/Advanced_Authoring_Format +func Aaf(raw []byte, limit uint32) bool { + if len(raw) < 31 { + return false + } + return bytes.HasPrefix(raw[8:], []byte{0x41, 0x41, 0x46, 0x42, 0x0D, 0x00, 0x4F, 0x4D}) && + (raw[30] == 0x09 || raw[30] == 0x0C) +} + +// Doc matches a Microsoft Word 97-2003 file. +// See: https://github.com/decalage2/oletools/blob/412ee36ae45e70f42123e835871bac956d958461/oletools/common/clsid.py +func Doc(raw []byte, _ uint32) bool { + clsids := [][]byte{ + // Microsoft Word 97-2003 Document (Word.Document.8) + {0x06, 0x09, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}, + // Microsoft Word 6.0-7.0 Document (Word.Document.6) + {0x00, 0x09, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}, + // Microsoft Word Picture (Word.Picture.8) + {0x07, 0x09, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}, + } + + for _, clsid := range clsids { + if matchOleClsid(raw, clsid) { + return true + } + } + + return false +} + +// Ppt matches a Microsoft PowerPoint 97-2003 file or a PowerPoint 95 presentation. +func Ppt(raw []byte, limit uint32) bool { + // Root CLSID test is the safest way to detect identify OLE, however, the format + // often places the root CLSID at the end of the file. + if matchOleClsid(raw, []byte{ + 0x10, 0x8d, 0x81, 0x64, 0x9b, 0x4f, 0xcf, 0x11, + 0x86, 0xea, 0x00, 0xaa, 0x00, 0xb9, 0x29, 0xe8, + }) || matchOleClsid(raw, []byte{ + 0x70, 0xae, 0x7b, 0xea, 0x3b, 0xfb, 0xcd, 0x11, + 0xa9, 0x03, 0x00, 0xaa, 0x00, 0x51, 0x0e, 0xa3, + }) { + return true + } + + lin := len(raw) + if lin < 520 { + return false + } + pptSubHeaders := [][]byte{ + {0xA0, 0x46, 0x1D, 0xF0}, + {0x00, 0x6E, 0x1E, 0xF0}, + {0x0F, 0x00, 0xE8, 0x03}, + } + for _, h := range pptSubHeaders { + if bytes.HasPrefix(raw[512:], h) { + return true + } + } + + if bytes.HasPrefix(raw[512:], []byte{0xFD, 0xFF, 0xFF, 0xFF}) && + raw[518] == 0x00 && raw[519] == 0x00 { + return true + } + + return lin > 1152 && bytes.Contains(raw[1152:min(4096, lin)], + []byte("P\x00o\x00w\x00e\x00r\x00P\x00o\x00i\x00n\x00t\x00 D\x00o\x00c\x00u\x00m\x00e\x00n\x00t")) +} + +// Xls matches a Microsoft Excel 97-2003 file. +func Xls(raw []byte, limit uint32) bool { + // Root CLSID test is the safest way to detect identify OLE, however, the format + // often places the root CLSID at the end of the file. + if matchOleClsid(raw, []byte{ + 0x10, 0x08, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, + }) || matchOleClsid(raw, []byte{ + 0x20, 0x08, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, + }) { + return true + } + + lin := len(raw) + if lin < 520 { + return false + } + xlsSubHeaders := [][]byte{ + {0x09, 0x08, 0x10, 0x00, 0x00, 0x06, 0x05, 0x00}, + {0xFD, 0xFF, 0xFF, 0xFF, 0x10}, + {0xFD, 0xFF, 0xFF, 0xFF, 0x1F}, + {0xFD, 0xFF, 0xFF, 0xFF, 0x22}, + {0xFD, 0xFF, 0xFF, 0xFF, 0x23}, + {0xFD, 0xFF, 0xFF, 0xFF, 0x28}, + {0xFD, 0xFF, 0xFF, 0xFF, 0x29}, + } + for _, h := range xlsSubHeaders { + if bytes.HasPrefix(raw[512:], h) { + return true + } + } + + return lin > 1152 && bytes.Contains(raw[1152:min(4096, lin)], + []byte("W\x00k\x00s\x00S\x00S\x00W\x00o\x00r\x00k\x00B\x00o\x00o\x00k")) +} + +// Pub matches a Microsoft Publisher file. +func Pub(raw []byte, limit uint32) bool { + return matchOleClsid(raw, []byte{ + 0x01, 0x12, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, + }) +} + +// Msg matches a Microsoft Outlook email file. +func Msg(raw []byte, limit uint32) bool { + return matchOleClsid(raw, []byte{ + 0x0B, 0x0D, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, + }) +} + +// Msi matches a Microsoft Windows Installer file. +// http://fileformats.archiveteam.org/wiki/Microsoft_Compound_File +func Msi(raw []byte, limit uint32) bool { + return matchOleClsid(raw, []byte{ + 0x84, 0x10, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, + }) +} + +// Helper to match by a specific CLSID of a compound file. +// +// http://fileformats.archiveteam.org/wiki/Microsoft_Compound_File +func matchOleClsid(in []byte, clsid []byte) bool { + // Microsoft Compound files v3 have a sector length of 512, while v4 has 4096. + // Change sector offset depending on file version. + // https://www.loc.gov/preservation/digital/formats/fdd/fdd000392.shtml + sectorLength := 512 + if len(in) < sectorLength { + return false + } + if in[26] == 0x04 && in[27] == 0x00 { + sectorLength = 4096 + } + + // SecID of first sector of the directory stream. + firstSecID := int(binary.LittleEndian.Uint32(in[48:52])) + + // Expected offset of CLSID for root storage object. + clsidOffset := sectorLength*(1+firstSecID) + 80 + + if len(in) <= clsidOffset+16 { + return false + } + + return bytes.HasPrefix(in[clsidOffset:], clsid) +} diff --git a/vendor/github.com/gabriel-vasile/mimetype/internal/magic/ogg.go b/vendor/github.com/gabriel-vasile/mimetype/internal/magic/ogg.go new file mode 100644 index 0000000000..bb4cd781b6 --- /dev/null +++ b/vendor/github.com/gabriel-vasile/mimetype/internal/magic/ogg.go @@ -0,0 +1,42 @@ +package magic + +import ( + "bytes" +) + +/* + NOTE: + + In May 2003, two Internet RFCs were published relating to the format. + The Ogg bitstream was defined in RFC 3533 (which is classified as + 'informative') and its Internet content type (application/ogg) in RFC + 3534 (which is, as of 2006, a proposed standard protocol). In + September 2008, RFC 3534 was obsoleted by RFC 5334, which added + content types video/ogg, audio/ogg and filename extensions .ogx, .ogv, + .oga, .spx. + + See: + https://tools.ietf.org/html/rfc3533 + https://developer.mozilla.org/en-US/docs/Web/HTTP/Configuring_servers_for_Ogg_media#Serve_media_with_the_correct_MIME_type + https://github.com/file/file/blob/master/magic/Magdir/vorbis +*/ + +// Ogg matches an Ogg file. +func Ogg(raw []byte, limit uint32) bool { + return bytes.HasPrefix(raw, []byte("\x4F\x67\x67\x53\x00")) +} + +// OggAudio matches an audio ogg file. +func OggAudio(raw []byte, limit uint32) bool { + return len(raw) >= 37 && (bytes.HasPrefix(raw[28:], []byte("\x7fFLAC")) || + bytes.HasPrefix(raw[28:], []byte("\x01vorbis")) || + bytes.HasPrefix(raw[28:], []byte("OpusHead")) || + bytes.HasPrefix(raw[28:], []byte("Speex\x20\x20\x20"))) +} + +// OggVideo matches a video ogg file. +func OggVideo(raw []byte, limit uint32) bool { + return len(raw) >= 37 && (bytes.HasPrefix(raw[28:], []byte("\x80theora")) || + bytes.HasPrefix(raw[28:], []byte("fishead\x00")) || + bytes.HasPrefix(raw[28:], []byte("\x01video\x00\x00\x00"))) // OGM video +} diff --git a/vendor/github.com/gabriel-vasile/mimetype/internal/magic/text.go b/vendor/github.com/gabriel-vasile/mimetype/internal/magic/text.go new file mode 100644 index 0000000000..e2a03caf50 --- /dev/null +++ b/vendor/github.com/gabriel-vasile/mimetype/internal/magic/text.go @@ -0,0 +1,375 @@ +package magic + +import ( + "bufio" + "bytes" + "strings" + "time" + + "github.com/gabriel-vasile/mimetype/internal/charset" + "github.com/gabriel-vasile/mimetype/internal/json" +) + +var ( + // HTML matches a Hypertext Markup Language file. + HTML = markup( + []byte(" 0 +} + +// GeoJSON matches a RFC 7946 GeoJSON file. +// +// GeoJSON detection implies searching for key:value pairs like: `"type": "Feature"` +// in the input. +// BUG(gabriel-vasile): The "type" key should be searched for in the root object. +func GeoJSON(raw []byte, limit uint32) bool { + raw = trimLWS(raw) + if len(raw) == 0 { + return false + } + // GeoJSON is always a JSON object, not a JSON array or any other JSON value. + if raw[0] != '{' { + return false + } + + s := []byte(`"type"`) + si, sl := bytes.Index(raw, s), len(s) + + if si == -1 { + return false + } + + // If the "type" string is the suffix of the input, + // there is no need to search for the value of the key. + if si+sl == len(raw) { + return false + } + // Skip the "type" part. + raw = raw[si+sl:] + // Skip any whitespace before the colon. + raw = trimLWS(raw) + // Check for colon. + if len(raw) == 0 || raw[0] != ':' { + return false + } + // Skip any whitespace after the colon. + raw = trimLWS(raw[1:]) + + geoJSONTypes := [][]byte{ + []byte(`"Feature"`), + []byte(`"FeatureCollection"`), + []byte(`"Point"`), + []byte(`"LineString"`), + []byte(`"Polygon"`), + []byte(`"MultiPoint"`), + []byte(`"MultiLineString"`), + []byte(`"MultiPolygon"`), + []byte(`"GeometryCollection"`), + } + for _, t := range geoJSONTypes { + if bytes.HasPrefix(raw, t) { + return true + } + } + + return false +} + +// NdJSON matches a Newline delimited JSON file. All complete lines from raw +// must be valid JSON documents meaning they contain one of the valid JSON data +// types. +func NdJSON(raw []byte, limit uint32) bool { + lCount, hasObjOrArr := 0, false + sc := bufio.NewScanner(dropLastLine(raw, limit)) + for sc.Scan() { + l := sc.Bytes() + // Empty lines are allowed in NDJSON. + if l = trimRWS(trimLWS(l)); len(l) == 0 { + continue + } + _, err := json.Scan(l) + if err != nil { + return false + } + if l[0] == '[' || l[0] == '{' { + hasObjOrArr = true + } + lCount++ + } + + return lCount > 1 && hasObjOrArr +} + +// HAR matches a HAR Spec file. +// Spec: http://www.softwareishard.com/blog/har-12-spec/ +func HAR(raw []byte, limit uint32) bool { + s := []byte(`"log"`) + si, sl := bytes.Index(raw, s), len(s) + + if si == -1 { + return false + } + + // If the "log" string is the suffix of the input, + // there is no need to search for the value of the key. + if si+sl == len(raw) { + return false + } + // Skip the "log" part. + raw = raw[si+sl:] + // Skip any whitespace before the colon. + raw = trimLWS(raw) + // Check for colon. + if len(raw) == 0 || raw[0] != ':' { + return false + } + // Skip any whitespace after the colon. + raw = trimLWS(raw[1:]) + + harJSONTypes := [][]byte{ + []byte(`"version"`), + []byte(`"creator"`), + []byte(`"entries"`), + } + for _, t := range harJSONTypes { + si := bytes.Index(raw, t) + if si > -1 { + return true + } + } + + return false +} + +// Svg matches a SVG file. +func Svg(raw []byte, limit uint32) bool { + return bytes.Contains(raw, []byte(" 00:02:19,376) limits secondLine + // length to exactly 29 characters. + if len(secondLine) != 29 { + return false + } + // Decimal separator of fractional seconds in the timestamps must be a + // comma, not a period. + if strings.Contains(secondLine, ".") { + return false + } + // For Go <1.17, comma is not recognised as a decimal separator by `time.Parse`. + secondLine = strings.ReplaceAll(secondLine, ",", ".") + // Second line must be a time range. + ts := strings.Split(secondLine, " --> ") + if len(ts) != 2 { + return false + } + const layout = "15:04:05.000" + t0, err := time.Parse(layout, ts[0]) + if err != nil { + return false + } + t1, err := time.Parse(layout, ts[1]) + if err != nil { + return false + } + if t0.After(t1) { + return false + } + + // A third line must exist and not be empty. This is the actual subtitle text. + return s.Scan() && len(s.Bytes()) != 0 +} + +// Vtt matches a Web Video Text Tracks (WebVTT) file. See +// https://www.iana.org/assignments/media-types/text/vtt. +func Vtt(raw []byte, limit uint32) bool { + // Prefix match. + prefixes := [][]byte{ + {0xEF, 0xBB, 0xBF, 0x57, 0x45, 0x42, 0x56, 0x54, 0x54, 0x0A}, // UTF-8 BOM, "WEBVTT" and a line feed + {0xEF, 0xBB, 0xBF, 0x57, 0x45, 0x42, 0x56, 0x54, 0x54, 0x0D}, // UTF-8 BOM, "WEBVTT" and a carriage return + {0xEF, 0xBB, 0xBF, 0x57, 0x45, 0x42, 0x56, 0x54, 0x54, 0x20}, // UTF-8 BOM, "WEBVTT" and a space + {0xEF, 0xBB, 0xBF, 0x57, 0x45, 0x42, 0x56, 0x54, 0x54, 0x09}, // UTF-8 BOM, "WEBVTT" and a horizontal tab + {0x57, 0x45, 0x42, 0x56, 0x54, 0x54, 0x0A}, // "WEBVTT" and a line feed + {0x57, 0x45, 0x42, 0x56, 0x54, 0x54, 0x0D}, // "WEBVTT" and a carriage return + {0x57, 0x45, 0x42, 0x56, 0x54, 0x54, 0x20}, // "WEBVTT" and a space + {0x57, 0x45, 0x42, 0x56, 0x54, 0x54, 0x09}, // "WEBVTT" and a horizontal tab + } + for _, p := range prefixes { + if bytes.HasPrefix(raw, p) { + return true + } + } + + // Exact match. + return bytes.Equal(raw, []byte{0xEF, 0xBB, 0xBF, 0x57, 0x45, 0x42, 0x56, 0x54, 0x54}) || // UTF-8 BOM and "WEBVTT" + bytes.Equal(raw, []byte{0x57, 0x45, 0x42, 0x56, 0x54, 0x54}) // "WEBVTT" +} diff --git a/vendor/github.com/gabriel-vasile/mimetype/internal/magic/text_csv.go b/vendor/github.com/gabriel-vasile/mimetype/internal/magic/text_csv.go new file mode 100644 index 0000000000..84ed649284 --- /dev/null +++ b/vendor/github.com/gabriel-vasile/mimetype/internal/magic/text_csv.go @@ -0,0 +1,63 @@ +package magic + +import ( + "bytes" + "encoding/csv" + "errors" + "io" +) + +// Csv matches a comma-separated values file. +func Csv(raw []byte, limit uint32) bool { + return sv(raw, ',', limit) +} + +// Tsv matches a tab-separated values file. +func Tsv(raw []byte, limit uint32) bool { + return sv(raw, '\t', limit) +} + +func sv(in []byte, comma rune, limit uint32) bool { + r := csv.NewReader(dropLastLine(in, limit)) + r.Comma = comma + r.ReuseRecord = true + r.LazyQuotes = true + r.Comment = '#' + + lines := 0 + for { + _, err := r.Read() + if errors.Is(err, io.EOF) { + break + } + if err != nil { + return false + } + lines++ + } + + return r.FieldsPerRecord > 1 && lines > 1 +} + +// dropLastLine drops the last incomplete line from b. +// +// mimetype limits itself to ReadLimit bytes when performing a detection. +// This means, for file formats like CSV for NDJSON, the last line of the input +// can be an incomplete line. +func dropLastLine(b []byte, cutAt uint32) io.Reader { + if cutAt == 0 { + return bytes.NewReader(b) + } + if uint32(len(b)) >= cutAt { + for i := cutAt - 1; i > 0; i-- { + if b[i] == '\n' { + return bytes.NewReader(b[:i]) + } + } + + // No newline was found between the 0 index and cutAt. + return bytes.NewReader(b[:cutAt]) + } + + return bytes.NewReader(b) +} diff --git a/vendor/github.com/gabriel-vasile/mimetype/internal/magic/video.go b/vendor/github.com/gabriel-vasile/mimetype/internal/magic/video.go new file mode 100644 index 0000000000..9caf55538a --- /dev/null +++ b/vendor/github.com/gabriel-vasile/mimetype/internal/magic/video.go @@ -0,0 +1,85 @@ +package magic + +import ( + "bytes" +) + +var ( + // Flv matches a Flash video file. + Flv = prefix([]byte("\x46\x4C\x56\x01")) + // Asf matches an Advanced Systems Format file. + Asf = prefix([]byte{ + 0x30, 0x26, 0xB2, 0x75, 0x8E, 0x66, 0xCF, 0x11, + 0xA6, 0xD9, 0x00, 0xAA, 0x00, 0x62, 0xCE, 0x6C, + }) + // Rmvb matches a RealMedia Variable Bitrate file. + Rmvb = prefix([]byte{0x2E, 0x52, 0x4D, 0x46}) +) + +// WebM matches a WebM file. +func WebM(raw []byte, limit uint32) bool { + return isMatroskaFileTypeMatched(raw, "webm") +} + +// Mkv matches a mkv file. +func Mkv(raw []byte, limit uint32) bool { + return isMatroskaFileTypeMatched(raw, "matroska") +} + +// isMatroskaFileTypeMatched is used for webm and mkv file matching. +// It checks for .Eߣ sequence. If the sequence is found, +// then it means it is Matroska media container, including WebM. +// Then it verifies which of the file type it is representing by matching the +// file specific string. +func isMatroskaFileTypeMatched(in []byte, flType string) bool { + if bytes.HasPrefix(in, []byte("\x1A\x45\xDF\xA3")) { + return isFileTypeNamePresent(in, flType) + } + return false +} + +// isFileTypeNamePresent accepts the matroska input data stream and searches +// for the given file type in the stream. Return whether a match is found. +// The logic of search is: find first instance of \x42\x82 and then +// search for given string after n bytes of above instance. +func isFileTypeNamePresent(in []byte, flType string) bool { + ind, maxInd, lenIn := 0, 4096, len(in) + if lenIn < maxInd { // restricting length to 4096 + maxInd = lenIn + } + ind = bytes.Index(in[:maxInd], []byte("\x42\x82")) + if ind > 0 && lenIn > ind+2 { + ind += 2 + + // filetype name will be present exactly + // n bytes after the match of the two bytes "\x42\x82" + n := vintWidth(int(in[ind])) + if lenIn > ind+n { + return bytes.HasPrefix(in[ind+n:], []byte(flType)) + } + } + return false +} + +// vintWidth parses the variable-integer width in matroska containers +func vintWidth(v int) int { + mask, max, num := 128, 8, 1 + for num < max && v&mask == 0 { + mask = mask >> 1 + num++ + } + return num +} + +// Mpeg matches a Moving Picture Experts Group file. +func Mpeg(raw []byte, limit uint32) bool { + return len(raw) > 3 && bytes.HasPrefix(raw, []byte{0x00, 0x00, 0x01}) && + raw[3] >= 0xB0 && raw[3] <= 0xBF +} + +// Avi matches an Audio Video Interleaved file. +func Avi(raw []byte, limit uint32) bool { + return len(raw) > 16 && + bytes.Equal(raw[:4], []byte("RIFF")) && + bytes.Equal(raw[8:16], []byte("AVI LIST")) +} diff --git a/vendor/github.com/gabriel-vasile/mimetype/internal/magic/zip.go b/vendor/github.com/gabriel-vasile/mimetype/internal/magic/zip.go new file mode 100644 index 0000000000..dabee947b9 --- /dev/null +++ b/vendor/github.com/gabriel-vasile/mimetype/internal/magic/zip.go @@ -0,0 +1,92 @@ +package magic + +import ( + "bytes" + "encoding/binary" + "strings" +) + +var ( + // Odt matches an OpenDocument Text file. + Odt = offset([]byte("mimetypeapplication/vnd.oasis.opendocument.text"), 30) + // Ott matches an OpenDocument Text Template file. + Ott = offset([]byte("mimetypeapplication/vnd.oasis.opendocument.text-template"), 30) + // Ods matches an OpenDocument Spreadsheet file. + Ods = offset([]byte("mimetypeapplication/vnd.oasis.opendocument.spreadsheet"), 30) + // Ots matches an OpenDocument Spreadsheet Template file. + Ots = offset([]byte("mimetypeapplication/vnd.oasis.opendocument.spreadsheet-template"), 30) + // Odp matches an OpenDocument Presentation file. + Odp = offset([]byte("mimetypeapplication/vnd.oasis.opendocument.presentation"), 30) + // Otp matches an OpenDocument Presentation Template file. + Otp = offset([]byte("mimetypeapplication/vnd.oasis.opendocument.presentation-template"), 30) + // Odg matches an OpenDocument Drawing file. + Odg = offset([]byte("mimetypeapplication/vnd.oasis.opendocument.graphics"), 30) + // Otg matches an OpenDocument Drawing Template file. + Otg = offset([]byte("mimetypeapplication/vnd.oasis.opendocument.graphics-template"), 30) + // Odf matches an OpenDocument Formula file. + Odf = offset([]byte("mimetypeapplication/vnd.oasis.opendocument.formula"), 30) + // Odc matches an OpenDocument Chart file. + Odc = offset([]byte("mimetypeapplication/vnd.oasis.opendocument.chart"), 30) + // Epub matches an EPUB file. + Epub = offset([]byte("mimetypeapplication/epub+zip"), 30) + // Sxc matches an OpenOffice Spreadsheet file. + Sxc = offset([]byte("mimetypeapplication/vnd.sun.xml.calc"), 30) +) + +// Zip matches a zip archive. +func Zip(raw []byte, limit uint32) bool { + return len(raw) > 3 && + raw[0] == 0x50 && raw[1] == 0x4B && + (raw[2] == 0x3 || raw[2] == 0x5 || raw[2] == 0x7) && + (raw[3] == 0x4 || raw[3] == 0x6 || raw[3] == 0x8) +} + +// Jar matches a Java archive file. +func Jar(raw []byte, limit uint32) bool { + return zipContains(raw, "META-INF/MANIFEST.MF") +} + +// zipTokenizer holds the source zip file and scanned index. +type zipTokenizer struct { + in []byte + i int // current index +} + +// next returns the next file name from the zip headers. +// https://web.archive.org/web/20191129114319/https://users.cs.jmu.edu/buchhofp/forensics/formats/pkzip.html +func (t *zipTokenizer) next() (fileName string) { + if t.i > len(t.in) { + return + } + in := t.in[t.i:] + // pkSig is the signature of the zip local file header. + pkSig := []byte("PK\003\004") + pkIndex := bytes.Index(in, pkSig) + // 30 is the offset of the file name in the header. + fNameOffset := pkIndex + 30 + // end if signature not found or file name offset outside of file. + if pkIndex == -1 || fNameOffset > len(in) { + return + } + + fNameLen := int(binary.LittleEndian.Uint16(in[pkIndex+26 : pkIndex+28])) + if fNameLen <= 0 || fNameOffset+fNameLen > len(in) { + return + } + t.i += fNameOffset + fNameLen + return string(in[fNameOffset : fNameOffset+fNameLen]) +} + +// zipContains returns true if the zip file headers from in contain any of the paths. +func zipContains(in []byte, paths ...string) bool { + t := zipTokenizer{in: in} + for i, tok := 0, t.next(); tok != ""; i, tok = i+1, t.next() { + for p := range paths { + if strings.HasPrefix(tok, paths[p]) { + return true + } + } + } + + return false +} diff --git a/vendor/github.com/gabriel-vasile/mimetype/mime.go b/vendor/github.com/gabriel-vasile/mimetype/mime.go new file mode 100644 index 0000000000..62cb15f593 --- /dev/null +++ b/vendor/github.com/gabriel-vasile/mimetype/mime.go @@ -0,0 +1,186 @@ +package mimetype + +import ( + "mime" + + "github.com/gabriel-vasile/mimetype/internal/charset" + "github.com/gabriel-vasile/mimetype/internal/magic" +) + +// MIME struct holds information about a file format: the string representation +// of the MIME type, the extension and the parent file format. +type MIME struct { + mime string + aliases []string + extension string + // detector receives the raw input and a limit for the number of bytes it is + // allowed to check. It returns whether the input matches a signature or not. + detector magic.Detector + children []*MIME + parent *MIME +} + +// String returns the string representation of the MIME type, e.g., "application/zip". +func (m *MIME) String() string { + return m.mime +} + +// Extension returns the file extension associated with the MIME type. +// It includes the leading dot, as in ".html". When the file format does not +// have an extension, the empty string is returned. +func (m *MIME) Extension() string { + return m.extension +} + +// Parent returns the parent MIME type from the hierarchy. +// Each MIME type has a non-nil parent, except for the root MIME type. +// +// For example, the application/json and text/html MIME types have text/plain as +// their parent because they are text files who happen to contain JSON or HTML. +// Another example is the ZIP format, which is used as container +// for Microsoft Office files, EPUB files, JAR files, and others. +func (m *MIME) Parent() *MIME { + return m.parent +} + +// Is checks whether this MIME type, or any of its aliases, is equal to the +// expected MIME type. MIME type equality test is done on the "type/subtype" +// section, ignores any optional MIME parameters, ignores any leading and +// trailing whitespace, and is case insensitive. +func (m *MIME) Is(expectedMIME string) bool { + // Parsing is needed because some detected MIME types contain parameters + // that need to be stripped for the comparison. + expectedMIME, _, _ = mime.ParseMediaType(expectedMIME) + found, _, _ := mime.ParseMediaType(m.mime) + + if expectedMIME == found { + return true + } + + for _, alias := range m.aliases { + if alias == expectedMIME { + return true + } + } + + return false +} + +func newMIME( + mime, extension string, + detector magic.Detector, + children ...*MIME) *MIME { + m := &MIME{ + mime: mime, + extension: extension, + detector: detector, + children: children, + } + + for _, c := range children { + c.parent = m + } + + return m +} + +func (m *MIME) alias(aliases ...string) *MIME { + m.aliases = aliases + return m +} + +// match does a depth-first search on the signature tree. It returns the deepest +// successful node for which all the children detection functions fail. +func (m *MIME) match(in []byte, readLimit uint32) *MIME { + for _, c := range m.children { + if c.detector(in, readLimit) { + return c.match(in, readLimit) + } + } + + needsCharset := map[string]func([]byte) string{ + "text/plain": charset.FromPlain, + "text/html": charset.FromHTML, + "text/xml": charset.FromXML, + } + // ps holds optional MIME parameters. + ps := map[string]string{} + if f, ok := needsCharset[m.mime]; ok { + if cset := f(in); cset != "" { + ps["charset"] = cset + } + } + + return m.cloneHierarchy(ps) +} + +// flatten transforms an hierarchy of MIMEs into a slice of MIMEs. +func (m *MIME) flatten() []*MIME { + out := []*MIME{m} + for _, c := range m.children { + out = append(out, c.flatten()...) + } + + return out +} + +// clone creates a new MIME with the provided optional MIME parameters. +func (m *MIME) clone(ps map[string]string) *MIME { + clonedMIME := m.mime + if len(ps) > 0 { + clonedMIME = mime.FormatMediaType(m.mime, ps) + } + + return &MIME{ + mime: clonedMIME, + aliases: m.aliases, + extension: m.extension, + } +} + +// cloneHierarchy creates a clone of m and all its ancestors. The optional MIME +// parameters are set on the last child of the hierarchy. +func (m *MIME) cloneHierarchy(ps map[string]string) *MIME { + ret := m.clone(ps) + lastChild := ret + for p := m.Parent(); p != nil; p = p.Parent() { + pClone := p.clone(nil) + lastChild.parent = pClone + lastChild = pClone + } + + return ret +} + +func (m *MIME) lookup(mime string) *MIME { + for _, n := range append(m.aliases, m.mime) { + if n == mime { + return m + } + } + + for _, c := range m.children { + if m := c.lookup(mime); m != nil { + return m + } + } + return nil +} + +// Extend adds detection for a sub-format. The detector is a function +// returning true when the raw input file satisfies a signature. +// The sub-format will be detected if all the detectors in the parent chain return true. +// The extension should include the leading dot, as in ".html". +func (m *MIME) Extend(detector func(raw []byte, limit uint32) bool, mime, extension string, aliases ...string) { + c := &MIME{ + mime: mime, + extension: extension, + detector: detector, + parent: m, + aliases: aliases, + } + + mu.Lock() + m.children = append([]*MIME{c}, m.children...) + mu.Unlock() +} diff --git a/vendor/github.com/gabriel-vasile/mimetype/mimetype.gif b/vendor/github.com/gabriel-vasile/mimetype/mimetype.gif new file mode 100644 index 0000000000..c3e8087673 Binary files /dev/null and b/vendor/github.com/gabriel-vasile/mimetype/mimetype.gif differ diff --git a/vendor/github.com/gabriel-vasile/mimetype/mimetype.go b/vendor/github.com/gabriel-vasile/mimetype/mimetype.go new file mode 100644 index 0000000000..1b5909b751 --- /dev/null +++ b/vendor/github.com/gabriel-vasile/mimetype/mimetype.go @@ -0,0 +1,124 @@ +// Package mimetype uses magic number signatures to detect the MIME type of a file. +// +// File formats are stored in a hierarchy with application/octet-stream at its root. +// For example, the hierarchy for HTML format is application/octet-stream -> +// text/plain -> text/html. +package mimetype + +import ( + "io" + "io/ioutil" + "mime" + "os" + "sync/atomic" +) + +// readLimit is the maximum number of bytes from the input used when detecting. +var readLimit uint32 = 3072 + +// Detect returns the MIME type found from the provided byte slice. +// +// The result is always a valid MIME type, with application/octet-stream +// returned when identification failed. +func Detect(in []byte) *MIME { + // Using atomic because readLimit can be written at the same time in other goroutine. + l := atomic.LoadUint32(&readLimit) + if l > 0 && len(in) > int(l) { + in = in[:l] + } + mu.RLock() + defer mu.RUnlock() + return root.match(in, l) +} + +// DetectReader returns the MIME type of the provided reader. +// +// The result is always a valid MIME type, with application/octet-stream +// returned when identification failed with or without an error. +// Any error returned is related to the reading from the input reader. +// +// DetectReader assumes the reader offset is at the start. If the input is an +// io.ReadSeeker you previously read from, it should be rewinded before detection: +// +// reader.Seek(0, io.SeekStart) +func DetectReader(r io.Reader) (*MIME, error) { + var in []byte + var err error + + // Using atomic because readLimit can be written at the same time in other goroutine. + l := atomic.LoadUint32(&readLimit) + if l == 0 { + in, err = ioutil.ReadAll(r) + if err != nil { + return errMIME, err + } + } else { + var n int + in = make([]byte, l) + // io.UnexpectedEOF means len(r) < len(in). It is not an error in this case, + // it just means the input file is smaller than the allocated bytes slice. + n, err = io.ReadFull(r, in) + if err != nil && err != io.EOF && err != io.ErrUnexpectedEOF { + return errMIME, err + } + in = in[:n] + } + + mu.RLock() + defer mu.RUnlock() + return root.match(in, l), nil +} + +// DetectFile returns the MIME type of the provided file. +// +// The result is always a valid MIME type, with application/octet-stream +// returned when identification failed with or without an error. +// Any error returned is related to the opening and reading from the input file. +func DetectFile(path string) (*MIME, error) { + f, err := os.Open(path) + if err != nil { + return errMIME, err + } + defer f.Close() + + return DetectReader(f) +} + +// EqualsAny reports whether s MIME type is equal to any MIME type in mimes. +// MIME type equality test is done on the "type/subtype" section, ignores +// any optional MIME parameters, ignores any leading and trailing whitespace, +// and is case insensitive. +func EqualsAny(s string, mimes ...string) bool { + s, _, _ = mime.ParseMediaType(s) + for _, m := range mimes { + m, _, _ = mime.ParseMediaType(m) + if s == m { + return true + } + } + + return false +} + +// SetLimit sets the maximum number of bytes read from input when detecting the MIME type. +// Increasing the limit provides better detection for file formats which store +// their magical numbers towards the end of the file: docx, pptx, xlsx, etc. +// A limit of 0 means the whole input file will be used. +func SetLimit(limit uint32) { + // Using atomic because readLimit can be read at the same time in other goroutine. + atomic.StoreUint32(&readLimit, limit) +} + +// Extend adds detection for other file formats. +// It is equivalent to calling Extend() on the root mime type "application/octet-stream". +func Extend(detector func(raw []byte, limit uint32) bool, mime, extension string, aliases ...string) { + root.Extend(detector, mime, extension, aliases...) +} + +// Lookup finds a MIME object by its string representation. +// The representation can be the main mime type, or any of its aliases. +func Lookup(mime string) *MIME { + mu.RLock() + defer mu.RUnlock() + return root.lookup(mime) +} diff --git a/vendor/github.com/gabriel-vasile/mimetype/supported_mimes.md b/vendor/github.com/gabriel-vasile/mimetype/supported_mimes.md new file mode 100644 index 0000000000..5ec6f6b650 --- /dev/null +++ b/vendor/github.com/gabriel-vasile/mimetype/supported_mimes.md @@ -0,0 +1,178 @@ +## 173 Supported MIME types +This file is automatically generated when running tests. Do not edit manually. + +Extension | MIME type | Aliases +--------- | --------- | ------- +**n/a** | application/octet-stream | - +**.xpm** | image/x-xpixmap | - +**.7z** | application/x-7z-compressed | - +**.zip** | application/zip | application/x-zip, application/x-zip-compressed +**.xlsx** | application/vnd.openxmlformats-officedocument.spreadsheetml.sheet | - +**.docx** | application/vnd.openxmlformats-officedocument.wordprocessingml.document | - +**.pptx** | application/vnd.openxmlformats-officedocument.presentationml.presentation | - +**.epub** | application/epub+zip | - +**.jar** | application/jar | - +**.odt** | application/vnd.oasis.opendocument.text | application/x-vnd.oasis.opendocument.text +**.ott** | application/vnd.oasis.opendocument.text-template | application/x-vnd.oasis.opendocument.text-template +**.ods** | application/vnd.oasis.opendocument.spreadsheet | application/x-vnd.oasis.opendocument.spreadsheet +**.ots** | application/vnd.oasis.opendocument.spreadsheet-template | application/x-vnd.oasis.opendocument.spreadsheet-template +**.odp** | application/vnd.oasis.opendocument.presentation | application/x-vnd.oasis.opendocument.presentation +**.otp** | application/vnd.oasis.opendocument.presentation-template | application/x-vnd.oasis.opendocument.presentation-template +**.odg** | application/vnd.oasis.opendocument.graphics | application/x-vnd.oasis.opendocument.graphics +**.otg** | application/vnd.oasis.opendocument.graphics-template | application/x-vnd.oasis.opendocument.graphics-template +**.odf** | application/vnd.oasis.opendocument.formula | application/x-vnd.oasis.opendocument.formula +**.odc** | application/vnd.oasis.opendocument.chart | application/x-vnd.oasis.opendocument.chart +**.sxc** | application/vnd.sun.xml.calc | - +**.pdf** | application/pdf | application/x-pdf +**.fdf** | application/vnd.fdf | - +**n/a** | application/x-ole-storage | - +**.msi** | application/x-ms-installer | application/x-windows-installer, application/x-msi +**.aaf** | application/octet-stream | - +**.msg** | application/vnd.ms-outlook | - +**.xls** | application/vnd.ms-excel | application/msexcel +**.pub** | application/vnd.ms-publisher | - +**.ppt** | application/vnd.ms-powerpoint | application/mspowerpoint +**.doc** | application/msword | application/vnd.ms-word +**.ps** | application/postscript | - +**.psd** | image/vnd.adobe.photoshop | image/x-psd, application/photoshop +**.p7s** | application/pkcs7-signature | - +**.ogg** | application/ogg | application/x-ogg +**.oga** | audio/ogg | - +**.ogv** | video/ogg | - +**.png** | image/png | - +**.png** | image/vnd.mozilla.apng | - +**.jpg** | image/jpeg | - +**.jxl** | image/jxl | - +**.jp2** | image/jp2 | - +**.jpf** | image/jpx | - +**.jpm** | image/jpm | video/jpm +**.jxs** | image/jxs | - +**.gif** | image/gif | - +**.webp** | image/webp | - +**.exe** | application/vnd.microsoft.portable-executable | - +**n/a** | application/x-elf | - +**n/a** | application/x-object | - +**n/a** | application/x-executable | - +**.so** | application/x-sharedlib | - +**n/a** | application/x-coredump | - +**.a** | application/x-archive | application/x-unix-archive +**.deb** | application/vnd.debian.binary-package | - +**.tar** | application/x-tar | - +**.xar** | application/x-xar | - +**.bz2** | application/x-bzip2 | - +**.fits** | application/fits | - +**.tiff** | image/tiff | - +**.bmp** | image/bmp | image/x-bmp, image/x-ms-bmp +**.ico** | image/x-icon | - +**.mp3** | audio/mpeg | audio/x-mpeg, audio/mp3 +**.flac** | audio/flac | - +**.midi** | audio/midi | audio/mid, audio/sp-midi, audio/x-mid, audio/x-midi +**.ape** | audio/ape | - +**.mpc** | audio/musepack | - +**.amr** | audio/amr | audio/amr-nb +**.wav** | audio/wav | audio/x-wav, audio/vnd.wave, audio/wave +**.aiff** | audio/aiff | audio/x-aiff +**.au** | audio/basic | - +**.mpeg** | video/mpeg | - +**.mov** | video/quicktime | - +**.mqv** | video/quicktime | - +**.mp4** | video/mp4 | - +**.webm** | video/webm | audio/webm +**.3gp** | video/3gpp | video/3gp, audio/3gpp +**.3g2** | video/3gpp2 | video/3g2, audio/3gpp2 +**.avi** | video/x-msvideo | video/avi, video/msvideo +**.flv** | video/x-flv | - +**.mkv** | video/x-matroska | - +**.asf** | video/x-ms-asf | video/asf, video/x-ms-wmv +**.aac** | audio/aac | - +**.voc** | audio/x-unknown | - +**.mp4** | audio/mp4 | audio/x-m4a, audio/x-mp4a +**.m4a** | audio/x-m4a | - +**.m3u** | application/vnd.apple.mpegurl | audio/mpegurl +**.m4v** | video/x-m4v | - +**.rmvb** | application/vnd.rn-realmedia-vbr | - +**.gz** | application/gzip | application/x-gzip, application/x-gunzip, application/gzipped, application/gzip-compressed, application/x-gzip-compressed, gzip/document +**.class** | application/x-java-applet | - +**.swf** | application/x-shockwave-flash | - +**.crx** | application/x-chrome-extension | - +**.ttf** | font/ttf | font/sfnt, application/x-font-ttf, application/font-sfnt +**.woff** | font/woff | - +**.woff2** | font/woff2 | - +**.otf** | font/otf | - +**.ttc** | font/collection | - +**.eot** | application/vnd.ms-fontobject | - +**.wasm** | application/wasm | - +**.shx** | application/vnd.shx | - +**.shp** | application/vnd.shp | - +**.dbf** | application/x-dbf | - +**.dcm** | application/dicom | - +**.rar** | application/x-rar-compressed | application/x-rar +**.djvu** | image/vnd.djvu | - +**.mobi** | application/x-mobipocket-ebook | - +**.lit** | application/x-ms-reader | - +**.bpg** | image/bpg | - +**.sqlite** | application/vnd.sqlite3 | application/x-sqlite3 +**.dwg** | image/vnd.dwg | image/x-dwg, application/acad, application/x-acad, application/autocad_dwg, application/dwg, application/x-dwg, application/x-autocad, drawing/dwg +**.nes** | application/vnd.nintendo.snes.rom | - +**.lnk** | application/x-ms-shortcut | - +**.macho** | application/x-mach-binary | - +**.qcp** | audio/qcelp | - +**.icns** | image/x-icns | - +**.heic** | image/heic | - +**.heic** | image/heic-sequence | - +**.heif** | image/heif | - +**.heif** | image/heif-sequence | - +**.hdr** | image/vnd.radiance | - +**.mrc** | application/marc | - +**.mdb** | application/x-msaccess | - +**.accdb** | application/x-msaccess | - +**.zst** | application/zstd | - +**.cab** | application/vnd.ms-cab-compressed | - +**.rpm** | application/x-rpm | - +**.xz** | application/x-xz | - +**.lz** | application/lzip | application/x-lzip +**.torrent** | application/x-bittorrent | - +**.cpio** | application/x-cpio | - +**n/a** | application/tzif | - +**.xcf** | image/x-xcf | - +**.pat** | image/x-gimp-pat | - +**.gbr** | image/x-gimp-gbr | - +**.glb** | model/gltf-binary | - +**.avif** | image/avif | - +**.cab** | application/x-installshield | - +**.jxr** | image/jxr | image/vnd.ms-photo +**.txt** | text/plain | - +**.html** | text/html | - +**.svg** | image/svg+xml | - +**.xml** | text/xml | - +**.rss** | application/rss+xml | text/rss +**.atom** | application/atom+xml | - +**.x3d** | model/x3d+xml | - +**.kml** | application/vnd.google-earth.kml+xml | - +**.xlf** | application/x-xliff+xml | - +**.dae** | model/vnd.collada+xml | - +**.gml** | application/gml+xml | - +**.gpx** | application/gpx+xml | - +**.tcx** | application/vnd.garmin.tcx+xml | - +**.amf** | application/x-amf | - +**.3mf** | application/vnd.ms-package.3dmanufacturing-3dmodel+xml | - +**.xfdf** | application/vnd.adobe.xfdf | - +**.owl** | application/owl+xml | - +**.php** | text/x-php | - +**.js** | application/javascript | application/x-javascript, text/javascript +**.lua** | text/x-lua | - +**.pl** | text/x-perl | - +**.py** | text/x-python | text/x-script.python, application/x-python +**.json** | application/json | - +**.geojson** | application/geo+json | - +**.har** | application/json | - +**.ndjson** | application/x-ndjson | - +**.rtf** | text/rtf | - +**.srt** | application/x-subrip | application/x-srt, text/x-srt +**.tcl** | text/x-tcl | application/x-tcl +**.csv** | text/csv | - +**.tsv** | text/tab-separated-values | - +**.vcf** | text/vcard | - +**.ics** | text/calendar | - +**.warc** | application/warc | - +**.vtt** | text/vtt | - diff --git a/vendor/github.com/gabriel-vasile/mimetype/tree.go b/vendor/github.com/gabriel-vasile/mimetype/tree.go new file mode 100644 index 0000000000..253bd00649 --- /dev/null +++ b/vendor/github.com/gabriel-vasile/mimetype/tree.go @@ -0,0 +1,260 @@ +package mimetype + +import ( + "sync" + + "github.com/gabriel-vasile/mimetype/internal/magic" +) + +// mimetype stores the list of MIME types in a tree structure with +// "application/octet-stream" at the root of the hierarchy. The hierarchy +// approach minimizes the number of checks that need to be done on the input +// and allows for more precise results once the base type of file has been +// identified. +// +// root is a detector which passes for any slice of bytes. +// When a detector passes the check, the children detectors +// are tried in order to find a more accurate MIME type. +var root = newMIME("application/octet-stream", "", + func([]byte, uint32) bool { return true }, + xpm, sevenZ, zip, pdf, fdf, ole, ps, psd, p7s, ogg, png, jpg, jxl, jp2, jpx, + jpm, jxs, gif, webp, exe, elf, ar, tar, xar, bz2, fits, tiff, bmp, ico, mp3, flac, + midi, ape, musePack, amr, wav, aiff, au, mpeg, quickTime, mqv, mp4, webM, + threeGP, threeG2, avi, flv, mkv, asf, aac, voc, aMp4, m4a, m3u, m4v, rmvb, + gzip, class, swf, crx, ttf, woff, woff2, otf, ttc, eot, wasm, shx, dbf, dcm, rar, + djvu, mobi, lit, bpg, sqlite3, dwg, nes, lnk, macho, qcp, icns, heic, + heicSeq, heif, heifSeq, hdr, mrc, mdb, accdb, zstd, cab, rpm, xz, lzip, + torrent, cpio, tzif, xcf, pat, gbr, glb, avif, cabIS, jxr, + // Keep text last because it is the slowest check + text, +) + +// errMIME is returned from Detect functions when err is not nil. +// Detect could return root for erroneous cases, but it needs to lock mu in order to do so. +// errMIME is same as root but it does not require locking. +var errMIME = newMIME("application/octet-stream", "", func([]byte, uint32) bool { return false }) + +// mu guards access to the root MIME tree. Access to root must be synchronized with this lock. +var mu = &sync.RWMutex{} + +// The list of nodes appended to the root node. +var ( + xz = newMIME("application/x-xz", ".xz", magic.Xz) + gzip = newMIME("application/gzip", ".gz", magic.Gzip).alias( + "application/x-gzip", "application/x-gunzip", "application/gzipped", + "application/gzip-compressed", "application/x-gzip-compressed", + "gzip/document") + sevenZ = newMIME("application/x-7z-compressed", ".7z", magic.SevenZ) + zip = newMIME("application/zip", ".zip", magic.Zip, xlsx, docx, pptx, epub, jar, odt, ods, odp, odg, odf, odc, sxc). + alias("application/x-zip", "application/x-zip-compressed") + tar = newMIME("application/x-tar", ".tar", magic.Tar) + xar = newMIME("application/x-xar", ".xar", magic.Xar) + bz2 = newMIME("application/x-bzip2", ".bz2", magic.Bz2) + pdf = newMIME("application/pdf", ".pdf", magic.Pdf). + alias("application/x-pdf") + fdf = newMIME("application/vnd.fdf", ".fdf", magic.Fdf) + xlsx = newMIME("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", ".xlsx", magic.Xlsx) + docx = newMIME("application/vnd.openxmlformats-officedocument.wordprocessingml.document", ".docx", magic.Docx) + pptx = newMIME("application/vnd.openxmlformats-officedocument.presentationml.presentation", ".pptx", magic.Pptx) + epub = newMIME("application/epub+zip", ".epub", magic.Epub) + jar = newMIME("application/jar", ".jar", magic.Jar) + ole = newMIME("application/x-ole-storage", "", magic.Ole, msi, aaf, msg, xls, pub, ppt, doc) + msi = newMIME("application/x-ms-installer", ".msi", magic.Msi). + alias("application/x-windows-installer", "application/x-msi") + aaf = newMIME("application/octet-stream", ".aaf", magic.Aaf) + doc = newMIME("application/msword", ".doc", magic.Doc). + alias("application/vnd.ms-word") + ppt = newMIME("application/vnd.ms-powerpoint", ".ppt", magic.Ppt). + alias("application/mspowerpoint") + pub = newMIME("application/vnd.ms-publisher", ".pub", magic.Pub) + xls = newMIME("application/vnd.ms-excel", ".xls", magic.Xls). + alias("application/msexcel") + msg = newMIME("application/vnd.ms-outlook", ".msg", magic.Msg) + ps = newMIME("application/postscript", ".ps", magic.Ps) + fits = newMIME("application/fits", ".fits", magic.Fits) + ogg = newMIME("application/ogg", ".ogg", magic.Ogg, oggAudio, oggVideo). + alias("application/x-ogg") + oggAudio = newMIME("audio/ogg", ".oga", magic.OggAudio) + oggVideo = newMIME("video/ogg", ".ogv", magic.OggVideo) + text = newMIME("text/plain", ".txt", magic.Text, html, svg, xml, php, js, lua, perl, python, json, ndJSON, rtf, srt, tcl, csv, tsv, vCard, iCalendar, warc, vtt) + xml = newMIME("text/xml", ".xml", magic.XML, rss, atom, x3d, kml, xliff, collada, gml, gpx, tcx, amf, threemf, xfdf, owl2) + json = newMIME("application/json", ".json", magic.JSON, geoJSON, har) + har = newMIME("application/json", ".har", magic.HAR) + csv = newMIME("text/csv", ".csv", magic.Csv) + tsv = newMIME("text/tab-separated-values", ".tsv", magic.Tsv) + geoJSON = newMIME("application/geo+json", ".geojson", magic.GeoJSON) + ndJSON = newMIME("application/x-ndjson", ".ndjson", magic.NdJSON) + html = newMIME("text/html", ".html", magic.HTML) + php = newMIME("text/x-php", ".php", magic.Php) + rtf = newMIME("text/rtf", ".rtf", magic.Rtf) + js = newMIME("application/javascript", ".js", magic.Js). + alias("application/x-javascript", "text/javascript") + srt = newMIME("application/x-subrip", ".srt", magic.Srt). + alias("application/x-srt", "text/x-srt") + vtt = newMIME("text/vtt", ".vtt", magic.Vtt) + lua = newMIME("text/x-lua", ".lua", magic.Lua) + perl = newMIME("text/x-perl", ".pl", magic.Perl) + python = newMIME("text/x-python", ".py", magic.Python). + alias("text/x-script.python", "application/x-python") + tcl = newMIME("text/x-tcl", ".tcl", magic.Tcl). + alias("application/x-tcl") + vCard = newMIME("text/vcard", ".vcf", magic.VCard) + iCalendar = newMIME("text/calendar", ".ics", magic.ICalendar) + svg = newMIME("image/svg+xml", ".svg", magic.Svg) + rss = newMIME("application/rss+xml", ".rss", magic.Rss). + alias("text/rss") + owl2 = newMIME("application/owl+xml", ".owl", magic.Owl2) + atom = newMIME("application/atom+xml", ".atom", magic.Atom) + x3d = newMIME("model/x3d+xml", ".x3d", magic.X3d) + kml = newMIME("application/vnd.google-earth.kml+xml", ".kml", magic.Kml) + xliff = newMIME("application/x-xliff+xml", ".xlf", magic.Xliff) + collada = newMIME("model/vnd.collada+xml", ".dae", magic.Collada) + gml = newMIME("application/gml+xml", ".gml", magic.Gml) + gpx = newMIME("application/gpx+xml", ".gpx", magic.Gpx) + tcx = newMIME("application/vnd.garmin.tcx+xml", ".tcx", magic.Tcx) + amf = newMIME("application/x-amf", ".amf", magic.Amf) + threemf = newMIME("application/vnd.ms-package.3dmanufacturing-3dmodel+xml", ".3mf", magic.Threemf) + png = newMIME("image/png", ".png", magic.Png, apng) + apng = newMIME("image/vnd.mozilla.apng", ".png", magic.Apng) + jpg = newMIME("image/jpeg", ".jpg", magic.Jpg) + jxl = newMIME("image/jxl", ".jxl", magic.Jxl) + jp2 = newMIME("image/jp2", ".jp2", magic.Jp2) + jpx = newMIME("image/jpx", ".jpf", magic.Jpx) + jpm = newMIME("image/jpm", ".jpm", magic.Jpm). + alias("video/jpm") + jxs = newMIME("image/jxs", ".jxs", magic.Jxs) + xpm = newMIME("image/x-xpixmap", ".xpm", magic.Xpm) + bpg = newMIME("image/bpg", ".bpg", magic.Bpg) + gif = newMIME("image/gif", ".gif", magic.Gif) + webp = newMIME("image/webp", ".webp", magic.Webp) + tiff = newMIME("image/tiff", ".tiff", magic.Tiff) + bmp = newMIME("image/bmp", ".bmp", magic.Bmp). + alias("image/x-bmp", "image/x-ms-bmp") + ico = newMIME("image/x-icon", ".ico", magic.Ico) + icns = newMIME("image/x-icns", ".icns", magic.Icns) + psd = newMIME("image/vnd.adobe.photoshop", ".psd", magic.Psd). + alias("image/x-psd", "application/photoshop") + heic = newMIME("image/heic", ".heic", magic.Heic) + heicSeq = newMIME("image/heic-sequence", ".heic", magic.HeicSequence) + heif = newMIME("image/heif", ".heif", magic.Heif) + heifSeq = newMIME("image/heif-sequence", ".heif", magic.HeifSequence) + hdr = newMIME("image/vnd.radiance", ".hdr", magic.Hdr) + avif = newMIME("image/avif", ".avif", magic.AVIF) + mp3 = newMIME("audio/mpeg", ".mp3", magic.Mp3). + alias("audio/x-mpeg", "audio/mp3") + flac = newMIME("audio/flac", ".flac", magic.Flac) + midi = newMIME("audio/midi", ".midi", magic.Midi). + alias("audio/mid", "audio/sp-midi", "audio/x-mid", "audio/x-midi") + ape = newMIME("audio/ape", ".ape", magic.Ape) + musePack = newMIME("audio/musepack", ".mpc", magic.MusePack) + wav = newMIME("audio/wav", ".wav", magic.Wav). + alias("audio/x-wav", "audio/vnd.wave", "audio/wave") + aiff = newMIME("audio/aiff", ".aiff", magic.Aiff).alias("audio/x-aiff") + au = newMIME("audio/basic", ".au", magic.Au) + amr = newMIME("audio/amr", ".amr", magic.Amr). + alias("audio/amr-nb") + aac = newMIME("audio/aac", ".aac", magic.AAC) + voc = newMIME("audio/x-unknown", ".voc", magic.Voc) + aMp4 = newMIME("audio/mp4", ".mp4", magic.AMp4). + alias("audio/x-m4a", "audio/x-mp4a") + m4a = newMIME("audio/x-m4a", ".m4a", magic.M4a) + m3u = newMIME("application/vnd.apple.mpegurl", ".m3u", magic.M3u). + alias("audio/mpegurl") + m4v = newMIME("video/x-m4v", ".m4v", magic.M4v) + mp4 = newMIME("video/mp4", ".mp4", magic.Mp4) + webM = newMIME("video/webm", ".webm", magic.WebM). + alias("audio/webm") + mpeg = newMIME("video/mpeg", ".mpeg", magic.Mpeg) + quickTime = newMIME("video/quicktime", ".mov", magic.QuickTime) + mqv = newMIME("video/quicktime", ".mqv", magic.Mqv) + threeGP = newMIME("video/3gpp", ".3gp", magic.ThreeGP). + alias("video/3gp", "audio/3gpp") + threeG2 = newMIME("video/3gpp2", ".3g2", magic.ThreeG2). + alias("video/3g2", "audio/3gpp2") + avi = newMIME("video/x-msvideo", ".avi", magic.Avi). + alias("video/avi", "video/msvideo") + flv = newMIME("video/x-flv", ".flv", magic.Flv) + mkv = newMIME("video/x-matroska", ".mkv", magic.Mkv) + asf = newMIME("video/x-ms-asf", ".asf", magic.Asf). + alias("video/asf", "video/x-ms-wmv") + rmvb = newMIME("application/vnd.rn-realmedia-vbr", ".rmvb", magic.Rmvb) + class = newMIME("application/x-java-applet", ".class", magic.Class) + swf = newMIME("application/x-shockwave-flash", ".swf", magic.SWF) + crx = newMIME("application/x-chrome-extension", ".crx", magic.CRX) + ttf = newMIME("font/ttf", ".ttf", magic.Ttf). + alias("font/sfnt", "application/x-font-ttf", "application/font-sfnt") + woff = newMIME("font/woff", ".woff", magic.Woff) + woff2 = newMIME("font/woff2", ".woff2", magic.Woff2) + otf = newMIME("font/otf", ".otf", magic.Otf) + ttc = newMIME("font/collection", ".ttc", magic.Ttc) + eot = newMIME("application/vnd.ms-fontobject", ".eot", magic.Eot) + wasm = newMIME("application/wasm", ".wasm", magic.Wasm) + shp = newMIME("application/vnd.shp", ".shp", magic.Shp) + shx = newMIME("application/vnd.shx", ".shx", magic.Shx, shp) + dbf = newMIME("application/x-dbf", ".dbf", magic.Dbf) + exe = newMIME("application/vnd.microsoft.portable-executable", ".exe", magic.Exe) + elf = newMIME("application/x-elf", "", magic.Elf, elfObj, elfExe, elfLib, elfDump) + elfObj = newMIME("application/x-object", "", magic.ElfObj) + elfExe = newMIME("application/x-executable", "", magic.ElfExe) + elfLib = newMIME("application/x-sharedlib", ".so", magic.ElfLib) + elfDump = newMIME("application/x-coredump", "", magic.ElfDump) + ar = newMIME("application/x-archive", ".a", magic.Ar, deb). + alias("application/x-unix-archive") + deb = newMIME("application/vnd.debian.binary-package", ".deb", magic.Deb) + rpm = newMIME("application/x-rpm", ".rpm", magic.RPM) + dcm = newMIME("application/dicom", ".dcm", magic.Dcm) + odt = newMIME("application/vnd.oasis.opendocument.text", ".odt", magic.Odt, ott). + alias("application/x-vnd.oasis.opendocument.text") + ott = newMIME("application/vnd.oasis.opendocument.text-template", ".ott", magic.Ott). + alias("application/x-vnd.oasis.opendocument.text-template") + ods = newMIME("application/vnd.oasis.opendocument.spreadsheet", ".ods", magic.Ods, ots). + alias("application/x-vnd.oasis.opendocument.spreadsheet") + ots = newMIME("application/vnd.oasis.opendocument.spreadsheet-template", ".ots", magic.Ots). + alias("application/x-vnd.oasis.opendocument.spreadsheet-template") + odp = newMIME("application/vnd.oasis.opendocument.presentation", ".odp", magic.Odp, otp). + alias("application/x-vnd.oasis.opendocument.presentation") + otp = newMIME("application/vnd.oasis.opendocument.presentation-template", ".otp", magic.Otp). + alias("application/x-vnd.oasis.opendocument.presentation-template") + odg = newMIME("application/vnd.oasis.opendocument.graphics", ".odg", magic.Odg, otg). + alias("application/x-vnd.oasis.opendocument.graphics") + otg = newMIME("application/vnd.oasis.opendocument.graphics-template", ".otg", magic.Otg). + alias("application/x-vnd.oasis.opendocument.graphics-template") + odf = newMIME("application/vnd.oasis.opendocument.formula", ".odf", magic.Odf). + alias("application/x-vnd.oasis.opendocument.formula") + odc = newMIME("application/vnd.oasis.opendocument.chart", ".odc", magic.Odc). + alias("application/x-vnd.oasis.opendocument.chart") + sxc = newMIME("application/vnd.sun.xml.calc", ".sxc", magic.Sxc) + rar = newMIME("application/x-rar-compressed", ".rar", magic.RAR). + alias("application/x-rar") + djvu = newMIME("image/vnd.djvu", ".djvu", magic.DjVu) + mobi = newMIME("application/x-mobipocket-ebook", ".mobi", magic.Mobi) + lit = newMIME("application/x-ms-reader", ".lit", magic.Lit) + sqlite3 = newMIME("application/vnd.sqlite3", ".sqlite", magic.Sqlite). + alias("application/x-sqlite3") + dwg = newMIME("image/vnd.dwg", ".dwg", magic.Dwg). + alias("image/x-dwg", "application/acad", "application/x-acad", + "application/autocad_dwg", "application/dwg", "application/x-dwg", + "application/x-autocad", "drawing/dwg") + warc = newMIME("application/warc", ".warc", magic.Warc) + nes = newMIME("application/vnd.nintendo.snes.rom", ".nes", magic.Nes) + lnk = newMIME("application/x-ms-shortcut", ".lnk", magic.Lnk) + macho = newMIME("application/x-mach-binary", ".macho", magic.MachO) + qcp = newMIME("audio/qcelp", ".qcp", magic.Qcp) + mrc = newMIME("application/marc", ".mrc", magic.Marc) + mdb = newMIME("application/x-msaccess", ".mdb", magic.MsAccessMdb) + accdb = newMIME("application/x-msaccess", ".accdb", magic.MsAccessAce) + zstd = newMIME("application/zstd", ".zst", magic.Zstd) + cab = newMIME("application/vnd.ms-cab-compressed", ".cab", magic.Cab) + cabIS = newMIME("application/x-installshield", ".cab", magic.InstallShieldCab) + lzip = newMIME("application/lzip", ".lz", magic.Lzip).alias("application/x-lzip") + torrent = newMIME("application/x-bittorrent", ".torrent", magic.Torrent) + cpio = newMIME("application/x-cpio", ".cpio", magic.Cpio) + tzif = newMIME("application/tzif", "", magic.TzIf) + p7s = newMIME("application/pkcs7-signature", ".p7s", magic.P7s) + xcf = newMIME("image/x-xcf", ".xcf", magic.Xcf) + pat = newMIME("image/x-gimp-pat", ".pat", magic.Pat) + gbr = newMIME("image/x-gimp-gbr", ".gbr", magic.Gbr) + xfdf = newMIME("application/vnd.adobe.xfdf", ".xfdf", magic.Xfdf) + glb = newMIME("model/gltf-binary", ".glb", magic.Glb) + jxr = newMIME("image/jxr", ".jxr", magic.Jxr).alias("image/vnd.ms-photo") +) diff --git a/vendor/github.com/go-openapi/errors/.golangci.yml b/vendor/github.com/go-openapi/errors/.golangci.yml index 4e1fc0c7d4..cf88ead324 100644 --- a/vendor/github.com/go-openapi/errors/.golangci.yml +++ b/vendor/github.com/go-openapi/errors/.golangci.yml @@ -4,45 +4,59 @@ linters-settings: golint: min-confidence: 0 gocyclo: - min-complexity: 30 + min-complexity: 45 maligned: suggest-new: true dupl: - threshold: 100 + threshold: 200 goconst: min-len: 2 - min-occurrences: 4 + min-occurrences: 3 + linters: enable-all: true disable: + - errname # this repo doesn't follow the convention advised by this linter - maligned + - unparam - lll + - gochecknoinits - gochecknoglobals + - funlen - godox - gocognit - whitespace - wsl - - funlen - - gochecknoglobals - - gochecknoinits - - scopelint - wrapcheck - - exhaustivestruct - - exhaustive - - nlreturn - testpackage - - gci - - gofumpt - - goerr113 + - nlreturn - gomnd - - tparallel + - exhaustivestruct + - goerr113 + - errorlint - nestif - godot - - errorlint + - gofumpt - paralleltest - tparallel - - cyclop - - errname - - varnamelen + - thelper + - ifshort - exhaustruct - - maintidx + - varnamelen + - gci + - depguard + - errchkjson + - inamedparam + - nonamedreturns + - musttag + - ireturn + - forcetypeassert + - cyclop + # deprecated linters + - deadcode + - interfacer + - scopelint + - varcheck + - structcheck + - golint + - nosnakecase diff --git a/vendor/github.com/go-openapi/errors/README.md b/vendor/github.com/go-openapi/errors/README.md index 4aac049e60..6d57ea55c7 100644 --- a/vendor/github.com/go-openapi/errors/README.md +++ b/vendor/github.com/go-openapi/errors/README.md @@ -1,11 +1,8 @@ -# OpenAPI errors +# OpenAPI errors [![Build Status](https://github.com/go-openapi/errors/actions/workflows/go-test.yml/badge.svg)](https://github.com/go-openapi/errors/actions?query=workflow%3A"go+test") [![codecov](https://codecov.io/gh/go-openapi/errors/branch/master/graph/badge.svg)](https://codecov.io/gh/go-openapi/errors) -[![Build Status](https://travis-ci.org/go-openapi/errors.svg?branch=master)](https://travis-ci.org/go-openapi/errors) -[![codecov](https://codecov.io/gh/go-openapi/errors/branch/master/graph/badge.svg)](https://codecov.io/gh/go-openapi/errors) [![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/errors/master/LICENSE) [![Go Reference](https://pkg.go.dev/badge/github.com/go-openapi/errors.svg)](https://pkg.go.dev/github.com/go-openapi/errors) -[![GolangCI](https://golangci.com/badges/github.com/go-openapi/errors.svg)](https://golangci.com) [![Go Report Card](https://goreportcard.com/badge/github.com/go-openapi/errors)](https://goreportcard.com/report/github.com/go-openapi/errors) Shared errors and error interface used throughout the various libraries found in the go-openapi toolkit. diff --git a/vendor/github.com/go-openapi/errors/api.go b/vendor/github.com/go-openapi/errors/api.go index 77f1f92c5e..5320cb9630 100644 --- a/vendor/github.com/go-openapi/errors/api.go +++ b/vendor/github.com/go-openapi/errors/api.go @@ -55,9 +55,15 @@ func (a apiError) MarshalJSON() ([]byte, error) { // New creates a new API error with a code and a message func New(code int32, message string, args ...interface{}) Error { if len(args) > 0 { - return &apiError{code, fmt.Sprintf(message, args...)} + return &apiError{ + code: code, + message: fmt.Sprintf(message, args...), + } + } + return &apiError{ + code: code, + message: message, } - return &apiError{code, message} } // NotFound creates a new not found error @@ -112,7 +118,7 @@ func flattenComposite(errs *CompositeError) *CompositeError { for _, er := range errs.Errors { switch e := er.(type) { case *CompositeError: - if len(e.Errors) > 0 { + if e != nil && len(e.Errors) > 0 { flat := flattenComposite(e) if len(flat.Errors) > 0 { res = append(res, flat.Errors...) @@ -130,10 +136,14 @@ func flattenComposite(errs *CompositeError) *CompositeError { // MethodNotAllowed creates a new method not allowed error func MethodNotAllowed(requested string, allow []string) Error { msg := fmt.Sprintf("method %s is not allowed, but [%s] are", requested, strings.Join(allow, ",")) - return &MethodNotAllowedError{code: http.StatusMethodNotAllowed, Allowed: allow, message: msg} + return &MethodNotAllowedError{ + code: http.StatusMethodNotAllowed, + Allowed: allow, + message: msg, + } } -// ServeError the error handler interface implementation +// ServeError implements the http error handler interface func ServeError(rw http.ResponseWriter, r *http.Request, err error) { rw.Header().Set("Content-Type", "application/json") switch e := err.(type) { diff --git a/vendor/github.com/go-openapi/errors/schema.go b/vendor/github.com/go-openapi/errors/schema.go index da5f6c78cb..cf7ac2ed4d 100644 --- a/vendor/github.com/go-openapi/errors/schema.go +++ b/vendor/github.com/go-openapi/errors/schema.go @@ -120,6 +120,10 @@ func (c *CompositeError) Error() string { return c.message } +func (c *CompositeError) Unwrap() []error { + return c.Errors +} + // MarshalJSON implements the JSON encoding interface func (c CompositeError) MarshalJSON() ([]byte, error) { return json.Marshal(map[string]interface{}{ @@ -133,7 +137,7 @@ func (c CompositeError) MarshalJSON() ([]byte, error) { func CompositeValidationError(errors ...error) *CompositeError { return &CompositeError{ code: CompositeErrorCode, - Errors: append([]error{}, errors...), + Errors: append(make([]error, 0, len(errors)), errors...), message: "validation failure list", } } diff --git a/vendor/github.com/go-openapi/strfmt/.golangci.yml b/vendor/github.com/go-openapi/strfmt/.golangci.yml index be4899cb12..22f8d21cca 100644 --- a/vendor/github.com/go-openapi/strfmt/.golangci.yml +++ b/vendor/github.com/go-openapi/strfmt/.golangci.yml @@ -4,56 +4,58 @@ linters-settings: golint: min-confidence: 0 gocyclo: - min-complexity: 31 + min-complexity: 45 maligned: suggest-new: true dupl: - threshold: 100 + threshold: 200 goconst: min-len: 2 - min-occurrences: 4 + min-occurrences: 3 linters: - enable: - - revive - - goimports - - gosec + enable-all: true + disable: + - maligned - unparam - - unconvert - - predeclared - - prealloc - - misspell - - # disable: - # - maligned - # - lll - # - gochecknoinits - # - gochecknoglobals - # - godox - # - gocognit - # - whitespace - # - wsl - # - funlen - # - wrapcheck - # - testpackage - # - nlreturn - # - gofumpt - # - goerr113 - # - gci - # - gomnd - # - godot - # - exhaustivestruct - # - paralleltest - # - varnamelen - # - ireturn - # - exhaustruct - # #- thelper - -issues: - exclude-rules: - - path: bson.go - text: "should be .*ObjectID" - linters: - - golint - - stylecheck - + - lll + - gochecknoinits + - gochecknoglobals + - funlen + - godox + - gocognit + - whitespace + - wsl + - wrapcheck + - testpackage + - nlreturn + - gomnd + - exhaustivestruct + - goerr113 + - errorlint + - nestif + - godot + - gofumpt + - paralleltest + - tparallel + - thelper + - ifshort + - exhaustruct + - varnamelen + - gci + - depguard + - errchkjson + - inamedparam + - nonamedreturns + - musttag + - ireturn + - forcetypeassert + - cyclop + # deprecated linters + - deadcode + - interfacer + - scopelint + - varcheck + - structcheck + - golint + - nosnakecase diff --git a/vendor/github.com/go-openapi/strfmt/README.md b/vendor/github.com/go-openapi/strfmt/README.md index 0cf89d7766..f6b39c6c56 100644 --- a/vendor/github.com/go-openapi/strfmt/README.md +++ b/vendor/github.com/go-openapi/strfmt/README.md @@ -1,8 +1,7 @@ -# Strfmt [![Build Status](https://travis-ci.org/go-openapi/strfmt.svg?branch=master)](https://travis-ci.org/go-openapi/strfmt) [![codecov](https://codecov.io/gh/go-openapi/strfmt/branch/master/graph/badge.svg)](https://codecov.io/gh/go-openapi/strfmt) [![Slack Status](https://slackin.goswagger.io/badge.svg)](https://slackin.goswagger.io) - +# Strfmt [![Build Status](https://github.com/go-openapi/strfmt/actions/workflows/go-test.yml/badge.svg)](https://github.com/go-openapi/strfmt/actions?query=workflow%3A"go+test") [![codecov](https://codecov.io/gh/go-openapi/strfmt/branch/master/graph/badge.svg)](https://codecov.io/gh/go-openapi/strfmt) +[![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/strfmt/master/LICENSE) [![GoDoc](https://godoc.org/github.com/go-openapi/strfmt?status.svg)](http://godoc.org/github.com/go-openapi/strfmt) -[![GolangCI](https://golangci.com/badges/github.com/go-openapi/strfmt.svg)](https://golangci.com) [![Go Report Card](https://goreportcard.com/badge/github.com/go-openapi/strfmt)](https://goreportcard.com/report/github.com/go-openapi/strfmt) This package exposes a registry of data types to support string formats in the go-openapi toolkit. diff --git a/vendor/github.com/go-openapi/strfmt/bson.go b/vendor/github.com/go-openapi/strfmt/bson.go index 8740b15059..cfa9a526fe 100644 --- a/vendor/github.com/go-openapi/strfmt/bson.go +++ b/vendor/github.com/go-openapi/strfmt/bson.go @@ -39,10 +39,10 @@ func IsBSONObjectID(str string) bool { // ObjectId represents a BSON object ID (alias to go.mongodb.org/mongo-driver/bson/primitive.ObjectID) // // swagger:strfmt bsonobjectid -type ObjectId bsonprim.ObjectID //nolint:revive +type ObjectId bsonprim.ObjectID //nolint:revive,stylecheck // NewObjectId creates a ObjectId from a Hex String -func NewObjectId(hex string) ObjectId { //nolint:revive +func NewObjectId(hex string) ObjectId { //nolint:revive,stylecheck oid, err := bsonprim.ObjectIDFromHex(hex) if err != nil { panic(err) @@ -135,14 +135,14 @@ func (id *ObjectId) UnmarshalBSON(data []byte) error { // BSON document if the error is nil. func (id ObjectId) MarshalBSONValue() (bsontype.Type, []byte, error) { oid := bsonprim.ObjectID(id) - return bsontype.ObjectID, oid[:], nil + return bson.TypeObjectID, oid[:], nil } // UnmarshalBSONValue is an interface implemented by types that can unmarshal a // BSON value representation of themselves. The BSON bytes and type can be // assumed to be valid. UnmarshalBSONValue must copy the BSON value bytes if it // wishes to retain the data after returning. -func (id *ObjectId) UnmarshalBSONValue(tpe bsontype.Type, data []byte) error { +func (id *ObjectId) UnmarshalBSONValue(_ bsontype.Type, data []byte) error { var oid bsonprim.ObjectID copy(oid[:], data) *id = ObjectId(oid) diff --git a/vendor/github.com/go-openapi/strfmt/default.go b/vendor/github.com/go-openapi/strfmt/default.go index a89a4de3f3..2813714060 100644 --- a/vendor/github.com/go-openapi/strfmt/default.go +++ b/vendor/github.com/go-openapi/strfmt/default.go @@ -25,6 +25,7 @@ import ( "strings" "github.com/asaskevich/govalidator" + "github.com/google/uuid" "go.mongodb.org/mongo-driver/bson" ) @@ -57,24 +58,35 @@ const ( // - long top-level domain names (e.g. example.london) are permitted // - symbol unicode points are permitted (e.g. emoji) (not for top-level domain) HostnamePattern = `^([a-zA-Z0-9\p{S}\p{L}]((-?[a-zA-Z0-9\p{S}\p{L}]{0,62})?)|([a-zA-Z0-9\p{S}\p{L}](([a-zA-Z0-9-\p{S}\p{L}]{0,61}[a-zA-Z0-9\p{S}\p{L}])?)(\.)){1,}([a-zA-Z\p{L}]){2,63})$` + + // json null type + jsonNull = "null" +) + +const ( // UUIDPattern Regex for UUID that allows uppercase - UUIDPattern = `(?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{12}$` + // + // Deprecated: strfmt no longer uses regular expressions to validate UUIDs. + UUIDPattern = `(?i)(^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$)|(^[0-9a-f]{32}$)` + // UUID3Pattern Regex for UUID3 that allows uppercase - UUID3Pattern = `(?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?3[0-9a-f]{3}-?[0-9a-f]{4}-?[0-9a-f]{12}$` + // + // Deprecated: strfmt no longer uses regular expressions to validate UUIDs. + UUID3Pattern = `(?i)(^[0-9a-f]{8}-[0-9a-f]{4}-3[0-9a-f]{3}-[0-9a-f]{4}-[0-9a-f]{12}$)|(^[0-9a-f]{12}3[0-9a-f]{3}?[0-9a-f]{16}$)` + // UUID4Pattern Regex for UUID4 that allows uppercase - UUID4Pattern = `(?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?4[0-9a-f]{3}-?[89ab][0-9a-f]{3}-?[0-9a-f]{12}$` + // + // Deprecated: strfmt no longer uses regular expressions to validate UUIDs. + UUID4Pattern = `(?i)(^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$)|(^[0-9a-f]{12}4[0-9a-f]{3}[89ab][0-9a-f]{15}$)` + // UUID5Pattern Regex for UUID5 that allows uppercase - UUID5Pattern = `(?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?5[0-9a-f]{3}-?[89ab][0-9a-f]{3}-?[0-9a-f]{12}$` - // json null type - jsonNull = "null" + // + // Deprecated: strfmt no longer uses regular expressions to validate UUIDs. + UUID5Pattern = `(?i)(^[0-9a-f]{8}-[0-9a-f]{4}-5[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$)|(^[0-9a-f]{12}5[0-9a-f]{3}[89ab][0-9a-f]{15}$)` ) var ( rxHostname = regexp.MustCompile(HostnamePattern) - rxUUID = regexp.MustCompile(UUIDPattern) - rxUUID3 = regexp.MustCompile(UUID3Pattern) - rxUUID4 = regexp.MustCompile(UUID4Pattern) - rxUUID5 = regexp.MustCompile(UUID5Pattern) ) // IsHostname returns true when the string is a valid hostname @@ -99,24 +111,28 @@ func IsHostname(str string) bool { return valid } -// IsUUID returns true is the string matches a UUID, upper case is allowed +// IsUUID returns true is the string matches a UUID (in any version, including v6 and v7), upper case is allowed func IsUUID(str string) bool { - return rxUUID.MatchString(str) + _, err := uuid.Parse(str) + return err == nil } -// IsUUID3 returns true is the string matches a UUID, upper case is allowed +// IsUUID3 returns true is the string matches a UUID v3, upper case is allowed func IsUUID3(str string) bool { - return rxUUID3.MatchString(str) + id, err := uuid.Parse(str) + return err == nil && id.Version() == uuid.Version(3) } -// IsUUID4 returns true is the string matches a UUID, upper case is allowed +// IsUUID4 returns true is the string matches a UUID v4, upper case is allowed func IsUUID4(str string) bool { - return rxUUID4.MatchString(str) + id, err := uuid.Parse(str) + return err == nil && id.Version() == uuid.Version(4) } -// IsUUID5 returns true is the string matches a UUID, upper case is allowed +// IsUUID5 returns true is the string matches a UUID v5, upper case is allowed func IsUUID5(str string) bool { - return rxUUID5.MatchString(str) + id, err := uuid.Parse(str) + return err == nil && id.Version() == uuid.Version(5) } // IsEmail validates an email address. diff --git a/vendor/github.com/go-openapi/strfmt/format.go b/vendor/github.com/go-openapi/strfmt/format.go index ad3b3c355b..888e107c38 100644 --- a/vendor/github.com/go-openapi/strfmt/format.go +++ b/vendor/github.com/go-openapi/strfmt/format.go @@ -16,6 +16,7 @@ package strfmt import ( "encoding" + stderrors "errors" "fmt" "reflect" "strings" @@ -94,7 +95,7 @@ func NewSeededFormats(seeds []knownFormat, normalizer NameNormalizer) Registry { } // MapStructureHookFunc is a decode hook function for mapstructure -func (f *defaultFormats) MapStructureHookFunc() mapstructure.DecodeHookFunc { //nolint:gocyclo,cyclop +func (f *defaultFormats) MapStructureHookFunc() mapstructure.DecodeHookFunc { return func(from reflect.Type, to reflect.Type, obj interface{}) (interface{}, error) { if from.Kind() != reflect.String { return obj, nil @@ -117,7 +118,7 @@ func (f *defaultFormats) MapStructureHookFunc() mapstructure.DecodeHookFunc { // case "datetime": input := data if len(input) == 0 { - return nil, fmt.Errorf("empty string is an invalid datetime format") + return nil, stderrors.New("empty string is an invalid datetime format") } return ParseDateTime(input) case "duration": diff --git a/vendor/github.com/go-openapi/strfmt/time.go b/vendor/github.com/go-openapi/strfmt/time.go index 6f5a44bb7d..f08ba4da5d 100644 --- a/vendor/github.com/go-openapi/strfmt/time.go +++ b/vendor/github.com/go-openapi/strfmt/time.go @@ -76,6 +76,8 @@ const ( ISO8601TimeWithReducedPrecisionLocaltime = "2006-01-02T15:04" // ISO8601TimeUniversalSortableDateTimePattern represents a ISO8601 universal sortable date time pattern. ISO8601TimeUniversalSortableDateTimePattern = "2006-01-02 15:04:05" + // short form of ISO8601TimeUniversalSortableDateTimePattern + ISO8601TimeUniversalSortableDateTimePatternShortForm = "2006-01-02" // DateTimePattern pattern to match for the date-time format from http://tools.ietf.org/html/rfc3339#section-5.6 DateTimePattern = `^([0-9]{2}):([0-9]{2}):([0-9]{2})(.[0-9]+)?(z|([+-][0-9]{2}:[0-9]{2}))$` ) @@ -84,7 +86,7 @@ var ( rxDateTime = regexp.MustCompile(DateTimePattern) // DateTimeFormats is the collection of formats used by ParseDateTime() - DateTimeFormats = []string{RFC3339Micro, RFC3339MicroNoColon, RFC3339Millis, RFC3339MillisNoColon, time.RFC3339, time.RFC3339Nano, ISO8601LocalTime, ISO8601TimeWithReducedPrecision, ISO8601TimeWithReducedPrecisionLocaltime, ISO8601TimeUniversalSortableDateTimePattern} + DateTimeFormats = []string{RFC3339Micro, RFC3339MicroNoColon, RFC3339Millis, RFC3339MillisNoColon, time.RFC3339, time.RFC3339Nano, ISO8601LocalTime, ISO8601TimeWithReducedPrecision, ISO8601TimeWithReducedPrecisionLocaltime, ISO8601TimeUniversalSortableDateTimePattern, ISO8601TimeUniversalSortableDateTimePatternShortForm} // MarshalFormat sets the time resolution format used for marshaling time (set to milliseconds) MarshalFormat = RFC3339Millis @@ -133,13 +135,19 @@ func (t DateTime) String() string { } // IsZero returns whether the date time is a zero value -func (t DateTime) IsZero() bool { - return time.Time(t).IsZero() +func (t *DateTime) IsZero() bool { + if t == nil { + return true + } + return time.Time(*t).IsZero() } // IsUnixZerom returns whether the date time is equivalent to time.Unix(0, 0).UTC(). -func (t DateTime) IsUnixZero() bool { - return time.Time(t) == UnixZero +func (t *DateTime) IsUnixZero() bool { + if t == nil { + return true + } + return time.Time(*t).Equal(UnixZero) } // MarshalText implements the text marshaller interface @@ -239,7 +247,7 @@ func (t DateTime) MarshalBSONValue() (bsontype.Type, []byte, error) { buf := make([]byte, 8) binary.LittleEndian.PutUint64(buf, uint64(i64)) - return bsontype.DateTime, buf, nil + return bson.TypeDateTime, buf, nil } // UnmarshalBSONValue is an interface implemented by types that can unmarshal a @@ -247,7 +255,7 @@ func (t DateTime) MarshalBSONValue() (bsontype.Type, []byte, error) { // assumed to be valid. UnmarshalBSONValue must copy the BSON value bytes if it // wishes to retain the data after returning. func (t *DateTime) UnmarshalBSONValue(tpe bsontype.Type, data []byte) error { - if tpe == bsontype.Null { + if tpe == bson.TypeNull { *t = DateTime{} return nil } diff --git a/vendor/github.com/go-playground/validator/v10/.gitignore b/vendor/github.com/go-playground/validator/v10/.gitignore index 2410a91b95..6305e52900 100644 --- a/vendor/github.com/go-playground/validator/v10/.gitignore +++ b/vendor/github.com/go-playground/validator/v10/.gitignore @@ -26,6 +26,7 @@ _testmain.go *.test *.out *.txt +/**/*.DS_Store cover.html README.html .idea diff --git a/vendor/github.com/go-playground/validator/v10/Makefile b/vendor/github.com/go-playground/validator/v10/Makefile index ec3455bd59..e097dfaf2f 100644 --- a/vendor/github.com/go-playground/validator/v10/Makefile +++ b/vendor/github.com/go-playground/validator/v10/Makefile @@ -1,4 +1,4 @@ -GOCMD=GO111MODULE=on go +GOCMD=go linters-install: @golangci-lint --version >/dev/null 2>&1 || { \ @@ -13,6 +13,6 @@ test: $(GOCMD) test -cover -race ./... bench: - $(GOCMD) test -bench=. -benchmem ./... + $(GOCMD) test -run=NONE -bench=. -benchmem ./... -.PHONY: test lint linters-install \ No newline at end of file +.PHONY: test lint linters-install diff --git a/vendor/github.com/go-playground/validator/v10/README.md b/vendor/github.com/go-playground/validator/v10/README.md index f5a9b75bb3..a6e1d0b51d 100644 --- a/vendor/github.com/go-playground/validator/v10/README.md +++ b/vendor/github.com/go-playground/validator/v10/README.md @@ -1,7 +1,7 @@ Package validator ================= -[![Join the chat at https://gitter.im/go-playground/validator](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/go-playground/validator?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -![Project status](https://img.shields.io/badge/version-10.13.0-green.svg) +[![Join the chat at https://gitter.im/go-playground/validator](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/go-playground/validator?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +![Project status](https://img.shields.io/badge/version-10.19.0-green.svg) [![Build Status](https://travis-ci.org/go-playground/validator.svg?branch=master)](https://travis-ci.org/go-playground/validator) [![Coverage Status](https://coveralls.io/repos/go-playground/validator/badge.svg?branch=master&service=github)](https://coveralls.io/github/go-playground/validator?branch=master) [![Go Report Card](https://goreportcard.com/badge/github.com/go-playground/validator)](https://goreportcard.com/report/github.com/go-playground/validator) @@ -67,6 +67,12 @@ Please see https://pkg.go.dev/github.com/go-playground/validator/v10 for detaile Baked-in Validations ------ +### Special Notes: +- If new to using validator it is highly recommended to initialize it using the `WithRequiredStructEnabled` option which is opt-in to new behaviour that will become the default behaviour in v11+. See documentation for more details. +```go +validate := validator.New(validator.WithRequiredStructEnabled()) +``` + ### Fields: | Tag | Description | @@ -158,6 +164,7 @@ Baked-in Validations | credit_card | Credit Card Number | | mongodb | MongoDB ObjectID | | cron | Cron | +| spicedb | SpiceDb ObjectID/Permission/Type | | datetime | Datetime | | e164 | e164 formatted phone number | | email | E-mail String @@ -171,6 +178,7 @@ Baked-in Validations | isbn | International Standard Book Number | | isbn10 | International Standard Book Number 10 | | isbn13 | International Standard Book Number 13 | +| issn | International Standard Serial Number | | iso3166_1_alpha2 | Two-letter country code (ISO 3166-1 alpha-2) | | iso3166_1_alpha3 | Three-letter country code (ISO 3166-1 alpha-3) | | iso3166_1_alpha_numeric | Numeric country code (ISO 3166-1 numeric) | @@ -228,6 +236,7 @@ Baked-in Validations | dirpath | Directory Path | | file | Existing File | | filepath | File Path | +| image | Image | | isdefault | Is Default | | len | Length | | max | Maximum | @@ -258,71 +267,72 @@ Benchmarks ------ ###### Run on MacBook Pro (15-inch, 2017) go version go1.10.2 darwin/amd64 ```go +go version go1.21.0 darwin/arm64 goos: darwin -goarch: amd64 -pkg: github.com/go-playground/validator -BenchmarkFieldSuccess-8 20000000 83.6 ns/op 0 B/op 0 allocs/op -BenchmarkFieldSuccessParallel-8 50000000 26.8 ns/op 0 B/op 0 allocs/op -BenchmarkFieldFailure-8 5000000 291 ns/op 208 B/op 4 allocs/op -BenchmarkFieldFailureParallel-8 20000000 107 ns/op 208 B/op 4 allocs/op -BenchmarkFieldArrayDiveSuccess-8 2000000 623 ns/op 201 B/op 11 allocs/op -BenchmarkFieldArrayDiveSuccessParallel-8 10000000 237 ns/op 201 B/op 11 allocs/op -BenchmarkFieldArrayDiveFailure-8 2000000 859 ns/op 412 B/op 16 allocs/op -BenchmarkFieldArrayDiveFailureParallel-8 5000000 335 ns/op 413 B/op 16 allocs/op -BenchmarkFieldMapDiveSuccess-8 1000000 1292 ns/op 432 B/op 18 allocs/op -BenchmarkFieldMapDiveSuccessParallel-8 3000000 467 ns/op 432 B/op 18 allocs/op -BenchmarkFieldMapDiveFailure-8 1000000 1082 ns/op 512 B/op 16 allocs/op -BenchmarkFieldMapDiveFailureParallel-8 5000000 425 ns/op 512 B/op 16 allocs/op -BenchmarkFieldMapDiveWithKeysSuccess-8 1000000 1539 ns/op 480 B/op 21 allocs/op -BenchmarkFieldMapDiveWithKeysSuccessParallel-8 3000000 613 ns/op 480 B/op 21 allocs/op -BenchmarkFieldMapDiveWithKeysFailure-8 1000000 1413 ns/op 721 B/op 21 allocs/op -BenchmarkFieldMapDiveWithKeysFailureParallel-8 3000000 575 ns/op 721 B/op 21 allocs/op -BenchmarkFieldCustomTypeSuccess-8 10000000 216 ns/op 32 B/op 2 allocs/op -BenchmarkFieldCustomTypeSuccessParallel-8 20000000 82.2 ns/op 32 B/op 2 allocs/op -BenchmarkFieldCustomTypeFailure-8 5000000 274 ns/op 208 B/op 4 allocs/op -BenchmarkFieldCustomTypeFailureParallel-8 20000000 116 ns/op 208 B/op 4 allocs/op -BenchmarkFieldOrTagSuccess-8 2000000 740 ns/op 16 B/op 1 allocs/op -BenchmarkFieldOrTagSuccessParallel-8 3000000 474 ns/op 16 B/op 1 allocs/op -BenchmarkFieldOrTagFailure-8 3000000 471 ns/op 224 B/op 5 allocs/op -BenchmarkFieldOrTagFailureParallel-8 3000000 414 ns/op 224 B/op 5 allocs/op -BenchmarkStructLevelValidationSuccess-8 10000000 213 ns/op 32 B/op 2 allocs/op -BenchmarkStructLevelValidationSuccessParallel-8 20000000 91.8 ns/op 32 B/op 2 allocs/op -BenchmarkStructLevelValidationFailure-8 3000000 473 ns/op 304 B/op 8 allocs/op -BenchmarkStructLevelValidationFailureParallel-8 10000000 234 ns/op 304 B/op 8 allocs/op -BenchmarkStructSimpleCustomTypeSuccess-8 5000000 385 ns/op 32 B/op 2 allocs/op -BenchmarkStructSimpleCustomTypeSuccessParallel-8 10000000 161 ns/op 32 B/op 2 allocs/op -BenchmarkStructSimpleCustomTypeFailure-8 2000000 640 ns/op 424 B/op 9 allocs/op -BenchmarkStructSimpleCustomTypeFailureParallel-8 5000000 318 ns/op 440 B/op 10 allocs/op -BenchmarkStructFilteredSuccess-8 2000000 597 ns/op 288 B/op 9 allocs/op -BenchmarkStructFilteredSuccessParallel-8 10000000 266 ns/op 288 B/op 9 allocs/op -BenchmarkStructFilteredFailure-8 3000000 454 ns/op 256 B/op 7 allocs/op -BenchmarkStructFilteredFailureParallel-8 10000000 214 ns/op 256 B/op 7 allocs/op -BenchmarkStructPartialSuccess-8 3000000 502 ns/op 256 B/op 6 allocs/op -BenchmarkStructPartialSuccessParallel-8 10000000 225 ns/op 256 B/op 6 allocs/op -BenchmarkStructPartialFailure-8 2000000 702 ns/op 480 B/op 11 allocs/op -BenchmarkStructPartialFailureParallel-8 5000000 329 ns/op 480 B/op 11 allocs/op -BenchmarkStructExceptSuccess-8 2000000 793 ns/op 496 B/op 12 allocs/op -BenchmarkStructExceptSuccessParallel-8 10000000 193 ns/op 240 B/op 5 allocs/op -BenchmarkStructExceptFailure-8 2000000 639 ns/op 464 B/op 10 allocs/op -BenchmarkStructExceptFailureParallel-8 5000000 300 ns/op 464 B/op 10 allocs/op -BenchmarkStructSimpleCrossFieldSuccess-8 3000000 417 ns/op 72 B/op 3 allocs/op -BenchmarkStructSimpleCrossFieldSuccessParallel-8 10000000 163 ns/op 72 B/op 3 allocs/op -BenchmarkStructSimpleCrossFieldFailure-8 2000000 645 ns/op 304 B/op 8 allocs/op -BenchmarkStructSimpleCrossFieldFailureParallel-8 5000000 285 ns/op 304 B/op 8 allocs/op -BenchmarkStructSimpleCrossStructCrossFieldSuccess-8 3000000 588 ns/op 80 B/op 4 allocs/op -BenchmarkStructSimpleCrossStructCrossFieldSuccessParallel-8 10000000 221 ns/op 80 B/op 4 allocs/op -BenchmarkStructSimpleCrossStructCrossFieldFailure-8 2000000 868 ns/op 320 B/op 9 allocs/op -BenchmarkStructSimpleCrossStructCrossFieldFailureParallel-8 5000000 337 ns/op 320 B/op 9 allocs/op -BenchmarkStructSimpleSuccess-8 5000000 260 ns/op 0 B/op 0 allocs/op -BenchmarkStructSimpleSuccessParallel-8 20000000 90.6 ns/op 0 B/op 0 allocs/op -BenchmarkStructSimpleFailure-8 2000000 619 ns/op 424 B/op 9 allocs/op -BenchmarkStructSimpleFailureParallel-8 5000000 296 ns/op 424 B/op 9 allocs/op -BenchmarkStructComplexSuccess-8 1000000 1454 ns/op 128 B/op 8 allocs/op -BenchmarkStructComplexSuccessParallel-8 3000000 579 ns/op 128 B/op 8 allocs/op -BenchmarkStructComplexFailure-8 300000 4140 ns/op 3041 B/op 53 allocs/op -BenchmarkStructComplexFailureParallel-8 1000000 2127 ns/op 3041 B/op 53 allocs/op -BenchmarkOneof-8 10000000 140 ns/op 0 B/op 0 allocs/op -BenchmarkOneofParallel-8 20000000 70.1 ns/op 0 B/op 0 allocs/op +goarch: arm64 +pkg: github.com/go-playground/validator/v10 +BenchmarkFieldSuccess-8 33142266 35.94 ns/op 0 B/op 0 allocs/op +BenchmarkFieldSuccessParallel-8 200816191 6.568 ns/op 0 B/op 0 allocs/op +BenchmarkFieldFailure-8 6779707 175.1 ns/op 200 B/op 4 allocs/op +BenchmarkFieldFailureParallel-8 11044147 108.4 ns/op 200 B/op 4 allocs/op +BenchmarkFieldArrayDiveSuccess-8 6054232 194.4 ns/op 97 B/op 5 allocs/op +BenchmarkFieldArrayDiveSuccessParallel-8 12523388 94.07 ns/op 97 B/op 5 allocs/op +BenchmarkFieldArrayDiveFailure-8 3587043 334.3 ns/op 300 B/op 10 allocs/op +BenchmarkFieldArrayDiveFailureParallel-8 5816665 200.8 ns/op 300 B/op 10 allocs/op +BenchmarkFieldMapDiveSuccess-8 2217910 540.1 ns/op 288 B/op 14 allocs/op +BenchmarkFieldMapDiveSuccessParallel-8 4446698 258.7 ns/op 288 B/op 14 allocs/op +BenchmarkFieldMapDiveFailure-8 2392759 504.6 ns/op 376 B/op 13 allocs/op +BenchmarkFieldMapDiveFailureParallel-8 4244199 286.9 ns/op 376 B/op 13 allocs/op +BenchmarkFieldMapDiveWithKeysSuccess-8 2005857 592.1 ns/op 288 B/op 14 allocs/op +BenchmarkFieldMapDiveWithKeysSuccessParallel-8 4400850 296.9 ns/op 288 B/op 14 allocs/op +BenchmarkFieldMapDiveWithKeysFailure-8 1850227 643.8 ns/op 553 B/op 16 allocs/op +BenchmarkFieldMapDiveWithKeysFailureParallel-8 3293233 375.1 ns/op 553 B/op 16 allocs/op +BenchmarkFieldCustomTypeSuccess-8 12174412 98.25 ns/op 32 B/op 2 allocs/op +BenchmarkFieldCustomTypeSuccessParallel-8 34389907 35.49 ns/op 32 B/op 2 allocs/op +BenchmarkFieldCustomTypeFailure-8 7582524 156.6 ns/op 184 B/op 3 allocs/op +BenchmarkFieldCustomTypeFailureParallel-8 13019902 92.79 ns/op 184 B/op 3 allocs/op +BenchmarkFieldOrTagSuccess-8 3427260 349.4 ns/op 16 B/op 1 allocs/op +BenchmarkFieldOrTagSuccessParallel-8 15144128 81.25 ns/op 16 B/op 1 allocs/op +BenchmarkFieldOrTagFailure-8 5913546 201.9 ns/op 216 B/op 5 allocs/op +BenchmarkFieldOrTagFailureParallel-8 9810212 113.7 ns/op 216 B/op 5 allocs/op +BenchmarkStructLevelValidationSuccess-8 13456327 87.66 ns/op 16 B/op 1 allocs/op +BenchmarkStructLevelValidationSuccessParallel-8 41818888 27.77 ns/op 16 B/op 1 allocs/op +BenchmarkStructLevelValidationFailure-8 4166284 272.6 ns/op 264 B/op 7 allocs/op +BenchmarkStructLevelValidationFailureParallel-8 7594581 152.1 ns/op 264 B/op 7 allocs/op +BenchmarkStructSimpleCustomTypeSuccess-8 6508082 182.6 ns/op 32 B/op 2 allocs/op +BenchmarkStructSimpleCustomTypeSuccessParallel-8 23078605 54.78 ns/op 32 B/op 2 allocs/op +BenchmarkStructSimpleCustomTypeFailure-8 3118352 381.0 ns/op 416 B/op 9 allocs/op +BenchmarkStructSimpleCustomTypeFailureParallel-8 5300738 224.1 ns/op 432 B/op 10 allocs/op +BenchmarkStructFilteredSuccess-8 4761807 251.1 ns/op 216 B/op 5 allocs/op +BenchmarkStructFilteredSuccessParallel-8 8792598 128.6 ns/op 216 B/op 5 allocs/op +BenchmarkStructFilteredFailure-8 5202573 232.1 ns/op 216 B/op 5 allocs/op +BenchmarkStructFilteredFailureParallel-8 9591267 121.4 ns/op 216 B/op 5 allocs/op +BenchmarkStructPartialSuccess-8 5188512 231.6 ns/op 224 B/op 4 allocs/op +BenchmarkStructPartialSuccessParallel-8 9179776 123.1 ns/op 224 B/op 4 allocs/op +BenchmarkStructPartialFailure-8 3071212 392.5 ns/op 440 B/op 9 allocs/op +BenchmarkStructPartialFailureParallel-8 5344261 223.7 ns/op 440 B/op 9 allocs/op +BenchmarkStructExceptSuccess-8 3184230 375.0 ns/op 424 B/op 8 allocs/op +BenchmarkStructExceptSuccessParallel-8 10090130 108.9 ns/op 208 B/op 3 allocs/op +BenchmarkStructExceptFailure-8 3347226 357.7 ns/op 424 B/op 8 allocs/op +BenchmarkStructExceptFailureParallel-8 5654923 209.5 ns/op 424 B/op 8 allocs/op +BenchmarkStructSimpleCrossFieldSuccess-8 5232265 229.1 ns/op 56 B/op 3 allocs/op +BenchmarkStructSimpleCrossFieldSuccessParallel-8 17436674 64.75 ns/op 56 B/op 3 allocs/op +BenchmarkStructSimpleCrossFieldFailure-8 3128613 383.6 ns/op 272 B/op 8 allocs/op +BenchmarkStructSimpleCrossFieldFailureParallel-8 6994113 168.8 ns/op 272 B/op 8 allocs/op +BenchmarkStructSimpleCrossStructCrossFieldSuccess-8 3506487 340.9 ns/op 64 B/op 4 allocs/op +BenchmarkStructSimpleCrossStructCrossFieldSuccessParallel-8 13431300 91.77 ns/op 64 B/op 4 allocs/op +BenchmarkStructSimpleCrossStructCrossFieldFailure-8 2410566 500.9 ns/op 288 B/op 9 allocs/op +BenchmarkStructSimpleCrossStructCrossFieldFailureParallel-8 6344510 188.2 ns/op 288 B/op 9 allocs/op +BenchmarkStructSimpleSuccess-8 8922726 133.8 ns/op 0 B/op 0 allocs/op +BenchmarkStructSimpleSuccessParallel-8 55291153 23.63 ns/op 0 B/op 0 allocs/op +BenchmarkStructSimpleFailure-8 3171553 378.4 ns/op 416 B/op 9 allocs/op +BenchmarkStructSimpleFailureParallel-8 5571692 212.0 ns/op 416 B/op 9 allocs/op +BenchmarkStructComplexSuccess-8 1683750 714.5 ns/op 224 B/op 5 allocs/op +BenchmarkStructComplexSuccessParallel-8 4578046 257.0 ns/op 224 B/op 5 allocs/op +BenchmarkStructComplexFailure-8 481585 2547 ns/op 3041 B/op 48 allocs/op +BenchmarkStructComplexFailureParallel-8 965764 1577 ns/op 3040 B/op 48 allocs/op +BenchmarkOneof-8 17380881 68.50 ns/op 0 B/op 0 allocs/op +BenchmarkOneofParallel-8 8084733 153.5 ns/op 0 B/op 0 allocs/op ``` Complementary Software diff --git a/vendor/github.com/go-playground/validator/v10/baked_in.go b/vendor/github.com/go-playground/validator/v10/baked_in.go index d66980b6e2..95f56e0080 100644 --- a/vendor/github.com/go-playground/validator/v10/baked_in.go +++ b/vendor/github.com/go-playground/validator/v10/baked_in.go @@ -22,7 +22,8 @@ import ( "golang.org/x/crypto/sha3" "golang.org/x/text/language" - "github.com/leodido/go-urn" + "github.com/gabriel-vasile/mimetype" + urn "github.com/leodido/go-urn" ) // Func accepts a FieldLevel interface for all validation needs. The return @@ -50,6 +51,7 @@ var ( endKeysTag: {}, structOnlyTag: {}, omitempty: {}, + omitnil: {}, skipValidationTag: {}, utf8HexComma: {}, utf8Pipe: {}, @@ -144,9 +146,11 @@ var ( "endswith": endsWith, "startsnotwith": startsNotWith, "endsnotwith": endsNotWith, + "image": isImage, "isbn": isISBN, "isbn10": isISBN10, "isbn13": isISBN13, + "issn": isISSN, "eth_addr": isEthereumAddress, "eth_addr_checksum": isEthereumAddressChecksum, "btc_addr": isBitcoinAddress, @@ -228,6 +232,7 @@ var ( "luhn_checksum": hasLuhnChecksum, "mongodb": isMongoDB, "cron": isCron, + "spicedb": isSpiceDB, } ) @@ -370,9 +375,9 @@ func isMAC(fl FieldLevel) bool { // isCIDRv4 is the validation function for validating if the field's value is a valid v4 CIDR address. func isCIDRv4(fl FieldLevel) bool { - ip, _, err := net.ParseCIDR(fl.Field().String()) + ip, net, err := net.ParseCIDR(fl.Field().String()) - return err == nil && ip.To4() != nil + return err == nil && ip.To4() != nil && net.IP.Equal(ip) } // isCIDRv6 is the validation function for validating if the field's value is a valid v6 CIDR address. @@ -505,47 +510,47 @@ func isASCII(fl FieldLevel) bool { // isUUID5 is the validation function for validating if the field's value is a valid v5 UUID. func isUUID5(fl FieldLevel) bool { - return uUID5Regex.MatchString(fl.Field().String()) + return fieldMatchesRegexByStringerValOrString(uUID5Regex, fl) } // isUUID4 is the validation function for validating if the field's value is a valid v4 UUID. func isUUID4(fl FieldLevel) bool { - return uUID4Regex.MatchString(fl.Field().String()) + return fieldMatchesRegexByStringerValOrString(uUID4Regex, fl) } // isUUID3 is the validation function for validating if the field's value is a valid v3 UUID. func isUUID3(fl FieldLevel) bool { - return uUID3Regex.MatchString(fl.Field().String()) + return fieldMatchesRegexByStringerValOrString(uUID3Regex, fl) } // isUUID is the validation function for validating if the field's value is a valid UUID of any version. func isUUID(fl FieldLevel) bool { - return uUIDRegex.MatchString(fl.Field().String()) + return fieldMatchesRegexByStringerValOrString(uUIDRegex, fl) } // isUUID5RFC4122 is the validation function for validating if the field's value is a valid RFC4122 v5 UUID. func isUUID5RFC4122(fl FieldLevel) bool { - return uUID5RFC4122Regex.MatchString(fl.Field().String()) + return fieldMatchesRegexByStringerValOrString(uUID5RFC4122Regex, fl) } // isUUID4RFC4122 is the validation function for validating if the field's value is a valid RFC4122 v4 UUID. func isUUID4RFC4122(fl FieldLevel) bool { - return uUID4RFC4122Regex.MatchString(fl.Field().String()) + return fieldMatchesRegexByStringerValOrString(uUID4RFC4122Regex, fl) } // isUUID3RFC4122 is the validation function for validating if the field's value is a valid RFC4122 v3 UUID. func isUUID3RFC4122(fl FieldLevel) bool { - return uUID3RFC4122Regex.MatchString(fl.Field().String()) + return fieldMatchesRegexByStringerValOrString(uUID3RFC4122Regex, fl) } // isUUIDRFC4122 is the validation function for validating if the field's value is a valid RFC4122 UUID of any version. func isUUIDRFC4122(fl FieldLevel) bool { - return uUIDRFC4122Regex.MatchString(fl.Field().String()) + return fieldMatchesRegexByStringerValOrString(uUIDRFC4122Regex, fl) } // isULID is the validation function for validating if the field's value is a valid ULID. func isULID(fl FieldLevel) bool { - return uLIDRegex.MatchString(fl.Field().String()) + return fieldMatchesRegexByStringerValOrString(uLIDRegex, fl) } // isMD4 is the validation function for validating if the field's value is a valid MD4. @@ -647,6 +652,32 @@ func isISBN10(fl FieldLevel) bool { return checksum%11 == 0 } +// isISSN is the validation function for validating if the field's value is a valid ISSN. +func isISSN(fl FieldLevel) bool { + s := fl.Field().String() + + if !iSSNRegex.MatchString(s) { + return false + } + s = strings.ReplaceAll(s, "-", "") + + pos := 8 + checksum := 0 + + for i := 0; i < 7; i++ { + checksum += pos * int(s[i]-'0') + pos-- + } + + if s[7] == 'X' { + checksum += 10 + } else { + checksum += int(s[7] - '0') + } + + return checksum%11 == 0 +} + // isEthereumAddress is the validation function for validating if the field's value is a valid Ethereum address. func isEthereumAddress(fl FieldLevel) bool { address := fl.Field().String() @@ -1292,8 +1323,13 @@ func isEq(fl FieldLevel) bool { return field.Uint() == p - case reflect.Float32, reflect.Float64: - p := asFloat(param) + case reflect.Float32: + p := asFloat32(param) + + return field.Float() == p + + case reflect.Float64: + p := asFloat64(param) return field.Float() == p @@ -1405,6 +1441,15 @@ func isURI(fl FieldLevel) bool { panic(fmt.Sprintf("Bad field type %T", field.Interface())) } +// isFileURL is the helper function for validating if the `path` valid file URL as per RFC8089 +func isFileURL(path string) bool { + if !strings.HasPrefix(path, "file:/") { + return false + } + _, err := url.ParseRequestURI(path) + return err == nil +} + // isURL is the validation function for validating if the current field's value is a valid URL. func isURL(fl FieldLevel) bool { field := fl.Field() @@ -1412,25 +1457,25 @@ func isURL(fl FieldLevel) bool { switch field.Kind() { case reflect.String: - var i int - s := field.String() - - // checks needed as of Go 1.6 because of change https://github.com/golang/go/commit/617c93ce740c3c3cc28cdd1a0d712be183d0b328#diff-6c2d018290e298803c0c9419d8739885L195 - // emulate browser and strip the '#' suffix prior to validation. see issue-#237 - if i = strings.Index(s, "#"); i > -1 { - s = s[:i] - } + s := strings.ToLower(field.String()) if len(s) == 0 { return false } - url, err := url.ParseRequestURI(s) + if isFileURL(s) { + return true + } + url, err := url.Parse(s) if err != nil || url.Scheme == "" { return false } + if url.Host == "" && url.Fragment == "" && url.Opaque == "" { + return false + } + return true } @@ -1448,7 +1493,13 @@ func isHttpURL(fl FieldLevel) bool { case reflect.String: s := strings.ToLower(field.String()) - return strings.HasPrefix(s, "http://") || strings.HasPrefix(s, "https://") + + url, err := url.Parse(s) + if err != nil || url.Host == "" { + return false + } + + return url.Scheme == "http" || url.Scheme == "https" } panic(fmt.Sprintf("Bad field type %T", field.Interface())) @@ -1488,6 +1539,67 @@ func isFile(fl FieldLevel) bool { panic(fmt.Sprintf("Bad field type %T", field.Interface())) } +// isImage is the validation function for validating if the current field's value contains the path to a valid image file +func isImage(fl FieldLevel) bool { + mimetypes := map[string]bool{ + "image/bmp": true, + "image/cis-cod": true, + "image/gif": true, + "image/ief": true, + "image/jpeg": true, + "image/jp2": true, + "image/jpx": true, + "image/jpm": true, + "image/pipeg": true, + "image/png": true, + "image/svg+xml": true, + "image/tiff": true, + "image/webp": true, + "image/x-cmu-raster": true, + "image/x-cmx": true, + "image/x-icon": true, + "image/x-portable-anymap": true, + "image/x-portable-bitmap": true, + "image/x-portable-graymap": true, + "image/x-portable-pixmap": true, + "image/x-rgb": true, + "image/x-xbitmap": true, + "image/x-xpixmap": true, + "image/x-xwindowdump": true, + } + field := fl.Field() + + switch field.Kind() { + case reflect.String: + filePath := field.String() + fileInfo, err := os.Stat(filePath) + + if err != nil { + return false + } + + if fileInfo.IsDir() { + return false + } + + file, err := os.Open(filePath) + if err != nil { + return false + } + defer file.Close() + + mime, err := mimetype.DetectReader(file) + if err != nil { + return false + } + + if _, ok := mimetypes[mime.String()]; ok { + return true + } + } + return false +} + // isFilePath is the validation function for validating if the current field's value is a valid file path. func isFilePath(fl FieldLevel) bool { @@ -1496,6 +1608,10 @@ func isFilePath(fl FieldLevel) bool { field := fl.Field() + // Not valid if it is a directory. + if isDir(fl) { + return false + } // If it exists, it obviously is valid. // This is done first to avoid code duplication and unnecessary additional logic. if exists = isFile(fl); exists { @@ -1645,7 +1761,7 @@ func hasValue(fl FieldLevel) bool { if fl.(*validate).fldIsPointer && field.Interface() != nil { return true } - return field.IsValid() && field.Interface() != reflect.Zero(field.Type()).Interface() + return field.IsValid() && !field.IsZero() } } @@ -1669,7 +1785,7 @@ func requireCheckFieldKind(fl FieldLevel, param string, defaultNotFoundValue boo if nullable && field.Interface() != nil { return false } - return field.IsValid() && field.Interface() == reflect.Zero(field.Type()).Interface() + return field.IsValid() && field.IsZero() } } @@ -1690,8 +1806,11 @@ func requireCheckFieldValue( case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: return field.Uint() == asUint(value) - case reflect.Float32, reflect.Float64: - return field.Float() == asFloat(value) + case reflect.Float32: + return field.Float() == asFloat32(value) + + case reflect.Float64: + return field.Float() == asFloat64(value) case reflect.Slice, reflect.Map, reflect.Array: return int64(field.Len()) == asInt(value) @@ -1990,8 +2109,13 @@ func isGte(fl FieldLevel) bool { return field.Uint() >= p - case reflect.Float32, reflect.Float64: - p := asFloat(param) + case reflect.Float32: + p := asFloat32(param) + + return field.Float() >= p + + case reflect.Float64: + p := asFloat64(param) return field.Float() >= p @@ -2036,10 +2160,16 @@ func isGt(fl FieldLevel) bool { return field.Uint() > p - case reflect.Float32, reflect.Float64: - p := asFloat(param) + case reflect.Float32: + p := asFloat32(param) return field.Float() > p + + case reflect.Float64: + p := asFloat64(param) + + return field.Float() > p + case reflect.Struct: if field.Type().ConvertibleTo(timeType) { @@ -2078,8 +2208,13 @@ func hasLengthOf(fl FieldLevel) bool { return field.Uint() == p - case reflect.Float32, reflect.Float64: - p := asFloat(param) + case reflect.Float32: + p := asFloat32(param) + + return field.Float() == p + + case reflect.Float64: + p := asFloat64(param) return field.Float() == p } @@ -2211,8 +2346,13 @@ func isLte(fl FieldLevel) bool { return field.Uint() <= p - case reflect.Float32, reflect.Float64: - p := asFloat(param) + case reflect.Float32: + p := asFloat32(param) + + return field.Float() <= p + + case reflect.Float64: + p := asFloat64(param) return field.Float() <= p @@ -2257,8 +2397,13 @@ func isLt(fl FieldLevel) bool { return field.Uint() < p - case reflect.Float32, reflect.Float64: - p := asFloat(param) + case reflect.Float32: + p := asFloat32(param) + + return field.Float() < p + + case reflect.Float64: + p := asFloat64(param) return field.Float() < p @@ -2505,9 +2650,17 @@ func isDirPath(fl FieldLevel) bool { func isJSON(fl FieldLevel) bool { field := fl.Field() - if field.Kind() == reflect.String { + switch field.Kind() { + case reflect.String: val := field.String() return json.Valid([]byte(val)) + case reflect.Slice: + fieldType := field.Type() + + if fieldType.ConvertibleTo(byteSliceType) { + b := field.Convert(byteSliceType).Interface().([]byte) + return json.Valid(b) + } } panic(fmt.Sprintf("Bad field type %T", field.Interface())) @@ -2735,6 +2888,23 @@ func isMongoDB(fl FieldLevel) bool { return mongodbRegex.MatchString(val) } +// isSpiceDB is the validation function for validating if the current field's value is valid for use with Authzed SpiceDB in the indicated way +func isSpiceDB(fl FieldLevel) bool { + val := fl.Field().String() + param := fl.Param() + + switch param { + case "permission": + return spicedbPermissionRegex.MatchString(val) + case "type": + return spicedbTypeRegex.MatchString(val) + case "id", "": + return spicedbIDRegex.MatchString(val) + } + + panic("Unrecognized parameter: " + param) +} + // isCreditCard is the validation function for validating if the current field's value is a valid credit card number func isCreditCard(fl FieldLevel) bool { val := fl.Field().String() diff --git a/vendor/github.com/go-playground/validator/v10/cache.go b/vendor/github.com/go-playground/validator/v10/cache.go index bbfd2a4af1..b6bdd11a1f 100644 --- a/vendor/github.com/go-playground/validator/v10/cache.go +++ b/vendor/github.com/go-playground/validator/v10/cache.go @@ -20,6 +20,7 @@ const ( typeOr typeKeys typeEndKeys + typeOmitNil ) const ( @@ -125,7 +126,7 @@ func (v *Validate) extractStructCache(current reflect.Value, sName string) *cStr fld = typ.Field(i) - if !fld.Anonymous && len(fld.PkgPath) > 0 { + if !v.privateFieldValidation && !fld.Anonymous && len(fld.PkgPath) > 0 { continue } @@ -252,6 +253,10 @@ func (v *Validate) parseFieldTagsRecursive(tag string, fieldName string, alias s current.typeof = typeOmitEmpty continue + case omitnil: + current.typeof = typeOmitNil + continue + case structOnlyTag: current.typeof = typeStructOnly continue diff --git a/vendor/github.com/go-playground/validator/v10/country_codes.go b/vendor/github.com/go-playground/validator/v10/country_codes.go index 91b2e0b909..0119f0574d 100644 --- a/vendor/github.com/go-playground/validator/v10/country_codes.go +++ b/vendor/github.com/go-playground/validator/v10/country_codes.go @@ -1135,7 +1135,7 @@ var iso3166_2 = map[string]bool{ "VN-69": true, "VN-70": true, "VN-71": true, "VN-72": true, "VN-73": true, "VN-CT": true, "VN-DN": true, "VN-HN": true, "VN-HP": true, "VN-SG": true, "VU-MAP": true, "VU-PAM": true, "VU-SAM": true, "VU-SEE": true, "VU-TAE": true, - "VU-TOB": true, "WF-SG": true,"WF-UV": true, "WS-AA": true, "WS-AL": true, "WS-AT": true, "WS-FA": true, + "VU-TOB": true, "WF-SG": true, "WF-UV": true, "WS-AA": true, "WS-AL": true, "WS-AT": true, "WS-FA": true, "WS-GE": true, "WS-GI": true, "WS-PA": true, "WS-SA": true, "WS-TU": true, "WS-VF": true, "WS-VS": true, "YE-AB": true, "YE-AD": true, "YE-AM": true, "YE-BA": true, "YE-DA": true, "YE-DH": true, "YE-HD": true, "YE-HJ": true, "YE-HU": true, diff --git a/vendor/github.com/go-playground/validator/v10/doc.go b/vendor/github.com/go-playground/validator/v10/doc.go index f31a7d538a..b474091881 100644 --- a/vendor/github.com/go-playground/validator/v10/doc.go +++ b/vendor/github.com/go-playground/validator/v10/doc.go @@ -194,6 +194,13 @@ such as min or max won't run, but if a value is set validation will run. Usage: omitempty +# Omit Nil + +Allows to skip the validation if the value is nil (same as omitempty, but +only for the nil-values). + + Usage: omitnil + # Dive This tells the validator to dive into a slice, array or map and validate that @@ -247,7 +254,7 @@ Example #2 This validates that the value is not the data types default zero value. For numbers ensures value is not zero. For strings ensures value is not "". For slices, maps, pointers, interfaces, channels and functions -ensures the value is not nil. +ensures the value is not nil. For structs ensures value is not the zero value when using WithRequiredStructEnabled. Usage: required @@ -256,7 +263,7 @@ ensures the value is not nil. The field under validation must be present and not empty only if all the other specified fields are equal to the value following the specified field. For strings ensures value is not "". For slices, maps, pointers, -interfaces, channels and functions ensures the value is not nil. +interfaces, channels and functions ensures the value is not nil. For structs ensures value is not the zero value. Usage: required_if @@ -273,7 +280,7 @@ Examples: The field under validation must be present and not empty unless all the other specified fields are equal to the value following the specified field. For strings ensures value is not "". For slices, maps, pointers, -interfaces, channels and functions ensures the value is not nil. +interfaces, channels and functions ensures the value is not nil. For structs ensures value is not the zero value. Usage: required_unless @@ -290,7 +297,7 @@ Examples: The field under validation must be present and not empty only if any of the other specified fields are present. For strings ensures value is not "". For slices, maps, pointers, interfaces, channels and functions -ensures the value is not nil. +ensures the value is not nil. For structs ensures value is not the zero value. Usage: required_with @@ -307,7 +314,7 @@ Examples: The field under validation must be present and not empty only if all of the other specified fields are present. For strings ensures value is not "". For slices, maps, pointers, interfaces, channels and functions -ensures the value is not nil. +ensures the value is not nil. For structs ensures value is not the zero value. Usage: required_with_all @@ -321,7 +328,7 @@ Example: The field under validation must be present and not empty only when any of the other specified fields are not present. For strings ensures value is not "". For slices, maps, pointers, interfaces, channels and functions -ensures the value is not nil. +ensures the value is not nil. For structs ensures value is not the zero value. Usage: required_without @@ -338,7 +345,7 @@ Examples: The field under validation must be present and not empty only when all of the other specified fields are not present. For strings ensures value is not "". For slices, maps, pointers, interfaces, channels and functions -ensures the value is not nil. +ensures the value is not nil. For structs ensures value is not the zero value. Usage: required_without_all @@ -352,7 +359,7 @@ Example: The field under validation must not be present or not empty only if all the other specified fields are equal to the value following the specified field. For strings ensures value is not "". For slices, maps, pointers, -interfaces, channels and functions ensures the value is not nil. +interfaces, channels and functions ensures the value is not nil. For structs ensures value is not the zero value. Usage: excluded_if @@ -369,7 +376,7 @@ Examples: The field under validation must not be present or empty unless all the other specified fields are equal to the value following the specified field. For strings ensures value is not "". For slices, maps, pointers, -interfaces, channels and functions ensures the value is not nil. +interfaces, channels and functions ensures the value is not nil. For structs ensures value is not the zero value. Usage: excluded_unless @@ -863,7 +870,6 @@ This validates that a string value is a valid JWT Usage: jwt - # File This validates that a string value contains a valid file path and that @@ -872,6 +878,13 @@ This is done using os.Stat, which is a platform independent function. Usage: file +# Image path + +This validates that a string value contains a valid file path and that +the file exists on the machine and is an image. +This is done using os.Stat and github.com/gabriel-vasile/mimetype + + Usage: image # File Path @@ -881,7 +894,6 @@ This is done using os.Stat, which is a platform independent function. Usage: filepath - # URL String This validates that a string value contains a valid url @@ -923,7 +935,6 @@ you can use this with the omitempty tag. Usage: base64url - # Base64RawURL String This validates that a string value contains a valid base64 URL safe value, @@ -934,7 +945,6 @@ you can use this with the omitempty tag. Usage: base64url - # Bitcoin Address This validates that a string value contains a valid bitcoin address. @@ -1267,7 +1277,6 @@ This is done using os.Stat, which is a platform independent function. Usage: dir - # Directory Path This validates that a string value contains a valid directory but does @@ -1278,7 +1287,6 @@ may not exist at the time of validation. Usage: dirpath - # HostPort This validates that a string value contains a valid DNS hostname and port that @@ -1350,7 +1358,6 @@ More information on https://semver.org/ Usage: semver - # CVE Identifier This validates that a string value is a valid cve id, defined in cve mitre. @@ -1358,17 +1365,15 @@ More information on https://cve.mitre.org/ Usage: cve - # Credit Card This validates that a string value contains a valid credit card number using Luhn algorithm. Usage: credit_card - # Luhn Checksum - Usage: luhn_checksum + Usage: luhn_checksum This validates that a string or (u)int value contains a valid checksum using the Luhn algorithm. @@ -1376,8 +1381,7 @@ This validates that a string or (u)int value contains a valid checksum using the This validates that a string is a valid 24 character hexadecimal string. - Usage: mongodb - + Usage: mongodb # Cron @@ -1385,7 +1389,13 @@ This validates that a string value contains a valid cron expression. Usage: cron -Alias Validators and Tags +# SpiceDb ObjectID/Permission/Object Type + +This validates that a string is valid for use with SpiceDb for the indicated purpose. If no purpose is given, a purpose of 'id' is assumed. + + Usage: spicedb=id|permission|type + +# Alias Validators and Tags Alias Validators and Tags NOTE: When returning an error, the tag returned in "FieldError" will be diff --git a/vendor/github.com/go-playground/validator/v10/errors.go b/vendor/github.com/go-playground/validator/v10/errors.go index 5856d57c8c..be2676e9e1 100644 --- a/vendor/github.com/go-playground/validator/v10/errors.go +++ b/vendor/github.com/go-playground/validator/v10/errors.go @@ -257,15 +257,19 @@ func (fe *fieldError) Error() string { // NOTE: if no registered translation can be found, it returns the original // untranslated error message. func (fe *fieldError) Translate(ut ut.Translator) string { + var fn TranslationFunc m, ok := fe.v.transTagFunc[ut] if !ok { return fe.Error() } - fn, ok := m[fe.tag] + fn, ok = m[fe.tag] if !ok { - return fe.Error() + fn, ok = m[fe.actualTag] + if !ok { + return fe.Error() + } } return fn(ut, fe) diff --git a/vendor/github.com/go-playground/validator/v10/options.go b/vendor/github.com/go-playground/validator/v10/options.go new file mode 100644 index 0000000000..86a0db218e --- /dev/null +++ b/vendor/github.com/go-playground/validator/v10/options.go @@ -0,0 +1,26 @@ +package validator + +// Option represents a configurations option to be applied to validator during initialization. +type Option func(*Validate) + +// WithRequiredStructEnabled enables required tag on non-pointer structs to be applied instead of ignored. +// +// This was made opt-in behaviour in order to maintain backward compatibility with the behaviour previous +// to being able to apply struct level validations on struct fields directly. +// +// It is recommended you enabled this as it will be the default behaviour in v11+ +func WithRequiredStructEnabled() Option { + return func(v *Validate) { + v.requiredStructEnabled = true + } +} + +// WithPrivateFieldValidation activates validation for unexported fields via the use of the `unsafe` package. +// +// By opting into this feature you are acknowledging that you are aware of the risks and accept any current or future +// consequences of using this feature. +func WithPrivateFieldValidation() Option { + return func(v *Validate) { + v.privateFieldValidation = true + } +} diff --git a/vendor/github.com/go-playground/validator/v10/regexes.go b/vendor/github.com/go-playground/validator/v10/regexes.go index ba450b3d05..af98d8daa6 100644 --- a/vendor/github.com/go-playground/validator/v10/regexes.go +++ b/vendor/github.com/go-playground/validator/v10/regexes.go @@ -22,6 +22,7 @@ const ( base64RawURLRegexString = "^(?:[A-Za-z0-9-_]{4})*(?:[A-Za-z0-9-_]{2,4})$" iSBN10RegexString = "^(?:[0-9]{9}X|[0-9]{10})$" iSBN13RegexString = "^(?:(?:97(?:8|9))[0-9]{10})$" + iSSNRegexString = "^(?:[0-9]{4}-[0-9]{3}[0-9X])$" uUID3RegexString = "^[0-9a-f]{8}-[0-9a-f]{4}-3[0-9a-f]{3}-[0-9a-f]{4}-[0-9a-f]{12}$" uUID4RegexString = "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$" uUID5RegexString = "^[0-9a-f]{8}-[0-9a-f]{4}-5[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$" @@ -68,6 +69,9 @@ const ( cveRegexString = `^CVE-(1999|2\d{3})-(0[^0]\d{2}|0\d[^0]\d{1}|0\d{2}[^0]|[1-9]{1}\d{3,})$` // CVE Format Id https://cve.mitre.org/cve/identifiers/syntaxchange.html mongodbRegexString = "^[a-f\\d]{24}$" cronRegexString = `(@(annually|yearly|monthly|weekly|daily|hourly|reboot))|(@every (\d+(ns|us|µs|ms|s|m|h))+)|((((\d+,)+\d+|(\d+(\/|-)\d+)|\d+|\*) ?){5,7})` + spicedbIDRegexString = `^(([a-zA-Z0-9/_|\-=+]{1,})|\*)$` + spicedbPermissionRegexString = "^([a-z][a-z0-9_]{1,62}[a-z0-9])?$" + spicedbTypeRegexString = "^([a-z][a-z0-9_]{1,61}[a-z0-9]/)?[a-z][a-z0-9_]{1,62}[a-z0-9]$" ) var ( @@ -90,6 +94,7 @@ var ( base64RawURLRegex = regexp.MustCompile(base64RawURLRegexString) iSBN10Regex = regexp.MustCompile(iSBN10RegexString) iSBN13Regex = regexp.MustCompile(iSBN13RegexString) + iSSNRegex = regexp.MustCompile(iSSNRegexString) uUID3Regex = regexp.MustCompile(uUID3RegexString) uUID4Regex = regexp.MustCompile(uUID4RegexString) uUID5Regex = regexp.MustCompile(uUID5RegexString) @@ -134,4 +139,7 @@ var ( cveRegex = regexp.MustCompile(cveRegexString) mongodbRegex = regexp.MustCompile(mongodbRegexString) cronRegex = regexp.MustCompile(cronRegexString) + spicedbIDRegex = regexp.MustCompile(spicedbIDRegexString) + spicedbPermissionRegex = regexp.MustCompile(spicedbPermissionRegexString) + spicedbTypeRegex = regexp.MustCompile(spicedbTypeRegexString) ) diff --git a/vendor/github.com/go-playground/validator/v10/util.go b/vendor/github.com/go-playground/validator/v10/util.go index 3925cfe1cd..16851593da 100644 --- a/vendor/github.com/go-playground/validator/v10/util.go +++ b/vendor/github.com/go-playground/validator/v10/util.go @@ -1,7 +1,9 @@ package validator import ( + "fmt" "reflect" + "regexp" "strconv" "strings" "time" @@ -261,13 +263,19 @@ func asUint(param string) uint64 { return i } -// asFloat returns the parameter as a float64 +// asFloat64 returns the parameter as a float64 // or panics if it can't convert -func asFloat(param string) float64 { - +func asFloat64(param string) float64 { i, err := strconv.ParseFloat(param, 64) panicIf(err) + return i +} +// asFloat64 returns the parameter as a float64 +// or panics if it can't convert +func asFloat32(param string) float64 { + i, err := strconv.ParseFloat(param, 32) + panicIf(err) return i } @@ -286,3 +294,18 @@ func panicIf(err error) { panic(err.Error()) } } + +// Checks if field value matches regex. If fl.Field can be cast to Stringer, it uses the Stringer interfaces +// String() return value. Otherwise, it uses fl.Field's String() value. +func fieldMatchesRegexByStringerValOrString(regex *regexp.Regexp, fl FieldLevel) bool { + switch fl.Field().Kind() { + case reflect.String: + return regex.MatchString(fl.Field().String()) + default: + if stringer, ok := fl.Field().Interface().(fmt.Stringer); ok { + return regex.MatchString(stringer.String()) + } else { + return regex.MatchString(fl.Field().String()) + } + } +} diff --git a/vendor/github.com/go-playground/validator/v10/validator.go b/vendor/github.com/go-playground/validator/v10/validator.go index 6f6d53ada7..901e7b50a4 100644 --- a/vendor/github.com/go-playground/validator/v10/validator.go +++ b/vendor/github.com/go-playground/validator/v10/validator.go @@ -5,6 +5,7 @@ import ( "fmt" "reflect" "strconv" + "unsafe" ) // per validate construct @@ -99,6 +100,8 @@ func (v *validate) traverseField(ctx context.Context, parent reflect.Value, curr current, kind, v.fldIsPointer = v.extractTypeInternal(current, false) + var isNestedStruct bool + switch kind { case reflect.Ptr, reflect.Interface, reflect.Invalid: @@ -110,6 +113,10 @@ func (v *validate) traverseField(ctx context.Context, parent reflect.Value, curr return } + if ct.typeof == typeOmitNil && (kind != reflect.Invalid && current.IsNil()) { + return + } + if ct.hasTag { if kind == reflect.Invalid { v.str1 = string(append(ns, cf.altName...)) @@ -150,7 +157,7 @@ func (v *validate) traverseField(ctx context.Context, parent reflect.Value, curr structNs: v.str2, fieldLen: uint8(len(cf.altName)), structfieldLen: uint8(len(cf.name)), - value: current.Interface(), + value: getValue(current), param: ct.param, kind: kind, typ: current.Type(), @@ -160,86 +167,61 @@ func (v *validate) traverseField(ctx context.Context, parent reflect.Value, curr } } - case reflect.Struct: - - typ = current.Type() - - if !typ.ConvertibleTo(timeType) { - - if ct != nil { - - if ct.typeof == typeStructOnly { - goto CONTINUE - } else if ct.typeof == typeIsDefault { - // set Field Level fields - v.slflParent = parent - v.flField = current - v.cf = cf - v.ct = ct - - if !ct.fn(ctx, v) { - v.str1 = string(append(ns, cf.altName...)) - - if v.v.hasTagNameFunc { - v.str2 = string(append(structNs, cf.name...)) - } else { - v.str2 = v.str1 - } - - v.errs = append(v.errs, - &fieldError{ - v: v.v, - tag: ct.aliasTag, - actualTag: ct.tag, - ns: v.str1, - structNs: v.str2, - fieldLen: uint8(len(cf.altName)), - structfieldLen: uint8(len(cf.name)), - value: current.Interface(), - param: ct.param, - kind: kind, - typ: typ, - }, - ) - return - } - } - - ct = ct.next - } - - if ct != nil && ct.typeof == typeNoStructLevel { - return - } - - CONTINUE: - // if len == 0 then validating using 'Var' or 'VarWithValue' - // Var - doesn't make much sense to do it that way, should call 'Struct', but no harm... - // VarWithField - this allows for validating against each field within the struct against a specific value - // pretty handy in certain situations - if len(cf.name) > 0 { - ns = append(append(ns, cf.altName...), '.') - structNs = append(append(structNs, cf.name...), '.') - } - - v.validateStruct(ctx, parent, current, typ, ns, structNs, ct) + if kind == reflect.Invalid { return } - } - if ct == nil || !ct.hasTag { - return + case reflect.Struct: + isNestedStruct = !current.Type().ConvertibleTo(timeType) + // For backward compatibility before struct level validation tags were supported + // as there were a number of projects relying on `required` not failing on non-pointer + // structs. Since it's basically nonsensical to use `required` with a non-pointer struct + // are explicitly skipping the required validation for it. This WILL be removed in the + // next major version. + if isNestedStruct && !v.v.requiredStructEnabled && ct != nil && ct.tag == requiredTag { + ct = ct.next + } } typ = current.Type() OUTER: for { - if ct == nil { + if ct == nil || !ct.hasTag || (isNestedStruct && len(cf.name) == 0) { + // isNestedStruct check here + if isNestedStruct { + // if len == 0 then validating using 'Var' or 'VarWithValue' + // Var - doesn't make much sense to do it that way, should call 'Struct', but no harm... + // VarWithField - this allows for validating against each field within the struct against a specific value + // pretty handy in certain situations + if len(cf.name) > 0 { + ns = append(append(ns, cf.altName...), '.') + structNs = append(append(structNs, cf.name...), '.') + } + + v.validateStruct(ctx, parent, current, typ, ns, structNs, ct) + } return } switch ct.typeof { + case typeNoStructLevel: + return + + case typeStructOnly: + if isNestedStruct { + // if len == 0 then validating using 'Var' or 'VarWithValue' + // Var - doesn't make much sense to do it that way, should call 'Struct', but no harm... + // VarWithField - this allows for validating against each field within the struct against a specific value + // pretty handy in certain situations + if len(cf.name) > 0 { + ns = append(append(ns, cf.altName...), '.') + structNs = append(append(structNs, cf.name...), '.') + } + + v.validateStruct(ctx, parent, current, typ, ns, structNs, ct) + } + return case typeOmitEmpty: @@ -256,6 +238,26 @@ OUTER: ct = ct.next continue + case typeOmitNil: + v.slflParent = parent + v.flField = current + v.cf = cf + v.ct = ct + + switch field := v.Field(); field.Kind() { + case reflect.Slice, reflect.Map, reflect.Ptr, reflect.Interface, reflect.Chan, reflect.Func: + if field.IsNil() { + return + } + default: + if v.fldIsPointer && field.Interface() == nil { + return + } + } + + ct = ct.next + continue + case typeEndKeys: return @@ -366,7 +368,7 @@ OUTER: ct = ct.next if ct == nil { - return + continue OUTER } if ct.typeof != typeOr { @@ -409,7 +411,7 @@ OUTER: structNs: v.str2, fieldLen: uint8(len(cf.altName)), structfieldLen: uint8(len(cf.name)), - value: current.Interface(), + value: getValue(current), param: ct.param, kind: kind, typ: typ, @@ -429,7 +431,7 @@ OUTER: structNs: v.str2, fieldLen: uint8(len(cf.altName)), structfieldLen: uint8(len(cf.name)), - value: current.Interface(), + value: getValue(current), param: ct.param, kind: kind, typ: typ, @@ -469,7 +471,7 @@ OUTER: structNs: v.str2, fieldLen: uint8(len(cf.altName)), structfieldLen: uint8(len(cf.name)), - value: current.Interface(), + value: getValue(current), param: ct.param, kind: kind, typ: typ, @@ -483,3 +485,26 @@ OUTER: } } + +func getValue(val reflect.Value) interface{} { + if val.CanInterface() { + return val.Interface() + } + + if val.CanAddr() { + return reflect.NewAt(val.Type(), unsafe.Pointer(val.UnsafeAddr())).Elem().Interface() + } + + switch val.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return val.Int() + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return val.Uint() + case reflect.Complex64, reflect.Complex128: + return val.Complex() + case reflect.Float32, reflect.Float64: + return val.Float() + default: + return val.String() + } +} diff --git a/vendor/github.com/go-playground/validator/v10/validator_instance.go b/vendor/github.com/go-playground/validator/v10/validator_instance.go index d2ee8fe38b..1a345138ed 100644 --- a/vendor/github.com/go-playground/validator/v10/validator_instance.go +++ b/vendor/github.com/go-playground/validator/v10/validator_instance.go @@ -22,6 +22,7 @@ const ( structOnlyTag = "structonly" noStructLevelTag = "nostructlevel" omitempty = "omitempty" + omitnil = "omitnil" isdefault = "isdefault" requiredWithoutAllTag = "required_without_all" requiredWithoutTag = "required_without" @@ -53,6 +54,8 @@ var ( timeDurationType = reflect.TypeOf(time.Duration(0)) timeType = reflect.TypeOf(time.Time{}) + byteSliceType = reflect.TypeOf([]byte{}) + defaultCField = &cField{namesEqual: true} ) @@ -77,19 +80,21 @@ type internalValidationFuncWrapper struct { // Validate contains the validator settings and cache type Validate struct { - tagName string - pool *sync.Pool - hasCustomFuncs bool - hasTagNameFunc bool - tagNameFunc TagNameFunc - structLevelFuncs map[reflect.Type]StructLevelFuncCtx - customFuncs map[reflect.Type]CustomTypeFunc - aliases map[string]string - validations map[string]internalValidationFuncWrapper - transTagFunc map[ut.Translator]map[string]TranslationFunc // map[]map[]TranslationFunc - rules map[reflect.Type]map[string]string - tagCache *tagCache - structCache *structCache + tagName string + pool *sync.Pool + tagNameFunc TagNameFunc + structLevelFuncs map[reflect.Type]StructLevelFuncCtx + customFuncs map[reflect.Type]CustomTypeFunc + aliases map[string]string + validations map[string]internalValidationFuncWrapper + transTagFunc map[ut.Translator]map[string]TranslationFunc // map[]map[]TranslationFunc + rules map[reflect.Type]map[string]string + tagCache *tagCache + structCache *structCache + hasCustomFuncs bool + hasTagNameFunc bool + requiredStructEnabled bool + privateFieldValidation bool } // New returns a new instance of 'validate' with sane defaults. @@ -97,7 +102,7 @@ type Validate struct { // It caches information about your struct and validations, // in essence only parsing your validation tags once per struct type. // Using multiple instances neglects the benefit of caching. -func New() *Validate { +func New(options ...Option) *Validate { tc := new(tagCache) tc.m.Store(make(map[string]*cTag)) @@ -144,6 +149,9 @@ func New() *Validate { }, } + for _, o := range options { + o(v) + } return v } diff --git a/vendor/github.com/leodido/go-urn/.gitignore b/vendor/github.com/leodido/go-urn/.gitignore index 89d4bc55dc..427454f8f1 100644 --- a/vendor/github.com/leodido/go-urn/.gitignore +++ b/vendor/github.com/leodido/go-urn/.gitignore @@ -9,4 +9,5 @@ *.txt vendor/ -/removecomments \ No newline at end of file +/removecomments +/snake2camel \ No newline at end of file diff --git a/vendor/github.com/leodido/go-urn/README.md b/vendor/github.com/leodido/go-urn/README.md index 731eecbb5f..619475bfbb 100644 --- a/vendor/github.com/leodido/go-urn/README.md +++ b/vendor/github.com/leodido/go-urn/README.md @@ -2,21 +2,34 @@ **A parser for URNs**. -> As seen on [RFC 2141](https://tools.ietf.org/html/rfc2141#ref-1). +> As seen on [RFC 2141](https://datatracker.ietf.org/doc/html/rfc2141), [RFC 7643](https://datatracker.ietf.org/doc/html/rfc7643#section-10), and on [RFC 8141](https://datatracker.ietf.org/doc/html/rfc8141). [API documentation](https://godoc.org/github.com/leodido/go-urn). +Starting with version 1.3 this library also supports [RFC 7643 SCIM URNs](https://datatracker.ietf.org/doc/html/rfc7643#section-10). + +Starting with version 1.4 this library also supports [RFC 8141 URNs (2017)](https://datatracker.ietf.org/doc/html/rfc8141). + ## Installation ``` go get github.com/leodido/go-urn ``` +## Features + +1. RFC 2141 URNs parsing (default) +2. RFC 8141 URNs parsing (supersedes RFC 2141) +3. RFC 7643 SCIM URNs parsing +4. Normalization as per RFCs +5. Lexical equivalence as per RFCs +6. Precise, fine-grained errors + ## Performances This implementation results to be really fast. -Usually below ½ microsecond on my machine[1](#mymachine). +Usually below 400 ns on my machine[1](#mymachine). Notice it also performs, while parsing: @@ -24,35 +37,64 @@ Notice it also performs, while parsing: 2. specific-string normalization ``` -ok/00/urn:a:b______________________________________/-4 20000000 265 ns/op 182 B/op 6 allocs/op -ok/01/URN:foo:a123,456_____________________________/-4 30000000 296 ns/op 200 B/op 6 allocs/op -ok/02/urn:foo:a123%2c456___________________________/-4 20000000 331 ns/op 208 B/op 6 allocs/op -ok/03/urn:ietf:params:scim:schemas:core:2.0:User___/-4 20000000 430 ns/op 280 B/op 6 allocs/op -ok/04/urn:ietf:params:scim:schemas:extension:enterp/-4 20000000 411 ns/op 312 B/op 6 allocs/op -ok/05/urn:ietf:params:scim:schemas:extension:enterp/-4 20000000 472 ns/op 344 B/op 6 allocs/op -ok/06/urn:burnout:nss______________________________/-4 30000000 257 ns/op 192 B/op 6 allocs/op -ok/07/urn:abcdefghilmnopqrstuvzabcdefghilm:x_______/-4 20000000 375 ns/op 213 B/op 6 allocs/op -ok/08/urn:urnurnurn:urn____________________________/-4 30000000 265 ns/op 197 B/op 6 allocs/op -ok/09/urn:ciao:@!=%2c(xyz)+a,b.*@g=$_'_____________/-4 20000000 307 ns/op 248 B/op 6 allocs/op -ok/10/URN:x:abc%1dz%2f%3az_________________________/-4 30000000 259 ns/op 212 B/op 6 allocs/op -no/11/URN:-xxx:x___________________________________/-4 20000000 445 ns/op 320 B/op 6 allocs/op -no/12/urn::colon:nss_______________________________/-4 20000000 461 ns/op 320 B/op 6 allocs/op -no/13/urn:abcdefghilmnopqrstuvzabcdefghilmn:specifi/-4 10000000 660 ns/op 320 B/op 6 allocs/op -no/14/URN:a!?:x____________________________________/-4 20000000 507 ns/op 320 B/op 6 allocs/op -no/15/urn:urn:NSS__________________________________/-4 20000000 429 ns/op 288 B/op 6 allocs/op -no/16/urn:white_space:NSS__________________________/-4 20000000 482 ns/op 320 B/op 6 allocs/op -no/17/urn:concat:no_spaces_________________________/-4 20000000 539 ns/op 328 B/op 7 allocs/op -no/18/urn:a:/______________________________________/-4 20000000 470 ns/op 320 B/op 7 allocs/op -no/19/urn:UrN:NSS__________________________________/-4 20000000 399 ns/op 288 B/op 6 allocs/op +ok/00/urn:a:b______________________________________/-10 51372006 109.0 ns/op 275 B/op 3 allocs/op +ok/01/URN:foo:a123,456_____________________________/-10 36024072 160.8 ns/op 296 B/op 6 allocs/op +ok/02/urn:foo:a123%2C456___________________________/-10 31901007 188.4 ns/op 320 B/op 7 allocs/op +ok/03/urn:ietf:params:scim:schemas:core:2.0:User___/-10 22736756 266.6 ns/op 376 B/op 6 allocs/op +ok/04/urn:ietf:params:scim:schemas:extension:enterp/-10 18291859 335.2 ns/op 408 B/op 6 allocs/op +ok/05/urn:ietf:params:scim:schemas:extension:enterp/-10 15283087 379.4 ns/op 440 B/op 6 allocs/op +ok/06/urn:burnout:nss______________________________/-10 39407593 155.1 ns/op 288 B/op 6 allocs/op +ok/07/urn:abcdefghilmnopqrstuvzabcdefghilm:x_______/-10 27832718 211.4 ns/op 307 B/op 4 allocs/op +ok/08/urn:urnurnurn:urn____________________________/-10 33269596 168.1 ns/op 293 B/op 6 allocs/op +ok/09/urn:ciao:!!*_________________________________/-10 41100675 148.8 ns/op 288 B/op 6 allocs/op +ok/10/urn:ciao:=@__________________________________/-10 37214253 149.7 ns/op 284 B/op 6 allocs/op +ok/11/urn:ciao:@!=%2C(xyz)+a,b.*@g=$_'_____________/-10 26534240 229.8 ns/op 336 B/op 7 allocs/op +ok/12/URN:x:abc%1Dz%2F%3az_________________________/-10 28166396 211.8 ns/op 336 B/op 7 allocs/op +no/13/URN:---xxx:x_________________________________/-10 23635159 255.6 ns/op 419 B/op 5 allocs/op +no/14/urn::colon:nss_______________________________/-10 23594779 258.4 ns/op 419 B/op 5 allocs/op +no/15/URN:@,:x_____________________________________/-10 23742535 261.5 ns/op 419 B/op 5 allocs/op +no/16/URN:URN:NSS__________________________________/-10 27432714 223.3 ns/op 371 B/op 5 allocs/op +no/17/urn:UrN:NSS__________________________________/-10 26922117 224.9 ns/op 371 B/op 5 allocs/op +no/18/urn:a:%______________________________________/-10 24926733 224.6 ns/op 371 B/op 5 allocs/op +no/19/urn:urn:NSS__________________________________/-10 27652641 220.7 ns/op 371 B/op 5 allocs/op ``` ---- - -* [1]: Intel Core i7-7600U CPU @ 2.80GHz +* [1]: Apple M1 Pro ---- ## Example + +For more examples take a look at the [examples file](examples_test.go). + + +```go +package main + +import ( + "fmt" + "github.com/leodido/go-urn" +) + +func main() { + var uid = "URN:foo:a123,456" + + // Parse the input string as a RFC 2141 URN only + u, e := urn.NewMachine().Parse(uid) + if e != nil { + fmt.Errorf(err) + + return + } + + fmt.Println(u.ID) + fmt.Println(u.SS) + + // Output: + // foo + // a123,456 +} +``` + ```go package main @@ -64,6 +106,7 @@ import ( func main() { var uid = "URN:foo:a123,456" + // Parse the input string as a RFC 2141 URN only u, ok := urn.Parse([]byte(uid)) if !ok { panic("error parsing urn") @@ -78,4 +121,33 @@ func main() { } ``` -[![Analytics](https://ga-beacon.appspot.com/UA-49657176-1/go-urn?flat)](https://github.com/igrigorik/ga-beacon) \ No newline at end of file +```go +package main + +import ( + "fmt" + "github.com/leodido/go-urn" +) + +func main() { + input := "urn:ietf:params:scim:api:messages:2.0:ListResponse" + + // Parsing the input string as a RFC 7643 SCIM URN + u, ok := urn.Parse([]byte(input), urn.WithParsingMode(urn.RFC7643Only)) + if !ok { + panic("error parsing urn") + } + + fmt.Println(u.IsSCIM()) + scim := u.SCIM() + fmt.Println(scim.Type.String()) + fmt.Println(scim.Name) + fmt.Println(scim.Other) + + // Output: + // true + // api + // messages + // 2.0:ListResponse +} +``` \ No newline at end of file diff --git a/vendor/github.com/leodido/go-urn/kind.go b/vendor/github.com/leodido/go-urn/kind.go new file mode 100644 index 0000000000..f5e140f0a4 --- /dev/null +++ b/vendor/github.com/leodido/go-urn/kind.go @@ -0,0 +1,10 @@ +package urn + +type Kind int + +const ( + NONE Kind = iota + RFC2141 + RFC7643 + RFC8141 +) diff --git a/vendor/github.com/leodido/go-urn/machine.go b/vendor/github.com/leodido/go-urn/machine.go index fe5a0cc861..aec1ba69cb 100644 --- a/vendor/github.com/leodido/go-urn/machine.go +++ b/vendor/github.com/leodido/go-urn/machine.go @@ -2,27 +2,98 @@ package urn import ( "fmt" + + scimschema "github.com/leodido/go-urn/scim/schema" ) var ( - errPrefix = "expecting the prefix to be the \"urn\" string (whatever case) [col %d]" - errIdentifier = "expecting the identifier to be string (1..31 alnum chars, also containing dashes but not at its start) [col %d]" - errSpecificString = "expecting the specific string to be a string containing alnum, hex, or others ([()+,-.:=@;$_!*']) chars [col %d]" - errNoUrnWithinID = "expecting the identifier to not contain the \"urn\" reserved string [col %d]" - errHex = "expecting the specific string hex chars to be well-formed (%%alnum{2}) [col %d]" - errParse = "parsing error [col %d]" + errPrefix = "expecting the prefix to be the \"urn\" string (whatever case) [col %d]" + errIdentifier = "expecting the identifier to be string (1..31 alnum chars, also containing dashes but not at its beginning) [col %d]" + errSpecificString = "expecting the specific string to be a string containing alnum, hex, or others ([()+,-.:=@;$_!*']) chars [col %d]" + errNoUrnWithinID = "expecting the identifier to not contain the \"urn\" reserved string [col %d]" + errHex = "expecting the percent encoded chars to be well-formed (%%alnum{2}) [col %d]" + errSCIMNamespace = "expecing the SCIM namespace identifier (ietf:params:scim) [col %d]" + errSCIMType = "expecting a correct SCIM type (schemas, api, param) [col %d]" + errSCIMName = "expecting one or more alnum char in the SCIM name part [col %d]" + errSCIMOther = "expecting a well-formed other SCIM part [col %d]" + errSCIMOtherIncomplete = "expecting a not empty SCIM other part after colon [col %d]" + err8141InformalID = "informal URN namespace must be in the form urn-[1-9][0-9] [col %d]" + err8141SpecificString = "expecting the specific string to contain alnum, hex, or others ([~&()+,-.:=@;$_!*'] or [/?] not in first position) chars [col %d]" + err8141Identifier = "expecting the indentifier to be a string with (length 2 to 32 chars) containing alnum (or dashes) not starting or ending with a dash [col %d]" + err8141RComponentStart = "expecting only one r-component (starting with the ?+ sequence) [col %d]" + err8141QComponentStart = "expecting only one q-component (starting with the ?= sequence) [col %d]" + err8141MalformedRComp = "expecting a non-empty r-component containing alnum, hex, or others ([~&()+,-.:=@;$_!*'] or [/?] but not at its beginning) [col %d]" + err8141MalformedQComp = "expecting a non-empty q-component containing alnum, hex, or others ([~&()+,-.:=@;$_!*'] or [/?] but not at its beginning) [col %d]" ) +var _toStateActions []byte = []byte{ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 33, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, +} + +var _eofActions []byte = []byte{ + 0, 1, 1, 1, 1, 4, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 8, 9, + 9, 4, 4, 11, 1, 1, 1, 1, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 14, 14, 14, 14, 16, 18, 20, + 20, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 1, 1, 1, 1, 21, + 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, + 23, 24, 24, 25, 25, 0, 26, 28, + 28, 29, 29, 30, 30, 26, 26, 31, + 31, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 21, + 21, 22, 22, 22, 34, 34, 35, 37, + 37, 38, 40, 41, 41, 38, 42, 42, + 42, 44, 42, 48, 48, 48, 50, 44, + 50, 0, +} const start int = 1 -const firstFinal int = 44 +const firstFinal int = 172 -const enFail int = 46 +const enScimOnly int = 44 +const enRfc8141Only int = 83 +const enFail int = 193 const enMain int = 1 // Machine is the interface representing the FSM type Machine interface { Error() error Parse(input []byte) (*URN, error) + WithParsingMode(ParsingMode) } type machine struct { @@ -30,12 +101,24 @@ type machine struct { cs int p, pe, eof, pb int err error - tolower []int + startParsingAt int + parsingMode ParsingMode + parsingModeSet bool } // NewMachine creates a new FSM able to parse RFC 2141 strings. -func NewMachine() Machine { - m := &machine{} +func NewMachine(options ...Option) Machine { + m := &machine{ + parsingModeSet: false, + } + + for _, o := range options { + o(m) + } + // Set default parsing mode + if !m.parsingModeSet { + m.WithParsingMode(DefaultParsingMode) + } return m } @@ -51,7 +134,7 @@ func (m *machine) text() []byte { return m.data[m.pb:m.p] } -// Parse parses the input byte array as a RFC 2141 string. +// Parse parses the input byte array as a RFC 2141 or RFC7643 string. func (m *machine) Parse(input []byte) (*URN, error) { m.data = input m.p = 0 @@ -59,1622 +142,4881 @@ func (m *machine) Parse(input []byte) (*URN, error) { m.pe = len(input) m.eof = len(input) m.err = nil - m.tolower = []int{} - output := &URN{} - - { - m.cs = start + m.cs = m.startParsingAt + output := &URN{ + tolower: []int{}, } - { if (m.p) == (m.pe) { goto _testEof } + if m.cs == 0 { + goto _out + } + _resume: switch m.cs { case 1: - goto stCase1 + switch (m.data)[(m.p)] { + case 85: + goto tr1 + case 117: + goto tr1 + } + goto tr0 case 0: - goto stCase0 + goto _out case 2: - goto stCase2 + switch (m.data)[(m.p)] { + case 82: + goto tr2 + case 114: + goto tr2 + } + goto tr0 case 3: - goto stCase3 + switch (m.data)[(m.p)] { + case 78: + goto tr3 + case 110: + goto tr3 + } + goto tr0 case 4: - goto stCase4 + if (m.data)[(m.p)] == 58 { + goto tr4 + } + goto tr0 case 5: - goto stCase5 + switch (m.data)[(m.p)] { + case 85: + goto tr7 + case 117: + goto tr7 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr6 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr6 + } + default: + goto tr6 + } + goto tr5 case 6: - goto stCase6 + switch (m.data)[(m.p)] { + case 45: + goto tr9 + case 58: + goto tr10 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr9 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr9 + } + default: + goto tr9 + } + goto tr8 case 7: - goto stCase7 + switch (m.data)[(m.p)] { + case 45: + goto tr11 + case 58: + goto tr10 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr11 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr11 + } + default: + goto tr11 + } + goto tr8 case 8: - goto stCase8 + switch (m.data)[(m.p)] { + case 45: + goto tr12 + case 58: + goto tr10 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr12 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr12 + } + default: + goto tr12 + } + goto tr8 case 9: - goto stCase9 + switch (m.data)[(m.p)] { + case 45: + goto tr13 + case 58: + goto tr10 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr13 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr13 + } + default: + goto tr13 + } + goto tr8 case 10: - goto stCase10 + switch (m.data)[(m.p)] { + case 45: + goto tr14 + case 58: + goto tr10 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr14 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr14 + } + default: + goto tr14 + } + goto tr8 case 11: - goto stCase11 + switch (m.data)[(m.p)] { + case 45: + goto tr15 + case 58: + goto tr10 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr15 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr15 + } + default: + goto tr15 + } + goto tr8 case 12: - goto stCase12 + switch (m.data)[(m.p)] { + case 45: + goto tr16 + case 58: + goto tr10 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr16 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr16 + } + default: + goto tr16 + } + goto tr8 case 13: - goto stCase13 + switch (m.data)[(m.p)] { + case 45: + goto tr17 + case 58: + goto tr10 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr17 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr17 + } + default: + goto tr17 + } + goto tr8 case 14: - goto stCase14 + switch (m.data)[(m.p)] { + case 45: + goto tr18 + case 58: + goto tr10 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr18 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr18 + } + default: + goto tr18 + } + goto tr8 case 15: - goto stCase15 + switch (m.data)[(m.p)] { + case 45: + goto tr19 + case 58: + goto tr10 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr19 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr19 + } + default: + goto tr19 + } + goto tr8 case 16: - goto stCase16 + switch (m.data)[(m.p)] { + case 45: + goto tr20 + case 58: + goto tr10 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr20 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr20 + } + default: + goto tr20 + } + goto tr8 case 17: - goto stCase17 + switch (m.data)[(m.p)] { + case 45: + goto tr21 + case 58: + goto tr10 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr21 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr21 + } + default: + goto tr21 + } + goto tr8 case 18: - goto stCase18 + switch (m.data)[(m.p)] { + case 45: + goto tr22 + case 58: + goto tr10 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr22 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr22 + } + default: + goto tr22 + } + goto tr8 case 19: - goto stCase19 + switch (m.data)[(m.p)] { + case 45: + goto tr23 + case 58: + goto tr10 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr23 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr23 + } + default: + goto tr23 + } + goto tr8 case 20: - goto stCase20 + switch (m.data)[(m.p)] { + case 45: + goto tr24 + case 58: + goto tr10 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr24 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr24 + } + default: + goto tr24 + } + goto tr8 case 21: - goto stCase21 + switch (m.data)[(m.p)] { + case 45: + goto tr25 + case 58: + goto tr10 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr25 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr25 + } + default: + goto tr25 + } + goto tr8 case 22: - goto stCase22 + switch (m.data)[(m.p)] { + case 45: + goto tr26 + case 58: + goto tr10 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr26 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr26 + } + default: + goto tr26 + } + goto tr8 case 23: - goto stCase23 + switch (m.data)[(m.p)] { + case 45: + goto tr27 + case 58: + goto tr10 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr27 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr27 + } + default: + goto tr27 + } + goto tr8 case 24: - goto stCase24 + switch (m.data)[(m.p)] { + case 45: + goto tr28 + case 58: + goto tr10 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr28 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr28 + } + default: + goto tr28 + } + goto tr8 case 25: - goto stCase25 + switch (m.data)[(m.p)] { + case 45: + goto tr29 + case 58: + goto tr10 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr29 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr29 + } + default: + goto tr29 + } + goto tr8 case 26: - goto stCase26 + switch (m.data)[(m.p)] { + case 45: + goto tr30 + case 58: + goto tr10 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr30 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr30 + } + default: + goto tr30 + } + goto tr8 case 27: - goto stCase27 + switch (m.data)[(m.p)] { + case 45: + goto tr31 + case 58: + goto tr10 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr31 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr31 + } + default: + goto tr31 + } + goto tr8 case 28: - goto stCase28 + switch (m.data)[(m.p)] { + case 45: + goto tr32 + case 58: + goto tr10 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr32 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr32 + } + default: + goto tr32 + } + goto tr8 case 29: - goto stCase29 + switch (m.data)[(m.p)] { + case 45: + goto tr33 + case 58: + goto tr10 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr33 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr33 + } + default: + goto tr33 + } + goto tr8 case 30: - goto stCase30 + switch (m.data)[(m.p)] { + case 45: + goto tr34 + case 58: + goto tr10 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr34 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr34 + } + default: + goto tr34 + } + goto tr8 case 31: - goto stCase31 + switch (m.data)[(m.p)] { + case 45: + goto tr35 + case 58: + goto tr10 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr35 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr35 + } + default: + goto tr35 + } + goto tr8 case 32: - goto stCase32 + switch (m.data)[(m.p)] { + case 45: + goto tr36 + case 58: + goto tr10 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr36 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr36 + } + default: + goto tr36 + } + goto tr8 case 33: - goto stCase33 + switch (m.data)[(m.p)] { + case 45: + goto tr37 + case 58: + goto tr10 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr37 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr37 + } + default: + goto tr37 + } + goto tr8 case 34: - goto stCase34 - case 35: - goto stCase35 - case 36: - goto stCase36 - case 37: - goto stCase37 - case 38: - goto stCase38 - case 44: - goto stCase44 - case 39: - goto stCase39 - case 40: - goto stCase40 - case 45: - goto stCase45 - case 41: - goto stCase41 - case 42: - goto stCase42 - case 43: - goto stCase43 - case 46: - goto stCase46 - } - goto stOut - stCase1: - switch (m.data)[(m.p)] { - case 85: - goto tr1 - case 117: - goto tr1 - } - goto tr0 - tr0: - - m.err = fmt.Errorf(errParse, m.p) - (m.p)-- - - { - goto st46 - } - - goto st0 - tr3: - - m.err = fmt.Errorf(errPrefix, m.p) - (m.p)-- - - { - goto st46 - } - - m.err = fmt.Errorf(errParse, m.p) - (m.p)-- - - { - goto st46 - } - - goto st0 - tr6: - - m.err = fmt.Errorf(errIdentifier, m.p) - (m.p)-- - - { - goto st46 - } - - m.err = fmt.Errorf(errParse, m.p) - (m.p)-- - - { - goto st46 - } - - goto st0 - tr41: - - m.err = fmt.Errorf(errSpecificString, m.p) - (m.p)-- - - { - goto st46 - } - - m.err = fmt.Errorf(errParse, m.p) - (m.p)-- - - { - goto st46 - } - - goto st0 - tr44: - - m.err = fmt.Errorf(errHex, m.p) - (m.p)-- - - { - goto st46 - } - - m.err = fmt.Errorf(errSpecificString, m.p) - (m.p)-- - - { - goto st46 - } - - m.err = fmt.Errorf(errParse, m.p) - (m.p)-- - - { - goto st46 - } - - goto st0 - tr50: - - m.err = fmt.Errorf(errPrefix, m.p) - (m.p)-- - - { - goto st46 - } - - m.err = fmt.Errorf(errIdentifier, m.p) - (m.p)-- - - { - goto st46 - } - - m.err = fmt.Errorf(errParse, m.p) - (m.p)-- - - { - goto st46 - } - - goto st0 - tr52: - - m.err = fmt.Errorf(errNoUrnWithinID, m.p) - (m.p)-- - - { - goto st46 - } - - m.err = fmt.Errorf(errIdentifier, m.p) - (m.p)-- - - { - goto st46 - } - - m.err = fmt.Errorf(errParse, m.p) - (m.p)-- - - { - goto st46 - } - - goto st0 - stCase0: - st0: - m.cs = 0 - goto _out - tr1: - - m.pb = m.p - - goto st2 - st2: - if (m.p)++; (m.p) == (m.pe) { - goto _testEof2 - } - stCase2: - switch (m.data)[(m.p)] { - case 82: - goto st3 - case 114: - goto st3 - } - goto tr0 - st3: - if (m.p)++; (m.p) == (m.pe) { - goto _testEof3 - } - stCase3: - switch (m.data)[(m.p)] { - case 78: - goto st4 - case 110: - goto st4 - } - goto tr3 - st4: - if (m.p)++; (m.p) == (m.pe) { - goto _testEof4 - } - stCase4: - if (m.data)[(m.p)] == 58 { - goto tr5 - } - goto tr0 - tr5: - - output.prefix = string(m.text()) - - goto st5 - st5: - if (m.p)++; (m.p) == (m.pe) { - goto _testEof5 - } - stCase5: - switch (m.data)[(m.p)] { - case 85: - goto tr8 - case 117: - goto tr8 - } - switch { - case (m.data)[(m.p)] < 65: - if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { - goto tr7 + switch (m.data)[(m.p)] { + case 45: + goto tr38 + case 58: + goto tr10 } - case (m.data)[(m.p)] > 90: - if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { - goto tr7 + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr38 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr38 + } + default: + goto tr38 } - default: - goto tr7 - } - goto tr6 - tr7: - - m.pb = m.p - - goto st6 - st6: - if (m.p)++; (m.p) == (m.pe) { - goto _testEof6 - } - stCase6: - switch (m.data)[(m.p)] { - case 45: - goto st7 - case 58: - goto tr10 - } - switch { - case (m.data)[(m.p)] < 65: - if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { - goto st7 + goto tr8 + case 35: + switch (m.data)[(m.p)] { + case 45: + goto tr39 + case 58: + goto tr10 } - case (m.data)[(m.p)] > 90: - if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { - goto st7 + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr39 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr39 + } + default: + goto tr39 } - default: - goto st7 - } - goto tr6 - st7: - if (m.p)++; (m.p) == (m.pe) { - goto _testEof7 - } - stCase7: - switch (m.data)[(m.p)] { - case 45: - goto st8 - case 58: - goto tr10 - } - switch { - case (m.data)[(m.p)] < 65: - if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { - goto st8 + goto tr8 + case 36: + switch (m.data)[(m.p)] { + case 45: + goto tr40 + case 58: + goto tr10 } - case (m.data)[(m.p)] > 90: - if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { - goto st8 + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr40 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr40 + } + default: + goto tr40 } - default: - goto st8 - } - goto tr6 - st8: - if (m.p)++; (m.p) == (m.pe) { - goto _testEof8 - } - stCase8: - switch (m.data)[(m.p)] { - case 45: - goto st9 - case 58: - goto tr10 - } - switch { - case (m.data)[(m.p)] < 65: - if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { - goto st9 + goto tr8 + case 37: + if (m.data)[(m.p)] == 58 { + goto tr10 } - case (m.data)[(m.p)] > 90: - if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { - goto st9 + goto tr8 + case 38: + switch (m.data)[(m.p)] { + case 33: + goto tr42 + case 36: + goto tr42 + case 37: + goto tr43 + case 61: + goto tr42 + case 95: + goto tr42 } - default: - goto st9 - } - goto tr6 - st9: - if (m.p)++; (m.p) == (m.pe) { - goto _testEof9 - } - stCase9: - switch (m.data)[(m.p)] { - case 45: - goto st10 - case 58: - goto tr10 - } - switch { - case (m.data)[(m.p)] < 65: - if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { - goto st10 + switch { + case (m.data)[(m.p)] < 48: + if 39 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 46 { + goto tr42 + } + case (m.data)[(m.p)] > 59: + switch { + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr42 + } + case (m.data)[(m.p)] >= 64: + goto tr42 + } + default: + goto tr42 } - case (m.data)[(m.p)] > 90: - if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { - goto st10 + goto tr41 + case 172: + switch (m.data)[(m.p)] { + case 33: + goto tr212 + case 36: + goto tr212 + case 37: + goto tr213 + case 61: + goto tr212 + case 95: + goto tr212 } - default: - goto st10 - } - goto tr6 - st10: - if (m.p)++; (m.p) == (m.pe) { - goto _testEof10 - } - stCase10: - switch (m.data)[(m.p)] { - case 45: - goto st11 - case 58: - goto tr10 - } - switch { - case (m.data)[(m.p)] < 65: - if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { - goto st11 + switch { + case (m.data)[(m.p)] < 48: + if 39 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 46 { + goto tr212 + } + case (m.data)[(m.p)] > 59: + switch { + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr212 + } + case (m.data)[(m.p)] >= 64: + goto tr212 + } + default: + goto tr212 } - case (m.data)[(m.p)] > 90: - if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { - goto st11 + goto tr41 + case 39: + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr45 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr45 + } + default: + goto tr46 } - default: - goto st11 - } - goto tr6 - st11: - if (m.p)++; (m.p) == (m.pe) { - goto _testEof11 - } - stCase11: - switch (m.data)[(m.p)] { - case 45: - goto st12 - case 58: - goto tr10 - } - switch { - case (m.data)[(m.p)] < 65: - if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { - goto st12 + goto tr44 + case 40: + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr47 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr47 + } + default: + goto tr48 } - case (m.data)[(m.p)] > 90: - if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { - goto st12 + goto tr44 + case 173: + switch (m.data)[(m.p)] { + case 33: + goto tr212 + case 36: + goto tr212 + case 37: + goto tr213 + case 61: + goto tr212 + case 95: + goto tr212 } - default: - goto st12 - } - goto tr6 - st12: - if (m.p)++; (m.p) == (m.pe) { - goto _testEof12 - } - stCase12: - switch (m.data)[(m.p)] { - case 45: - goto st13 - case 58: - goto tr10 - } - switch { - case (m.data)[(m.p)] < 65: - if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { - goto st13 + switch { + case (m.data)[(m.p)] < 48: + if 39 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 46 { + goto tr212 + } + case (m.data)[(m.p)] > 59: + switch { + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr212 + } + case (m.data)[(m.p)] >= 64: + goto tr212 + } + default: + goto tr212 } - case (m.data)[(m.p)] > 90: - if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { - goto st13 + goto tr44 + case 41: + switch (m.data)[(m.p)] { + case 45: + goto tr9 + case 58: + goto tr10 + case 82: + goto tr49 + case 114: + goto tr49 } - default: - goto st13 - } - goto tr6 - st13: - if (m.p)++; (m.p) == (m.pe) { - goto _testEof13 - } - stCase13: - switch (m.data)[(m.p)] { - case 45: - goto st14 - case 58: - goto tr10 - } - switch { - case (m.data)[(m.p)] < 65: - if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { - goto st14 + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr9 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr9 + } + default: + goto tr9 } - case (m.data)[(m.p)] > 90: - if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { - goto st14 + goto tr5 + case 42: + switch (m.data)[(m.p)] { + case 45: + goto tr11 + case 58: + goto tr10 + case 78: + goto tr50 + case 110: + goto tr50 } - default: - goto st14 - } - goto tr6 - st14: - if (m.p)++; (m.p) == (m.pe) { - goto _testEof14 - } - stCase14: - switch (m.data)[(m.p)] { - case 45: - goto st15 - case 58: - goto tr10 - } - switch { - case (m.data)[(m.p)] < 65: - if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { - goto st15 + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr11 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr11 + } + default: + goto tr11 } - case (m.data)[(m.p)] > 90: - if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { - goto st15 + goto tr5 + case 43: + if (m.data)[(m.p)] == 45 { + goto tr12 } - default: - goto st15 - } - goto tr6 - st15: - if (m.p)++; (m.p) == (m.pe) { - goto _testEof15 - } - stCase15: - switch (m.data)[(m.p)] { - case 45: - goto st16 - case 58: - goto tr10 - } - switch { - case (m.data)[(m.p)] < 65: - if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { - goto st16 + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr12 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr12 + } + default: + goto tr12 } - case (m.data)[(m.p)] > 90: - if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { - goto st16 + goto tr51 + case 44: + switch (m.data)[(m.p)] { + case 85: + goto tr52 + case 117: + goto tr52 } - default: - goto st16 - } - goto tr6 - st16: - if (m.p)++; (m.p) == (m.pe) { - goto _testEof16 - } - stCase16: - switch (m.data)[(m.p)] { + goto tr0 case 45: - goto st17 - case 58: - goto tr10 - } - switch { - case (m.data)[(m.p)] < 65: - if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { - goto st17 + switch (m.data)[(m.p)] { + case 82: + goto tr53 + case 114: + goto tr53 } - case (m.data)[(m.p)] > 90: - if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { - goto st17 + goto tr0 + case 46: + switch (m.data)[(m.p)] { + case 78: + goto tr54 + case 110: + goto tr54 } - default: - goto st17 - } - goto tr6 - st17: - if (m.p)++; (m.p) == (m.pe) { - goto _testEof17 - } - stCase17: - switch (m.data)[(m.p)] { - case 45: - goto st18 - case 58: - goto tr10 - } - switch { - case (m.data)[(m.p)] < 65: - if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { - goto st18 + goto tr0 + case 47: + if (m.data)[(m.p)] == 58 { + goto tr55 } - case (m.data)[(m.p)] > 90: - if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { - goto st18 + goto tr0 + case 48: + if (m.data)[(m.p)] == 105 { + goto tr57 } - default: - goto st18 - } - goto tr6 - st18: - if (m.p)++; (m.p) == (m.pe) { - goto _testEof18 - } - stCase18: - switch (m.data)[(m.p)] { - case 45: - goto st19 - case 58: - goto tr10 - } - switch { - case (m.data)[(m.p)] < 65: - if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { - goto st19 + goto tr56 + case 49: + if (m.data)[(m.p)] == 101 { + goto tr58 } - case (m.data)[(m.p)] > 90: - if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { - goto st19 + goto tr56 + case 50: + if (m.data)[(m.p)] == 116 { + goto tr59 } - default: - goto st19 - } - goto tr6 - st19: - if (m.p)++; (m.p) == (m.pe) { - goto _testEof19 - } - stCase19: - switch (m.data)[(m.p)] { - case 45: - goto st20 - case 58: - goto tr10 - } - switch { - case (m.data)[(m.p)] < 65: - if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { - goto st20 + goto tr56 + case 51: + if (m.data)[(m.p)] == 102 { + goto tr60 } - case (m.data)[(m.p)] > 90: - if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { - goto st20 + goto tr56 + case 52: + if (m.data)[(m.p)] == 58 { + goto tr61 } - default: - goto st20 - } - goto tr6 - st20: - if (m.p)++; (m.p) == (m.pe) { - goto _testEof20 - } - stCase20: - switch (m.data)[(m.p)] { - case 45: - goto st21 - case 58: - goto tr10 - } - switch { - case (m.data)[(m.p)] < 65: - if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { - goto st21 + goto tr56 + case 53: + if (m.data)[(m.p)] == 112 { + goto tr62 } - case (m.data)[(m.p)] > 90: - if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { - goto st21 + goto tr56 + case 54: + if (m.data)[(m.p)] == 97 { + goto tr63 } - default: - goto st21 - } - goto tr6 - st21: - if (m.p)++; (m.p) == (m.pe) { - goto _testEof21 - } - stCase21: - switch (m.data)[(m.p)] { - case 45: - goto st22 - case 58: - goto tr10 - } - switch { - case (m.data)[(m.p)] < 65: - if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { - goto st22 + goto tr56 + case 55: + if (m.data)[(m.p)] == 114 { + goto tr64 } - case (m.data)[(m.p)] > 90: - if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { - goto st22 + goto tr56 + case 56: + if (m.data)[(m.p)] == 97 { + goto tr65 } - default: - goto st22 - } - goto tr6 - st22: - if (m.p)++; (m.p) == (m.pe) { - goto _testEof22 - } - stCase22: - switch (m.data)[(m.p)] { - case 45: - goto st23 + goto tr56 + case 57: + if (m.data)[(m.p)] == 109 { + goto tr66 + } + goto tr56 case 58: - goto tr10 - } - switch { - case (m.data)[(m.p)] < 65: - if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { - goto st23 + if (m.data)[(m.p)] == 115 { + goto tr67 } - case (m.data)[(m.p)] > 90: - if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { - goto st23 + goto tr56 + case 59: + if (m.data)[(m.p)] == 58 { + goto tr68 } - default: - goto st23 - } - goto tr6 - st23: - if (m.p)++; (m.p) == (m.pe) { - goto _testEof23 - } - stCase23: - switch (m.data)[(m.p)] { - case 45: - goto st24 - case 58: - goto tr10 - } - switch { - case (m.data)[(m.p)] < 65: - if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { - goto st24 + goto tr56 + case 60: + if (m.data)[(m.p)] == 115 { + goto tr69 } - case (m.data)[(m.p)] > 90: - if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { - goto st24 + goto tr56 + case 61: + if (m.data)[(m.p)] == 99 { + goto tr70 } - default: - goto st24 - } - goto tr6 - st24: - if (m.p)++; (m.p) == (m.pe) { - goto _testEof24 - } - stCase24: - switch (m.data)[(m.p)] { - case 45: - goto st25 - case 58: - goto tr10 - } - switch { - case (m.data)[(m.p)] < 65: - if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { - goto st25 + goto tr56 + case 62: + if (m.data)[(m.p)] == 105 { + goto tr71 } - case (m.data)[(m.p)] > 90: - if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { - goto st25 + goto tr56 + case 63: + if (m.data)[(m.p)] == 109 { + goto tr72 } - default: - goto st25 - } - goto tr6 - st25: - if (m.p)++; (m.p) == (m.pe) { - goto _testEof25 - } - stCase25: - switch (m.data)[(m.p)] { - case 45: - goto st26 - case 58: - goto tr10 - } - switch { - case (m.data)[(m.p)] < 65: - if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { - goto st26 + goto tr56 + case 64: + if (m.data)[(m.p)] == 58 { + goto tr73 } - case (m.data)[(m.p)] > 90: - if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { - goto st26 + goto tr56 + case 65: + switch (m.data)[(m.p)] { + case 97: + goto tr75 + case 112: + goto tr76 + case 115: + goto tr77 } - default: - goto st26 - } - goto tr6 - st26: - if (m.p)++; (m.p) == (m.pe) { - goto _testEof26 - } - stCase26: - switch (m.data)[(m.p)] { - case 45: - goto st27 - case 58: - goto tr10 - } - switch { - case (m.data)[(m.p)] < 65: - if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { - goto st27 + goto tr74 + case 66: + if (m.data)[(m.p)] == 112 { + goto tr78 } - case (m.data)[(m.p)] > 90: - if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { - goto st27 + goto tr74 + case 67: + if (m.data)[(m.p)] == 105 { + goto tr79 } - default: - goto st27 - } - goto tr6 - st27: - if (m.p)++; (m.p) == (m.pe) { - goto _testEof27 - } - stCase27: - switch (m.data)[(m.p)] { - case 45: - goto st28 - case 58: - goto tr10 - } - switch { - case (m.data)[(m.p)] < 65: - if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { - goto st28 + goto tr74 + case 68: + if (m.data)[(m.p)] == 58 { + goto tr80 } - case (m.data)[(m.p)] > 90: - if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { - goto st28 + goto tr74 + case 69: + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr82 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr82 + } + default: + goto tr82 } - default: - goto st28 - } - goto tr6 - st28: - if (m.p)++; (m.p) == (m.pe) { - goto _testEof28 - } - stCase28: - switch (m.data)[(m.p)] { - case 45: - goto st29 - case 58: - goto tr10 - } - switch { - case (m.data)[(m.p)] < 65: - if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { - goto st29 + goto tr81 + case 174: + if (m.data)[(m.p)] == 58 { + goto tr215 } - case (m.data)[(m.p)] > 90: - if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { - goto st29 + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr214 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr214 + } + default: + goto tr214 } - default: - goto st29 - } - goto tr6 - st29: - if (m.p)++; (m.p) == (m.pe) { - goto _testEof29 - } - stCase29: - switch (m.data)[(m.p)] { - case 45: - goto st30 - case 58: - goto tr10 - } - switch { - case (m.data)[(m.p)] < 65: - if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { - goto st30 + goto tr81 + case 70: + switch (m.data)[(m.p)] { + case 33: + goto tr84 + case 36: + goto tr84 + case 37: + goto tr85 + case 61: + goto tr84 + case 95: + goto tr84 } - case (m.data)[(m.p)] > 90: - if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { - goto st30 + switch { + case (m.data)[(m.p)] < 48: + if 39 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 46 { + goto tr84 + } + case (m.data)[(m.p)] > 59: + switch { + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr84 + } + case (m.data)[(m.p)] >= 64: + goto tr84 + } + default: + goto tr84 } - default: - goto st30 - } - goto tr6 - st30: - if (m.p)++; (m.p) == (m.pe) { - goto _testEof30 - } - stCase30: - switch (m.data)[(m.p)] { - case 45: - goto st31 - case 58: - goto tr10 - } - switch { - case (m.data)[(m.p)] < 65: - if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { - goto st31 + goto tr83 + case 175: + switch (m.data)[(m.p)] { + case 33: + goto tr216 + case 36: + goto tr216 + case 37: + goto tr217 + case 61: + goto tr216 + case 95: + goto tr216 } - case (m.data)[(m.p)] > 90: - if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { - goto st31 + switch { + case (m.data)[(m.p)] < 48: + if 39 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 46 { + goto tr216 + } + case (m.data)[(m.p)] > 59: + switch { + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr216 + } + case (m.data)[(m.p)] >= 64: + goto tr216 + } + default: + goto tr216 } - default: - goto st31 - } - goto tr6 - st31: - if (m.p)++; (m.p) == (m.pe) { - goto _testEof31 - } - stCase31: - switch (m.data)[(m.p)] { - case 45: - goto st32 - case 58: - goto tr10 - } - switch { - case (m.data)[(m.p)] < 65: - if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { - goto st32 + goto tr83 + case 71: + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr87 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr87 + } + default: + goto tr88 } - case (m.data)[(m.p)] > 90: - if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { - goto st32 + goto tr86 + case 72: + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr89 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr89 + } + default: + goto tr90 } - default: - goto st32 - } - goto tr6 - st32: - if (m.p)++; (m.p) == (m.pe) { - goto _testEof32 - } - stCase32: - switch (m.data)[(m.p)] { - case 45: - goto st33 - case 58: - goto tr10 - } - switch { - case (m.data)[(m.p)] < 65: - if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { - goto st33 + goto tr86 + case 176: + switch (m.data)[(m.p)] { + case 33: + goto tr216 + case 36: + goto tr216 + case 37: + goto tr217 + case 61: + goto tr216 + case 95: + goto tr216 } - case (m.data)[(m.p)] > 90: - if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { - goto st33 + switch { + case (m.data)[(m.p)] < 48: + if 39 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 46 { + goto tr216 + } + case (m.data)[(m.p)] > 59: + switch { + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr216 + } + case (m.data)[(m.p)] >= 64: + goto tr216 + } + default: + goto tr216 } - default: - goto st33 - } - goto tr6 - st33: - if (m.p)++; (m.p) == (m.pe) { - goto _testEof33 - } - stCase33: - switch (m.data)[(m.p)] { - case 45: - goto st34 - case 58: - goto tr10 - } - switch { - case (m.data)[(m.p)] < 65: - if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { - goto st34 + goto tr86 + case 73: + if (m.data)[(m.p)] == 97 { + goto tr91 } - case (m.data)[(m.p)] > 90: - if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { - goto st34 + goto tr74 + case 74: + if (m.data)[(m.p)] == 114 { + goto tr92 } - default: - goto st34 - } - goto tr6 - st34: - if (m.p)++; (m.p) == (m.pe) { - goto _testEof34 - } - stCase34: - switch (m.data)[(m.p)] { - case 45: - goto st35 - case 58: - goto tr10 - } - switch { - case (m.data)[(m.p)] < 65: - if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { - goto st35 + goto tr74 + case 75: + if (m.data)[(m.p)] == 97 { + goto tr93 } - case (m.data)[(m.p)] > 90: - if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { - goto st35 + goto tr74 + case 76: + if (m.data)[(m.p)] == 109 { + goto tr79 } - default: - goto st35 - } - goto tr6 - st35: - if (m.p)++; (m.p) == (m.pe) { - goto _testEof35 - } - stCase35: - switch (m.data)[(m.p)] { - case 45: - goto st36 - case 58: - goto tr10 - } - switch { - case (m.data)[(m.p)] < 65: - if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { - goto st36 + goto tr74 + case 77: + if (m.data)[(m.p)] == 99 { + goto tr94 } - case (m.data)[(m.p)] > 90: - if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { - goto st36 + goto tr74 + case 78: + if (m.data)[(m.p)] == 104 { + goto tr95 } - default: - goto st36 - } - goto tr6 - st36: - if (m.p)++; (m.p) == (m.pe) { - goto _testEof36 - } - stCase36: - switch (m.data)[(m.p)] { - case 45: - goto st37 - case 58: - goto tr10 - } - switch { - case (m.data)[(m.p)] < 65: - if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { - goto st37 + goto tr74 + case 79: + if (m.data)[(m.p)] == 101 { + goto tr96 } - case (m.data)[(m.p)] > 90: - if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { - goto st37 + goto tr74 + case 80: + if (m.data)[(m.p)] == 109 { + goto tr97 } - default: - goto st37 - } - goto tr6 - st37: - if (m.p)++; (m.p) == (m.pe) { - goto _testEof37 - } - stCase37: - if (m.data)[(m.p)] == 58 { - goto tr10 - } - goto tr6 - tr10: - - output.ID = string(m.text()) - - goto st38 - st38: - if (m.p)++; (m.p) == (m.pe) { - goto _testEof38 - } - stCase38: - switch (m.data)[(m.p)] { - case 33: - goto tr42 - case 36: - goto tr42 - case 37: - goto tr43 - case 61: - goto tr42 - case 95: - goto tr42 - } - switch { - case (m.data)[(m.p)] < 48: - if 39 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 46 { - goto tr42 + goto tr74 + case 81: + if (m.data)[(m.p)] == 97 { + goto tr98 + } + goto tr74 + case 82: + if (m.data)[(m.p)] == 115 { + goto tr79 + } + goto tr74 + case 83: + switch (m.data)[(m.p)] { + case 85: + goto tr99 + case 117: + goto tr99 + } + goto tr0 + case 84: + switch (m.data)[(m.p)] { + case 82: + goto tr100 + case 114: + goto tr100 + } + goto tr0 + case 85: + switch (m.data)[(m.p)] { + case 78: + goto tr101 + case 110: + goto tr101 + } + goto tr0 + case 86: + if (m.data)[(m.p)] == 58 { + goto tr102 + } + goto tr0 + case 87: + switch (m.data)[(m.p)] { + case 85: + goto tr105 + case 117: + goto tr105 } - case (m.data)[(m.p)] > 59: switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr104 + } case (m.data)[(m.p)] > 90: if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { - goto tr42 + goto tr104 } - case (m.data)[(m.p)] >= 64: - goto tr42 + default: + goto tr104 } - default: - goto tr42 - } - goto tr41 - tr42: - - m.pb = m.p - - goto st44 - st44: - if (m.p)++; (m.p) == (m.pe) { - goto _testEof44 - } - stCase44: - switch (m.data)[(m.p)] { - case 33: - goto st44 - case 36: - goto st44 - case 37: - goto st39 - case 61: - goto st44 + goto tr103 + case 88: + if (m.data)[(m.p)] == 45 { + goto tr107 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr108 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr108 + } + default: + goto tr108 + } + goto tr106 + case 89: + if (m.data)[(m.p)] == 45 { + goto tr109 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr110 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr110 + } + default: + goto tr110 + } + goto tr106 + case 90: + if (m.data)[(m.p)] == 45 { + goto tr111 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr112 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr112 + } + default: + goto tr112 + } + goto tr106 + case 91: + if (m.data)[(m.p)] == 45 { + goto tr113 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr114 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr114 + } + default: + goto tr114 + } + goto tr106 + case 92: + if (m.data)[(m.p)] == 45 { + goto tr115 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr116 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr116 + } + default: + goto tr116 + } + goto tr106 + case 93: + if (m.data)[(m.p)] == 45 { + goto tr117 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr118 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr118 + } + default: + goto tr118 + } + goto tr106 + case 94: + if (m.data)[(m.p)] == 45 { + goto tr119 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr120 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr120 + } + default: + goto tr120 + } + goto tr106 case 95: - goto st44 - } - switch { - case (m.data)[(m.p)] < 48: - if 39 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 46 { - goto st44 + if (m.data)[(m.p)] == 45 { + goto tr121 } - case (m.data)[(m.p)] > 59: switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr122 + } case (m.data)[(m.p)] > 90: if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { - goto st44 + goto tr122 } - case (m.data)[(m.p)] >= 64: - goto st44 + default: + goto tr122 } - default: - goto st44 - } - goto tr41 - tr43: + goto tr106 + case 96: + if (m.data)[(m.p)] == 45 { + goto tr123 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr124 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr124 + } + default: + goto tr124 + } + goto tr106 + case 97: + if (m.data)[(m.p)] == 45 { + goto tr125 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr126 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr126 + } + default: + goto tr126 + } + goto tr106 + case 98: + if (m.data)[(m.p)] == 45 { + goto tr127 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr128 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr128 + } + default: + goto tr128 + } + goto tr106 + case 99: + if (m.data)[(m.p)] == 45 { + goto tr129 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr130 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr130 + } + default: + goto tr130 + } + goto tr106 + case 100: + if (m.data)[(m.p)] == 45 { + goto tr131 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr132 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr132 + } + default: + goto tr132 + } + goto tr106 + case 101: + if (m.data)[(m.p)] == 45 { + goto tr133 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr134 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr134 + } + default: + goto tr134 + } + goto tr106 + case 102: + if (m.data)[(m.p)] == 45 { + goto tr135 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr136 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr136 + } + default: + goto tr136 + } + goto tr106 + case 103: + if (m.data)[(m.p)] == 45 { + goto tr137 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr138 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr138 + } + default: + goto tr138 + } + goto tr106 + case 104: + if (m.data)[(m.p)] == 45 { + goto tr139 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr140 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr140 + } + default: + goto tr140 + } + goto tr106 + case 105: + if (m.data)[(m.p)] == 45 { + goto tr141 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr142 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr142 + } + default: + goto tr142 + } + goto tr106 + case 106: + if (m.data)[(m.p)] == 45 { + goto tr143 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr144 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr144 + } + default: + goto tr144 + } + goto tr106 + case 107: + if (m.data)[(m.p)] == 45 { + goto tr145 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr146 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr146 + } + default: + goto tr146 + } + goto tr106 + case 108: + if (m.data)[(m.p)] == 45 { + goto tr147 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr148 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr148 + } + default: + goto tr148 + } + goto tr106 + case 109: + if (m.data)[(m.p)] == 45 { + goto tr149 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr150 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr150 + } + default: + goto tr150 + } + goto tr106 + case 110: + if (m.data)[(m.p)] == 45 { + goto tr151 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr152 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr152 + } + default: + goto tr152 + } + goto tr106 + case 111: + if (m.data)[(m.p)] == 45 { + goto tr153 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr154 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr154 + } + default: + goto tr154 + } + goto tr106 + case 112: + if (m.data)[(m.p)] == 45 { + goto tr155 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr156 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr156 + } + default: + goto tr156 + } + goto tr106 + case 113: + if (m.data)[(m.p)] == 45 { + goto tr157 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr158 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr158 + } + default: + goto tr158 + } + goto tr106 + case 114: + if (m.data)[(m.p)] == 45 { + goto tr159 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr160 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr160 + } + default: + goto tr160 + } + goto tr106 + case 115: + if (m.data)[(m.p)] == 45 { + goto tr161 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr162 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr162 + } + default: + goto tr162 + } + goto tr106 + case 116: + if (m.data)[(m.p)] == 45 { + goto tr163 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr164 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr164 + } + default: + goto tr164 + } + goto tr106 + case 117: + if (m.data)[(m.p)] == 45 { + goto tr165 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr166 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr166 + } + default: + goto tr166 + } + goto tr106 + case 118: + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr167 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr167 + } + default: + goto tr167 + } + goto tr106 + case 119: + if (m.data)[(m.p)] == 58 { + goto tr168 + } + goto tr106 + case 120: + switch (m.data)[(m.p)] { + case 33: + goto tr170 + case 37: + goto tr171 + case 61: + goto tr170 + case 95: + goto tr170 + case 126: + goto tr170 + } + switch { + case (m.data)[(m.p)] < 48: + if 36 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 46 { + goto tr170 + } + case (m.data)[(m.p)] > 59: + switch { + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr170 + } + case (m.data)[(m.p)] >= 64: + goto tr170 + } + default: + goto tr170 + } + goto tr169 + case 177: + switch (m.data)[(m.p)] { + case 33: + goto tr218 + case 35: + goto tr219 + case 37: + goto tr220 + case 61: + goto tr218 + case 63: + goto tr221 + case 95: + goto tr218 + case 126: + goto tr218 + } + switch { + case (m.data)[(m.p)] < 64: + if 36 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 59 { + goto tr218 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr218 + } + default: + goto tr218 + } + goto tr169 + case 178: + switch (m.data)[(m.p)] { + case 33: + goto tr222 + case 37: + goto tr223 + case 61: + goto tr222 + case 95: + goto tr222 + case 126: + goto tr222 + } + switch { + case (m.data)[(m.p)] < 63: + if 36 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 59 { + goto tr222 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr222 + } + default: + goto tr222 + } + goto tr183 + case 179: + switch (m.data)[(m.p)] { + case 33: + goto tr224 + case 37: + goto tr225 + case 61: + goto tr224 + case 95: + goto tr224 + case 126: + goto tr224 + } + switch { + case (m.data)[(m.p)] < 63: + if 36 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 59 { + goto tr224 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr224 + } + default: + goto tr224 + } + goto tr183 + case 121: + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr173 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr173 + } + default: + goto tr174 + } + goto tr172 + case 122: + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr175 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr175 + } + default: + goto tr176 + } + goto tr172 + case 180: + switch (m.data)[(m.p)] { + case 33: + goto tr224 + case 37: + goto tr225 + case 61: + goto tr224 + case 95: + goto tr224 + case 126: + goto tr224 + } + switch { + case (m.data)[(m.p)] < 63: + if 36 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 59 { + goto tr224 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr224 + } + default: + goto tr224 + } + goto tr172 + case 123: + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr178 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr178 + } + default: + goto tr179 + } + goto tr177 + case 124: + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr180 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr180 + } + default: + goto tr181 + } + goto tr177 + case 181: + switch (m.data)[(m.p)] { + case 33: + goto tr218 + case 35: + goto tr219 + case 37: + goto tr220 + case 61: + goto tr218 + case 63: + goto tr221 + case 95: + goto tr218 + case 126: + goto tr218 + } + switch { + case (m.data)[(m.p)] < 64: + if 36 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 59 { + goto tr218 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr218 + } + default: + goto tr218 + } + goto tr177 + case 125: + switch (m.data)[(m.p)] { + case 43: + goto tr182 + case 61: + goto tr184 + } + goto tr183 + case 126: + switch (m.data)[(m.p)] { + case 33: + goto tr186 + case 37: + goto tr187 + case 61: + goto tr186 + case 63: + goto tr188 + case 95: + goto tr186 + case 126: + goto tr186 + } + switch { + case (m.data)[(m.p)] < 48: + if 36 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 46 { + goto tr186 + } + case (m.data)[(m.p)] > 59: + switch { + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr186 + } + case (m.data)[(m.p)] >= 64: + goto tr186 + } + default: + goto tr186 + } + goto tr185 + case 182: + switch (m.data)[(m.p)] { + case 33: + goto tr226 + case 35: + goto tr227 + case 37: + goto tr228 + case 61: + goto tr226 + case 63: + goto tr229 + case 95: + goto tr226 + case 126: + goto tr226 + } + switch { + case (m.data)[(m.p)] < 64: + if 36 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 59 { + goto tr226 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr226 + } + default: + goto tr226 + } + goto tr185 + case 127: + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr190 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr190 + } + default: + goto tr191 + } + goto tr189 + case 128: + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr192 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr192 + } + default: + goto tr193 + } + goto tr189 + case 183: + switch (m.data)[(m.p)] { + case 33: + goto tr226 + case 35: + goto tr227 + case 37: + goto tr228 + case 61: + goto tr226 + case 63: + goto tr229 + case 95: + goto tr226 + case 126: + goto tr226 + } + switch { + case (m.data)[(m.p)] < 64: + if 36 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 59 { + goto tr226 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr226 + } + default: + goto tr226 + } + goto tr189 + case 184: + switch (m.data)[(m.p)] { + case 33: + goto tr226 + case 35: + goto tr227 + case 37: + goto tr228 + case 43: + goto tr230 + case 61: + goto tr231 + case 63: + goto tr229 + case 95: + goto tr226 + case 126: + goto tr226 + } + switch { + case (m.data)[(m.p)] < 64: + if 36 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 59 { + goto tr226 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr226 + } + default: + goto tr226 + } + goto tr185 + case 185: + switch (m.data)[(m.p)] { + case 33: + goto tr232 + case 35: + goto tr233 + case 37: + goto tr234 + case 47: + goto tr226 + case 61: + goto tr232 + case 63: + goto tr235 + case 95: + goto tr232 + case 126: + goto tr232 + } + switch { + case (m.data)[(m.p)] < 64: + if 36 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 59 { + goto tr232 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr232 + } + default: + goto tr232 + } + goto tr185 + case 186: + switch (m.data)[(m.p)] { + case 33: + goto tr204 + case 35: + goto tr227 + case 37: + goto tr237 + case 47: + goto tr226 + case 61: + goto tr204 + case 63: + goto tr229 + case 95: + goto tr204 + case 126: + goto tr204 + } + switch { + case (m.data)[(m.p)] < 64: + if 36 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 59 { + goto tr204 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr204 + } + default: + goto tr204 + } + goto tr236 + case 187: + switch (m.data)[(m.p)] { + case 33: + goto tr238 + case 35: + goto tr239 + case 37: + goto tr240 + case 61: + goto tr238 + case 63: + goto tr241 + case 95: + goto tr238 + case 126: + goto tr238 + } + switch { + case (m.data)[(m.p)] < 64: + if 36 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 59 { + goto tr238 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr238 + } + default: + goto tr238 + } + goto tr203 + case 129: + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr195 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr195 + } + default: + goto tr196 + } + goto tr194 + case 130: + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr197 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr197 + } + default: + goto tr198 + } + goto tr194 + case 188: + switch (m.data)[(m.p)] { + case 33: + goto tr238 + case 35: + goto tr239 + case 37: + goto tr240 + case 61: + goto tr238 + case 63: + goto tr241 + case 95: + goto tr238 + case 126: + goto tr238 + } + switch { + case (m.data)[(m.p)] < 64: + if 36 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 59 { + goto tr238 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr238 + } + default: + goto tr238 + } + goto tr194 + case 189: + switch (m.data)[(m.p)] { + case 33: + goto tr238 + case 35: + goto tr239 + case 37: + goto tr240 + case 61: + goto tr242 + case 63: + goto tr241 + case 95: + goto tr238 + case 126: + goto tr238 + } + switch { + case (m.data)[(m.p)] < 64: + if 36 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 59 { + goto tr238 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr238 + } + default: + goto tr238 + } + goto tr203 + case 190: + switch (m.data)[(m.p)] { + case 33: + goto tr243 + case 35: + goto tr244 + case 37: + goto tr245 + case 47: + goto tr238 + case 61: + goto tr243 + case 63: + goto tr246 + case 95: + goto tr243 + case 126: + goto tr243 + } + switch { + case (m.data)[(m.p)] < 64: + if 36 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 59 { + goto tr243 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr243 + } + default: + goto tr243 + } + goto tr203 + case 131: + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr200 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr200 + } + default: + goto tr201 + } + goto tr199 + case 132: + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr197 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr197 + } + default: + goto tr198 + } + goto tr199 + case 133: + if (m.data)[(m.p)] == 43 { + goto tr202 + } + goto tr185 + case 191: + switch (m.data)[(m.p)] { + case 33: + goto tr232 + case 35: + goto tr233 + case 37: + goto tr234 + case 61: + goto tr232 + case 63: + goto tr247 + case 95: + goto tr232 + case 126: + goto tr232 + } + switch { + case (m.data)[(m.p)] < 48: + if 36 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 46 { + goto tr232 + } + case (m.data)[(m.p)] > 59: + switch { + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr232 + } + case (m.data)[(m.p)] >= 64: + goto tr232 + } + default: + goto tr232 + } + goto tr185 + case 134: + switch (m.data)[(m.p)] { + case 43: + goto tr202 + case 61: + goto tr184 + } + goto tr185 + case 135: + switch (m.data)[(m.p)] { + case 33: + goto tr204 + case 37: + goto tr205 + case 61: + goto tr204 + case 63: + goto tr206 + case 95: + goto tr204 + case 126: + goto tr204 + } + switch { + case (m.data)[(m.p)] < 48: + if 36 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 46 { + goto tr204 + } + case (m.data)[(m.p)] > 59: + switch { + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr204 + } + case (m.data)[(m.p)] >= 64: + goto tr204 + } + default: + goto tr204 + } + goto tr203 + case 136: + if (m.data)[(m.p)] == 61 { + goto tr207 + } + goto tr203 + case 192: + switch (m.data)[(m.p)] { + case 33: + goto tr243 + case 35: + goto tr244 + case 37: + goto tr245 + case 61: + goto tr243 + case 63: + goto tr248 + case 95: + goto tr243 + case 126: + goto tr243 + } + switch { + case (m.data)[(m.p)] < 48: + if 36 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 46 { + goto tr243 + } + case (m.data)[(m.p)] > 59: + switch { + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr243 + } + case (m.data)[(m.p)] >= 64: + goto tr243 + } + default: + goto tr243 + } + goto tr203 + case 137: + if (m.data)[(m.p)] == 58 { + goto tr168 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr167 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr167 + } + default: + goto tr167 + } + goto tr106 + case 138: + switch (m.data)[(m.p)] { + case 45: + goto tr165 + case 58: + goto tr168 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr166 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr166 + } + default: + goto tr166 + } + goto tr106 + case 139: + switch (m.data)[(m.p)] { + case 45: + goto tr163 + case 58: + goto tr168 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr164 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr164 + } + default: + goto tr164 + } + goto tr106 + case 140: + switch (m.data)[(m.p)] { + case 45: + goto tr161 + case 58: + goto tr168 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr162 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr162 + } + default: + goto tr162 + } + goto tr106 + case 141: + switch (m.data)[(m.p)] { + case 45: + goto tr159 + case 58: + goto tr168 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr160 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr160 + } + default: + goto tr160 + } + goto tr106 + case 142: + switch (m.data)[(m.p)] { + case 45: + goto tr157 + case 58: + goto tr168 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr158 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr158 + } + default: + goto tr158 + } + goto tr106 + case 143: + switch (m.data)[(m.p)] { + case 45: + goto tr155 + case 58: + goto tr168 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr156 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr156 + } + default: + goto tr156 + } + goto tr106 + case 144: + switch (m.data)[(m.p)] { + case 45: + goto tr153 + case 58: + goto tr168 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr154 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr154 + } + default: + goto tr154 + } + goto tr106 + case 145: + switch (m.data)[(m.p)] { + case 45: + goto tr151 + case 58: + goto tr168 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr152 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr152 + } + default: + goto tr152 + } + goto tr106 + case 146: + switch (m.data)[(m.p)] { + case 45: + goto tr149 + case 58: + goto tr168 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr150 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr150 + } + default: + goto tr150 + } + goto tr106 + case 147: + switch (m.data)[(m.p)] { + case 45: + goto tr147 + case 58: + goto tr168 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr148 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr148 + } + default: + goto tr148 + } + goto tr106 + case 148: + switch (m.data)[(m.p)] { + case 45: + goto tr145 + case 58: + goto tr168 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr146 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr146 + } + default: + goto tr146 + } + goto tr106 + case 149: + switch (m.data)[(m.p)] { + case 45: + goto tr143 + case 58: + goto tr168 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr144 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr144 + } + default: + goto tr144 + } + goto tr106 + case 150: + switch (m.data)[(m.p)] { + case 45: + goto tr141 + case 58: + goto tr168 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr142 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr142 + } + default: + goto tr142 + } + goto tr106 + case 151: + switch (m.data)[(m.p)] { + case 45: + goto tr139 + case 58: + goto tr168 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr140 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr140 + } + default: + goto tr140 + } + goto tr106 + case 152: + switch (m.data)[(m.p)] { + case 45: + goto tr137 + case 58: + goto tr168 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr138 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr138 + } + default: + goto tr138 + } + goto tr106 + case 153: + switch (m.data)[(m.p)] { + case 45: + goto tr135 + case 58: + goto tr168 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr136 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr136 + } + default: + goto tr136 + } + goto tr106 + case 154: + switch (m.data)[(m.p)] { + case 45: + goto tr133 + case 58: + goto tr168 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr134 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr134 + } + default: + goto tr134 + } + goto tr106 + case 155: + switch (m.data)[(m.p)] { + case 45: + goto tr131 + case 58: + goto tr168 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr132 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr132 + } + default: + goto tr132 + } + goto tr106 + case 156: + switch (m.data)[(m.p)] { + case 45: + goto tr129 + case 58: + goto tr168 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr130 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr130 + } + default: + goto tr130 + } + goto tr106 + case 157: + switch (m.data)[(m.p)] { + case 45: + goto tr127 + case 58: + goto tr168 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr128 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr128 + } + default: + goto tr128 + } + goto tr106 + case 158: + switch (m.data)[(m.p)] { + case 45: + goto tr125 + case 58: + goto tr168 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr126 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr126 + } + default: + goto tr126 + } + goto tr106 + case 159: + switch (m.data)[(m.p)] { + case 45: + goto tr123 + case 58: + goto tr168 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr124 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr124 + } + default: + goto tr124 + } + goto tr106 + case 160: + switch (m.data)[(m.p)] { + case 45: + goto tr121 + case 58: + goto tr168 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr122 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr122 + } + default: + goto tr122 + } + goto tr106 + case 161: + switch (m.data)[(m.p)] { + case 45: + goto tr119 + case 58: + goto tr168 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr120 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr120 + } + default: + goto tr120 + } + goto tr106 + case 162: + switch (m.data)[(m.p)] { + case 45: + goto tr117 + case 58: + goto tr168 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr118 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr118 + } + default: + goto tr118 + } + goto tr106 + case 163: + switch (m.data)[(m.p)] { + case 45: + goto tr115 + case 58: + goto tr168 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr116 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr116 + } + default: + goto tr116 + } + goto tr106 + case 164: + switch (m.data)[(m.p)] { + case 45: + goto tr113 + case 58: + goto tr168 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr114 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr114 + } + default: + goto tr114 + } + goto tr106 + case 165: + switch (m.data)[(m.p)] { + case 45: + goto tr111 + case 58: + goto tr168 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr112 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr112 + } + default: + goto tr112 + } + goto tr106 + case 166: + switch (m.data)[(m.p)] { + case 45: + goto tr109 + case 58: + goto tr168 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr110 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr110 + } + default: + goto tr110 + } + goto tr106 + case 167: + switch (m.data)[(m.p)] { + case 45: + goto tr107 + case 82: + goto tr208 + case 114: + goto tr208 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr108 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr108 + } + default: + goto tr108 + } + goto tr103 + case 168: + switch (m.data)[(m.p)] { + case 45: + goto tr109 + case 58: + goto tr168 + case 78: + goto tr209 + case 110: + goto tr209 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr110 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr110 + } + default: + goto tr110 + } + goto tr103 + case 169: + switch (m.data)[(m.p)] { + case 45: + goto tr210 + case 58: + goto tr168 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr112 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr112 + } + default: + goto tr112 + } + goto tr106 + case 170: + switch (m.data)[(m.p)] { + case 45: + goto tr113 + case 48: + goto tr211 + } + switch { + case (m.data)[(m.p)] < 65: + if 49 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr114 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr211 + } + default: + goto tr211 + } + goto tr106 + case 171: + if (m.data)[(m.p)] == 45 { + goto tr115 + } + switch { + case (m.data)[(m.p)] < 65: + if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { + goto tr116 + } + case (m.data)[(m.p)] > 90: + if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { + goto tr116 + } + default: + goto tr116 + } + goto tr106 + case 193: + switch (m.data)[(m.p)] { + case 10: + goto tr183 + case 13: + goto tr183 + } + goto tr249 + } + + tr183: + m.cs = 0 + goto _again + tr0: + m.cs = 0 + goto f0 + tr5: + m.cs = 0 + goto f3 + tr8: + m.cs = 0 + goto f5 + tr41: + m.cs = 0 + goto f7 + tr44: + m.cs = 0 + goto f8 + tr51: + m.cs = 0 + goto f10 + tr56: + m.cs = 0 + goto f11 + tr74: + m.cs = 0 + goto f13 + tr81: + m.cs = 0 + goto f15 + tr83: + m.cs = 0 + goto f17 + tr86: + m.cs = 0 + goto f19 + tr103: + m.cs = 0 + goto f20 + tr106: + m.cs = 0 + goto f21 + tr169: + m.cs = 0 + goto f22 + tr172: + m.cs = 0 + goto f23 + tr177: + m.cs = 0 + goto f24 + tr185: + m.cs = 0 + goto f25 + tr189: + m.cs = 0 + goto f27 + tr194: + m.cs = 0 + goto f28 + tr199: + m.cs = 0 + goto f29 + tr203: + m.cs = 0 + goto f30 + tr236: + m.cs = 0 + goto f46 + tr1: + m.cs = 2 + goto f1 + tr2: + m.cs = 3 + goto _again + tr3: + m.cs = 4 + goto _again + tr4: + m.cs = 5 + goto f2 + tr6: + m.cs = 6 + goto f4 + tr9: + m.cs = 7 + goto _again + tr11: + m.cs = 8 + goto _again + tr12: + m.cs = 9 + goto _again + tr13: + m.cs = 10 + goto _again + tr14: + m.cs = 11 + goto _again + tr15: + m.cs = 12 + goto _again + tr16: + m.cs = 13 + goto _again + tr17: + m.cs = 14 + goto _again + tr18: + m.cs = 15 + goto _again + tr19: + m.cs = 16 + goto _again + tr20: + m.cs = 17 + goto _again + tr21: + m.cs = 18 + goto _again + tr22: + m.cs = 19 + goto _again + tr23: + m.cs = 20 + goto _again + tr24: + m.cs = 21 + goto _again + tr25: + m.cs = 22 + goto _again + tr26: + m.cs = 23 + goto _again + tr27: + m.cs = 24 + goto _again + tr28: + m.cs = 25 + goto _again + tr29: + m.cs = 26 + goto _again + tr30: + m.cs = 27 + goto _again + tr31: + m.cs = 28 + goto _again + tr32: + m.cs = 29 + goto _again + tr33: + m.cs = 30 + goto _again + tr34: + m.cs = 31 + goto _again + tr35: + m.cs = 32 + goto _again + tr36: + m.cs = 33 + goto _again + tr37: + m.cs = 34 + goto _again + tr38: + m.cs = 35 + goto _again + tr39: + m.cs = 36 + goto _again + tr40: + m.cs = 37 + goto _again + tr10: + m.cs = 38 + goto f6 + tr213: + m.cs = 39 + goto _again + tr43: + m.cs = 39 + goto f4 + tr45: + m.cs = 40 + goto _again + tr46: + m.cs = 40 + goto f9 + tr7: + m.cs = 41 + goto f1 + tr49: + m.cs = 42 + goto _again + tr50: + m.cs = 43 + goto _again + tr52: + m.cs = 45 + goto f1 + tr53: + m.cs = 46 + goto _again + tr54: + m.cs = 47 + goto _again + tr55: + m.cs = 48 + goto f2 + tr57: + m.cs = 49 + goto f4 + tr58: + m.cs = 50 + goto _again + tr59: + m.cs = 51 + goto _again + tr60: + m.cs = 52 + goto _again + tr61: + m.cs = 53 + goto _again + tr62: + m.cs = 54 + goto _again + tr63: + m.cs = 55 + goto _again + tr64: + m.cs = 56 + goto _again + tr65: + m.cs = 57 + goto _again + tr66: + m.cs = 58 + goto _again + tr67: + m.cs = 59 + goto _again + tr68: + m.cs = 60 + goto _again + tr69: + m.cs = 61 + goto _again + tr70: + m.cs = 62 + goto _again + tr71: + m.cs = 63 + goto _again + tr72: + m.cs = 64 + goto _again + tr73: + m.cs = 65 + goto f12 + tr75: + m.cs = 66 + goto f4 + tr78: + m.cs = 67 + goto _again + tr79: + m.cs = 68 + goto _again + tr80: + m.cs = 69 + goto f14 + tr215: + m.cs = 70 + goto f35 + tr217: + m.cs = 71 + goto _again + tr85: + m.cs = 71 + goto f18 + tr87: + m.cs = 72 + goto _again + tr88: + m.cs = 72 + goto f9 + tr76: + m.cs = 73 + goto f4 + tr91: + m.cs = 74 + goto _again + tr92: + m.cs = 75 + goto _again + tr93: + m.cs = 76 + goto _again + tr77: + m.cs = 77 + goto f4 + tr94: + m.cs = 78 + goto _again + tr95: + m.cs = 79 + goto _again + tr96: + m.cs = 80 + goto _again + tr97: + m.cs = 81 + goto _again + tr98: + m.cs = 82 + goto _again + tr99: + m.cs = 84 + goto f1 + tr100: + m.cs = 85 + goto _again + tr101: + m.cs = 86 + goto _again + tr102: + m.cs = 87 + goto f2 + tr104: + m.cs = 88 + goto f4 + tr107: + m.cs = 89 + goto _again + tr109: + m.cs = 90 + goto _again + tr111: + m.cs = 91 + goto _again + tr113: + m.cs = 92 + goto _again + tr115: + m.cs = 93 + goto _again + tr117: + m.cs = 94 + goto _again + tr119: + m.cs = 95 + goto _again + tr121: + m.cs = 96 + goto _again + tr123: + m.cs = 97 + goto _again + tr125: + m.cs = 98 + goto _again + tr127: + m.cs = 99 + goto _again + tr129: + m.cs = 100 + goto _again + tr131: + m.cs = 101 + goto _again + tr133: + m.cs = 102 + goto _again + tr135: + m.cs = 103 + goto _again + tr137: + m.cs = 104 + goto _again + tr139: + m.cs = 105 + goto _again + tr141: + m.cs = 106 + goto _again + tr143: + m.cs = 107 + goto _again + tr145: + m.cs = 108 + goto _again + tr147: + m.cs = 109 + goto _again + tr149: + m.cs = 110 + goto _again + tr151: + m.cs = 111 + goto _again + tr153: + m.cs = 112 + goto _again + tr155: + m.cs = 113 + goto _again + tr157: + m.cs = 114 + goto _again + tr159: + m.cs = 115 + goto _again + tr161: + m.cs = 116 + goto _again + tr163: + m.cs = 117 + goto _again + tr165: + m.cs = 118 + goto _again + tr167: + m.cs = 119 + goto _again + tr168: + m.cs = 120 + goto f6 + tr225: + m.cs = 121 + goto _again + tr223: + m.cs = 121 + goto f4 + tr173: + m.cs = 122 + goto _again + tr174: + m.cs = 122 + goto f9 + tr220: + m.cs = 123 + goto _again + tr171: + m.cs = 123 + goto f4 + tr178: + m.cs = 124 + goto _again + tr179: + m.cs = 124 + goto f9 + tr221: + m.cs = 125 + goto f38 + tr182: + m.cs = 126 + goto _again + tr228: + m.cs = 127 + goto _again + tr187: + m.cs = 127 + goto f26 + tr234: + m.cs = 127 + goto f44 + tr190: + m.cs = 128 + goto _again + tr191: + m.cs = 128 + goto f9 + tr240: + m.cs = 129 + goto _again + tr205: + m.cs = 129 + goto f31 + tr245: + m.cs = 129 + goto f50 + tr195: + m.cs = 130 + goto _again + tr196: + m.cs = 130 + goto f9 + tr237: + m.cs = 131 + goto f31 + tr200: + m.cs = 132 + goto _again + tr201: + m.cs = 132 + goto f9 + tr188: + m.cs = 133 + goto f26 + tr247: + m.cs = 134 + goto f45 + tr184: + m.cs = 135 + goto _again + tr206: + m.cs = 136 + goto f31 + tr248: + m.cs = 136 + goto f50 + tr166: + m.cs = 137 + goto _again + tr164: + m.cs = 138 + goto _again + tr162: + m.cs = 139 + goto _again + tr160: + m.cs = 140 + goto _again + tr158: + m.cs = 141 + goto _again + tr156: + m.cs = 142 + goto _again + tr154: + m.cs = 143 + goto _again + tr152: + m.cs = 144 + goto _again + tr150: + m.cs = 145 + goto _again + tr148: + m.cs = 146 + goto _again + tr146: + m.cs = 147 + goto _again + tr144: + m.cs = 148 + goto _again + tr142: + m.cs = 149 + goto _again + tr140: + m.cs = 150 + goto _again + tr138: + m.cs = 151 + goto _again + tr136: + m.cs = 152 + goto _again + tr134: + m.cs = 153 + goto _again + tr132: + m.cs = 154 + goto _again + tr130: + m.cs = 155 + goto _again + tr128: + m.cs = 156 + goto _again + tr126: + m.cs = 157 + goto _again + tr124: + m.cs = 158 + goto _again + tr122: + m.cs = 159 + goto _again + tr120: + m.cs = 160 + goto _again + tr118: + m.cs = 161 + goto _again + tr116: + m.cs = 162 + goto _again + tr114: + m.cs = 163 + goto _again + tr112: + m.cs = 164 + goto _again + tr110: + m.cs = 165 + goto _again + tr108: + m.cs = 166 + goto _again + tr105: + m.cs = 167 + goto f1 + tr208: + m.cs = 168 + goto _again + tr209: + m.cs = 169 + goto _again + tr210: + m.cs = 170 + goto f2 + tr211: + m.cs = 171 + goto _again + tr212: + m.cs = 172 + goto _again + tr42: + m.cs = 172 + goto f4 + tr47: + m.cs = 173 + goto _again + tr48: + m.cs = 173 + goto f9 + tr214: + m.cs = 174 + goto _again + tr82: + m.cs = 174 + goto f16 + tr216: + m.cs = 175 + goto _again + tr84: + m.cs = 175 + goto f18 + tr89: + m.cs = 176 + goto _again + tr90: + m.cs = 176 + goto f9 + tr218: + m.cs = 177 + goto _again + tr170: + m.cs = 177 + goto f4 + tr219: + m.cs = 178 + goto f38 + tr227: + m.cs = 178 + goto f42 + tr233: + m.cs = 178 + goto f45 + tr239: + m.cs = 178 + goto f48 + tr244: + m.cs = 178 + goto f51 + tr224: + m.cs = 179 + goto _again + tr222: + m.cs = 179 + goto f4 + tr175: + m.cs = 180 + goto _again + tr176: + m.cs = 180 + goto f9 + tr180: + m.cs = 181 + goto _again + tr181: + m.cs = 181 + goto f9 + tr226: + m.cs = 182 + goto _again + tr186: + m.cs = 182 + goto f26 + tr232: + m.cs = 182 + goto f44 + tr192: + m.cs = 183 + goto _again + tr193: + m.cs = 183 + goto f9 + tr229: + m.cs = 184 + goto f42 + tr235: + m.cs = 184 + goto f45 + tr230: + m.cs = 185 + goto _again + tr231: + m.cs = 186 + goto _again + tr238: + m.cs = 187 + goto _again + tr204: + m.cs = 187 + goto f31 + tr243: + m.cs = 187 + goto f50 + tr197: + m.cs = 188 + goto _again + tr198: + m.cs = 188 + goto f9 + tr241: + m.cs = 189 + goto _again + tr246: + m.cs = 189 + goto f50 + tr242: + m.cs = 190 + goto _again + tr202: + m.cs = 191 + goto _again + tr207: + m.cs = 192 + goto _again + tr249: + m.cs = 193 + goto _again + + f4: + + m.pb = m.p + + goto _again + f9: + + // List of positions in the buffer to later lowercase + output.tolower = append(output.tolower, m.p-m.pb) + + goto _again + f2: + + output.prefix = string(m.text()) + + goto _again + f6: + + output.ID = string(m.text()) + + goto _again + f38: + + output.SS = string(m.text()) + // Iterate upper letters lowering them + for _, i := range output.tolower { + m.data[m.pb+i] = m.data[m.pb+i] + 32 + } + output.norm = string(m.text()) + // Revert the buffer to the original + for _, i := range output.tolower { + m.data[m.pb+i] = m.data[m.pb+i] - 32 + } + + goto _again + f0: + + m.err = fmt.Errorf(errPrefix, m.p) + (m.p)-- + + m.cs = 193 + goto _again + + goto _again + f5: + + m.err = fmt.Errorf(errIdentifier, m.p) + (m.p)-- + + m.cs = 193 + goto _again + + goto _again + f7: + + m.err = fmt.Errorf(errSpecificString, m.p) + (m.p)-- + + m.cs = 193 + goto _again + + goto _again + f23: + + if m.parsingMode == RFC2141Only || m.parsingMode == RFC8141Only { + m.err = fmt.Errorf(errHex, m.p) + (m.p)-- + + m.cs = 193 + goto _again + + } + + goto _again + f11: + + m.err = fmt.Errorf(errSCIMNamespace, m.p) + (m.p)-- + + m.cs = 193 + goto _again + + goto _again + f13: + + m.err = fmt.Errorf(errSCIMType, m.p) + (m.p)-- + + m.cs = 193 + goto _again + + goto _again + f15: + + m.err = fmt.Errorf(errSCIMName, m.p) + (m.p)-- + + m.cs = 193 + goto _again + + goto _again + f17: + + if m.p == m.pe { + m.err = fmt.Errorf(errSCIMOtherIncomplete, m.p-1) + } else { + m.err = fmt.Errorf(errSCIMOther, m.p) + } + (m.p)-- + + m.cs = 193 + goto _again + + goto _again + f14: + + output.scim.Type = scimschema.TypeFromString(string(m.text())) + + goto _again + f16: + + output.scim.pos = m.p + + goto _again + f35: + + output.scim.Name = string(m.data[output.scim.pos:m.p]) + + goto _again + f18: + + output.scim.pos = m.p + + goto _again + f22: + + m.err = fmt.Errorf(err8141SpecificString, m.p) + (m.p)-- + + m.cs = 193 + goto _again + + goto _again + f21: + + m.err = fmt.Errorf(err8141Identifier, m.p) + (m.p)-- + + m.cs = 193 + goto _again + + goto _again + f42: + + output.rComponent = string(m.text()) + + goto _again + f48: + + output.qComponent = string(m.text()) + + goto _again + f44: + + if output.rStart { + m.err = fmt.Errorf(err8141RComponentStart, m.p) + (m.p)-- + + m.cs = 193 + goto _again + + } + output.rStart = true + + goto _again + f50: + + if output.qStart { + m.err = fmt.Errorf(err8141QComponentStart, m.p) + (m.p)-- + + m.cs = 193 + goto _again + + } + output.qStart = true + + goto _again + f25: + + m.err = fmt.Errorf(err8141MalformedRComp, m.p) + (m.p)-- + + m.cs = 193 + goto _again + + goto _again + f30: + + m.err = fmt.Errorf(err8141MalformedQComp, m.p) + (m.p)-- + + m.cs = 193 + goto _again + + goto _again + f1: + + m.pb = m.p + + if m.parsingMode != RFC8141Only { + // Throw an error when: + // - we are entering here matching the the prefix in the namespace identifier part + // - looking ahead (3 chars) we find a colon + if pos := m.p + 3; pos < m.pe && m.data[pos] == 58 && output.prefix != "" { + m.err = fmt.Errorf(errNoUrnWithinID, pos) + (m.p)-- + + m.cs = 193 + goto _again + + } + } + + goto _again + f12: + + output.ID = string(m.text()) + + output.scim = &SCIM{} + + goto _again + f3: + + m.err = fmt.Errorf(errIdentifier, m.p) + (m.p)-- + + m.cs = 193 + goto _again + + m.err = fmt.Errorf(errPrefix, m.p) + (m.p)-- + + m.cs = 193 + goto _again + + goto _again + f10: + + m.err = fmt.Errorf(errIdentifier, m.p) + (m.p)-- + + m.cs = 193 + goto _again + + m.err = fmt.Errorf(errNoUrnWithinID, m.p) + (m.p)-- + + m.cs = 193 + goto _again + + goto _again + f8: + + if m.parsingMode == RFC2141Only || m.parsingMode == RFC8141Only { + m.err = fmt.Errorf(errHex, m.p) + (m.p)-- + + m.cs = 193 + goto _again + + } + + m.err = fmt.Errorf(errSpecificString, m.p) + (m.p)-- + + m.cs = 193 + goto _again + + goto _again + f19: + + if m.parsingMode == RFC2141Only || m.parsingMode == RFC8141Only { + m.err = fmt.Errorf(errHex, m.p) + (m.p)-- + + m.cs = 193 + goto _again + + } + + if m.p == m.pe { + m.err = fmt.Errorf(errSCIMOtherIncomplete, m.p-1) + } else { + m.err = fmt.Errorf(errSCIMOther, m.p) + } + (m.p)-- + + m.cs = 193 + goto _again + + goto _again + f24: + + if m.parsingMode == RFC2141Only || m.parsingMode == RFC8141Only { + m.err = fmt.Errorf(errHex, m.p) + (m.p)-- + + m.cs = 193 + goto _again + + } + + m.err = fmt.Errorf(err8141SpecificString, m.p) + (m.p)-- + + m.cs = 193 + goto _again + + goto _again + f27: + + if m.parsingMode == RFC2141Only || m.parsingMode == RFC8141Only { + m.err = fmt.Errorf(errHex, m.p) + (m.p)-- + + m.cs = 193 + goto _again + + } + + m.err = fmt.Errorf(err8141MalformedRComp, m.p) + (m.p)-- + + m.cs = 193 + goto _again + + goto _again + f28: + + if m.parsingMode == RFC2141Only || m.parsingMode == RFC8141Only { + m.err = fmt.Errorf(errHex, m.p) + (m.p)-- + + m.cs = 193 + goto _again + + } + + m.err = fmt.Errorf(err8141MalformedQComp, m.p) + (m.p)-- + + m.cs = 193 + goto _again + + goto _again + f20: + + m.err = fmt.Errorf(err8141Identifier, m.p) + (m.p)-- + + m.cs = 193 + goto _again + + m.err = fmt.Errorf(errPrefix, m.p) + (m.p)-- + + m.cs = 193 + goto _again + + goto _again + f26: + + if output.rStart { + m.err = fmt.Errorf(err8141RComponentStart, m.p) + (m.p)-- + + m.cs = 193 + goto _again + + } + output.rStart = true m.pb = m.p - goto st39 - st39: - if (m.p)++; (m.p) == (m.pe) { - goto _testEof39 - } - stCase39: - switch { - case (m.data)[(m.p)] < 65: - if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { - goto st40 - } - case (m.data)[(m.p)] > 90: - if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { - goto st40 - } - default: - goto tr46 - } - goto tr44 - tr46: + goto _again + f45: - m.tolower = append(m.tolower, m.p-m.pb) + if output.rStart { + m.err = fmt.Errorf(err8141RComponentStart, m.p) + (m.p)-- + + m.cs = 193 + goto _again - goto st40 - st40: - if (m.p)++; (m.p) == (m.pe) { - goto _testEof40 - } - stCase40: - switch { - case (m.data)[(m.p)] < 65: - if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { - goto st45 - } - case (m.data)[(m.p)] > 90: - if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { - goto st45 - } - default: - goto tr48 } - goto tr44 - tr48: + output.rStart = true - m.tolower = append(m.tolower, m.p-m.pb) + output.rComponent = string(m.text()) + + goto _again + f31: + + if output.qStart { + m.err = fmt.Errorf(err8141QComponentStart, m.p) + (m.p)-- + + m.cs = 193 + goto _again - goto st45 - st45: - if (m.p)++; (m.p) == (m.pe) { - goto _testEof45 - } - stCase45: - switch (m.data)[(m.p)] { - case 33: - goto st44 - case 36: - goto st44 - case 37: - goto st39 - case 61: - goto st44 - case 95: - goto st44 - } - switch { - case (m.data)[(m.p)] < 48: - if 39 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 46 { - goto st44 - } - case (m.data)[(m.p)] > 59: - switch { - case (m.data)[(m.p)] > 90: - if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { - goto st44 - } - case (m.data)[(m.p)] >= 64: - goto st44 - } - default: - goto st44 } - goto tr44 - tr8: + output.qStart = true m.pb = m.p - goto st41 - st41: - if (m.p)++; (m.p) == (m.pe) { - goto _testEof41 - } - stCase41: - switch (m.data)[(m.p)] { - case 45: - goto st7 - case 58: - goto tr10 - case 82: - goto st42 - case 114: - goto st42 - } - switch { - case (m.data)[(m.p)] < 65: - if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { - goto st7 - } - case (m.data)[(m.p)] > 90: - if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { - goto st7 - } - default: - goto st7 - } - goto tr6 - st42: - if (m.p)++; (m.p) == (m.pe) { - goto _testEof42 - } - stCase42: - switch (m.data)[(m.p)] { - case 45: - goto st8 - case 58: - goto tr10 - case 78: - goto st43 - case 110: - goto st43 - } - switch { - case (m.data)[(m.p)] < 65: - if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { - goto st8 - } - case (m.data)[(m.p)] > 90: - if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { - goto st8 - } - default: - goto st8 - } - goto tr50 - st43: - if (m.p)++; (m.p) == (m.pe) { - goto _testEof43 + goto _again + f51: + + if output.qStart { + m.err = fmt.Errorf(err8141QComponentStart, m.p) + (m.p)-- + + m.cs = 193 + goto _again + } - stCase43: - if (m.data)[(m.p)] == 45 { - goto st9 + output.qStart = true + + output.qComponent = string(m.text()) + + goto _again + f46: + + m.err = fmt.Errorf(err8141MalformedRComp, m.p) + (m.p)-- + + m.cs = 193 + goto _again + + m.err = fmt.Errorf(err8141MalformedQComp, m.p) + (m.p)-- + + m.cs = 193 + goto _again + + goto _again + f29: + + if m.parsingMode == RFC2141Only || m.parsingMode == RFC8141Only { + m.err = fmt.Errorf(errHex, m.p) + (m.p)-- + + m.cs = 193 + goto _again + } - switch { - case (m.data)[(m.p)] < 65: - if 48 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 57 { - goto st9 - } - case (m.data)[(m.p)] > 90: - if 97 <= (m.data)[(m.p)] && (m.data)[(m.p)] <= 122 { - goto st9 - } - default: - goto st9 + + m.err = fmt.Errorf(err8141MalformedRComp, m.p) + (m.p)-- + + m.cs = 193 + goto _again + + m.err = fmt.Errorf(err8141MalformedQComp, m.p) + (m.p)-- + + m.cs = 193 + goto _again + + goto _again + + _again: + switch _toStateActions[m.cs] { + case 33: + + (m.p)-- + + m.err = fmt.Errorf(err8141InformalID, m.p) + m.cs = 193 + goto _again } - goto tr52 - st46: - if (m.p)++; (m.p) == (m.pe) { - goto _testEof46 + + if m.cs == 0 { + goto _out } - stCase46: - switch (m.data)[(m.p)] { - case 10: - goto st0 - case 13: - goto st0 + if (m.p)++; (m.p) != (m.pe) { + goto _resume } - goto st46 - stOut: - _testEof2: - m.cs = 2 - goto _testEof - _testEof3: - m.cs = 3 - goto _testEof - _testEof4: - m.cs = 4 - goto _testEof - _testEof5: - m.cs = 5 - goto _testEof - _testEof6: - m.cs = 6 - goto _testEof - _testEof7: - m.cs = 7 - goto _testEof - _testEof8: - m.cs = 8 - goto _testEof - _testEof9: - m.cs = 9 - goto _testEof - _testEof10: - m.cs = 10 - goto _testEof - _testEof11: - m.cs = 11 - goto _testEof - _testEof12: - m.cs = 12 - goto _testEof - _testEof13: - m.cs = 13 - goto _testEof - _testEof14: - m.cs = 14 - goto _testEof - _testEof15: - m.cs = 15 - goto _testEof - _testEof16: - m.cs = 16 - goto _testEof - _testEof17: - m.cs = 17 - goto _testEof - _testEof18: - m.cs = 18 - goto _testEof - _testEof19: - m.cs = 19 - goto _testEof - _testEof20: - m.cs = 20 - goto _testEof - _testEof21: - m.cs = 21 - goto _testEof - _testEof22: - m.cs = 22 - goto _testEof - _testEof23: - m.cs = 23 - goto _testEof - _testEof24: - m.cs = 24 - goto _testEof - _testEof25: - m.cs = 25 - goto _testEof - _testEof26: - m.cs = 26 - goto _testEof - _testEof27: - m.cs = 27 - goto _testEof - _testEof28: - m.cs = 28 - goto _testEof - _testEof29: - m.cs = 29 - goto _testEof - _testEof30: - m.cs = 30 - goto _testEof - _testEof31: - m.cs = 31 - goto _testEof - _testEof32: - m.cs = 32 - goto _testEof - _testEof33: - m.cs = 33 - goto _testEof - _testEof34: - m.cs = 34 - goto _testEof - _testEof35: - m.cs = 35 - goto _testEof - _testEof36: - m.cs = 36 - goto _testEof - _testEof37: - m.cs = 37 - goto _testEof - _testEof38: - m.cs = 38 - goto _testEof - _testEof44: - m.cs = 44 - goto _testEof - _testEof39: - m.cs = 39 - goto _testEof - _testEof40: - m.cs = 40 - goto _testEof - _testEof45: - m.cs = 45 - goto _testEof - _testEof41: - m.cs = 41 - goto _testEof - _testEof42: - m.cs = 42 - goto _testEof - _testEof43: - m.cs = 43 - goto _testEof - _testEof46: - m.cs = 46 - goto _testEof - _testEof: { } if (m.p) == (m.eof) { - switch m.cs { - case 44, 45: + switch _eofActions[m.cs] { + case 1: - raw := m.text() - output.SS = string(raw) - // Iterate upper letters lowering them - for _, i := range m.tolower { - raw[i] = raw[i] + 32 - } - output.norm = string(raw) + m.err = fmt.Errorf(errPrefix, m.p) + (m.p)-- + + m.cs = 193 + goto _again - case 1, 2, 4: + case 6: - m.err = fmt.Errorf(errParse, m.p) + m.err = fmt.Errorf(errIdentifier, m.p) (m.p)-- - { - goto st46 - } + m.cs = 193 + goto _again - case 3: + case 8: - m.err = fmt.Errorf(errPrefix, m.p) + m.err = fmt.Errorf(errSpecificString, m.p) (m.p)-- - { - goto st46 + m.cs = 193 + goto _again + + case 24: + + if m.parsingMode == RFC2141Only || m.parsingMode == RFC8141Only { + m.err = fmt.Errorf(errHex, m.p) + (m.p)-- + + m.cs = 193 + goto _again + } - m.err = fmt.Errorf(errParse, m.p) + case 12: + + m.err = fmt.Errorf(errSCIMNamespace, m.p) (m.p)-- - { - goto st46 - } + m.cs = 193 + goto _again - case 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 41: + case 14: - m.err = fmt.Errorf(errIdentifier, m.p) + m.err = fmt.Errorf(errSCIMType, m.p) (m.p)-- - { - goto st46 - } + m.cs = 193 + goto _again - m.err = fmt.Errorf(errParse, m.p) + case 16: + + m.err = fmt.Errorf(errSCIMName, m.p) (m.p)-- - { - goto st46 + m.cs = 193 + goto _again + + case 18: + + if m.p == m.pe { + m.err = fmt.Errorf(errSCIMOtherIncomplete, m.p-1) + } else { + m.err = fmt.Errorf(errSCIMOther, m.p) } + (m.p)-- - case 38: + m.cs = 193 + goto _again - m.err = fmt.Errorf(errSpecificString, m.p) + case 23: + + m.err = fmt.Errorf(err8141SpecificString, m.p) (m.p)-- - { - goto st46 - } + m.cs = 193 + goto _again - m.err = fmt.Errorf(errParse, m.p) + case 22: + + m.err = fmt.Errorf(err8141Identifier, m.p) (m.p)-- - { - goto st46 - } + m.cs = 193 + goto _again - case 42: + case 26: - m.err = fmt.Errorf(errPrefix, m.p) + m.err = fmt.Errorf(err8141MalformedRComp, m.p) + (m.p)-- + + m.cs = 193 + goto _again + + case 31: + + m.err = fmt.Errorf(err8141MalformedQComp, m.p) (m.p)-- - { - goto st46 + m.cs = 193 + goto _again + + case 34: + + output.SS = string(m.text()) + // Iterate upper letters lowering them + for _, i := range output.tolower { + m.data[m.pb+i] = m.data[m.pb+i] + 32 + } + output.norm = string(m.text()) + // Revert the buffer to the original + for _, i := range output.tolower { + m.data[m.pb+i] = m.data[m.pb+i] - 32 + } + + output.kind = RFC2141 + + case 38: + + output.SS = string(m.text()) + // Iterate upper letters lowering them + for _, i := range output.tolower { + m.data[m.pb+i] = m.data[m.pb+i] + 32 } + output.norm = string(m.text()) + // Revert the buffer to the original + for _, i := range output.tolower { + m.data[m.pb+i] = m.data[m.pb+i] - 32 + } + + output.kind = RFC8141 + + case 4: m.err = fmt.Errorf(errIdentifier, m.p) (m.p)-- - { - goto st46 - } + m.cs = 193 + goto _again - m.err = fmt.Errorf(errParse, m.p) + m.err = fmt.Errorf(errPrefix, m.p) (m.p)-- - { - goto st46 - } + m.cs = 193 + goto _again - case 43: + case 11: + + m.err = fmt.Errorf(errIdentifier, m.p) + (m.p)-- + + m.cs = 193 + goto _again m.err = fmt.Errorf(errNoUrnWithinID, m.p) (m.p)-- - { - goto st46 + m.cs = 193 + goto _again + + case 9: + + if m.parsingMode == RFC2141Only || m.parsingMode == RFC8141Only { + m.err = fmt.Errorf(errHex, m.p) + (m.p)-- + + m.cs = 193 + goto _again + } - m.err = fmt.Errorf(errIdentifier, m.p) + m.err = fmt.Errorf(errSpecificString, m.p) (m.p)-- - { - goto st46 + m.cs = 193 + goto _again + + case 20: + + if m.parsingMode == RFC2141Only || m.parsingMode == RFC8141Only { + m.err = fmt.Errorf(errHex, m.p) + (m.p)-- + + m.cs = 193 + goto _again + } - m.err = fmt.Errorf(errParse, m.p) + if m.p == m.pe { + m.err = fmt.Errorf(errSCIMOtherIncomplete, m.p-1) + } else { + m.err = fmt.Errorf(errSCIMOther, m.p) + } (m.p)-- - { - goto st46 + m.cs = 193 + goto _again + + case 25: + + if m.parsingMode == RFC2141Only || m.parsingMode == RFC8141Only { + m.err = fmt.Errorf(errHex, m.p) + (m.p)-- + + m.cs = 193 + goto _again + } - case 39, 40: + m.err = fmt.Errorf(err8141SpecificString, m.p) + (m.p)-- + + m.cs = 193 + goto _again + + case 28: + + if m.parsingMode == RFC2141Only || m.parsingMode == RFC8141Only { + m.err = fmt.Errorf(errHex, m.p) + (m.p)-- + + m.cs = 193 + goto _again + + } - m.err = fmt.Errorf(errHex, m.p) + m.err = fmt.Errorf(err8141MalformedRComp, m.p) (m.p)-- - { - goto st46 + m.cs = 193 + goto _again + + case 29: + + if m.parsingMode == RFC2141Only || m.parsingMode == RFC8141Only { + m.err = fmt.Errorf(errHex, m.p) + (m.p)-- + + m.cs = 193 + goto _again + } - m.err = fmt.Errorf(errSpecificString, m.p) + m.err = fmt.Errorf(err8141MalformedQComp, m.p) + (m.p)-- + + m.cs = 193 + goto _again + + case 21: + + m.err = fmt.Errorf(err8141Identifier, m.p) + (m.p)-- + + m.cs = 193 + goto _again + + m.err = fmt.Errorf(errPrefix, m.p) (m.p)-- - { - goto st46 + m.cs = 193 + goto _again + + case 42: + + output.rComponent = string(m.text()) + + output.kind = RFC8141 + + case 48: + + output.qComponent = string(m.text()) + + output.kind = RFC8141 + + case 41: + + output.fComponent = string(m.text()) + + output.kind = RFC8141 + + case 40: + + m.pb = m.p + + output.fComponent = string(m.text()) + + output.kind = RFC8141 + + case 30: + + if m.parsingMode == RFC2141Only || m.parsingMode == RFC8141Only { + m.err = fmt.Errorf(errHex, m.p) + (m.p)-- + + m.cs = 193 + goto _again + } - m.err = fmt.Errorf(errParse, m.p) + m.err = fmt.Errorf(err8141MalformedRComp, m.p) (m.p)-- - { - goto st46 + m.cs = 193 + goto _again + + m.err = fmt.Errorf(err8141MalformedQComp, m.p) + (m.p)-- + + m.cs = 193 + goto _again + + case 35: + + output.scim.Name = string(m.data[output.scim.pos:m.p]) + + output.SS = string(m.text()) + // Iterate upper letters lowering them + for _, i := range output.tolower { + m.data[m.pb+i] = m.data[m.pb+i] + 32 + } + output.norm = string(m.text()) + // Revert the buffer to the original + for _, i := range output.tolower { + m.data[m.pb+i] = m.data[m.pb+i] - 32 + } + + output.kind = RFC7643 + + case 37: + + output.scim.Other = string(m.data[output.scim.pos:m.p]) + + output.SS = string(m.text()) + // Iterate upper letters lowering them + for _, i := range output.tolower { + m.data[m.pb+i] = m.data[m.pb+i] + 32 + } + output.norm = string(m.text()) + // Revert the buffer to the original + for _, i := range output.tolower { + m.data[m.pb+i] = m.data[m.pb+i] - 32 + } + + output.kind = RFC7643 + + case 44: + + if output.rStart { + m.err = fmt.Errorf(err8141RComponentStart, m.p) + (m.p)-- + + m.cs = 193 + goto _again + + } + output.rStart = true + + output.rComponent = string(m.text()) + + output.kind = RFC8141 + + case 50: + + if output.qStart { + m.err = fmt.Errorf(err8141QComponentStart, m.p) + (m.p)-- + + m.cs = 193 + goto _again + } + output.qStart = true + output.qComponent = string(m.text()) + + output.kind = RFC8141 } } @@ -1689,3 +5031,16 @@ func (m *machine) Parse(input []byte) (*URN, error) { return output, nil } + +func (m *machine) WithParsingMode(x ParsingMode) { + m.parsingMode = x + switch m.parsingMode { + case RFC2141Only: + m.startParsingAt = enMain + case RFC8141Only: + m.startParsingAt = enRfc8141Only + case RFC7643Only: + m.startParsingAt = enScimOnly + } + m.parsingModeSet = true +} diff --git a/vendor/github.com/leodido/go-urn/machine.go.rl b/vendor/github.com/leodido/go-urn/machine.go.rl index 3bc05a651a..0a17421998 100644 --- a/vendor/github.com/leodido/go-urn/machine.go.rl +++ b/vendor/github.com/leodido/go-urn/machine.go.rl @@ -2,15 +2,28 @@ package urn import ( "fmt" + + scimschema "github.com/leodido/go-urn/scim/schema" ) var ( - errPrefix = "expecting the prefix to be the \"urn\" string (whatever case) [col %d]" - errIdentifier = "expecting the identifier to be string (1..31 alnum chars, also containing dashes but not at its start) [col %d]" - errSpecificString = "expecting the specific string to be a string containing alnum, hex, or others ([()+,-.:=@;$_!*']) chars [col %d]" - errNoUrnWithinID = "expecting the identifier to not contain the \"urn\" reserved string [col %d]" - errHex = "expecting the specific string hex chars to be well-formed (%%alnum{2}) [col %d]" - errParse = "parsing error [col %d]" + errPrefix = "expecting the prefix to be the \"urn\" string (whatever case) [col %d]" + errIdentifier = "expecting the identifier to be string (1..31 alnum chars, also containing dashes but not at its beginning) [col %d]" + errSpecificString = "expecting the specific string to be a string containing alnum, hex, or others ([()+,-.:=@;$_!*']) chars [col %d]" + errNoUrnWithinID = "expecting the identifier to not contain the \"urn\" reserved string [col %d]" + errHex = "expecting the percent encoded chars to be well-formed (%%alnum{2}) [col %d]" + errSCIMNamespace = "expecing the SCIM namespace identifier (ietf:params:scim) [col %d]" + errSCIMType = "expecting a correct SCIM type (schemas, api, param) [col %d]" + errSCIMName = "expecting one or more alnum char in the SCIM name part [col %d]" + errSCIMOther = "expecting a well-formed other SCIM part [col %d]" + errSCIMOtherIncomplete = "expecting a not empty SCIM other part after colon [col %d]" + err8141InformalID = "informal URN namespace must be in the form urn-[1-9][0-9] [col %d]" + err8141SpecificString = "expecting the specific string to contain alnum, hex, or others ([~&()+,-.:=@;$_!*'] or [/?] not in first position) chars [col %d]" + err8141Identifier = "expecting the indentifier to be a string with (length 2 to 32 chars) containing alnum (or dashes) not starting or ending with a dash [col %d]" + err8141RComponentStart = "expecting only one r-component (starting with the ?+ sequence) [col %d]" + err8141QComponentStart = "expecting only one q-component (starting with the ?= sequence) [col %d]" + err8141MalformedRComp = "expecting a non-empty r-component containing alnum, hex, or others ([~&()+,-.:=@;$_!*'] or [/?] but not at its beginning) [col %d]" + err8141MalformedQComp = "expecting a non-empty q-component containing alnum, hex, or others ([~&()+,-.:=@;$_!*'] or [/?] but not at its beginning) [col %d]" ) %%{ @@ -24,25 +37,42 @@ action mark { } action tolower { - m.tolower = append(m.tolower, m.p - m.pb) + // List of positions in the buffer to later lowercase + output.tolower = append(output.tolower, m.p - m.pb) } action set_pre { output.prefix = string(m.text()) } +action throw_pre_urn_err { + if m.parsingMode != RFC8141Only { + // Throw an error when: + // - we are entering here matching the the prefix in the namespace identifier part + // - looking ahead (3 chars) we find a colon + if pos := m.p + 3; pos < m.pe && m.data[pos] == 58 && output.prefix != "" { + m.err = fmt.Errorf(errNoUrnWithinID, pos) + fhold; + fgoto fail; + } + } +} + action set_nid { output.ID = string(m.text()) } action set_nss { - raw := m.text() - output.SS = string(raw) + output.SS = string(m.text()) // Iterate upper letters lowering them - for _, i := range m.tolower { - raw[i] = raw[i] + 32 + for _, i := range output.tolower { + m.data[m.pb+i] = m.data[m.pb+i] + 32 + } + output.norm = string(m.text()) + // Revert the buffer to the original + for _, i := range output.tolower { + m.data[m.pb+i] = m.data[m.pb+i] - 32 } - output.norm = string(raw) } action err_pre { @@ -70,30 +100,200 @@ action err_urn { } action err_hex { - m.err = fmt.Errorf(errHex, m.p) + if m.parsingMode == RFC2141Only || m.parsingMode == RFC8141Only { + m.err = fmt.Errorf(errHex, m.p) + fhold; + fgoto fail; + } +} + +action base_type { + output.kind = RFC2141; +} + +pre = ([uU] @err(err_pre) [rR] @err(err_pre) [nN] @err(err_pre)) >mark >throw_pre_urn_err %set_pre; + +nid = (alnum >mark (alnum | '-'){0,31}) $err(err_nid) %set_nid; + +hex = '%' (digit | lower | upper >tolower){2} $err(err_hex); + +sss = (alnum | [()+,\-.:=@;$_!*']); + +nss = (sss | hex)+ $err(err_nss); + +nid_not_urn = (nid - pre %err(err_urn)); + +urn = pre ':' @err(err_pre) (nid_not_urn ':' nss >mark %set_nss) %eof(base_type); + +### SCIM BEG + +action err_scim_nid { + m.err = fmt.Errorf(errSCIMNamespace, m.p) fhold; fgoto fail; } -action err_parse { - m.err = fmt.Errorf(errParse, m.p) +action err_scim_type { + m.err = fmt.Errorf(errSCIMType, m.p) fhold; fgoto fail; } -pre = ([uU][rR][nN] @err(err_pre)) >mark %set_pre; +action err_scim_name { + m.err = fmt.Errorf(errSCIMName, m.p) + fhold; + fgoto fail; +} -nid = (alnum >mark (alnum | '-'){0,31}) %set_nid; +action err_scim_other { + if m.p == m.pe { + m.err = fmt.Errorf(errSCIMOtherIncomplete, m.p-1) + } else { + m.err = fmt.Errorf(errSCIMOther, m.p) + } + fhold; + fgoto fail; +} -hex = '%' (digit | lower | upper >tolower){2} $err(err_hex); +action scim_type { + output.kind = RFC7643; +} -sss = (alnum | [()+,\-.:=@;$_!*']); +action create_scim { + output.scim = &SCIM{}; +} -nss = (sss | hex)+ $err(err_nss); +action set_scim_type { + output.scim.Type = scimschema.TypeFromString(string(m.text())) +} + +action mark_scim_name { + output.scim.pos = m.p +} + +action set_scim_name { + output.scim.Name = string(m.data[output.scim.pos:m.p]) +} + +action mark_scim_other { + output.scim.pos = m.p +} + +action set_scim_other { + output.scim.Other = string(m.data[output.scim.pos:m.p]) +} + +scim_nid = 'ietf:params:scim' >mark %set_nid %create_scim $err(err_scim_nid); + +scim_other = ':' (sss | hex)+ >mark_scim_other %set_scim_other $err(err_scim_other); + +scim_name = (alnum)+ >mark_scim_name %set_scim_name $err(err_scim_name); + +scim_type = ('schemas' | 'api' | 'param') >mark %set_scim_type $err(err_scim_type); + +scim_only := pre ':' @err(err_pre) (scim_nid ':' scim_type ':' scim_name scim_other? %set_nss) %eof(scim_type); + +### SCIM END + +### 8141 BEG + +action err_nss_8141 { + m.err = fmt.Errorf(err8141SpecificString, m.p) + fhold; + fgoto fail; +} + +action err_nid_8141 { + m.err = fmt.Errorf(err8141Identifier, m.p) + fhold; + fgoto fail; +} + +action rfc8141_type { + output.kind = RFC8141; +} + +action set_r_component { + output.rComponent = string(m.text()) +} + +action set_q_component { + output.qComponent = string(m.text()) +} + +action set_f_component { + output.fComponent = string(m.text()) +} + +action informal_nid_match { + fhold; + m.err = fmt.Errorf(err8141InformalID, m.p); + fgoto fail; +} + +action mark_r_start { + if output.rStart { + m.err = fmt.Errorf(err8141RComponentStart, m.p) + fhold; + fgoto fail; + } + output.rStart = true +} + +action mark_q_start { + if output.qStart { + m.err = fmt.Errorf(err8141QComponentStart, m.p) + fhold; + fgoto fail; + } + output.qStart = true +} + +action err_malformed_r_component { + m.err = fmt.Errorf(err8141MalformedRComp, m.p) + fhold; + fgoto fail; +} + +action err_malformed_q_component { + m.err = fmt.Errorf(err8141MalformedQComp, m.p) + fhold; + fgoto fail; +} + +pchar = (sss | '~' | '&' | hex); + +component = pchar (pchar | '/' | '?')*; + +r_start = ('?+') %mark_r_start; + +r_component = r_start <: (r_start | component)+ $err(err_malformed_r_component) >mark %set_r_component; + +q_start = ('?=') %mark_q_start; + +q_component = q_start <: (q_start | component)+ $err(err_malformed_q_component) >mark %set_q_component; + +rq_components = (r_component :>> q_component? | q_component); + +fragment = (pchar | '/' | '?')*; + +f_component = '#' fragment >mark %set_f_component; + +nss_rfc8141 = (pchar >mark (pchar | '/')*) $err(err_nss_8141) %set_nss; + +nid_rfc8141 = (alnum >mark (alnum | '-'){0,30} alnum) $err(err_nid_8141) %set_nid; + +informal_id = pre ('-' [a-zA-z0] %to(informal_nid_match)); + +nid_rfc8141_not_urn = (nid_rfc8141 - informal_id?); + +rfc8141_only := pre ':' @err(err_pre) nid_rfc8141_not_urn ':' nss_rfc8141 rq_components? f_component? %eof(rfc8141_type); + +### 8141 END fail := (any - [\n\r])* @err{ fgoto main; }; -main := (pre ':' (nid - pre %err(err_urn)) $err(err_nid) ':' nss >mark %set_nss) $err(err_parse); +main := urn; }%% @@ -103,6 +303,7 @@ main := (pre ':' (nid - pre %err(err_urn)) $err(err_nid) ':' nss >mark %set_nss) type Machine interface { Error() error Parse(input []byte) (*URN, error) + WithParsingMode(ParsingMode) } type machine struct { @@ -110,12 +311,24 @@ type machine struct { cs int p, pe, eof, pb int err error - tolower []int + startParsingAt int + parsingMode ParsingMode + parsingModeSet bool } // NewMachine creates a new FSM able to parse RFC 2141 strings. -func NewMachine() Machine { - m := &machine{} +func NewMachine(options ...Option) Machine { + m := &machine{ + parsingModeSet: false, + } + + for _, o := range options { + o(m) + } + // Set default parsing mode + if !m.parsingModeSet { + m.WithParsingMode(DefaultParsingMode) + } %% access m.; %% variable p m.p; @@ -137,7 +350,7 @@ func (m *machine) text() []byte { return m.data[m.pb:m.p] } -// Parse parses the input byte array as a RFC 2141 string. +// Parse parses the input byte array as a RFC 2141 or RFC7643 string. func (m *machine) Parse(input []byte) (*URN, error) { m.data = input m.p = 0 @@ -145,10 +358,11 @@ func (m *machine) Parse(input []byte) (*URN, error) { m.pe = len(input) m.eof = len(input) m.err = nil - m.tolower = []int{} - output := &URN{} + m.cs = m.startParsingAt + output := &URN{ + tolower: []int{}, + } - %% write init; %% write exec; if m.cs < first_final || m.cs == en_fail { @@ -157,3 +371,16 @@ func (m *machine) Parse(input []byte) (*URN, error) { return output, nil } + +func (m *machine) WithParsingMode(x ParsingMode) { + m.parsingMode = x + switch m.parsingMode { + case RFC2141Only: + m.startParsingAt = en_main + case RFC8141Only: + m.startParsingAt = en_rfc8141_only + case RFC7643Only: + m.startParsingAt = en_scim_only + } + m.parsingModeSet = true +} \ No newline at end of file diff --git a/vendor/github.com/leodido/go-urn/makefile b/vendor/github.com/leodido/go-urn/makefile index d088c044e6..68d5dd0f1b 100644 --- a/vendor/github.com/leodido/go-urn/makefile +++ b/vendor/github.com/leodido/go-urn/makefile @@ -15,18 +15,24 @@ clean: .PHONY: images images: docs/urn.png +.PHONY: snake2camel +snake2camel: + @cd ./tools/snake2camel; go build -o ../../snake2camel . + .PHONY: removecomments removecomments: - @cd ./tools/removecomments; go build -o ../../removecomments ./main.go + @cd ./tools/removecomments; go build -o ../../removecomments . machine.go: machine.go.rl +machine.go: snake2camel + machine.go: removecomments machine.go: - $(RAGEL) -Z -G2 -e -o $@ $< + $(RAGEL) -Z -G1 -e -o $@ $< @./removecomments $@ - $(MAKE) -s file=$@ snake2camel + @./snake2camel $@ $(GOFMT) $@ docs/urn.dot: machine.go.rl @@ -41,13 +47,5 @@ bench: *_test.go machine.go go test -bench=. -benchmem -benchtime=5s ./... .PHONY: tests -tests: *_test.go +tests: *_test.go $(GO_TEST) ./... - -.PHONY: snake2camel -snake2camel: - @awk -i inplace '{ \ - while ( match($$0, /(.*)([a-z]+[0-9]*)_([a-zA-Z0-9])(.*)/, cap) ) \ - $$0 = cap[1] cap[2] toupper(cap[3]) cap[4]; \ - print \ - }' $(file) \ No newline at end of file diff --git a/vendor/github.com/leodido/go-urn/options.go b/vendor/github.com/leodido/go-urn/options.go new file mode 100644 index 0000000000..c543835a28 --- /dev/null +++ b/vendor/github.com/leodido/go-urn/options.go @@ -0,0 +1,9 @@ +package urn + +type Option func(Machine) + +func WithParsingMode(mode ParsingMode) Option { + return func(m Machine) { + m.WithParsingMode(mode) + } +} diff --git a/vendor/github.com/leodido/go-urn/parsing_mode.go b/vendor/github.com/leodido/go-urn/parsing_mode.go new file mode 100644 index 0000000000..fce5aadc3c --- /dev/null +++ b/vendor/github.com/leodido/go-urn/parsing_mode.go @@ -0,0 +1,12 @@ +package urn + +type ParsingMode int + +const ( + Default ParsingMode = iota + RFC2141Only + RFC7643Only + RFC8141Only +) + +const DefaultParsingMode = RFC2141Only diff --git a/vendor/github.com/leodido/go-urn/scim.go b/vendor/github.com/leodido/go-urn/scim.go new file mode 100644 index 0000000000..f6b7aefbad --- /dev/null +++ b/vendor/github.com/leodido/go-urn/scim.go @@ -0,0 +1,48 @@ +package urn + +import ( + "encoding/json" + "fmt" + + scimschema "github.com/leodido/go-urn/scim/schema" +) + +const errInvalidSCIMURN = "invalid SCIM URN: %s" + +type SCIM struct { + Type scimschema.Type + Name string + Other string + pos int +} + +func (s SCIM) MarshalJSON() ([]byte, error) { + return json.Marshal(s.String()) +} + +func (s *SCIM) UnmarshalJSON(bytes []byte) error { + var str string + if err := json.Unmarshal(bytes, &str); err != nil { + return err + } + // Parse as SCIM + value, ok := Parse([]byte(str), WithParsingMode(RFC7643Only)) + if !ok { + return fmt.Errorf(errInvalidSCIMURN, str) + } + if value.RFC() != RFC7643 { + return fmt.Errorf(errInvalidSCIMURN, str) + } + *s = *value.SCIM() + + return nil +} + +func (s *SCIM) String() string { + ret := fmt.Sprintf("urn:ietf:params:scim:%s:%s", s.Type.String(), s.Name) + if s.Other != "" { + ret += fmt.Sprintf(":%s", s.Other) + } + + return ret +} diff --git a/vendor/github.com/leodido/go-urn/scim/schema/type.go b/vendor/github.com/leodido/go-urn/scim/schema/type.go new file mode 100644 index 0000000000..134918230f --- /dev/null +++ b/vendor/github.com/leodido/go-urn/scim/schema/type.go @@ -0,0 +1,36 @@ +package scimschema + +type Type int + +const ( + Unsupported Type = iota + Schemas + API + Param +) + +func (t Type) String() string { + switch t { + case Schemas: + return "schemas" + case API: + return "api" + case Param: + return "param" + } + + return "" +} + +func TypeFromString(input string) Type { + switch input { + case "schemas": + return Schemas + case "api": + return API + case "param": + return Param + } + + return Unsupported +} diff --git a/vendor/github.com/leodido/go-urn/urn.go b/vendor/github.com/leodido/go-urn/urn.go index d51a6c915b..894d6258dc 100644 --- a/vendor/github.com/leodido/go-urn/urn.go +++ b/vendor/github.com/leodido/go-urn/urn.go @@ -16,10 +16,18 @@ const errInvalidURN = "invalid URN: %s" // // Details at https://tools.ietf.org/html/rfc2141. type URN struct { - prefix string // Static prefix. Equal to "urn" when empty. - ID string // Namespace identifier - SS string // Namespace specific string - norm string // Normalized namespace specific string + prefix string // Static prefix. Equal to "urn" when empty. + ID string // Namespace identifier (NID) + SS string // Namespace specific string (NSS) + norm string // Normalized namespace specific string + kind Kind + scim *SCIM + rComponent string // RFC8141 + qComponent string // RFC8141 + fComponent string // RFC8141 + rStart bool // RFC8141 + qStart bool // RFC8141 + tolower []int } // Normalize turns the receiving URN into its norm version. @@ -30,12 +38,21 @@ func (u *URN) Normalize() *URN { prefix: "urn", ID: strings.ToLower(u.ID), SS: u.norm, + // rComponent: u.rComponent, + // qComponent: u.qComponent, + // fComponent: u.fComponent, } } // Equal checks the lexical equivalence of the current URN with another one. func (u *URN) Equal(x *URN) bool { - return *u.Normalize() == *x.Normalize() + if x == nil { + return false + } + nu := u.Normalize() + nx := x.Normalize() + + return nu.prefix == nx.prefix && nu.ID == nx.ID && nu.SS == nx.SS } // String reassembles the URN into a valid URN string. @@ -51,14 +68,23 @@ func (u *URN) String() string { res += "urn" } res += u.prefix + ":" + u.ID + ":" + u.SS + if u.rComponent != "" { + res += "?+" + u.rComponent + } + if u.qComponent != "" { + res += "?=" + u.qComponent + } + if u.fComponent != "" { + res += "#" + u.fComponent + } } return res } -// Parse is responsible to create an URN instance from a byte array matching the correct URN syntax. -func Parse(u []byte) (*URN, bool) { - urn, err := NewMachine().Parse(u) +// Parse is responsible to create an URN instance from a byte array matching the correct URN syntax (RFC 2141). +func Parse(u []byte, options ...Option) (*URN, bool) { + urn, err := NewMachine(options...).Parse(u) if err != nil { return nil, false } @@ -71,7 +97,7 @@ func (u URN) MarshalJSON() ([]byte, error) { return json.Marshal(u.String()) } -// MarshalJSON unmarshals a URN from JSON string form (e.g. `"urn:oid:1.2.3.4"`). +// UnmarshalJSON unmarshals a URN from JSON string form (e.g. `"urn:oid:1.2.3.4"`). func (u *URN) UnmarshalJSON(bytes []byte) error { var str string if err := json.Unmarshal(bytes, &str); err != nil { @@ -82,5 +108,34 @@ func (u *URN) UnmarshalJSON(bytes []byte) error { } else { *u = *value } + return nil -} \ No newline at end of file +} + +func (u *URN) IsSCIM() bool { + return u.kind == RFC7643 +} + +func (u *URN) SCIM() *SCIM { + if u.kind != RFC7643 { + return nil + } + + return u.scim +} + +func (u *URN) RFC() Kind { + return u.kind +} + +func (u *URN) FComponent() string { + return u.fComponent +} + +func (u *URN) QComponent() string { + return u.qComponent +} + +func (u *URN) RComponent() string { + return u.rComponent +} diff --git a/vendor/github.com/leodido/go-urn/urn8141.go b/vendor/github.com/leodido/go-urn/urn8141.go new file mode 100644 index 0000000000..da4dd062e3 --- /dev/null +++ b/vendor/github.com/leodido/go-urn/urn8141.go @@ -0,0 +1,30 @@ +package urn + +import ( + "encoding/json" + "fmt" +) + +const errInvalidURN8141 = "invalid URN per RFC 8141: %s" + +type URN8141 struct { + *URN +} + +func (u URN8141) MarshalJSON() ([]byte, error) { + return json.Marshal(u.String()) +} + +func (u *URN8141) UnmarshalJSON(bytes []byte) error { + var str string + if err := json.Unmarshal(bytes, &str); err != nil { + return err + } + if value, ok := Parse([]byte(str), WithParsingMode(RFC8141Only)); !ok { + return fmt.Errorf(errInvalidURN8141, str) + } else { + *u = URN8141{value} + } + + return nil +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/array_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/array_codec.go index 4e24f9eed6..652aa48b85 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/array_codec.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/array_codec.go @@ -14,17 +14,22 @@ import ( ) // ArrayCodec is the Codec used for bsoncore.Array values. +// +// Deprecated: ArrayCodec will not be directly accessible in Go Driver 2.0. type ArrayCodec struct{} var defaultArrayCodec = NewArrayCodec() // NewArrayCodec returns an ArrayCodec. +// +// Deprecated: NewArrayCodec will not be available in Go Driver 2.0. See +// [ArrayCodec] for more details. func NewArrayCodec() *ArrayCodec { return &ArrayCodec{} } // EncodeValue is the ValueEncoder for bsoncore.Array values. -func (ac *ArrayCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +func (ac *ArrayCodec) EncodeValue(_ EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Type() != tCoreArray { return ValueEncoderError{Name: "CoreArrayEncodeValue", Types: []reflect.Type{tCoreArray}, Received: val} } @@ -34,7 +39,7 @@ func (ac *ArrayCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val r } // DecodeValue is the ValueDecoder for bsoncore.Array values. -func (ac *ArrayCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +func (ac *ArrayCodec) DecodeValue(_ DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { if !val.CanSet() || val.Type() != tCoreArray { return ValueDecoderError{Name: "CoreArrayDecodeValue", Types: []reflect.Type{tCoreArray}, Received: val} } diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/bsoncodec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/bsoncodec.go index 098ed69f98..0693bd432f 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/bsoncodec.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/bsoncodec.go @@ -23,6 +23,8 @@ var ( // Marshaler is an interface implemented by types that can marshal themselves // into a BSON document represented as bytes. The bytes returned must be a valid // BSON document if the error is nil. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.Marshaler] instead. type Marshaler interface { MarshalBSON() ([]byte, error) } @@ -31,6 +33,8 @@ type Marshaler interface { // themselves into a BSON value as bytes. The type must be the valid type for // the bytes returned. The bytes and byte type together must be valid if the // error is nil. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.ValueMarshaler] instead. type ValueMarshaler interface { MarshalBSONValue() (bsontype.Type, []byte, error) } @@ -39,6 +43,8 @@ type ValueMarshaler interface { // document representation of themselves. The BSON bytes can be assumed to be // valid. UnmarshalBSON must copy the BSON bytes if it wishes to retain the data // after returning. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.Unmarshaler] instead. type Unmarshaler interface { UnmarshalBSON([]byte) error } @@ -47,6 +53,8 @@ type Unmarshaler interface { // BSON value representation of themselves. The BSON bytes and type can be // assumed to be valid. UnmarshalBSONValue must copy the BSON value bytes if it // wishes to retain the data after returning. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.ValueUnmarshaler] instead. type ValueUnmarshaler interface { UnmarshalBSONValue(bsontype.Type, []byte) error } @@ -111,13 +119,93 @@ func (vde ValueDecoderError) Error() string { // value. type EncodeContext struct { *Registry + + // MinSize causes the Encoder to marshal Go integer values (int, int8, int16, int32, int64, + // uint, uint8, uint16, uint32, or uint64) as the minimum BSON int size (either 32 or 64 bits) + // that can represent the integer value. + // + // Deprecated: Use bson.Encoder.IntMinSize instead. MinSize bool + + errorOnInlineDuplicates bool + stringifyMapKeysWithFmt bool + nilMapAsEmpty bool + nilSliceAsEmpty bool + nilByteSliceAsEmpty bool + omitZeroStruct bool + useJSONStructTags bool +} + +// ErrorOnInlineDuplicates causes the Encoder to return an error if there is a duplicate field in +// the marshaled BSON when the "inline" struct tag option is set. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.Encoder.ErrorOnInlineDuplicates] instead. +func (ec *EncodeContext) ErrorOnInlineDuplicates() { + ec.errorOnInlineDuplicates = true +} + +// StringifyMapKeysWithFmt causes the Encoder to convert Go map keys to BSON document field name +// strings using fmt.Sprintf() instead of the default string conversion logic. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.Encoder.StringifyMapKeysWithFmt] instead. +func (ec *EncodeContext) StringifyMapKeysWithFmt() { + ec.stringifyMapKeysWithFmt = true +} + +// NilMapAsEmpty causes the Encoder to marshal nil Go maps as empty BSON documents instead of BSON +// null. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.Encoder.NilMapAsEmpty] instead. +func (ec *EncodeContext) NilMapAsEmpty() { + ec.nilMapAsEmpty = true +} + +// NilSliceAsEmpty causes the Encoder to marshal nil Go slices as empty BSON arrays instead of BSON +// null. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.Encoder.NilSliceAsEmpty] instead. +func (ec *EncodeContext) NilSliceAsEmpty() { + ec.nilSliceAsEmpty = true +} + +// NilByteSliceAsEmpty causes the Encoder to marshal nil Go byte slices as empty BSON binary values +// instead of BSON null. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.Encoder.NilByteSliceAsEmpty] instead. +func (ec *EncodeContext) NilByteSliceAsEmpty() { + ec.nilByteSliceAsEmpty = true +} + +// OmitZeroStruct causes the Encoder to consider the zero value for a struct (e.g. MyStruct{}) +// as empty and omit it from the marshaled BSON when the "omitempty" struct tag option is set. +// +// Note that the Encoder only examines exported struct fields when determining if a struct is the +// zero value. It considers pointers to a zero struct value (e.g. &MyStruct{}) not empty. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.Encoder.OmitZeroStruct] instead. +func (ec *EncodeContext) OmitZeroStruct() { + ec.omitZeroStruct = true +} + +// UseJSONStructTags causes the Encoder to fall back to using the "json" struct tag if a "bson" +// struct tag is not specified. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.Encoder.UseJSONStructTags] instead. +func (ec *EncodeContext) UseJSONStructTags() { + ec.useJSONStructTags = true } // DecodeContext is the contextual information required for a Codec to decode a // value. type DecodeContext struct { *Registry + + // Truncate, if true, instructs decoders to to truncate the fractional part of BSON "double" + // values when attempting to unmarshal them into a Go integer (int, int8, int16, int32, int64, + // uint, uint8, uint16, uint32, or uint64) struct field. The truncation logic does not apply to + // BSON "decimal128" values. + // + // Deprecated: Use bson.Decoder.AllowTruncatingDoubles instead. Truncate bool // Ancestor is the type of a containing document. This is mainly used to determine what type @@ -125,7 +213,7 @@ type DecodeContext struct { // Ancestor is a bson.M, BSON embedded document values being decoded into an empty interface // will be decoded into a bson.M. // - // Deprecated: Use DefaultDocumentM or DefaultDocumentD instead. + // Deprecated: Use bson.Decoder.DefaultDocumentM or bson.Decoder.DefaultDocumentD instead. Ancestor reflect.Type // defaultDocumentType specifies the Go type to decode top-level and nested BSON documents into. In particular, the @@ -133,22 +221,74 @@ type DecodeContext struct { // set to a type that a BSON document cannot be unmarshaled into (e.g. "string"), unmarshalling will result in an // error. DocumentType overrides the Ancestor field. defaultDocumentType reflect.Type + + binaryAsSlice bool + useJSONStructTags bool + useLocalTimeZone bool + zeroMaps bool + zeroStructs bool } -// DefaultDocumentM will decode empty documents using the primitive.M type. This behavior is restricted to data typed as -// "interface{}" or "map[string]interface{}". +// BinaryAsSlice causes the Decoder to unmarshal BSON binary field values that are the "Generic" or +// "Old" BSON binary subtype as a Go byte slice instead of a primitive.Binary. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.Decoder.BinaryAsSlice] instead. +func (dc *DecodeContext) BinaryAsSlice() { + dc.binaryAsSlice = true +} + +// UseJSONStructTags causes the Decoder to fall back to using the "json" struct tag if a "bson" +// struct tag is not specified. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.Decoder.UseJSONStructTags] instead. +func (dc *DecodeContext) UseJSONStructTags() { + dc.useJSONStructTags = true +} + +// UseLocalTimeZone causes the Decoder to unmarshal time.Time values in the local timezone instead +// of the UTC timezone. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.Decoder.UseLocalTimeZone] instead. +func (dc *DecodeContext) UseLocalTimeZone() { + dc.useLocalTimeZone = true +} + +// ZeroMaps causes the Decoder to delete any existing values from Go maps in the destination value +// passed to Decode before unmarshaling BSON documents into them. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.Decoder.ZeroMaps] instead. +func (dc *DecodeContext) ZeroMaps() { + dc.zeroMaps = true +} + +// ZeroStructs causes the Decoder to delete any existing values from Go structs in the destination +// value passed to Decode before unmarshaling BSON documents into them. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.Decoder.ZeroStructs] instead. +func (dc *DecodeContext) ZeroStructs() { + dc.zeroStructs = true +} + +// DefaultDocumentM causes the Decoder to always unmarshal documents into the primitive.M type. This +// behavior is restricted to data typed as "interface{}" or "map[string]interface{}". +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.Decoder.DefaultDocumentM] instead. func (dc *DecodeContext) DefaultDocumentM() { dc.defaultDocumentType = reflect.TypeOf(primitive.M{}) } -// DefaultDocumentD will decode empty documents using the primitive.D type. This behavior is restricted to data typed as -// "interface{}" or "map[string]interface{}". +// DefaultDocumentD causes the Decoder to always unmarshal documents into the primitive.D type. This +// behavior is restricted to data typed as "interface{}" or "map[string]interface{}". +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.Decoder.DefaultDocumentD] instead. func (dc *DecodeContext) DefaultDocumentD() { dc.defaultDocumentType = reflect.TypeOf(primitive.D{}) } -// ValueCodec is the interface that groups the methods to encode and decode +// ValueCodec is an interface for encoding and decoding a reflect.Value. // values. +// +// Deprecated: Use [ValueEncoder] and [ValueDecoder] instead. type ValueCodec interface { ValueEncoder ValueDecoder @@ -233,6 +373,10 @@ func decodeTypeOrValueWithInfo(vd ValueDecoder, td typeDecoder, dc DecodeContext // CodecZeroer is the interface implemented by Codecs that can also determine if // a value of the type that would be encoded is zero. +// +// Deprecated: Defining custom rules for the zero/empty value will not be supported in Go Driver +// 2.0. Users who want to omit empty complex values should use a pointer field and set the value to +// nil instead. type CodecZeroer interface { IsTypeZero(interface{}) bool } diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/byte_slice_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/byte_slice_codec.go index 5a916cc159..0134b5a94b 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/byte_slice_codec.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/byte_slice_codec.go @@ -16,18 +16,45 @@ import ( ) // ByteSliceCodec is the Codec used for []byte values. +// +// Deprecated: ByteSliceCodec will not be directly configurable in Go Driver +// 2.0. To configure the byte slice encode and decode behavior, use the +// configuration methods on a [go.mongodb.org/mongo-driver/bson.Encoder] or +// [go.mongodb.org/mongo-driver/bson.Decoder]. To configure the byte slice +// encode and decode behavior for a mongo.Client, use +// [go.mongodb.org/mongo-driver/mongo/options.ClientOptions.SetBSONOptions]. +// +// For example, to configure a mongo.Client to encode nil byte slices as empty +// BSON binary values, use: +// +// opt := options.Client().SetBSONOptions(&options.BSONOptions{ +// NilByteSliceAsEmpty: true, +// }) +// +// See the deprecation notice for each field in ByteSliceCodec for the +// corresponding settings. type ByteSliceCodec struct { + // EncodeNilAsEmpty causes EncodeValue to marshal nil Go byte slices as empty BSON binary values + // instead of BSON null. + // + // Deprecated: Use bson.Encoder.NilByteSliceAsEmpty or options.BSONOptions.NilByteSliceAsEmpty + // instead. EncodeNilAsEmpty bool } var ( defaultByteSliceCodec = NewByteSliceCodec() - _ ValueCodec = defaultByteSliceCodec + // Assert that defaultByteSliceCodec satisfies the typeDecoder interface, which allows it to be + // used by collection type decoders (e.g. map, slice, etc) to set individual values in a + // collection. _ typeDecoder = defaultByteSliceCodec ) -// NewByteSliceCodec returns a StringCodec with options opts. +// NewByteSliceCodec returns a ByteSliceCodec with options opts. +// +// Deprecated: NewByteSliceCodec will not be available in Go Driver 2.0. See +// [ByteSliceCodec] for more details. func NewByteSliceCodec(opts ...*bsonoptions.ByteSliceCodecOptions) *ByteSliceCodec { byteSliceOpt := bsonoptions.MergeByteSliceCodecOptions(opts...) codec := ByteSliceCodec{} @@ -42,13 +69,13 @@ func (bsc *ByteSliceCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, if !val.IsValid() || val.Type() != tByteSlice { return ValueEncoderError{Name: "ByteSliceEncodeValue", Types: []reflect.Type{tByteSlice}, Received: val} } - if val.IsNil() && !bsc.EncodeNilAsEmpty { + if val.IsNil() && !bsc.EncodeNilAsEmpty && !ec.nilByteSliceAsEmpty { return vw.WriteNull() } return vw.WriteBinary(val.Interface().([]byte)) } -func (bsc *ByteSliceCodec) decodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { +func (bsc *ByteSliceCodec) decodeType(_ DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { if t != tByteSlice { return emptyValue, ValueDecoderError{ Name: "ByteSliceDecodeValue", diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/codec_cache.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/codec_cache.go new file mode 100644 index 0000000000..844b50299f --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/codec_cache.go @@ -0,0 +1,166 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// 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 + +package bsoncodec + +import ( + "reflect" + "sync" + "sync/atomic" +) + +// Runtime check that the kind encoder and decoder caches can store any valid +// reflect.Kind constant. +func init() { + if s := reflect.Kind(len(kindEncoderCache{}.entries)).String(); s != "kind27" { + panic("The capacity of kindEncoderCache is too small.\n" + + "This is due to a new type being added to reflect.Kind.") + } +} + +// statically assert array size +var _ = (kindEncoderCache{}).entries[reflect.UnsafePointer] +var _ = (kindDecoderCache{}).entries[reflect.UnsafePointer] + +type typeEncoderCache struct { + cache sync.Map // map[reflect.Type]ValueEncoder +} + +func (c *typeEncoderCache) Store(rt reflect.Type, enc ValueEncoder) { + c.cache.Store(rt, enc) +} + +func (c *typeEncoderCache) Load(rt reflect.Type) (ValueEncoder, bool) { + if v, _ := c.cache.Load(rt); v != nil { + return v.(ValueEncoder), true + } + return nil, false +} + +func (c *typeEncoderCache) LoadOrStore(rt reflect.Type, enc ValueEncoder) ValueEncoder { + if v, loaded := c.cache.LoadOrStore(rt, enc); loaded { + enc = v.(ValueEncoder) + } + return enc +} + +func (c *typeEncoderCache) Clone() *typeEncoderCache { + cc := new(typeEncoderCache) + c.cache.Range(func(k, v interface{}) bool { + if k != nil && v != nil { + cc.cache.Store(k, v) + } + return true + }) + return cc +} + +type typeDecoderCache struct { + cache sync.Map // map[reflect.Type]ValueDecoder +} + +func (c *typeDecoderCache) Store(rt reflect.Type, dec ValueDecoder) { + c.cache.Store(rt, dec) +} + +func (c *typeDecoderCache) Load(rt reflect.Type) (ValueDecoder, bool) { + if v, _ := c.cache.Load(rt); v != nil { + return v.(ValueDecoder), true + } + return nil, false +} + +func (c *typeDecoderCache) LoadOrStore(rt reflect.Type, dec ValueDecoder) ValueDecoder { + if v, loaded := c.cache.LoadOrStore(rt, dec); loaded { + dec = v.(ValueDecoder) + } + return dec +} + +func (c *typeDecoderCache) Clone() *typeDecoderCache { + cc := new(typeDecoderCache) + c.cache.Range(func(k, v interface{}) bool { + if k != nil && v != nil { + cc.cache.Store(k, v) + } + return true + }) + return cc +} + +// atomic.Value requires that all calls to Store() have the same concrete type +// so we wrap the ValueEncoder with a kindEncoderCacheEntry to ensure the type +// is always the same (since different concrete types may implement the +// ValueEncoder interface). +type kindEncoderCacheEntry struct { + enc ValueEncoder +} + +type kindEncoderCache struct { + entries [reflect.UnsafePointer + 1]atomic.Value // *kindEncoderCacheEntry +} + +func (c *kindEncoderCache) Store(rt reflect.Kind, enc ValueEncoder) { + if enc != nil && rt < reflect.Kind(len(c.entries)) { + c.entries[rt].Store(&kindEncoderCacheEntry{enc: enc}) + } +} + +func (c *kindEncoderCache) Load(rt reflect.Kind) (ValueEncoder, bool) { + if rt < reflect.Kind(len(c.entries)) { + if ent, ok := c.entries[rt].Load().(*kindEncoderCacheEntry); ok { + return ent.enc, ent.enc != nil + } + } + return nil, false +} + +func (c *kindEncoderCache) Clone() *kindEncoderCache { + cc := new(kindEncoderCache) + for i, v := range c.entries { + if val := v.Load(); val != nil { + cc.entries[i].Store(val) + } + } + return cc +} + +// atomic.Value requires that all calls to Store() have the same concrete type +// so we wrap the ValueDecoder with a kindDecoderCacheEntry to ensure the type +// is always the same (since different concrete types may implement the +// ValueDecoder interface). +type kindDecoderCacheEntry struct { + dec ValueDecoder +} + +type kindDecoderCache struct { + entries [reflect.UnsafePointer + 1]atomic.Value // *kindDecoderCacheEntry +} + +func (c *kindDecoderCache) Store(rt reflect.Kind, dec ValueDecoder) { + if rt < reflect.Kind(len(c.entries)) { + c.entries[rt].Store(&kindDecoderCacheEntry{dec: dec}) + } +} + +func (c *kindDecoderCache) Load(rt reflect.Kind) (ValueDecoder, bool) { + if rt < reflect.Kind(len(c.entries)) { + if ent, ok := c.entries[rt].Load().(*kindDecoderCacheEntry); ok { + return ent.dec, ent.dec != nil + } + } + return nil, false +} + +func (c *kindDecoderCache) Clone() *kindDecoderCache { + cc := new(kindDecoderCache) + for i, v := range c.entries { + if val := v.Load(); val != nil { + cc.entries[i].Store(val) + } + } + return cc +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_decoders.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_decoders.go index e95cab585f..7e08aab35e 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_decoders.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_decoders.go @@ -24,7 +24,7 @@ import ( var ( defaultValueDecoders DefaultValueDecoders - errCannotTruncate = errors.New("float64 can only be truncated to an integer type when truncation is enabled") + errCannotTruncate = errors.New("float64 can only be truncated to a lower precision type when truncation is enabled") ) type decodeBinaryError struct { @@ -41,13 +41,16 @@ func newDefaultStructCodec() *StructCodec { if err != nil { // This function is called from the codec registration path, so errors can't be propagated. If there's an error // constructing the StructCodec, we panic to avoid losing it. - panic(fmt.Errorf("error creating default StructCodec: %v", err)) + panic(fmt.Errorf("error creating default StructCodec: %w", err)) } return codec } // DefaultValueDecoders is a namespace type for the default ValueDecoders used // when creating a registry. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default +// value decoders registered. type DefaultValueDecoders struct{} // RegisterDefaultDecoders will register the decoder methods attached to DefaultValueDecoders with @@ -56,6 +59,9 @@ type DefaultValueDecoders struct{} // There is no support for decoding map[string]interface{} because there is no decoder for // interface{}, so users must either register this decoder themselves or use the // EmptyInterfaceDecoder available in the bson package. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default +// value decoders registered. func (dvd DefaultValueDecoders) RegisterDefaultDecoders(rb *RegistryBuilder) { if rb == nil { panic(errors.New("argument to RegisterDefaultDecoders must not be nil")) @@ -132,6 +138,9 @@ func (dvd DefaultValueDecoders) RegisterDefaultDecoders(rb *RegistryBuilder) { } // DDecodeValue is the ValueDecoderFunc for primitive.D instances. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default +// value decoders registered. func (dvd DefaultValueDecoders) DDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { if !val.IsValid() || !val.CanSet() || val.Type() != tD { return ValueDecoderError{Name: "DDecodeValue", Kinds: []reflect.Kind{reflect.Slice}, Received: val} @@ -169,7 +178,7 @@ func (dvd DefaultValueDecoders) DDecodeValue(dc DecodeContext, vr bsonrw.ValueRe for { key, elemVr, err := dr.ReadElement() - if err == bsonrw.ErrEOD { + if errors.Is(err, bsonrw.ErrEOD) { break } else if err != nil { return err @@ -188,7 +197,7 @@ func (dvd DefaultValueDecoders) DDecodeValue(dc DecodeContext, vr bsonrw.ValueRe return nil } -func (dvd DefaultValueDecoders) booleanDecodeType(dctx DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { +func (dvd DefaultValueDecoders) booleanDecodeType(_ DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { if t.Kind() != reflect.Bool { return emptyValue, ValueDecoderError{ Name: "BooleanDecodeValue", @@ -235,6 +244,9 @@ func (dvd DefaultValueDecoders) booleanDecodeType(dctx DecodeContext, vr bsonrw. } // BooleanDecodeValue is the ValueDecoderFunc for bool types. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default +// value decoders registered. func (dvd DefaultValueDecoders) BooleanDecodeValue(dctx DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { if !val.IsValid() || !val.CanSet() || val.Kind() != reflect.Bool { return ValueDecoderError{Name: "BooleanDecodeValue", Kinds: []reflect.Kind{reflect.Bool}, Received: val} @@ -333,6 +345,9 @@ func (DefaultValueDecoders) intDecodeType(dc DecodeContext, vr bsonrw.ValueReade } // IntDecodeValue is the ValueDecoderFunc for int types. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default +// value decoders registered. func (dvd DefaultValueDecoders) IntDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { if !val.CanSet() { return ValueDecoderError{ @@ -434,7 +449,7 @@ func (dvd DefaultValueDecoders) UintDecodeValue(dc DecodeContext, vr bsonrw.Valu return nil } -func (dvd DefaultValueDecoders) floatDecodeType(ec DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { +func (dvd DefaultValueDecoders) floatDecodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { var f float64 var err error switch vrType := vr.Type(); vrType { @@ -477,7 +492,7 @@ func (dvd DefaultValueDecoders) floatDecodeType(ec DecodeContext, vr bsonrw.Valu switch t.Kind() { case reflect.Float32: - if !ec.Truncate && float64(float32(f)) != f { + if !dc.Truncate && float64(float32(f)) != f { return emptyValue, errCannotTruncate } @@ -494,6 +509,9 @@ func (dvd DefaultValueDecoders) floatDecodeType(ec DecodeContext, vr bsonrw.Valu } // FloatDecodeValue is the ValueDecoderFunc for float types. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default +// value decoders registered. func (dvd DefaultValueDecoders) FloatDecodeValue(ec DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { if !val.CanSet() { return ValueDecoderError{ @@ -515,7 +533,7 @@ func (dvd DefaultValueDecoders) FloatDecodeValue(ec DecodeContext, vr bsonrw.Val // StringDecodeValue is the ValueDecoderFunc for string types. // // Deprecated: StringDecodeValue is not registered by default. Use StringCodec.DecodeValue instead. -func (dvd DefaultValueDecoders) StringDecodeValue(dctx DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +func (dvd DefaultValueDecoders) StringDecodeValue(_ DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { var str string var err error switch vr.Type() { @@ -536,7 +554,7 @@ func (dvd DefaultValueDecoders) StringDecodeValue(dctx DecodeContext, vr bsonrw. return nil } -func (DefaultValueDecoders) javaScriptDecodeType(dctx DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { +func (DefaultValueDecoders) javaScriptDecodeType(_ DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { if t != tJavaScript { return emptyValue, ValueDecoderError{ Name: "JavaScriptDecodeValue", @@ -565,6 +583,9 @@ func (DefaultValueDecoders) javaScriptDecodeType(dctx DecodeContext, vr bsonrw.V } // JavaScriptDecodeValue is the ValueDecoderFunc for the primitive.JavaScript type. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default +// value decoders registered. func (dvd DefaultValueDecoders) JavaScriptDecodeValue(dctx DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { if !val.CanSet() || val.Type() != tJavaScript { return ValueDecoderError{Name: "JavaScriptDecodeValue", Types: []reflect.Type{tJavaScript}, Received: val} @@ -579,7 +600,7 @@ func (dvd DefaultValueDecoders) JavaScriptDecodeValue(dctx DecodeContext, vr bso return nil } -func (DefaultValueDecoders) symbolDecodeType(dctx DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { +func (DefaultValueDecoders) symbolDecodeType(_ DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { if t != tSymbol { return emptyValue, ValueDecoderError{ Name: "SymbolDecodeValue", @@ -620,6 +641,9 @@ func (DefaultValueDecoders) symbolDecodeType(dctx DecodeContext, vr bsonrw.Value } // SymbolDecodeValue is the ValueDecoderFunc for the primitive.Symbol type. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default +// value decoders registered. func (dvd DefaultValueDecoders) SymbolDecodeValue(dctx DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { if !val.CanSet() || val.Type() != tSymbol { return ValueDecoderError{Name: "SymbolDecodeValue", Types: []reflect.Type{tSymbol}, Received: val} @@ -634,7 +658,7 @@ func (dvd DefaultValueDecoders) SymbolDecodeValue(dctx DecodeContext, vr bsonrw. return nil } -func (DefaultValueDecoders) binaryDecodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { +func (DefaultValueDecoders) binaryDecodeType(_ DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { if t != tBinary { return emptyValue, ValueDecoderError{ Name: "BinaryDecodeValue", @@ -664,6 +688,9 @@ func (DefaultValueDecoders) binaryDecodeType(dc DecodeContext, vr bsonrw.ValueRe } // BinaryDecodeValue is the ValueDecoderFunc for Binary. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default +// value decoders registered. func (dvd DefaultValueDecoders) BinaryDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { if !val.CanSet() || val.Type() != tBinary { return ValueDecoderError{Name: "BinaryDecodeValue", Types: []reflect.Type{tBinary}, Received: val} @@ -678,7 +705,7 @@ func (dvd DefaultValueDecoders) BinaryDecodeValue(dc DecodeContext, vr bsonrw.Va return nil } -func (DefaultValueDecoders) undefinedDecodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { +func (DefaultValueDecoders) undefinedDecodeType(_ DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { if t != tUndefined { return emptyValue, ValueDecoderError{ Name: "UndefinedDecodeValue", @@ -704,6 +731,9 @@ func (DefaultValueDecoders) undefinedDecodeType(dc DecodeContext, vr bsonrw.Valu } // UndefinedDecodeValue is the ValueDecoderFunc for Undefined. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default +// value decoders registered. func (dvd DefaultValueDecoders) UndefinedDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { if !val.CanSet() || val.Type() != tUndefined { return ValueDecoderError{Name: "UndefinedDecodeValue", Types: []reflect.Type{tUndefined}, Received: val} @@ -719,7 +749,7 @@ func (dvd DefaultValueDecoders) UndefinedDecodeValue(dc DecodeContext, vr bsonrw } // Accept both 12-byte string and pretty-printed 24-byte hex string formats. -func (dvd DefaultValueDecoders) objectIDDecodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { +func (dvd DefaultValueDecoders) objectIDDecodeType(_ DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { if t != tOID { return emptyValue, ValueDecoderError{ Name: "ObjectIDDecodeValue", @@ -765,6 +795,9 @@ func (dvd DefaultValueDecoders) objectIDDecodeType(dc DecodeContext, vr bsonrw.V } // ObjectIDDecodeValue is the ValueDecoderFunc for primitive.ObjectID. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default +// value decoders registered. func (dvd DefaultValueDecoders) ObjectIDDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { if !val.CanSet() || val.Type() != tOID { return ValueDecoderError{Name: "ObjectIDDecodeValue", Types: []reflect.Type{tOID}, Received: val} @@ -779,7 +812,7 @@ func (dvd DefaultValueDecoders) ObjectIDDecodeValue(dc DecodeContext, vr bsonrw. return nil } -func (DefaultValueDecoders) dateTimeDecodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { +func (DefaultValueDecoders) dateTimeDecodeType(_ DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { if t != tDateTime { return emptyValue, ValueDecoderError{ Name: "DateTimeDecodeValue", @@ -808,6 +841,9 @@ func (DefaultValueDecoders) dateTimeDecodeType(dc DecodeContext, vr bsonrw.Value } // DateTimeDecodeValue is the ValueDecoderFunc for DateTime. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default +// value decoders registered. func (dvd DefaultValueDecoders) DateTimeDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { if !val.CanSet() || val.Type() != tDateTime { return ValueDecoderError{Name: "DateTimeDecodeValue", Types: []reflect.Type{tDateTime}, Received: val} @@ -822,7 +858,7 @@ func (dvd DefaultValueDecoders) DateTimeDecodeValue(dc DecodeContext, vr bsonrw. return nil } -func (DefaultValueDecoders) nullDecodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { +func (DefaultValueDecoders) nullDecodeType(_ DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { if t != tNull { return emptyValue, ValueDecoderError{ Name: "NullDecodeValue", @@ -848,6 +884,9 @@ func (DefaultValueDecoders) nullDecodeType(dc DecodeContext, vr bsonrw.ValueRead } // NullDecodeValue is the ValueDecoderFunc for Null. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default +// value decoders registered. func (dvd DefaultValueDecoders) NullDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { if !val.CanSet() || val.Type() != tNull { return ValueDecoderError{Name: "NullDecodeValue", Types: []reflect.Type{tNull}, Received: val} @@ -862,7 +901,7 @@ func (dvd DefaultValueDecoders) NullDecodeValue(dc DecodeContext, vr bsonrw.Valu return nil } -func (DefaultValueDecoders) regexDecodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { +func (DefaultValueDecoders) regexDecodeType(_ DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { if t != tRegex { return emptyValue, ValueDecoderError{ Name: "RegexDecodeValue", @@ -891,6 +930,9 @@ func (DefaultValueDecoders) regexDecodeType(dc DecodeContext, vr bsonrw.ValueRea } // RegexDecodeValue is the ValueDecoderFunc for Regex. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default +// value decoders registered. func (dvd DefaultValueDecoders) RegexDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { if !val.CanSet() || val.Type() != tRegex { return ValueDecoderError{Name: "RegexDecodeValue", Types: []reflect.Type{tRegex}, Received: val} @@ -905,7 +947,7 @@ func (dvd DefaultValueDecoders) RegexDecodeValue(dc DecodeContext, vr bsonrw.Val return nil } -func (DefaultValueDecoders) dBPointerDecodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { +func (DefaultValueDecoders) dBPointerDecodeType(_ DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { if t != tDBPointer { return emptyValue, ValueDecoderError{ Name: "DBPointerDecodeValue", @@ -935,6 +977,9 @@ func (DefaultValueDecoders) dBPointerDecodeType(dc DecodeContext, vr bsonrw.Valu } // DBPointerDecodeValue is the ValueDecoderFunc for DBPointer. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default +// value decoders registered. func (dvd DefaultValueDecoders) DBPointerDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { if !val.CanSet() || val.Type() != tDBPointer { return ValueDecoderError{Name: "DBPointerDecodeValue", Types: []reflect.Type{tDBPointer}, Received: val} @@ -949,7 +994,7 @@ func (dvd DefaultValueDecoders) DBPointerDecodeValue(dc DecodeContext, vr bsonrw return nil } -func (DefaultValueDecoders) timestampDecodeType(dc DecodeContext, vr bsonrw.ValueReader, reflectType reflect.Type) (reflect.Value, error) { +func (DefaultValueDecoders) timestampDecodeType(_ DecodeContext, vr bsonrw.ValueReader, reflectType reflect.Type) (reflect.Value, error) { if reflectType != tTimestamp { return emptyValue, ValueDecoderError{ Name: "TimestampDecodeValue", @@ -978,6 +1023,9 @@ func (DefaultValueDecoders) timestampDecodeType(dc DecodeContext, vr bsonrw.Valu } // TimestampDecodeValue is the ValueDecoderFunc for Timestamp. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default +// value decoders registered. func (dvd DefaultValueDecoders) TimestampDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { if !val.CanSet() || val.Type() != tTimestamp { return ValueDecoderError{Name: "TimestampDecodeValue", Types: []reflect.Type{tTimestamp}, Received: val} @@ -992,7 +1040,7 @@ func (dvd DefaultValueDecoders) TimestampDecodeValue(dc DecodeContext, vr bsonrw return nil } -func (DefaultValueDecoders) minKeyDecodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { +func (DefaultValueDecoders) minKeyDecodeType(_ DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { if t != tMinKey { return emptyValue, ValueDecoderError{ Name: "MinKeyDecodeValue", @@ -1020,6 +1068,9 @@ func (DefaultValueDecoders) minKeyDecodeType(dc DecodeContext, vr bsonrw.ValueRe } // MinKeyDecodeValue is the ValueDecoderFunc for MinKey. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default +// value decoders registered. func (dvd DefaultValueDecoders) MinKeyDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { if !val.CanSet() || val.Type() != tMinKey { return ValueDecoderError{Name: "MinKeyDecodeValue", Types: []reflect.Type{tMinKey}, Received: val} @@ -1034,7 +1085,7 @@ func (dvd DefaultValueDecoders) MinKeyDecodeValue(dc DecodeContext, vr bsonrw.Va return nil } -func (DefaultValueDecoders) maxKeyDecodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { +func (DefaultValueDecoders) maxKeyDecodeType(_ DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { if t != tMaxKey { return emptyValue, ValueDecoderError{ Name: "MaxKeyDecodeValue", @@ -1062,6 +1113,9 @@ func (DefaultValueDecoders) maxKeyDecodeType(dc DecodeContext, vr bsonrw.ValueRe } // MaxKeyDecodeValue is the ValueDecoderFunc for MaxKey. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default +// value decoders registered. func (dvd DefaultValueDecoders) MaxKeyDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { if !val.CanSet() || val.Type() != tMaxKey { return ValueDecoderError{Name: "MaxKeyDecodeValue", Types: []reflect.Type{tMaxKey}, Received: val} @@ -1076,7 +1130,7 @@ func (dvd DefaultValueDecoders) MaxKeyDecodeValue(dc DecodeContext, vr bsonrw.Va return nil } -func (dvd DefaultValueDecoders) decimal128DecodeType(dctx DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { +func (dvd DefaultValueDecoders) decimal128DecodeType(_ DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { if t != tDecimal { return emptyValue, ValueDecoderError{ Name: "Decimal128DecodeValue", @@ -1105,6 +1159,9 @@ func (dvd DefaultValueDecoders) decimal128DecodeType(dctx DecodeContext, vr bson } // Decimal128DecodeValue is the ValueDecoderFunc for primitive.Decimal128. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default +// value decoders registered. func (dvd DefaultValueDecoders) Decimal128DecodeValue(dctx DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { if !val.CanSet() || val.Type() != tDecimal { return ValueDecoderError{Name: "Decimal128DecodeValue", Types: []reflect.Type{tDecimal}, Received: val} @@ -1119,7 +1176,7 @@ func (dvd DefaultValueDecoders) Decimal128DecodeValue(dctx DecodeContext, vr bso return nil } -func (dvd DefaultValueDecoders) jsonNumberDecodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { +func (dvd DefaultValueDecoders) jsonNumberDecodeType(_ DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { if t != tJSONNumber { return emptyValue, ValueDecoderError{ Name: "JSONNumberDecodeValue", @@ -1164,6 +1221,9 @@ func (dvd DefaultValueDecoders) jsonNumberDecodeType(dc DecodeContext, vr bsonrw } // JSONNumberDecodeValue is the ValueDecoderFunc for json.Number. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default +// value decoders registered. func (dvd DefaultValueDecoders) JSONNumberDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { if !val.CanSet() || val.Type() != tJSONNumber { return ValueDecoderError{Name: "JSONNumberDecodeValue", Types: []reflect.Type{tJSONNumber}, Received: val} @@ -1178,7 +1238,7 @@ func (dvd DefaultValueDecoders) JSONNumberDecodeValue(dc DecodeContext, vr bsonr return nil } -func (dvd DefaultValueDecoders) urlDecodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { +func (dvd DefaultValueDecoders) urlDecodeType(_ DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { if t != tURL { return emptyValue, ValueDecoderError{ Name: "URLDecodeValue", @@ -1213,6 +1273,9 @@ func (dvd DefaultValueDecoders) urlDecodeType(dc DecodeContext, vr bsonrw.ValueR } // URLDecodeValue is the ValueDecoderFunc for url.URL. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default +// value decoders registered. func (dvd DefaultValueDecoders) URLDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { if !val.CanSet() || val.Type() != tURL { return ValueDecoderError{Name: "URLDecodeValue", Types: []reflect.Type{tURL}, Received: val} @@ -1230,7 +1293,7 @@ func (dvd DefaultValueDecoders) URLDecodeValue(dc DecodeContext, vr bsonrw.Value // TimeDecodeValue is the ValueDecoderFunc for time.Time. // // Deprecated: TimeDecodeValue is not registered by default. Use TimeCodec.DecodeValue instead. -func (dvd DefaultValueDecoders) TimeDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +func (dvd DefaultValueDecoders) TimeDecodeValue(_ DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { if vr.Type() != bsontype.DateTime { return fmt.Errorf("cannot decode %v into a time.Time", vr.Type()) } @@ -1251,7 +1314,7 @@ func (dvd DefaultValueDecoders) TimeDecodeValue(dc DecodeContext, vr bsonrw.Valu // ByteSliceDecodeValue is the ValueDecoderFunc for []byte. // // Deprecated: ByteSliceDecodeValue is not registered by default. Use ByteSliceCodec.DecodeValue instead. -func (dvd DefaultValueDecoders) ByteSliceDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +func (dvd DefaultValueDecoders) ByteSliceDecodeValue(_ DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { if vr.Type() != bsontype.Binary && vr.Type() != bsontype.Null { return fmt.Errorf("cannot decode %v into a []byte", vr.Type()) } @@ -1316,7 +1379,7 @@ func (dvd DefaultValueDecoders) MapDecodeValue(dc DecodeContext, vr bsonrw.Value keyType := val.Type().Key() for { key, vr, err := dr.ReadElement() - if err == bsonrw.ErrEOD { + if errors.Is(err, bsonrw.ErrEOD) { break } if err != nil { @@ -1336,6 +1399,9 @@ func (dvd DefaultValueDecoders) MapDecodeValue(dc DecodeContext, vr bsonrw.Value } // ArrayDecodeValue is the ValueDecoderFunc for array types. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default +// value decoders registered. func (dvd DefaultValueDecoders) ArrayDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { if !val.IsValid() || val.Kind() != reflect.Array { return ValueDecoderError{Name: "ArrayDecodeValue", Kinds: []reflect.Kind{reflect.Array}, Received: val} @@ -1447,7 +1513,10 @@ func (dvd DefaultValueDecoders) SliceDecodeValue(dc DecodeContext, vr bsonrw.Val } // ValueUnmarshalerDecodeValue is the ValueDecoderFunc for ValueUnmarshaler implementations. -func (dvd DefaultValueDecoders) ValueUnmarshalerDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default +// value decoders registered. +func (dvd DefaultValueDecoders) ValueUnmarshalerDecodeValue(_ DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { if !val.IsValid() || (!val.Type().Implements(tValueUnmarshaler) && !reflect.PtrTo(val.Type()).Implements(tValueUnmarshaler)) { return ValueDecoderError{Name: "ValueUnmarshalerDecodeValue", Types: []reflect.Type{tValueUnmarshaler}, Received: val} } @@ -1471,16 +1540,19 @@ func (dvd DefaultValueDecoders) ValueUnmarshalerDecodeValue(dc DecodeContext, vr return err } - fn := val.Convert(tValueUnmarshaler).MethodByName("UnmarshalBSONValue") - errVal := fn.Call([]reflect.Value{reflect.ValueOf(t), reflect.ValueOf(src)})[0] - if !errVal.IsNil() { - return errVal.Interface().(error) + m, ok := val.Interface().(ValueUnmarshaler) + if !ok { + // NB: this error should be unreachable due to the above checks + return ValueDecoderError{Name: "ValueUnmarshalerDecodeValue", Types: []reflect.Type{tValueUnmarshaler}, Received: val} } - return nil + return m.UnmarshalBSONValue(t, src) } // UnmarshalerDecodeValue is the ValueDecoderFunc for Unmarshaler implementations. -func (dvd DefaultValueDecoders) UnmarshalerDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default +// value decoders registered. +func (dvd DefaultValueDecoders) UnmarshalerDecodeValue(_ DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { if !val.IsValid() || (!val.Type().Implements(tUnmarshaler) && !reflect.PtrTo(val.Type()).Implements(tUnmarshaler)) { return ValueDecoderError{Name: "UnmarshalerDecodeValue", Types: []reflect.Type{tUnmarshaler}, Received: val} } @@ -1516,12 +1588,12 @@ func (dvd DefaultValueDecoders) UnmarshalerDecodeValue(dc DecodeContext, vr bson val = val.Addr() // If the type doesn't implement the interface, a pointer to it must. } - fn := val.Convert(tUnmarshaler).MethodByName("UnmarshalBSON") - errVal := fn.Call([]reflect.Value{reflect.ValueOf(src)})[0] - if !errVal.IsNil() { - return errVal.Interface().(error) + m, ok := val.Interface().(Unmarshaler) + if !ok { + // NB: this error should be unreachable due to the above checks + return ValueDecoderError{Name: "UnmarshalerDecodeValue", Types: []reflect.Type{tUnmarshaler}, Received: val} } - return nil + return m.UnmarshalBSON(src) } // EmptyInterfaceDecodeValue is the ValueDecoderFunc for interface{}. @@ -1565,7 +1637,10 @@ func (dvd DefaultValueDecoders) EmptyInterfaceDecodeValue(dc DecodeContext, vr b } // CoreDocumentDecodeValue is the ValueDecoderFunc for bsoncore.Document. -func (DefaultValueDecoders) CoreDocumentDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default +// value decoders registered. +func (DefaultValueDecoders) CoreDocumentDecodeValue(_ DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { if !val.CanSet() || val.Type() != tCoreDocument { return ValueDecoderError{Name: "CoreDocumentDecodeValue", Types: []reflect.Type{tCoreDocument}, Received: val} } @@ -1600,7 +1675,7 @@ func (dvd DefaultValueDecoders) decodeDefault(dc DecodeContext, vr bsonrw.ValueR idx := 0 for { vr, err := ar.ReadValue() - if err == bsonrw.ErrEOA { + if errors.Is(err, bsonrw.ErrEOA) { break } if err != nil { @@ -1671,6 +1746,9 @@ func (dvd DefaultValueDecoders) codeWithScopeDecodeType(dc DecodeContext, vr bso } // CodeWithScopeDecodeValue is the ValueDecoderFunc for CodeWithScope. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default +// value decoders registered. func (dvd DefaultValueDecoders) CodeWithScopeDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { if !val.CanSet() || val.Type() != tCodeWithScope { return ValueDecoderError{Name: "CodeWithScopeDecodeValue", Types: []reflect.Type{tCodeWithScope}, Received: val} @@ -1709,7 +1787,7 @@ func (DefaultValueDecoders) decodeElemsFromDocumentReader(dc DecodeContext, dr b elems := make([]reflect.Value, 0) for { key, vr, err := dr.ReadElement() - if err == bsonrw.ErrEOD { + if errors.Is(err, bsonrw.ErrEOD) { break } if err != nil { diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_encoders.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_encoders.go index 6bdb43cb43..4751ae995e 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_encoders.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_encoders.go @@ -58,10 +58,16 @@ func encodeElement(ec EncodeContext, dw bsonrw.DocumentWriter, e primitive.E) er // DefaultValueEncoders is a namespace type for the default ValueEncoders used // when creating a registry. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default +// value encoders registered. type DefaultValueEncoders struct{} // RegisterDefaultEncoders will register the encoder methods attached to DefaultValueEncoders with // the provided RegistryBuilder. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default +// value encoders registered. func (dve DefaultValueEncoders) RegisterDefaultEncoders(rb *RegistryBuilder) { if rb == nil { panic(errors.New("argument to RegisterDefaultEncoders must not be nil")) @@ -113,7 +119,10 @@ func (dve DefaultValueEncoders) RegisterDefaultEncoders(rb *RegistryBuilder) { } // BooleanEncodeValue is the ValueEncoderFunc for bool types. -func (dve DefaultValueEncoders) BooleanEncodeValue(ectx EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default +// value encoders registered. +func (dve DefaultValueEncoders) BooleanEncodeValue(_ EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Kind() != reflect.Bool { return ValueEncoderError{Name: "BooleanEncodeValue", Kinds: []reflect.Kind{reflect.Bool}, Received: val} } @@ -125,6 +134,9 @@ func fitsIn32Bits(i int64) bool { } // IntEncodeValue is the ValueEncoderFunc for int types. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default +// value encoders registered. func (dve DefaultValueEncoders) IntEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { switch val.Kind() { case reflect.Int8, reflect.Int16, reflect.Int32: @@ -176,7 +188,10 @@ func (dve DefaultValueEncoders) UintEncodeValue(ec EncodeContext, vw bsonrw.Valu } // FloatEncodeValue is the ValueEncoderFunc for float types. -func (dve DefaultValueEncoders) FloatEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default +// value encoders registered. +func (dve DefaultValueEncoders) FloatEncodeValue(_ EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { switch val.Kind() { case reflect.Float32, reflect.Float64: return vw.WriteDouble(val.Float()) @@ -188,7 +203,7 @@ func (dve DefaultValueEncoders) FloatEncodeValue(ec EncodeContext, vw bsonrw.Val // StringEncodeValue is the ValueEncoderFunc for string types. // // Deprecated: StringEncodeValue is not registered by default. Use StringCodec.EncodeValue instead. -func (dve DefaultValueEncoders) StringEncodeValue(ectx EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +func (dve DefaultValueEncoders) StringEncodeValue(_ EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { if val.Kind() != reflect.String { return ValueEncoderError{ Name: "StringEncodeValue", @@ -201,7 +216,10 @@ func (dve DefaultValueEncoders) StringEncodeValue(ectx EncodeContext, vw bsonrw. } // ObjectIDEncodeValue is the ValueEncoderFunc for primitive.ObjectID. -func (dve DefaultValueEncoders) ObjectIDEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default +// value encoders registered. +func (dve DefaultValueEncoders) ObjectIDEncodeValue(_ EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Type() != tOID { return ValueEncoderError{Name: "ObjectIDEncodeValue", Types: []reflect.Type{tOID}, Received: val} } @@ -209,7 +227,10 @@ func (dve DefaultValueEncoders) ObjectIDEncodeValue(ec EncodeContext, vw bsonrw. } // Decimal128EncodeValue is the ValueEncoderFunc for primitive.Decimal128. -func (dve DefaultValueEncoders) Decimal128EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default +// value encoders registered. +func (dve DefaultValueEncoders) Decimal128EncodeValue(_ EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Type() != tDecimal { return ValueEncoderError{Name: "Decimal128EncodeValue", Types: []reflect.Type{tDecimal}, Received: val} } @@ -217,6 +238,9 @@ func (dve DefaultValueEncoders) Decimal128EncodeValue(ec EncodeContext, vw bsonr } // JSONNumberEncodeValue is the ValueEncoderFunc for json.Number. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default +// value encoders registered. func (dve DefaultValueEncoders) JSONNumberEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Type() != tJSONNumber { return ValueEncoderError{Name: "JSONNumberEncodeValue", Types: []reflect.Type{tJSONNumber}, Received: val} @@ -237,7 +261,10 @@ func (dve DefaultValueEncoders) JSONNumberEncodeValue(ec EncodeContext, vw bsonr } // URLEncodeValue is the ValueEncoderFunc for url.URL. -func (dve DefaultValueEncoders) URLEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default +// value encoders registered. +func (dve DefaultValueEncoders) URLEncodeValue(_ EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Type() != tURL { return ValueEncoderError{Name: "URLEncodeValue", Types: []reflect.Type{tURL}, Received: val} } @@ -248,7 +275,7 @@ func (dve DefaultValueEncoders) URLEncodeValue(ec EncodeContext, vw bsonrw.Value // TimeEncodeValue is the ValueEncoderFunc for time.TIme. // // Deprecated: TimeEncodeValue is not registered by default. Use TimeCodec.EncodeValue instead. -func (dve DefaultValueEncoders) TimeEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +func (dve DefaultValueEncoders) TimeEncodeValue(_ EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Type() != tTime { return ValueEncoderError{Name: "TimeEncodeValue", Types: []reflect.Type{tTime}, Received: val} } @@ -260,7 +287,7 @@ func (dve DefaultValueEncoders) TimeEncodeValue(ec EncodeContext, vw bsonrw.Valu // ByteSliceEncodeValue is the ValueEncoderFunc for []byte. // // Deprecated: ByteSliceEncodeValue is not registered by default. Use ByteSliceCodec.EncodeValue instead. -func (dve DefaultValueEncoders) ByteSliceEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +func (dve DefaultValueEncoders) ByteSliceEncodeValue(_ EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Type() != tByteSlice { return ValueEncoderError{Name: "ByteSliceEncodeValue", Types: []reflect.Type{tByteSlice}, Received: val} } @@ -316,7 +343,7 @@ func (dve DefaultValueEncoders) mapEncodeValue(ec EncodeContext, dw bsonrw.Docum } currEncoder, currVal, lookupErr := dve.lookupElementEncoder(ec, encoder, val.MapIndex(key)) - if lookupErr != nil && lookupErr != errInvalidValue { + if lookupErr != nil && !errors.Is(lookupErr, errInvalidValue) { return lookupErr } @@ -325,7 +352,7 @@ func (dve DefaultValueEncoders) mapEncodeValue(ec EncodeContext, dw bsonrw.Docum return err } - if lookupErr == errInvalidValue { + if errors.Is(lookupErr, errInvalidValue) { err = vw.WriteNull() if err != nil { return err @@ -343,6 +370,9 @@ func (dve DefaultValueEncoders) mapEncodeValue(ec EncodeContext, dw bsonrw.Docum } // ArrayEncodeValue is the ValueEncoderFunc for array types. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default +// value encoders registered. func (dve DefaultValueEncoders) ArrayEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Kind() != reflect.Array { return ValueEncoderError{Name: "ArrayEncodeValue", Kinds: []reflect.Kind{reflect.Array}, Received: val} @@ -388,7 +418,7 @@ func (dve DefaultValueEncoders) ArrayEncodeValue(ec EncodeContext, vw bsonrw.Val for idx := 0; idx < val.Len(); idx++ { currEncoder, currVal, lookupErr := dve.lookupElementEncoder(ec, encoder, val.Index(idx)) - if lookupErr != nil && lookupErr != errInvalidValue { + if lookupErr != nil && !errors.Is(lookupErr, errInvalidValue) { return lookupErr } @@ -397,7 +427,7 @@ func (dve DefaultValueEncoders) ArrayEncodeValue(ec EncodeContext, vw bsonrw.Val return err } - if lookupErr == errInvalidValue { + if errors.Is(lookupErr, errInvalidValue) { err = vw.WriteNull() if err != nil { return err @@ -457,7 +487,7 @@ func (dve DefaultValueEncoders) SliceEncodeValue(ec EncodeContext, vw bsonrw.Val for idx := 0; idx < val.Len(); idx++ { currEncoder, currVal, lookupErr := dve.lookupElementEncoder(ec, encoder, val.Index(idx)) - if lookupErr != nil && lookupErr != errInvalidValue { + if lookupErr != nil && !errors.Is(lookupErr, errInvalidValue) { return lookupErr } @@ -466,7 +496,7 @@ func (dve DefaultValueEncoders) SliceEncodeValue(ec EncodeContext, vw bsonrw.Val return err } - if lookupErr == errInvalidValue { + if errors.Is(lookupErr, errInvalidValue) { err = vw.WriteNull() if err != nil { return err @@ -515,7 +545,10 @@ func (dve DefaultValueEncoders) EmptyInterfaceEncodeValue(ec EncodeContext, vw b } // ValueMarshalerEncodeValue is the ValueEncoderFunc for ValueMarshaler implementations. -func (dve DefaultValueEncoders) ValueMarshalerEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default +// value encoders registered. +func (dve DefaultValueEncoders) ValueMarshalerEncodeValue(_ EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { // Either val or a pointer to val must implement ValueMarshaler switch { case !val.IsValid(): @@ -531,17 +564,22 @@ func (dve DefaultValueEncoders) ValueMarshalerEncodeValue(ec EncodeContext, vw b return ValueEncoderError{Name: "ValueMarshalerEncodeValue", Types: []reflect.Type{tValueMarshaler}, Received: val} } - fn := val.Convert(tValueMarshaler).MethodByName("MarshalBSONValue") - returns := fn.Call(nil) - if !returns[2].IsNil() { - return returns[2].Interface().(error) + m, ok := val.Interface().(ValueMarshaler) + if !ok { + return vw.WriteNull() + } + t, data, err := m.MarshalBSONValue() + if err != nil { + return err } - t, data := returns[0].Interface().(bsontype.Type), returns[1].Interface().([]byte) return bsonrw.Copier{}.CopyValueFromBytes(vw, t, data) } // MarshalerEncodeValue is the ValueEncoderFunc for Marshaler implementations. -func (dve DefaultValueEncoders) MarshalerEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default +// value encoders registered. +func (dve DefaultValueEncoders) MarshalerEncodeValue(_ EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { // Either val or a pointer to val must implement Marshaler switch { case !val.IsValid(): @@ -557,16 +595,21 @@ func (dve DefaultValueEncoders) MarshalerEncodeValue(ec EncodeContext, vw bsonrw return ValueEncoderError{Name: "MarshalerEncodeValue", Types: []reflect.Type{tMarshaler}, Received: val} } - fn := val.Convert(tMarshaler).MethodByName("MarshalBSON") - returns := fn.Call(nil) - if !returns[1].IsNil() { - return returns[1].Interface().(error) + m, ok := val.Interface().(Marshaler) + if !ok { + return vw.WriteNull() + } + data, err := m.MarshalBSON() + if err != nil { + return err } - data := returns[0].Interface().([]byte) return bsonrw.Copier{}.CopyValueFromBytes(vw, bsontype.EmbeddedDocument, data) } // ProxyEncodeValue is the ValueEncoderFunc for Proxy implementations. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default +// value encoders registered. func (dve DefaultValueEncoders) ProxyEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { // Either val or a pointer to val must implement Proxy switch { @@ -583,27 +626,38 @@ func (dve DefaultValueEncoders) ProxyEncodeValue(ec EncodeContext, vw bsonrw.Val return ValueEncoderError{Name: "ProxyEncodeValue", Types: []reflect.Type{tProxy}, Received: val} } - fn := val.Convert(tProxy).MethodByName("ProxyBSON") - returns := fn.Call(nil) - if !returns[1].IsNil() { - return returns[1].Interface().(error) + m, ok := val.Interface().(Proxy) + if !ok { + return vw.WriteNull() } - data := returns[0] - var encoder ValueEncoder - var err error - if data.Elem().IsValid() { - encoder, err = ec.LookupEncoder(data.Elem().Type()) - } else { - encoder, err = ec.LookupEncoder(nil) + v, err := m.ProxyBSON() + if err != nil { + return err } + if v == nil { + encoder, err := ec.LookupEncoder(nil) + if err != nil { + return err + } + return encoder.EncodeValue(ec, vw, reflect.ValueOf(nil)) + } + vv := reflect.ValueOf(v) + switch vv.Kind() { + case reflect.Ptr, reflect.Interface: + vv = vv.Elem() + } + encoder, err := ec.LookupEncoder(vv.Type()) if err != nil { return err } - return encoder.EncodeValue(ec, vw, data.Elem()) + return encoder.EncodeValue(ec, vw, vv) } // JavaScriptEncodeValue is the ValueEncoderFunc for the primitive.JavaScript type. -func (DefaultValueEncoders) JavaScriptEncodeValue(ectx EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default +// value encoders registered. +func (DefaultValueEncoders) JavaScriptEncodeValue(_ EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Type() != tJavaScript { return ValueEncoderError{Name: "JavaScriptEncodeValue", Types: []reflect.Type{tJavaScript}, Received: val} } @@ -612,7 +666,10 @@ func (DefaultValueEncoders) JavaScriptEncodeValue(ectx EncodeContext, vw bsonrw. } // SymbolEncodeValue is the ValueEncoderFunc for the primitive.Symbol type. -func (DefaultValueEncoders) SymbolEncodeValue(ectx EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default +// value encoders registered. +func (DefaultValueEncoders) SymbolEncodeValue(_ EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Type() != tSymbol { return ValueEncoderError{Name: "SymbolEncodeValue", Types: []reflect.Type{tSymbol}, Received: val} } @@ -621,7 +678,10 @@ func (DefaultValueEncoders) SymbolEncodeValue(ectx EncodeContext, vw bsonrw.Valu } // BinaryEncodeValue is the ValueEncoderFunc for Binary. -func (DefaultValueEncoders) BinaryEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default +// value encoders registered. +func (DefaultValueEncoders) BinaryEncodeValue(_ EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Type() != tBinary { return ValueEncoderError{Name: "BinaryEncodeValue", Types: []reflect.Type{tBinary}, Received: val} } @@ -631,7 +691,10 @@ func (DefaultValueEncoders) BinaryEncodeValue(ec EncodeContext, vw bsonrw.ValueW } // UndefinedEncodeValue is the ValueEncoderFunc for Undefined. -func (DefaultValueEncoders) UndefinedEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default +// value encoders registered. +func (DefaultValueEncoders) UndefinedEncodeValue(_ EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Type() != tUndefined { return ValueEncoderError{Name: "UndefinedEncodeValue", Types: []reflect.Type{tUndefined}, Received: val} } @@ -640,7 +703,10 @@ func (DefaultValueEncoders) UndefinedEncodeValue(ec EncodeContext, vw bsonrw.Val } // DateTimeEncodeValue is the ValueEncoderFunc for DateTime. -func (DefaultValueEncoders) DateTimeEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default +// value encoders registered. +func (DefaultValueEncoders) DateTimeEncodeValue(_ EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Type() != tDateTime { return ValueEncoderError{Name: "DateTimeEncodeValue", Types: []reflect.Type{tDateTime}, Received: val} } @@ -649,7 +715,10 @@ func (DefaultValueEncoders) DateTimeEncodeValue(ec EncodeContext, vw bsonrw.Valu } // NullEncodeValue is the ValueEncoderFunc for Null. -func (DefaultValueEncoders) NullEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default +// value encoders registered. +func (DefaultValueEncoders) NullEncodeValue(_ EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Type() != tNull { return ValueEncoderError{Name: "NullEncodeValue", Types: []reflect.Type{tNull}, Received: val} } @@ -658,7 +727,10 @@ func (DefaultValueEncoders) NullEncodeValue(ec EncodeContext, vw bsonrw.ValueWri } // RegexEncodeValue is the ValueEncoderFunc for Regex. -func (DefaultValueEncoders) RegexEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default +// value encoders registered. +func (DefaultValueEncoders) RegexEncodeValue(_ EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Type() != tRegex { return ValueEncoderError{Name: "RegexEncodeValue", Types: []reflect.Type{tRegex}, Received: val} } @@ -669,7 +741,10 @@ func (DefaultValueEncoders) RegexEncodeValue(ec EncodeContext, vw bsonrw.ValueWr } // DBPointerEncodeValue is the ValueEncoderFunc for DBPointer. -func (DefaultValueEncoders) DBPointerEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default +// value encoders registered. +func (DefaultValueEncoders) DBPointerEncodeValue(_ EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Type() != tDBPointer { return ValueEncoderError{Name: "DBPointerEncodeValue", Types: []reflect.Type{tDBPointer}, Received: val} } @@ -680,7 +755,10 @@ func (DefaultValueEncoders) DBPointerEncodeValue(ec EncodeContext, vw bsonrw.Val } // TimestampEncodeValue is the ValueEncoderFunc for Timestamp. -func (DefaultValueEncoders) TimestampEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default +// value encoders registered. +func (DefaultValueEncoders) TimestampEncodeValue(_ EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Type() != tTimestamp { return ValueEncoderError{Name: "TimestampEncodeValue", Types: []reflect.Type{tTimestamp}, Received: val} } @@ -691,7 +769,10 @@ func (DefaultValueEncoders) TimestampEncodeValue(ec EncodeContext, vw bsonrw.Val } // MinKeyEncodeValue is the ValueEncoderFunc for MinKey. -func (DefaultValueEncoders) MinKeyEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default +// value encoders registered. +func (DefaultValueEncoders) MinKeyEncodeValue(_ EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Type() != tMinKey { return ValueEncoderError{Name: "MinKeyEncodeValue", Types: []reflect.Type{tMinKey}, Received: val} } @@ -700,7 +781,10 @@ func (DefaultValueEncoders) MinKeyEncodeValue(ec EncodeContext, vw bsonrw.ValueW } // MaxKeyEncodeValue is the ValueEncoderFunc for MaxKey. -func (DefaultValueEncoders) MaxKeyEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default +// value encoders registered. +func (DefaultValueEncoders) MaxKeyEncodeValue(_ EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Type() != tMaxKey { return ValueEncoderError{Name: "MaxKeyEncodeValue", Types: []reflect.Type{tMaxKey}, Received: val} } @@ -709,7 +793,10 @@ func (DefaultValueEncoders) MaxKeyEncodeValue(ec EncodeContext, vw bsonrw.ValueW } // CoreDocumentEncodeValue is the ValueEncoderFunc for bsoncore.Document. -func (DefaultValueEncoders) CoreDocumentEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default +// value encoders registered. +func (DefaultValueEncoders) CoreDocumentEncodeValue(_ EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Type() != tCoreDocument { return ValueEncoderError{Name: "CoreDocumentEncodeValue", Types: []reflect.Type{tCoreDocument}, Received: val} } @@ -720,6 +807,9 @@ func (DefaultValueEncoders) CoreDocumentEncodeValue(ec EncodeContext, vw bsonrw. } // CodeWithScopeEncodeValue is the ValueEncoderFunc for CodeWithScope. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default +// value encoders registered. func (dve DefaultValueEncoders) CodeWithScopeEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Type() != tCodeWithScope { return ValueEncoderError{Name: "CodeWithScopeEncodeValue", Types: []reflect.Type{tCodeWithScope}, Received: val} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/doc.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/doc.go index 5f903ebea6..4613e5a1ec 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/doc.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/doc.go @@ -31,35 +31,39 @@ // allow the use of a function with the correct signature as a ValueDecoder. A DecodeContext // instance is provided and serves similar functionality to the EncodeContext. // -// # Registry and RegistryBuilder -// -// A Registry is an immutable store for ValueEncoders, ValueDecoders, and a type map. See the Registry type -// documentation for examples of registering various custom encoders and decoders. A Registry can be constructed using a -// RegistryBuilder, which handles three main types of codecs: -// -// 1. Type encoders/decoders - These can be registered using the RegisterTypeEncoder and RegisterTypeDecoder methods. -// The registered codec will be invoked when encoding/decoding a value whose type matches the registered type exactly. -// If the registered type is an interface, the codec will be invoked when encoding or decoding values whose type is the -// interface, but not for values with concrete types that implement the interface. -// -// 2. Hook encoders/decoders - These can be registered using the RegisterHookEncoder and RegisterHookDecoder methods. -// These methods only accept interface types and the registered codecs will be invoked when encoding or decoding values -// whose types implement the interface. An example of a hook defined by the driver is bson.Marshaler. The driver will -// call the MarshalBSON method for any value whose type implements bson.Marshaler, regardless of the value's concrete -// type. -// -// 3. Type map entries - This can be used to associate a BSON type with a Go type. These type associations are used when -// decoding into a bson.D/bson.M or a struct field of type interface{}. For example, by default, BSON int32 and int64 -// values decode as Go int32 and int64 instances, respectively, when decoding into a bson.D. The following code would -// change the behavior so these values decode as Go int instances instead: +// # Registry +// +// A Registry is a store for ValueEncoders, ValueDecoders, and a type map. See the Registry type +// documentation for examples of registering various custom encoders and decoders. A Registry can +// have three main types of codecs: +// +// 1. Type encoders/decoders - These can be registered using the RegisterTypeEncoder and +// RegisterTypeDecoder methods. The registered codec will be invoked when encoding/decoding a value +// whose type matches the registered type exactly. +// If the registered type is an interface, the codec will be invoked when encoding or decoding +// values whose type is the interface, but not for values with concrete types that implement the +// interface. +// +// 2. Hook encoders/decoders - These can be registered using the RegisterHookEncoder and +// RegisterHookDecoder methods. These methods only accept interface types and the registered codecs +// will be invoked when encoding or decoding values whose types implement the interface. An example +// of a hook defined by the driver is bson.Marshaler. The driver will call the MarshalBSON method +// for any value whose type implements bson.Marshaler, regardless of the value's concrete type. +// +// 3. Type map entries - This can be used to associate a BSON type with a Go type. These type +// associations are used when decoding into a bson.D/bson.M or a struct field of type interface{}. +// For example, by default, BSON int32 and int64 values decode as Go int32 and int64 instances, +// respectively, when decoding into a bson.D. The following code would change the behavior so these +// values decode as Go int instances instead: // // intType := reflect.TypeOf(int(0)) -// registryBuilder.RegisterTypeMapEntry(bsontype.Int32, intType).RegisterTypeMapEntry(bsontype.Int64, intType) +// registry.RegisterTypeMapEntry(bsontype.Int32, intType).RegisterTypeMapEntry(bsontype.Int64, intType) // -// 4. Kind encoder/decoders - These can be registered using the RegisterDefaultEncoder and RegisterDefaultDecoder -// methods. The registered codec will be invoked when encoding or decoding values whose reflect.Kind matches the -// registered reflect.Kind as long as the value's type doesn't match a registered type or hook encoder/decoder first. -// These methods should be used to change the behavior for all values for a specific kind. +// 4. Kind encoder/decoders - These can be registered using the RegisterDefaultEncoder and +// RegisterDefaultDecoder methods. The registered codec will be invoked when encoding or decoding +// values whose reflect.Kind matches the registered reflect.Kind as long as the value's type doesn't +// match a registered type or hook encoder/decoder first. These methods should be used to change the +// behavior for all values for a specific kind. // // # Registry Lookup Procedure // @@ -67,17 +71,18 @@ // // 1. A type encoder registered for the exact type of the value. // -// 2. A hook encoder registered for an interface that is implemented by the value or by a pointer to the value. If the -// value matches multiple hooks (e.g. the type implements bsoncodec.Marshaler and bsoncodec.ValueMarshaler), the first -// one registered will be selected. Note that registries constructed using bson.NewRegistryBuilder have driver-defined -// hooks registered for the bsoncodec.Marshaler, bsoncodec.ValueMarshaler, and bsoncodec.Proxy interfaces, so those -// will take precedence over any new hooks. +// 2. A hook encoder registered for an interface that is implemented by the value or by a pointer to +// the value. If the value matches multiple hooks (e.g. the type implements bsoncodec.Marshaler and +// bsoncodec.ValueMarshaler), the first one registered will be selected. Note that registries +// constructed using bson.NewRegistry have driver-defined hooks registered for the +// bsoncodec.Marshaler, bsoncodec.ValueMarshaler, and bsoncodec.Proxy interfaces, so those will take +// precedence over any new hooks. // // 3. A kind encoder registered for the value's kind. // -// If all of these lookups fail to find an encoder, an error of type ErrNoEncoder is returned. The same precedence -// rules apply for decoders, with the exception that an error of type ErrNoDecoder will be returned if no decoder is -// found. +// If all of these lookups fail to find an encoder, an error of type ErrNoEncoder is returned. The +// same precedence rules apply for decoders, with the exception that an error of type ErrNoDecoder +// will be returned if no decoder is found. // // # DefaultValueEncoders and DefaultValueDecoders // diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/empty_interface_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/empty_interface_codec.go index eda417cff8..098368f071 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/empty_interface_codec.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/empty_interface_codec.go @@ -16,18 +16,44 @@ import ( ) // EmptyInterfaceCodec is the Codec used for interface{} values. +// +// Deprecated: EmptyInterfaceCodec will not be directly configurable in Go +// Driver 2.0. To configure the empty interface encode and decode behavior, use +// the configuration methods on a [go.mongodb.org/mongo-driver/bson.Encoder] or +// [go.mongodb.org/mongo-driver/bson.Decoder]. To configure the empty interface +// encode and decode behavior for a mongo.Client, use +// [go.mongodb.org/mongo-driver/mongo/options.ClientOptions.SetBSONOptions]. +// +// For example, to configure a mongo.Client to unmarshal BSON binary field +// values as a Go byte slice, use: +// +// opt := options.Client().SetBSONOptions(&options.BSONOptions{ +// BinaryAsSlice: true, +// }) +// +// See the deprecation notice for each field in EmptyInterfaceCodec for the +// corresponding settings. type EmptyInterfaceCodec struct { + // DecodeBinaryAsSlice causes DecodeValue to unmarshal BSON binary field values that are the + // "Generic" or "Old" BSON binary subtype as a Go byte slice instead of a primitive.Binary. + // + // Deprecated: Use bson.Decoder.BinaryAsSlice or options.BSONOptions.BinaryAsSlice instead. DecodeBinaryAsSlice bool } var ( defaultEmptyInterfaceCodec = NewEmptyInterfaceCodec() - _ ValueCodec = defaultEmptyInterfaceCodec + // Assert that defaultEmptyInterfaceCodec satisfies the typeDecoder interface, which allows it + // to be used by collection type decoders (e.g. map, slice, etc) to set individual values in a + // collection. _ typeDecoder = defaultEmptyInterfaceCodec ) // NewEmptyInterfaceCodec returns a EmptyInterfaceCodec with options opts. +// +// Deprecated: NewEmptyInterfaceCodec will not be available in Go Driver 2.0. See +// [EmptyInterfaceCodec] for more details. func NewEmptyInterfaceCodec(opts ...*bsonoptions.EmptyInterfaceCodecOptions) *EmptyInterfaceCodec { interfaceOpt := bsonoptions.MergeEmptyInterfaceCodecOptions(opts...) @@ -121,7 +147,7 @@ func (eic EmptyInterfaceCodec) decodeType(dc DecodeContext, vr bsonrw.ValueReade return emptyValue, err } - if eic.DecodeBinaryAsSlice && rtype == tBinary { + if (eic.DecodeBinaryAsSlice || dc.binaryAsSlice) && rtype == tBinary { binElem := elem.Interface().(primitive.Binary) if binElem.Subtype == bsontype.BinaryGeneric || binElem.Subtype == bsontype.BinaryBinaryOld { elem = reflect.ValueOf(binElem.Data) diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/map_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/map_codec.go index e1fbef9c6c..d7e00ffa8d 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/map_codec.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/map_codec.go @@ -8,6 +8,7 @@ package bsoncodec import ( "encoding" + "errors" "fmt" "reflect" "strconv" @@ -20,14 +21,44 @@ import ( var defaultMapCodec = NewMapCodec() // MapCodec is the Codec used for map values. +// +// Deprecated: MapCodec will not be directly configurable in Go Driver 2.0. To +// configure the map encode and decode behavior, use the configuration methods +// on a [go.mongodb.org/mongo-driver/bson.Encoder] or +// [go.mongodb.org/mongo-driver/bson.Decoder]. To configure the map encode and +// decode behavior for a mongo.Client, use +// [go.mongodb.org/mongo-driver/mongo/options.ClientOptions.SetBSONOptions]. +// +// For example, to configure a mongo.Client to marshal nil Go maps as empty BSON +// documents, use: +// +// opt := options.Client().SetBSONOptions(&options.BSONOptions{ +// NilMapAsEmpty: true, +// }) +// +// See the deprecation notice for each field in MapCodec for the corresponding +// settings. type MapCodec struct { - DecodeZerosMap bool - EncodeNilAsEmpty bool + // DecodeZerosMap causes DecodeValue to delete any existing values from Go maps in the destination + // value passed to Decode before unmarshaling BSON documents into them. + // + // Deprecated: Use bson.Decoder.ZeroMaps or options.BSONOptions.ZeroMaps instead. + DecodeZerosMap bool + + // EncodeNilAsEmpty causes EncodeValue to marshal nil Go maps as empty BSON documents instead of + // BSON null. + // + // Deprecated: Use bson.Encoder.NilMapAsEmpty or options.BSONOptions.NilMapAsEmpty instead. + EncodeNilAsEmpty bool + + // EncodeKeysWithStringer causes the Encoder to convert Go map keys to BSON document field name + // strings using fmt.Sprintf() instead of the default string conversion logic. + // + // Deprecated: Use bson.Encoder.StringifyMapKeysWithFmt or + // options.BSONOptions.StringifyMapKeysWithFmt instead. EncodeKeysWithStringer bool } -var _ ValueCodec = &MapCodec{} - // KeyMarshaler is the interface implemented by an object that can marshal itself into a string key. // This applies to types used as map keys and is similar to encoding.TextMarshaler. type KeyMarshaler interface { @@ -45,6 +76,9 @@ type KeyUnmarshaler interface { } // NewMapCodec returns a MapCodec with options opts. +// +// Deprecated: NewMapCodec will not be available in Go Driver 2.0. See +// [MapCodec] for more details. func NewMapCodec(opts ...*bsonoptions.MapCodecOptions) *MapCodec { mapOpt := bsonoptions.MergeMapCodecOptions(opts...) @@ -67,7 +101,7 @@ func (mc *MapCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val ref return ValueEncoderError{Name: "MapEncodeValue", Kinds: []reflect.Kind{reflect.Map}, Received: val} } - if val.IsNil() && !mc.EncodeNilAsEmpty { + if val.IsNil() && !mc.EncodeNilAsEmpty && !ec.nilMapAsEmpty { // If we have a nil map but we can't WriteNull, that means we're probably trying to encode // to a TopLevel document. We can't currently tell if this is what actually happened, but if // there's a deeper underlying problem, the error will also be returned from WriteDocument, @@ -100,7 +134,7 @@ func (mc *MapCodec) mapEncodeValue(ec EncodeContext, dw bsonrw.DocumentWriter, v keys := val.MapKeys() for _, key := range keys { - keyStr, err := mc.encodeKey(key) + keyStr, err := mc.encodeKey(key, ec.stringifyMapKeysWithFmt) if err != nil { return err } @@ -110,7 +144,7 @@ func (mc *MapCodec) mapEncodeValue(ec EncodeContext, dw bsonrw.DocumentWriter, v } currEncoder, currVal, lookupErr := defaultValueEncoders.lookupElementEncoder(ec, encoder, val.MapIndex(key)) - if lookupErr != nil && lookupErr != errInvalidValue { + if lookupErr != nil && !errors.Is(lookupErr, errInvalidValue) { return lookupErr } @@ -119,7 +153,7 @@ func (mc *MapCodec) mapEncodeValue(ec EncodeContext, dw bsonrw.DocumentWriter, v return err } - if lookupErr == errInvalidValue { + if errors.Is(lookupErr, errInvalidValue) { err = vw.WriteNull() if err != nil { return err @@ -163,7 +197,7 @@ func (mc *MapCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val ref val.Set(reflect.MakeMap(val.Type())) } - if val.Len() > 0 && mc.DecodeZerosMap { + if val.Len() > 0 && (mc.DecodeZerosMap || dc.zeroMaps) { clearMap(val) } @@ -182,7 +216,7 @@ func (mc *MapCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val ref for { key, vr, err := dr.ReadElement() - if err == bsonrw.ErrEOD { + if errors.Is(err, bsonrw.ErrEOD) { break } if err != nil { @@ -211,8 +245,8 @@ func clearMap(m reflect.Value) { } } -func (mc *MapCodec) encodeKey(val reflect.Value) (string, error) { - if mc.EncodeKeysWithStringer { +func (mc *MapCodec) encodeKey(val reflect.Value, encodeKeysWithStringer bool) (string, error) { + if mc.EncodeKeysWithStringer || encodeKeysWithStringer { return fmt.Sprint(val), nil } @@ -295,7 +329,7 @@ func (mc *MapCodec) decodeKey(key string, keyType reflect.Type) (reflect.Value, if mc.EncodeKeysWithStringer { parsed, err := strconv.ParseFloat(key, 64) if err != nil { - return keyVal, fmt.Errorf("Map key is defined to be a decimal type (%v) but got error %v", keyType.Kind(), err) + return keyVal, fmt.Errorf("Map key is defined to be a decimal type (%v) but got error %w", keyType.Kind(), err) } keyVal = reflect.ValueOf(parsed) break diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/pointer_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/pointer_codec.go index 616a3e701b..ddfa4a33e1 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/pointer_codec.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/pointer_codec.go @@ -8,7 +8,6 @@ package bsoncodec import ( "reflect" - "sync" "go.mongodb.org/mongo-driver/bson/bsonrw" "go.mongodb.org/mongo-driver/bson/bsontype" @@ -18,18 +17,28 @@ var _ ValueEncoder = &PointerCodec{} var _ ValueDecoder = &PointerCodec{} // PointerCodec is the Codec used for pointers. +// +// Deprecated: PointerCodec will not be directly accessible in Go Driver 2.0. To +// override the default pointer encode and decode behavior, create a new registry +// with [go.mongodb.org/mongo-driver/bson.NewRegistry] and register a new +// encoder and decoder for pointers. +// +// For example, +// +// reg := bson.NewRegistry() +// reg.RegisterKindEncoder(reflect.Ptr, myPointerEncoder) +// reg.RegisterKindDecoder(reflect.Ptr, myPointerDecoder) type PointerCodec struct { - ecache map[reflect.Type]ValueEncoder - dcache map[reflect.Type]ValueDecoder - l sync.RWMutex + ecache typeEncoderCache + dcache typeDecoderCache } // NewPointerCodec returns a PointerCodec that has been initialized. +// +// Deprecated: NewPointerCodec will not be available in Go Driver 2.0. See +// [PointerCodec] for more details. func NewPointerCodec() *PointerCodec { - return &PointerCodec{ - ecache: make(map[reflect.Type]ValueEncoder), - dcache: make(map[reflect.Type]ValueDecoder), - } + return &PointerCodec{} } // EncodeValue handles encoding a pointer by either encoding it to BSON Null if the pointer is nil @@ -46,24 +55,19 @@ func (pc *PointerCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val return vw.WriteNull() } - pc.l.RLock() - enc, ok := pc.ecache[val.Type()] - pc.l.RUnlock() - if ok { - if enc == nil { - return ErrNoEncoder{Type: val.Type()} + typ := val.Type() + if v, ok := pc.ecache.Load(typ); ok { + if v == nil { + return ErrNoEncoder{Type: typ} } - return enc.EncodeValue(ec, vw, val.Elem()) + return v.EncodeValue(ec, vw, val.Elem()) } - - enc, err := ec.LookupEncoder(val.Type().Elem()) - pc.l.Lock() - pc.ecache[val.Type()] = enc - pc.l.Unlock() + // TODO(charlie): handle concurrent requests for the same type + enc, err := ec.LookupEncoder(typ.Elem()) + enc = pc.ecache.LoadOrStore(typ, enc) if err != nil { return err } - return enc.EncodeValue(ec, vw, val.Elem()) } @@ -74,36 +78,31 @@ func (pc *PointerCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val return ValueDecoderError{Name: "PointerCodec.DecodeValue", Kinds: []reflect.Kind{reflect.Ptr}, Received: val} } + typ := val.Type() if vr.Type() == bsontype.Null { - val.Set(reflect.Zero(val.Type())) + val.Set(reflect.Zero(typ)) return vr.ReadNull() } if vr.Type() == bsontype.Undefined { - val.Set(reflect.Zero(val.Type())) + val.Set(reflect.Zero(typ)) return vr.ReadUndefined() } if val.IsNil() { - val.Set(reflect.New(val.Type().Elem())) + val.Set(reflect.New(typ.Elem())) } - pc.l.RLock() - dec, ok := pc.dcache[val.Type()] - pc.l.RUnlock() - if ok { - if dec == nil { - return ErrNoDecoder{Type: val.Type()} + if v, ok := pc.dcache.Load(typ); ok { + if v == nil { + return ErrNoDecoder{Type: typ} } - return dec.DecodeValue(dc, vr, val.Elem()) + return v.DecodeValue(dc, vr, val.Elem()) } - - dec, err := dc.LookupDecoder(val.Type().Elem()) - pc.l.Lock() - pc.dcache[val.Type()] = dec - pc.l.Unlock() + // TODO(charlie): handle concurrent requests for the same type + dec, err := dc.LookupDecoder(typ.Elem()) + dec = pc.dcache.LoadOrStore(typ, dec) if err != nil { return err } - return dec.DecodeValue(dc, vr, val.Elem()) } diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/registry.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/registry.go index 80644023c2..196c491bbb 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/registry.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/registry.go @@ -16,12 +16,18 @@ import ( ) // ErrNilType is returned when nil is passed to either LookupEncoder or LookupDecoder. +// +// Deprecated: ErrNilType will not be supported in Go Driver 2.0. var ErrNilType = errors.New("cannot perform a decoder lookup on ") // ErrNotPointer is returned when a non-pointer type is provided to LookupDecoder. +// +// Deprecated: ErrNotPointer will not be supported in Go Driver 2.0. var ErrNotPointer = errors.New("non-pointer provided to LookupDecoder") // ErrNoEncoder is returned when there wasn't an encoder available for a type. +// +// Deprecated: ErrNoEncoder will not be supported in Go Driver 2.0. type ErrNoEncoder struct { Type reflect.Type } @@ -34,6 +40,8 @@ func (ene ErrNoEncoder) Error() string { } // ErrNoDecoder is returned when there wasn't a decoder available for a type. +// +// Deprecated: ErrNoDecoder will not be supported in Go Driver 2.0. type ErrNoDecoder struct { Type reflect.Type } @@ -43,6 +51,8 @@ func (end ErrNoDecoder) Error() string { } // ErrNoTypeMapEntry is returned when there wasn't a type available for the provided BSON type. +// +// Deprecated: ErrNoTypeMapEntry will not be supported in Go Driver 2.0. type ErrNoTypeMapEntry struct { Type bsontype.Type } @@ -52,63 +62,30 @@ func (entme ErrNoTypeMapEntry) Error() string { } // ErrNotInterface is returned when the provided type is not an interface. +// +// Deprecated: ErrNotInterface will not be supported in Go Driver 2.0. var ErrNotInterface = errors.New("The provided type is not an interface") // A RegistryBuilder is used to build a Registry. This type is not goroutine // safe. +// +// Deprecated: Use Registry instead. type RegistryBuilder struct { - typeEncoders map[reflect.Type]ValueEncoder - interfaceEncoders []interfaceValueEncoder - kindEncoders map[reflect.Kind]ValueEncoder - - typeDecoders map[reflect.Type]ValueDecoder - interfaceDecoders []interfaceValueDecoder - kindDecoders map[reflect.Kind]ValueDecoder - - typeMap map[bsontype.Type]reflect.Type -} - -// A Registry is used to store and retrieve codecs for types and interfaces. This type is the main -// typed passed around and Encoders and Decoders are constructed from it. -type Registry struct { - typeEncoders map[reflect.Type]ValueEncoder - typeDecoders map[reflect.Type]ValueDecoder - - interfaceEncoders []interfaceValueEncoder - interfaceDecoders []interfaceValueDecoder - - kindEncoders map[reflect.Kind]ValueEncoder - kindDecoders map[reflect.Kind]ValueDecoder - - typeMap map[bsontype.Type]reflect.Type - - mu sync.RWMutex + registry *Registry } // NewRegistryBuilder creates a new empty RegistryBuilder. +// +// Deprecated: Use NewRegistry instead. func NewRegistryBuilder() *RegistryBuilder { return &RegistryBuilder{ - typeEncoders: make(map[reflect.Type]ValueEncoder), - typeDecoders: make(map[reflect.Type]ValueDecoder), - - interfaceEncoders: make([]interfaceValueEncoder, 0), - interfaceDecoders: make([]interfaceValueDecoder, 0), - - kindEncoders: make(map[reflect.Kind]ValueEncoder), - kindDecoders: make(map[reflect.Kind]ValueDecoder), - - typeMap: make(map[bsontype.Type]reflect.Type), + registry: NewRegistry(), } } -func buildDefaultRegistry() *Registry { - rb := NewRegistryBuilder() - defaultValueEncoders.RegisterDefaultEncoders(rb) - defaultValueDecoders.RegisterDefaultDecoders(rb) - return rb.Build() -} - // RegisterCodec will register the provided ValueCodec for the provided type. +// +// Deprecated: Use Registry.RegisterTypeEncoder and Registry.RegisterTypeDecoder instead. func (rb *RegistryBuilder) RegisterCodec(t reflect.Type, codec ValueCodec) *RegistryBuilder { rb.RegisterTypeEncoder(t, codec) rb.RegisterTypeDecoder(t, codec) @@ -120,31 +97,22 @@ func (rb *RegistryBuilder) RegisterCodec(t reflect.Type, codec ValueCodec) *Regi // The type will be used directly, so an encoder can be registered for a type and a different encoder can be registered // for a pointer to that type. // -// If the given type is an interface, the encoder will be called when marshalling a type that is that interface. It -// will not be called when marshalling a non-interface type that implements the interface. +// If the given type is an interface, the encoder will be called when marshaling a type that is that interface. It +// will not be called when marshaling a non-interface type that implements the interface. +// +// Deprecated: Use Registry.RegisterTypeEncoder instead. func (rb *RegistryBuilder) RegisterTypeEncoder(t reflect.Type, enc ValueEncoder) *RegistryBuilder { - rb.typeEncoders[t] = enc + rb.registry.RegisterTypeEncoder(t, enc) return rb } // RegisterHookEncoder will register an encoder for the provided interface type t. This encoder will be called when -// marshalling a type if the type implements t or a pointer to the type implements t. If the provided type is not +// marshaling a type if the type implements t or a pointer to the type implements t. If the provided type is not // an interface (i.e. t.Kind() != reflect.Interface), this method will panic. +// +// Deprecated: Use Registry.RegisterInterfaceEncoder instead. func (rb *RegistryBuilder) RegisterHookEncoder(t reflect.Type, enc ValueEncoder) *RegistryBuilder { - if t.Kind() != reflect.Interface { - panicStr := fmt.Sprintf("RegisterHookEncoder expects a type with kind reflect.Interface, "+ - "got type %s with kind %s", t, t.Kind()) - panic(panicStr) - } - - for idx, encoder := range rb.interfaceEncoders { - if encoder.i == t { - rb.interfaceEncoders[idx].ve = enc - return rb - } - } - - rb.interfaceEncoders = append(rb.interfaceEncoders, interfaceValueEncoder{i: t, ve: enc}) + rb.registry.RegisterInterfaceEncoder(t, enc) return rb } @@ -153,97 +121,78 @@ func (rb *RegistryBuilder) RegisterHookEncoder(t reflect.Type, enc ValueEncoder) // The type will be used directly, so a decoder can be registered for a type and a different decoder can be registered // for a pointer to that type. // -// If the given type is an interface, the decoder will be called when unmarshalling into a type that is that interface. -// It will not be called when unmarshalling into a non-interface type that implements the interface. +// If the given type is an interface, the decoder will be called when unmarshaling into a type that is that interface. +// It will not be called when unmarshaling into a non-interface type that implements the interface. +// +// Deprecated: Use Registry.RegisterTypeDecoder instead. func (rb *RegistryBuilder) RegisterTypeDecoder(t reflect.Type, dec ValueDecoder) *RegistryBuilder { - rb.typeDecoders[t] = dec + rb.registry.RegisterTypeDecoder(t, dec) return rb } // RegisterHookDecoder will register an decoder for the provided interface type t. This decoder will be called when -// unmarshalling into a type if the type implements t or a pointer to the type implements t. If the provided type is not +// unmarshaling into a type if the type implements t or a pointer to the type implements t. If the provided type is not // an interface (i.e. t.Kind() != reflect.Interface), this method will panic. +// +// Deprecated: Use Registry.RegisterInterfaceDecoder instead. func (rb *RegistryBuilder) RegisterHookDecoder(t reflect.Type, dec ValueDecoder) *RegistryBuilder { - if t.Kind() != reflect.Interface { - panicStr := fmt.Sprintf("RegisterHookDecoder expects a type with kind reflect.Interface, "+ - "got type %s with kind %s", t, t.Kind()) - panic(panicStr) - } - - for idx, decoder := range rb.interfaceDecoders { - if decoder.i == t { - rb.interfaceDecoders[idx].vd = dec - return rb - } - } - - rb.interfaceDecoders = append(rb.interfaceDecoders, interfaceValueDecoder{i: t, vd: dec}) + rb.registry.RegisterInterfaceDecoder(t, dec) return rb } // RegisterEncoder registers the provided type and encoder pair. // -// Deprecated: Use RegisterTypeEncoder or RegisterHookEncoder instead. +// Deprecated: Use Registry.RegisterTypeEncoder or Registry.RegisterInterfaceEncoder instead. func (rb *RegistryBuilder) RegisterEncoder(t reflect.Type, enc ValueEncoder) *RegistryBuilder { if t == tEmpty { - rb.typeEncoders[t] = enc + rb.registry.RegisterTypeEncoder(t, enc) return rb } switch t.Kind() { case reflect.Interface: - for idx, ir := range rb.interfaceEncoders { - if ir.i == t { - rb.interfaceEncoders[idx].ve = enc - return rb - } - } - - rb.interfaceEncoders = append(rb.interfaceEncoders, interfaceValueEncoder{i: t, ve: enc}) + rb.registry.RegisterInterfaceEncoder(t, enc) default: - rb.typeEncoders[t] = enc + rb.registry.RegisterTypeEncoder(t, enc) } return rb } // RegisterDecoder registers the provided type and decoder pair. // -// Deprecated: Use RegisterTypeDecoder or RegisterHookDecoder instead. +// Deprecated: Use Registry.RegisterTypeDecoder or Registry.RegisterInterfaceDecoder instead. func (rb *RegistryBuilder) RegisterDecoder(t reflect.Type, dec ValueDecoder) *RegistryBuilder { if t == nil { - rb.typeDecoders[nil] = dec + rb.registry.RegisterTypeDecoder(t, dec) return rb } if t == tEmpty { - rb.typeDecoders[t] = dec + rb.registry.RegisterTypeDecoder(t, dec) return rb } switch t.Kind() { case reflect.Interface: - for idx, ir := range rb.interfaceDecoders { - if ir.i == t { - rb.interfaceDecoders[idx].vd = dec - return rb - } - } - - rb.interfaceDecoders = append(rb.interfaceDecoders, interfaceValueDecoder{i: t, vd: dec}) + rb.registry.RegisterInterfaceDecoder(t, dec) default: - rb.typeDecoders[t] = dec + rb.registry.RegisterTypeDecoder(t, dec) } return rb } -// RegisterDefaultEncoder will registr the provided ValueEncoder to the provided +// RegisterDefaultEncoder will register the provided ValueEncoder to the provided // kind. +// +// Deprecated: Use Registry.RegisterKindEncoder instead. func (rb *RegistryBuilder) RegisterDefaultEncoder(kind reflect.Kind, enc ValueEncoder) *RegistryBuilder { - rb.kindEncoders[kind] = enc + rb.registry.RegisterKindEncoder(kind, enc) return rb } // RegisterDefaultDecoder will register the provided ValueDecoder to the // provided kind. +// +// Deprecated: Use Registry.RegisterKindDecoder instead. func (rb *RegistryBuilder) RegisterDefaultDecoder(kind reflect.Kind, dec ValueDecoder) *RegistryBuilder { - rb.kindDecoders[kind] = dec + rb.registry.RegisterKindDecoder(kind, dec) return rb } @@ -256,120 +205,233 @@ func (rb *RegistryBuilder) RegisterDefaultDecoder(kind reflect.Kind, dec ValueDe // to decode to bson.Raw, use the following code: // // rb.RegisterTypeMapEntry(bsontype.EmbeddedDocument, reflect.TypeOf(bson.Raw{})) +// +// Deprecated: Use Registry.RegisterTypeMapEntry instead. func (rb *RegistryBuilder) RegisterTypeMapEntry(bt bsontype.Type, rt reflect.Type) *RegistryBuilder { - rb.typeMap[bt] = rt + rb.registry.RegisterTypeMapEntry(bt, rt) return rb } // Build creates a Registry from the current state of this RegistryBuilder. +// +// Deprecated: Use NewRegistry instead. func (rb *RegistryBuilder) Build() *Registry { - registry := new(Registry) - - registry.typeEncoders = make(map[reflect.Type]ValueEncoder) - for t, enc := range rb.typeEncoders { - registry.typeEncoders[t] = enc + r := &Registry{ + interfaceEncoders: append([]interfaceValueEncoder(nil), rb.registry.interfaceEncoders...), + interfaceDecoders: append([]interfaceValueDecoder(nil), rb.registry.interfaceDecoders...), + typeEncoders: rb.registry.typeEncoders.Clone(), + typeDecoders: rb.registry.typeDecoders.Clone(), + kindEncoders: rb.registry.kindEncoders.Clone(), + kindDecoders: rb.registry.kindDecoders.Clone(), } + rb.registry.typeMap.Range(func(k, v interface{}) bool { + if k != nil && v != nil { + r.typeMap.Store(k, v) + } + return true + }) + return r +} - registry.typeDecoders = make(map[reflect.Type]ValueDecoder) - for t, dec := range rb.typeDecoders { - registry.typeDecoders[t] = dec +// A Registry is used to store and retrieve codecs for types and interfaces. This type is the main +// typed passed around and Encoders and Decoders are constructed from it. +type Registry struct { + interfaceEncoders []interfaceValueEncoder + interfaceDecoders []interfaceValueDecoder + typeEncoders *typeEncoderCache + typeDecoders *typeDecoderCache + kindEncoders *kindEncoderCache + kindDecoders *kindDecoderCache + typeMap sync.Map // map[bsontype.Type]reflect.Type +} + +// NewRegistry creates a new empty Registry. +func NewRegistry() *Registry { + return &Registry{ + typeEncoders: new(typeEncoderCache), + typeDecoders: new(typeDecoderCache), + kindEncoders: new(kindEncoderCache), + kindDecoders: new(kindDecoderCache), } +} + +// RegisterTypeEncoder registers the provided ValueEncoder for the provided type. +// +// The type will be used as provided, so an encoder can be registered for a type and a different +// encoder can be registered for a pointer to that type. +// +// If the given type is an interface, the encoder will be called when marshaling a type that is +// that interface. It will not be called when marshaling a non-interface type that implements the +// interface. To get the latter behavior, call RegisterHookEncoder instead. +// +// RegisterTypeEncoder should not be called concurrently with any other Registry method. +func (r *Registry) RegisterTypeEncoder(valueType reflect.Type, enc ValueEncoder) { + r.typeEncoders.Store(valueType, enc) +} + +// RegisterTypeDecoder registers the provided ValueDecoder for the provided type. +// +// The type will be used as provided, so a decoder can be registered for a type and a different +// decoder can be registered for a pointer to that type. +// +// If the given type is an interface, the decoder will be called when unmarshaling into a type that +// is that interface. It will not be called when unmarshaling into a non-interface type that +// implements the interface. To get the latter behavior, call RegisterHookDecoder instead. +// +// RegisterTypeDecoder should not be called concurrently with any other Registry method. +func (r *Registry) RegisterTypeDecoder(valueType reflect.Type, dec ValueDecoder) { + r.typeDecoders.Store(valueType, dec) +} - registry.interfaceEncoders = make([]interfaceValueEncoder, len(rb.interfaceEncoders)) - copy(registry.interfaceEncoders, rb.interfaceEncoders) +// RegisterKindEncoder registers the provided ValueEncoder for the provided kind. +// +// Use RegisterKindEncoder to register an encoder for any type with the same underlying kind. For +// example, consider the type MyInt defined as +// +// type MyInt int32 +// +// To define an encoder for MyInt and int32, use RegisterKindEncoder like +// +// reg.RegisterKindEncoder(reflect.Int32, myEncoder) +// +// RegisterKindEncoder should not be called concurrently with any other Registry method. +func (r *Registry) RegisterKindEncoder(kind reflect.Kind, enc ValueEncoder) { + r.kindEncoders.Store(kind, enc) +} - registry.interfaceDecoders = make([]interfaceValueDecoder, len(rb.interfaceDecoders)) - copy(registry.interfaceDecoders, rb.interfaceDecoders) +// RegisterKindDecoder registers the provided ValueDecoder for the provided kind. +// +// Use RegisterKindDecoder to register a decoder for any type with the same underlying kind. For +// example, consider the type MyInt defined as +// +// type MyInt int32 +// +// To define an decoder for MyInt and int32, use RegisterKindDecoder like +// +// reg.RegisterKindDecoder(reflect.Int32, myDecoder) +// +// RegisterKindDecoder should not be called concurrently with any other Registry method. +func (r *Registry) RegisterKindDecoder(kind reflect.Kind, dec ValueDecoder) { + r.kindDecoders.Store(kind, dec) +} - registry.kindEncoders = make(map[reflect.Kind]ValueEncoder) - for kind, enc := range rb.kindEncoders { - registry.kindEncoders[kind] = enc +// RegisterInterfaceEncoder registers an encoder for the provided interface type iface. This encoder will +// be called when marshaling a type if the type implements iface or a pointer to the type +// implements iface. If the provided type is not an interface +// (i.e. iface.Kind() != reflect.Interface), this method will panic. +// +// RegisterInterfaceEncoder should not be called concurrently with any other Registry method. +func (r *Registry) RegisterInterfaceEncoder(iface reflect.Type, enc ValueEncoder) { + if iface.Kind() != reflect.Interface { + panicStr := fmt.Errorf("RegisterInterfaceEncoder expects a type with kind reflect.Interface, "+ + "got type %s with kind %s", iface, iface.Kind()) + panic(panicStr) } - registry.kindDecoders = make(map[reflect.Kind]ValueDecoder) - for kind, dec := range rb.kindDecoders { - registry.kindDecoders[kind] = dec + for idx, encoder := range r.interfaceEncoders { + if encoder.i == iface { + r.interfaceEncoders[idx].ve = enc + return + } + } + + r.interfaceEncoders = append(r.interfaceEncoders, interfaceValueEncoder{i: iface, ve: enc}) +} + +// RegisterInterfaceDecoder registers an decoder for the provided interface type iface. This decoder will +// be called when unmarshaling into a type if the type implements iface or a pointer to the type +// implements iface. If the provided type is not an interface (i.e. iface.Kind() != reflect.Interface), +// this method will panic. +// +// RegisterInterfaceDecoder should not be called concurrently with any other Registry method. +func (r *Registry) RegisterInterfaceDecoder(iface reflect.Type, dec ValueDecoder) { + if iface.Kind() != reflect.Interface { + panicStr := fmt.Errorf("RegisterInterfaceDecoder expects a type with kind reflect.Interface, "+ + "got type %s with kind %s", iface, iface.Kind()) + panic(panicStr) } - registry.typeMap = make(map[bsontype.Type]reflect.Type) - for bt, rt := range rb.typeMap { - registry.typeMap[bt] = rt + for idx, decoder := range r.interfaceDecoders { + if decoder.i == iface { + r.interfaceDecoders[idx].vd = dec + return + } } - return registry + r.interfaceDecoders = append(r.interfaceDecoders, interfaceValueDecoder{i: iface, vd: dec}) } -// LookupEncoder inspects the registry for an encoder for the given type. The lookup precedence works as follows: +// RegisterTypeMapEntry will register the provided type to the BSON type. The primary usage for this +// mapping is decoding situations where an empty interface is used and a default type needs to be +// created and decoded into. // -// 1. An encoder registered for the exact type. If the given type represents an interface, an encoder registered using -// RegisterTypeEncoder for the interface will be selected. +// By default, BSON documents will decode into interface{} values as bson.D. To change the default type for BSON +// documents, a type map entry for bsontype.EmbeddedDocument should be registered. For example, to force BSON documents +// to decode to bson.Raw, use the following code: // -// 2. An encoder registered using RegisterHookEncoder for an interface implemented by the type or by a pointer to the -// type. +// reg.RegisterTypeMapEntry(bsontype.EmbeddedDocument, reflect.TypeOf(bson.Raw{})) +func (r *Registry) RegisterTypeMapEntry(bt bsontype.Type, rt reflect.Type) { + r.typeMap.Store(bt, rt) +} + +// LookupEncoder returns the first matching encoder in the Registry. It uses the following lookup +// order: +// +// 1. An encoder registered for the exact type. If the given type is an interface, an encoder +// registered using RegisterTypeEncoder for that interface will be selected. // -// 3. An encoder registered for the reflect.Kind of the value. +// 2. An encoder registered using RegisterInterfaceEncoder for an interface implemented by the type +// or by a pointer to the type. // -// If no encoder is found, an error of type ErrNoEncoder is returned. -func (r *Registry) LookupEncoder(t reflect.Type) (ValueEncoder, error) { - encodererr := ErrNoEncoder{Type: t} - r.mu.RLock() - enc, found := r.lookupTypeEncoder(t) - r.mu.RUnlock() +// 3. An encoder registered using RegisterKindEncoder for the kind of value. +// +// If no encoder is found, an error of type ErrNoEncoder is returned. LookupEncoder is safe for +// concurrent use by multiple goroutines after all codecs and encoders are registered. +func (r *Registry) LookupEncoder(valueType reflect.Type) (ValueEncoder, error) { + if valueType == nil { + return nil, ErrNoEncoder{Type: valueType} + } + enc, found := r.lookupTypeEncoder(valueType) if found { if enc == nil { - return nil, ErrNoEncoder{Type: t} + return nil, ErrNoEncoder{Type: valueType} } return enc, nil } - enc, found = r.lookupInterfaceEncoder(t, true) + enc, found = r.lookupInterfaceEncoder(valueType, true) if found { - r.mu.Lock() - r.typeEncoders[t] = enc - r.mu.Unlock() - return enc, nil - } - - if t == nil { - r.mu.Lock() - r.typeEncoders[t] = nil - r.mu.Unlock() - return nil, encodererr + return r.typeEncoders.LoadOrStore(valueType, enc), nil } - enc, found = r.kindEncoders[t.Kind()] - if !found { - r.mu.Lock() - r.typeEncoders[t] = nil - r.mu.Unlock() - return nil, encodererr + if v, ok := r.kindEncoders.Load(valueType.Kind()); ok { + return r.storeTypeEncoder(valueType, v), nil } + return nil, ErrNoEncoder{Type: valueType} +} - r.mu.Lock() - r.typeEncoders[t] = enc - r.mu.Unlock() - return enc, nil +func (r *Registry) storeTypeEncoder(rt reflect.Type, enc ValueEncoder) ValueEncoder { + return r.typeEncoders.LoadOrStore(rt, enc) } -func (r *Registry) lookupTypeEncoder(t reflect.Type) (ValueEncoder, bool) { - enc, found := r.typeEncoders[t] - return enc, found +func (r *Registry) lookupTypeEncoder(rt reflect.Type) (ValueEncoder, bool) { + return r.typeEncoders.Load(rt) } -func (r *Registry) lookupInterfaceEncoder(t reflect.Type, allowAddr bool) (ValueEncoder, bool) { - if t == nil { +func (r *Registry) lookupInterfaceEncoder(valueType reflect.Type, allowAddr bool) (ValueEncoder, bool) { + if valueType == nil { return nil, false } for _, ienc := range r.interfaceEncoders { - if t.Implements(ienc.i) { + if valueType.Implements(ienc.i) { return ienc.ve, true } - if allowAddr && t.Kind() != reflect.Ptr && reflect.PtrTo(t).Implements(ienc.i) { - // if *t implements an interface, this will catch if t implements an interface further ahead - // in interfaceEncoders - defaultEnc, found := r.lookupInterfaceEncoder(t, false) + if allowAddr && valueType.Kind() != reflect.Ptr && reflect.PtrTo(valueType).Implements(ienc.i) { + // if *t implements an interface, this will catch if t implements an interface further + // ahead in interfaceEncoders + defaultEnc, found := r.lookupInterfaceEncoder(valueType, false) if !found { - defaultEnc = r.kindEncoders[t.Kind()] + defaultEnc, _ = r.kindEncoders.Load(valueType.Kind()) } return newCondAddrEncoder(ienc.ve, defaultEnc), true } @@ -377,70 +439,61 @@ func (r *Registry) lookupInterfaceEncoder(t reflect.Type, allowAddr bool) (Value return nil, false } -// LookupDecoder inspects the registry for an decoder for the given type. The lookup precedence works as follows: +// LookupDecoder returns the first matching decoder in the Registry. It uses the following lookup +// order: // -// 1. A decoder registered for the exact type. If the given type represents an interface, a decoder registered using -// RegisterTypeDecoder for the interface will be selected. +// 1. A decoder registered for the exact type. If the given type is an interface, a decoder +// registered using RegisterTypeDecoder for that interface will be selected. // -// 2. A decoder registered using RegisterHookDecoder for an interface implemented by the type or by a pointer to the -// type. +// 2. A decoder registered using RegisterInterfaceDecoder for an interface implemented by the type or by +// a pointer to the type. // -// 3. A decoder registered for the reflect.Kind of the value. +// 3. A decoder registered using RegisterKindDecoder for the kind of value. // -// If no decoder is found, an error of type ErrNoDecoder is returned. -func (r *Registry) LookupDecoder(t reflect.Type) (ValueDecoder, error) { - if t == nil { +// If no decoder is found, an error of type ErrNoDecoder is returned. LookupDecoder is safe for +// concurrent use by multiple goroutines after all codecs and decoders are registered. +func (r *Registry) LookupDecoder(valueType reflect.Type) (ValueDecoder, error) { + if valueType == nil { return nil, ErrNilType } - decodererr := ErrNoDecoder{Type: t} - r.mu.RLock() - dec, found := r.lookupTypeDecoder(t) - r.mu.RUnlock() + dec, found := r.lookupTypeDecoder(valueType) if found { if dec == nil { - return nil, ErrNoDecoder{Type: t} + return nil, ErrNoDecoder{Type: valueType} } return dec, nil } - dec, found = r.lookupInterfaceDecoder(t, true) + dec, found = r.lookupInterfaceDecoder(valueType, true) if found { - r.mu.Lock() - r.typeDecoders[t] = dec - r.mu.Unlock() - return dec, nil + return r.storeTypeDecoder(valueType, dec), nil } - dec, found = r.kindDecoders[t.Kind()] - if !found { - r.mu.Lock() - r.typeDecoders[t] = nil - r.mu.Unlock() - return nil, decodererr + if v, ok := r.kindDecoders.Load(valueType.Kind()); ok { + return r.storeTypeDecoder(valueType, v), nil } + return nil, ErrNoDecoder{Type: valueType} +} - r.mu.Lock() - r.typeDecoders[t] = dec - r.mu.Unlock() - return dec, nil +func (r *Registry) lookupTypeDecoder(valueType reflect.Type) (ValueDecoder, bool) { + return r.typeDecoders.Load(valueType) } -func (r *Registry) lookupTypeDecoder(t reflect.Type) (ValueDecoder, bool) { - dec, found := r.typeDecoders[t] - return dec, found +func (r *Registry) storeTypeDecoder(typ reflect.Type, dec ValueDecoder) ValueDecoder { + return r.typeDecoders.LoadOrStore(typ, dec) } -func (r *Registry) lookupInterfaceDecoder(t reflect.Type, allowAddr bool) (ValueDecoder, bool) { +func (r *Registry) lookupInterfaceDecoder(valueType reflect.Type, allowAddr bool) (ValueDecoder, bool) { for _, idec := range r.interfaceDecoders { - if t.Implements(idec.i) { + if valueType.Implements(idec.i) { return idec.vd, true } - if allowAddr && t.Kind() != reflect.Ptr && reflect.PtrTo(t).Implements(idec.i) { - // if *t implements an interface, this will catch if t implements an interface further ahead - // in interfaceDecoders - defaultDec, found := r.lookupInterfaceDecoder(t, false) + if allowAddr && valueType.Kind() != reflect.Ptr && reflect.PtrTo(valueType).Implements(idec.i) { + // if *t implements an interface, this will catch if t implements an interface further + // ahead in interfaceDecoders + defaultDec, found := r.lookupInterfaceDecoder(valueType, false) if !found { - defaultDec = r.kindDecoders[t.Kind()] + defaultDec, _ = r.kindDecoders.Load(valueType.Kind()) } return newCondAddrDecoder(idec.vd, defaultDec), true } @@ -450,12 +503,14 @@ func (r *Registry) lookupInterfaceDecoder(t reflect.Type, allowAddr bool) (Value // LookupTypeMapEntry inspects the registry's type map for a Go type for the corresponding BSON // type. If no type is found, ErrNoTypeMapEntry is returned. +// +// LookupTypeMapEntry should not be called concurrently with any other Registry method. func (r *Registry) LookupTypeMapEntry(bt bsontype.Type) (reflect.Type, error) { - t, ok := r.typeMap[bt] - if !ok || t == nil { + v, ok := r.typeMap.Load(bt) + if v == nil || !ok { return nil, ErrNoTypeMapEntry{Type: bt} } - return t, nil + return v.(reflect.Type), nil } type interfaceValueEncoder struct { diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/slice_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/slice_codec.go index 3c1b6b860a..14c9fd2564 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/slice_codec.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/slice_codec.go @@ -7,6 +7,7 @@ package bsoncodec import ( + "errors" "fmt" "reflect" @@ -19,13 +20,35 @@ import ( var defaultSliceCodec = NewSliceCodec() // SliceCodec is the Codec used for slice values. +// +// Deprecated: SliceCodec will not be directly configurable in Go Driver 2.0. To +// configure the slice encode and decode behavior, use the configuration methods +// on a [go.mongodb.org/mongo-driver/bson.Encoder] or +// [go.mongodb.org/mongo-driver/bson.Decoder]. To configure the slice encode and +// decode behavior for a mongo.Client, use +// [go.mongodb.org/mongo-driver/mongo/options.ClientOptions.SetBSONOptions]. +// +// For example, to configure a mongo.Client to marshal nil Go slices as empty +// BSON arrays, use: +// +// opt := options.Client().SetBSONOptions(&options.BSONOptions{ +// NilSliceAsEmpty: true, +// }) +// +// See the deprecation notice for each field in SliceCodec for the corresponding +// settings. type SliceCodec struct { + // EncodeNilAsEmpty causes EncodeValue to marshal nil Go slices as empty BSON arrays instead of + // BSON null. + // + // Deprecated: Use bson.Encoder.NilSliceAsEmpty instead. EncodeNilAsEmpty bool } -var _ ValueCodec = &MapCodec{} - // NewSliceCodec returns a MapCodec with options opts. +// +// Deprecated: NewSliceCodec will not be available in Go Driver 2.0. See +// [SliceCodec] for more details. func NewSliceCodec(opts ...*bsonoptions.SliceCodecOptions) *SliceCodec { sliceOpt := bsonoptions.MergeSliceCodecOptions(opts...) @@ -42,21 +65,19 @@ func (sc SliceCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val re return ValueEncoderError{Name: "SliceEncodeValue", Kinds: []reflect.Kind{reflect.Slice}, Received: val} } - if val.IsNil() && !sc.EncodeNilAsEmpty { + if val.IsNil() && !sc.EncodeNilAsEmpty && !ec.nilSliceAsEmpty { return vw.WriteNull() } // If we have a []byte we want to treat it as a binary instead of as an array. if val.Type().Elem() == tByte { - var byteSlice []byte - for idx := 0; idx < val.Len(); idx++ { - byteSlice = append(byteSlice, val.Index(idx).Interface().(byte)) - } + byteSlice := make([]byte, val.Len()) + reflect.Copy(reflect.ValueOf(byteSlice), val) return vw.WriteBinary(byteSlice) } // If we have a []primitive.E we want to treat it as a document instead of as an array. - if val.Type().ConvertibleTo(tD) { + if val.Type() == tD || val.Type().ConvertibleTo(tD) { d := val.Convert(tD).Interface().(primitive.D) dw, err := vw.WriteDocument() @@ -87,7 +108,7 @@ func (sc SliceCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val re for idx := 0; idx < val.Len(); idx++ { currEncoder, currVal, lookupErr := defaultValueEncoders.lookupElementEncoder(ec, encoder, val.Index(idx)) - if lookupErr != nil && lookupErr != errInvalidValue { + if lookupErr != nil && !errors.Is(lookupErr, errInvalidValue) { return lookupErr } @@ -96,7 +117,7 @@ func (sc SliceCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val re return err } - if lookupErr == errInvalidValue { + if errors.Is(lookupErr, errInvalidValue) { err = vw.WriteNull() if err != nil { return err @@ -145,11 +166,8 @@ func (sc *SliceCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val r if val.IsNil() { val.Set(reflect.MakeSlice(val.Type(), 0, len(data))) } - val.SetLen(0) - for _, elem := range data { - val.Set(reflect.Append(val, reflect.ValueOf(elem))) - } + val.Set(reflect.AppendSlice(val, reflect.ValueOf(data))) return nil case bsontype.String: if sliceType := val.Type().Elem(); sliceType != tByte { @@ -164,11 +182,8 @@ func (sc *SliceCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val r if val.IsNil() { val.Set(reflect.MakeSlice(val.Type(), 0, len(byteStr))) } - val.SetLen(0) - for _, elem := range byteStr { - val.Set(reflect.Append(val, reflect.ValueOf(elem))) - } + val.Set(reflect.AppendSlice(val, reflect.ValueOf(byteStr))) return nil default: return fmt.Errorf("cannot decode %v into a slice", vrType) diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/string_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/string_codec.go index 5332b7c3b5..a8f885a854 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/string_codec.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/string_codec.go @@ -15,26 +15,46 @@ import ( "go.mongodb.org/mongo-driver/bson/bsontype" ) -// StringCodec is the Codec used for struct values. +// StringCodec is the Codec used for string values. +// +// Deprecated: StringCodec will not be directly accessible in Go Driver 2.0. To +// override the default string encode and decode behavior, create a new registry +// with [go.mongodb.org/mongo-driver/bson.NewRegistry] and register a new +// encoder and decoder for strings. +// +// For example, +// +// reg := bson.NewRegistry() +// reg.RegisterKindEncoder(reflect.String, myStringEncoder) +// reg.RegisterKindDecoder(reflect.String, myStringDecoder) type StringCodec struct { + // DecodeObjectIDAsHex specifies if object IDs should be decoded as their hex representation. + // If false, a string made from the raw object ID bytes will be used. Defaults to true. + // + // Deprecated: Decoding object IDs as raw bytes will not be supported in Go Driver 2.0. DecodeObjectIDAsHex bool } var ( defaultStringCodec = NewStringCodec() - _ ValueCodec = defaultStringCodec + // Assert that defaultStringCodec satisfies the typeDecoder interface, which allows it to be + // used by collection type decoders (e.g. map, slice, etc) to set individual values in a + // collection. _ typeDecoder = defaultStringCodec ) // NewStringCodec returns a StringCodec with options opts. +// +// Deprecated: NewStringCodec will not be available in Go Driver 2.0. See +// [StringCodec] for more details. func NewStringCodec(opts ...*bsonoptions.StringCodecOptions) *StringCodec { stringOpt := bsonoptions.MergeStringCodecOptions(opts...) return &StringCodec{*stringOpt.DecodeObjectIDAsHex} } // EncodeValue is the ValueEncoder for string types. -func (sc *StringCodec) EncodeValue(ectx EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +func (sc *StringCodec) EncodeValue(_ EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { if val.Kind() != reflect.String { return ValueEncoderError{ Name: "StringEncodeValue", @@ -46,7 +66,7 @@ func (sc *StringCodec) EncodeValue(ectx EncodeContext, vw bsonrw.ValueWriter, va return vw.WriteString(val.String()) } -func (sc *StringCodec) decodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { +func (sc *StringCodec) decodeType(_ DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { if t.Kind() != reflect.String { return emptyValue, ValueDecoderError{ Name: "StringDecodeValue", @@ -71,6 +91,7 @@ func (sc *StringCodec) decodeType(dc DecodeContext, vr bsonrw.ValueReader, t ref if sc.DecodeObjectIDAsHex { str = oid.Hex() } else { + // TODO(GODRIVER-2796): Return an error here instead of decoding to a garbled string. byteArray := [12]byte(oid) str = string(byteArray[:]) } diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/struct_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/struct_codec.go index be3f2081e9..f8d9690c13 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/struct_codec.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/struct_codec.go @@ -59,14 +59,58 @@ type Zeroer interface { } // StructCodec is the Codec used for struct values. +// +// Deprecated: StructCodec will not be directly configurable in Go Driver 2.0. +// To configure the struct encode and decode behavior, use the configuration +// methods on a [go.mongodb.org/mongo-driver/bson.Encoder] or +// [go.mongodb.org/mongo-driver/bson.Decoder]. To configure the struct encode +// and decode behavior for a mongo.Client, use +// [go.mongodb.org/mongo-driver/mongo/options.ClientOptions.SetBSONOptions]. +// +// For example, to configure a mongo.Client to omit zero-value structs when +// using the "omitempty" struct tag, use: +// +// opt := options.Client().SetBSONOptions(&options.BSONOptions{ +// OmitZeroStruct: true, +// }) +// +// See the deprecation notice for each field in StructCodec for the corresponding +// settings. type StructCodec struct { - cache map[reflect.Type]*structDescription - l sync.RWMutex - parser StructTagParser - DecodeZeroStruct bool - DecodeDeepZeroInline bool - EncodeOmitDefaultStruct bool - AllowUnexportedFields bool + cache sync.Map // map[reflect.Type]*structDescription + parser StructTagParser + + // DecodeZeroStruct causes DecodeValue to delete any existing values from Go structs in the + // destination value passed to Decode before unmarshaling BSON documents into them. + // + // Deprecated: Use bson.Decoder.ZeroStructs or options.BSONOptions.ZeroStructs instead. + DecodeZeroStruct bool + + // DecodeDeepZeroInline causes DecodeValue to delete any existing values from Go structs in the + // destination value passed to Decode before unmarshaling BSON documents into them. + // + // Deprecated: DecodeDeepZeroInline will not be supported in Go Driver 2.0. + DecodeDeepZeroInline bool + + // EncodeOmitDefaultStruct causes the Encoder to consider the zero value for a struct (e.g. + // MyStruct{}) as empty and omit it from the marshaled BSON when the "omitempty" struct tag + // option is set. + // + // Deprecated: Use bson.Encoder.OmitZeroStruct or options.BSONOptions.OmitZeroStruct instead. + EncodeOmitDefaultStruct bool + + // AllowUnexportedFields allows encoding and decoding values from un-exported struct fields. + // + // Deprecated: AllowUnexportedFields does not work on recent versions of Go and will not be + // supported in Go Driver 2.0. + AllowUnexportedFields bool + + // OverwriteDuplicatedInlinedFields, if false, causes EncodeValue to return an error if there is + // a duplicate field in the marshaled BSON when the "inline" struct tag option is set. The + // default value is true. + // + // Deprecated: Use bson.Encoder.ErrorOnInlineDuplicates or + // options.BSONOptions.ErrorOnInlineDuplicates instead. OverwriteDuplicatedInlinedFields bool } @@ -74,6 +118,9 @@ var _ ValueEncoder = &StructCodec{} var _ ValueDecoder = &StructCodec{} // NewStructCodec returns a StructCodec that uses p for struct tag parsing. +// +// Deprecated: NewStructCodec will not be available in Go Driver 2.0. See +// [StructCodec] for more details. func NewStructCodec(p StructTagParser, opts ...*bsonoptions.StructCodecOptions) (*StructCodec, error) { if p == nil { return nil, errors.New("a StructTagParser must be provided to NewStructCodec") @@ -82,7 +129,6 @@ func NewStructCodec(p StructTagParser, opts ...*bsonoptions.StructCodecOptions) structOpt := bsonoptions.MergeStructCodecOptions(opts...) codec := &StructCodec{ - cache: make(map[reflect.Type]*structDescription), parser: p, } @@ -106,12 +152,12 @@ func NewStructCodec(p StructTagParser, opts ...*bsonoptions.StructCodecOptions) } // EncodeValue handles encoding generic struct types. -func (sc *StructCodec) EncodeValue(r EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +func (sc *StructCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Kind() != reflect.Struct { return ValueEncoderError{Name: "StructCodec.EncodeValue", Kinds: []reflect.Kind{reflect.Struct}, Received: val} } - sd, err := sc.describeStruct(r.Registry, val.Type()) + sd, err := sc.describeStruct(ec.Registry, val.Type(), ec.useJSONStructTags, ec.errorOnInlineDuplicates) if err != nil { return err } @@ -131,13 +177,13 @@ func (sc *StructCodec) EncodeValue(r EncodeContext, vw bsonrw.ValueWriter, val r } } - desc.encoder, rv, err = defaultValueEncoders.lookupElementEncoder(r, desc.encoder, rv) + desc.encoder, rv, err = defaultValueEncoders.lookupElementEncoder(ec, desc.encoder, rv) - if err != nil && err != errInvalidValue { + if err != nil && !errors.Is(err, errInvalidValue) { return err } - if err == errInvalidValue { + if errors.Is(err, errInvalidValue) { if desc.omitEmpty { continue } @@ -158,17 +204,17 @@ func (sc *StructCodec) EncodeValue(r EncodeContext, vw bsonrw.ValueWriter, val r encoder := desc.encoder - var isZero bool - rvInterface := rv.Interface() + var empty bool if cz, ok := encoder.(CodecZeroer); ok { - isZero = cz.IsTypeZero(rvInterface) + empty = cz.IsTypeZero(rv.Interface()) } else if rv.Kind() == reflect.Interface { - // sc.isZero will not treat an interface rv as an interface, so we need to check for the zero interface separately. - isZero = rv.IsNil() + // isEmpty will not treat an interface rv as an interface, so we need to check for the + // nil interface separately. + empty = rv.IsNil() } else { - isZero = sc.isZero(rvInterface) + empty = isEmpty(rv, sc.EncodeOmitDefaultStruct || ec.omitZeroStruct) } - if desc.omitEmpty && isZero { + if desc.omitEmpty && empty { continue } @@ -177,7 +223,17 @@ func (sc *StructCodec) EncodeValue(r EncodeContext, vw bsonrw.ValueWriter, val r return err } - ectx := EncodeContext{Registry: r.Registry, MinSize: desc.minSize} + ectx := EncodeContext{ + Registry: ec.Registry, + MinSize: desc.minSize || ec.MinSize, + errorOnInlineDuplicates: ec.errorOnInlineDuplicates, + stringifyMapKeysWithFmt: ec.stringifyMapKeysWithFmt, + nilMapAsEmpty: ec.nilMapAsEmpty, + nilSliceAsEmpty: ec.nilSliceAsEmpty, + nilByteSliceAsEmpty: ec.nilByteSliceAsEmpty, + omitZeroStruct: ec.omitZeroStruct, + useJSONStructTags: ec.useJSONStructTags, + } err = encoder.EncodeValue(ectx, vw2, rv) if err != nil { return err @@ -191,15 +247,15 @@ func (sc *StructCodec) EncodeValue(r EncodeContext, vw bsonrw.ValueWriter, val r return exists } - return defaultMapCodec.mapEncodeValue(r, dw, rv, collisionFn) + return defaultMapCodec.mapEncodeValue(ec, dw, rv, collisionFn) } return dw.WriteDocumentEnd() } func newDecodeError(key string, original error) error { - de, ok := original.(*DecodeError) - if !ok { + var de *DecodeError + if !errors.As(original, &de) { return &DecodeError{ keys: []string{key}, wrapped: original, @@ -213,7 +269,7 @@ func newDecodeError(key string, original error) error { // DecodeValue implements the Codec interface. // By default, map types in val will not be cleared. If a map has existing key/value pairs, it will be extended with the new ones from vr. // For slices, the decoder will set the length of the slice to zero and append all elements. The underlying array will not be cleared. -func (sc *StructCodec) DecodeValue(r DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +func (sc *StructCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { if !val.CanSet() || val.Kind() != reflect.Struct { return ValueDecoderError{Name: "StructCodec.DecodeValue", Kinds: []reflect.Kind{reflect.Struct}, Received: val} } @@ -238,12 +294,12 @@ func (sc *StructCodec) DecodeValue(r DecodeContext, vr bsonrw.ValueReader, val r return fmt.Errorf("cannot decode %v into a %s", vrType, val.Type()) } - sd, err := sc.describeStruct(r.Registry, val.Type()) + sd, err := sc.describeStruct(dc.Registry, val.Type(), dc.useJSONStructTags, false) if err != nil { return err } - if sc.DecodeZeroStruct { + if sc.DecodeZeroStruct || dc.zeroStructs { val.Set(reflect.Zero(val.Type())) } if sc.DecodeDeepZeroInline && sd.inline { @@ -254,7 +310,7 @@ func (sc *StructCodec) DecodeValue(r DecodeContext, vr bsonrw.ValueReader, val r var inlineMap reflect.Value if sd.inlineMap >= 0 { inlineMap = val.Field(sd.inlineMap) - decoder, err = r.LookupDecoder(inlineMap.Type().Elem()) + decoder, err = dc.LookupDecoder(inlineMap.Type().Elem()) if err != nil { return err } @@ -267,7 +323,7 @@ func (sc *StructCodec) DecodeValue(r DecodeContext, vr bsonrw.ValueReader, val r for { name, vr, err := dr.ReadElement() - if err == bsonrw.ErrEOD { + if errors.Is(err, bsonrw.ErrEOD) { break } if err != nil { @@ -298,8 +354,8 @@ func (sc *StructCodec) DecodeValue(r DecodeContext, vr bsonrw.ValueReader, val r } elem := reflect.New(inlineMap.Type().Elem()).Elem() - r.Ancestor = inlineMap.Type() - err = decoder.DecodeValue(r, vr, elem) + dc.Ancestor = inlineMap.Type() + err = decoder.DecodeValue(dc, vr, elem) if err != nil { return err } @@ -326,7 +382,17 @@ func (sc *StructCodec) DecodeValue(r DecodeContext, vr bsonrw.ValueReader, val r } field = field.Addr() - dctx := DecodeContext{Registry: r.Registry, Truncate: fd.truncate || r.Truncate} + dctx := DecodeContext{ + Registry: dc.Registry, + Truncate: fd.truncate || dc.Truncate, + defaultDocumentType: dc.defaultDocumentType, + binaryAsSlice: dc.binaryAsSlice, + useJSONStructTags: dc.useJSONStructTags, + useLocalTimeZone: dc.useLocalTimeZone, + zeroMaps: dc.zeroMaps, + zeroStructs: dc.zeroStructs, + } + if fd.decoder == nil { return newDecodeError(fd.name, ErrNoDecoder{Type: field.Elem().Type()}) } @@ -340,51 +406,35 @@ func (sc *StructCodec) DecodeValue(r DecodeContext, vr bsonrw.ValueReader, val r return nil } -func (sc *StructCodec) isZero(i interface{}) bool { - v := reflect.ValueOf(i) - - // check the value validity - if !v.IsValid() { - return true - } - - if z, ok := v.Interface().(Zeroer); ok && (v.Kind() != reflect.Ptr || !v.IsNil()) { - return z.IsZero() +func isEmpty(v reflect.Value, omitZeroStruct bool) bool { + kind := v.Kind() + if (kind != reflect.Ptr || !v.IsNil()) && v.Type().Implements(tZeroer) { + return v.Interface().(Zeroer).IsZero() } - - switch v.Kind() { + switch kind { case reflect.Array, reflect.Map, reflect.Slice, reflect.String: return v.Len() == 0 - case reflect.Bool: - return !v.Bool() - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return v.Int() == 0 - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - return v.Uint() == 0 - case reflect.Float32, reflect.Float64: - return v.Float() == 0 - case reflect.Interface, reflect.Ptr: - return v.IsNil() case reflect.Struct: - if sc.EncodeOmitDefaultStruct { - vt := v.Type() - if vt == tTime { - return v.Interface().(time.Time).IsZero() + if !omitZeroStruct { + return false + } + vt := v.Type() + if vt == tTime { + return v.Interface().(time.Time).IsZero() + } + numField := vt.NumField() + for i := 0; i < numField; i++ { + ff := vt.Field(i) + if ff.PkgPath != "" && !ff.Anonymous { + continue // Private field } - for i := 0; i < v.NumField(); i++ { - if vt.Field(i).PkgPath != "" && !vt.Field(i).Anonymous { - continue // Private field - } - fld := v.Field(i) - if !sc.isZero(fld.Interface()) { - return false - } + if !isEmpty(v.Field(i), omitZeroStruct) { + return false } - return true } + return true } - - return false + return !v.IsValid() || v.IsZero() } type structDescription struct { @@ -435,16 +485,35 @@ func (bi byIndex) Less(i, j int) bool { return len(bi[i].inline) < len(bi[j].inline) } -func (sc *StructCodec) describeStruct(r *Registry, t reflect.Type) (*structDescription, error) { +func (sc *StructCodec) describeStruct( + r *Registry, + t reflect.Type, + useJSONStructTags bool, + errorOnDuplicates bool, +) (*structDescription, error) { // We need to analyze the struct, including getting the tags, collecting // information about inlining, and create a map of the field name to the field. - sc.l.RLock() - ds, exists := sc.cache[t] - sc.l.RUnlock() - if exists { - return ds, nil + if v, ok := sc.cache.Load(t); ok { + return v.(*structDescription), nil } + // TODO(charlie): Only describe the struct once when called + // concurrently with the same type. + ds, err := sc.describeStructSlow(r, t, useJSONStructTags, errorOnDuplicates) + if err != nil { + return nil, err + } + if v, loaded := sc.cache.LoadOrStore(t, ds); loaded { + ds = v.(*structDescription) + } + return ds, nil +} +func (sc *StructCodec) describeStructSlow( + r *Registry, + t reflect.Type, + useJSONStructTags bool, + errorOnDuplicates bool, +) (*structDescription, error) { numFields := t.NumField() sd := &structDescription{ fm: make(map[string]fieldDescription, numFields), @@ -477,7 +546,14 @@ func (sc *StructCodec) describeStruct(r *Registry, t reflect.Type) (*structDescr decoder: decoder, } - stags, err := sc.parser.ParseStructTags(sf) + var stags StructTags + // If the caller requested that we use JSON struct tags, use the JSONFallbackStructTagParser + // instead of the parser defined on the codec. + if useJSONStructTags { + stags, err = JSONFallbackStructTagParser.ParseStructTags(sf) + } else { + stags, err = sc.parser.ParseStructTags(sf) + } if err != nil { return nil, err } @@ -507,7 +583,7 @@ func (sc *StructCodec) describeStruct(r *Registry, t reflect.Type) (*structDescr } fallthrough case reflect.Struct: - inlinesf, err := sc.describeStruct(r, sfType) + inlinesf, err := sc.describeStruct(r, sfType, useJSONStructTags, errorOnDuplicates) if err != nil { return nil, err } @@ -559,7 +635,7 @@ func (sc *StructCodec) describeStruct(r *Registry, t reflect.Type) (*structDescr continue } dominant, ok := dominantField(fields[i : i+advance]) - if !ok || !sc.OverwriteDuplicatedInlinedFields { + if !ok || !sc.OverwriteDuplicatedInlinedFields || errorOnDuplicates { return nil, fmt.Errorf("struct %s has duplicated key %s", t.String(), name) } sd.fl = append(sd.fl, dominant) @@ -568,10 +644,6 @@ func (sc *StructCodec) describeStruct(r *Registry, t reflect.Type) (*structDescr sort.Sort(byIndex(sd.fl)) - sc.l.Lock() - sc.cache[t] = sd - sc.l.Unlock() - return sd, nil } @@ -629,21 +701,21 @@ func getInlineField(val reflect.Value, index []int) (reflect.Value, error) { // DeepZero returns recursive zero object func deepZero(st reflect.Type) (result reflect.Value) { - result = reflect.Indirect(reflect.New(st)) - - if result.Kind() == reflect.Struct { - for i := 0; i < result.NumField(); i++ { - if f := result.Field(i); f.Kind() == reflect.Ptr { - if f.CanInterface() { - if ft := reflect.TypeOf(f.Interface()); ft.Elem().Kind() == reflect.Struct { - result.Field(i).Set(recursivePointerTo(deepZero(ft.Elem()))) - } + if st.Kind() == reflect.Struct { + numField := st.NumField() + for i := 0; i < numField; i++ { + if result == emptyValue { + result = reflect.Indirect(reflect.New(st)) + } + f := result.Field(i) + if f.CanInterface() { + if f.Type().Kind() == reflect.Struct { + result.Field(i).Set(recursivePointerTo(deepZero(f.Type().Elem()))) } } } } - - return + return result } // recursivePointerTo calls reflect.New(v.Type) but recursively for its fields inside diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/struct_tag_parser.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/struct_tag_parser.go index 62708c5c74..18d85bfb03 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/struct_tag_parser.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/struct_tag_parser.go @@ -12,12 +12,16 @@ import ( ) // StructTagParser returns the struct tags for a given struct field. +// +// Deprecated: Defining custom BSON struct tag parsers will not be supported in Go Driver 2.0. type StructTagParser interface { ParseStructTags(reflect.StructField) (StructTags, error) } // StructTagParserFunc is an adapter that allows a generic function to be used // as a StructTagParser. +// +// Deprecated: Defining custom BSON struct tag parsers will not be supported in Go Driver 2.0. type StructTagParserFunc func(reflect.StructField) (StructTags, error) // ParseStructTags implements the StructTagParser interface. @@ -50,7 +54,7 @@ func (stpf StructTagParserFunc) ParseStructTags(sf reflect.StructField) (StructT // Skip This struct field should be skipped. This is usually denoted by parsing a "-" // for the name. // -// TODO(skriptble): Add tags for undefined as nil and for null as nil. +// Deprecated: Defining custom BSON struct tag parsers will not be supported in Go Driver 2.0. type StructTags struct { Name string OmitEmpty bool @@ -85,6 +89,8 @@ type StructTags struct { // A struct tag either consisting entirely of '-' or with a bson key with a // value consisting entirely of '-' will return a StructTags with Skip true and // the remaining fields will be their default values. +// +// Deprecated: DefaultStructTagParser will be removed in Go Driver 2.0. var DefaultStructTagParser StructTagParserFunc = func(sf reflect.StructField) (StructTags, error) { key := strings.ToLower(sf.Name) tag, ok := sf.Tag.Lookup("bson") @@ -125,6 +131,9 @@ func parseTags(key string, tag string) (StructTags, error) { // JSONFallbackStructTagParser has the same behavior as DefaultStructTagParser // but will also fallback to parsing the json tag instead on a field where the // bson tag isn't available. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.Encoder.UseJSONStructTags] and +// [go.mongodb.org/mongo-driver/bson.Decoder.UseJSONStructTags] instead. var JSONFallbackStructTagParser StructTagParserFunc = func(sf reflect.StructField) (StructTags, error) { key := strings.ToLower(sf.Name) tag, ok := sf.Tag.Lookup("bson") diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/time_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/time_codec.go index ec7e30f724..22fb762c41 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/time_codec.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/time_codec.go @@ -22,18 +22,42 @@ const ( ) // TimeCodec is the Codec used for time.Time values. +// +// Deprecated: TimeCodec will not be directly configurable in Go Driver 2.0. +// To configure the time.Time encode and decode behavior, use the configuration +// methods on a [go.mongodb.org/mongo-driver/bson.Encoder] or +// [go.mongodb.org/mongo-driver/bson.Decoder]. To configure the time.Time encode +// and decode behavior for a mongo.Client, use +// [go.mongodb.org/mongo-driver/mongo/options.ClientOptions.SetBSONOptions]. +// +// For example, to configure a mongo.Client to ..., use: +// +// opt := options.Client().SetBSONOptions(&options.BSONOptions{ +// UseLocalTimeZone: true, +// }) +// +// See the deprecation notice for each field in TimeCodec for the corresponding +// settings. type TimeCodec struct { + // UseLocalTimeZone specifies if we should decode into the local time zone. Defaults to false. + // + // Deprecated: Use bson.Decoder.UseLocalTimeZone or options.BSONOptions.UseLocalTimeZone + // instead. UseLocalTimeZone bool } var ( defaultTimeCodec = NewTimeCodec() - _ ValueCodec = defaultTimeCodec + // Assert that defaultTimeCodec satisfies the typeDecoder interface, which allows it to be used + // by collection type decoders (e.g. map, slice, etc) to set individual values in a collection. _ typeDecoder = defaultTimeCodec ) // NewTimeCodec returns a TimeCodec with options opts. +// +// Deprecated: NewTimeCodec will not be available in Go Driver 2.0. See +// [TimeCodec] for more details. func NewTimeCodec(opts ...*bsonoptions.TimeCodecOptions) *TimeCodec { timeOpt := bsonoptions.MergeTimeCodecOptions(opts...) @@ -95,7 +119,7 @@ func (tc *TimeCodec) decodeType(dc DecodeContext, vr bsonrw.ValueReader, t refle return emptyValue, fmt.Errorf("cannot decode %v into a time.Time", vrType) } - if !tc.UseLocalTimeZone { + if !tc.UseLocalTimeZone && !dc.useLocalTimeZone { timeVal = timeVal.UTC() } return reflect.ValueOf(timeVal), nil @@ -117,7 +141,7 @@ func (tc *TimeCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val re } // EncodeValue is the ValueEncoderFunc for time.TIme. -func (tc *TimeCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +func (tc *TimeCodec) EncodeValue(_ EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Type() != tTime { return ValueEncoderError{Name: "TimeEncodeValue", Types: []reflect.Type{tTime}, Received: val} } diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/types.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/types.go index 07f4b70e6d..6ade17b7d3 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/types.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/types.go @@ -34,6 +34,7 @@ var tValueUnmarshaler = reflect.TypeOf((*ValueUnmarshaler)(nil)).Elem() var tMarshaler = reflect.TypeOf((*Marshaler)(nil)).Elem() var tUnmarshaler = reflect.TypeOf((*Unmarshaler)(nil)).Elem() var tProxy = reflect.TypeOf((*Proxy)(nil)).Elem() +var tZeroer = reflect.TypeOf((*Zeroer)(nil)).Elem() var tBinary = reflect.TypeOf(primitive.Binary{}) var tUndefined = reflect.TypeOf(primitive.Undefined{}) diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/uint_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/uint_codec.go index 0b21ce999c..8525472769 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/uint_codec.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/uint_codec.go @@ -17,18 +17,43 @@ import ( ) // UIntCodec is the Codec used for uint values. +// +// Deprecated: UIntCodec will not be directly configurable in Go Driver 2.0. To +// configure the uint encode and decode behavior, use the configuration methods +// on a [go.mongodb.org/mongo-driver/bson.Encoder] or +// [go.mongodb.org/mongo-driver/bson.Decoder]. To configure the uint encode and +// decode behavior for a mongo.Client, use +// [go.mongodb.org/mongo-driver/mongo/options.ClientOptions.SetBSONOptions]. +// +// For example, to configure a mongo.Client to marshal Go uint values as the +// minimum BSON int size that can represent the value, use: +// +// opt := options.Client().SetBSONOptions(&options.BSONOptions{ +// IntMinSize: true, +// }) +// +// See the deprecation notice for each field in UIntCodec for the corresponding +// settings. type UIntCodec struct { + // EncodeToMinSize causes EncodeValue to marshal Go uint values (excluding uint64) as the + // minimum BSON int size (either 32-bit or 64-bit) that can represent the integer value. + // + // Deprecated: Use bson.Encoder.IntMinSize or options.BSONOptions.IntMinSize instead. EncodeToMinSize bool } var ( defaultUIntCodec = NewUIntCodec() - _ ValueCodec = defaultUIntCodec + // Assert that defaultUIntCodec satisfies the typeDecoder interface, which allows it to be used + // by collection type decoders (e.g. map, slice, etc) to set individual values in a collection. _ typeDecoder = defaultUIntCodec ) // NewUIntCodec returns a UIntCodec with options opts. +// +// Deprecated: NewUIntCodec will not be available in Go Driver 2.0. See +// [UIntCodec] for more details. func NewUIntCodec(opts ...*bsonoptions.UIntCodecOptions) *UIntCodec { uintOpt := bsonoptions.MergeUIntCodecOptions(opts...) diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/byte_slice_codec_options.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/byte_slice_codec_options.go index b1256a4dca..996bd17127 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/byte_slice_codec_options.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/byte_slice_codec_options.go @@ -7,22 +7,33 @@ package bsonoptions // ByteSliceCodecOptions represents all possible options for byte slice encoding and decoding. +// +// Deprecated: Use the bson.Encoder and bson.Decoder configuration methods to set the desired BSON marshal +// and unmarshal behavior instead. type ByteSliceCodecOptions struct { EncodeNilAsEmpty *bool // Specifies if a nil byte slice should encode as an empty binary instead of null. Defaults to false. } // ByteSliceCodec creates a new *ByteSliceCodecOptions +// +// Deprecated: Use the bson.Encoder and bson.Decoder configuration methods to set the desired BSON marshal +// and unmarshal behavior instead. func ByteSliceCodec() *ByteSliceCodecOptions { return &ByteSliceCodecOptions{} } // SetEncodeNilAsEmpty specifies if a nil byte slice should encode as an empty binary instead of null. Defaults to false. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.Encoder.NilByteSliceAsEmpty] instead. func (bs *ByteSliceCodecOptions) SetEncodeNilAsEmpty(b bool) *ByteSliceCodecOptions { bs.EncodeNilAsEmpty = &b return bs } // MergeByteSliceCodecOptions combines the given *ByteSliceCodecOptions into a single *ByteSliceCodecOptions in a last one wins fashion. +// +// Deprecated: Merging options structs will not be supported in Go Driver 2.0. Users should create a +// single options struct instead. func MergeByteSliceCodecOptions(opts ...*ByteSliceCodecOptions) *ByteSliceCodecOptions { bs := ByteSliceCodec() for _, opt := range opts { diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/empty_interface_codec_options.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/empty_interface_codec_options.go index 6caaa000e6..f522c7e03f 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/empty_interface_codec_options.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/empty_interface_codec_options.go @@ -7,22 +7,33 @@ package bsonoptions // EmptyInterfaceCodecOptions represents all possible options for interface{} encoding and decoding. +// +// Deprecated: Use the bson.Encoder and bson.Decoder configuration methods to set the desired BSON marshal +// and unmarshal behavior instead. type EmptyInterfaceCodecOptions struct { DecodeBinaryAsSlice *bool // Specifies if Old and Generic type binarys should default to []slice instead of primitive.Binary. Defaults to false. } // EmptyInterfaceCodec creates a new *EmptyInterfaceCodecOptions +// +// Deprecated: Use the bson.Encoder and bson.Decoder configuration methods to set the desired BSON marshal +// and unmarshal behavior instead. func EmptyInterfaceCodec() *EmptyInterfaceCodecOptions { return &EmptyInterfaceCodecOptions{} } // SetDecodeBinaryAsSlice specifies if Old and Generic type binarys should default to []slice instead of primitive.Binary. Defaults to false. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.Decoder.BinaryAsSlice] instead. func (e *EmptyInterfaceCodecOptions) SetDecodeBinaryAsSlice(b bool) *EmptyInterfaceCodecOptions { e.DecodeBinaryAsSlice = &b return e } // MergeEmptyInterfaceCodecOptions combines the given *EmptyInterfaceCodecOptions into a single *EmptyInterfaceCodecOptions in a last one wins fashion. +// +// Deprecated: Merging options structs will not be supported in Go Driver 2.0. Users should create a +// single options struct instead. func MergeEmptyInterfaceCodecOptions(opts ...*EmptyInterfaceCodecOptions) *EmptyInterfaceCodecOptions { e := EmptyInterfaceCodec() for _, opt := range opts { diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/map_codec_options.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/map_codec_options.go index 7a6a880b88..a7a7c1d980 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/map_codec_options.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/map_codec_options.go @@ -7,6 +7,9 @@ package bsonoptions // MapCodecOptions represents all possible options for map encoding and decoding. +// +// Deprecated: Use the bson.Encoder and bson.Decoder configuration methods to set the desired BSON marshal +// and unmarshal behavior instead. type MapCodecOptions struct { DecodeZerosMap *bool // Specifies if the map should be zeroed before decoding into it. Defaults to false. EncodeNilAsEmpty *bool // Specifies if a nil map should encode as an empty document instead of null. Defaults to false. @@ -19,17 +22,24 @@ type MapCodecOptions struct { } // MapCodec creates a new *MapCodecOptions +// +// Deprecated: Use the bson.Encoder and bson.Decoder configuration methods to set the desired BSON marshal +// and unmarshal behavior instead. func MapCodec() *MapCodecOptions { return &MapCodecOptions{} } // SetDecodeZerosMap specifies if the map should be zeroed before decoding into it. Defaults to false. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.Decoder.ZeroMaps] instead. func (t *MapCodecOptions) SetDecodeZerosMap(b bool) *MapCodecOptions { t.DecodeZerosMap = &b return t } // SetEncodeNilAsEmpty specifies if a nil map should encode as an empty document instead of null. Defaults to false. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.Encoder.NilMapAsEmpty] instead. func (t *MapCodecOptions) SetEncodeNilAsEmpty(b bool) *MapCodecOptions { t.EncodeNilAsEmpty = &b return t @@ -40,12 +50,17 @@ func (t *MapCodecOptions) SetEncodeNilAsEmpty(b bool) *MapCodecOptions { // type must either be a string, an integer type, or implement bsoncodec.KeyUnmarshaler. If true, keys are encoded with // fmt.Sprint() and the encoding key type must be a string, an integer type, or a float. If true, the use of Stringer // will override TextMarshaler/TextUnmarshaler. Defaults to false. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.Encoder.StringifyMapKeysWithFmt] instead. func (t *MapCodecOptions) SetEncodeKeysWithStringer(b bool) *MapCodecOptions { t.EncodeKeysWithStringer = &b return t } // MergeMapCodecOptions combines the given *MapCodecOptions into a single *MapCodecOptions in a last one wins fashion. +// +// Deprecated: Merging options structs will not be supported in Go Driver 2.0. Users should create a +// single options struct instead. func MergeMapCodecOptions(opts ...*MapCodecOptions) *MapCodecOptions { s := MapCodec() for _, opt := range opts { diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/slice_codec_options.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/slice_codec_options.go index ef965e4b41..3c1e4f35ba 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/slice_codec_options.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/slice_codec_options.go @@ -7,22 +7,33 @@ package bsonoptions // SliceCodecOptions represents all possible options for slice encoding and decoding. +// +// Deprecated: Use the bson.Encoder and bson.Decoder configuration methods to set the desired BSON marshal +// and unmarshal behavior instead. type SliceCodecOptions struct { EncodeNilAsEmpty *bool // Specifies if a nil slice should encode as an empty array instead of null. Defaults to false. } // SliceCodec creates a new *SliceCodecOptions +// +// Deprecated: Use the bson.Encoder and bson.Decoder configuration methods to set the desired BSON marshal +// and unmarshal behavior instead. func SliceCodec() *SliceCodecOptions { return &SliceCodecOptions{} } // SetEncodeNilAsEmpty specifies if a nil slice should encode as an empty array instead of null. Defaults to false. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.Encoder.NilSliceAsEmpty] instead. func (s *SliceCodecOptions) SetEncodeNilAsEmpty(b bool) *SliceCodecOptions { s.EncodeNilAsEmpty = &b return s } // MergeSliceCodecOptions combines the given *SliceCodecOptions into a single *SliceCodecOptions in a last one wins fashion. +// +// Deprecated: Merging options structs will not be supported in Go Driver 2.0. Users should create a +// single options struct instead. func MergeSliceCodecOptions(opts ...*SliceCodecOptions) *SliceCodecOptions { s := SliceCodec() for _, opt := range opts { diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/string_codec_options.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/string_codec_options.go index 65964f4207..f8b76f996e 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/string_codec_options.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/string_codec_options.go @@ -9,23 +9,34 @@ package bsonoptions var defaultDecodeOIDAsHex = true // StringCodecOptions represents all possible options for string encoding and decoding. +// +// Deprecated: Use the bson.Encoder and bson.Decoder configuration methods to set the desired BSON marshal +// and unmarshal behavior instead. type StringCodecOptions struct { DecodeObjectIDAsHex *bool // Specifies if we should decode ObjectID as the hex value. Defaults to true. } // StringCodec creates a new *StringCodecOptions +// +// Deprecated: Use the bson.Encoder and bson.Decoder configuration methods to set the desired BSON marshal +// and unmarshal behavior instead. func StringCodec() *StringCodecOptions { return &StringCodecOptions{} } // SetDecodeObjectIDAsHex specifies if object IDs should be decoded as their hex representation. If false, a string made // from the raw object ID bytes will be used. Defaults to true. +// +// Deprecated: Decoding object IDs as raw bytes will not be supported in Go Driver 2.0. func (t *StringCodecOptions) SetDecodeObjectIDAsHex(b bool) *StringCodecOptions { t.DecodeObjectIDAsHex = &b return t } // MergeStringCodecOptions combines the given *StringCodecOptions into a single *StringCodecOptions in a last one wins fashion. +// +// Deprecated: Merging options structs will not be supported in Go Driver 2.0. Users should create a +// single options struct instead. func MergeStringCodecOptions(opts ...*StringCodecOptions) *StringCodecOptions { s := &StringCodecOptions{&defaultDecodeOIDAsHex} for _, opt := range opts { diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/struct_codec_options.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/struct_codec_options.go index 78d1dd8668..1cbfa32e8b 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/struct_codec_options.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/struct_codec_options.go @@ -9,6 +9,9 @@ package bsonoptions var defaultOverwriteDuplicatedInlinedFields = true // StructCodecOptions represents all possible options for struct encoding and decoding. +// +// Deprecated: Use the bson.Encoder and bson.Decoder configuration methods to set the desired BSON marshal +// and unmarshal behavior instead. type StructCodecOptions struct { DecodeZeroStruct *bool // Specifies if structs should be zeroed before decoding into them. Defaults to false. DecodeDeepZeroInline *bool // Specifies if structs should be recursively zeroed when a inline value is decoded. Defaults to false. @@ -18,17 +21,24 @@ type StructCodecOptions struct { } // StructCodec creates a new *StructCodecOptions +// +// Deprecated: Use the bson.Encoder and bson.Decoder configuration methods to set the desired BSON marshal +// and unmarshal behavior instead. func StructCodec() *StructCodecOptions { return &StructCodecOptions{} } // SetDecodeZeroStruct specifies if structs should be zeroed before decoding into them. Defaults to false. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.Decoder.ZeroStructs] instead. func (t *StructCodecOptions) SetDecodeZeroStruct(b bool) *StructCodecOptions { t.DecodeZeroStruct = &b return t } // SetDecodeDeepZeroInline specifies if structs should be zeroed before decoding into them. Defaults to false. +// +// Deprecated: DecodeDeepZeroInline will not be supported in Go Driver 2.0. func (t *StructCodecOptions) SetDecodeDeepZeroInline(b bool) *StructCodecOptions { t.DecodeDeepZeroInline = &b return t @@ -36,6 +46,8 @@ func (t *StructCodecOptions) SetDecodeDeepZeroInline(b bool) *StructCodecOptions // SetEncodeOmitDefaultStruct specifies if default structs should be considered empty by omitempty. A default struct has all // its values set to their default value. Defaults to false. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.Encoder.OmitZeroStruct] instead. func (t *StructCodecOptions) SetEncodeOmitDefaultStruct(b bool) *StructCodecOptions { t.EncodeOmitDefaultStruct = &b return t @@ -45,18 +57,26 @@ func (t *StructCodecOptions) SetEncodeOmitDefaultStruct(b bool) *StructCodecOpti // same bson key. When true and decoding, values will be written to the outermost struct with a matching key, and when // encoding, keys will have the value of the top-most matching field. When false, decoding and encoding will error if // there are duplicate keys after the struct is inlined. Defaults to true. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.Encoder.ErrorOnInlineDuplicates] instead. func (t *StructCodecOptions) SetOverwriteDuplicatedInlinedFields(b bool) *StructCodecOptions { t.OverwriteDuplicatedInlinedFields = &b return t } // SetAllowUnexportedFields specifies if unexported fields should be marshaled/unmarshaled. Defaults to false. +// +// Deprecated: AllowUnexportedFields does not work on recent versions of Go and will not be +// supported in Go Driver 2.0. func (t *StructCodecOptions) SetAllowUnexportedFields(b bool) *StructCodecOptions { t.AllowUnexportedFields = &b return t } // MergeStructCodecOptions combines the given *StructCodecOptions into a single *StructCodecOptions in a last one wins fashion. +// +// Deprecated: Merging options structs will not be supported in Go Driver 2.0. Users should create a +// single options struct instead. func MergeStructCodecOptions(opts ...*StructCodecOptions) *StructCodecOptions { s := &StructCodecOptions{ OverwriteDuplicatedInlinedFields: &defaultOverwriteDuplicatedInlinedFields, diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/time_codec_options.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/time_codec_options.go index 13496d1217..3f38433d22 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/time_codec_options.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/time_codec_options.go @@ -7,22 +7,33 @@ package bsonoptions // TimeCodecOptions represents all possible options for time.Time encoding and decoding. +// +// Deprecated: Use the bson.Encoder and bson.Decoder configuration methods to set the desired BSON marshal +// and unmarshal behavior instead. type TimeCodecOptions struct { UseLocalTimeZone *bool // Specifies if we should decode into the local time zone. Defaults to false. } // TimeCodec creates a new *TimeCodecOptions +// +// Deprecated: Use the bson.Encoder and bson.Decoder configuration methods to set the desired BSON marshal +// and unmarshal behavior instead. func TimeCodec() *TimeCodecOptions { return &TimeCodecOptions{} } // SetUseLocalTimeZone specifies if we should decode into the local time zone. Defaults to false. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.Decoder.UseLocalTimeZone] instead. func (t *TimeCodecOptions) SetUseLocalTimeZone(b bool) *TimeCodecOptions { t.UseLocalTimeZone = &b return t } // MergeTimeCodecOptions combines the given *TimeCodecOptions into a single *TimeCodecOptions in a last one wins fashion. +// +// Deprecated: Merging options structs will not be supported in Go Driver 2.0. Users should create a +// single options struct instead. func MergeTimeCodecOptions(opts ...*TimeCodecOptions) *TimeCodecOptions { t := TimeCodec() for _, opt := range opts { diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/uint_codec_options.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/uint_codec_options.go index e08b7f192e..5091e4d963 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/uint_codec_options.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/uint_codec_options.go @@ -7,22 +7,33 @@ package bsonoptions // UIntCodecOptions represents all possible options for uint encoding and decoding. +// +// Deprecated: Use the bson.Encoder and bson.Decoder configuration methods to set the desired BSON marshal +// and unmarshal behavior instead. type UIntCodecOptions struct { EncodeToMinSize *bool // Specifies if all uints except uint64 should be decoded to minimum size bsontype. Defaults to false. } // UIntCodec creates a new *UIntCodecOptions +// +// Deprecated: Use the bson.Encoder and bson.Decoder configuration methods to set the desired BSON marshal +// and unmarshal behavior instead. func UIntCodec() *UIntCodecOptions { return &UIntCodecOptions{} } // SetEncodeToMinSize specifies if all uints except uint64 should be decoded to minimum size bsontype. Defaults to false. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.Encoder.IntMinSize] instead. func (u *UIntCodecOptions) SetEncodeToMinSize(b bool) *UIntCodecOptions { u.EncodeToMinSize = &b return u } // MergeUIntCodecOptions combines the given *UIntCodecOptions into a single *UIntCodecOptions in a last one wins fashion. +// +// Deprecated: Merging options structs will not be supported in Go Driver 2.0. Users should create a +// single options struct instead. func MergeUIntCodecOptions(opts ...*UIntCodecOptions) *UIntCodecOptions { u := UIntCodec() for _, opt := range opts { diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/copier.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/copier.go index 5cdf6460bc..1e25570b85 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/copier.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/copier.go @@ -7,6 +7,7 @@ package bsonrw import ( + "errors" "fmt" "io" @@ -17,20 +18,32 @@ import ( // Copier is a type that allows copying between ValueReaders, ValueWriters, and // []byte values. +// +// Deprecated: Copying BSON documents using the ValueWriter and ValueReader interfaces will not be +// supported in Go Driver 2.0. type Copier struct{} // NewCopier creates a new copier with the given registry. If a nil registry is provided // a default registry is used. +// +// Deprecated: Copying BSON documents using the ValueWriter and ValueReader interfaces will not be +// supported in Go Driver 2.0. func NewCopier() Copier { return Copier{} } // CopyDocument handles copying a document from src to dst. +// +// Deprecated: Copying BSON documents using the ValueWriter and ValueReader interfaces will not be +// supported in Go Driver 2.0. func CopyDocument(dst ValueWriter, src ValueReader) error { return Copier{}.CopyDocument(dst, src) } // CopyDocument handles copying one document from the src to the dst. +// +// Deprecated: Copying BSON documents using the ValueWriter and ValueReader interfaces will not be +// supported in Go Driver 2.0. func (c Copier) CopyDocument(dst ValueWriter, src ValueReader) error { dr, err := src.ReadDocument() if err != nil { @@ -47,6 +60,9 @@ func (c Copier) CopyDocument(dst ValueWriter, src ValueReader) error { // CopyArrayFromBytes copies the values from a BSON array represented as a // []byte to a ValueWriter. +// +// Deprecated: Copying BSON arrays using the ValueWriter and ValueReader interfaces will not be +// supported in Go Driver 2.0. func (c Copier) CopyArrayFromBytes(dst ValueWriter, src []byte) error { aw, err := dst.WriteArray() if err != nil { @@ -63,6 +79,9 @@ func (c Copier) CopyArrayFromBytes(dst ValueWriter, src []byte) error { // CopyDocumentFromBytes copies the values from a BSON document represented as a // []byte to a ValueWriter. +// +// Deprecated: Copying BSON documents using the ValueWriter and ValueReader interfaces will not be +// supported in Go Driver 2.0. func (c Copier) CopyDocumentFromBytes(dst ValueWriter, src []byte) error { dw, err := dst.WriteDocument() if err != nil { @@ -81,6 +100,9 @@ type writeElementFn func(key string) (ValueWriter, error) // CopyBytesToArrayWriter copies the values from a BSON Array represented as a []byte to an // ArrayWriter. +// +// Deprecated: Copying BSON arrays using the ArrayWriter interface will not be supported in Go +// Driver 2.0. func (c Copier) CopyBytesToArrayWriter(dst ArrayWriter, src []byte) error { wef := func(_ string) (ValueWriter, error) { return dst.WriteArrayElement() @@ -91,6 +113,9 @@ func (c Copier) CopyBytesToArrayWriter(dst ArrayWriter, src []byte) error { // CopyBytesToDocumentWriter copies the values from a BSON document represented as a []byte to a // DocumentWriter. +// +// Deprecated: Copying BSON documents using the ValueWriter and ValueReader interfaces will not be +// supported in Go Driver 2.0. func (c Copier) CopyBytesToDocumentWriter(dst DocumentWriter, src []byte) error { wef := func(key string) (ValueWriter, error) { return dst.WriteDocumentElement(key) @@ -100,7 +125,7 @@ func (c Copier) CopyBytesToDocumentWriter(dst DocumentWriter, src []byte) error } func (c Copier) copyBytesToValueWriter(src []byte, wef writeElementFn) error { - // TODO(skriptble): Create errors types here. Anything thats a tag should be a property. + // TODO(skriptble): Create errors types here. Anything that is a tag should be a property. length, rem, ok := bsoncore.ReadLength(src) if !ok { return fmt.Errorf("couldn't read length from src, not enough bytes. length=%d", len(src)) @@ -150,12 +175,18 @@ func (c Copier) copyBytesToValueWriter(src []byte, wef writeElementFn) error { // CopyDocumentToBytes copies an entire document from the ValueReader and // returns it as bytes. +// +// Deprecated: Copying BSON documents using the ValueWriter and ValueReader interfaces will not be +// supported in Go Driver 2.0. func (c Copier) CopyDocumentToBytes(src ValueReader) ([]byte, error) { return c.AppendDocumentBytes(nil, src) } // AppendDocumentBytes functions the same as CopyDocumentToBytes, but will // append the result to dst. +// +// Deprecated: Copying BSON documents using the ValueWriter and ValueReader interfaces will not be +// supported in Go Driver 2.0. func (c Copier) AppendDocumentBytes(dst []byte, src ValueReader) ([]byte, error) { if br, ok := src.(BytesReader); ok { _, dst, err := br.ReadValueBytes(dst) @@ -163,7 +194,7 @@ func (c Copier) AppendDocumentBytes(dst []byte, src ValueReader) ([]byte, error) } vw := vwPool.Get().(*valueWriter) - defer vwPool.Put(vw) + defer putValueWriter(vw) vw.reset(dst) @@ -173,6 +204,9 @@ func (c Copier) AppendDocumentBytes(dst []byte, src ValueReader) ([]byte, error) } // AppendArrayBytes copies an array from the ValueReader to dst. +// +// Deprecated: Copying BSON arrays using the ValueWriter and ValueReader interfaces will not be +// supported in Go Driver 2.0. func (c Copier) AppendArrayBytes(dst []byte, src ValueReader) ([]byte, error) { if br, ok := src.(BytesReader); ok { _, dst, err := br.ReadValueBytes(dst) @@ -180,7 +214,7 @@ func (c Copier) AppendArrayBytes(dst []byte, src ValueReader) ([]byte, error) { } vw := vwPool.Get().(*valueWriter) - defer vwPool.Put(vw) + defer putValueWriter(vw) vw.reset(dst) @@ -190,6 +224,8 @@ func (c Copier) AppendArrayBytes(dst []byte, src ValueReader) ([]byte, error) { } // CopyValueFromBytes will write the value represtend by t and src to dst. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.UnmarshalValue] instead. func (c Copier) CopyValueFromBytes(dst ValueWriter, t bsontype.Type, src []byte) error { if wvb, ok := dst.(BytesWriter); ok { return wvb.WriteValueBytes(t, src) @@ -206,19 +242,24 @@ func (c Copier) CopyValueFromBytes(dst ValueWriter, t bsontype.Type, src []byte) // CopyValueToBytes copies a value from src and returns it as a bsontype.Type and a // []byte. +// +// Deprecated: Use [go.mongodb.org/mongo-driver/bson.MarshalValue] instead. func (c Copier) CopyValueToBytes(src ValueReader) (bsontype.Type, []byte, error) { return c.AppendValueBytes(nil, src) } // AppendValueBytes functions the same as CopyValueToBytes, but will append the // result to dst. +// +// Deprecated: Appending individual BSON elements to an existing slice will not be supported in Go +// Driver 2.0. func (c Copier) AppendValueBytes(dst []byte, src ValueReader) (bsontype.Type, []byte, error) { if br, ok := src.(BytesReader); ok { return br.ReadValueBytes(dst) } vw := vwPool.Get().(*valueWriter) - defer vwPool.Put(vw) + defer putValueWriter(vw) start := len(dst) @@ -234,6 +275,9 @@ func (c Copier) AppendValueBytes(dst []byte, src ValueReader) (bsontype.Type, [] } // CopyValue will copy a single value from src to dst. +// +// Deprecated: Copying BSON values using the ValueWriter and ValueReader interfaces will not be +// supported in Go Driver 2.0. func (c Copier) CopyValue(dst ValueWriter, src ValueReader) error { var err error switch src.Type() { @@ -399,7 +443,7 @@ func (c Copier) copyArray(dst ValueWriter, src ValueReader) error { for { vr, err := ar.ReadValue() - if err == ErrEOA { + if errors.Is(err, ErrEOA) { break } if err != nil { @@ -423,7 +467,7 @@ func (c Copier) copyArray(dst ValueWriter, src ValueReader) error { func (c Copier) copyDocumentCore(dw DocumentWriter, dr DocumentReader) error { for { key, vr, err := dr.ReadElement() - if err == ErrEOD { + if errors.Is(err, ErrEOD) { break } if err != nil { diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_parser.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_parser.go index 54c76bf746..bb52a0ec3d 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_parser.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_parser.go @@ -313,7 +313,7 @@ func (ejp *extJSONParser) readValue(t bsontype.Type) (*extJSONValue, error) { // convert hex to bytes bytes, err := hex.DecodeString(uuidNoHyphens) if err != nil { - return nil, fmt.Errorf("$uuid value does not follow RFC 4122 format regarding hex bytes: %v", err) + return nil, fmt.Errorf("$uuid value does not follow RFC 4122 format regarding hex bytes: %w", err) } ejp.advanceState() diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_reader.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_reader.go index 35832d73aa..59ddfc4485 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_reader.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_reader.go @@ -7,6 +7,7 @@ package bsonrw import ( + "errors" "fmt" "io" "sync" @@ -16,11 +17,15 @@ import ( ) // ExtJSONValueReaderPool is a pool for ValueReaders that read ExtJSON. +// +// Deprecated: ExtJSONValueReaderPool will not be supported in Go Driver 2.0. type ExtJSONValueReaderPool struct { pool sync.Pool } // NewExtJSONValueReaderPool instantiates a new ExtJSONValueReaderPool. +// +// Deprecated: ExtJSONValueReaderPool will not be supported in Go Driver 2.0. func NewExtJSONValueReaderPool() *ExtJSONValueReaderPool { return &ExtJSONValueReaderPool{ pool: sync.Pool{ @@ -32,6 +37,8 @@ func NewExtJSONValueReaderPool() *ExtJSONValueReaderPool { } // Get retrieves a ValueReader from the pool and uses src as the underlying ExtJSON. +// +// Deprecated: ExtJSONValueReaderPool will not be supported in Go Driver 2.0. func (bvrp *ExtJSONValueReaderPool) Get(r io.Reader, canonical bool) (ValueReader, error) { vr := bvrp.pool.Get().(*extJSONValueReader) return vr.reset(r, canonical) @@ -39,6 +46,8 @@ func (bvrp *ExtJSONValueReaderPool) Get(r io.Reader, canonical bool) (ValueReade // Put inserts a ValueReader into the pool. If the ValueReader is not a ExtJSON ValueReader nothing // is inserted into the pool and ok will be false. +// +// Deprecated: ExtJSONValueReaderPool will not be supported in Go Driver 2.0. func (bvrp *ExtJSONValueReaderPool) Put(vr ValueReader) (ok bool) { bvr, ok := vr.(*extJSONValueReader) if !ok { @@ -605,7 +614,7 @@ func (ejvr *extJSONValueReader) ReadElement() (string, ValueReader, error) { name, t, err := ejvr.p.readKey() if err != nil { - if err == ErrEOD { + if errors.Is(err, ErrEOD) { if ejvr.stack[ejvr.frame].mode == mCodeWithScope { _, err := ejvr.p.peekType() if err != nil { @@ -632,7 +641,7 @@ func (ejvr *extJSONValueReader) ReadValue() (ValueReader, error) { t, err := ejvr.p.peekType() if err != nil { - if err == ErrEOA { + if errors.Is(err, ErrEOA) { ejvr.pop() } diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_writer.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_writer.go index 99ed524b77..bb9303167c 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_writer.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_writer.go @@ -23,11 +23,15 @@ import ( ) // ExtJSONValueWriterPool is a pool for ExtJSON ValueWriters. +// +// Deprecated: ExtJSONValueWriterPool will not be supported in Go Driver 2.0. type ExtJSONValueWriterPool struct { pool sync.Pool } // NewExtJSONValueWriterPool creates a new pool for ValueWriter instances that write to ExtJSON. +// +// Deprecated: ExtJSONValueWriterPool will not be supported in Go Driver 2.0. func NewExtJSONValueWriterPool() *ExtJSONValueWriterPool { return &ExtJSONValueWriterPool{ pool: sync.Pool{ @@ -39,6 +43,8 @@ func NewExtJSONValueWriterPool() *ExtJSONValueWriterPool { } // Get retrieves a ExtJSON ValueWriter from the pool and resets it to use w as the destination. +// +// Deprecated: ExtJSONValueWriterPool will not be supported in Go Driver 2.0. func (bvwp *ExtJSONValueWriterPool) Get(w io.Writer, canonical, escapeHTML bool) ValueWriter { vw := bvwp.pool.Get().(*extJSONValueWriter) if writer, ok := w.(*SliceWriter); ok { @@ -53,6 +59,8 @@ func (bvwp *ExtJSONValueWriterPool) Get(w io.Writer, canonical, escapeHTML bool) // Put inserts a ValueWriter into the pool. If the ValueWriter is not a ExtJSON ValueWriter, nothing // happens and ok will be false. +// +// Deprecated: ExtJSONValueWriterPool will not be supported in Go Driver 2.0. func (bvwp *ExtJSONValueWriterPool) Put(vw ValueWriter) (ok bool) { bvw, ok := vw.(*extJSONValueWriter) if !ok { @@ -80,6 +88,7 @@ type extJSONValueWriter struct { frame int64 canonical bool escapeHTML bool + newlines bool } // NewExtJSONValueWriter creates a ValueWriter that writes Extended JSON to w. @@ -88,10 +97,13 @@ func NewExtJSONValueWriter(w io.Writer, canonical, escapeHTML bool) (ValueWriter return nil, errNilWriter } - return newExtJSONWriter(w, canonical, escapeHTML), nil + // Enable newlines for all Extended JSON value writers created by NewExtJSONValueWriter. We + // expect these value writers to be used with an Encoder, which should add newlines after + // encoded Extended JSON documents. + return newExtJSONWriter(w, canonical, escapeHTML, true), nil } -func newExtJSONWriter(w io.Writer, canonical, escapeHTML bool) *extJSONValueWriter { +func newExtJSONWriter(w io.Writer, canonical, escapeHTML, newlines bool) *extJSONValueWriter { stack := make([]ejvwState, 1, 5) stack[0] = ejvwState{mode: mTopLevel} @@ -101,6 +113,7 @@ func newExtJSONWriter(w io.Writer, canonical, escapeHTML bool) *extJSONValueWrit stack: stack, canonical: canonical, escapeHTML: escapeHTML, + newlines: newlines, } } @@ -564,6 +577,12 @@ func (ejvw *extJSONValueWriter) WriteDocumentEnd() error { case mDocument: ejvw.buf = append(ejvw.buf, ',') case mTopLevel: + // If the value writer has newlines enabled, end top-level documents with a newline so that + // multiple documents encoded to the same writer are separated by newlines. That matches the + // Go json.Encoder behavior and also works with bsonrw.NewExtJSONValueReader. + if ejvw.newlines { + ejvw.buf = append(ejvw.buf, '\n') + } if ejvw.w != nil { if _, err := ejvw.w.Write(ejvw.buf); err != nil { return err diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/json_scanner.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/json_scanner.go index cd4843a3a4..43f3e4f383 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/json_scanner.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/json_scanner.go @@ -58,7 +58,7 @@ func (js *jsonScanner) nextToken() (*jsonToken, error) { c, err = js.readNextByte() } - if err == io.EOF { + if errors.Is(err, io.EOF) { return &jsonToken{t: jttEOF}, nil } else if err != nil { return nil, err @@ -198,7 +198,7 @@ func (js *jsonScanner) scanString() (*jsonToken, error) { for { c, err = js.readNextByte() if err != nil { - if err == io.EOF { + if errors.Is(err, io.EOF) { return nil, errors.New("end of input in JSON string") } return nil, err @@ -209,7 +209,7 @@ func (js *jsonScanner) scanString() (*jsonToken, error) { case '\\': c, err = js.readNextByte() if err != nil { - if err == io.EOF { + if errors.Is(err, io.EOF) { return nil, errors.New("end of input in JSON string") } return nil, err @@ -248,7 +248,7 @@ func (js *jsonScanner) scanString() (*jsonToken, error) { if utf16.IsSurrogate(rn) { c, err = js.readNextByte() if err != nil { - if err == io.EOF { + if errors.Is(err, io.EOF) { return nil, errors.New("end of input in JSON string") } return nil, err @@ -264,7 +264,7 @@ func (js *jsonScanner) scanString() (*jsonToken, error) { c, err = js.readNextByte() if err != nil { - if err == io.EOF { + if errors.Is(err, io.EOF) { return nil, errors.New("end of input in JSON string") } return nil, err @@ -325,17 +325,17 @@ func (js *jsonScanner) scanLiteral(first byte) (*jsonToken, error) { c5, err := js.readNextByte() - if bytes.Equal([]byte("true"), lit) && (isValueTerminator(c5) || err == io.EOF) { + if bytes.Equal([]byte("true"), lit) && (isValueTerminator(c5) || errors.Is(err, io.EOF)) { js.pos = int(math.Max(0, float64(js.pos-1))) return &jsonToken{t: jttBool, v: true, p: p}, nil - } else if bytes.Equal([]byte("null"), lit) && (isValueTerminator(c5) || err == io.EOF) { + } else if bytes.Equal([]byte("null"), lit) && (isValueTerminator(c5) || errors.Is(err, io.EOF)) { js.pos = int(math.Max(0, float64(js.pos-1))) return &jsonToken{t: jttNull, v: nil, p: p}, nil } else if bytes.Equal([]byte("fals"), lit) { if c5 == 'e' { c5, err = js.readNextByte() - if isValueTerminator(c5) || err == io.EOF { + if isValueTerminator(c5) || errors.Is(err, io.EOF) { js.pos = int(math.Max(0, float64(js.pos-1))) return &jsonToken{t: jttBool, v: false, p: p}, nil } @@ -384,7 +384,7 @@ func (js *jsonScanner) scanNumber(first byte) (*jsonToken, error) { for { c, err = js.readNextByte() - if err != nil && err != io.EOF { + if err != nil && !errors.Is(err, io.EOF) { return nil, err } @@ -413,7 +413,7 @@ func (js *jsonScanner) scanNumber(first byte) (*jsonToken, error) { case '}', ']', ',': s = nssDone default: - if isWhiteSpace(c) || err == io.EOF { + if isWhiteSpace(c) || errors.Is(err, io.EOF) { s = nssDone } else { s = nssInvalid @@ -430,7 +430,7 @@ func (js *jsonScanner) scanNumber(first byte) (*jsonToken, error) { case '}', ']', ',': s = nssDone default: - if isWhiteSpace(c) || err == io.EOF { + if isWhiteSpace(c) || errors.Is(err, io.EOF) { s = nssDone } else if isDigit(c) { s = nssSawIntegerDigits @@ -455,7 +455,7 @@ func (js *jsonScanner) scanNumber(first byte) (*jsonToken, error) { case '}', ']', ',': s = nssDone default: - if isWhiteSpace(c) || err == io.EOF { + if isWhiteSpace(c) || errors.Is(err, io.EOF) { s = nssDone } else if isDigit(c) { s = nssSawFractionDigits @@ -490,7 +490,7 @@ func (js *jsonScanner) scanNumber(first byte) (*jsonToken, error) { case '}', ']', ',': s = nssDone default: - if isWhiteSpace(c) || err == io.EOF { + if isWhiteSpace(c) || errors.Is(err, io.EOF) { s = nssDone } else if isDigit(c) { s = nssSawExponentDigits diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/reader.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/reader.go index 0b8fa28d57..324b10b616 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/reader.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/reader.go @@ -58,6 +58,8 @@ type ValueReader interface { // types that implement ValueReader may also implement this interface. // // The bytes of the value will be appended to dst. +// +// Deprecated: BytesReader will not be supported in Go Driver 2.0. type BytesReader interface { ReadValueBytes(dst []byte) (bsontype.Type, []byte, error) } diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/value_reader.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/value_reader.go index ef5d837c2f..a242bb57cf 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/value_reader.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/value_reader.go @@ -28,11 +28,15 @@ var vrPool = sync.Pool{ } // BSONValueReaderPool is a pool for ValueReaders that read BSON. +// +// Deprecated: BSONValueReaderPool will not be supported in Go Driver 2.0. type BSONValueReaderPool struct { pool sync.Pool } // NewBSONValueReaderPool instantiates a new BSONValueReaderPool. +// +// Deprecated: BSONValueReaderPool will not be supported in Go Driver 2.0. func NewBSONValueReaderPool() *BSONValueReaderPool { return &BSONValueReaderPool{ pool: sync.Pool{ @@ -44,6 +48,8 @@ func NewBSONValueReaderPool() *BSONValueReaderPool { } // Get retrieves a ValueReader from the pool and uses src as the underlying BSON. +// +// Deprecated: BSONValueReaderPool will not be supported in Go Driver 2.0. func (bvrp *BSONValueReaderPool) Get(src []byte) ValueReader { vr := bvrp.pool.Get().(*valueReader) vr.reset(src) @@ -52,6 +58,8 @@ func (bvrp *BSONValueReaderPool) Get(src []byte) ValueReader { // Put inserts a ValueReader into the pool. If the ValueReader is not a BSON ValueReader nothing // is inserted into the pool and ok will be false. +// +// Deprecated: BSONValueReaderPool will not be supported in Go Driver 2.0. func (bvrp *BSONValueReaderPool) Put(vr ValueReader) (ok bool) { bvr, ok := vr.(*valueReader) if !ok { @@ -731,8 +739,7 @@ func (vr *valueReader) ReadValue() (ValueReader, error) { return nil, ErrEOA } - _, err = vr.readCString() - if err != nil { + if err := vr.skipCString(); err != nil { return nil, err } @@ -786,6 +793,15 @@ func (vr *valueReader) readByte() (byte, error) { return vr.d[vr.offset-1], nil } +func (vr *valueReader) skipCString() error { + idx := bytes.IndexByte(vr.d[vr.offset:], 0x00) + if idx < 0 { + return io.EOF + } + vr.offset += int64(idx) + 1 + return nil +} + func (vr *valueReader) readCString() (string, error) { idx := bytes.IndexByte(vr.d[vr.offset:], 0x00) if idx < 0 { diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/value_writer.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/value_writer.go index f95a08afd5..311518a80d 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/value_writer.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/value_writer.go @@ -28,12 +28,23 @@ var vwPool = sync.Pool{ }, } +func putValueWriter(vw *valueWriter) { + if vw != nil { + vw.w = nil // don't leak the writer + vwPool.Put(vw) + } +} + // BSONValueWriterPool is a pool for BSON ValueWriters. +// +// Deprecated: BSONValueWriterPool will not be supported in Go Driver 2.0. type BSONValueWriterPool struct { pool sync.Pool } // NewBSONValueWriterPool creates a new pool for ValueWriter instances that write to BSON. +// +// Deprecated: BSONValueWriterPool will not be supported in Go Driver 2.0. func NewBSONValueWriterPool() *BSONValueWriterPool { return &BSONValueWriterPool{ pool: sync.Pool{ @@ -45,6 +56,8 @@ func NewBSONValueWriterPool() *BSONValueWriterPool { } // Get retrieves a BSON ValueWriter from the pool and resets it to use w as the destination. +// +// Deprecated: BSONValueWriterPool will not be supported in Go Driver 2.0. func (bvwp *BSONValueWriterPool) Get(w io.Writer) ValueWriter { vw := bvwp.pool.Get().(*valueWriter) @@ -56,6 +69,8 @@ func (bvwp *BSONValueWriterPool) Get(w io.Writer) ValueWriter { } // GetAtModeElement retrieves a ValueWriterFlusher from the pool and resets it to use w as the destination. +// +// Deprecated: BSONValueWriterPool will not be supported in Go Driver 2.0. func (bvwp *BSONValueWriterPool) GetAtModeElement(w io.Writer) ValueWriterFlusher { vw := bvwp.Get(w).(*valueWriter) vw.push(mElement) @@ -64,6 +79,8 @@ func (bvwp *BSONValueWriterPool) GetAtModeElement(w io.Writer) ValueWriterFlushe // Put inserts a ValueWriter into the pool. If the ValueWriter is not a BSON ValueWriter, nothing // happens and ok will be false. +// +// Deprecated: BSONValueWriterPool will not be supported in Go Driver 2.0. func (bvwp *BSONValueWriterPool) Put(vw ValueWriter) (ok bool) { bvw, ok := vw.(*valueWriter) if !ok { @@ -139,32 +156,21 @@ type valueWriter struct { } func (vw *valueWriter) advanceFrame() { - if vw.frame+1 >= int64(len(vw.stack)) { // We need to grow the stack - length := len(vw.stack) - if length+1 >= cap(vw.stack) { - // double it - buf := make([]vwState, 2*cap(vw.stack)+1) - copy(buf, vw.stack) - vw.stack = buf - } - vw.stack = vw.stack[:length+1] - } vw.frame++ + if vw.frame >= int64(len(vw.stack)) { + vw.stack = append(vw.stack, vwState{}) + } } func (vw *valueWriter) push(m mode) { vw.advanceFrame() // Clean the stack - vw.stack[vw.frame].mode = m - vw.stack[vw.frame].key = "" - vw.stack[vw.frame].arrkey = 0 - vw.stack[vw.frame].start = 0 + vw.stack[vw.frame] = vwState{mode: m} - vw.stack[vw.frame].mode = m switch m { case mDocument, mArray, mCodeWithScope: - vw.reserveLength() + vw.reserveLength() // WARN: this is not needed } } @@ -203,6 +209,7 @@ func newValueWriter(w io.Writer) *valueWriter { return vw } +// TODO: only used in tests func newValueWriterFromSlice(buf []byte) *valueWriter { vw := new(valueWriter) stack := make([]vwState, 1, 5) @@ -239,17 +246,16 @@ func (vw *valueWriter) invalidTransitionError(destination mode, name string, mod } func (vw *valueWriter) writeElementHeader(t bsontype.Type, destination mode, callerName string, addmodes ...mode) error { - switch vw.stack[vw.frame].mode { + frame := &vw.stack[vw.frame] + switch frame.mode { case mElement: - key := vw.stack[vw.frame].key + key := frame.key if !isValidCString(key) { return errors.New("BSON element key cannot contain null bytes") } - - vw.buf = bsoncore.AppendHeader(vw.buf, t, key) + vw.appendHeader(t, key) case mValue: - // TODO: Do this with a cache of the first 1000 or so array keys. - vw.buf = bsoncore.AppendHeader(vw.buf, t, strconv.Itoa(vw.stack[vw.frame].arrkey)) + vw.appendIntHeader(t, frame.arrkey) default: modes := []mode{mElement, mValue} if addmodes != nil { @@ -591,9 +597,11 @@ func (vw *valueWriter) writeLength() error { if length > maxSize { return errMaxDocumentSizeExceeded{size: int64(len(vw.buf))} } - length = length - int(vw.stack[vw.frame].start) - start := vw.stack[vw.frame].start + frame := &vw.stack[vw.frame] + length = length - int(frame.start) + start := frame.start + _ = vw.buf[start+3] // BCE vw.buf[start+0] = byte(length) vw.buf[start+1] = byte(length >> 8) vw.buf[start+2] = byte(length >> 16) @@ -602,5 +610,31 @@ func (vw *valueWriter) writeLength() error { } func isValidCString(cs string) bool { - return !strings.ContainsRune(cs, '\x00') + // Disallow the zero byte in a cstring because the zero byte is used as the + // terminating character. + // + // It's safe to check bytes instead of runes because all multibyte UTF-8 + // code points start with (binary) 11xxxxxx or 10xxxxxx, so 00000000 (i.e. + // 0) will never be part of a multibyte UTF-8 code point. This logic is the + // same as the "r < utf8.RuneSelf" case in strings.IndexRune but can be + // inlined. + // + // https://cs.opensource.google/go/go/+/refs/tags/go1.21.1:src/strings/strings.go;l=127 + return strings.IndexByte(cs, 0) == -1 +} + +// appendHeader is the same as bsoncore.AppendHeader but does not check if the +// key is a valid C string since the caller has already checked for that. +// +// The caller of this function must check if key is a valid C string. +func (vw *valueWriter) appendHeader(t bsontype.Type, key string) { + vw.buf = bsoncore.AppendType(vw.buf, t) + vw.buf = append(vw.buf, key...) + vw.buf = append(vw.buf, 0x00) +} + +func (vw *valueWriter) appendIntHeader(t bsontype.Type, key int) { + vw.buf = bsoncore.AppendType(vw.buf, t) + vw.buf = strconv.AppendInt(vw.buf, int64(key), 10) + vw.buf = append(vw.buf, 0x00) } diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/writer.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/writer.go index dff65f87f7..628f452932 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/writer.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/writer.go @@ -56,6 +56,8 @@ type ValueWriter interface { } // ValueWriterFlusher is a superset of ValueWriter that exposes functionality to flush to the underlying buffer. +// +// Deprecated: ValueWriterFlusher will not be supported in Go Driver 2.0. type ValueWriterFlusher interface { ValueWriter Flush() error @@ -64,13 +66,20 @@ type ValueWriterFlusher interface { // BytesWriter is the interface used to write BSON bytes to a ValueWriter. // This interface is meant to be a superset of ValueWriter, so that types that // implement ValueWriter may also implement this interface. +// +// Deprecated: BytesWriter will not be supported in Go Driver 2.0. type BytesWriter interface { WriteValueBytes(t bsontype.Type, b []byte) error } // SliceWriter allows a pointer to a slice of bytes to be used as an io.Writer. +// +// Deprecated: SliceWriter will not be supported in Go Driver 2.0. type SliceWriter []byte +// Write writes the bytes to the underlying slice. +// +// Deprecated: SliceWriter will not be supported in Go Driver 2.0. func (sw *SliceWriter) Write(p []byte) (int, error) { written := len(p) *sw = append(*sw, p...) diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsontype/bsontype.go b/vendor/go.mongodb.org/mongo-driver/bson/bsontype/bsontype.go index 7c91ae5186..255d9909e3 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsontype/bsontype.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsontype/bsontype.go @@ -8,7 +8,9 @@ // a stringifier for the Type to enable easier debugging when working with BSON. package bsontype // import "go.mongodb.org/mongo-driver/bson/bsontype" -// These constants uniquely refer to each BSON type. +// BSON element types as described in https://bsonspec.org/spec.html. +// +// Deprecated: Use bson.Type* constants instead. const ( Double Type = 0x01 String Type = 0x02 @@ -31,7 +33,12 @@ const ( Decimal128 Type = 0x13 MinKey Type = 0xFF MaxKey Type = 0x7F +) +// BSON binary element subtypes as described in https://bsonspec.org/spec.html. +// +// Deprecated: Use the bson.TypeBinary* constants instead. +const ( BinaryGeneric byte = 0x00 BinaryFunction byte = 0x01 BinaryBinaryOld byte = 0x02 @@ -40,6 +47,7 @@ const ( BinaryMD5 byte = 0x05 BinaryEncrypted byte = 0x06 BinaryColumn byte = 0x07 + BinarySensitive byte = 0x08 BinaryUserDefined byte = 0x80 ) @@ -95,3 +103,14 @@ func (bt Type) String() string { return "invalid" } } + +// IsValid will return true if the Type is valid. +func (bt Type) IsValid() bool { + switch bt { + case Double, String, EmbeddedDocument, Array, Binary, Undefined, ObjectID, Boolean, DateTime, Null, Regex, + DBPointer, JavaScript, Symbol, CodeWithScope, Int32, Timestamp, Int64, Decimal128, MinKey, MaxKey: + return true + default: + return false + } +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/decoder.go b/vendor/go.mongodb.org/mongo-driver/bson/decoder.go index 6e189fa589..eac74cd399 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/decoder.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/decoder.go @@ -38,6 +38,12 @@ type Decoder struct { // (*Decoder).SetContext. defaultDocumentM bool defaultDocumentD bool + + binaryAsSlice bool + useJSONStructTags bool + useLocalTimeZone bool + zeroMaps bool + zeroStructs bool } // NewDecoder returns a new decoder that uses the DefaultRegistry to read from vr. @@ -53,6 +59,9 @@ func NewDecoder(vr bsonrw.ValueReader) (*Decoder, error) { } // NewDecoderWithContext returns a new decoder that uses DecodeContext dc to read from vr. +// +// Deprecated: Use [NewDecoder] and use the Decoder configuration methods set the desired unmarshal +// behavior instead. func NewDecoderWithContext(dc bsoncodec.DecodeContext, vr bsonrw.ValueReader) (*Decoder, error) { if dc.Registry == nil { dc.Registry = DefaultRegistry @@ -70,8 +79,7 @@ func NewDecoderWithContext(dc bsoncodec.DecodeContext, vr bsonrw.ValueReader) (* // Decode reads the next BSON document from the stream and decodes it into the // value pointed to by val. // -// The documentation for Unmarshal contains details about of BSON into a Go -// value. +// See [Unmarshal] for details about BSON unmarshaling behavior. func (d *Decoder) Decode(val interface{}) error { if unmarshaler, ok := val.(Unmarshaler); ok { // TODO(skriptble): Reuse a []byte here and use the AppendDocumentBytes method. @@ -100,42 +108,101 @@ func (d *Decoder) Decode(val interface{}) error { if err != nil { return err } + if d.defaultDocumentM { d.dc.DefaultDocumentM() } if d.defaultDocumentD { d.dc.DefaultDocumentD() } + if d.binaryAsSlice { + d.dc.BinaryAsSlice() + } + if d.useJSONStructTags { + d.dc.UseJSONStructTags() + } + if d.useLocalTimeZone { + d.dc.UseLocalTimeZone() + } + if d.zeroMaps { + d.dc.ZeroMaps() + } + if d.zeroStructs { + d.dc.ZeroStructs() + } + return decoder.DecodeValue(d.dc, d.vr, rval) } // Reset will reset the state of the decoder, using the same *DecodeContext used in // the original construction but using vr for reading. func (d *Decoder) Reset(vr bsonrw.ValueReader) error { + // TODO:(GODRIVER-2719): Remove error return value. d.vr = vr return nil } // SetRegistry replaces the current registry of the decoder with r. func (d *Decoder) SetRegistry(r *bsoncodec.Registry) error { + // TODO:(GODRIVER-2719): Remove error return value. d.dc.Registry = r return nil } // SetContext replaces the current registry of the decoder with dc. +// +// Deprecated: Use the Decoder configuration methods to set the desired unmarshal behavior instead. func (d *Decoder) SetContext(dc bsoncodec.DecodeContext) error { + // TODO:(GODRIVER-2719): Remove error return value. d.dc = dc return nil } -// DefaultDocumentM will decode empty documents using the primitive.M type. This behavior is restricted to data typed as -// "interface{}" or "map[string]interface{}". +// DefaultDocumentM causes the Decoder to always unmarshal documents into the primitive.M type. This +// behavior is restricted to data typed as "interface{}" or "map[string]interface{}". func (d *Decoder) DefaultDocumentM() { d.defaultDocumentM = true } -// DefaultDocumentD will decode empty documents using the primitive.D type. This behavior is restricted to data typed as -// "interface{}" or "map[string]interface{}". +// DefaultDocumentD causes the Decoder to always unmarshal documents into the primitive.D type. This +// behavior is restricted to data typed as "interface{}" or "map[string]interface{}". func (d *Decoder) DefaultDocumentD() { d.defaultDocumentD = true } + +// AllowTruncatingDoubles causes the Decoder to truncate the fractional part of BSON "double" values +// when attempting to unmarshal them into a Go integer (int, int8, int16, int32, or int64) struct +// field. The truncation logic does not apply to BSON "decimal128" values. +func (d *Decoder) AllowTruncatingDoubles() { + d.dc.Truncate = true +} + +// BinaryAsSlice causes the Decoder to unmarshal BSON binary field values that are the "Generic" or +// "Old" BSON binary subtype as a Go byte slice instead of a primitive.Binary. +func (d *Decoder) BinaryAsSlice() { + d.binaryAsSlice = true +} + +// UseJSONStructTags causes the Decoder to fall back to using the "json" struct tag if a "bson" +// struct tag is not specified. +func (d *Decoder) UseJSONStructTags() { + d.useJSONStructTags = true +} + +// UseLocalTimeZone causes the Decoder to unmarshal time.Time values in the local timezone instead +// of the UTC timezone. +func (d *Decoder) UseLocalTimeZone() { + d.useLocalTimeZone = true +} + +// ZeroMaps causes the Decoder to delete any existing values from Go maps in the destination value +// passed to Decode before unmarshaling BSON documents into them. +func (d *Decoder) ZeroMaps() { + d.zeroMaps = true +} + +// ZeroStructs causes the Decoder to delete any existing values from Go structs in the destination +// value passed to Decode before unmarshaling BSON documents into them. +func (d *Decoder) ZeroStructs() { + d.zeroStructs = true +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/doc.go b/vendor/go.mongodb.org/mongo-driver/bson/doc.go index 0134006d8e..af6098475e 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/doc.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/doc.go @@ -6,8 +6,9 @@ // Package bson is a library for reading, writing, and manipulating BSON. BSON is a binary serialization format used to // store documents and make remote procedure calls in MongoDB. The BSON specification is located at https://bsonspec.org. -// The BSON library handles marshalling and unmarshalling of values through a configurable codec system. For a description -// of the codec system and examples of registering custom codecs, see the bsoncodec package. +// The BSON library handles marshaling and unmarshaling of values through a configurable codec system. For a description +// of the codec system and examples of registering custom codecs, see the bsoncodec package. For additional information +// and usage examples, check out the [Work with BSON] page in the Go Driver docs site. // // # Raw BSON // @@ -37,7 +38,7 @@ // bson.D{{"foo", "bar"}, {"hello", "world"}, {"pi", 3.14159}} // bson.M{"foo": "bar", "hello": "world", "pi": 3.14159} // -// When decoding BSON to a D or M, the following type mappings apply when unmarshalling: +// When decoding BSON to a D or M, the following type mappings apply when unmarshaling: // // 1. BSON int32 unmarshals to an int32. // 2. BSON int64 unmarshals to an int64. @@ -61,81 +62,78 @@ // 20. BSON DBPointer unmarshals to a primitive.DBPointer. // 21. BSON symbol unmarshals to a primitive.Symbol. // -// The above mappings also apply when marshalling a D or M to BSON. Some other useful marshalling mappings are: +// The above mappings also apply when marshaling a D or M to BSON. Some other useful marshaling mappings are: // // 1. time.Time marshals to a BSON datetime. // 2. int8, int16, and int32 marshal to a BSON int32. // 3. int marshals to a BSON int32 if the value is between math.MinInt32 and math.MaxInt32, inclusive, and a BSON int64 // otherwise. -// 4. int64 marshals to BSON int64. +// 4. int64 marshals to BSON int64 (unless [Encoder.IntMinSize] is set). // 5. uint8 and uint16 marshal to a BSON int32. -// 6. uint, uint32, and uint64 marshal to a BSON int32 if the value is between math.MinInt32 and math.MaxInt32, -// inclusive, and BSON int64 otherwise. -// 7. BSON null and undefined values will unmarshal into the zero value of a field (e.g. unmarshalling a BSON null or +// 6. uint, uint32, and uint64 marshal to a BSON int64 (unless [Encoder.IntMinSize] is set). +// 7. BSON null and undefined values will unmarshal into the zero value of a field (e.g. unmarshaling a BSON null or // undefined value into a string will yield the empty string.). // // # Structs // -// Structs can be marshalled/unmarshalled to/from BSON or Extended JSON. When transforming structs to/from BSON or Extended +// Structs can be marshaled/unmarshaled to/from BSON or Extended JSON. When transforming structs to/from BSON or Extended // JSON, the following rules apply: // -// 1. Only exported fields in structs will be marshalled or unmarshalled. +// 1. Only exported fields in structs will be marshaled or unmarshaled. // -// 2. When marshalling a struct, each field will be lowercased to generate the key for the corresponding BSON element. +// 2. When marshaling a struct, each field will be lowercased to generate the key for the corresponding BSON element. // For example, a struct field named "Foo" will generate key "foo". This can be overridden via a struct tag (e.g. // `bson:"fooField"` to generate key "fooField" instead). // -// 3. An embedded struct field is marshalled as a subdocument. The key will be the lowercased name of the field's type. +// 3. An embedded struct field is marshaled as a subdocument. The key will be the lowercased name of the field's type. // -// 4. A pointer field is marshalled as the underlying type if the pointer is non-nil. If the pointer is nil, it is -// marshalled as a BSON null value. +// 4. A pointer field is marshaled as the underlying type if the pointer is non-nil. If the pointer is nil, it is +// marshaled as a BSON null value. // -// 5. When unmarshalling, a field of type interface{} will follow the D/M type mappings listed above. BSON documents -// unmarshalled into an interface{} field will be unmarshalled as a D. +// 5. When unmarshaling, a field of type interface{} will follow the D/M type mappings listed above. BSON documents +// unmarshaled into an interface{} field will be unmarshaled as a D. // // The encoding of each struct field can be customized by the "bson" struct tag. // // This tag behavior is configurable, and different struct tag behavior can be configured by initializing a new -// bsoncodec.StructCodec with the desired tag parser and registering that StructCodec onto the Registry. By default, JSON tags -// are not honored, but that can be enabled by creating a StructCodec with JSONFallbackStructTagParser, like below: +// bsoncodec.StructCodec with the desired tag parser and registering that StructCodec onto the Registry. By default, JSON +// tags are not honored, but that can be enabled by creating a StructCodec with JSONFallbackStructTagParser, like below: // // Example: // // structcodec, _ := bsoncodec.NewStructCodec(bsoncodec.JSONFallbackStructTagParser) // // The bson tag gives the name of the field, possibly followed by a comma-separated list of options. -// The name may be empty in order to specify options without overriding the default field name. The following options can be used -// to configure behavior: -// -// 1. omitempty: If the omitempty struct tag is specified on a field, the field will not be marshalled if it is set to -// the zero value. Fields with language primitive types such as integers, booleans, and strings are considered empty if -// their value is equal to the zero value for the type (i.e. 0 for integers, false for booleans, and "" for strings). -// Slices, maps, and arrays are considered empty if they are of length zero. Interfaces and pointers are considered -// empty if their value is nil. By default, structs are only considered empty if the struct type implements the -// bsoncodec.Zeroer interface and the IsZero method returns true. Struct fields whose types do not implement Zeroer are -// never considered empty and will be marshalled as embedded documents. +// The name may be empty in order to specify options without overriding the default field name. The following options can +// be used to configure behavior: +// +// 1. omitempty: If the omitempty struct tag is specified on a field, the field will be omitted from the marshaling if +// the field has an empty value, defined as false, 0, a nil pointer, a nil interface value, and any empty array, +// slice, map, or string. // NOTE: It is recommended that this tag be used for all slice and map fields. // // 2. minsize: If the minsize struct tag is specified on a field of type int64, uint, uint32, or uint64 and the value of -// the field can fit in a signed int32, the field will be serialized as a BSON int32 rather than a BSON int64. For other -// types, this tag is ignored. +// the field can fit in a signed int32, the field will be serialized as a BSON int32 rather than a BSON int64. For +// other types, this tag is ignored. // -// 3. truncate: If the truncate struct tag is specified on a field with a non-float numeric type, BSON doubles unmarshalled -// into that field will be truncated at the decimal point. For example, if 3.14 is unmarshalled into a field of type int, -// it will be unmarshalled as 3. If this tag is not specified, the decoder will throw an error if the value cannot be -// decoded without losing precision. For float64 or non-numeric types, this tag is ignored. +// 3. truncate: If the truncate struct tag is specified on a field with a non-float numeric type, BSON doubles +// unmarshaled into that field will be truncated at the decimal point. For example, if 3.14 is unmarshaled into a +// field of type int, it will be unmarshaled as 3. If this tag is not specified, the decoder will throw an error if +// the value cannot be decoded without losing precision. For float64 or non-numeric types, this tag is ignored. // // 4. inline: If the inline struct tag is specified for a struct or map field, the field will be "flattened" when -// marshalling and "un-flattened" when unmarshalling. This means that all of the fields in that struct/map will be -// pulled up one level and will become top-level fields rather than being fields in a nested document. For example, if a -// map field named "Map" with value map[string]interface{}{"foo": "bar"} is inlined, the resulting document will be -// {"foo": "bar"} instead of {"map": {"foo": "bar"}}. There can only be one inlined map field in a struct. If there are -// duplicated fields in the resulting document when an inlined struct is marshalled, the inlined field will be overwritten. -// If there are duplicated fields in the resulting document when an inlined map is marshalled, an error will be returned. -// This tag can be used with fields that are pointers to structs. If an inlined pointer field is nil, it will not be -// marshalled. For fields that are not maps or structs, this tag is ignored. -// -// # Marshalling and Unmarshalling -// -// Manually marshalling and unmarshalling can be done with the Marshal and Unmarshal family of functions. +// marshaling and "un-flattened" when unmarshaling. This means that all of the fields in that struct/map will be +// pulled up one level and will become top-level fields rather than being fields in a nested document. For example, +// if a map field named "Map" with value map[string]interface{}{"foo": "bar"} is inlined, the resulting document will +// be {"foo": "bar"} instead of {"map": {"foo": "bar"}}. There can only be one inlined map field in a struct. If +// there are duplicated fields in the resulting document when an inlined struct is marshaled, the inlined field will +// be overwritten. If there are duplicated fields in the resulting document when an inlined map is marshaled, an +// error will be returned. This tag can be used with fields that are pointers to structs. If an inlined pointer field +// is nil, it will not be marshaled. For fields that are not maps or structs, this tag is ignored. +// +// # Marshaling and Unmarshaling +// +// Manually marshaling and unmarshaling can be done with the Marshal and Unmarshal family of functions. +// +// [Work with BSON]: https://www.mongodb.com/docs/drivers/go/current/fundamentals/bson/ package bson diff --git a/vendor/go.mongodb.org/mongo-driver/bson/encoder.go b/vendor/go.mongodb.org/mongo-driver/bson/encoder.go index fe5125d086..0be2a97fbc 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/encoder.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/encoder.go @@ -29,10 +29,20 @@ var encPool = sync.Pool{ type Encoder struct { ec bsoncodec.EncodeContext vw bsonrw.ValueWriter + + errorOnInlineDuplicates bool + intMinSize bool + stringifyMapKeysWithFmt bool + nilMapAsEmpty bool + nilSliceAsEmpty bool + nilByteSliceAsEmpty bool + omitZeroStruct bool + useJSONStructTags bool } // NewEncoder returns a new encoder that uses the DefaultRegistry to write to vw. func NewEncoder(vw bsonrw.ValueWriter) (*Encoder, error) { + // TODO:(GODRIVER-2719): Remove error return value. if vw == nil { return nil, errors.New("cannot create a new Encoder with a nil ValueWriter") } @@ -44,6 +54,9 @@ func NewEncoder(vw bsonrw.ValueWriter) (*Encoder, error) { } // NewEncoderWithContext returns a new encoder that uses EncodeContext ec to write to vw. +// +// Deprecated: Use [NewEncoder] and use the Encoder configuration methods to set the desired marshal +// behavior instead. func NewEncoderWithContext(ec bsoncodec.EncodeContext, vw bsonrw.ValueWriter) (*Encoder, error) { if ec.Registry == nil { ec = bsoncodec.EncodeContext{Registry: DefaultRegistry} @@ -60,8 +73,7 @@ func NewEncoderWithContext(ec bsoncodec.EncodeContext, vw bsonrw.ValueWriter) (* // Encode writes the BSON encoding of val to the stream. // -// The documentation for Marshal contains details about the conversion of Go -// values to BSON. +// See [Marshal] for details about BSON marshaling behavior. func (e *Encoder) Encode(val interface{}) error { if marshaler, ok := val.(Marshaler); ok { // TODO(skriptble): Should we have a MarshalAppender interface so that we can have []byte reuse? @@ -76,24 +88,112 @@ func (e *Encoder) Encode(val interface{}) error { if err != nil { return err } + + // Copy the configurations applied to the Encoder over to the EncodeContext, which actually + // communicates those configurations to the default ValueEncoders. + if e.errorOnInlineDuplicates { + e.ec.ErrorOnInlineDuplicates() + } + if e.intMinSize { + e.ec.MinSize = true + } + if e.stringifyMapKeysWithFmt { + e.ec.StringifyMapKeysWithFmt() + } + if e.nilMapAsEmpty { + e.ec.NilMapAsEmpty() + } + if e.nilSliceAsEmpty { + e.ec.NilSliceAsEmpty() + } + if e.nilByteSliceAsEmpty { + e.ec.NilByteSliceAsEmpty() + } + if e.omitZeroStruct { + e.ec.OmitZeroStruct() + } + if e.useJSONStructTags { + e.ec.UseJSONStructTags() + } + return encoder.EncodeValue(e.ec, e.vw, reflect.ValueOf(val)) } -// Reset will reset the state of the encoder, using the same *EncodeContext used in +// Reset will reset the state of the Encoder, using the same *EncodeContext used in // the original construction but using vw. func (e *Encoder) Reset(vw bsonrw.ValueWriter) error { + // TODO:(GODRIVER-2719): Remove error return value. e.vw = vw return nil } -// SetRegistry replaces the current registry of the encoder with r. +// SetRegistry replaces the current registry of the Encoder with r. func (e *Encoder) SetRegistry(r *bsoncodec.Registry) error { + // TODO:(GODRIVER-2719): Remove error return value. e.ec.Registry = r return nil } -// SetContext replaces the current EncodeContext of the encoder with er. +// SetContext replaces the current EncodeContext of the encoder with ec. +// +// Deprecated: Use the Encoder configuration methods set the desired marshal behavior instead. func (e *Encoder) SetContext(ec bsoncodec.EncodeContext) error { + // TODO:(GODRIVER-2719): Remove error return value. e.ec = ec return nil } + +// ErrorOnInlineDuplicates causes the Encoder to return an error if there is a duplicate field in +// the marshaled BSON when the "inline" struct tag option is set. +func (e *Encoder) ErrorOnInlineDuplicates() { + e.errorOnInlineDuplicates = true +} + +// IntMinSize causes the Encoder to marshal Go integer values (int, int8, int16, int32, int64, uint, +// uint8, uint16, uint32, or uint64) as the minimum BSON int size (either 32 or 64 bits) that can +// represent the integer value. +func (e *Encoder) IntMinSize() { + e.intMinSize = true +} + +// StringifyMapKeysWithFmt causes the Encoder to convert Go map keys to BSON document field name +// strings using fmt.Sprint instead of the default string conversion logic. +func (e *Encoder) StringifyMapKeysWithFmt() { + e.stringifyMapKeysWithFmt = true +} + +// NilMapAsEmpty causes the Encoder to marshal nil Go maps as empty BSON documents instead of BSON +// null. +func (e *Encoder) NilMapAsEmpty() { + e.nilMapAsEmpty = true +} + +// NilSliceAsEmpty causes the Encoder to marshal nil Go slices as empty BSON arrays instead of BSON +// null. +func (e *Encoder) NilSliceAsEmpty() { + e.nilSliceAsEmpty = true +} + +// NilByteSliceAsEmpty causes the Encoder to marshal nil Go byte slices as empty BSON binary values +// instead of BSON null. +func (e *Encoder) NilByteSliceAsEmpty() { + e.nilByteSliceAsEmpty = true +} + +// TODO(GODRIVER-2820): Update the description to remove the note about only examining exported +// TODO struct fields once the logic is updated to also inspect private struct fields. + +// OmitZeroStruct causes the Encoder to consider the zero value for a struct (e.g. MyStruct{}) +// as empty and omit it from the marshaled BSON when the "omitempty" struct tag option is set. +// +// Note that the Encoder only examines exported struct fields when determining if a struct is the +// zero value. It considers pointers to a zero struct value (e.g. &MyStruct{}) not empty. +func (e *Encoder) OmitZeroStruct() { + e.omitZeroStruct = true +} + +// UseJSONStructTags causes the Encoder to fall back to using the "json" struct tag if a "bson" +// struct tag is not specified. +func (e *Encoder) UseJSONStructTags() { + e.useJSONStructTags = true +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/marshal.go b/vendor/go.mongodb.org/mongo-driver/bson/marshal.go index db8d8ee92b..17ce6697e0 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/marshal.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/marshal.go @@ -9,6 +9,7 @@ package bson import ( "bytes" "encoding/json" + "sync" "go.mongodb.org/mongo-driver/bson/bsoncodec" "go.mongodb.org/mongo-driver/bson/bsonrw" @@ -20,17 +21,23 @@ const defaultDstCap = 256 var bvwPool = bsonrw.NewBSONValueWriterPool() var extjPool = bsonrw.NewExtJSONValueWriterPool() -// Marshaler is an interface implemented by types that can marshal themselves -// into a BSON document represented as bytes. The bytes returned must be a valid -// BSON document if the error is nil. +// Marshaler is the interface implemented by types that can marshal themselves +// into a valid BSON document. +// +// Implementations of Marshaler must return a full BSON document. To create +// custom BSON marshaling behavior for individual values in a BSON document, +// implement the ValueMarshaler interface instead. type Marshaler interface { MarshalBSON() ([]byte, error) } -// ValueMarshaler is an interface implemented by types that can marshal -// themselves into a BSON value as bytes. The type must be the valid type for -// the bytes returned. The bytes and byte type together must be valid if the -// error is nil. +// ValueMarshaler is the interface implemented by types that can marshal +// themselves into a valid BSON value. The format of the returned bytes must +// match the returned type. +// +// Implementations of ValueMarshaler must return an individual BSON value. To +// create custom BSON marshaling behavior for an entire BSON document, implement +// the Marshaler interface instead. type ValueMarshaler interface { MarshalBSONValue() (bsontype.Type, []byte, error) } @@ -48,12 +55,42 @@ func Marshal(val interface{}) ([]byte, error) { // MarshalAppend will encode val as a BSON document and append the bytes to dst. If dst is not large enough to hold the // bytes, it will be grown. If val is not a type that can be transformed into a document, MarshalValueAppend should be // used instead. +// +// Deprecated: Use [NewEncoder] and pass the dst byte slice (wrapped by a bytes.Buffer) into +// [bsonrw.NewBSONValueWriter]: +// +// buf := bytes.NewBuffer(dst) +// vw, err := bsonrw.NewBSONValueWriter(buf) +// if err != nil { +// panic(err) +// } +// enc, err := bson.NewEncoder(vw) +// if err != nil { +// panic(err) +// } +// +// See [Encoder] for more examples. func MarshalAppend(dst []byte, val interface{}) ([]byte, error) { return MarshalAppendWithRegistry(DefaultRegistry, dst, val) } // MarshalWithRegistry returns the BSON encoding of val as a BSON document. If val is not a type that can be transformed // into a document, MarshalValueWithRegistry should be used instead. +// +// Deprecated: Use [NewEncoder] and specify the Registry by calling [Encoder.SetRegistry] instead: +// +// buf := new(bytes.Buffer) +// vw, err := bsonrw.NewBSONValueWriter(buf) +// if err != nil { +// panic(err) +// } +// enc, err := bson.NewEncoder(vw) +// if err != nil { +// panic(err) +// } +// enc.SetRegistry(reg) +// +// See [Encoder] for more examples. func MarshalWithRegistry(r *bsoncodec.Registry, val interface{}) ([]byte, error) { dst := make([]byte, 0) return MarshalAppendWithRegistry(r, dst, val) @@ -61,6 +98,22 @@ func MarshalWithRegistry(r *bsoncodec.Registry, val interface{}) ([]byte, error) // MarshalWithContext returns the BSON encoding of val as a BSON document using EncodeContext ec. If val is not a type // that can be transformed into a document, MarshalValueWithContext should be used instead. +// +// Deprecated: Use [NewEncoder] and use the Encoder configuration methods to set the desired marshal +// behavior instead: +// +// buf := bytes.NewBuffer(dst) +// vw, err := bsonrw.NewBSONValueWriter(buf) +// if err != nil { +// panic(err) +// } +// enc, err := bson.NewEncoder(vw) +// if err != nil { +// panic(err) +// } +// enc.IntMinSize() +// +// See [Encoder] for more examples. func MarshalWithContext(ec bsoncodec.EncodeContext, val interface{}) ([]byte, error) { dst := make([]byte, 0) return MarshalAppendWithContext(ec, dst, val) @@ -69,16 +122,74 @@ func MarshalWithContext(ec bsoncodec.EncodeContext, val interface{}) ([]byte, er // MarshalAppendWithRegistry will encode val as a BSON document using Registry r and append the bytes to dst. If dst is // not large enough to hold the bytes, it will be grown. If val is not a type that can be transformed into a document, // MarshalValueAppendWithRegistry should be used instead. +// +// Deprecated: Use [NewEncoder], and pass the dst byte slice (wrapped by a bytes.Buffer) into +// [bsonrw.NewBSONValueWriter], and specify the Registry by calling [Encoder.SetRegistry] instead: +// +// buf := bytes.NewBuffer(dst) +// vw, err := bsonrw.NewBSONValueWriter(buf) +// if err != nil { +// panic(err) +// } +// enc, err := bson.NewEncoder(vw) +// if err != nil { +// panic(err) +// } +// enc.SetRegistry(reg) +// +// See [Encoder] for more examples. func MarshalAppendWithRegistry(r *bsoncodec.Registry, dst []byte, val interface{}) ([]byte, error) { return MarshalAppendWithContext(bsoncodec.EncodeContext{Registry: r}, dst, val) } +// Pool of buffers for marshalling BSON. +var bufPool = sync.Pool{ + New: func() interface{} { + return new(bytes.Buffer) + }, +} + // MarshalAppendWithContext will encode val as a BSON document using Registry r and EncodeContext ec and append the // bytes to dst. If dst is not large enough to hold the bytes, it will be grown. If val is not a type that can be // transformed into a document, MarshalValueAppendWithContext should be used instead. +// +// Deprecated: Use [NewEncoder], pass the dst byte slice (wrapped by a bytes.Buffer) into +// [bsonrw.NewBSONValueWriter], and use the Encoder configuration methods to set the desired marshal +// behavior instead: +// +// buf := bytes.NewBuffer(dst) +// vw, err := bsonrw.NewBSONValueWriter(buf) +// if err != nil { +// panic(err) +// } +// enc, err := bson.NewEncoder(vw) +// if err != nil { +// panic(err) +// } +// enc.IntMinSize() +// +// See [Encoder] for more examples. func MarshalAppendWithContext(ec bsoncodec.EncodeContext, dst []byte, val interface{}) ([]byte, error) { - sw := new(bsonrw.SliceWriter) - *sw = dst + sw := bufPool.Get().(*bytes.Buffer) + defer func() { + // Proper usage of a sync.Pool requires each entry to have approximately + // the same memory cost. To obtain this property when the stored type + // contains a variably-sized buffer, we add a hard limit on the maximum + // buffer to place back in the pool. We limit the size to 16MiB because + // that's the maximum wire message size supported by any current MongoDB + // server. + // + // Comment based on + // https://cs.opensource.google/go/go/+/refs/tags/go1.19:src/fmt/print.go;l=147 + // + // Recycle byte slices that are smaller than 16MiB and at least half + // occupied. + if sw.Cap() < 16*1024*1024 && sw.Cap()/2 < sw.Len() { + bufPool.Put(sw) + } + }() + + sw.Reset() vw := bvwPool.Get(sw) defer bvwPool.Put(vw) @@ -99,7 +210,7 @@ func MarshalAppendWithContext(ec bsoncodec.EncodeContext, dst []byte, val interf return nil, err } - return *sw, nil + return append(dst, sw.Bytes()...), nil } // MarshalValue returns the BSON encoding of val. @@ -112,17 +223,26 @@ func MarshalValue(val interface{}) (bsontype.Type, []byte, error) { // MarshalValueAppend will append the BSON encoding of val to dst. If dst is not large enough to hold the BSON encoding // of val, dst will be grown. +// +// Deprecated: Appending individual BSON elements to an existing slice will not be supported in Go +// Driver 2.0. func MarshalValueAppend(dst []byte, val interface{}) (bsontype.Type, []byte, error) { return MarshalValueAppendWithRegistry(DefaultRegistry, dst, val) } // MarshalValueWithRegistry returns the BSON encoding of val using Registry r. +// +// Deprecated: Using a custom registry to marshal individual BSON values will not be supported in Go +// Driver 2.0. func MarshalValueWithRegistry(r *bsoncodec.Registry, val interface{}) (bsontype.Type, []byte, error) { dst := make([]byte, 0) return MarshalValueAppendWithRegistry(r, dst, val) } // MarshalValueWithContext returns the BSON encoding of val using EncodeContext ec. +// +// Deprecated: Using a custom EncodeContext to marshal individual BSON elements will not be +// supported in Go Driver 2.0. func MarshalValueWithContext(ec bsoncodec.EncodeContext, val interface{}) (bsontype.Type, []byte, error) { dst := make([]byte, 0) return MarshalValueAppendWithContext(ec, dst, val) @@ -130,12 +250,18 @@ func MarshalValueWithContext(ec bsoncodec.EncodeContext, val interface{}) (bsont // MarshalValueAppendWithRegistry will append the BSON encoding of val to dst using Registry r. If dst is not large // enough to hold the BSON encoding of val, dst will be grown. +// +// Deprecated: Appending individual BSON elements to an existing slice will not be supported in Go +// Driver 2.0. func MarshalValueAppendWithRegistry(r *bsoncodec.Registry, dst []byte, val interface{}) (bsontype.Type, []byte, error) { return MarshalValueAppendWithContext(bsoncodec.EncodeContext{Registry: r}, dst, val) } // MarshalValueAppendWithContext will append the BSON encoding of val to dst using EncodeContext ec. If dst is not large // enough to hold the BSON encoding of val, dst will be grown. +// +// Deprecated: Appending individual BSON elements to an existing slice will not be supported in Go +// Driver 2.0. func MarshalValueAppendWithContext(ec bsoncodec.EncodeContext, dst []byte, val interface{}) (bsontype.Type, []byte, error) { // get a ValueWriter configured to write to dst sw := new(bsonrw.SliceWriter) @@ -173,17 +299,63 @@ func MarshalExtJSON(val interface{}, canonical, escapeHTML bool) ([]byte, error) // MarshalExtJSONAppend will append the extended JSON encoding of val to dst. // If dst is not large enough to hold the extended JSON encoding of val, dst // will be grown. +// +// Deprecated: Use [NewEncoder] and pass the dst byte slice (wrapped by a bytes.Buffer) into +// [bsonrw.NewExtJSONValueWriter] instead: +// +// buf := bytes.NewBuffer(dst) +// vw, err := bsonrw.NewExtJSONValueWriter(buf, true, false) +// if err != nil { +// panic(err) +// } +// enc, err := bson.NewEncoder(vw) +// if err != nil { +// panic(err) +// } +// +// See [Encoder] for more examples. func MarshalExtJSONAppend(dst []byte, val interface{}, canonical, escapeHTML bool) ([]byte, error) { return MarshalExtJSONAppendWithRegistry(DefaultRegistry, dst, val, canonical, escapeHTML) } // MarshalExtJSONWithRegistry returns the extended JSON encoding of val using Registry r. +// +// Deprecated: Use [NewEncoder] and specify the Registry by calling [Encoder.SetRegistry] instead: +// +// buf := new(bytes.Buffer) +// vw, err := bsonrw.NewBSONValueWriter(buf) +// if err != nil { +// panic(err) +// } +// enc, err := bson.NewEncoder(vw) +// if err != nil { +// panic(err) +// } +// enc.SetRegistry(reg) +// +// See [Encoder] for more examples. func MarshalExtJSONWithRegistry(r *bsoncodec.Registry, val interface{}, canonical, escapeHTML bool) ([]byte, error) { dst := make([]byte, 0, defaultDstCap) return MarshalExtJSONAppendWithContext(bsoncodec.EncodeContext{Registry: r}, dst, val, canonical, escapeHTML) } // MarshalExtJSONWithContext returns the extended JSON encoding of val using Registry r. +// +// Deprecated: Use [NewEncoder] and use the Encoder configuration methods to set the desired marshal +// behavior instead: +// +// buf := new(bytes.Buffer) +// vw, err := bsonrw.NewBSONValueWriter(buf) +// if err != nil { +// panic(err) +// } +// enc, err := bson.NewEncoder(vw) +// if err != nil { +// panic(err) +// } +// enc.IntMinSize() +// +// See [Encoder] for more examples. func MarshalExtJSONWithContext(ec bsoncodec.EncodeContext, val interface{}, canonical, escapeHTML bool) ([]byte, error) { dst := make([]byte, 0, defaultDstCap) return MarshalExtJSONAppendWithContext(ec, dst, val, canonical, escapeHTML) @@ -192,6 +364,22 @@ func MarshalExtJSONWithContext(ec bsoncodec.EncodeContext, val interface{}, cano // MarshalExtJSONAppendWithRegistry will append the extended JSON encoding of // val to dst using Registry r. If dst is not large enough to hold the BSON // encoding of val, dst will be grown. +// +// Deprecated: Use [NewEncoder], pass the dst byte slice (wrapped by a bytes.Buffer) into +// [bsonrw.NewExtJSONValueWriter], and specify the Registry by calling [Encoder.SetRegistry] +// instead: +// +// buf := bytes.NewBuffer(dst) +// vw, err := bsonrw.NewExtJSONValueWriter(buf, true, false) +// if err != nil { +// panic(err) +// } +// enc, err := bson.NewEncoder(vw) +// if err != nil { +// panic(err) +// } +// +// See [Encoder] for more examples. func MarshalExtJSONAppendWithRegistry(r *bsoncodec.Registry, dst []byte, val interface{}, canonical, escapeHTML bool) ([]byte, error) { return MarshalExtJSONAppendWithContext(bsoncodec.EncodeContext{Registry: r}, dst, val, canonical, escapeHTML) } @@ -199,6 +387,23 @@ func MarshalExtJSONAppendWithRegistry(r *bsoncodec.Registry, dst []byte, val int // MarshalExtJSONAppendWithContext will append the extended JSON encoding of // val to dst using Registry r. If dst is not large enough to hold the BSON // encoding of val, dst will be grown. +// +// Deprecated: Use [NewEncoder], pass the dst byte slice (wrapped by a bytes.Buffer) into +// [bsonrw.NewExtJSONValueWriter], and use the Encoder configuration methods to set the desired marshal +// behavior instead: +// +// buf := bytes.NewBuffer(dst) +// vw, err := bsonrw.NewExtJSONValueWriter(buf, true, false) +// if err != nil { +// panic(err) +// } +// enc, err := bson.NewEncoder(vw) +// if err != nil { +// panic(err) +// } +// enc.IntMinSize() +// +// See [Encoder] for more examples. func MarshalExtJSONAppendWithContext(ec bsoncodec.EncodeContext, dst []byte, val interface{}, canonical, escapeHTML bool) ([]byte, error) { sw := new(bsonrw.SliceWriter) *sw = dst diff --git a/vendor/go.mongodb.org/mongo-driver/bson/primitive/decimal.go b/vendor/go.mongodb.org/mongo-driver/bson/primitive/decimal.go index ba7c9112e9..08c39514be 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/primitive/decimal.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/primitive/decimal.go @@ -164,9 +164,6 @@ func (d Decimal128) BigInt() (*big.Int, int, error) { // Would be handled by the logic below, but that's trivial and common. if high == 0 && low == 0 && exp == 0 { - if posSign { - return new(big.Int), 0, nil - } return new(big.Int), 0, nil } @@ -328,6 +325,7 @@ func ParseDecimal128(s string) (Decimal128, error) { return dErr(s) } + // Parse the significand (i.e. the non-exponent part) as a big.Int. bi, ok := new(big.Int).SetString(intPart+decPart, 10) if !ok { return dErr(s) @@ -360,6 +358,19 @@ func ParseDecimal128FromBigInt(bi *big.Int, exp int) (Decimal128, bool) { q := new(big.Int) r := new(big.Int) + // If the significand is zero, the logical value will always be zero, independent of the + // exponent. However, the loops for handling out-of-range exponent values below may be extremely + // slow for zero values because the significand never changes. Limit the exponent value to the + // supported range here to prevent entering the loops below. + if bi.Cmp(zero) == 0 { + if exp > MaxDecimal128Exp { + exp = MaxDecimal128Exp + } + if exp < MinDecimal128Exp { + exp = MinDecimal128Exp + } + } + for bigIntCmpAbs(bi, maxS) == 1 { bi, _ = q.QuoRem(bi, ten, r) if r.Cmp(zero) != 0 { diff --git a/vendor/go.mongodb.org/mongo-driver/bson/primitive/objectid.go b/vendor/go.mongodb.org/mongo-driver/bson/primitive/objectid.go index ded3673165..c130e3ff19 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/primitive/objectid.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/primitive/objectid.go @@ -82,18 +82,18 @@ func ObjectIDFromHex(s string) (ObjectID, error) { return NilObjectID, ErrInvalidHex } - b, err := hex.DecodeString(s) + var oid [12]byte + _, err := hex.Decode(oid[:], []byte(s)) if err != nil { return NilObjectID, err } - var oid [12]byte - copy(oid[:], b) - return oid, nil } // IsValidObjectID returns true if the provided hex string represents a valid ObjectID and false if not. +// +// Deprecated: Use ObjectIDFromHex and check the error instead. func IsValidObjectID(s string) bool { _, err := ObjectIDFromHex(s) return err == nil @@ -183,7 +183,7 @@ func processUniqueBytes() [5]byte { var b [5]byte _, err := io.ReadFull(rand.Reader, b[:]) if err != nil { - panic(fmt.Errorf("cannot initialize objectid package with crypto.rand.Reader: %v", err)) + panic(fmt.Errorf("cannot initialize objectid package with crypto.rand.Reader: %w", err)) } return b @@ -193,7 +193,7 @@ func readRandomUint32() uint32 { var b [4]byte _, err := io.ReadFull(rand.Reader, b[:]) if err != nil { - panic(fmt.Errorf("cannot initialize objectid package with crypto.rand.Reader: %v", err)) + panic(fmt.Errorf("cannot initialize objectid package with crypto.rand.Reader: %w", err)) } return (uint32(b[0]) << 0) | (uint32(b[1]) << 8) | (uint32(b[2]) << 16) | (uint32(b[3]) << 24) diff --git a/vendor/go.mongodb.org/mongo-driver/bson/primitive/primitive.go b/vendor/go.mongodb.org/mongo-driver/bson/primitive/primitive.go index c72ccc1c4d..65f4fbb949 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/primitive/primitive.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/primitive/primitive.go @@ -45,7 +45,7 @@ var _ json.Unmarshaler = (*DateTime)(nil) // MarshalJSON marshal to time type. func (d DateTime) MarshalJSON() ([]byte, error) { - return json.Marshal(d.Time()) + return json.Marshal(d.Time().UTC()) } // UnmarshalJSON creates a primitive.DateTime from a JSON string. @@ -141,6 +141,16 @@ type Timestamp struct { I uint32 } +// After reports whether the time instant tp is after tp2. +func (tp Timestamp) After(tp2 Timestamp) bool { + return tp.T > tp2.T || (tp.T == tp2.T && tp.I > tp2.I) +} + +// Before reports whether the time instant tp is before tp2. +func (tp Timestamp) Before(tp2 Timestamp) bool { + return tp.T < tp2.T || (tp.T == tp2.T && tp.I < tp2.I) +} + // Equal compares tp to tp2 and returns true if they are equal. func (tp Timestamp) Equal(tp2 Timestamp) bool { return tp.T == tp2.T && tp.I == tp2.I @@ -151,24 +161,25 @@ func (tp Timestamp) IsZero() bool { return tp.T == 0 && tp.I == 0 } -// CompareTimestamp returns an integer comparing two Timestamps, where T is compared first, followed by I. -// Returns 0 if tp = tp2, 1 if tp > tp2, -1 if tp < tp2. -func CompareTimestamp(tp, tp2 Timestamp) int { - if tp.Equal(tp2) { +// Compare compares the time instant tp with tp2. If tp is before tp2, it returns -1; if tp is after +// tp2, it returns +1; if they're the same, it returns 0. +func (tp Timestamp) Compare(tp2 Timestamp) int { + switch { + case tp.Equal(tp2): return 0 - } - - if tp.T > tp2.T { - return 1 - } - if tp.T < tp2.T { + case tp.Before(tp2): return -1 + default: + return +1 } - // Compare I values because T values are equal - if tp.I > tp2.I { - return 1 - } - return -1 +} + +// CompareTimestamp compares the time instant tp with tp2. If tp is before tp2, it returns -1; if tp is after +// tp2, it returns +1; if they're the same, it returns 0. +// +// Deprecated: Use Timestamp.Compare instead. +func CompareTimestamp(tp, tp2 Timestamp) int { + return tp.Compare(tp2) } // MinKey represents the BSON minkey value. @@ -186,6 +197,9 @@ type MaxKey struct{} type D []E // Map creates a map from the elements of the D. +// +// Deprecated: Converting directly from a D to an M will not be supported in Go Driver 2.0. Instead, +// users should marshal the D to BSON using bson.Marshal and unmarshal it to M using bson.Unmarshal. func (d D) Map() M { m := make(M, len(d)) for _, e := range d { diff --git a/vendor/go.mongodb.org/mongo-driver/bson/primitive_codecs.go b/vendor/go.mongodb.org/mongo-driver/bson/primitive_codecs.go index 1cbe3884d1..ff32a87a79 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/primitive_codecs.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/primitive_codecs.go @@ -8,6 +8,7 @@ package bson import ( "errors" + "fmt" "reflect" "go.mongodb.org/mongo-driver/bson/bsoncodec" @@ -21,10 +22,16 @@ var primitiveCodecs PrimitiveCodecs // PrimitiveCodecs is a namespace for all of the default bsoncodec.Codecs for the primitive types // defined in this package. +// +// Deprecated: Use bson.NewRegistry to get a registry with all primitive encoders and decoders +// registered. type PrimitiveCodecs struct{} // RegisterPrimitiveCodecs will register the encode and decode methods attached to PrimitiveCodecs // with the provided RegistryBuilder. if rb is nil, a new empty RegistryBuilder will be created. +// +// Deprecated: Use bson.NewRegistry to get a registry with all primitive encoders and decoders +// registered. func (pc PrimitiveCodecs) RegisterPrimitiveCodecs(rb *bsoncodec.RegistryBuilder) { if rb == nil { panic(errors.New("argument to RegisterPrimitiveCodecs must not be nil")) @@ -38,18 +45,35 @@ func (pc PrimitiveCodecs) RegisterPrimitiveCodecs(rb *bsoncodec.RegistryBuilder) } // RawValueEncodeValue is the ValueEncoderFunc for RawValue. -func (PrimitiveCodecs) RawValueEncodeValue(ec bsoncodec.EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +// +// If the RawValue's Type is "invalid" and the RawValue's Value is not empty or +// nil, then this method will return an error. +// +// Deprecated: Use bson.NewRegistry to get a registry with all primitive +// encoders and decoders registered. +func (PrimitiveCodecs) RawValueEncodeValue(_ bsoncodec.EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Type() != tRawValue { - return bsoncodec.ValueEncoderError{Name: "RawValueEncodeValue", Types: []reflect.Type{tRawValue}, Received: val} + return bsoncodec.ValueEncoderError{ + Name: "RawValueEncodeValue", + Types: []reflect.Type{tRawValue}, + Received: val, + } } rawvalue := val.Interface().(RawValue) + if !rawvalue.Type.IsValid() { + return fmt.Errorf("the RawValue Type specifies an invalid BSON type: %#x", byte(rawvalue.Type)) + } + return bsonrw.Copier{}.CopyValueFromBytes(vw, rawvalue.Type, rawvalue.Value) } // RawValueDecodeValue is the ValueDecoderFunc for RawValue. -func (PrimitiveCodecs) RawValueDecodeValue(dc bsoncodec.DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +// +// Deprecated: Use bson.NewRegistry to get a registry with all primitive encoders and decoders +// registered. +func (PrimitiveCodecs) RawValueDecodeValue(_ bsoncodec.DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { if !val.CanSet() || val.Type() != tRawValue { return bsoncodec.ValueDecoderError{Name: "RawValueDecodeValue", Types: []reflect.Type{tRawValue}, Received: val} } @@ -64,7 +88,10 @@ func (PrimitiveCodecs) RawValueDecodeValue(dc bsoncodec.DecodeContext, vr bsonrw } // RawEncodeValue is the ValueEncoderFunc for Reader. -func (PrimitiveCodecs) RawEncodeValue(ec bsoncodec.EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +// +// Deprecated: Use bson.NewRegistry to get a registry with all primitive encoders and decoders +// registered. +func (PrimitiveCodecs) RawEncodeValue(_ bsoncodec.EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Type() != tRaw { return bsoncodec.ValueEncoderError{Name: "RawEncodeValue", Types: []reflect.Type{tRaw}, Received: val} } @@ -75,7 +102,10 @@ func (PrimitiveCodecs) RawEncodeValue(ec bsoncodec.EncodeContext, vw bsonrw.Valu } // RawDecodeValue is the ValueDecoderFunc for Reader. -func (PrimitiveCodecs) RawDecodeValue(dc bsoncodec.DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +// +// Deprecated: Use bson.NewRegistry to get a registry with all primitive encoders and decoders +// registered. +func (PrimitiveCodecs) RawDecodeValue(_ bsoncodec.DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { if !val.CanSet() || val.Type() != tRaw { return bsoncodec.ValueDecoderError{Name: "RawDecodeValue", Types: []reflect.Type{tRaw}, Received: val} } diff --git a/vendor/go.mongodb.org/mongo-driver/bson/raw.go b/vendor/go.mongodb.org/mongo-driver/bson/raw.go index efd705daaa..130da61ba0 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/raw.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/raw.go @@ -16,18 +16,27 @@ import ( // ErrNilReader indicates that an operation was attempted on a nil bson.Reader. var ErrNilReader = errors.New("nil reader") -// Raw is a wrapper around a byte slice. It will interpret the slice as a -// BSON document. This type is a wrapper around a bsoncore.Document. Errors returned from the -// methods on this type and associated types come from the bsoncore package. +// Raw is a raw encoded BSON document. It can be used to delay BSON document decoding or precompute +// a BSON encoded document. +// +// A Raw must be a full BSON document. Use the RawValue type for individual BSON values. type Raw []byte -// NewFromIOReader reads in a document from the given io.Reader and constructs a Raw from -// it. -func NewFromIOReader(r io.Reader) (Raw, error) { +// ReadDocument reads a BSON document from the io.Reader and returns it as a bson.Raw. If the +// reader contains multiple BSON documents, only the first document is read. +func ReadDocument(r io.Reader) (Raw, error) { doc, err := bsoncore.NewDocumentFromReader(r) return Raw(doc), err } +// NewFromIOReader reads a BSON document from the io.Reader and returns it as a bson.Raw. If the +// reader contains multiple BSON documents, only the first document is read. +// +// Deprecated: Use ReadDocument instead. +func NewFromIOReader(r io.Reader) (Raw, error) { + return ReadDocument(r) +} + // Validate validates the document. This method only validates the first document in // the slice, to validate other documents, the slice must be resliced. func (r Raw) Validate() (err error) { return bsoncore.Document(r).Validate() } @@ -51,12 +60,19 @@ func (r Raw) LookupErr(key ...string) (RawValue, error) { // elements. If the document is not valid, the elements up to the invalid point will be returned // along with an error. func (r Raw) Elements() ([]RawElement, error) { - elems, err := bsoncore.Document(r).Elements() + doc := bsoncore.Document(r) + if len(doc) == 0 { + return nil, nil + } + elems, err := doc.Elements() + if err != nil { + return nil, err + } relems := make([]RawElement, 0, len(elems)) for _, elem := range elems { relems = append(relems, RawElement(elem)) } - return relems, err + return relems, nil } // Values returns this document as a slice of values. The returned slice will contain valid values. @@ -81,5 +97,5 @@ func (r Raw) IndexErr(index uint) (RawElement, error) { return RawElement(elem), err } -// String implements the fmt.Stringer interface. +// String returns the BSON document encoded as Extended JSON. func (r Raw) String() string { return bsoncore.Document(r).String() } diff --git a/vendor/go.mongodb.org/mongo-driver/bson/raw_element.go b/vendor/go.mongodb.org/mongo-driver/bson/raw_element.go index 006f503a30..8ce13c2cc7 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/raw_element.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/raw_element.go @@ -10,10 +10,7 @@ import ( "go.mongodb.org/mongo-driver/x/bsonx/bsoncore" ) -// RawElement represents a BSON element in byte form. This type provides a simple way to -// transform a slice of bytes into a BSON element and extract information from it. -// -// RawElement is a thin wrapper around a bsoncore.Element. +// RawElement is a raw encoded BSON document or array element. type RawElement []byte // Key returns the key for this element. If the element is not valid, this method returns an empty @@ -36,7 +33,7 @@ func (re RawElement) ValueErr() (RawValue, error) { // Validate ensures re is a valid BSON element. func (re RawElement) Validate() error { return bsoncore.Element(re).Validate() } -// String implements the fmt.Stringer interface. The output will be in extended JSON format. +// String returns the BSON element encoded as Extended JSON. func (re RawElement) String() string { doc := bsoncore.BuildDocument(nil, re) j, err := MarshalExtJSON(Raw(doc), true, false) diff --git a/vendor/go.mongodb.org/mongo-driver/bson/raw_value.go b/vendor/go.mongodb.org/mongo-driver/bson/raw_value.go index 75297f30fe..4d1bfb3160 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/raw_value.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/raw_value.go @@ -26,11 +26,10 @@ var ErrNilContext = errors.New("DecodeContext cannot be nil") // ErrNilRegistry is returned when the provided registry is nil. var ErrNilRegistry = errors.New("Registry cannot be nil") -// RawValue represents a BSON value in byte form. It can be used to hold unprocessed BSON or to -// defer processing of BSON. Type is the BSON type of the value and Value are the raw bytes that -// represent the element. +// RawValue is a raw encoded BSON value. It can be used to delay BSON value decoding or precompute +// BSON encoded value. Type is the BSON type of the value and Value is the raw encoded BSON value. // -// This type wraps bsoncore.Value for most of it's functionality. +// A RawValue must be an individual BSON value. Use the Raw type for full BSON documents. type RawValue struct { Type bsontype.Type Value []byte @@ -38,6 +37,12 @@ type RawValue struct { r *bsoncodec.Registry } +// IsZero reports whether the RawValue is zero, i.e. no data is present on +// the RawValue. It returns true if Type is 0 and Value is empty or nil. +func (rv RawValue) IsZero() bool { + return rv.Type == 0x00 && len(rv.Value) == 0 +} + // Unmarshal deserializes BSON into the provided val. If RawValue cannot be unmarshaled into val, an // error is returned. This method will use the registry used to create the RawValue, if the RawValue // was created from partial BSON processing, or it will use the default registry. Users wishing to @@ -268,10 +273,16 @@ func (rv RawValue) Int32OK() (int32, bool) { return convertToCoreValue(rv).Int32 // AsInt32 returns a BSON number as an int32. If the BSON type is not a numeric one, this method // will panic. +// +// Deprecated: Use AsInt64 instead. If an int32 is required, convert the returned value to an int32 +// and perform any required overflow/underflow checking. func (rv RawValue) AsInt32() int32 { return convertToCoreValue(rv).AsInt32() } // AsInt32OK is the same as AsInt32, except that it returns a boolean instead of // panicking. +// +// Deprecated: Use AsInt64OK instead. If an int32 is required, convert the returned value to an +// int32 and perform any required overflow/underflow checking. func (rv RawValue) AsInt32OK() (int32, bool) { return convertToCoreValue(rv).AsInt32OK() } // Timestamp returns the BSON timestamp value the Value represents. It panics if the value is a diff --git a/vendor/go.mongodb.org/mongo-driver/bson/registry.go b/vendor/go.mongodb.org/mongo-driver/bson/registry.go index 16d7573e75..b5b0f35687 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/registry.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/registry.go @@ -6,15 +6,19 @@ package bson -import "go.mongodb.org/mongo-driver/bson/bsoncodec" +import ( + "go.mongodb.org/mongo-driver/bson/bsoncodec" +) // DefaultRegistry is the default bsoncodec.Registry. It contains the default codecs and the // primitive codecs. -var DefaultRegistry = NewRegistryBuilder().Build() +var DefaultRegistry = NewRegistry() // NewRegistryBuilder creates a new RegistryBuilder configured with the default encoders and // decoders from the bsoncodec.DefaultValueEncoders and bsoncodec.DefaultValueDecoders types and the // PrimitiveCodecs type in this package. +// +// Deprecated: Use NewRegistry instead. func NewRegistryBuilder() *bsoncodec.RegistryBuilder { rb := bsoncodec.NewRegistryBuilder() bsoncodec.DefaultValueEncoders{}.RegisterDefaultEncoders(rb) @@ -22,3 +26,10 @@ func NewRegistryBuilder() *bsoncodec.RegistryBuilder { primitiveCodecs.RegisterPrimitiveCodecs(rb) return rb } + +// NewRegistry creates a new Registry configured with the default encoders and decoders from the +// bsoncodec.DefaultValueEncoders and bsoncodec.DefaultValueDecoders types and the PrimitiveCodecs +// type in this package. +func NewRegistry() *bsoncodec.Registry { + return NewRegistryBuilder().Build() +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/types.go b/vendor/go.mongodb.org/mongo-driver/bson/types.go index 13a1c35cf6..ef39812467 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/types.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/types.go @@ -10,7 +10,7 @@ import ( "go.mongodb.org/mongo-driver/bson/bsontype" ) -// These constants uniquely refer to each BSON type. +// BSON element types as described in https://bsonspec.org/spec.html. const ( TypeDouble = bsontype.Double TypeString = bsontype.String @@ -34,3 +34,17 @@ const ( TypeMinKey = bsontype.MinKey TypeMaxKey = bsontype.MaxKey ) + +// BSON binary element subtypes as described in https://bsonspec.org/spec.html. +const ( + TypeBinaryGeneric = bsontype.BinaryGeneric + TypeBinaryFunction = bsontype.BinaryFunction + TypeBinaryBinaryOld = bsontype.BinaryBinaryOld + TypeBinaryUUIDOld = bsontype.BinaryUUIDOld + TypeBinaryUUID = bsontype.BinaryUUID + TypeBinaryMD5 = bsontype.BinaryMD5 + TypeBinaryEncrypted = bsontype.BinaryEncrypted + TypeBinaryColumn = bsontype.BinaryColumn + TypeBinarySensitive = bsontype.BinarySensitive + TypeBinaryUserDefined = bsontype.BinaryUserDefined +) diff --git a/vendor/go.mongodb.org/mongo-driver/bson/unmarshal.go b/vendor/go.mongodb.org/mongo-driver/bson/unmarshal.go index f936ba1836..66da17ee01 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/unmarshal.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/unmarshal.go @@ -14,18 +14,26 @@ import ( "go.mongodb.org/mongo-driver/bson/bsontype" ) -// Unmarshaler is an interface implemented by types that can unmarshal a BSON -// document representation of themselves. The BSON bytes can be assumed to be -// valid. UnmarshalBSON must copy the BSON bytes if it wishes to retain the data -// after returning. +// Unmarshaler is the interface implemented by types that can unmarshal a BSON +// document representation of themselves. The input can be assumed to be a valid +// encoding of a BSON document. UnmarshalBSON must copy the JSON data if it +// wishes to retain the data after returning. +// +// Unmarshaler is only used to unmarshal full BSON documents. To create custom +// BSON unmarshaling behavior for individual values in a BSON document, +// implement the ValueUnmarshaler interface instead. type Unmarshaler interface { UnmarshalBSON([]byte) error } -// ValueUnmarshaler is an interface implemented by types that can unmarshal a -// BSON value representation of themselves. The BSON bytes and type can be -// assumed to be valid. UnmarshalBSONValue must copy the BSON value bytes if it -// wishes to retain the data after returning. +// ValueUnmarshaler is the interface implemented by types that can unmarshal a +// BSON value representation of themselves. The input can be assumed to be a +// valid encoding of a BSON value. UnmarshalBSONValue must copy the BSON value +// bytes if it wishes to retain the data after returning. +// +// ValueUnmarshaler is only used to unmarshal individual values in a BSON +// document. To create custom BSON unmarshaling behavior for an entire BSON +// document, implement the Unmarshaler interface instead. type ValueUnmarshaler interface { UnmarshalBSONValue(bsontype.Type, []byte) error } @@ -40,6 +48,16 @@ func Unmarshal(data []byte, val interface{}) error { // UnmarshalWithRegistry parses the BSON-encoded data using Registry r and // stores the result in the value pointed to by val. If val is nil or not // a pointer, UnmarshalWithRegistry returns InvalidUnmarshalError. +// +// Deprecated: Use [NewDecoder] and specify the Registry by calling [Decoder.SetRegistry] instead: +// +// dec, err := bson.NewDecoder(bsonrw.NewBSONDocumentReader(data)) +// if err != nil { +// panic(err) +// } +// dec.SetRegistry(reg) +// +// See [Decoder] for more examples. func UnmarshalWithRegistry(r *bsoncodec.Registry, data []byte, val interface{}) error { vr := bsonrw.NewBSONDocumentReader(data) return unmarshalFromReader(bsoncodec.DecodeContext{Registry: r}, vr, val) @@ -48,11 +66,40 @@ func UnmarshalWithRegistry(r *bsoncodec.Registry, data []byte, val interface{}) // UnmarshalWithContext parses the BSON-encoded data using DecodeContext dc and // stores the result in the value pointed to by val. If val is nil or not // a pointer, UnmarshalWithRegistry returns InvalidUnmarshalError. +// +// Deprecated: Use [NewDecoder] and use the Decoder configuration methods to set the desired unmarshal +// behavior instead: +// +// dec, err := bson.NewDecoder(bsonrw.NewBSONDocumentReader(data)) +// if err != nil { +// panic(err) +// } +// dec.DefaultDocumentM() +// +// See [Decoder] for more examples. func UnmarshalWithContext(dc bsoncodec.DecodeContext, data []byte, val interface{}) error { vr := bsonrw.NewBSONDocumentReader(data) return unmarshalFromReader(dc, vr, val) } +// UnmarshalValue parses the BSON value of type t with bson.DefaultRegistry and +// stores the result in the value pointed to by val. If val is nil or not a pointer, +// UnmarshalValue returns an error. +func UnmarshalValue(t bsontype.Type, data []byte, val interface{}) error { + return UnmarshalValueWithRegistry(DefaultRegistry, t, data, val) +} + +// UnmarshalValueWithRegistry parses the BSON value of type t with registry r and +// stores the result in the value pointed to by val. If val is nil or not a pointer, +// UnmarshalValue returns an error. +// +// Deprecated: Using a custom registry to unmarshal individual BSON values will not be supported in +// Go Driver 2.0. +func UnmarshalValueWithRegistry(r *bsoncodec.Registry, t bsontype.Type, data []byte, val interface{}) error { + vr := bsonrw.NewBSONValueReader(t, data) + return unmarshalFromReader(bsoncodec.DecodeContext{Registry: r}, vr, val) +} + // UnmarshalExtJSON parses the extended JSON-encoded data and stores the result // in the value pointed to by val. If val is nil or not a pointer, Unmarshal // returns InvalidUnmarshalError. @@ -63,6 +110,20 @@ func UnmarshalExtJSON(data []byte, canonical bool, val interface{}) error { // UnmarshalExtJSONWithRegistry parses the extended JSON-encoded data using // Registry r and stores the result in the value pointed to by val. If val is // nil or not a pointer, UnmarshalWithRegistry returns InvalidUnmarshalError. +// +// Deprecated: Use [NewDecoder] and specify the Registry by calling [Decoder.SetRegistry] instead: +// +// vr, err := bsonrw.NewExtJSONValueReader(bytes.NewReader(data), true) +// if err != nil { +// panic(err) +// } +// dec, err := bson.NewDecoder(vr) +// if err != nil { +// panic(err) +// } +// dec.SetRegistry(reg) +// +// See [Decoder] for more examples. func UnmarshalExtJSONWithRegistry(r *bsoncodec.Registry, data []byte, canonical bool, val interface{}) error { ejvr, err := bsonrw.NewExtJSONValueReader(bytes.NewReader(data), canonical) if err != nil { @@ -75,6 +136,21 @@ func UnmarshalExtJSONWithRegistry(r *bsoncodec.Registry, data []byte, canonical // UnmarshalExtJSONWithContext parses the extended JSON-encoded data using // DecodeContext dc and stores the result in the value pointed to by val. If val is // nil or not a pointer, UnmarshalWithRegistry returns InvalidUnmarshalError. +// +// Deprecated: Use [NewDecoder] and use the Decoder configuration methods to set the desired unmarshal +// behavior instead: +// +// vr, err := bsonrw.NewExtJSONValueReader(bytes.NewReader(data), true) +// if err != nil { +// panic(err) +// } +// dec, err := bson.NewDecoder(vr) +// if err != nil { +// panic(err) +// } +// dec.DefaultDocumentM() +// +// See [Decoder] for more examples. func UnmarshalExtJSONWithContext(dc bsoncodec.DecodeContext, data []byte, canonical bool, val interface{}) error { ejvr, err := bsonrw.NewExtJSONValueReader(bytes.NewReader(data), canonical) if err != nil { diff --git a/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/array.go b/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/array.go index 8ea60ba3c6..6bc0afa700 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/array.go +++ b/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/array.go @@ -7,10 +7,10 @@ package bsoncore import ( - "bytes" "fmt" "io" "strconv" + "strings" ) // NewArrayLengthError creates and returns an error for when the length of an array exceeds the @@ -53,7 +53,7 @@ func (a Array) DebugString() string { if len(a) < 5 { return "" } - var buf bytes.Buffer + var buf strings.Builder buf.WriteString("Array") length, rem, _ := ReadLength(a) // We know we have enough bytes to read the length buf.WriteByte('(') @@ -69,7 +69,7 @@ func (a Array) DebugString() string { buf.WriteString(fmt.Sprintf("", length)) break } - fmt.Fprintf(&buf, "%s", elem.Value().DebugString()) + buf.WriteString(elem.Value().DebugString()) if length != 1 { buf.WriteByte(',') } @@ -85,7 +85,7 @@ func (a Array) String() string { if len(a) < 5 { return "" } - var buf bytes.Buffer + var buf strings.Builder buf.WriteByte('[') length, rem, _ := ReadLength(a) // We know we have enough bytes to read the length @@ -100,7 +100,7 @@ func (a Array) String() string { if !ok { return "" } - fmt.Fprintf(&buf, "%s", elem.Value().String()) + buf.WriteString(elem.Value().String()) if length > 1 { buf.WriteByte(',') } diff --git a/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/bsoncore.go b/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/bsoncore.go index 17aad6d71e..88133293ea 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/bsoncore.go +++ b/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/bsoncore.go @@ -4,25 +4,6 @@ // 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 -// Package bsoncore contains functions that can be used to encode and decode BSON -// elements and values to or from a slice of bytes. These functions are aimed at -// allowing low level manipulation of BSON and can be used to build a higher -// level BSON library. -// -// The Read* functions within this package return the values of the element and -// a boolean indicating if the values are valid. A boolean was used instead of -// an error because any error that would be returned would be the same: not -// enough bytes. This library attempts to do no validation, it will only return -// false if there are not enough bytes for an item to be read. For example, the -// ReadDocument function checks the length, if that length is larger than the -// number of bytes available, it will return false, if there are enough bytes, it -// will return those bytes and true. It is the consumers responsibility to -// validate those bytes. -// -// The Append* functions within this package will append the type value to the -// given dst slice. If the slice has enough capacity, it will not grow the -// slice. The Append*Element functions within this package operate in the same -// way, but additionally append the BSON type and the key before the value. package bsoncore // import "go.mongodb.org/mongo-driver/x/bsonx/bsoncore" import ( @@ -254,7 +235,7 @@ func BuildDocumentValue(elems ...[]byte) Value { return Value{Type: bsontype.EmbeddedDocument, Data: BuildDocument(nil, elems...)} } -// BuildDocumentElement will append a BSON embedded document elemnt using key and the provided +// BuildDocumentElement will append a BSON embedded document element using key and the provided // elements and return the extended buffer. func BuildDocumentElement(dst []byte, key string, elems ...[]byte) []byte { return BuildDocument(AppendHeader(dst, bsontype.EmbeddedDocument, key), elems...) @@ -844,6 +825,9 @@ func readLengthBytes(src []byte) ([]byte, []byte, bool) { if !ok { return nil, src, false } + if l < 4 { + return nil, src, false + } if len(src) < int(l) { return nil, src, false } diff --git a/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/doc.go b/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/doc.go new file mode 100644 index 0000000000..6837b53fc5 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/doc.go @@ -0,0 +1,29 @@ +// Copyright (C) MongoDB, Inc. 2022-present. +// +// 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 + +// Package bsoncore contains functions that can be used to encode and decode BSON +// elements and values to or from a slice of bytes. These functions are aimed at +// allowing low level manipulation of BSON and can be used to build a higher +// level BSON library. +// +// The Read* functions within this package return the values of the element and +// a boolean indicating if the values are valid. A boolean was used instead of +// an error because any error that would be returned would be the same: not +// enough bytes. This library attempts to do no validation, it will only return +// false if there are not enough bytes for an item to be read. For example, the +// ReadDocument function checks the length, if that length is larger than the +// number of bytes available, it will return false, if there are enough bytes, it +// will return those bytes and true. It is the consumers responsibility to +// validate those bytes. +// +// The Append* functions within this package will append the type value to the +// given dst slice. If the slice has enough capacity, it will not grow the +// slice. The Append*Element functions within this package operate in the same +// way, but additionally append the BSON type and the key before the value. +// +// Warning: Package bsoncore is unstable and there is no backward compatibility +// guarantee. It is experimental and subject to change. +package bsoncore diff --git a/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/document.go b/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/document.go index d6e4bb069f..3f360f1ae1 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/document.go +++ b/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/document.go @@ -7,11 +7,11 @@ package bsoncore import ( - "bytes" "errors" "fmt" "io" "strconv" + "strings" "go.mongodb.org/mongo-driver/bson/bsontype" ) @@ -237,7 +237,7 @@ func (d Document) DebugString() string { if len(d) < 5 { return "" } - var buf bytes.Buffer + var buf strings.Builder buf.WriteString("Document") length, rem, _ := ReadLength(d) // We know we have enough bytes to read the length buf.WriteByte('(') @@ -253,7 +253,7 @@ func (d Document) DebugString() string { buf.WriteString(fmt.Sprintf("", length)) break } - fmt.Fprintf(&buf, "%s ", elem.DebugString()) + buf.WriteString(elem.DebugString()) } buf.WriteByte('}') @@ -266,7 +266,7 @@ func (d Document) String() string { if len(d) < 5 { return "" } - var buf bytes.Buffer + var buf strings.Builder buf.WriteByte('{') length, rem, _ := ReadLength(d) // We know we have enough bytes to read the length @@ -285,7 +285,7 @@ func (d Document) String() string { if !ok { return "" } - fmt.Fprintf(&buf, "%s", elem.String()) + buf.WriteString(elem.String()) first = false } buf.WriteByte('}') diff --git a/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/element.go b/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/element.go index 3acb4222b2..1fe0897c91 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/element.go +++ b/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/element.go @@ -129,7 +129,7 @@ func (e Element) String() string { if !valid { return "" } - return fmt.Sprintf(`"%s": %v`, key, val) + return "\"" + string(key) + "\": " + val.String() } // DebugString outputs a human readable version of RawElement. It will attempt to stringify the diff --git a/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/value.go b/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/value.go index 789d2b9828..69c1f9edbb 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/value.go +++ b/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/value.go @@ -59,8 +59,6 @@ func (v Value) IsNumber() bool { // AsInt32 returns a BSON number as an int32. If the BSON type is not a numeric one, this method // will panic. -// -// TODO(skriptble): Add support for Decimal128. func (v Value) AsInt32() int32 { if !v.IsNumber() { panic(ElementTypeError{"bsoncore.Value.AsInt32", v.Type}) @@ -93,8 +91,6 @@ func (v Value) AsInt32() int32 { // AsInt32OK functions the same as AsInt32 but returns a boolean instead of panicking. False // indicates an error. -// -// TODO(skriptble): Add support for Decimal128. func (v Value) AsInt32OK() (int32, bool) { if !v.IsNumber() { return 0, false @@ -127,8 +123,6 @@ func (v Value) AsInt32OK() (int32, bool) { // AsInt64 returns a BSON number as an int64. If the BSON type is not a numeric one, this method // will panic. -// -// TODO(skriptble): Add support for Decimal128. func (v Value) AsInt64() int64 { if !v.IsNumber() { panic(ElementTypeError{"bsoncore.Value.AsInt64", v.Type}) @@ -162,8 +156,6 @@ func (v Value) AsInt64() int64 { // AsInt64OK functions the same as AsInt64 but returns a boolean instead of panicking. False // indicates an error. -// -// TODO(skriptble): Add support for Decimal128. func (v Value) AsInt64OK() (int64, bool) { if !v.IsNumber() { return 0, false @@ -198,21 +190,14 @@ func (v Value) AsInt64OK() (int64, bool) { // AsFloat64 returns a BSON number as an float64. If the BSON type is not a numeric one, this method // will panic. // -// TODO(skriptble): Add support for Decimal128. -func (v Value) AsFloat64() float64 { return 0 } +// TODO(GODRIVER-2751): Implement AsFloat64. +// func (v Value) AsFloat64() float64 // AsFloat64OK functions the same as AsFloat64 but returns a boolean instead of panicking. False // indicates an error. // -// TODO(skriptble): Add support for Decimal128. -func (v Value) AsFloat64OK() (float64, bool) { return 0, false } - -// Add will add this value to another. This is currently only implemented for strings and numbers. -// If either value is a string, the other type is coerced into a string and added to the other. -// -// This method will alter v and will attempt to reuse the []byte of v. If the []byte is too small, -// it will be expanded. -func (v *Value) Add(v2 Value) error { return nil } +// TODO(GODRIVER-2751): Implement AsFloat64OK. +// func (v Value) AsFloat64OK() (float64, bool) // Equal compaes v to v2 and returns true if they are equal. func (v Value) Equal(v2 Value) bool { diff --git a/vendor/golang.org/x/net/html/atom/atom.go b/vendor/golang.org/x/net/html/atom/atom.go new file mode 100644 index 0000000000..cd0a8ac154 --- /dev/null +++ b/vendor/golang.org/x/net/html/atom/atom.go @@ -0,0 +1,78 @@ +// Copyright 2012 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 atom provides integer codes (also known as atoms) for a fixed set of +// frequently occurring HTML strings: tag names and attribute keys such as "p" +// and "id". +// +// Sharing an atom's name between all elements with the same tag can result in +// fewer string allocations when tokenizing and parsing HTML. Integer +// comparisons are also generally faster than string comparisons. +// +// The value of an atom's particular code is not guaranteed to stay the same +// between versions of this package. Neither is any ordering guaranteed: +// whether atom.H1 < atom.H2 may also change. The codes are not guaranteed to +// be dense. The only guarantees are that e.g. looking up "div" will yield +// atom.Div, calling atom.Div.String will return "div", and atom.Div != 0. +package atom // import "golang.org/x/net/html/atom" + +// Atom is an integer code for a string. The zero value maps to "". +type Atom uint32 + +// String returns the atom's name. +func (a Atom) String() string { + start := uint32(a >> 8) + n := uint32(a & 0xff) + if start+n > uint32(len(atomText)) { + return "" + } + return atomText[start : start+n] +} + +func (a Atom) string() string { + return atomText[a>>8 : a>>8+a&0xff] +} + +// fnv computes the FNV hash with an arbitrary starting value h. +func fnv(h uint32, s []byte) uint32 { + for i := range s { + h ^= uint32(s[i]) + h *= 16777619 + } + return h +} + +func match(s string, t []byte) bool { + for i, c := range t { + if s[i] != c { + return false + } + } + return true +} + +// Lookup returns the atom whose name is s. It returns zero if there is no +// such atom. The lookup is case sensitive. +func Lookup(s []byte) Atom { + if len(s) == 0 || len(s) > maxAtomLen { + return 0 + } + h := fnv(hash0, s) + if a := table[h&uint32(len(table)-1)]; int(a&0xff) == len(s) && match(a.string(), s) { + return a + } + if a := table[(h>>16)&uint32(len(table)-1)]; int(a&0xff) == len(s) && match(a.string(), s) { + return a + } + return 0 +} + +// String returns a string whose contents are equal to s. In that sense, it is +// equivalent to string(s) but may be more efficient. +func String(s []byte) string { + if a := Lookup(s); a != 0 { + return a.String() + } + return string(s) +} diff --git a/vendor/golang.org/x/net/html/atom/table.go b/vendor/golang.org/x/net/html/atom/table.go new file mode 100644 index 0000000000..2a938864cb --- /dev/null +++ b/vendor/golang.org/x/net/html/atom/table.go @@ -0,0 +1,783 @@ +// Code generated by go generate gen.go; DO NOT EDIT. + +//go:generate go run gen.go + +package atom + +const ( + A Atom = 0x1 + Abbr Atom = 0x4 + Accept Atom = 0x1a06 + AcceptCharset Atom = 0x1a0e + Accesskey Atom = 0x2c09 + Acronym Atom = 0xaa07 + Action Atom = 0x27206 + Address Atom = 0x6f307 + Align Atom = 0xb105 + Allowfullscreen Atom = 0x2080f + Allowpaymentrequest Atom = 0xc113 + Allowusermedia Atom = 0xdd0e + Alt Atom = 0xf303 + Annotation Atom = 0x1c90a + AnnotationXml Atom = 0x1c90e + Applet Atom = 0x31906 + Area Atom = 0x35604 + Article Atom = 0x3fc07 + As Atom = 0x3c02 + Aside Atom = 0x10705 + Async Atom = 0xff05 + Audio Atom = 0x11505 + Autocomplete Atom = 0x2780c + Autofocus Atom = 0x12109 + Autoplay Atom = 0x13c08 + B Atom = 0x101 + Base Atom = 0x3b04 + Basefont Atom = 0x3b08 + Bdi Atom = 0xba03 + Bdo Atom = 0x14b03 + Bgsound Atom = 0x15e07 + Big Atom = 0x17003 + Blink Atom = 0x17305 + Blockquote Atom = 0x1870a + Body Atom = 0x2804 + Br Atom = 0x202 + Button Atom = 0x19106 + Canvas Atom = 0x10306 + Caption Atom = 0x23107 + Center Atom = 0x22006 + Challenge Atom = 0x29b09 + Charset Atom = 0x2107 + Checked Atom = 0x47907 + Cite Atom = 0x19c04 + Class Atom = 0x56405 + Code Atom = 0x5c504 + Col Atom = 0x1ab03 + Colgroup Atom = 0x1ab08 + Color Atom = 0x1bf05 + Cols Atom = 0x1c404 + Colspan Atom = 0x1c407 + Command Atom = 0x1d707 + Content Atom = 0x58b07 + Contenteditable Atom = 0x58b0f + Contextmenu Atom = 0x3800b + Controls Atom = 0x1de08 + Coords Atom = 0x1ea06 + Crossorigin Atom = 0x1fb0b + Data Atom = 0x4a504 + Datalist Atom = 0x4a508 + Datetime Atom = 0x2b808 + Dd Atom = 0x2d702 + Default Atom = 0x10a07 + Defer Atom = 0x5c705 + Del Atom = 0x45203 + Desc Atom = 0x56104 + Details Atom = 0x7207 + Dfn Atom = 0x8703 + Dialog Atom = 0xbb06 + Dir Atom = 0x9303 + Dirname Atom = 0x9307 + Disabled Atom = 0x16408 + Div Atom = 0x16b03 + Dl Atom = 0x5e602 + Download Atom = 0x46308 + Draggable Atom = 0x17a09 + Dropzone Atom = 0x40508 + Dt Atom = 0x64b02 + Em Atom = 0x6e02 + Embed Atom = 0x6e05 + Enctype Atom = 0x28d07 + Face Atom = 0x21e04 + Fieldset Atom = 0x22608 + Figcaption Atom = 0x22e0a + Figure Atom = 0x24806 + Font Atom = 0x3f04 + Footer Atom = 0xf606 + For Atom = 0x25403 + ForeignObject Atom = 0x2540d + Foreignobject Atom = 0x2610d + Form Atom = 0x26e04 + Formaction Atom = 0x26e0a + Formenctype Atom = 0x2890b + Formmethod Atom = 0x2a40a + Formnovalidate Atom = 0x2ae0e + Formtarget Atom = 0x2c00a + Frame Atom = 0x8b05 + Frameset Atom = 0x8b08 + H1 Atom = 0x15c02 + H2 Atom = 0x2de02 + H3 Atom = 0x30d02 + H4 Atom = 0x34502 + H5 Atom = 0x34f02 + H6 Atom = 0x64d02 + Head Atom = 0x33104 + Header Atom = 0x33106 + Headers Atom = 0x33107 + Height Atom = 0x5206 + Hgroup Atom = 0x2ca06 + Hidden Atom = 0x2d506 + High Atom = 0x2db04 + Hr Atom = 0x15702 + Href Atom = 0x2e004 + Hreflang Atom = 0x2e008 + Html Atom = 0x5604 + HttpEquiv Atom = 0x2e80a + I Atom = 0x601 + Icon Atom = 0x58a04 + Id Atom = 0x10902 + Iframe Atom = 0x2fc06 + Image Atom = 0x30205 + Img Atom = 0x30703 + Input Atom = 0x44b05 + Inputmode Atom = 0x44b09 + Ins Atom = 0x20403 + Integrity Atom = 0x23f09 + Is Atom = 0x16502 + Isindex Atom = 0x30f07 + Ismap Atom = 0x31605 + Itemid Atom = 0x38b06 + Itemprop Atom = 0x19d08 + Itemref Atom = 0x3cd07 + Itemscope Atom = 0x67109 + Itemtype Atom = 0x31f08 + Kbd Atom = 0xb903 + Keygen Atom = 0x3206 + Keytype Atom = 0xd607 + Kind Atom = 0x17704 + Label Atom = 0x5905 + Lang Atom = 0x2e404 + Legend Atom = 0x18106 + Li Atom = 0xb202 + Link Atom = 0x17404 + List Atom = 0x4a904 + Listing Atom = 0x4a907 + Loop Atom = 0x5d04 + Low Atom = 0xc303 + Main Atom = 0x1004 + Malignmark Atom = 0xb00a + Manifest Atom = 0x6d708 + Map Atom = 0x31803 + Mark Atom = 0xb604 + Marquee Atom = 0x32707 + Math Atom = 0x32e04 + Max Atom = 0x33d03 + Maxlength Atom = 0x33d09 + Media Atom = 0xe605 + Mediagroup Atom = 0xe60a + Menu Atom = 0x38704 + Menuitem Atom = 0x38708 + Meta Atom = 0x4b804 + Meter Atom = 0x9805 + Method Atom = 0x2a806 + Mglyph Atom = 0x30806 + Mi Atom = 0x34702 + Min Atom = 0x34703 + Minlength Atom = 0x34709 + Mn Atom = 0x2b102 + Mo Atom = 0xa402 + Ms Atom = 0x67402 + Mtext Atom = 0x35105 + Multiple Atom = 0x35f08 + Muted Atom = 0x36705 + Name Atom = 0x9604 + Nav Atom = 0x1303 + Nobr Atom = 0x3704 + Noembed Atom = 0x6c07 + Noframes Atom = 0x8908 + Nomodule Atom = 0xa208 + Nonce Atom = 0x1a605 + Noscript Atom = 0x21608 + Novalidate Atom = 0x2b20a + Object Atom = 0x26806 + Ol Atom = 0x13702 + Onabort Atom = 0x19507 + Onafterprint Atom = 0x2360c + Onautocomplete Atom = 0x2760e + Onautocompleteerror Atom = 0x27613 + Onauxclick Atom = 0x61f0a + Onbeforeprint Atom = 0x69e0d + Onbeforeunload Atom = 0x6e70e + Onblur Atom = 0x56d06 + Oncancel Atom = 0x11908 + Oncanplay Atom = 0x14d09 + Oncanplaythrough Atom = 0x14d10 + Onchange Atom = 0x41b08 + Onclick Atom = 0x2f507 + Onclose Atom = 0x36c07 + Oncontextmenu Atom = 0x37e0d + Oncopy Atom = 0x39106 + Oncuechange Atom = 0x3970b + Oncut Atom = 0x3a205 + Ondblclick Atom = 0x3a70a + Ondrag Atom = 0x3b106 + Ondragend Atom = 0x3b109 + Ondragenter Atom = 0x3ba0b + Ondragexit Atom = 0x3c50a + Ondragleave Atom = 0x3df0b + Ondragover Atom = 0x3ea0a + Ondragstart Atom = 0x3f40b + Ondrop Atom = 0x40306 + Ondurationchange Atom = 0x41310 + Onemptied Atom = 0x40a09 + Onended Atom = 0x42307 + Onerror Atom = 0x42a07 + Onfocus Atom = 0x43107 + Onhashchange Atom = 0x43d0c + Oninput Atom = 0x44907 + Oninvalid Atom = 0x45509 + Onkeydown Atom = 0x45e09 + Onkeypress Atom = 0x46b0a + Onkeyup Atom = 0x48007 + Onlanguagechange Atom = 0x48d10 + Onload Atom = 0x49d06 + Onloadeddata Atom = 0x49d0c + Onloadedmetadata Atom = 0x4b010 + Onloadend Atom = 0x4c609 + Onloadstart Atom = 0x4cf0b + Onmessage Atom = 0x4da09 + Onmessageerror Atom = 0x4da0e + Onmousedown Atom = 0x4e80b + Onmouseenter Atom = 0x4f30c + Onmouseleave Atom = 0x4ff0c + Onmousemove Atom = 0x50b0b + Onmouseout Atom = 0x5160a + Onmouseover Atom = 0x5230b + Onmouseup Atom = 0x52e09 + Onmousewheel Atom = 0x53c0c + Onoffline Atom = 0x54809 + Ononline Atom = 0x55108 + Onpagehide Atom = 0x5590a + Onpageshow Atom = 0x5730a + Onpaste Atom = 0x57f07 + Onpause Atom = 0x59a07 + Onplay Atom = 0x5a406 + Onplaying Atom = 0x5a409 + Onpopstate Atom = 0x5ad0a + Onprogress Atom = 0x5b70a + Onratechange Atom = 0x5cc0c + Onrejectionhandled Atom = 0x5d812 + Onreset Atom = 0x5ea07 + Onresize Atom = 0x5f108 + Onscroll Atom = 0x60008 + Onsecuritypolicyviolation Atom = 0x60819 + Onseeked Atom = 0x62908 + Onseeking Atom = 0x63109 + Onselect Atom = 0x63a08 + Onshow Atom = 0x64406 + Onsort Atom = 0x64f06 + Onstalled Atom = 0x65909 + Onstorage Atom = 0x66209 + Onsubmit Atom = 0x66b08 + Onsuspend Atom = 0x67b09 + Ontimeupdate Atom = 0x400c + Ontoggle Atom = 0x68408 + Onunhandledrejection Atom = 0x68c14 + Onunload Atom = 0x6ab08 + Onvolumechange Atom = 0x6b30e + Onwaiting Atom = 0x6c109 + Onwheel Atom = 0x6ca07 + Open Atom = 0x1a304 + Optgroup Atom = 0x5f08 + Optimum Atom = 0x6d107 + Option Atom = 0x6e306 + Output Atom = 0x51d06 + P Atom = 0xc01 + Param Atom = 0xc05 + Pattern Atom = 0x6607 + Picture Atom = 0x7b07 + Ping Atom = 0xef04 + Placeholder Atom = 0x1310b + Plaintext Atom = 0x1b209 + Playsinline Atom = 0x1400b + Poster Atom = 0x2cf06 + Pre Atom = 0x47003 + Preload Atom = 0x48607 + Progress Atom = 0x5b908 + Prompt Atom = 0x53606 + Public Atom = 0x58606 + Q Atom = 0xcf01 + Radiogroup Atom = 0x30a + Rb Atom = 0x3a02 + Readonly Atom = 0x35708 + Referrerpolicy Atom = 0x3d10e + Rel Atom = 0x48703 + Required Atom = 0x24c08 + Reversed Atom = 0x8008 + Rows Atom = 0x9c04 + Rowspan Atom = 0x9c07 + Rp Atom = 0x23c02 + Rt Atom = 0x19a02 + Rtc Atom = 0x19a03 + Ruby Atom = 0xfb04 + S Atom = 0x2501 + Samp Atom = 0x7804 + Sandbox Atom = 0x12907 + Scope Atom = 0x67505 + Scoped Atom = 0x67506 + Script Atom = 0x21806 + Seamless Atom = 0x37108 + Section Atom = 0x56807 + Select Atom = 0x63c06 + Selected Atom = 0x63c08 + Shape Atom = 0x1e505 + Size Atom = 0x5f504 + Sizes Atom = 0x5f505 + Slot Atom = 0x1ef04 + Small Atom = 0x20605 + Sortable Atom = 0x65108 + Sorted Atom = 0x33706 + Source Atom = 0x37806 + Spacer Atom = 0x43706 + Span Atom = 0x9f04 + Spellcheck Atom = 0x4740a + Src Atom = 0x5c003 + Srcdoc Atom = 0x5c006 + Srclang Atom = 0x5f907 + Srcset Atom = 0x6f906 + Start Atom = 0x3fa05 + Step Atom = 0x58304 + Strike Atom = 0xd206 + Strong Atom = 0x6dd06 + Style Atom = 0x6ff05 + Sub Atom = 0x66d03 + Summary Atom = 0x70407 + Sup Atom = 0x70b03 + Svg Atom = 0x70e03 + System Atom = 0x71106 + Tabindex Atom = 0x4be08 + Table Atom = 0x59505 + Target Atom = 0x2c406 + Tbody Atom = 0x2705 + Td Atom = 0x9202 + Template Atom = 0x71408 + Textarea Atom = 0x35208 + Tfoot Atom = 0xf505 + Th Atom = 0x15602 + Thead Atom = 0x33005 + Time Atom = 0x4204 + Title Atom = 0x11005 + Tr Atom = 0xcc02 + Track Atom = 0x1ba05 + Translate Atom = 0x1f209 + Tt Atom = 0x6802 + Type Atom = 0xd904 + Typemustmatch Atom = 0x2900d + U Atom = 0xb01 + Ul Atom = 0xa702 + Updateviacache Atom = 0x460e + Usemap Atom = 0x59e06 + Value Atom = 0x1505 + Var Atom = 0x16d03 + Video Atom = 0x2f105 + Wbr Atom = 0x57c03 + Width Atom = 0x64905 + Workertype Atom = 0x71c0a + Wrap Atom = 0x72604 + Xmp Atom = 0x12f03 +) + +const hash0 = 0x81cdf10e + +const maxAtomLen = 25 + +var table = [1 << 9]Atom{ + 0x1: 0xe60a, // mediagroup + 0x2: 0x2e404, // lang + 0x4: 0x2c09, // accesskey + 0x5: 0x8b08, // frameset + 0x7: 0x63a08, // onselect + 0x8: 0x71106, // system + 0xa: 0x64905, // width + 0xc: 0x2890b, // formenctype + 0xd: 0x13702, // ol + 0xe: 0x3970b, // oncuechange + 0x10: 0x14b03, // bdo + 0x11: 0x11505, // audio + 0x12: 0x17a09, // draggable + 0x14: 0x2f105, // video + 0x15: 0x2b102, // mn + 0x16: 0x38704, // menu + 0x17: 0x2cf06, // poster + 0x19: 0xf606, // footer + 0x1a: 0x2a806, // method + 0x1b: 0x2b808, // datetime + 0x1c: 0x19507, // onabort + 0x1d: 0x460e, // updateviacache + 0x1e: 0xff05, // async + 0x1f: 0x49d06, // onload + 0x21: 0x11908, // oncancel + 0x22: 0x62908, // onseeked + 0x23: 0x30205, // image + 0x24: 0x5d812, // onrejectionhandled + 0x26: 0x17404, // link + 0x27: 0x51d06, // output + 0x28: 0x33104, // head + 0x29: 0x4ff0c, // onmouseleave + 0x2a: 0x57f07, // onpaste + 0x2b: 0x5a409, // onplaying + 0x2c: 0x1c407, // colspan + 0x2f: 0x1bf05, // color + 0x30: 0x5f504, // size + 0x31: 0x2e80a, // http-equiv + 0x33: 0x601, // i + 0x34: 0x5590a, // onpagehide + 0x35: 0x68c14, // onunhandledrejection + 0x37: 0x42a07, // onerror + 0x3a: 0x3b08, // basefont + 0x3f: 0x1303, // nav + 0x40: 0x17704, // kind + 0x41: 0x35708, // readonly + 0x42: 0x30806, // mglyph + 0x44: 0xb202, // li + 0x46: 0x2d506, // hidden + 0x47: 0x70e03, // svg + 0x48: 0x58304, // step + 0x49: 0x23f09, // integrity + 0x4a: 0x58606, // public + 0x4c: 0x1ab03, // col + 0x4d: 0x1870a, // blockquote + 0x4e: 0x34f02, // h5 + 0x50: 0x5b908, // progress + 0x51: 0x5f505, // sizes + 0x52: 0x34502, // h4 + 0x56: 0x33005, // thead + 0x57: 0xd607, // keytype + 0x58: 0x5b70a, // onprogress + 0x59: 0x44b09, // inputmode + 0x5a: 0x3b109, // ondragend + 0x5d: 0x3a205, // oncut + 0x5e: 0x43706, // spacer + 0x5f: 0x1ab08, // colgroup + 0x62: 0x16502, // is + 0x65: 0x3c02, // as + 0x66: 0x54809, // onoffline + 0x67: 0x33706, // sorted + 0x69: 0x48d10, // onlanguagechange + 0x6c: 0x43d0c, // onhashchange + 0x6d: 0x9604, // name + 0x6e: 0xf505, // tfoot + 0x6f: 0x56104, // desc + 0x70: 0x33d03, // max + 0x72: 0x1ea06, // coords + 0x73: 0x30d02, // h3 + 0x74: 0x6e70e, // onbeforeunload + 0x75: 0x9c04, // rows + 0x76: 0x63c06, // select + 0x77: 0x9805, // meter + 0x78: 0x38b06, // itemid + 0x79: 0x53c0c, // onmousewheel + 0x7a: 0x5c006, // srcdoc + 0x7d: 0x1ba05, // track + 0x7f: 0x31f08, // itemtype + 0x82: 0xa402, // mo + 0x83: 0x41b08, // onchange + 0x84: 0x33107, // headers + 0x85: 0x5cc0c, // onratechange + 0x86: 0x60819, // onsecuritypolicyviolation + 0x88: 0x4a508, // datalist + 0x89: 0x4e80b, // onmousedown + 0x8a: 0x1ef04, // slot + 0x8b: 0x4b010, // onloadedmetadata + 0x8c: 0x1a06, // accept + 0x8d: 0x26806, // object + 0x91: 0x6b30e, // onvolumechange + 0x92: 0x2107, // charset + 0x93: 0x27613, // onautocompleteerror + 0x94: 0xc113, // allowpaymentrequest + 0x95: 0x2804, // body + 0x96: 0x10a07, // default + 0x97: 0x63c08, // selected + 0x98: 0x21e04, // face + 0x99: 0x1e505, // shape + 0x9b: 0x68408, // ontoggle + 0x9e: 0x64b02, // dt + 0x9f: 0xb604, // mark + 0xa1: 0xb01, // u + 0xa4: 0x6ab08, // onunload + 0xa5: 0x5d04, // loop + 0xa6: 0x16408, // disabled + 0xaa: 0x42307, // onended + 0xab: 0xb00a, // malignmark + 0xad: 0x67b09, // onsuspend + 0xae: 0x35105, // mtext + 0xaf: 0x64f06, // onsort + 0xb0: 0x19d08, // itemprop + 0xb3: 0x67109, // itemscope + 0xb4: 0x17305, // blink + 0xb6: 0x3b106, // ondrag + 0xb7: 0xa702, // ul + 0xb8: 0x26e04, // form + 0xb9: 0x12907, // sandbox + 0xba: 0x8b05, // frame + 0xbb: 0x1505, // value + 0xbc: 0x66209, // onstorage + 0xbf: 0xaa07, // acronym + 0xc0: 0x19a02, // rt + 0xc2: 0x202, // br + 0xc3: 0x22608, // fieldset + 0xc4: 0x2900d, // typemustmatch + 0xc5: 0xa208, // nomodule + 0xc6: 0x6c07, // noembed + 0xc7: 0x69e0d, // onbeforeprint + 0xc8: 0x19106, // button + 0xc9: 0x2f507, // onclick + 0xca: 0x70407, // summary + 0xcd: 0xfb04, // ruby + 0xce: 0x56405, // class + 0xcf: 0x3f40b, // ondragstart + 0xd0: 0x23107, // caption + 0xd4: 0xdd0e, // allowusermedia + 0xd5: 0x4cf0b, // onloadstart + 0xd9: 0x16b03, // div + 0xda: 0x4a904, // list + 0xdb: 0x32e04, // math + 0xdc: 0x44b05, // input + 0xdf: 0x3ea0a, // ondragover + 0xe0: 0x2de02, // h2 + 0xe2: 0x1b209, // plaintext + 0xe4: 0x4f30c, // onmouseenter + 0xe7: 0x47907, // checked + 0xe8: 0x47003, // pre + 0xea: 0x35f08, // multiple + 0xeb: 0xba03, // bdi + 0xec: 0x33d09, // maxlength + 0xed: 0xcf01, // q + 0xee: 0x61f0a, // onauxclick + 0xf0: 0x57c03, // wbr + 0xf2: 0x3b04, // base + 0xf3: 0x6e306, // option + 0xf5: 0x41310, // ondurationchange + 0xf7: 0x8908, // noframes + 0xf9: 0x40508, // dropzone + 0xfb: 0x67505, // scope + 0xfc: 0x8008, // reversed + 0xfd: 0x3ba0b, // ondragenter + 0xfe: 0x3fa05, // start + 0xff: 0x12f03, // xmp + 0x100: 0x5f907, // srclang + 0x101: 0x30703, // img + 0x104: 0x101, // b + 0x105: 0x25403, // for + 0x106: 0x10705, // aside + 0x107: 0x44907, // oninput + 0x108: 0x35604, // area + 0x109: 0x2a40a, // formmethod + 0x10a: 0x72604, // wrap + 0x10c: 0x23c02, // rp + 0x10d: 0x46b0a, // onkeypress + 0x10e: 0x6802, // tt + 0x110: 0x34702, // mi + 0x111: 0x36705, // muted + 0x112: 0xf303, // alt + 0x113: 0x5c504, // code + 0x114: 0x6e02, // em + 0x115: 0x3c50a, // ondragexit + 0x117: 0x9f04, // span + 0x119: 0x6d708, // manifest + 0x11a: 0x38708, // menuitem + 0x11b: 0x58b07, // content + 0x11d: 0x6c109, // onwaiting + 0x11f: 0x4c609, // onloadend + 0x121: 0x37e0d, // oncontextmenu + 0x123: 0x56d06, // onblur + 0x124: 0x3fc07, // article + 0x125: 0x9303, // dir + 0x126: 0xef04, // ping + 0x127: 0x24c08, // required + 0x128: 0x45509, // oninvalid + 0x129: 0xb105, // align + 0x12b: 0x58a04, // icon + 0x12c: 0x64d02, // h6 + 0x12d: 0x1c404, // cols + 0x12e: 0x22e0a, // figcaption + 0x12f: 0x45e09, // onkeydown + 0x130: 0x66b08, // onsubmit + 0x131: 0x14d09, // oncanplay + 0x132: 0x70b03, // sup + 0x133: 0xc01, // p + 0x135: 0x40a09, // onemptied + 0x136: 0x39106, // oncopy + 0x137: 0x19c04, // cite + 0x138: 0x3a70a, // ondblclick + 0x13a: 0x50b0b, // onmousemove + 0x13c: 0x66d03, // sub + 0x13d: 0x48703, // rel + 0x13e: 0x5f08, // optgroup + 0x142: 0x9c07, // rowspan + 0x143: 0x37806, // source + 0x144: 0x21608, // noscript + 0x145: 0x1a304, // open + 0x146: 0x20403, // ins + 0x147: 0x2540d, // foreignObject + 0x148: 0x5ad0a, // onpopstate + 0x14a: 0x28d07, // enctype + 0x14b: 0x2760e, // onautocomplete + 0x14c: 0x35208, // textarea + 0x14e: 0x2780c, // autocomplete + 0x14f: 0x15702, // hr + 0x150: 0x1de08, // controls + 0x151: 0x10902, // id + 0x153: 0x2360c, // onafterprint + 0x155: 0x2610d, // foreignobject + 0x156: 0x32707, // marquee + 0x157: 0x59a07, // onpause + 0x158: 0x5e602, // dl + 0x159: 0x5206, // height + 0x15a: 0x34703, // min + 0x15b: 0x9307, // dirname + 0x15c: 0x1f209, // translate + 0x15d: 0x5604, // html + 0x15e: 0x34709, // minlength + 0x15f: 0x48607, // preload + 0x160: 0x71408, // template + 0x161: 0x3df0b, // ondragleave + 0x162: 0x3a02, // rb + 0x164: 0x5c003, // src + 0x165: 0x6dd06, // strong + 0x167: 0x7804, // samp + 0x168: 0x6f307, // address + 0x169: 0x55108, // ononline + 0x16b: 0x1310b, // placeholder + 0x16c: 0x2c406, // target + 0x16d: 0x20605, // small + 0x16e: 0x6ca07, // onwheel + 0x16f: 0x1c90a, // annotation + 0x170: 0x4740a, // spellcheck + 0x171: 0x7207, // details + 0x172: 0x10306, // canvas + 0x173: 0x12109, // autofocus + 0x174: 0xc05, // param + 0x176: 0x46308, // download + 0x177: 0x45203, // del + 0x178: 0x36c07, // onclose + 0x179: 0xb903, // kbd + 0x17a: 0x31906, // applet + 0x17b: 0x2e004, // href + 0x17c: 0x5f108, // onresize + 0x17e: 0x49d0c, // onloadeddata + 0x180: 0xcc02, // tr + 0x181: 0x2c00a, // formtarget + 0x182: 0x11005, // title + 0x183: 0x6ff05, // style + 0x184: 0xd206, // strike + 0x185: 0x59e06, // usemap + 0x186: 0x2fc06, // iframe + 0x187: 0x1004, // main + 0x189: 0x7b07, // picture + 0x18c: 0x31605, // ismap + 0x18e: 0x4a504, // data + 0x18f: 0x5905, // label + 0x191: 0x3d10e, // referrerpolicy + 0x192: 0x15602, // th + 0x194: 0x53606, // prompt + 0x195: 0x56807, // section + 0x197: 0x6d107, // optimum + 0x198: 0x2db04, // high + 0x199: 0x15c02, // h1 + 0x19a: 0x65909, // onstalled + 0x19b: 0x16d03, // var + 0x19c: 0x4204, // time + 0x19e: 0x67402, // ms + 0x19f: 0x33106, // header + 0x1a0: 0x4da09, // onmessage + 0x1a1: 0x1a605, // nonce + 0x1a2: 0x26e0a, // formaction + 0x1a3: 0x22006, // center + 0x1a4: 0x3704, // nobr + 0x1a5: 0x59505, // table + 0x1a6: 0x4a907, // listing + 0x1a7: 0x18106, // legend + 0x1a9: 0x29b09, // challenge + 0x1aa: 0x24806, // figure + 0x1ab: 0xe605, // media + 0x1ae: 0xd904, // type + 0x1af: 0x3f04, // font + 0x1b0: 0x4da0e, // onmessageerror + 0x1b1: 0x37108, // seamless + 0x1b2: 0x8703, // dfn + 0x1b3: 0x5c705, // defer + 0x1b4: 0xc303, // low + 0x1b5: 0x19a03, // rtc + 0x1b6: 0x5230b, // onmouseover + 0x1b7: 0x2b20a, // novalidate + 0x1b8: 0x71c0a, // workertype + 0x1ba: 0x3cd07, // itemref + 0x1bd: 0x1, // a + 0x1be: 0x31803, // map + 0x1bf: 0x400c, // ontimeupdate + 0x1c0: 0x15e07, // bgsound + 0x1c1: 0x3206, // keygen + 0x1c2: 0x2705, // tbody + 0x1c5: 0x64406, // onshow + 0x1c7: 0x2501, // s + 0x1c8: 0x6607, // pattern + 0x1cc: 0x14d10, // oncanplaythrough + 0x1ce: 0x2d702, // dd + 0x1cf: 0x6f906, // srcset + 0x1d0: 0x17003, // big + 0x1d2: 0x65108, // sortable + 0x1d3: 0x48007, // onkeyup + 0x1d5: 0x5a406, // onplay + 0x1d7: 0x4b804, // meta + 0x1d8: 0x40306, // ondrop + 0x1da: 0x60008, // onscroll + 0x1db: 0x1fb0b, // crossorigin + 0x1dc: 0x5730a, // onpageshow + 0x1dd: 0x4, // abbr + 0x1de: 0x9202, // td + 0x1df: 0x58b0f, // contenteditable + 0x1e0: 0x27206, // action + 0x1e1: 0x1400b, // playsinline + 0x1e2: 0x43107, // onfocus + 0x1e3: 0x2e008, // hreflang + 0x1e5: 0x5160a, // onmouseout + 0x1e6: 0x5ea07, // onreset + 0x1e7: 0x13c08, // autoplay + 0x1e8: 0x63109, // onseeking + 0x1ea: 0x67506, // scoped + 0x1ec: 0x30a, // radiogroup + 0x1ee: 0x3800b, // contextmenu + 0x1ef: 0x52e09, // onmouseup + 0x1f1: 0x2ca06, // hgroup + 0x1f2: 0x2080f, // allowfullscreen + 0x1f3: 0x4be08, // tabindex + 0x1f6: 0x30f07, // isindex + 0x1f7: 0x1a0e, // accept-charset + 0x1f8: 0x2ae0e, // formnovalidate + 0x1fb: 0x1c90e, // annotation-xml + 0x1fc: 0x6e05, // embed + 0x1fd: 0x21806, // script + 0x1fe: 0xbb06, // dialog + 0x1ff: 0x1d707, // command +} + +const atomText = "abbradiogrouparamainavalueaccept-charsetbodyaccesskeygenobrb" + + "asefontimeupdateviacacheightmlabelooptgroupatternoembedetail" + + "sampictureversedfnoframesetdirnameterowspanomoduleacronymali" + + "gnmarkbdialogallowpaymentrequestrikeytypeallowusermediagroup" + + "ingaltfooterubyasyncanvasidefaultitleaudioncancelautofocusan" + + "dboxmplaceholderautoplaysinlinebdoncanplaythrough1bgsoundisa" + + "bledivarbigblinkindraggablegendblockquotebuttonabortcitempro" + + "penoncecolgrouplaintextrackcolorcolspannotation-xmlcommandco" + + "ntrolshapecoordslotranslatecrossoriginsmallowfullscreenoscri" + + "ptfacenterfieldsetfigcaptionafterprintegrityfigurequiredfore" + + "ignObjectforeignobjectformactionautocompleteerrorformenctype" + + "mustmatchallengeformmethodformnovalidatetimeformtargethgroup" + + "osterhiddenhigh2hreflanghttp-equivideonclickiframeimageimgly" + + "ph3isindexismappletitemtypemarqueematheadersortedmaxlength4m" + + "inlength5mtextareadonlymultiplemutedoncloseamlessourceoncont" + + "extmenuitemidoncopyoncuechangeoncutondblclickondragendondrag" + + "enterondragexitemreferrerpolicyondragleaveondragoverondragst" + + "articleondropzonemptiedondurationchangeonendedonerroronfocus" + + "paceronhashchangeoninputmodeloninvalidonkeydownloadonkeypres" + + "spellcheckedonkeyupreloadonlanguagechangeonloadeddatalisting" + + "onloadedmetadatabindexonloadendonloadstartonmessageerroronmo" + + "usedownonmouseenteronmouseleaveonmousemoveonmouseoutputonmou" + + "seoveronmouseupromptonmousewheelonofflineononlineonpagehides" + + "classectionbluronpageshowbronpastepublicontenteditableonpaus" + + "emaponplayingonpopstateonprogressrcdocodeferonratechangeonre" + + "jectionhandledonresetonresizesrclangonscrollonsecuritypolicy" + + "violationauxclickonseekedonseekingonselectedonshowidth6onsor" + + "tableonstalledonstorageonsubmitemscopedonsuspendontoggleonun" + + "handledrejectionbeforeprintonunloadonvolumechangeonwaitingon" + + "wheeloptimumanifestrongoptionbeforeunloaddressrcsetstylesumm" + + "arysupsvgsystemplateworkertypewrap" diff --git a/vendor/golang.org/x/net/html/const.go b/vendor/golang.org/x/net/html/const.go new file mode 100644 index 0000000000..ff7acf2d5b --- /dev/null +++ b/vendor/golang.org/x/net/html/const.go @@ -0,0 +1,111 @@ +// Copyright 2011 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 html + +// Section 12.2.4.2 of the HTML5 specification says "The following elements +// have varying levels of special parsing rules". +// https://html.spec.whatwg.org/multipage/syntax.html#the-stack-of-open-elements +var isSpecialElementMap = map[string]bool{ + "address": true, + "applet": true, + "area": true, + "article": true, + "aside": true, + "base": true, + "basefont": true, + "bgsound": true, + "blockquote": true, + "body": true, + "br": true, + "button": true, + "caption": true, + "center": true, + "col": true, + "colgroup": true, + "dd": true, + "details": true, + "dir": true, + "div": true, + "dl": true, + "dt": true, + "embed": true, + "fieldset": true, + "figcaption": true, + "figure": true, + "footer": true, + "form": true, + "frame": true, + "frameset": true, + "h1": true, + "h2": true, + "h3": true, + "h4": true, + "h5": true, + "h6": true, + "head": true, + "header": true, + "hgroup": true, + "hr": true, + "html": true, + "iframe": true, + "img": true, + "input": true, + "keygen": true, // "keygen" has been removed from the spec, but are kept here for backwards compatibility. + "li": true, + "link": true, + "listing": true, + "main": true, + "marquee": true, + "menu": true, + "meta": true, + "nav": true, + "noembed": true, + "noframes": true, + "noscript": true, + "object": true, + "ol": true, + "p": true, + "param": true, + "plaintext": true, + "pre": true, + "script": true, + "section": true, + "select": true, + "source": true, + "style": true, + "summary": true, + "table": true, + "tbody": true, + "td": true, + "template": true, + "textarea": true, + "tfoot": true, + "th": true, + "thead": true, + "title": true, + "tr": true, + "track": true, + "ul": true, + "wbr": true, + "xmp": true, +} + +func isSpecialElement(element *Node) bool { + switch element.Namespace { + case "", "html": + return isSpecialElementMap[element.Data] + case "math": + switch element.Data { + case "mi", "mo", "mn", "ms", "mtext", "annotation-xml": + return true + } + case "svg": + switch element.Data { + case "foreignObject", "desc", "title": + return true + } + } + return false +} diff --git a/vendor/golang.org/x/net/html/doc.go b/vendor/golang.org/x/net/html/doc.go new file mode 100644 index 0000000000..3a7e5ab176 --- /dev/null +++ b/vendor/golang.org/x/net/html/doc.go @@ -0,0 +1,127 @@ +// Copyright 2010 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 html implements an HTML5-compliant tokenizer and parser. + +Tokenization is done by creating a Tokenizer for an io.Reader r. It is the +caller's responsibility to ensure that r provides UTF-8 encoded HTML. + + z := html.NewTokenizer(r) + +Given a Tokenizer z, the HTML is tokenized by repeatedly calling z.Next(), +which parses the next token and returns its type, or an error: + + for { + tt := z.Next() + if tt == html.ErrorToken { + // ... + return ... + } + // Process the current token. + } + +There are two APIs for retrieving the current token. The high-level API is to +call Token; the low-level API is to call Text or TagName / TagAttr. Both APIs +allow optionally calling Raw after Next but before Token, Text, TagName, or +TagAttr. In EBNF notation, the valid call sequence per token is: + + Next {Raw} [ Token | Text | TagName {TagAttr} ] + +Token returns an independent data structure that completely describes a token. +Entities (such as "<") are unescaped, tag names and attribute keys are +lower-cased, and attributes are collected into a []Attribute. For example: + + for { + if z.Next() == html.ErrorToken { + // Returning io.EOF indicates success. + return z.Err() + } + emitToken(z.Token()) + } + +The low-level API performs fewer allocations and copies, but the contents of +the []byte values returned by Text, TagName and TagAttr may change on the next +call to Next. For example, to extract an HTML page's anchor text: + + depth := 0 + for { + tt := z.Next() + switch tt { + case html.ErrorToken: + return z.Err() + case html.TextToken: + if depth > 0 { + // emitBytes should copy the []byte it receives, + // if it doesn't process it immediately. + emitBytes(z.Text()) + } + case html.StartTagToken, html.EndTagToken: + tn, _ := z.TagName() + if len(tn) == 1 && tn[0] == 'a' { + if tt == html.StartTagToken { + depth++ + } else { + depth-- + } + } + } + } + +Parsing is done by calling Parse with an io.Reader, which returns the root of +the parse tree (the document element) as a *Node. It is the caller's +responsibility to ensure that the Reader provides UTF-8 encoded HTML. For +example, to process each anchor node in depth-first order: + + doc, err := html.Parse(r) + if err != nil { + // ... + } + var f func(*html.Node) + f = func(n *html.Node) { + if n.Type == html.ElementNode && n.Data == "a" { + // Do something with n... + } + for c := n.FirstChild; c != nil; c = c.NextSibling { + f(c) + } + } + f(doc) + +The relevant specifications include: +https://html.spec.whatwg.org/multipage/syntax.html and +https://html.spec.whatwg.org/multipage/syntax.html#tokenization + +# Security Considerations + +Care should be taken when parsing and interpreting HTML, whether full documents +or fragments, within the framework of the HTML specification, especially with +regard to untrusted inputs. + +This package provides both a tokenizer and a parser, which implement the +tokenization, and tokenization and tree construction stages of the WHATWG HTML +parsing specification respectively. While the tokenizer parses and normalizes +individual HTML tokens, only the parser constructs the DOM tree from the +tokenized HTML, as described in the tree construction stage of the +specification, dynamically modifying or extending the document's DOM tree. + +If your use case requires semantically well-formed HTML documents, as defined by +the WHATWG specification, the parser should be used rather than the tokenizer. + +In security contexts, if trust decisions are being made using the tokenized or +parsed content, the input must be re-serialized (for instance by using Render or +Token.String) in order for those trust decisions to hold, as the process of +tokenization or parsing may alter the content. +*/ +package html // import "golang.org/x/net/html" + +// The tokenization algorithm implemented by this package is not a line-by-line +// transliteration of the relatively verbose state-machine in the WHATWG +// specification. A more direct approach is used instead, where the program +// counter implies the state, such as whether it is tokenizing a tag or a text +// node. Specification compliance is verified by checking expected and actual +// outputs over a test suite rather than aiming for algorithmic fidelity. + +// TODO(nigeltao): Does a DOM API belong in this package or a separate one? +// TODO(nigeltao): How does parsing interact with a JavaScript engine? diff --git a/vendor/golang.org/x/net/html/doctype.go b/vendor/golang.org/x/net/html/doctype.go new file mode 100644 index 0000000000..c484e5a94f --- /dev/null +++ b/vendor/golang.org/x/net/html/doctype.go @@ -0,0 +1,156 @@ +// Copyright 2011 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 html + +import ( + "strings" +) + +// parseDoctype parses the data from a DoctypeToken into a name, +// public identifier, and system identifier. It returns a Node whose Type +// is DoctypeNode, whose Data is the name, and which has attributes +// named "system" and "public" for the two identifiers if they were present. +// quirks is whether the document should be parsed in "quirks mode". +func parseDoctype(s string) (n *Node, quirks bool) { + n = &Node{Type: DoctypeNode} + + // Find the name. + space := strings.IndexAny(s, whitespace) + if space == -1 { + space = len(s) + } + n.Data = s[:space] + // The comparison to "html" is case-sensitive. + if n.Data != "html" { + quirks = true + } + n.Data = strings.ToLower(n.Data) + s = strings.TrimLeft(s[space:], whitespace) + + if len(s) < 6 { + // It can't start with "PUBLIC" or "SYSTEM". + // Ignore the rest of the string. + return n, quirks || s != "" + } + + key := strings.ToLower(s[:6]) + s = s[6:] + for key == "public" || key == "system" { + s = strings.TrimLeft(s, whitespace) + if s == "" { + break + } + quote := s[0] + if quote != '"' && quote != '\'' { + break + } + s = s[1:] + q := strings.IndexRune(s, rune(quote)) + var id string + if q == -1 { + id = s + s = "" + } else { + id = s[:q] + s = s[q+1:] + } + n.Attr = append(n.Attr, Attribute{Key: key, Val: id}) + if key == "public" { + key = "system" + } else { + key = "" + } + } + + if key != "" || s != "" { + quirks = true + } else if len(n.Attr) > 0 { + if n.Attr[0].Key == "public" { + public := strings.ToLower(n.Attr[0].Val) + switch public { + case "-//w3o//dtd w3 html strict 3.0//en//", "-/w3d/dtd html 4.0 transitional/en", "html": + quirks = true + default: + for _, q := range quirkyIDs { + if strings.HasPrefix(public, q) { + quirks = true + break + } + } + } + // The following two public IDs only cause quirks mode if there is no system ID. + if len(n.Attr) == 1 && (strings.HasPrefix(public, "-//w3c//dtd html 4.01 frameset//") || + strings.HasPrefix(public, "-//w3c//dtd html 4.01 transitional//")) { + quirks = true + } + } + if lastAttr := n.Attr[len(n.Attr)-1]; lastAttr.Key == "system" && + strings.ToLower(lastAttr.Val) == "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd" { + quirks = true + } + } + + return n, quirks +} + +// quirkyIDs is a list of public doctype identifiers that cause a document +// to be interpreted in quirks mode. The identifiers should be in lower case. +var quirkyIDs = []string{ + "+//silmaril//dtd html pro v0r11 19970101//", + "-//advasoft ltd//dtd html 3.0 aswedit + extensions//", + "-//as//dtd html 3.0 aswedit + extensions//", + "-//ietf//dtd html 2.0 level 1//", + "-//ietf//dtd html 2.0 level 2//", + "-//ietf//dtd html 2.0 strict level 1//", + "-//ietf//dtd html 2.0 strict level 2//", + "-//ietf//dtd html 2.0 strict//", + "-//ietf//dtd html 2.0//", + "-//ietf//dtd html 2.1e//", + "-//ietf//dtd html 3.0//", + "-//ietf//dtd html 3.2 final//", + "-//ietf//dtd html 3.2//", + "-//ietf//dtd html 3//", + "-//ietf//dtd html level 0//", + "-//ietf//dtd html level 1//", + "-//ietf//dtd html level 2//", + "-//ietf//dtd html level 3//", + "-//ietf//dtd html strict level 0//", + "-//ietf//dtd html strict level 1//", + "-//ietf//dtd html strict level 2//", + "-//ietf//dtd html strict level 3//", + "-//ietf//dtd html strict//", + "-//ietf//dtd html//", + "-//metrius//dtd metrius presentational//", + "-//microsoft//dtd internet explorer 2.0 html strict//", + "-//microsoft//dtd internet explorer 2.0 html//", + "-//microsoft//dtd internet explorer 2.0 tables//", + "-//microsoft//dtd internet explorer 3.0 html strict//", + "-//microsoft//dtd internet explorer 3.0 html//", + "-//microsoft//dtd internet explorer 3.0 tables//", + "-//netscape comm. corp.//dtd html//", + "-//netscape comm. corp.//dtd strict html//", + "-//o'reilly and associates//dtd html 2.0//", + "-//o'reilly and associates//dtd html extended 1.0//", + "-//o'reilly and associates//dtd html extended relaxed 1.0//", + "-//softquad software//dtd hotmetal pro 6.0::19990601::extensions to html 4.0//", + "-//softquad//dtd hotmetal pro 4.0::19971010::extensions to html 4.0//", + "-//spyglass//dtd html 2.0 extended//", + "-//sq//dtd html 2.0 hotmetal + extensions//", + "-//sun microsystems corp.//dtd hotjava html//", + "-//sun microsystems corp.//dtd hotjava strict html//", + "-//w3c//dtd html 3 1995-03-24//", + "-//w3c//dtd html 3.2 draft//", + "-//w3c//dtd html 3.2 final//", + "-//w3c//dtd html 3.2//", + "-//w3c//dtd html 3.2s draft//", + "-//w3c//dtd html 4.0 frameset//", + "-//w3c//dtd html 4.0 transitional//", + "-//w3c//dtd html experimental 19960712//", + "-//w3c//dtd html experimental 970421//", + "-//w3c//dtd w3 html//", + "-//w3o//dtd w3 html 3.0//", + "-//webtechs//dtd mozilla html 2.0//", + "-//webtechs//dtd mozilla html//", +} diff --git a/vendor/golang.org/x/net/html/entity.go b/vendor/golang.org/x/net/html/entity.go new file mode 100644 index 0000000000..b628880a01 --- /dev/null +++ b/vendor/golang.org/x/net/html/entity.go @@ -0,0 +1,2253 @@ +// Copyright 2010 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 html + +// All entities that do not end with ';' are 6 or fewer bytes long. +const longestEntityWithoutSemicolon = 6 + +// entity is a map from HTML entity names to their values. The semicolon matters: +// https://html.spec.whatwg.org/multipage/syntax.html#named-character-references +// lists both "amp" and "amp;" as two separate entries. +// +// Note that the HTML5 list is larger than the HTML4 list at +// http://www.w3.org/TR/html4/sgml/entities.html +var entity = map[string]rune{ + "AElig;": '\U000000C6', + "AMP;": '\U00000026', + "Aacute;": '\U000000C1', + "Abreve;": '\U00000102', + "Acirc;": '\U000000C2', + "Acy;": '\U00000410', + "Afr;": '\U0001D504', + "Agrave;": '\U000000C0', + "Alpha;": '\U00000391', + "Amacr;": '\U00000100', + "And;": '\U00002A53', + "Aogon;": '\U00000104', + "Aopf;": '\U0001D538', + "ApplyFunction;": '\U00002061', + "Aring;": '\U000000C5', + "Ascr;": '\U0001D49C', + "Assign;": '\U00002254', + "Atilde;": '\U000000C3', + "Auml;": '\U000000C4', + "Backslash;": '\U00002216', + "Barv;": '\U00002AE7', + "Barwed;": '\U00002306', + "Bcy;": '\U00000411', + "Because;": '\U00002235', + "Bernoullis;": '\U0000212C', + "Beta;": '\U00000392', + "Bfr;": '\U0001D505', + "Bopf;": '\U0001D539', + "Breve;": '\U000002D8', + "Bscr;": '\U0000212C', + "Bumpeq;": '\U0000224E', + "CHcy;": '\U00000427', + "COPY;": '\U000000A9', + "Cacute;": '\U00000106', + "Cap;": '\U000022D2', + "CapitalDifferentialD;": '\U00002145', + "Cayleys;": '\U0000212D', + "Ccaron;": '\U0000010C', + "Ccedil;": '\U000000C7', + "Ccirc;": '\U00000108', + "Cconint;": '\U00002230', + "Cdot;": '\U0000010A', + "Cedilla;": '\U000000B8', + "CenterDot;": '\U000000B7', + "Cfr;": '\U0000212D', + "Chi;": '\U000003A7', + "CircleDot;": '\U00002299', + "CircleMinus;": '\U00002296', + "CirclePlus;": '\U00002295', + "CircleTimes;": '\U00002297', + "ClockwiseContourIntegral;": '\U00002232', + "CloseCurlyDoubleQuote;": '\U0000201D', + "CloseCurlyQuote;": '\U00002019', + "Colon;": '\U00002237', + "Colone;": '\U00002A74', + "Congruent;": '\U00002261', + "Conint;": '\U0000222F', + "ContourIntegral;": '\U0000222E', + "Copf;": '\U00002102', + "Coproduct;": '\U00002210', + "CounterClockwiseContourIntegral;": '\U00002233', + "Cross;": '\U00002A2F', + "Cscr;": '\U0001D49E', + "Cup;": '\U000022D3', + "CupCap;": '\U0000224D', + "DD;": '\U00002145', + "DDotrahd;": '\U00002911', + "DJcy;": '\U00000402', + "DScy;": '\U00000405', + "DZcy;": '\U0000040F', + "Dagger;": '\U00002021', + "Darr;": '\U000021A1', + "Dashv;": '\U00002AE4', + "Dcaron;": '\U0000010E', + "Dcy;": '\U00000414', + "Del;": '\U00002207', + "Delta;": '\U00000394', + "Dfr;": '\U0001D507', + "DiacriticalAcute;": '\U000000B4', + "DiacriticalDot;": '\U000002D9', + "DiacriticalDoubleAcute;": '\U000002DD', + "DiacriticalGrave;": '\U00000060', + "DiacriticalTilde;": '\U000002DC', + "Diamond;": '\U000022C4', + "DifferentialD;": '\U00002146', + "Dopf;": '\U0001D53B', + "Dot;": '\U000000A8', + "DotDot;": '\U000020DC', + "DotEqual;": '\U00002250', + "DoubleContourIntegral;": '\U0000222F', + "DoubleDot;": '\U000000A8', + "DoubleDownArrow;": '\U000021D3', + "DoubleLeftArrow;": '\U000021D0', + "DoubleLeftRightArrow;": '\U000021D4', + "DoubleLeftTee;": '\U00002AE4', + "DoubleLongLeftArrow;": '\U000027F8', + "DoubleLongLeftRightArrow;": '\U000027FA', + "DoubleLongRightArrow;": '\U000027F9', + "DoubleRightArrow;": '\U000021D2', + "DoubleRightTee;": '\U000022A8', + "DoubleUpArrow;": '\U000021D1', + "DoubleUpDownArrow;": '\U000021D5', + "DoubleVerticalBar;": '\U00002225', + "DownArrow;": '\U00002193', + "DownArrowBar;": '\U00002913', + "DownArrowUpArrow;": '\U000021F5', + "DownBreve;": '\U00000311', + "DownLeftRightVector;": '\U00002950', + "DownLeftTeeVector;": '\U0000295E', + "DownLeftVector;": '\U000021BD', + "DownLeftVectorBar;": '\U00002956', + "DownRightTeeVector;": '\U0000295F', + "DownRightVector;": '\U000021C1', + "DownRightVectorBar;": '\U00002957', + "DownTee;": '\U000022A4', + "DownTeeArrow;": '\U000021A7', + "Downarrow;": '\U000021D3', + "Dscr;": '\U0001D49F', + "Dstrok;": '\U00000110', + "ENG;": '\U0000014A', + "ETH;": '\U000000D0', + "Eacute;": '\U000000C9', + "Ecaron;": '\U0000011A', + "Ecirc;": '\U000000CA', + "Ecy;": '\U0000042D', + "Edot;": '\U00000116', + "Efr;": '\U0001D508', + "Egrave;": '\U000000C8', + "Element;": '\U00002208', + "Emacr;": '\U00000112', + "EmptySmallSquare;": '\U000025FB', + "EmptyVerySmallSquare;": '\U000025AB', + "Eogon;": '\U00000118', + "Eopf;": '\U0001D53C', + "Epsilon;": '\U00000395', + "Equal;": '\U00002A75', + "EqualTilde;": '\U00002242', + "Equilibrium;": '\U000021CC', + "Escr;": '\U00002130', + "Esim;": '\U00002A73', + "Eta;": '\U00000397', + "Euml;": '\U000000CB', + "Exists;": '\U00002203', + "ExponentialE;": '\U00002147', + "Fcy;": '\U00000424', + "Ffr;": '\U0001D509', + "FilledSmallSquare;": '\U000025FC', + "FilledVerySmallSquare;": '\U000025AA', + "Fopf;": '\U0001D53D', + "ForAll;": '\U00002200', + "Fouriertrf;": '\U00002131', + "Fscr;": '\U00002131', + "GJcy;": '\U00000403', + "GT;": '\U0000003E', + "Gamma;": '\U00000393', + "Gammad;": '\U000003DC', + "Gbreve;": '\U0000011E', + "Gcedil;": '\U00000122', + "Gcirc;": '\U0000011C', + "Gcy;": '\U00000413', + "Gdot;": '\U00000120', + "Gfr;": '\U0001D50A', + "Gg;": '\U000022D9', + "Gopf;": '\U0001D53E', + "GreaterEqual;": '\U00002265', + "GreaterEqualLess;": '\U000022DB', + "GreaterFullEqual;": '\U00002267', + "GreaterGreater;": '\U00002AA2', + "GreaterLess;": '\U00002277', + "GreaterSlantEqual;": '\U00002A7E', + "GreaterTilde;": '\U00002273', + "Gscr;": '\U0001D4A2', + "Gt;": '\U0000226B', + "HARDcy;": '\U0000042A', + "Hacek;": '\U000002C7', + "Hat;": '\U0000005E', + "Hcirc;": '\U00000124', + "Hfr;": '\U0000210C', + "HilbertSpace;": '\U0000210B', + "Hopf;": '\U0000210D', + "HorizontalLine;": '\U00002500', + "Hscr;": '\U0000210B', + "Hstrok;": '\U00000126', + "HumpDownHump;": '\U0000224E', + "HumpEqual;": '\U0000224F', + "IEcy;": '\U00000415', + "IJlig;": '\U00000132', + "IOcy;": '\U00000401', + "Iacute;": '\U000000CD', + "Icirc;": '\U000000CE', + "Icy;": '\U00000418', + "Idot;": '\U00000130', + "Ifr;": '\U00002111', + "Igrave;": '\U000000CC', + "Im;": '\U00002111', + "Imacr;": '\U0000012A', + "ImaginaryI;": '\U00002148', + "Implies;": '\U000021D2', + "Int;": '\U0000222C', + "Integral;": '\U0000222B', + "Intersection;": '\U000022C2', + "InvisibleComma;": '\U00002063', + "InvisibleTimes;": '\U00002062', + "Iogon;": '\U0000012E', + "Iopf;": '\U0001D540', + "Iota;": '\U00000399', + "Iscr;": '\U00002110', + "Itilde;": '\U00000128', + "Iukcy;": '\U00000406', + "Iuml;": '\U000000CF', + "Jcirc;": '\U00000134', + "Jcy;": '\U00000419', + "Jfr;": '\U0001D50D', + "Jopf;": '\U0001D541', + "Jscr;": '\U0001D4A5', + "Jsercy;": '\U00000408', + "Jukcy;": '\U00000404', + "KHcy;": '\U00000425', + "KJcy;": '\U0000040C', + "Kappa;": '\U0000039A', + "Kcedil;": '\U00000136', + "Kcy;": '\U0000041A', + "Kfr;": '\U0001D50E', + "Kopf;": '\U0001D542', + "Kscr;": '\U0001D4A6', + "LJcy;": '\U00000409', + "LT;": '\U0000003C', + "Lacute;": '\U00000139', + "Lambda;": '\U0000039B', + "Lang;": '\U000027EA', + "Laplacetrf;": '\U00002112', + "Larr;": '\U0000219E', + "Lcaron;": '\U0000013D', + "Lcedil;": '\U0000013B', + "Lcy;": '\U0000041B', + "LeftAngleBracket;": '\U000027E8', + "LeftArrow;": '\U00002190', + "LeftArrowBar;": '\U000021E4', + "LeftArrowRightArrow;": '\U000021C6', + "LeftCeiling;": '\U00002308', + "LeftDoubleBracket;": '\U000027E6', + "LeftDownTeeVector;": '\U00002961', + "LeftDownVector;": '\U000021C3', + "LeftDownVectorBar;": '\U00002959', + "LeftFloor;": '\U0000230A', + "LeftRightArrow;": '\U00002194', + "LeftRightVector;": '\U0000294E', + "LeftTee;": '\U000022A3', + "LeftTeeArrow;": '\U000021A4', + "LeftTeeVector;": '\U0000295A', + "LeftTriangle;": '\U000022B2', + "LeftTriangleBar;": '\U000029CF', + "LeftTriangleEqual;": '\U000022B4', + "LeftUpDownVector;": '\U00002951', + "LeftUpTeeVector;": '\U00002960', + "LeftUpVector;": '\U000021BF', + "LeftUpVectorBar;": '\U00002958', + "LeftVector;": '\U000021BC', + "LeftVectorBar;": '\U00002952', + "Leftarrow;": '\U000021D0', + "Leftrightarrow;": '\U000021D4', + "LessEqualGreater;": '\U000022DA', + "LessFullEqual;": '\U00002266', + "LessGreater;": '\U00002276', + "LessLess;": '\U00002AA1', + "LessSlantEqual;": '\U00002A7D', + "LessTilde;": '\U00002272', + "Lfr;": '\U0001D50F', + "Ll;": '\U000022D8', + "Lleftarrow;": '\U000021DA', + "Lmidot;": '\U0000013F', + "LongLeftArrow;": '\U000027F5', + "LongLeftRightArrow;": '\U000027F7', + "LongRightArrow;": '\U000027F6', + "Longleftarrow;": '\U000027F8', + "Longleftrightarrow;": '\U000027FA', + "Longrightarrow;": '\U000027F9', + "Lopf;": '\U0001D543', + "LowerLeftArrow;": '\U00002199', + "LowerRightArrow;": '\U00002198', + "Lscr;": '\U00002112', + "Lsh;": '\U000021B0', + "Lstrok;": '\U00000141', + "Lt;": '\U0000226A', + "Map;": '\U00002905', + "Mcy;": '\U0000041C', + "MediumSpace;": '\U0000205F', + "Mellintrf;": '\U00002133', + "Mfr;": '\U0001D510', + "MinusPlus;": '\U00002213', + "Mopf;": '\U0001D544', + "Mscr;": '\U00002133', + "Mu;": '\U0000039C', + "NJcy;": '\U0000040A', + "Nacute;": '\U00000143', + "Ncaron;": '\U00000147', + "Ncedil;": '\U00000145', + "Ncy;": '\U0000041D', + "NegativeMediumSpace;": '\U0000200B', + "NegativeThickSpace;": '\U0000200B', + "NegativeThinSpace;": '\U0000200B', + "NegativeVeryThinSpace;": '\U0000200B', + "NestedGreaterGreater;": '\U0000226B', + "NestedLessLess;": '\U0000226A', + "NewLine;": '\U0000000A', + "Nfr;": '\U0001D511', + "NoBreak;": '\U00002060', + "NonBreakingSpace;": '\U000000A0', + "Nopf;": '\U00002115', + "Not;": '\U00002AEC', + "NotCongruent;": '\U00002262', + "NotCupCap;": '\U0000226D', + "NotDoubleVerticalBar;": '\U00002226', + "NotElement;": '\U00002209', + "NotEqual;": '\U00002260', + "NotExists;": '\U00002204', + "NotGreater;": '\U0000226F', + "NotGreaterEqual;": '\U00002271', + "NotGreaterLess;": '\U00002279', + "NotGreaterTilde;": '\U00002275', + "NotLeftTriangle;": '\U000022EA', + "NotLeftTriangleEqual;": '\U000022EC', + "NotLess;": '\U0000226E', + "NotLessEqual;": '\U00002270', + "NotLessGreater;": '\U00002278', + "NotLessTilde;": '\U00002274', + "NotPrecedes;": '\U00002280', + "NotPrecedesSlantEqual;": '\U000022E0', + "NotReverseElement;": '\U0000220C', + "NotRightTriangle;": '\U000022EB', + "NotRightTriangleEqual;": '\U000022ED', + "NotSquareSubsetEqual;": '\U000022E2', + "NotSquareSupersetEqual;": '\U000022E3', + "NotSubsetEqual;": '\U00002288', + "NotSucceeds;": '\U00002281', + "NotSucceedsSlantEqual;": '\U000022E1', + "NotSupersetEqual;": '\U00002289', + "NotTilde;": '\U00002241', + "NotTildeEqual;": '\U00002244', + "NotTildeFullEqual;": '\U00002247', + "NotTildeTilde;": '\U00002249', + "NotVerticalBar;": '\U00002224', + "Nscr;": '\U0001D4A9', + "Ntilde;": '\U000000D1', + "Nu;": '\U0000039D', + "OElig;": '\U00000152', + "Oacute;": '\U000000D3', + "Ocirc;": '\U000000D4', + "Ocy;": '\U0000041E', + "Odblac;": '\U00000150', + "Ofr;": '\U0001D512', + "Ograve;": '\U000000D2', + "Omacr;": '\U0000014C', + "Omega;": '\U000003A9', + "Omicron;": '\U0000039F', + "Oopf;": '\U0001D546', + "OpenCurlyDoubleQuote;": '\U0000201C', + "OpenCurlyQuote;": '\U00002018', + "Or;": '\U00002A54', + "Oscr;": '\U0001D4AA', + "Oslash;": '\U000000D8', + "Otilde;": '\U000000D5', + "Otimes;": '\U00002A37', + "Ouml;": '\U000000D6', + "OverBar;": '\U0000203E', + "OverBrace;": '\U000023DE', + "OverBracket;": '\U000023B4', + "OverParenthesis;": '\U000023DC', + "PartialD;": '\U00002202', + "Pcy;": '\U0000041F', + "Pfr;": '\U0001D513', + "Phi;": '\U000003A6', + "Pi;": '\U000003A0', + "PlusMinus;": '\U000000B1', + "Poincareplane;": '\U0000210C', + "Popf;": '\U00002119', + "Pr;": '\U00002ABB', + "Precedes;": '\U0000227A', + "PrecedesEqual;": '\U00002AAF', + "PrecedesSlantEqual;": '\U0000227C', + "PrecedesTilde;": '\U0000227E', + "Prime;": '\U00002033', + "Product;": '\U0000220F', + "Proportion;": '\U00002237', + "Proportional;": '\U0000221D', + "Pscr;": '\U0001D4AB', + "Psi;": '\U000003A8', + "QUOT;": '\U00000022', + "Qfr;": '\U0001D514', + "Qopf;": '\U0000211A', + "Qscr;": '\U0001D4AC', + "RBarr;": '\U00002910', + "REG;": '\U000000AE', + "Racute;": '\U00000154', + "Rang;": '\U000027EB', + "Rarr;": '\U000021A0', + "Rarrtl;": '\U00002916', + "Rcaron;": '\U00000158', + "Rcedil;": '\U00000156', + "Rcy;": '\U00000420', + "Re;": '\U0000211C', + "ReverseElement;": '\U0000220B', + "ReverseEquilibrium;": '\U000021CB', + "ReverseUpEquilibrium;": '\U0000296F', + "Rfr;": '\U0000211C', + "Rho;": '\U000003A1', + "RightAngleBracket;": '\U000027E9', + "RightArrow;": '\U00002192', + "RightArrowBar;": '\U000021E5', + "RightArrowLeftArrow;": '\U000021C4', + "RightCeiling;": '\U00002309', + "RightDoubleBracket;": '\U000027E7', + "RightDownTeeVector;": '\U0000295D', + "RightDownVector;": '\U000021C2', + "RightDownVectorBar;": '\U00002955', + "RightFloor;": '\U0000230B', + "RightTee;": '\U000022A2', + "RightTeeArrow;": '\U000021A6', + "RightTeeVector;": '\U0000295B', + "RightTriangle;": '\U000022B3', + "RightTriangleBar;": '\U000029D0', + "RightTriangleEqual;": '\U000022B5', + "RightUpDownVector;": '\U0000294F', + "RightUpTeeVector;": '\U0000295C', + "RightUpVector;": '\U000021BE', + "RightUpVectorBar;": '\U00002954', + "RightVector;": '\U000021C0', + "RightVectorBar;": '\U00002953', + "Rightarrow;": '\U000021D2', + "Ropf;": '\U0000211D', + "RoundImplies;": '\U00002970', + "Rrightarrow;": '\U000021DB', + "Rscr;": '\U0000211B', + "Rsh;": '\U000021B1', + "RuleDelayed;": '\U000029F4', + "SHCHcy;": '\U00000429', + "SHcy;": '\U00000428', + "SOFTcy;": '\U0000042C', + "Sacute;": '\U0000015A', + "Sc;": '\U00002ABC', + "Scaron;": '\U00000160', + "Scedil;": '\U0000015E', + "Scirc;": '\U0000015C', + "Scy;": '\U00000421', + "Sfr;": '\U0001D516', + "ShortDownArrow;": '\U00002193', + "ShortLeftArrow;": '\U00002190', + "ShortRightArrow;": '\U00002192', + "ShortUpArrow;": '\U00002191', + "Sigma;": '\U000003A3', + "SmallCircle;": '\U00002218', + "Sopf;": '\U0001D54A', + "Sqrt;": '\U0000221A', + "Square;": '\U000025A1', + "SquareIntersection;": '\U00002293', + "SquareSubset;": '\U0000228F', + "SquareSubsetEqual;": '\U00002291', + "SquareSuperset;": '\U00002290', + "SquareSupersetEqual;": '\U00002292', + "SquareUnion;": '\U00002294', + "Sscr;": '\U0001D4AE', + "Star;": '\U000022C6', + "Sub;": '\U000022D0', + "Subset;": '\U000022D0', + "SubsetEqual;": '\U00002286', + "Succeeds;": '\U0000227B', + "SucceedsEqual;": '\U00002AB0', + "SucceedsSlantEqual;": '\U0000227D', + "SucceedsTilde;": '\U0000227F', + "SuchThat;": '\U0000220B', + "Sum;": '\U00002211', + "Sup;": '\U000022D1', + "Superset;": '\U00002283', + "SupersetEqual;": '\U00002287', + "Supset;": '\U000022D1', + "THORN;": '\U000000DE', + "TRADE;": '\U00002122', + "TSHcy;": '\U0000040B', + "TScy;": '\U00000426', + "Tab;": '\U00000009', + "Tau;": '\U000003A4', + "Tcaron;": '\U00000164', + "Tcedil;": '\U00000162', + "Tcy;": '\U00000422', + "Tfr;": '\U0001D517', + "Therefore;": '\U00002234', + "Theta;": '\U00000398', + "ThinSpace;": '\U00002009', + "Tilde;": '\U0000223C', + "TildeEqual;": '\U00002243', + "TildeFullEqual;": '\U00002245', + "TildeTilde;": '\U00002248', + "Topf;": '\U0001D54B', + "TripleDot;": '\U000020DB', + "Tscr;": '\U0001D4AF', + "Tstrok;": '\U00000166', + "Uacute;": '\U000000DA', + "Uarr;": '\U0000219F', + "Uarrocir;": '\U00002949', + "Ubrcy;": '\U0000040E', + "Ubreve;": '\U0000016C', + "Ucirc;": '\U000000DB', + "Ucy;": '\U00000423', + "Udblac;": '\U00000170', + "Ufr;": '\U0001D518', + "Ugrave;": '\U000000D9', + "Umacr;": '\U0000016A', + "UnderBar;": '\U0000005F', + "UnderBrace;": '\U000023DF', + "UnderBracket;": '\U000023B5', + "UnderParenthesis;": '\U000023DD', + "Union;": '\U000022C3', + "UnionPlus;": '\U0000228E', + "Uogon;": '\U00000172', + "Uopf;": '\U0001D54C', + "UpArrow;": '\U00002191', + "UpArrowBar;": '\U00002912', + "UpArrowDownArrow;": '\U000021C5', + "UpDownArrow;": '\U00002195', + "UpEquilibrium;": '\U0000296E', + "UpTee;": '\U000022A5', + "UpTeeArrow;": '\U000021A5', + "Uparrow;": '\U000021D1', + "Updownarrow;": '\U000021D5', + "UpperLeftArrow;": '\U00002196', + "UpperRightArrow;": '\U00002197', + "Upsi;": '\U000003D2', + "Upsilon;": '\U000003A5', + "Uring;": '\U0000016E', + "Uscr;": '\U0001D4B0', + "Utilde;": '\U00000168', + "Uuml;": '\U000000DC', + "VDash;": '\U000022AB', + "Vbar;": '\U00002AEB', + "Vcy;": '\U00000412', + "Vdash;": '\U000022A9', + "Vdashl;": '\U00002AE6', + "Vee;": '\U000022C1', + "Verbar;": '\U00002016', + "Vert;": '\U00002016', + "VerticalBar;": '\U00002223', + "VerticalLine;": '\U0000007C', + "VerticalSeparator;": '\U00002758', + "VerticalTilde;": '\U00002240', + "VeryThinSpace;": '\U0000200A', + "Vfr;": '\U0001D519', + "Vopf;": '\U0001D54D', + "Vscr;": '\U0001D4B1', + "Vvdash;": '\U000022AA', + "Wcirc;": '\U00000174', + "Wedge;": '\U000022C0', + "Wfr;": '\U0001D51A', + "Wopf;": '\U0001D54E', + "Wscr;": '\U0001D4B2', + "Xfr;": '\U0001D51B', + "Xi;": '\U0000039E', + "Xopf;": '\U0001D54F', + "Xscr;": '\U0001D4B3', + "YAcy;": '\U0000042F', + "YIcy;": '\U00000407', + "YUcy;": '\U0000042E', + "Yacute;": '\U000000DD', + "Ycirc;": '\U00000176', + "Ycy;": '\U0000042B', + "Yfr;": '\U0001D51C', + "Yopf;": '\U0001D550', + "Yscr;": '\U0001D4B4', + "Yuml;": '\U00000178', + "ZHcy;": '\U00000416', + "Zacute;": '\U00000179', + "Zcaron;": '\U0000017D', + "Zcy;": '\U00000417', + "Zdot;": '\U0000017B', + "ZeroWidthSpace;": '\U0000200B', + "Zeta;": '\U00000396', + "Zfr;": '\U00002128', + "Zopf;": '\U00002124', + "Zscr;": '\U0001D4B5', + "aacute;": '\U000000E1', + "abreve;": '\U00000103', + "ac;": '\U0000223E', + "acd;": '\U0000223F', + "acirc;": '\U000000E2', + "acute;": '\U000000B4', + "acy;": '\U00000430', + "aelig;": '\U000000E6', + "af;": '\U00002061', + "afr;": '\U0001D51E', + "agrave;": '\U000000E0', + "alefsym;": '\U00002135', + "aleph;": '\U00002135', + "alpha;": '\U000003B1', + "amacr;": '\U00000101', + "amalg;": '\U00002A3F', + "amp;": '\U00000026', + "and;": '\U00002227', + "andand;": '\U00002A55', + "andd;": '\U00002A5C', + "andslope;": '\U00002A58', + "andv;": '\U00002A5A', + "ang;": '\U00002220', + "ange;": '\U000029A4', + "angle;": '\U00002220', + "angmsd;": '\U00002221', + "angmsdaa;": '\U000029A8', + "angmsdab;": '\U000029A9', + "angmsdac;": '\U000029AA', + "angmsdad;": '\U000029AB', + "angmsdae;": '\U000029AC', + "angmsdaf;": '\U000029AD', + "angmsdag;": '\U000029AE', + "angmsdah;": '\U000029AF', + "angrt;": '\U0000221F', + "angrtvb;": '\U000022BE', + "angrtvbd;": '\U0000299D', + "angsph;": '\U00002222', + "angst;": '\U000000C5', + "angzarr;": '\U0000237C', + "aogon;": '\U00000105', + "aopf;": '\U0001D552', + "ap;": '\U00002248', + "apE;": '\U00002A70', + "apacir;": '\U00002A6F', + "ape;": '\U0000224A', + "apid;": '\U0000224B', + "apos;": '\U00000027', + "approx;": '\U00002248', + "approxeq;": '\U0000224A', + "aring;": '\U000000E5', + "ascr;": '\U0001D4B6', + "ast;": '\U0000002A', + "asymp;": '\U00002248', + "asympeq;": '\U0000224D', + "atilde;": '\U000000E3', + "auml;": '\U000000E4', + "awconint;": '\U00002233', + "awint;": '\U00002A11', + "bNot;": '\U00002AED', + "backcong;": '\U0000224C', + "backepsilon;": '\U000003F6', + "backprime;": '\U00002035', + "backsim;": '\U0000223D', + "backsimeq;": '\U000022CD', + "barvee;": '\U000022BD', + "barwed;": '\U00002305', + "barwedge;": '\U00002305', + "bbrk;": '\U000023B5', + "bbrktbrk;": '\U000023B6', + "bcong;": '\U0000224C', + "bcy;": '\U00000431', + "bdquo;": '\U0000201E', + "becaus;": '\U00002235', + "because;": '\U00002235', + "bemptyv;": '\U000029B0', + "bepsi;": '\U000003F6', + "bernou;": '\U0000212C', + "beta;": '\U000003B2', + "beth;": '\U00002136', + "between;": '\U0000226C', + "bfr;": '\U0001D51F', + "bigcap;": '\U000022C2', + "bigcirc;": '\U000025EF', + "bigcup;": '\U000022C3', + "bigodot;": '\U00002A00', + "bigoplus;": '\U00002A01', + "bigotimes;": '\U00002A02', + "bigsqcup;": '\U00002A06', + "bigstar;": '\U00002605', + "bigtriangledown;": '\U000025BD', + "bigtriangleup;": '\U000025B3', + "biguplus;": '\U00002A04', + "bigvee;": '\U000022C1', + "bigwedge;": '\U000022C0', + "bkarow;": '\U0000290D', + "blacklozenge;": '\U000029EB', + "blacksquare;": '\U000025AA', + "blacktriangle;": '\U000025B4', + "blacktriangledown;": '\U000025BE', + "blacktriangleleft;": '\U000025C2', + "blacktriangleright;": '\U000025B8', + "blank;": '\U00002423', + "blk12;": '\U00002592', + "blk14;": '\U00002591', + "blk34;": '\U00002593', + "block;": '\U00002588', + "bnot;": '\U00002310', + "bopf;": '\U0001D553', + "bot;": '\U000022A5', + "bottom;": '\U000022A5', + "bowtie;": '\U000022C8', + "boxDL;": '\U00002557', + "boxDR;": '\U00002554', + "boxDl;": '\U00002556', + "boxDr;": '\U00002553', + "boxH;": '\U00002550', + "boxHD;": '\U00002566', + "boxHU;": '\U00002569', + "boxHd;": '\U00002564', + "boxHu;": '\U00002567', + "boxUL;": '\U0000255D', + "boxUR;": '\U0000255A', + "boxUl;": '\U0000255C', + "boxUr;": '\U00002559', + "boxV;": '\U00002551', + "boxVH;": '\U0000256C', + "boxVL;": '\U00002563', + "boxVR;": '\U00002560', + "boxVh;": '\U0000256B', + "boxVl;": '\U00002562', + "boxVr;": '\U0000255F', + "boxbox;": '\U000029C9', + "boxdL;": '\U00002555', + "boxdR;": '\U00002552', + "boxdl;": '\U00002510', + "boxdr;": '\U0000250C', + "boxh;": '\U00002500', + "boxhD;": '\U00002565', + "boxhU;": '\U00002568', + "boxhd;": '\U0000252C', + "boxhu;": '\U00002534', + "boxminus;": '\U0000229F', + "boxplus;": '\U0000229E', + "boxtimes;": '\U000022A0', + "boxuL;": '\U0000255B', + "boxuR;": '\U00002558', + "boxul;": '\U00002518', + "boxur;": '\U00002514', + "boxv;": '\U00002502', + "boxvH;": '\U0000256A', + "boxvL;": '\U00002561', + "boxvR;": '\U0000255E', + "boxvh;": '\U0000253C', + "boxvl;": '\U00002524', + "boxvr;": '\U0000251C', + "bprime;": '\U00002035', + "breve;": '\U000002D8', + "brvbar;": '\U000000A6', + "bscr;": '\U0001D4B7', + "bsemi;": '\U0000204F', + "bsim;": '\U0000223D', + "bsime;": '\U000022CD', + "bsol;": '\U0000005C', + "bsolb;": '\U000029C5', + "bsolhsub;": '\U000027C8', + "bull;": '\U00002022', + "bullet;": '\U00002022', + "bump;": '\U0000224E', + "bumpE;": '\U00002AAE', + "bumpe;": '\U0000224F', + "bumpeq;": '\U0000224F', + "cacute;": '\U00000107', + "cap;": '\U00002229', + "capand;": '\U00002A44', + "capbrcup;": '\U00002A49', + "capcap;": '\U00002A4B', + "capcup;": '\U00002A47', + "capdot;": '\U00002A40', + "caret;": '\U00002041', + "caron;": '\U000002C7', + "ccaps;": '\U00002A4D', + "ccaron;": '\U0000010D', + "ccedil;": '\U000000E7', + "ccirc;": '\U00000109', + "ccups;": '\U00002A4C', + "ccupssm;": '\U00002A50', + "cdot;": '\U0000010B', + "cedil;": '\U000000B8', + "cemptyv;": '\U000029B2', + "cent;": '\U000000A2', + "centerdot;": '\U000000B7', + "cfr;": '\U0001D520', + "chcy;": '\U00000447', + "check;": '\U00002713', + "checkmark;": '\U00002713', + "chi;": '\U000003C7', + "cir;": '\U000025CB', + "cirE;": '\U000029C3', + "circ;": '\U000002C6', + "circeq;": '\U00002257', + "circlearrowleft;": '\U000021BA', + "circlearrowright;": '\U000021BB', + "circledR;": '\U000000AE', + "circledS;": '\U000024C8', + "circledast;": '\U0000229B', + "circledcirc;": '\U0000229A', + "circleddash;": '\U0000229D', + "cire;": '\U00002257', + "cirfnint;": '\U00002A10', + "cirmid;": '\U00002AEF', + "cirscir;": '\U000029C2', + "clubs;": '\U00002663', + "clubsuit;": '\U00002663', + "colon;": '\U0000003A', + "colone;": '\U00002254', + "coloneq;": '\U00002254', + "comma;": '\U0000002C', + "commat;": '\U00000040', + "comp;": '\U00002201', + "compfn;": '\U00002218', + "complement;": '\U00002201', + "complexes;": '\U00002102', + "cong;": '\U00002245', + "congdot;": '\U00002A6D', + "conint;": '\U0000222E', + "copf;": '\U0001D554', + "coprod;": '\U00002210', + "copy;": '\U000000A9', + "copysr;": '\U00002117', + "crarr;": '\U000021B5', + "cross;": '\U00002717', + "cscr;": '\U0001D4B8', + "csub;": '\U00002ACF', + "csube;": '\U00002AD1', + "csup;": '\U00002AD0', + "csupe;": '\U00002AD2', + "ctdot;": '\U000022EF', + "cudarrl;": '\U00002938', + "cudarrr;": '\U00002935', + "cuepr;": '\U000022DE', + "cuesc;": '\U000022DF', + "cularr;": '\U000021B6', + "cularrp;": '\U0000293D', + "cup;": '\U0000222A', + "cupbrcap;": '\U00002A48', + "cupcap;": '\U00002A46', + "cupcup;": '\U00002A4A', + "cupdot;": '\U0000228D', + "cupor;": '\U00002A45', + "curarr;": '\U000021B7', + "curarrm;": '\U0000293C', + "curlyeqprec;": '\U000022DE', + "curlyeqsucc;": '\U000022DF', + "curlyvee;": '\U000022CE', + "curlywedge;": '\U000022CF', + "curren;": '\U000000A4', + "curvearrowleft;": '\U000021B6', + "curvearrowright;": '\U000021B7', + "cuvee;": '\U000022CE', + "cuwed;": '\U000022CF', + "cwconint;": '\U00002232', + "cwint;": '\U00002231', + "cylcty;": '\U0000232D', + "dArr;": '\U000021D3', + "dHar;": '\U00002965', + "dagger;": '\U00002020', + "daleth;": '\U00002138', + "darr;": '\U00002193', + "dash;": '\U00002010', + "dashv;": '\U000022A3', + "dbkarow;": '\U0000290F', + "dblac;": '\U000002DD', + "dcaron;": '\U0000010F', + "dcy;": '\U00000434', + "dd;": '\U00002146', + "ddagger;": '\U00002021', + "ddarr;": '\U000021CA', + "ddotseq;": '\U00002A77', + "deg;": '\U000000B0', + "delta;": '\U000003B4', + "demptyv;": '\U000029B1', + "dfisht;": '\U0000297F', + "dfr;": '\U0001D521', + "dharl;": '\U000021C3', + "dharr;": '\U000021C2', + "diam;": '\U000022C4', + "diamond;": '\U000022C4', + "diamondsuit;": '\U00002666', + "diams;": '\U00002666', + "die;": '\U000000A8', + "digamma;": '\U000003DD', + "disin;": '\U000022F2', + "div;": '\U000000F7', + "divide;": '\U000000F7', + "divideontimes;": '\U000022C7', + "divonx;": '\U000022C7', + "djcy;": '\U00000452', + "dlcorn;": '\U0000231E', + "dlcrop;": '\U0000230D', + "dollar;": '\U00000024', + "dopf;": '\U0001D555', + "dot;": '\U000002D9', + "doteq;": '\U00002250', + "doteqdot;": '\U00002251', + "dotminus;": '\U00002238', + "dotplus;": '\U00002214', + "dotsquare;": '\U000022A1', + "doublebarwedge;": '\U00002306', + "downarrow;": '\U00002193', + "downdownarrows;": '\U000021CA', + "downharpoonleft;": '\U000021C3', + "downharpoonright;": '\U000021C2', + "drbkarow;": '\U00002910', + "drcorn;": '\U0000231F', + "drcrop;": '\U0000230C', + "dscr;": '\U0001D4B9', + "dscy;": '\U00000455', + "dsol;": '\U000029F6', + "dstrok;": '\U00000111', + "dtdot;": '\U000022F1', + "dtri;": '\U000025BF', + "dtrif;": '\U000025BE', + "duarr;": '\U000021F5', + "duhar;": '\U0000296F', + "dwangle;": '\U000029A6', + "dzcy;": '\U0000045F', + "dzigrarr;": '\U000027FF', + "eDDot;": '\U00002A77', + "eDot;": '\U00002251', + "eacute;": '\U000000E9', + "easter;": '\U00002A6E', + "ecaron;": '\U0000011B', + "ecir;": '\U00002256', + "ecirc;": '\U000000EA', + "ecolon;": '\U00002255', + "ecy;": '\U0000044D', + "edot;": '\U00000117', + "ee;": '\U00002147', + "efDot;": '\U00002252', + "efr;": '\U0001D522', + "eg;": '\U00002A9A', + "egrave;": '\U000000E8', + "egs;": '\U00002A96', + "egsdot;": '\U00002A98', + "el;": '\U00002A99', + "elinters;": '\U000023E7', + "ell;": '\U00002113', + "els;": '\U00002A95', + "elsdot;": '\U00002A97', + "emacr;": '\U00000113', + "empty;": '\U00002205', + "emptyset;": '\U00002205', + "emptyv;": '\U00002205', + "emsp;": '\U00002003', + "emsp13;": '\U00002004', + "emsp14;": '\U00002005', + "eng;": '\U0000014B', + "ensp;": '\U00002002', + "eogon;": '\U00000119', + "eopf;": '\U0001D556', + "epar;": '\U000022D5', + "eparsl;": '\U000029E3', + "eplus;": '\U00002A71', + "epsi;": '\U000003B5', + "epsilon;": '\U000003B5', + "epsiv;": '\U000003F5', + "eqcirc;": '\U00002256', + "eqcolon;": '\U00002255', + "eqsim;": '\U00002242', + "eqslantgtr;": '\U00002A96', + "eqslantless;": '\U00002A95', + "equals;": '\U0000003D', + "equest;": '\U0000225F', + "equiv;": '\U00002261', + "equivDD;": '\U00002A78', + "eqvparsl;": '\U000029E5', + "erDot;": '\U00002253', + "erarr;": '\U00002971', + "escr;": '\U0000212F', + "esdot;": '\U00002250', + "esim;": '\U00002242', + "eta;": '\U000003B7', + "eth;": '\U000000F0', + "euml;": '\U000000EB', + "euro;": '\U000020AC', + "excl;": '\U00000021', + "exist;": '\U00002203', + "expectation;": '\U00002130', + "exponentiale;": '\U00002147', + "fallingdotseq;": '\U00002252', + "fcy;": '\U00000444', + "female;": '\U00002640', + "ffilig;": '\U0000FB03', + "fflig;": '\U0000FB00', + "ffllig;": '\U0000FB04', + "ffr;": '\U0001D523', + "filig;": '\U0000FB01', + "flat;": '\U0000266D', + "fllig;": '\U0000FB02', + "fltns;": '\U000025B1', + "fnof;": '\U00000192', + "fopf;": '\U0001D557', + "forall;": '\U00002200', + "fork;": '\U000022D4', + "forkv;": '\U00002AD9', + "fpartint;": '\U00002A0D', + "frac12;": '\U000000BD', + "frac13;": '\U00002153', + "frac14;": '\U000000BC', + "frac15;": '\U00002155', + "frac16;": '\U00002159', + "frac18;": '\U0000215B', + "frac23;": '\U00002154', + "frac25;": '\U00002156', + "frac34;": '\U000000BE', + "frac35;": '\U00002157', + "frac38;": '\U0000215C', + "frac45;": '\U00002158', + "frac56;": '\U0000215A', + "frac58;": '\U0000215D', + "frac78;": '\U0000215E', + "frasl;": '\U00002044', + "frown;": '\U00002322', + "fscr;": '\U0001D4BB', + "gE;": '\U00002267', + "gEl;": '\U00002A8C', + "gacute;": '\U000001F5', + "gamma;": '\U000003B3', + "gammad;": '\U000003DD', + "gap;": '\U00002A86', + "gbreve;": '\U0000011F', + "gcirc;": '\U0000011D', + "gcy;": '\U00000433', + "gdot;": '\U00000121', + "ge;": '\U00002265', + "gel;": '\U000022DB', + "geq;": '\U00002265', + "geqq;": '\U00002267', + "geqslant;": '\U00002A7E', + "ges;": '\U00002A7E', + "gescc;": '\U00002AA9', + "gesdot;": '\U00002A80', + "gesdoto;": '\U00002A82', + "gesdotol;": '\U00002A84', + "gesles;": '\U00002A94', + "gfr;": '\U0001D524', + "gg;": '\U0000226B', + "ggg;": '\U000022D9', + "gimel;": '\U00002137', + "gjcy;": '\U00000453', + "gl;": '\U00002277', + "glE;": '\U00002A92', + "gla;": '\U00002AA5', + "glj;": '\U00002AA4', + "gnE;": '\U00002269', + "gnap;": '\U00002A8A', + "gnapprox;": '\U00002A8A', + "gne;": '\U00002A88', + "gneq;": '\U00002A88', + "gneqq;": '\U00002269', + "gnsim;": '\U000022E7', + "gopf;": '\U0001D558', + "grave;": '\U00000060', + "gscr;": '\U0000210A', + "gsim;": '\U00002273', + "gsime;": '\U00002A8E', + "gsiml;": '\U00002A90', + "gt;": '\U0000003E', + "gtcc;": '\U00002AA7', + "gtcir;": '\U00002A7A', + "gtdot;": '\U000022D7', + "gtlPar;": '\U00002995', + "gtquest;": '\U00002A7C', + "gtrapprox;": '\U00002A86', + "gtrarr;": '\U00002978', + "gtrdot;": '\U000022D7', + "gtreqless;": '\U000022DB', + "gtreqqless;": '\U00002A8C', + "gtrless;": '\U00002277', + "gtrsim;": '\U00002273', + "hArr;": '\U000021D4', + "hairsp;": '\U0000200A', + "half;": '\U000000BD', + "hamilt;": '\U0000210B', + "hardcy;": '\U0000044A', + "harr;": '\U00002194', + "harrcir;": '\U00002948', + "harrw;": '\U000021AD', + "hbar;": '\U0000210F', + "hcirc;": '\U00000125', + "hearts;": '\U00002665', + "heartsuit;": '\U00002665', + "hellip;": '\U00002026', + "hercon;": '\U000022B9', + "hfr;": '\U0001D525', + "hksearow;": '\U00002925', + "hkswarow;": '\U00002926', + "hoarr;": '\U000021FF', + "homtht;": '\U0000223B', + "hookleftarrow;": '\U000021A9', + "hookrightarrow;": '\U000021AA', + "hopf;": '\U0001D559', + "horbar;": '\U00002015', + "hscr;": '\U0001D4BD', + "hslash;": '\U0000210F', + "hstrok;": '\U00000127', + "hybull;": '\U00002043', + "hyphen;": '\U00002010', + "iacute;": '\U000000ED', + "ic;": '\U00002063', + "icirc;": '\U000000EE', + "icy;": '\U00000438', + "iecy;": '\U00000435', + "iexcl;": '\U000000A1', + "iff;": '\U000021D4', + "ifr;": '\U0001D526', + "igrave;": '\U000000EC', + "ii;": '\U00002148', + "iiiint;": '\U00002A0C', + "iiint;": '\U0000222D', + "iinfin;": '\U000029DC', + "iiota;": '\U00002129', + "ijlig;": '\U00000133', + "imacr;": '\U0000012B', + "image;": '\U00002111', + "imagline;": '\U00002110', + "imagpart;": '\U00002111', + "imath;": '\U00000131', + "imof;": '\U000022B7', + "imped;": '\U000001B5', + "in;": '\U00002208', + "incare;": '\U00002105', + "infin;": '\U0000221E', + "infintie;": '\U000029DD', + "inodot;": '\U00000131', + "int;": '\U0000222B', + "intcal;": '\U000022BA', + "integers;": '\U00002124', + "intercal;": '\U000022BA', + "intlarhk;": '\U00002A17', + "intprod;": '\U00002A3C', + "iocy;": '\U00000451', + "iogon;": '\U0000012F', + "iopf;": '\U0001D55A', + "iota;": '\U000003B9', + "iprod;": '\U00002A3C', + "iquest;": '\U000000BF', + "iscr;": '\U0001D4BE', + "isin;": '\U00002208', + "isinE;": '\U000022F9', + "isindot;": '\U000022F5', + "isins;": '\U000022F4', + "isinsv;": '\U000022F3', + "isinv;": '\U00002208', + "it;": '\U00002062', + "itilde;": '\U00000129', + "iukcy;": '\U00000456', + "iuml;": '\U000000EF', + "jcirc;": '\U00000135', + "jcy;": '\U00000439', + "jfr;": '\U0001D527', + "jmath;": '\U00000237', + "jopf;": '\U0001D55B', + "jscr;": '\U0001D4BF', + "jsercy;": '\U00000458', + "jukcy;": '\U00000454', + "kappa;": '\U000003BA', + "kappav;": '\U000003F0', + "kcedil;": '\U00000137', + "kcy;": '\U0000043A', + "kfr;": '\U0001D528', + "kgreen;": '\U00000138', + "khcy;": '\U00000445', + "kjcy;": '\U0000045C', + "kopf;": '\U0001D55C', + "kscr;": '\U0001D4C0', + "lAarr;": '\U000021DA', + "lArr;": '\U000021D0', + "lAtail;": '\U0000291B', + "lBarr;": '\U0000290E', + "lE;": '\U00002266', + "lEg;": '\U00002A8B', + "lHar;": '\U00002962', + "lacute;": '\U0000013A', + "laemptyv;": '\U000029B4', + "lagran;": '\U00002112', + "lambda;": '\U000003BB', + "lang;": '\U000027E8', + "langd;": '\U00002991', + "langle;": '\U000027E8', + "lap;": '\U00002A85', + "laquo;": '\U000000AB', + "larr;": '\U00002190', + "larrb;": '\U000021E4', + "larrbfs;": '\U0000291F', + "larrfs;": '\U0000291D', + "larrhk;": '\U000021A9', + "larrlp;": '\U000021AB', + "larrpl;": '\U00002939', + "larrsim;": '\U00002973', + "larrtl;": '\U000021A2', + "lat;": '\U00002AAB', + "latail;": '\U00002919', + "late;": '\U00002AAD', + "lbarr;": '\U0000290C', + "lbbrk;": '\U00002772', + "lbrace;": '\U0000007B', + "lbrack;": '\U0000005B', + "lbrke;": '\U0000298B', + "lbrksld;": '\U0000298F', + "lbrkslu;": '\U0000298D', + "lcaron;": '\U0000013E', + "lcedil;": '\U0000013C', + "lceil;": '\U00002308', + "lcub;": '\U0000007B', + "lcy;": '\U0000043B', + "ldca;": '\U00002936', + "ldquo;": '\U0000201C', + "ldquor;": '\U0000201E', + "ldrdhar;": '\U00002967', + "ldrushar;": '\U0000294B', + "ldsh;": '\U000021B2', + "le;": '\U00002264', + "leftarrow;": '\U00002190', + "leftarrowtail;": '\U000021A2', + "leftharpoondown;": '\U000021BD', + "leftharpoonup;": '\U000021BC', + "leftleftarrows;": '\U000021C7', + "leftrightarrow;": '\U00002194', + "leftrightarrows;": '\U000021C6', + "leftrightharpoons;": '\U000021CB', + "leftrightsquigarrow;": '\U000021AD', + "leftthreetimes;": '\U000022CB', + "leg;": '\U000022DA', + "leq;": '\U00002264', + "leqq;": '\U00002266', + "leqslant;": '\U00002A7D', + "les;": '\U00002A7D', + "lescc;": '\U00002AA8', + "lesdot;": '\U00002A7F', + "lesdoto;": '\U00002A81', + "lesdotor;": '\U00002A83', + "lesges;": '\U00002A93', + "lessapprox;": '\U00002A85', + "lessdot;": '\U000022D6', + "lesseqgtr;": '\U000022DA', + "lesseqqgtr;": '\U00002A8B', + "lessgtr;": '\U00002276', + "lesssim;": '\U00002272', + "lfisht;": '\U0000297C', + "lfloor;": '\U0000230A', + "lfr;": '\U0001D529', + "lg;": '\U00002276', + "lgE;": '\U00002A91', + "lhard;": '\U000021BD', + "lharu;": '\U000021BC', + "lharul;": '\U0000296A', + "lhblk;": '\U00002584', + "ljcy;": '\U00000459', + "ll;": '\U0000226A', + "llarr;": '\U000021C7', + "llcorner;": '\U0000231E', + "llhard;": '\U0000296B', + "lltri;": '\U000025FA', + "lmidot;": '\U00000140', + "lmoust;": '\U000023B0', + "lmoustache;": '\U000023B0', + "lnE;": '\U00002268', + "lnap;": '\U00002A89', + "lnapprox;": '\U00002A89', + "lne;": '\U00002A87', + "lneq;": '\U00002A87', + "lneqq;": '\U00002268', + "lnsim;": '\U000022E6', + "loang;": '\U000027EC', + "loarr;": '\U000021FD', + "lobrk;": '\U000027E6', + "longleftarrow;": '\U000027F5', + "longleftrightarrow;": '\U000027F7', + "longmapsto;": '\U000027FC', + "longrightarrow;": '\U000027F6', + "looparrowleft;": '\U000021AB', + "looparrowright;": '\U000021AC', + "lopar;": '\U00002985', + "lopf;": '\U0001D55D', + "loplus;": '\U00002A2D', + "lotimes;": '\U00002A34', + "lowast;": '\U00002217', + "lowbar;": '\U0000005F', + "loz;": '\U000025CA', + "lozenge;": '\U000025CA', + "lozf;": '\U000029EB', + "lpar;": '\U00000028', + "lparlt;": '\U00002993', + "lrarr;": '\U000021C6', + "lrcorner;": '\U0000231F', + "lrhar;": '\U000021CB', + "lrhard;": '\U0000296D', + "lrm;": '\U0000200E', + "lrtri;": '\U000022BF', + "lsaquo;": '\U00002039', + "lscr;": '\U0001D4C1', + "lsh;": '\U000021B0', + "lsim;": '\U00002272', + "lsime;": '\U00002A8D', + "lsimg;": '\U00002A8F', + "lsqb;": '\U0000005B', + "lsquo;": '\U00002018', + "lsquor;": '\U0000201A', + "lstrok;": '\U00000142', + "lt;": '\U0000003C', + "ltcc;": '\U00002AA6', + "ltcir;": '\U00002A79', + "ltdot;": '\U000022D6', + "lthree;": '\U000022CB', + "ltimes;": '\U000022C9', + "ltlarr;": '\U00002976', + "ltquest;": '\U00002A7B', + "ltrPar;": '\U00002996', + "ltri;": '\U000025C3', + "ltrie;": '\U000022B4', + "ltrif;": '\U000025C2', + "lurdshar;": '\U0000294A', + "luruhar;": '\U00002966', + "mDDot;": '\U0000223A', + "macr;": '\U000000AF', + "male;": '\U00002642', + "malt;": '\U00002720', + "maltese;": '\U00002720', + "map;": '\U000021A6', + "mapsto;": '\U000021A6', + "mapstodown;": '\U000021A7', + "mapstoleft;": '\U000021A4', + "mapstoup;": '\U000021A5', + "marker;": '\U000025AE', + "mcomma;": '\U00002A29', + "mcy;": '\U0000043C', + "mdash;": '\U00002014', + "measuredangle;": '\U00002221', + "mfr;": '\U0001D52A', + "mho;": '\U00002127', + "micro;": '\U000000B5', + "mid;": '\U00002223', + "midast;": '\U0000002A', + "midcir;": '\U00002AF0', + "middot;": '\U000000B7', + "minus;": '\U00002212', + "minusb;": '\U0000229F', + "minusd;": '\U00002238', + "minusdu;": '\U00002A2A', + "mlcp;": '\U00002ADB', + "mldr;": '\U00002026', + "mnplus;": '\U00002213', + "models;": '\U000022A7', + "mopf;": '\U0001D55E', + "mp;": '\U00002213', + "mscr;": '\U0001D4C2', + "mstpos;": '\U0000223E', + "mu;": '\U000003BC', + "multimap;": '\U000022B8', + "mumap;": '\U000022B8', + "nLeftarrow;": '\U000021CD', + "nLeftrightarrow;": '\U000021CE', + "nRightarrow;": '\U000021CF', + "nVDash;": '\U000022AF', + "nVdash;": '\U000022AE', + "nabla;": '\U00002207', + "nacute;": '\U00000144', + "nap;": '\U00002249', + "napos;": '\U00000149', + "napprox;": '\U00002249', + "natur;": '\U0000266E', + "natural;": '\U0000266E', + "naturals;": '\U00002115', + "nbsp;": '\U000000A0', + "ncap;": '\U00002A43', + "ncaron;": '\U00000148', + "ncedil;": '\U00000146', + "ncong;": '\U00002247', + "ncup;": '\U00002A42', + "ncy;": '\U0000043D', + "ndash;": '\U00002013', + "ne;": '\U00002260', + "neArr;": '\U000021D7', + "nearhk;": '\U00002924', + "nearr;": '\U00002197', + "nearrow;": '\U00002197', + "nequiv;": '\U00002262', + "nesear;": '\U00002928', + "nexist;": '\U00002204', + "nexists;": '\U00002204', + "nfr;": '\U0001D52B', + "nge;": '\U00002271', + "ngeq;": '\U00002271', + "ngsim;": '\U00002275', + "ngt;": '\U0000226F', + "ngtr;": '\U0000226F', + "nhArr;": '\U000021CE', + "nharr;": '\U000021AE', + "nhpar;": '\U00002AF2', + "ni;": '\U0000220B', + "nis;": '\U000022FC', + "nisd;": '\U000022FA', + "niv;": '\U0000220B', + "njcy;": '\U0000045A', + "nlArr;": '\U000021CD', + "nlarr;": '\U0000219A', + "nldr;": '\U00002025', + "nle;": '\U00002270', + "nleftarrow;": '\U0000219A', + "nleftrightarrow;": '\U000021AE', + "nleq;": '\U00002270', + "nless;": '\U0000226E', + "nlsim;": '\U00002274', + "nlt;": '\U0000226E', + "nltri;": '\U000022EA', + "nltrie;": '\U000022EC', + "nmid;": '\U00002224', + "nopf;": '\U0001D55F', + "not;": '\U000000AC', + "notin;": '\U00002209', + "notinva;": '\U00002209', + "notinvb;": '\U000022F7', + "notinvc;": '\U000022F6', + "notni;": '\U0000220C', + "notniva;": '\U0000220C', + "notnivb;": '\U000022FE', + "notnivc;": '\U000022FD', + "npar;": '\U00002226', + "nparallel;": '\U00002226', + "npolint;": '\U00002A14', + "npr;": '\U00002280', + "nprcue;": '\U000022E0', + "nprec;": '\U00002280', + "nrArr;": '\U000021CF', + "nrarr;": '\U0000219B', + "nrightarrow;": '\U0000219B', + "nrtri;": '\U000022EB', + "nrtrie;": '\U000022ED', + "nsc;": '\U00002281', + "nsccue;": '\U000022E1', + "nscr;": '\U0001D4C3', + "nshortmid;": '\U00002224', + "nshortparallel;": '\U00002226', + "nsim;": '\U00002241', + "nsime;": '\U00002244', + "nsimeq;": '\U00002244', + "nsmid;": '\U00002224', + "nspar;": '\U00002226', + "nsqsube;": '\U000022E2', + "nsqsupe;": '\U000022E3', + "nsub;": '\U00002284', + "nsube;": '\U00002288', + "nsubseteq;": '\U00002288', + "nsucc;": '\U00002281', + "nsup;": '\U00002285', + "nsupe;": '\U00002289', + "nsupseteq;": '\U00002289', + "ntgl;": '\U00002279', + "ntilde;": '\U000000F1', + "ntlg;": '\U00002278', + "ntriangleleft;": '\U000022EA', + "ntrianglelefteq;": '\U000022EC', + "ntriangleright;": '\U000022EB', + "ntrianglerighteq;": '\U000022ED', + "nu;": '\U000003BD', + "num;": '\U00000023', + "numero;": '\U00002116', + "numsp;": '\U00002007', + "nvDash;": '\U000022AD', + "nvHarr;": '\U00002904', + "nvdash;": '\U000022AC', + "nvinfin;": '\U000029DE', + "nvlArr;": '\U00002902', + "nvrArr;": '\U00002903', + "nwArr;": '\U000021D6', + "nwarhk;": '\U00002923', + "nwarr;": '\U00002196', + "nwarrow;": '\U00002196', + "nwnear;": '\U00002927', + "oS;": '\U000024C8', + "oacute;": '\U000000F3', + "oast;": '\U0000229B', + "ocir;": '\U0000229A', + "ocirc;": '\U000000F4', + "ocy;": '\U0000043E', + "odash;": '\U0000229D', + "odblac;": '\U00000151', + "odiv;": '\U00002A38', + "odot;": '\U00002299', + "odsold;": '\U000029BC', + "oelig;": '\U00000153', + "ofcir;": '\U000029BF', + "ofr;": '\U0001D52C', + "ogon;": '\U000002DB', + "ograve;": '\U000000F2', + "ogt;": '\U000029C1', + "ohbar;": '\U000029B5', + "ohm;": '\U000003A9', + "oint;": '\U0000222E', + "olarr;": '\U000021BA', + "olcir;": '\U000029BE', + "olcross;": '\U000029BB', + "oline;": '\U0000203E', + "olt;": '\U000029C0', + "omacr;": '\U0000014D', + "omega;": '\U000003C9', + "omicron;": '\U000003BF', + "omid;": '\U000029B6', + "ominus;": '\U00002296', + "oopf;": '\U0001D560', + "opar;": '\U000029B7', + "operp;": '\U000029B9', + "oplus;": '\U00002295', + "or;": '\U00002228', + "orarr;": '\U000021BB', + "ord;": '\U00002A5D', + "order;": '\U00002134', + "orderof;": '\U00002134', + "ordf;": '\U000000AA', + "ordm;": '\U000000BA', + "origof;": '\U000022B6', + "oror;": '\U00002A56', + "orslope;": '\U00002A57', + "orv;": '\U00002A5B', + "oscr;": '\U00002134', + "oslash;": '\U000000F8', + "osol;": '\U00002298', + "otilde;": '\U000000F5', + "otimes;": '\U00002297', + "otimesas;": '\U00002A36', + "ouml;": '\U000000F6', + "ovbar;": '\U0000233D', + "par;": '\U00002225', + "para;": '\U000000B6', + "parallel;": '\U00002225', + "parsim;": '\U00002AF3', + "parsl;": '\U00002AFD', + "part;": '\U00002202', + "pcy;": '\U0000043F', + "percnt;": '\U00000025', + "period;": '\U0000002E', + "permil;": '\U00002030', + "perp;": '\U000022A5', + "pertenk;": '\U00002031', + "pfr;": '\U0001D52D', + "phi;": '\U000003C6', + "phiv;": '\U000003D5', + "phmmat;": '\U00002133', + "phone;": '\U0000260E', + "pi;": '\U000003C0', + "pitchfork;": '\U000022D4', + "piv;": '\U000003D6', + "planck;": '\U0000210F', + "planckh;": '\U0000210E', + "plankv;": '\U0000210F', + "plus;": '\U0000002B', + "plusacir;": '\U00002A23', + "plusb;": '\U0000229E', + "pluscir;": '\U00002A22', + "plusdo;": '\U00002214', + "plusdu;": '\U00002A25', + "pluse;": '\U00002A72', + "plusmn;": '\U000000B1', + "plussim;": '\U00002A26', + "plustwo;": '\U00002A27', + "pm;": '\U000000B1', + "pointint;": '\U00002A15', + "popf;": '\U0001D561', + "pound;": '\U000000A3', + "pr;": '\U0000227A', + "prE;": '\U00002AB3', + "prap;": '\U00002AB7', + "prcue;": '\U0000227C', + "pre;": '\U00002AAF', + "prec;": '\U0000227A', + "precapprox;": '\U00002AB7', + "preccurlyeq;": '\U0000227C', + "preceq;": '\U00002AAF', + "precnapprox;": '\U00002AB9', + "precneqq;": '\U00002AB5', + "precnsim;": '\U000022E8', + "precsim;": '\U0000227E', + "prime;": '\U00002032', + "primes;": '\U00002119', + "prnE;": '\U00002AB5', + "prnap;": '\U00002AB9', + "prnsim;": '\U000022E8', + "prod;": '\U0000220F', + "profalar;": '\U0000232E', + "profline;": '\U00002312', + "profsurf;": '\U00002313', + "prop;": '\U0000221D', + "propto;": '\U0000221D', + "prsim;": '\U0000227E', + "prurel;": '\U000022B0', + "pscr;": '\U0001D4C5', + "psi;": '\U000003C8', + "puncsp;": '\U00002008', + "qfr;": '\U0001D52E', + "qint;": '\U00002A0C', + "qopf;": '\U0001D562', + "qprime;": '\U00002057', + "qscr;": '\U0001D4C6', + "quaternions;": '\U0000210D', + "quatint;": '\U00002A16', + "quest;": '\U0000003F', + "questeq;": '\U0000225F', + "quot;": '\U00000022', + "rAarr;": '\U000021DB', + "rArr;": '\U000021D2', + "rAtail;": '\U0000291C', + "rBarr;": '\U0000290F', + "rHar;": '\U00002964', + "racute;": '\U00000155', + "radic;": '\U0000221A', + "raemptyv;": '\U000029B3', + "rang;": '\U000027E9', + "rangd;": '\U00002992', + "range;": '\U000029A5', + "rangle;": '\U000027E9', + "raquo;": '\U000000BB', + "rarr;": '\U00002192', + "rarrap;": '\U00002975', + "rarrb;": '\U000021E5', + "rarrbfs;": '\U00002920', + "rarrc;": '\U00002933', + "rarrfs;": '\U0000291E', + "rarrhk;": '\U000021AA', + "rarrlp;": '\U000021AC', + "rarrpl;": '\U00002945', + "rarrsim;": '\U00002974', + "rarrtl;": '\U000021A3', + "rarrw;": '\U0000219D', + "ratail;": '\U0000291A', + "ratio;": '\U00002236', + "rationals;": '\U0000211A', + "rbarr;": '\U0000290D', + "rbbrk;": '\U00002773', + "rbrace;": '\U0000007D', + "rbrack;": '\U0000005D', + "rbrke;": '\U0000298C', + "rbrksld;": '\U0000298E', + "rbrkslu;": '\U00002990', + "rcaron;": '\U00000159', + "rcedil;": '\U00000157', + "rceil;": '\U00002309', + "rcub;": '\U0000007D', + "rcy;": '\U00000440', + "rdca;": '\U00002937', + "rdldhar;": '\U00002969', + "rdquo;": '\U0000201D', + "rdquor;": '\U0000201D', + "rdsh;": '\U000021B3', + "real;": '\U0000211C', + "realine;": '\U0000211B', + "realpart;": '\U0000211C', + "reals;": '\U0000211D', + "rect;": '\U000025AD', + "reg;": '\U000000AE', + "rfisht;": '\U0000297D', + "rfloor;": '\U0000230B', + "rfr;": '\U0001D52F', + "rhard;": '\U000021C1', + "rharu;": '\U000021C0', + "rharul;": '\U0000296C', + "rho;": '\U000003C1', + "rhov;": '\U000003F1', + "rightarrow;": '\U00002192', + "rightarrowtail;": '\U000021A3', + "rightharpoondown;": '\U000021C1', + "rightharpoonup;": '\U000021C0', + "rightleftarrows;": '\U000021C4', + "rightleftharpoons;": '\U000021CC', + "rightrightarrows;": '\U000021C9', + "rightsquigarrow;": '\U0000219D', + "rightthreetimes;": '\U000022CC', + "ring;": '\U000002DA', + "risingdotseq;": '\U00002253', + "rlarr;": '\U000021C4', + "rlhar;": '\U000021CC', + "rlm;": '\U0000200F', + "rmoust;": '\U000023B1', + "rmoustache;": '\U000023B1', + "rnmid;": '\U00002AEE', + "roang;": '\U000027ED', + "roarr;": '\U000021FE', + "robrk;": '\U000027E7', + "ropar;": '\U00002986', + "ropf;": '\U0001D563', + "roplus;": '\U00002A2E', + "rotimes;": '\U00002A35', + "rpar;": '\U00000029', + "rpargt;": '\U00002994', + "rppolint;": '\U00002A12', + "rrarr;": '\U000021C9', + "rsaquo;": '\U0000203A', + "rscr;": '\U0001D4C7', + "rsh;": '\U000021B1', + "rsqb;": '\U0000005D', + "rsquo;": '\U00002019', + "rsquor;": '\U00002019', + "rthree;": '\U000022CC', + "rtimes;": '\U000022CA', + "rtri;": '\U000025B9', + "rtrie;": '\U000022B5', + "rtrif;": '\U000025B8', + "rtriltri;": '\U000029CE', + "ruluhar;": '\U00002968', + "rx;": '\U0000211E', + "sacute;": '\U0000015B', + "sbquo;": '\U0000201A', + "sc;": '\U0000227B', + "scE;": '\U00002AB4', + "scap;": '\U00002AB8', + "scaron;": '\U00000161', + "sccue;": '\U0000227D', + "sce;": '\U00002AB0', + "scedil;": '\U0000015F', + "scirc;": '\U0000015D', + "scnE;": '\U00002AB6', + "scnap;": '\U00002ABA', + "scnsim;": '\U000022E9', + "scpolint;": '\U00002A13', + "scsim;": '\U0000227F', + "scy;": '\U00000441', + "sdot;": '\U000022C5', + "sdotb;": '\U000022A1', + "sdote;": '\U00002A66', + "seArr;": '\U000021D8', + "searhk;": '\U00002925', + "searr;": '\U00002198', + "searrow;": '\U00002198', + "sect;": '\U000000A7', + "semi;": '\U0000003B', + "seswar;": '\U00002929', + "setminus;": '\U00002216', + "setmn;": '\U00002216', + "sext;": '\U00002736', + "sfr;": '\U0001D530', + "sfrown;": '\U00002322', + "sharp;": '\U0000266F', + "shchcy;": '\U00000449', + "shcy;": '\U00000448', + "shortmid;": '\U00002223', + "shortparallel;": '\U00002225', + "shy;": '\U000000AD', + "sigma;": '\U000003C3', + "sigmaf;": '\U000003C2', + "sigmav;": '\U000003C2', + "sim;": '\U0000223C', + "simdot;": '\U00002A6A', + "sime;": '\U00002243', + "simeq;": '\U00002243', + "simg;": '\U00002A9E', + "simgE;": '\U00002AA0', + "siml;": '\U00002A9D', + "simlE;": '\U00002A9F', + "simne;": '\U00002246', + "simplus;": '\U00002A24', + "simrarr;": '\U00002972', + "slarr;": '\U00002190', + "smallsetminus;": '\U00002216', + "smashp;": '\U00002A33', + "smeparsl;": '\U000029E4', + "smid;": '\U00002223', + "smile;": '\U00002323', + "smt;": '\U00002AAA', + "smte;": '\U00002AAC', + "softcy;": '\U0000044C', + "sol;": '\U0000002F', + "solb;": '\U000029C4', + "solbar;": '\U0000233F', + "sopf;": '\U0001D564', + "spades;": '\U00002660', + "spadesuit;": '\U00002660', + "spar;": '\U00002225', + "sqcap;": '\U00002293', + "sqcup;": '\U00002294', + "sqsub;": '\U0000228F', + "sqsube;": '\U00002291', + "sqsubset;": '\U0000228F', + "sqsubseteq;": '\U00002291', + "sqsup;": '\U00002290', + "sqsupe;": '\U00002292', + "sqsupset;": '\U00002290', + "sqsupseteq;": '\U00002292', + "squ;": '\U000025A1', + "square;": '\U000025A1', + "squarf;": '\U000025AA', + "squf;": '\U000025AA', + "srarr;": '\U00002192', + "sscr;": '\U0001D4C8', + "ssetmn;": '\U00002216', + "ssmile;": '\U00002323', + "sstarf;": '\U000022C6', + "star;": '\U00002606', + "starf;": '\U00002605', + "straightepsilon;": '\U000003F5', + "straightphi;": '\U000003D5', + "strns;": '\U000000AF', + "sub;": '\U00002282', + "subE;": '\U00002AC5', + "subdot;": '\U00002ABD', + "sube;": '\U00002286', + "subedot;": '\U00002AC3', + "submult;": '\U00002AC1', + "subnE;": '\U00002ACB', + "subne;": '\U0000228A', + "subplus;": '\U00002ABF', + "subrarr;": '\U00002979', + "subset;": '\U00002282', + "subseteq;": '\U00002286', + "subseteqq;": '\U00002AC5', + "subsetneq;": '\U0000228A', + "subsetneqq;": '\U00002ACB', + "subsim;": '\U00002AC7', + "subsub;": '\U00002AD5', + "subsup;": '\U00002AD3', + "succ;": '\U0000227B', + "succapprox;": '\U00002AB8', + "succcurlyeq;": '\U0000227D', + "succeq;": '\U00002AB0', + "succnapprox;": '\U00002ABA', + "succneqq;": '\U00002AB6', + "succnsim;": '\U000022E9', + "succsim;": '\U0000227F', + "sum;": '\U00002211', + "sung;": '\U0000266A', + "sup;": '\U00002283', + "sup1;": '\U000000B9', + "sup2;": '\U000000B2', + "sup3;": '\U000000B3', + "supE;": '\U00002AC6', + "supdot;": '\U00002ABE', + "supdsub;": '\U00002AD8', + "supe;": '\U00002287', + "supedot;": '\U00002AC4', + "suphsol;": '\U000027C9', + "suphsub;": '\U00002AD7', + "suplarr;": '\U0000297B', + "supmult;": '\U00002AC2', + "supnE;": '\U00002ACC', + "supne;": '\U0000228B', + "supplus;": '\U00002AC0', + "supset;": '\U00002283', + "supseteq;": '\U00002287', + "supseteqq;": '\U00002AC6', + "supsetneq;": '\U0000228B', + "supsetneqq;": '\U00002ACC', + "supsim;": '\U00002AC8', + "supsub;": '\U00002AD4', + "supsup;": '\U00002AD6', + "swArr;": '\U000021D9', + "swarhk;": '\U00002926', + "swarr;": '\U00002199', + "swarrow;": '\U00002199', + "swnwar;": '\U0000292A', + "szlig;": '\U000000DF', + "target;": '\U00002316', + "tau;": '\U000003C4', + "tbrk;": '\U000023B4', + "tcaron;": '\U00000165', + "tcedil;": '\U00000163', + "tcy;": '\U00000442', + "tdot;": '\U000020DB', + "telrec;": '\U00002315', + "tfr;": '\U0001D531', + "there4;": '\U00002234', + "therefore;": '\U00002234', + "theta;": '\U000003B8', + "thetasym;": '\U000003D1', + "thetav;": '\U000003D1', + "thickapprox;": '\U00002248', + "thicksim;": '\U0000223C', + "thinsp;": '\U00002009', + "thkap;": '\U00002248', + "thksim;": '\U0000223C', + "thorn;": '\U000000FE', + "tilde;": '\U000002DC', + "times;": '\U000000D7', + "timesb;": '\U000022A0', + "timesbar;": '\U00002A31', + "timesd;": '\U00002A30', + "tint;": '\U0000222D', + "toea;": '\U00002928', + "top;": '\U000022A4', + "topbot;": '\U00002336', + "topcir;": '\U00002AF1', + "topf;": '\U0001D565', + "topfork;": '\U00002ADA', + "tosa;": '\U00002929', + "tprime;": '\U00002034', + "trade;": '\U00002122', + "triangle;": '\U000025B5', + "triangledown;": '\U000025BF', + "triangleleft;": '\U000025C3', + "trianglelefteq;": '\U000022B4', + "triangleq;": '\U0000225C', + "triangleright;": '\U000025B9', + "trianglerighteq;": '\U000022B5', + "tridot;": '\U000025EC', + "trie;": '\U0000225C', + "triminus;": '\U00002A3A', + "triplus;": '\U00002A39', + "trisb;": '\U000029CD', + "tritime;": '\U00002A3B', + "trpezium;": '\U000023E2', + "tscr;": '\U0001D4C9', + "tscy;": '\U00000446', + "tshcy;": '\U0000045B', + "tstrok;": '\U00000167', + "twixt;": '\U0000226C', + "twoheadleftarrow;": '\U0000219E', + "twoheadrightarrow;": '\U000021A0', + "uArr;": '\U000021D1', + "uHar;": '\U00002963', + "uacute;": '\U000000FA', + "uarr;": '\U00002191', + "ubrcy;": '\U0000045E', + "ubreve;": '\U0000016D', + "ucirc;": '\U000000FB', + "ucy;": '\U00000443', + "udarr;": '\U000021C5', + "udblac;": '\U00000171', + "udhar;": '\U0000296E', + "ufisht;": '\U0000297E', + "ufr;": '\U0001D532', + "ugrave;": '\U000000F9', + "uharl;": '\U000021BF', + "uharr;": '\U000021BE', + "uhblk;": '\U00002580', + "ulcorn;": '\U0000231C', + "ulcorner;": '\U0000231C', + "ulcrop;": '\U0000230F', + "ultri;": '\U000025F8', + "umacr;": '\U0000016B', + "uml;": '\U000000A8', + "uogon;": '\U00000173', + "uopf;": '\U0001D566', + "uparrow;": '\U00002191', + "updownarrow;": '\U00002195', + "upharpoonleft;": '\U000021BF', + "upharpoonright;": '\U000021BE', + "uplus;": '\U0000228E', + "upsi;": '\U000003C5', + "upsih;": '\U000003D2', + "upsilon;": '\U000003C5', + "upuparrows;": '\U000021C8', + "urcorn;": '\U0000231D', + "urcorner;": '\U0000231D', + "urcrop;": '\U0000230E', + "uring;": '\U0000016F', + "urtri;": '\U000025F9', + "uscr;": '\U0001D4CA', + "utdot;": '\U000022F0', + "utilde;": '\U00000169', + "utri;": '\U000025B5', + "utrif;": '\U000025B4', + "uuarr;": '\U000021C8', + "uuml;": '\U000000FC', + "uwangle;": '\U000029A7', + "vArr;": '\U000021D5', + "vBar;": '\U00002AE8', + "vBarv;": '\U00002AE9', + "vDash;": '\U000022A8', + "vangrt;": '\U0000299C', + "varepsilon;": '\U000003F5', + "varkappa;": '\U000003F0', + "varnothing;": '\U00002205', + "varphi;": '\U000003D5', + "varpi;": '\U000003D6', + "varpropto;": '\U0000221D', + "varr;": '\U00002195', + "varrho;": '\U000003F1', + "varsigma;": '\U000003C2', + "vartheta;": '\U000003D1', + "vartriangleleft;": '\U000022B2', + "vartriangleright;": '\U000022B3', + "vcy;": '\U00000432', + "vdash;": '\U000022A2', + "vee;": '\U00002228', + "veebar;": '\U000022BB', + "veeeq;": '\U0000225A', + "vellip;": '\U000022EE', + "verbar;": '\U0000007C', + "vert;": '\U0000007C', + "vfr;": '\U0001D533', + "vltri;": '\U000022B2', + "vopf;": '\U0001D567', + "vprop;": '\U0000221D', + "vrtri;": '\U000022B3', + "vscr;": '\U0001D4CB', + "vzigzag;": '\U0000299A', + "wcirc;": '\U00000175', + "wedbar;": '\U00002A5F', + "wedge;": '\U00002227', + "wedgeq;": '\U00002259', + "weierp;": '\U00002118', + "wfr;": '\U0001D534', + "wopf;": '\U0001D568', + "wp;": '\U00002118', + "wr;": '\U00002240', + "wreath;": '\U00002240', + "wscr;": '\U0001D4CC', + "xcap;": '\U000022C2', + "xcirc;": '\U000025EF', + "xcup;": '\U000022C3', + "xdtri;": '\U000025BD', + "xfr;": '\U0001D535', + "xhArr;": '\U000027FA', + "xharr;": '\U000027F7', + "xi;": '\U000003BE', + "xlArr;": '\U000027F8', + "xlarr;": '\U000027F5', + "xmap;": '\U000027FC', + "xnis;": '\U000022FB', + "xodot;": '\U00002A00', + "xopf;": '\U0001D569', + "xoplus;": '\U00002A01', + "xotime;": '\U00002A02', + "xrArr;": '\U000027F9', + "xrarr;": '\U000027F6', + "xscr;": '\U0001D4CD', + "xsqcup;": '\U00002A06', + "xuplus;": '\U00002A04', + "xutri;": '\U000025B3', + "xvee;": '\U000022C1', + "xwedge;": '\U000022C0', + "yacute;": '\U000000FD', + "yacy;": '\U0000044F', + "ycirc;": '\U00000177', + "ycy;": '\U0000044B', + "yen;": '\U000000A5', + "yfr;": '\U0001D536', + "yicy;": '\U00000457', + "yopf;": '\U0001D56A', + "yscr;": '\U0001D4CE', + "yucy;": '\U0000044E', + "yuml;": '\U000000FF', + "zacute;": '\U0000017A', + "zcaron;": '\U0000017E', + "zcy;": '\U00000437', + "zdot;": '\U0000017C', + "zeetrf;": '\U00002128', + "zeta;": '\U000003B6', + "zfr;": '\U0001D537', + "zhcy;": '\U00000436', + "zigrarr;": '\U000021DD', + "zopf;": '\U0001D56B', + "zscr;": '\U0001D4CF', + "zwj;": '\U0000200D', + "zwnj;": '\U0000200C', + "AElig": '\U000000C6', + "AMP": '\U00000026', + "Aacute": '\U000000C1', + "Acirc": '\U000000C2', + "Agrave": '\U000000C0', + "Aring": '\U000000C5', + "Atilde": '\U000000C3', + "Auml": '\U000000C4', + "COPY": '\U000000A9', + "Ccedil": '\U000000C7', + "ETH": '\U000000D0', + "Eacute": '\U000000C9', + "Ecirc": '\U000000CA', + "Egrave": '\U000000C8', + "Euml": '\U000000CB', + "GT": '\U0000003E', + "Iacute": '\U000000CD', + "Icirc": '\U000000CE', + "Igrave": '\U000000CC', + "Iuml": '\U000000CF', + "LT": '\U0000003C', + "Ntilde": '\U000000D1', + "Oacute": '\U000000D3', + "Ocirc": '\U000000D4', + "Ograve": '\U000000D2', + "Oslash": '\U000000D8', + "Otilde": '\U000000D5', + "Ouml": '\U000000D6', + "QUOT": '\U00000022', + "REG": '\U000000AE', + "THORN": '\U000000DE', + "Uacute": '\U000000DA', + "Ucirc": '\U000000DB', + "Ugrave": '\U000000D9', + "Uuml": '\U000000DC', + "Yacute": '\U000000DD', + "aacute": '\U000000E1', + "acirc": '\U000000E2', + "acute": '\U000000B4', + "aelig": '\U000000E6', + "agrave": '\U000000E0', + "amp": '\U00000026', + "aring": '\U000000E5', + "atilde": '\U000000E3', + "auml": '\U000000E4', + "brvbar": '\U000000A6', + "ccedil": '\U000000E7', + "cedil": '\U000000B8', + "cent": '\U000000A2', + "copy": '\U000000A9', + "curren": '\U000000A4', + "deg": '\U000000B0', + "divide": '\U000000F7', + "eacute": '\U000000E9', + "ecirc": '\U000000EA', + "egrave": '\U000000E8', + "eth": '\U000000F0', + "euml": '\U000000EB', + "frac12": '\U000000BD', + "frac14": '\U000000BC', + "frac34": '\U000000BE', + "gt": '\U0000003E', + "iacute": '\U000000ED', + "icirc": '\U000000EE', + "iexcl": '\U000000A1', + "igrave": '\U000000EC', + "iquest": '\U000000BF', + "iuml": '\U000000EF', + "laquo": '\U000000AB', + "lt": '\U0000003C', + "macr": '\U000000AF', + "micro": '\U000000B5', + "middot": '\U000000B7', + "nbsp": '\U000000A0', + "not": '\U000000AC', + "ntilde": '\U000000F1', + "oacute": '\U000000F3', + "ocirc": '\U000000F4', + "ograve": '\U000000F2', + "ordf": '\U000000AA', + "ordm": '\U000000BA', + "oslash": '\U000000F8', + "otilde": '\U000000F5', + "ouml": '\U000000F6', + "para": '\U000000B6', + "plusmn": '\U000000B1', + "pound": '\U000000A3', + "quot": '\U00000022', + "raquo": '\U000000BB', + "reg": '\U000000AE', + "sect": '\U000000A7', + "shy": '\U000000AD', + "sup1": '\U000000B9', + "sup2": '\U000000B2', + "sup3": '\U000000B3', + "szlig": '\U000000DF', + "thorn": '\U000000FE', + "times": '\U000000D7', + "uacute": '\U000000FA', + "ucirc": '\U000000FB', + "ugrave": '\U000000F9', + "uml": '\U000000A8', + "uuml": '\U000000FC', + "yacute": '\U000000FD', + "yen": '\U000000A5', + "yuml": '\U000000FF', +} + +// HTML entities that are two unicode codepoints. +var entity2 = map[string][2]rune{ + // TODO(nigeltao): Handle replacements that are wider than their names. + // "nLt;": {'\u226A', '\u20D2'}, + // "nGt;": {'\u226B', '\u20D2'}, + "NotEqualTilde;": {'\u2242', '\u0338'}, + "NotGreaterFullEqual;": {'\u2267', '\u0338'}, + "NotGreaterGreater;": {'\u226B', '\u0338'}, + "NotGreaterSlantEqual;": {'\u2A7E', '\u0338'}, + "NotHumpDownHump;": {'\u224E', '\u0338'}, + "NotHumpEqual;": {'\u224F', '\u0338'}, + "NotLeftTriangleBar;": {'\u29CF', '\u0338'}, + "NotLessLess;": {'\u226A', '\u0338'}, + "NotLessSlantEqual;": {'\u2A7D', '\u0338'}, + "NotNestedGreaterGreater;": {'\u2AA2', '\u0338'}, + "NotNestedLessLess;": {'\u2AA1', '\u0338'}, + "NotPrecedesEqual;": {'\u2AAF', '\u0338'}, + "NotRightTriangleBar;": {'\u29D0', '\u0338'}, + "NotSquareSubset;": {'\u228F', '\u0338'}, + "NotSquareSuperset;": {'\u2290', '\u0338'}, + "NotSubset;": {'\u2282', '\u20D2'}, + "NotSucceedsEqual;": {'\u2AB0', '\u0338'}, + "NotSucceedsTilde;": {'\u227F', '\u0338'}, + "NotSuperset;": {'\u2283', '\u20D2'}, + "ThickSpace;": {'\u205F', '\u200A'}, + "acE;": {'\u223E', '\u0333'}, + "bne;": {'\u003D', '\u20E5'}, + "bnequiv;": {'\u2261', '\u20E5'}, + "caps;": {'\u2229', '\uFE00'}, + "cups;": {'\u222A', '\uFE00'}, + "fjlig;": {'\u0066', '\u006A'}, + "gesl;": {'\u22DB', '\uFE00'}, + "gvertneqq;": {'\u2269', '\uFE00'}, + "gvnE;": {'\u2269', '\uFE00'}, + "lates;": {'\u2AAD', '\uFE00'}, + "lesg;": {'\u22DA', '\uFE00'}, + "lvertneqq;": {'\u2268', '\uFE00'}, + "lvnE;": {'\u2268', '\uFE00'}, + "nGg;": {'\u22D9', '\u0338'}, + "nGtv;": {'\u226B', '\u0338'}, + "nLl;": {'\u22D8', '\u0338'}, + "nLtv;": {'\u226A', '\u0338'}, + "nang;": {'\u2220', '\u20D2'}, + "napE;": {'\u2A70', '\u0338'}, + "napid;": {'\u224B', '\u0338'}, + "nbump;": {'\u224E', '\u0338'}, + "nbumpe;": {'\u224F', '\u0338'}, + "ncongdot;": {'\u2A6D', '\u0338'}, + "nedot;": {'\u2250', '\u0338'}, + "nesim;": {'\u2242', '\u0338'}, + "ngE;": {'\u2267', '\u0338'}, + "ngeqq;": {'\u2267', '\u0338'}, + "ngeqslant;": {'\u2A7E', '\u0338'}, + "nges;": {'\u2A7E', '\u0338'}, + "nlE;": {'\u2266', '\u0338'}, + "nleqq;": {'\u2266', '\u0338'}, + "nleqslant;": {'\u2A7D', '\u0338'}, + "nles;": {'\u2A7D', '\u0338'}, + "notinE;": {'\u22F9', '\u0338'}, + "notindot;": {'\u22F5', '\u0338'}, + "nparsl;": {'\u2AFD', '\u20E5'}, + "npart;": {'\u2202', '\u0338'}, + "npre;": {'\u2AAF', '\u0338'}, + "npreceq;": {'\u2AAF', '\u0338'}, + "nrarrc;": {'\u2933', '\u0338'}, + "nrarrw;": {'\u219D', '\u0338'}, + "nsce;": {'\u2AB0', '\u0338'}, + "nsubE;": {'\u2AC5', '\u0338'}, + "nsubset;": {'\u2282', '\u20D2'}, + "nsubseteqq;": {'\u2AC5', '\u0338'}, + "nsucceq;": {'\u2AB0', '\u0338'}, + "nsupE;": {'\u2AC6', '\u0338'}, + "nsupset;": {'\u2283', '\u20D2'}, + "nsupseteqq;": {'\u2AC6', '\u0338'}, + "nvap;": {'\u224D', '\u20D2'}, + "nvge;": {'\u2265', '\u20D2'}, + "nvgt;": {'\u003E', '\u20D2'}, + "nvle;": {'\u2264', '\u20D2'}, + "nvlt;": {'\u003C', '\u20D2'}, + "nvltrie;": {'\u22B4', '\u20D2'}, + "nvrtrie;": {'\u22B5', '\u20D2'}, + "nvsim;": {'\u223C', '\u20D2'}, + "race;": {'\u223D', '\u0331'}, + "smtes;": {'\u2AAC', '\uFE00'}, + "sqcaps;": {'\u2293', '\uFE00'}, + "sqcups;": {'\u2294', '\uFE00'}, + "varsubsetneq;": {'\u228A', '\uFE00'}, + "varsubsetneqq;": {'\u2ACB', '\uFE00'}, + "varsupsetneq;": {'\u228B', '\uFE00'}, + "varsupsetneqq;": {'\u2ACC', '\uFE00'}, + "vnsub;": {'\u2282', '\u20D2'}, + "vnsup;": {'\u2283', '\u20D2'}, + "vsubnE;": {'\u2ACB', '\uFE00'}, + "vsubne;": {'\u228A', '\uFE00'}, + "vsupnE;": {'\u2ACC', '\uFE00'}, + "vsupne;": {'\u228B', '\uFE00'}, +} diff --git a/vendor/golang.org/x/net/html/escape.go b/vendor/golang.org/x/net/html/escape.go new file mode 100644 index 0000000000..04c6bec210 --- /dev/null +++ b/vendor/golang.org/x/net/html/escape.go @@ -0,0 +1,339 @@ +// Copyright 2010 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 html + +import ( + "bytes" + "strings" + "unicode/utf8" +) + +// These replacements permit compatibility with old numeric entities that +// assumed Windows-1252 encoding. +// https://html.spec.whatwg.org/multipage/syntax.html#consume-a-character-reference +var replacementTable = [...]rune{ + '\u20AC', // First entry is what 0x80 should be replaced with. + '\u0081', + '\u201A', + '\u0192', + '\u201E', + '\u2026', + '\u2020', + '\u2021', + '\u02C6', + '\u2030', + '\u0160', + '\u2039', + '\u0152', + '\u008D', + '\u017D', + '\u008F', + '\u0090', + '\u2018', + '\u2019', + '\u201C', + '\u201D', + '\u2022', + '\u2013', + '\u2014', + '\u02DC', + '\u2122', + '\u0161', + '\u203A', + '\u0153', + '\u009D', + '\u017E', + '\u0178', // Last entry is 0x9F. + // 0x00->'\uFFFD' is handled programmatically. + // 0x0D->'\u000D' is a no-op. +} + +// unescapeEntity reads an entity like "<" from b[src:] and writes the +// corresponding "<" to b[dst:], returning the incremented dst and src cursors. +// Precondition: b[src] == '&' && dst <= src. +// attribute should be true if parsing an attribute value. +func unescapeEntity(b []byte, dst, src int, attribute bool) (dst1, src1 int) { + // https://html.spec.whatwg.org/multipage/syntax.html#consume-a-character-reference + + // i starts at 1 because we already know that s[0] == '&'. + i, s := 1, b[src:] + + if len(s) <= 1 { + b[dst] = b[src] + return dst + 1, src + 1 + } + + if s[i] == '#' { + if len(s) <= 3 { // We need to have at least "&#.". + b[dst] = b[src] + return dst + 1, src + 1 + } + i++ + c := s[i] + hex := false + if c == 'x' || c == 'X' { + hex = true + i++ + } + + x := '\x00' + for i < len(s) { + c = s[i] + i++ + if hex { + if '0' <= c && c <= '9' { + x = 16*x + rune(c) - '0' + continue + } else if 'a' <= c && c <= 'f' { + x = 16*x + rune(c) - 'a' + 10 + continue + } else if 'A' <= c && c <= 'F' { + x = 16*x + rune(c) - 'A' + 10 + continue + } + } else if '0' <= c && c <= '9' { + x = 10*x + rune(c) - '0' + continue + } + if c != ';' { + i-- + } + break + } + + if i <= 3 { // No characters matched. + b[dst] = b[src] + return dst + 1, src + 1 + } + + if 0x80 <= x && x <= 0x9F { + // Replace characters from Windows-1252 with UTF-8 equivalents. + x = replacementTable[x-0x80] + } else if x == 0 || (0xD800 <= x && x <= 0xDFFF) || x > 0x10FFFF { + // Replace invalid characters with the replacement character. + x = '\uFFFD' + } + + return dst + utf8.EncodeRune(b[dst:], x), src + i + } + + // Consume the maximum number of characters possible, with the + // consumed characters matching one of the named references. + + for i < len(s) { + c := s[i] + i++ + // Lower-cased characters are more common in entities, so we check for them first. + if 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || '0' <= c && c <= '9' { + continue + } + if c != ';' { + i-- + } + break + } + + entityName := string(s[1:i]) + if entityName == "" { + // No-op. + } else if attribute && entityName[len(entityName)-1] != ';' && len(s) > i && s[i] == '=' { + // No-op. + } else if x := entity[entityName]; x != 0 { + return dst + utf8.EncodeRune(b[dst:], x), src + i + } else if x := entity2[entityName]; x[0] != 0 { + dst1 := dst + utf8.EncodeRune(b[dst:], x[0]) + return dst1 + utf8.EncodeRune(b[dst1:], x[1]), src + i + } else if !attribute { + maxLen := len(entityName) - 1 + if maxLen > longestEntityWithoutSemicolon { + maxLen = longestEntityWithoutSemicolon + } + for j := maxLen; j > 1; j-- { + if x := entity[entityName[:j]]; x != 0 { + return dst + utf8.EncodeRune(b[dst:], x), src + j + 1 + } + } + } + + dst1, src1 = dst+i, src+i + copy(b[dst:dst1], b[src:src1]) + return dst1, src1 +} + +// unescape unescapes b's entities in-place, so that "a<b" becomes "a' byte that, per above, we'd like to avoid escaping unless we have to. +// +// Studying the summary table (and T actions in its '>' column) closely, we +// only need to escape in states 43, 44, 49, 51 and 52. State 43 is at the +// start of the comment data. State 52 is after a '!'. The other three states +// are after a '-'. +// +// Our algorithm is thus to escape every '&' and to escape '>' if and only if: +// - The '>' is after a '!' or '-' (in the unescaped data) or +// - The '>' is at the start of the comment data (after the opening ""); err != nil { + return err + } + return nil + case DoctypeNode: + if _, err := w.WriteString("') + case RawNode: + _, err := w.WriteString(n.Data) + return err + default: + return errors.New("html: unknown node type") + } + + // Render the opening tag. + if err := w.WriteByte('<'); err != nil { + return err + } + if _, err := w.WriteString(n.Data); err != nil { + return err + } + for _, a := range n.Attr { + if err := w.WriteByte(' '); err != nil { + return err + } + if a.Namespace != "" { + if _, err := w.WriteString(a.Namespace); err != nil { + return err + } + if err := w.WriteByte(':'); err != nil { + return err + } + } + if _, err := w.WriteString(a.Key); err != nil { + return err + } + if _, err := w.WriteString(`="`); err != nil { + return err + } + if err := escape(w, a.Val); err != nil { + return err + } + if err := w.WriteByte('"'); err != nil { + return err + } + } + if voidElements[n.Data] { + if n.FirstChild != nil { + return fmt.Errorf("html: void element <%s> has child nodes", n.Data) + } + _, err := w.WriteString("/>") + return err + } + if err := w.WriteByte('>'); err != nil { + return err + } + + // Add initial newline where there is danger of a newline beging ignored. + if c := n.FirstChild; c != nil && c.Type == TextNode && strings.HasPrefix(c.Data, "\n") { + switch n.Data { + case "pre", "listing", "textarea": + if err := w.WriteByte('\n'); err != nil { + return err + } + } + } + + // Render any child nodes + if childTextNodesAreLiteral(n) { + for c := n.FirstChild; c != nil; c = c.NextSibling { + if c.Type == TextNode { + if _, err := w.WriteString(c.Data); err != nil { + return err + } + } else { + if err := render1(w, c); err != nil { + return err + } + } + } + if n.Data == "plaintext" { + // Don't render anything else. must be the + // last element in the file, with no closing tag. + return plaintextAbort + } + } else { + for c := n.FirstChild; c != nil; c = c.NextSibling { + if err := render1(w, c); err != nil { + return err + } + } + } + + // Render the </xxx> closing tag. + if _, err := w.WriteString("</"); err != nil { + return err + } + if _, err := w.WriteString(n.Data); err != nil { + return err + } + return w.WriteByte('>') +} + +func childTextNodesAreLiteral(n *Node) bool { + // Per WHATWG HTML 13.3, if the parent of the current node is a style, + // script, xmp, iframe, noembed, noframes, or plaintext element, and the + // current node is a text node, append the value of the node's data + // literally. The specification is not explicit about it, but we only + // enforce this if we are in the HTML namespace (i.e. when the namespace is + // ""). + // NOTE: we also always include noscript elements, although the + // specification states that they should only be rendered as such if + // scripting is enabled for the node (which is not something we track). + if n.Namespace != "" { + return false + } + switch n.Data { + case "iframe", "noembed", "noframes", "noscript", "plaintext", "script", "style", "xmp": + return true + default: + return false + } +} + +// writeQuoted writes s to w surrounded by quotes. Normally it will use double +// quotes, but if s contains a double quote, it will use single quotes. +// It is used for writing the identifiers in a doctype declaration. +// In valid HTML, they can't contain both types of quotes. +func writeQuoted(w writer, s string) error { + var q byte = '"' + if strings.Contains(s, `"`) { + q = '\'' + } + if err := w.WriteByte(q); err != nil { + return err + } + if _, err := w.WriteString(s); err != nil { + return err + } + if err := w.WriteByte(q); err != nil { + return err + } + return nil +} + +// Section 12.1.2, "Elements", gives this list of void elements. Void elements +// are those that can't have any contents. +var voidElements = map[string]bool{ + "area": true, + "base": true, + "br": true, + "col": true, + "embed": true, + "hr": true, + "img": true, + "input": true, + "keygen": true, // "keygen" has been removed from the spec, but are kept here for backwards compatibility. + "link": true, + "meta": true, + "param": true, + "source": true, + "track": true, + "wbr": true, +} diff --git a/vendor/golang.org/x/net/html/token.go b/vendor/golang.org/x/net/html/token.go new file mode 100644 index 0000000000..3c57880d69 --- /dev/null +++ b/vendor/golang.org/x/net/html/token.go @@ -0,0 +1,1272 @@ +// Copyright 2010 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 html + +import ( + "bytes" + "errors" + "io" + "strconv" + "strings" + + "golang.org/x/net/html/atom" +) + +// A TokenType is the type of a Token. +type TokenType uint32 + +const ( + // ErrorToken means that an error occurred during tokenization. + ErrorToken TokenType = iota + // TextToken means a text node. + TextToken + // A StartTagToken looks like <a>. + StartTagToken + // An EndTagToken looks like </a>. + EndTagToken + // A SelfClosingTagToken tag looks like <br/>. + SelfClosingTagToken + // A CommentToken looks like <!--x-->. + CommentToken + // A DoctypeToken looks like <!DOCTYPE x> + DoctypeToken +) + +// ErrBufferExceeded means that the buffering limit was exceeded. +var ErrBufferExceeded = errors.New("max buffer exceeded") + +// String returns a string representation of the TokenType. +func (t TokenType) String() string { + switch t { + case ErrorToken: + return "Error" + case TextToken: + return "Text" + case StartTagToken: + return "StartTag" + case EndTagToken: + return "EndTag" + case SelfClosingTagToken: + return "SelfClosingTag" + case CommentToken: + return "Comment" + case DoctypeToken: + return "Doctype" + } + return "Invalid(" + strconv.Itoa(int(t)) + ")" +} + +// An Attribute is an attribute namespace-key-value triple. Namespace is +// non-empty for foreign attributes like xlink, Key is alphabetic (and hence +// does not contain escapable characters like '&', '<' or '>'), and Val is +// unescaped (it looks like "a<b" rather than "a&lt;b"). +// +// Namespace is only used by the parser, not the tokenizer. +type Attribute struct { + Namespace, Key, Val string +} + +// A Token consists of a TokenType and some Data (tag name for start and end +// tags, content for text, comments and doctypes). A tag Token may also contain +// a slice of Attributes. Data is unescaped for all Tokens (it looks like "a<b" +// rather than "a&lt;b"). For tag Tokens, DataAtom is the atom for Data, or +// zero if Data is not a known tag name. +type Token struct { + Type TokenType + DataAtom atom.Atom + Data string + Attr []Attribute +} + +// tagString returns a string representation of a tag Token's Data and Attr. +func (t Token) tagString() string { + if len(t.Attr) == 0 { + return t.Data + } + buf := bytes.NewBufferString(t.Data) + for _, a := range t.Attr { + buf.WriteByte(' ') + buf.WriteString(a.Key) + buf.WriteString(`="`) + escape(buf, a.Val) + buf.WriteByte('"') + } + return buf.String() +} + +// String returns a string representation of the Token. +func (t Token) String() string { + switch t.Type { + case ErrorToken: + return "" + case TextToken: + return EscapeString(t.Data) + case StartTagToken: + return "<" + t.tagString() + ">" + case EndTagToken: + return "</" + t.tagString() + ">" + case SelfClosingTagToken: + return "<" + t.tagString() + "/>" + case CommentToken: + return "<!--" + escapeCommentString(t.Data) + "-->" + case DoctypeToken: + return "<!DOCTYPE " + EscapeString(t.Data) + ">" + } + return "Invalid(" + strconv.Itoa(int(t.Type)) + ")" +} + +// span is a range of bytes in a Tokenizer's buffer. The start is inclusive, +// the end is exclusive. +type span struct { + start, end int +} + +// A Tokenizer returns a stream of HTML Tokens. +type Tokenizer struct { + // r is the source of the HTML text. + r io.Reader + // tt is the TokenType of the current token. + tt TokenType + // err is the first error encountered during tokenization. It is possible + // for tt != Error && err != nil to hold: this means that Next returned a + // valid token but the subsequent Next call will return an error token. + // For example, if the HTML text input was just "plain", then the first + // Next call would set z.err to io.EOF but return a TextToken, and all + // subsequent Next calls would return an ErrorToken. + // err is never reset. Once it becomes non-nil, it stays non-nil. + err error + // readErr is the error returned by the io.Reader r. It is separate from + // err because it is valid for an io.Reader to return (n int, err1 error) + // such that n > 0 && err1 != nil, and callers should always process the + // n > 0 bytes before considering the error err1. + readErr error + // buf[raw.start:raw.end] holds the raw bytes of the current token. + // buf[raw.end:] is buffered input that will yield future tokens. + raw span + buf []byte + // maxBuf limits the data buffered in buf. A value of 0 means unlimited. + maxBuf int + // buf[data.start:data.end] holds the raw bytes of the current token's data: + // a text token's text, a tag token's tag name, etc. + data span + // pendingAttr is the attribute key and value currently being tokenized. + // When complete, pendingAttr is pushed onto attr. nAttrReturned is + // incremented on each call to TagAttr. + pendingAttr [2]span + attr [][2]span + nAttrReturned int + // rawTag is the "script" in "</script>" that closes the next token. If + // non-empty, the subsequent call to Next will return a raw or RCDATA text + // token: one that treats "<p>" as text instead of an element. + // rawTag's contents are lower-cased. + rawTag string + // textIsRaw is whether the current text token's data is not escaped. + textIsRaw bool + // convertNUL is whether NUL bytes in the current token's data should + // be converted into \ufffd replacement characters. + convertNUL bool + // allowCDATA is whether CDATA sections are allowed in the current context. + allowCDATA bool +} + +// AllowCDATA sets whether or not the tokenizer recognizes <![CDATA[foo]]> as +// the text "foo". The default value is false, which means to recognize it as +// a bogus comment "<!-- [CDATA[foo]] -->" instead. +// +// Strictly speaking, an HTML5 compliant tokenizer should allow CDATA if and +// only if tokenizing foreign content, such as MathML and SVG. However, +// tracking foreign-contentness is difficult to do purely in the tokenizer, +// as opposed to the parser, due to HTML integration points: an <svg> element +// can contain a <foreignObject> that is foreign-to-SVG but not foreign-to- +// HTML. For strict compliance with the HTML5 tokenization algorithm, it is the +// responsibility of the user of a tokenizer to call AllowCDATA as appropriate. +// In practice, if using the tokenizer without caring whether MathML or SVG +// CDATA is text or comments, such as tokenizing HTML to find all the anchor +// text, it is acceptable to ignore this responsibility. +func (z *Tokenizer) AllowCDATA(allowCDATA bool) { + z.allowCDATA = allowCDATA +} + +// NextIsNotRawText instructs the tokenizer that the next token should not be +// considered as 'raw text'. Some elements, such as script and title elements, +// normally require the next token after the opening tag to be 'raw text' that +// has no child elements. For example, tokenizing "<title>a<b>c</b>d</title>" +// yields a start tag token for "<title>", a text token for "a<b>c</b>d", and +// an end tag token for "</title>". There are no distinct start tag or end tag +// tokens for the "<b>" and "</b>". +// +// This tokenizer implementation will generally look for raw text at the right +// times. Strictly speaking, an HTML5 compliant tokenizer should not look for +// raw text if in foreign content: <title> generally needs raw text, but a +// <title> inside an <svg> does not. Another example is that a <textarea> +// generally needs raw text, but a <textarea> is not allowed as an immediate +// child of a <select>; in normal parsing, a <textarea> implies </select>, but +// one cannot close the implicit element when parsing a <select>'s InnerHTML. +// Similarly to AllowCDATA, tracking the correct moment to override raw-text- +// ness is difficult to do purely in the tokenizer, as opposed to the parser. +// For strict compliance with the HTML5 tokenization algorithm, it is the +// responsibility of the user of a tokenizer to call NextIsNotRawText as +// appropriate. In practice, like AllowCDATA, it is acceptable to ignore this +// responsibility for basic usage. +// +// Note that this 'raw text' concept is different from the one offered by the +// Tokenizer.Raw method. +func (z *Tokenizer) NextIsNotRawText() { + z.rawTag = "" +} + +// Err returns the error associated with the most recent ErrorToken token. +// This is typically io.EOF, meaning the end of tokenization. +func (z *Tokenizer) Err() error { + if z.tt != ErrorToken { + return nil + } + return z.err +} + +// readByte returns the next byte from the input stream, doing a buffered read +// from z.r into z.buf if necessary. z.buf[z.raw.start:z.raw.end] remains a contiguous byte +// slice that holds all the bytes read so far for the current token. +// It sets z.err if the underlying reader returns an error. +// Pre-condition: z.err == nil. +func (z *Tokenizer) readByte() byte { + if z.raw.end >= len(z.buf) { + // Our buffer is exhausted and we have to read from z.r. Check if the + // previous read resulted in an error. + if z.readErr != nil { + z.err = z.readErr + return 0 + } + // We copy z.buf[z.raw.start:z.raw.end] to the beginning of z.buf. If the length + // z.raw.end - z.raw.start is more than half the capacity of z.buf, then we + // allocate a new buffer before the copy. + c := cap(z.buf) + d := z.raw.end - z.raw.start + var buf1 []byte + if 2*d > c { + buf1 = make([]byte, d, 2*c) + } else { + buf1 = z.buf[:d] + } + copy(buf1, z.buf[z.raw.start:z.raw.end]) + if x := z.raw.start; x != 0 { + // Adjust the data/attr spans to refer to the same contents after the copy. + z.data.start -= x + z.data.end -= x + z.pendingAttr[0].start -= x + z.pendingAttr[0].end -= x + z.pendingAttr[1].start -= x + z.pendingAttr[1].end -= x + for i := range z.attr { + z.attr[i][0].start -= x + z.attr[i][0].end -= x + z.attr[i][1].start -= x + z.attr[i][1].end -= x + } + } + z.raw.start, z.raw.end, z.buf = 0, d, buf1[:d] + // Now that we have copied the live bytes to the start of the buffer, + // we read from z.r into the remainder. + var n int + n, z.readErr = readAtLeastOneByte(z.r, buf1[d:cap(buf1)]) + if n == 0 { + z.err = z.readErr + return 0 + } + z.buf = buf1[:d+n] + } + x := z.buf[z.raw.end] + z.raw.end++ + if z.maxBuf > 0 && z.raw.end-z.raw.start >= z.maxBuf { + z.err = ErrBufferExceeded + return 0 + } + return x +} + +// Buffered returns a slice containing data buffered but not yet tokenized. +func (z *Tokenizer) Buffered() []byte { + return z.buf[z.raw.end:] +} + +// readAtLeastOneByte wraps an io.Reader so that reading cannot return (0, nil). +// It returns io.ErrNoProgress if the underlying r.Read method returns (0, nil) +// too many times in succession. +func readAtLeastOneByte(r io.Reader, b []byte) (int, error) { + for i := 0; i < 100; i++ { + if n, err := r.Read(b); n != 0 || err != nil { + return n, err + } + } + return 0, io.ErrNoProgress +} + +// skipWhiteSpace skips past any white space. +func (z *Tokenizer) skipWhiteSpace() { + if z.err != nil { + return + } + for { + c := z.readByte() + if z.err != nil { + return + } + switch c { + case ' ', '\n', '\r', '\t', '\f': + // No-op. + default: + z.raw.end-- + return + } + } +} + +// readRawOrRCDATA reads until the next "</foo>", where "foo" is z.rawTag and +// is typically something like "script" or "textarea". +func (z *Tokenizer) readRawOrRCDATA() { + if z.rawTag == "script" { + z.readScript() + z.textIsRaw = true + z.rawTag = "" + return + } +loop: + for { + c := z.readByte() + if z.err != nil { + break loop + } + if c != '<' { + continue loop + } + c = z.readByte() + if z.err != nil { + break loop + } + if c != '/' { + z.raw.end-- + continue loop + } + if z.readRawEndTag() || z.err != nil { + break loop + } + } + z.data.end = z.raw.end + // A textarea's or title's RCDATA can contain escaped entities. + z.textIsRaw = z.rawTag != "textarea" && z.rawTag != "title" + z.rawTag = "" +} + +// readRawEndTag attempts to read a tag like "</foo>", where "foo" is z.rawTag. +// If it succeeds, it backs up the input position to reconsume the tag and +// returns true. Otherwise it returns false. The opening "</" has already been +// consumed. +func (z *Tokenizer) readRawEndTag() bool { + for i := 0; i < len(z.rawTag); i++ { + c := z.readByte() + if z.err != nil { + return false + } + if c != z.rawTag[i] && c != z.rawTag[i]-('a'-'A') { + z.raw.end-- + return false + } + } + c := z.readByte() + if z.err != nil { + return false + } + switch c { + case ' ', '\n', '\r', '\t', '\f', '/', '>': + // The 3 is 2 for the leading "</" plus 1 for the trailing character c. + z.raw.end -= 3 + len(z.rawTag) + return true + } + z.raw.end-- + return false +} + +// readScript reads until the next </script> tag, following the byzantine +// rules for escaping/hiding the closing tag. +func (z *Tokenizer) readScript() { + defer func() { + z.data.end = z.raw.end + }() + var c byte + +scriptData: + c = z.readByte() + if z.err != nil { + return + } + if c == '<' { + goto scriptDataLessThanSign + } + goto scriptData + +scriptDataLessThanSign: + c = z.readByte() + if z.err != nil { + return + } + switch c { + case '/': + goto scriptDataEndTagOpen + case '!': + goto scriptDataEscapeStart + } + z.raw.end-- + goto scriptData + +scriptDataEndTagOpen: + if z.readRawEndTag() || z.err != nil { + return + } + goto scriptData + +scriptDataEscapeStart: + c = z.readByte() + if z.err != nil { + return + } + if c == '-' { + goto scriptDataEscapeStartDash + } + z.raw.end-- + goto scriptData + +scriptDataEscapeStartDash: + c = z.readByte() + if z.err != nil { + return + } + if c == '-' { + goto scriptDataEscapedDashDash + } + z.raw.end-- + goto scriptData + +scriptDataEscaped: + c = z.readByte() + if z.err != nil { + return + } + switch c { + case '-': + goto scriptDataEscapedDash + case '<': + goto scriptDataEscapedLessThanSign + } + goto scriptDataEscaped + +scriptDataEscapedDash: + c = z.readByte() + if z.err != nil { + return + } + switch c { + case '-': + goto scriptDataEscapedDashDash + case '<': + goto scriptDataEscapedLessThanSign + } + goto scriptDataEscaped + +scriptDataEscapedDashDash: + c = z.readByte() + if z.err != nil { + return + } + switch c { + case '-': + goto scriptDataEscapedDashDash + case '<': + goto scriptDataEscapedLessThanSign + case '>': + goto scriptData + } + goto scriptDataEscaped + +scriptDataEscapedLessThanSign: + c = z.readByte() + if z.err != nil { + return + } + if c == '/' { + goto scriptDataEscapedEndTagOpen + } + if 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' { + goto scriptDataDoubleEscapeStart + } + z.raw.end-- + goto scriptData + +scriptDataEscapedEndTagOpen: + if z.readRawEndTag() || z.err != nil { + return + } + goto scriptDataEscaped + +scriptDataDoubleEscapeStart: + z.raw.end-- + for i := 0; i < len("script"); i++ { + c = z.readByte() + if z.err != nil { + return + } + if c != "script"[i] && c != "SCRIPT"[i] { + z.raw.end-- + goto scriptDataEscaped + } + } + c = z.readByte() + if z.err != nil { + return + } + switch c { + case ' ', '\n', '\r', '\t', '\f', '/', '>': + goto scriptDataDoubleEscaped + } + z.raw.end-- + goto scriptDataEscaped + +scriptDataDoubleEscaped: + c = z.readByte() + if z.err != nil { + return + } + switch c { + case '-': + goto scriptDataDoubleEscapedDash + case '<': + goto scriptDataDoubleEscapedLessThanSign + } + goto scriptDataDoubleEscaped + +scriptDataDoubleEscapedDash: + c = z.readByte() + if z.err != nil { + return + } + switch c { + case '-': + goto scriptDataDoubleEscapedDashDash + case '<': + goto scriptDataDoubleEscapedLessThanSign + } + goto scriptDataDoubleEscaped + +scriptDataDoubleEscapedDashDash: + c = z.readByte() + if z.err != nil { + return + } + switch c { + case '-': + goto scriptDataDoubleEscapedDashDash + case '<': + goto scriptDataDoubleEscapedLessThanSign + case '>': + goto scriptData + } + goto scriptDataDoubleEscaped + +scriptDataDoubleEscapedLessThanSign: + c = z.readByte() + if z.err != nil { + return + } + if c == '/' { + goto scriptDataDoubleEscapeEnd + } + z.raw.end-- + goto scriptDataDoubleEscaped + +scriptDataDoubleEscapeEnd: + if z.readRawEndTag() { + z.raw.end += len("</script>") + goto scriptDataEscaped + } + if z.err != nil { + return + } + goto scriptDataDoubleEscaped +} + +// readComment reads the next comment token starting with "<!--". The opening +// "<!--" has already been consumed. +func (z *Tokenizer) readComment() { + // When modifying this function, consider manually increasing the + // maxSuffixLen constant in func TestComments, from 6 to e.g. 9 or more. + // That increase should only be temporary, not committed, as it + // exponentially affects the test running time. + + z.data.start = z.raw.end + defer func() { + if z.data.end < z.data.start { + // It's a comment with no data, like <!-->. + z.data.end = z.data.start + } + }() + + var dashCount int + beginning := true + for { + c := z.readByte() + if z.err != nil { + z.data.end = z.calculateAbruptCommentDataEnd() + return + } + switch c { + case '-': + dashCount++ + continue + case '>': + if dashCount >= 2 || beginning { + z.data.end = z.raw.end - len("-->") + return + } + case '!': + if dashCount >= 2 { + c = z.readByte() + if z.err != nil { + z.data.end = z.calculateAbruptCommentDataEnd() + return + } else if c == '>' { + z.data.end = z.raw.end - len("--!>") + return + } else if c == '-' { + dashCount = 1 + beginning = false + continue + } + } + } + dashCount = 0 + beginning = false + } +} + +func (z *Tokenizer) calculateAbruptCommentDataEnd() int { + raw := z.Raw() + const prefixLen = len("<!--") + if len(raw) >= prefixLen { + raw = raw[prefixLen:] + if hasSuffix(raw, "--!") { + return z.raw.end - 3 + } else if hasSuffix(raw, "--") { + return z.raw.end - 2 + } else if hasSuffix(raw, "-") { + return z.raw.end - 1 + } + } + return z.raw.end +} + +func hasSuffix(b []byte, suffix string) bool { + if len(b) < len(suffix) { + return false + } + b = b[len(b)-len(suffix):] + for i := range b { + if b[i] != suffix[i] { + return false + } + } + return true +} + +// readUntilCloseAngle reads until the next ">". +func (z *Tokenizer) readUntilCloseAngle() { + z.data.start = z.raw.end + for { + c := z.readByte() + if z.err != nil { + z.data.end = z.raw.end + return + } + if c == '>' { + z.data.end = z.raw.end - len(">") + return + } + } +} + +// readMarkupDeclaration reads the next token starting with "<!". It might be +// a "<!--comment-->", a "<!DOCTYPE foo>", a "<![CDATA[section]]>" or +// "<!a bogus comment". The opening "<!" has already been consumed. +func (z *Tokenizer) readMarkupDeclaration() TokenType { + z.data.start = z.raw.end + var c [2]byte + for i := 0; i < 2; i++ { + c[i] = z.readByte() + if z.err != nil { + z.data.end = z.raw.end + return CommentToken + } + } + if c[0] == '-' && c[1] == '-' { + z.readComment() + return CommentToken + } + z.raw.end -= 2 + if z.readDoctype() { + return DoctypeToken + } + if z.allowCDATA && z.readCDATA() { + z.convertNUL = true + return TextToken + } + // It's a bogus comment. + z.readUntilCloseAngle() + return CommentToken +} + +// readDoctype attempts to read a doctype declaration and returns true if +// successful. The opening "<!" has already been consumed. +func (z *Tokenizer) readDoctype() bool { + const s = "DOCTYPE" + for i := 0; i < len(s); i++ { + c := z.readByte() + if z.err != nil { + z.data.end = z.raw.end + return false + } + if c != s[i] && c != s[i]+('a'-'A') { + // Back up to read the fragment of "DOCTYPE" again. + z.raw.end = z.data.start + return false + } + } + if z.skipWhiteSpace(); z.err != nil { + z.data.start = z.raw.end + z.data.end = z.raw.end + return true + } + z.readUntilCloseAngle() + return true +} + +// readCDATA attempts to read a CDATA section and returns true if +// successful. The opening "<!" has already been consumed. +func (z *Tokenizer) readCDATA() bool { + const s = "[CDATA[" + for i := 0; i < len(s); i++ { + c := z.readByte() + if z.err != nil { + z.data.end = z.raw.end + return false + } + if c != s[i] { + // Back up to read the fragment of "[CDATA[" again. + z.raw.end = z.data.start + return false + } + } + z.data.start = z.raw.end + brackets := 0 + for { + c := z.readByte() + if z.err != nil { + z.data.end = z.raw.end + return true + } + switch c { + case ']': + brackets++ + case '>': + if brackets >= 2 { + z.data.end = z.raw.end - len("]]>") + return true + } + brackets = 0 + default: + brackets = 0 + } + } +} + +// startTagIn returns whether the start tag in z.buf[z.data.start:z.data.end] +// case-insensitively matches any element of ss. +func (z *Tokenizer) startTagIn(ss ...string) bool { +loop: + for _, s := range ss { + if z.data.end-z.data.start != len(s) { + continue loop + } + for i := 0; i < len(s); i++ { + c := z.buf[z.data.start+i] + if 'A' <= c && c <= 'Z' { + c += 'a' - 'A' + } + if c != s[i] { + continue loop + } + } + return true + } + return false +} + +// readStartTag reads the next start tag token. The opening "<a" has already +// been consumed, where 'a' means anything in [A-Za-z]. +func (z *Tokenizer) readStartTag() TokenType { + z.readTag(true) + if z.err != nil { + return ErrorToken + } + // Several tags flag the tokenizer's next token as raw. + c, raw := z.buf[z.data.start], false + if 'A' <= c && c <= 'Z' { + c += 'a' - 'A' + } + switch c { + case 'i': + raw = z.startTagIn("iframe") + case 'n': + raw = z.startTagIn("noembed", "noframes", "noscript") + case 'p': + raw = z.startTagIn("plaintext") + case 's': + raw = z.startTagIn("script", "style") + case 't': + raw = z.startTagIn("textarea", "title") + case 'x': + raw = z.startTagIn("xmp") + } + if raw { + z.rawTag = strings.ToLower(string(z.buf[z.data.start:z.data.end])) + } + // Look for a self-closing token like "<br/>". + if z.err == nil && z.buf[z.raw.end-2] == '/' { + return SelfClosingTagToken + } + return StartTagToken +} + +// readTag reads the next tag token and its attributes. If saveAttr, those +// attributes are saved in z.attr, otherwise z.attr is set to an empty slice. +// The opening "<a" or "</a" has already been consumed, where 'a' means anything +// in [A-Za-z]. +func (z *Tokenizer) readTag(saveAttr bool) { + z.attr = z.attr[:0] + z.nAttrReturned = 0 + // Read the tag name and attribute key/value pairs. + z.readTagName() + if z.skipWhiteSpace(); z.err != nil { + return + } + for { + c := z.readByte() + if z.err != nil || c == '>' { + break + } + z.raw.end-- + z.readTagAttrKey() + z.readTagAttrVal() + // Save pendingAttr if saveAttr and that attribute has a non-empty key. + if saveAttr && z.pendingAttr[0].start != z.pendingAttr[0].end { + z.attr = append(z.attr, z.pendingAttr) + } + if z.skipWhiteSpace(); z.err != nil { + break + } + } +} + +// readTagName sets z.data to the "div" in "<div k=v>". The reader (z.raw.end) +// is positioned such that the first byte of the tag name (the "d" in "<div") +// has already been consumed. +func (z *Tokenizer) readTagName() { + z.data.start = z.raw.end - 1 + for { + c := z.readByte() + if z.err != nil { + z.data.end = z.raw.end + return + } + switch c { + case ' ', '\n', '\r', '\t', '\f': + z.data.end = z.raw.end - 1 + return + case '/', '>': + z.raw.end-- + z.data.end = z.raw.end + return + } + } +} + +// readTagAttrKey sets z.pendingAttr[0] to the "k" in "<div k=v>". +// Precondition: z.err == nil. +func (z *Tokenizer) readTagAttrKey() { + z.pendingAttr[0].start = z.raw.end + for { + c := z.readByte() + if z.err != nil { + z.pendingAttr[0].end = z.raw.end + return + } + switch c { + case '=': + if z.pendingAttr[0].start+1 == z.raw.end { + // WHATWG 13.2.5.32, if we see an equals sign before the attribute name + // begins, we treat it as a character in the attribute name and continue. + continue + } + fallthrough + case ' ', '\n', '\r', '\t', '\f', '/', '>': + // WHATWG 13.2.5.33 Attribute name state + // We need to reconsume the char in the after attribute name state to support the / character + z.raw.end-- + z.pendingAttr[0].end = z.raw.end + return + } + } +} + +// readTagAttrVal sets z.pendingAttr[1] to the "v" in "<div k=v>". +func (z *Tokenizer) readTagAttrVal() { + z.pendingAttr[1].start = z.raw.end + z.pendingAttr[1].end = z.raw.end + if z.skipWhiteSpace(); z.err != nil { + return + } + c := z.readByte() + if z.err != nil { + return + } + if c == '/' { + // WHATWG 13.2.5.34 After attribute name state + // U+002F SOLIDUS (/) - Switch to the self-closing start tag state. + return + } + if c != '=' { + z.raw.end-- + return + } + if z.skipWhiteSpace(); z.err != nil { + return + } + quote := z.readByte() + if z.err != nil { + return + } + switch quote { + case '>': + z.raw.end-- + return + + case '\'', '"': + z.pendingAttr[1].start = z.raw.end + for { + c := z.readByte() + if z.err != nil { + z.pendingAttr[1].end = z.raw.end + return + } + if c == quote { + z.pendingAttr[1].end = z.raw.end - 1 + return + } + } + + default: + z.pendingAttr[1].start = z.raw.end - 1 + for { + c := z.readByte() + if z.err != nil { + z.pendingAttr[1].end = z.raw.end + return + } + switch c { + case ' ', '\n', '\r', '\t', '\f': + z.pendingAttr[1].end = z.raw.end - 1 + return + case '>': + z.raw.end-- + z.pendingAttr[1].end = z.raw.end + return + } + } + } +} + +// Next scans the next token and returns its type. +func (z *Tokenizer) Next() TokenType { + z.raw.start = z.raw.end + z.data.start = z.raw.end + z.data.end = z.raw.end + if z.err != nil { + z.tt = ErrorToken + return z.tt + } + if z.rawTag != "" { + if z.rawTag == "plaintext" { + // Read everything up to EOF. + for z.err == nil { + z.readByte() + } + z.data.end = z.raw.end + z.textIsRaw = true + } else { + z.readRawOrRCDATA() + } + if z.data.end > z.data.start { + z.tt = TextToken + z.convertNUL = true + return z.tt + } + } + z.textIsRaw = false + z.convertNUL = false + +loop: + for { + c := z.readByte() + if z.err != nil { + break loop + } + if c != '<' { + continue loop + } + + // Check if the '<' we have just read is part of a tag, comment + // or doctype. If not, it's part of the accumulated text token. + c = z.readByte() + if z.err != nil { + break loop + } + var tokenType TokenType + switch { + case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z': + tokenType = StartTagToken + case c == '/': + tokenType = EndTagToken + case c == '!' || c == '?': + // We use CommentToken to mean any of "<!--actual comments-->", + // "<!DOCTYPE declarations>" and "<?xml processing instructions?>". + tokenType = CommentToken + default: + // Reconsume the current character. + z.raw.end-- + continue + } + + // We have a non-text token, but we might have accumulated some text + // before that. If so, we return the text first, and return the non- + // text token on the subsequent call to Next. + if x := z.raw.end - len("<a"); z.raw.start < x { + z.raw.end = x + z.data.end = x + z.tt = TextToken + return z.tt + } + switch tokenType { + case StartTagToken: + z.tt = z.readStartTag() + return z.tt + case EndTagToken: + c = z.readByte() + if z.err != nil { + break loop + } + if c == '>' { + // "</>" does not generate a token at all. Generate an empty comment + // to allow passthrough clients to pick up the data using Raw. + // Reset the tokenizer state and start again. + z.tt = CommentToken + return z.tt + } + if 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' { + z.readTag(false) + if z.err != nil { + z.tt = ErrorToken + } else { + z.tt = EndTagToken + } + return z.tt + } + z.raw.end-- + z.readUntilCloseAngle() + z.tt = CommentToken + return z.tt + case CommentToken: + if c == '!' { + z.tt = z.readMarkupDeclaration() + return z.tt + } + z.raw.end-- + z.readUntilCloseAngle() + z.tt = CommentToken + return z.tt + } + } + if z.raw.start < z.raw.end { + z.data.end = z.raw.end + z.tt = TextToken + return z.tt + } + z.tt = ErrorToken + return z.tt +} + +// Raw returns the unmodified text of the current token. Calling Next, Token, +// Text, TagName or TagAttr may change the contents of the returned slice. +// +// The token stream's raw bytes partition the byte stream (up until an +// ErrorToken). There are no overlaps or gaps between two consecutive token's +// raw bytes. One implication is that the byte offset of the current token is +// the sum of the lengths of all previous tokens' raw bytes. +func (z *Tokenizer) Raw() []byte { + return z.buf[z.raw.start:z.raw.end] +} + +// convertNewlines converts "\r" and "\r\n" in s to "\n". +// The conversion happens in place, but the resulting slice may be shorter. +func convertNewlines(s []byte) []byte { + for i, c := range s { + if c != '\r' { + continue + } + + src := i + 1 + if src >= len(s) || s[src] != '\n' { + s[i] = '\n' + continue + } + + dst := i + for src < len(s) { + if s[src] == '\r' { + if src+1 < len(s) && s[src+1] == '\n' { + src++ + } + s[dst] = '\n' + } else { + s[dst] = s[src] + } + src++ + dst++ + } + return s[:dst] + } + return s +} + +var ( + nul = []byte("\x00") + replacement = []byte("\ufffd") +) + +// Text returns the unescaped text of a text, comment or doctype token. The +// contents of the returned slice may change on the next call to Next. +func (z *Tokenizer) Text() []byte { + switch z.tt { + case TextToken, CommentToken, DoctypeToken: + s := z.buf[z.data.start:z.data.end] + z.data.start = z.raw.end + z.data.end = z.raw.end + s = convertNewlines(s) + if (z.convertNUL || z.tt == CommentToken) && bytes.Contains(s, nul) { + s = bytes.Replace(s, nul, replacement, -1) + } + if !z.textIsRaw { + s = unescape(s, false) + } + return s + } + return nil +} + +// TagName returns the lower-cased name of a tag token (the `img` out of +// `<IMG SRC="foo">`) and whether the tag has attributes. +// The contents of the returned slice may change on the next call to Next. +func (z *Tokenizer) TagName() (name []byte, hasAttr bool) { + if z.data.start < z.data.end { + switch z.tt { + case StartTagToken, EndTagToken, SelfClosingTagToken: + s := z.buf[z.data.start:z.data.end] + z.data.start = z.raw.end + z.data.end = z.raw.end + return lower(s), z.nAttrReturned < len(z.attr) + } + } + return nil, false +} + +// TagAttr returns the lower-cased key and unescaped value of the next unparsed +// attribute for the current tag token and whether there are more attributes. +// The contents of the returned slices may change on the next call to Next. +func (z *Tokenizer) TagAttr() (key, val []byte, moreAttr bool) { + if z.nAttrReturned < len(z.attr) { + switch z.tt { + case StartTagToken, SelfClosingTagToken: + x := z.attr[z.nAttrReturned] + z.nAttrReturned++ + key = z.buf[x[0].start:x[0].end] + val = z.buf[x[1].start:x[1].end] + return lower(key), unescape(convertNewlines(val), true), z.nAttrReturned < len(z.attr) + } + } + return nil, nil, false +} + +// Token returns the current Token. The result's Data and Attr values remain +// valid after subsequent Next calls. +func (z *Tokenizer) Token() Token { + t := Token{Type: z.tt} + switch z.tt { + case TextToken, CommentToken, DoctypeToken: + t.Data = string(z.Text()) + case StartTagToken, SelfClosingTagToken, EndTagToken: + name, moreAttr := z.TagName() + for moreAttr { + var key, val []byte + key, val, moreAttr = z.TagAttr() + t.Attr = append(t.Attr, Attribute{"", atom.String(key), string(val)}) + } + if a := atom.Lookup(name); a != 0 { + t.DataAtom, t.Data = a, a.String() + } else { + t.DataAtom, t.Data = 0, string(name) + } + } + return t +} + +// SetMaxBuf sets a limit on the amount of data buffered during tokenization. +// A value of 0 means unlimited. +func (z *Tokenizer) SetMaxBuf(n int) { + z.maxBuf = n +} + +// NewTokenizer returns a new HTML Tokenizer for the given Reader. +// The input is assumed to be UTF-8 encoded. +func NewTokenizer(r io.Reader) *Tokenizer { + return NewTokenizerFragment(r, "") +} + +// NewTokenizerFragment returns a new HTML Tokenizer for the given Reader, for +// tokenizing an existing element's InnerHTML fragment. contextTag is that +// element's tag, such as "div" or "iframe". +// +// For example, how the InnerHTML "a<b" is tokenized depends on whether it is +// for a <p> tag or a <script> tag. +// +// The input is assumed to be UTF-8 encoded. +func NewTokenizerFragment(r io.Reader, contextTag string) *Tokenizer { + z := &Tokenizer{ + r: r, + buf: make([]byte, 0, 4096), + } + if contextTag != "" { + switch s := strings.ToLower(contextTag); s { + case "iframe", "noembed", "noframes", "noscript", "plaintext", "script", "style", "title", "textarea", "xmp": + z.rawTag = s + } + } + return z +} diff --git a/vendor/modules.txt b/vendor/modules.txt index de4beca58c..57eb2e3288 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -154,8 +154,8 @@ github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/options github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/shared github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/version github.com/AzureAD/microsoft-authentication-library-for-go/apps/public -# github.com/IBM/go-sdk-core/v5 v5.14.1 -## explicit; go 1.19 +# github.com/IBM/go-sdk-core/v5 v5.17.4 +## explicit; go 1.20 github.com/IBM/go-sdk-core/v5/core # github.com/IBM/ibm-cos-sdk-go v1.10.0 ## explicit; go 1.11 @@ -200,8 +200,8 @@ github.com/IBM/ibm-cos-sdk-go/private/protocol/xml/xmlutil github.com/IBM/ibm-cos-sdk-go/service/s3 github.com/IBM/ibm-cos-sdk-go/service/s3/s3iface github.com/IBM/ibm-cos-sdk-go/service/s3/s3manager -# github.com/IBM/platform-services-go-sdk v0.55.0 -## explicit; go 1.19 +# github.com/IBM/platform-services-go-sdk v0.67.0 +## explicit; go 1.20 github.com/IBM/platform-services-go-sdk/common github.com/IBM/platform-services-go-sdk/resourcecontrollerv2 github.com/IBM/platform-services-go-sdk/resourcemanagerv2 @@ -310,6 +310,12 @@ github.com/felixge/httpsnoop # github.com/fsnotify/fsnotify v1.7.0 ## explicit; go 1.17 github.com/fsnotify/fsnotify +# github.com/gabriel-vasile/mimetype v1.4.3 +## explicit; go 1.20 +github.com/gabriel-vasile/mimetype +github.com/gabriel-vasile/mimetype/internal/charset +github.com/gabriel-vasile/mimetype/internal/json +github.com/gabriel-vasile/mimetype/internal/magic # github.com/ghodss/yaml v1.0.0 ## explicit github.com/ghodss/yaml @@ -320,8 +326,8 @@ github.com/go-logr/logr/funcr # github.com/go-logr/stdr v1.2.2 ## explicit; go 1.16 github.com/go-logr/stdr -# github.com/go-openapi/errors v0.20.3 -## explicit; go 1.14 +# github.com/go-openapi/errors v0.21.0 +## explicit; go 1.19 github.com/go-openapi/errors # github.com/go-openapi/jsonpointer v0.19.6 ## explicit; go 1.13 @@ -330,8 +336,8 @@ github.com/go-openapi/jsonpointer ## explicit; go 1.13 github.com/go-openapi/jsonreference github.com/go-openapi/jsonreference/internal -# github.com/go-openapi/strfmt v0.21.5 -## explicit; go 1.13 +# github.com/go-openapi/strfmt v0.22.1 +## explicit; go 1.19 github.com/go-openapi/strfmt # github.com/go-openapi/swag v0.22.3 ## explicit; go 1.18 @@ -343,7 +349,7 @@ github.com/go-playground/locales/currency # github.com/go-playground/universal-translator v0.18.1 ## explicit; go 1.18 github.com/go-playground/universal-translator -# github.com/go-playground/validator/v10 v10.13.0 +# github.com/go-playground/validator/v10 v10.19.0 ## explicit; go 1.18 github.com/go-playground/validator/v10 # github.com/gofrs/uuid/v5 v5.2.0 @@ -515,9 +521,10 @@ github.com/json-iterator/go ## explicit; go 1.11 github.com/kylelemons/godebug/diff github.com/kylelemons/godebug/pretty -# github.com/leodido/go-urn v1.2.3 -## explicit; go 1.16 +# github.com/leodido/go-urn v1.4.0 +## explicit; go 1.18 github.com/leodido/go-urn +github.com/leodido/go-urn/scim/schema # github.com/mailru/easyjson v0.7.7 ## explicit; go 1.12 github.com/mailru/easyjson/buffer @@ -791,8 +798,8 @@ go.etcd.io/etcd/client/v3 go.etcd.io/etcd/client/v3/credentials go.etcd.io/etcd/client/v3/internal/endpoint go.etcd.io/etcd/client/v3/internal/resolver -# go.mongodb.org/mongo-driver v1.11.3 -## explicit; go 1.13 +# go.mongodb.org/mongo-driver v1.14.0 +## explicit; go 1.18 go.mongodb.org/mongo-driver/bson go.mongodb.org/mongo-driver/bson/bsoncodec go.mongodb.org/mongo-driver/bson/bsonoptions @@ -914,6 +921,8 @@ golang.org/x/exp/slices # golang.org/x/net v0.27.0 ## explicit; go 1.18 golang.org/x/net/context +golang.org/x/net/html +golang.org/x/net/html/atom golang.org/x/net/http/httpguts golang.org/x/net/http/httpproxy golang.org/x/net/http2