diff --git a/go.mod b/go.mod
index dba493af1e5..4cf78d736a2 100644
--- a/go.mod
+++ b/go.mod
@@ -22,7 +22,7 @@ require (
github.com/golang/snappy v0.0.4
github.com/google/gopacket v1.1.19
github.com/gorilla/mux v1.8.1
- github.com/grafana/dskit v0.0.0-20250106205746-3702098cbd0c
+ github.com/grafana/dskit v0.0.0-20250106220817-6eb1cce03889
github.com/grafana/e2e v0.1.2-0.20240118170847-db90b84177fc
github.com/hashicorp/golang-lru v1.0.2 // indirect
github.com/json-iterator/go v1.1.12
@@ -97,13 +97,15 @@ require (
require (
cloud.google.com/go/auth v0.10.2 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.5 // indirect
+ dario.cat/mergo v1.0.1 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect
+ github.com/CrowdStrike/csproto v0.33.0 // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
- github.com/Masterminds/semver/v3 v3.1.1 // indirect
- github.com/Masterminds/sprig/v3 v3.2.1 // indirect
+ github.com/Masterminds/semver/v3 v3.3.0 // indirect
+ github.com/Masterminds/sprig/v3 v3.3.0 // indirect
github.com/at-wat/mqtt-go v0.19.4 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.4 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.5 // indirect
@@ -122,19 +124,18 @@ require (
github.com/hashicorp/go-secure-stdlib/parseutil v0.1.7 // indirect
github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect
github.com/hashicorp/hcl v1.0.1-vault-5 // indirect
- github.com/huandu/xstrings v1.3.2 // indirect
- github.com/imdario/mergo v0.3.16 // indirect
+ github.com/huandu/xstrings v1.5.0 // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
github.com/mdlayher/socket v0.4.1 // indirect
github.com/mdlayher/vsock v1.2.1 // indirect
- github.com/mitchellh/copystructure v1.0.0 // indirect
- github.com/mitchellh/reflectwalk v1.0.0 // indirect
+ github.com/mitchellh/copystructure v1.2.0 // indirect
+ github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/pires/go-proxyproto v0.7.0 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/prometheus/sigv4 v0.1.0 // indirect
github.com/ryanuber/go-glob v1.0.0 // indirect
- github.com/shopspring/decimal v1.2.0 // indirect
- github.com/spf13/cast v1.5.0 // indirect
+ github.com/shopspring/decimal v1.4.0 // indirect
+ github.com/spf13/cast v1.7.0 // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect
diff --git a/go.sum b/go.sum
index 973ab8a936b..0fa3d3835ef 100644
--- a/go.sum
+++ b/go.sum
@@ -764,6 +764,8 @@ cloud.google.com/go/workflows v1.8.0/go.mod h1:ysGhmEajwZxGn1OhGOGKsTXc5PyxOc0vf
cloud.google.com/go/workflows v1.9.0/go.mod h1:ZGkj1aFIOd9c8Gerkjjq7OW7I5+l6cSvT3ujaO/WwSA=
cloud.google.com/go/workflows v1.10.0/go.mod h1:fZ8LmRmZQWacon9UCX1r/g/DfAXx5VcPALq2CxzdePw=
cloud.google.com/go/workflows v1.11.1/go.mod h1:Z+t10G1wF7h8LgdY/EmRcQY8ptBD/nvofaL6FqlET6g=
+dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
+dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8=
git.sr.ht/~sbinet/gg v0.3.1/go.mod h1:KGYtlADtqsqANL9ueOFkWymvzUvLMQllU5Ixo+8v3pc=
@@ -791,6 +793,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/Code-Hex/go-generics-cache v1.5.1 h1:6vhZGc5M7Y/YD8cIUcY8kcuQLB4cHR7U+0KMqAA0KcU=
github.com/Code-Hex/go-generics-cache v1.5.1/go.mod h1:qxcC9kRVrct9rHeiYpFWSoW1vxyillCVzX13KZG8dl4=
+github.com/CrowdStrike/csproto v0.33.0 h1:xdGHWB/WFcAwV1OmxCSOkoUcRrQRc3fDDKcKRCN0Zlg=
+github.com/CrowdStrike/csproto v0.33.0/go.mod h1:quhKDsPpKaXwLWgG5xvW47QCtlmV41of4gRmMZrSxEs=
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
github.com/DmitriyVTitov/size v1.5.0 h1:/PzqxYrOyOUX1BXj6J9OuVRVGe+66VL4D9FlUaW515g=
github.com/DmitriyVTitov/size v1.5.0/go.mod h1:le6rNI4CoLQV1b9gzp1+3d7hMAD/uu2QcJ+aYbNgiU0=
@@ -799,10 +803,10 @@ github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXY
github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk=
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
-github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc=
-github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
-github.com/Masterminds/sprig/v3 v3.2.1 h1:n6EPaDyLSvCEa3frruQvAiHuNp2dhBlMSmkEr+HuzGc=
-github.com/Masterminds/sprig/v3 v3.2.1/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk=
+github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0=
+github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
+github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs=
+github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0=
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
@@ -1014,8 +1018,9 @@ github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
-github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
+github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
+github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
@@ -1229,7 +1234,6 @@ github.com/google/s2a-go v0.1.3/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkj
github.com/google/s2a-go v0.1.4/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A=
github.com/google/s2a-go v0.1.8 h1:zZDs9gcbt9ZPLV0ndSyQk6Kacx2g/X+SKYovpnz3SMM=
github.com/google/s2a-go v0.1.8/go.mod h1:6iNWHTpQ+nfNRN5E00MSdfDwVesa8hhS32PhPO8deJA=
-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=
@@ -1271,8 +1275,8 @@ github.com/grafana-tools/sdk v0.0.0-20220919052116-6562121319fc h1:PXZQA2WCxe85T
github.com/grafana-tools/sdk v0.0.0-20220919052116-6562121319fc/go.mod h1:AHHlOEv1+GGQ3ktHMlhuTUwo3zljV3QJbC0+8o2kn+4=
github.com/grafana/alerting v0.0.0-20241211182001-0f317eb6b2f7 h1:VGLUQ2mwzlF1NGwTxpSfv1RnuOsDlNh/NT5KRvhZ0sQ=
github.com/grafana/alerting v0.0.0-20241211182001-0f317eb6b2f7/go.mod h1:QsnoKX/iYZxA4Cv+H+wC7uxutBD8qi8ZW5UJvD2TYmU=
-github.com/grafana/dskit v0.0.0-20250106205746-3702098cbd0c h1:zixK7kthU3M9Wo0tIxdKmM0X2DHDQeqwvfrhRqRXQbk=
-github.com/grafana/dskit v0.0.0-20250106205746-3702098cbd0c/go.mod h1:SPLNCARd4xdjCkue0O6hvuoveuS1dGJjDnfxYe405YQ=
+github.com/grafana/dskit v0.0.0-20250106220817-6eb1cce03889 h1:XNwjvRrWfCNBih3I4WCrLKJPUMQ+6vWZfDzgELCpnvU=
+github.com/grafana/dskit v0.0.0-20250106220817-6eb1cce03889/go.mod h1:wGJd0nMgUTuFhkyMMuPiWUvfOaoBmn2A3LOew29i8KI=
github.com/grafana/e2e v0.1.2-0.20240118170847-db90b84177fc h1:BW+LjKJDz0So5LI8UZfW5neWeKpSkWqhmGjQFzcFfLM=
github.com/grafana/e2e v0.1.2-0.20240118170847-db90b84177fc/go.mod h1:JVmqPBe8A/pZWwRoJW5ZjyALeY5OXMzPl7LrVXOdZAI=
github.com/grafana/franz-go v0.0.0-20241009100846-782ba1442937 h1:fwwnG/NcygoS6XbAaEyK2QzMXI/BZIEJvQ3CD+7XZm8=
@@ -1379,9 +1383,8 @@ github.com/hetznercloud/hcloud-go/v2 v2.17.0 h1:ge0w2piey9SV6XGyU/wQ6HBR24QyMbJ3
github.com/hetznercloud/hcloud-go/v2 v2.17.0/go.mod h1:zfyZ4Orx+mPpYDzWAxXR7DHGL50nnlZ5Edzgs1o6f/s=
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
-github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
-github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw=
-github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
+github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI=
+github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/huaweicloud/huaweicloud-sdk-go-obs v3.23.3+incompatible h1:tKTaPHNVwikS3I1rdyf1INNvgJXWSf/+TzqsiGbrgnQ=
github.com/huaweicloud/huaweicloud-sdk-go-obs v3.23.3+incompatible/go.mod h1:l7VUhRbTKCzdOacdT4oWCwATKyvZqUOlOqr0Ous3k4s=
github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
@@ -1389,7 +1392,6 @@ github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw=
-github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
@@ -1504,8 +1506,8 @@ github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceT
github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI=
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ=
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw=
-github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ=
-github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
+github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
+github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
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/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
@@ -1518,8 +1520,8 @@ github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR
github.com/mitchellh/mapstructure v1.4.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/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY=
-github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
+github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
+github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -1666,8 +1668,8 @@ github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/shirou/gopsutil/v4 v4.24.12 h1:qvePBOk20e0IKA1QXrIIU+jmk+zEiYVVx06WjBRlZo4=
github.com/shirou/gopsutil/v4 v4.24.12/go.mod h1:DCtMPAad2XceTeIAbGyVfycbYQNBGk2P8cvDi7/VN9o=
-github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ=
-github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
+github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=
+github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c h1:aqg5Vm5dwtvL+YgDpBcK1ITf3o96N/K7/wsRXQnUTEs=
github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c/go.mod h1:owqhoLW1qZoYLZzLnBw+QkPP9WZnjlSWihhxAJC1+/M=
github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546 h1:pXY9qYc/MP5zdvqWEUH6SjNiu7VhSjuVFTFiTcphaLU=
@@ -1687,9 +1689,9 @@ github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcD
github.com/spf13/afero v1.10.0/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ=
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
-github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
-github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU=
+github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w=
+github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
@@ -1705,7 +1707,6 @@ github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
-github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
@@ -1826,7 +1827,6 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
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=
diff --git a/pkg/distributor/query.go.patch b/pkg/distributor/query.go.patch
new file mode 100644
index 00000000000..92a3014f217
--- /dev/null
+++ b/pkg/distributor/query.go.patch
@@ -0,0 +1,32 @@
+diff --git a/pkg/distributor/query.go b/pkg/distributor/query.go
+index 2b766f30f4..41d83b124f 100644
+--- a/pkg/distributor/query.go
++++ b/pkg/distributor/query.go
+@@ -337,15 +337,20 @@ func (d *Distributor) queryIngesterStream(ctx context.Context, replicationSets [
+ for _, batch := range res.chunkseriesBatches {
+ for _, series := range batch {
+ key := mimirpb.FromLabelAdaptersToKeyString(series.Labels)
+- existing := hashToChunkseries[key]
+- existing.Labels = series.Labels
++ if existing, ok := hashToChunkseries[key]; ok {
++ existing.Labels = series.Labels
+
+- numPotentialChunks := len(existing.Chunks) + len(series.Chunks)
+- existing.Chunks = ingester_client.AccumulateChunks(existing.Chunks, series.Chunks)
++ numPotentialChunks := len(existing.Chunks) + len(series.Chunks)
++ existing.Chunks = ingester_client.AccumulateChunks(existing.Chunks, series.Chunks)
+
+- deduplicatedChunks += numPotentialChunks - len(existing.Chunks)
+- totalChunks += len(series.Chunks)
+- hashToChunkseries[key] = existing
++ deduplicatedChunks += numPotentialChunks - len(existing.Chunks)
++ totalChunks += len(series.Chunks)
++ hashToChunkseries[key] = existing
++ } else {
++ // no existing series to dedupe
++ totalChunks += len(series.Chunks)
++ hashToChunkseries[key] = series
++ }
+ }
+ }
+
diff --git a/pkg/frontend/v1/frontendv1pb/frontend.pb.go b/pkg/frontend/v1/frontendv1pb/frontend.pb.go
index 305178a0d45..4e8e7364d13 100644
--- a/pkg/frontend/v1/frontendv1pb/frontend.pb.go
+++ b/pkg/frontend/v1/frontendv1pb/frontend.pb.go
@@ -75,22 +75,13 @@ func (m *FrontendToClient) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *FrontendToClient) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
- if deterministic {
- return xxx_messageInfo_FrontendToClient.Marshal(b, m, deterministic)
- } else {
- b = b[:cap(b)]
- n, err := m.MarshalToSizedBuffer(b)
- if err != nil {
- return nil, err
- }
- return b[:n], nil
- }
+ return xxx_messageInfo_FrontendToClient.Marshal(b, m, deterministic)
}
func (m *FrontendToClient) XXX_Merge(src proto.Message) {
xxx_messageInfo_FrontendToClient.Merge(m, src)
}
func (m *FrontendToClient) XXX_Size() int {
- return m.Size()
+ return xxx_messageInfo_FrontendToClient.Size(m)
}
func (m *FrontendToClient) XXX_DiscardUnknown() {
xxx_messageInfo_FrontendToClient.DiscardUnknown(m)
@@ -141,22 +132,13 @@ func (m *ClientToFrontend) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *ClientToFrontend) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
- if deterministic {
- return xxx_messageInfo_ClientToFrontend.Marshal(b, m, deterministic)
- } else {
- b = b[:cap(b)]
- n, err := m.MarshalToSizedBuffer(b)
- if err != nil {
- return nil, err
- }
- return b[:n], nil
- }
+ return xxx_messageInfo_ClientToFrontend.Marshal(b, m, deterministic)
}
func (m *ClientToFrontend) XXX_Merge(src proto.Message) {
xxx_messageInfo_ClientToFrontend.Merge(m, src)
}
func (m *ClientToFrontend) XXX_Size() int {
- return m.Size()
+ return xxx_messageInfo_ClientToFrontend.Size(m)
}
func (m *ClientToFrontend) XXX_DiscardUnknown() {
xxx_messageInfo_ClientToFrontend.DiscardUnknown(m)
@@ -274,39 +256,39 @@ func init() {
func init() { proto.RegisterFile("frontend.proto", fileDescriptor_eca3873955a29cfe) }
var fileDescriptor_eca3873955a29cfe = []byte{
- // 498 bytes of a gzipped FileDescriptorProto
- 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x92, 0x41, 0x6e, 0xd3, 0x40,
- 0x14, 0x86, 0xfd, 0x68, 0x28, 0xe1, 0xc5, 0x8a, 0xac, 0x51, 0x41, 0x91, 0x41, 0xa3, 0xc8, 0x82,
- 0xca, 0x62, 0x61, 0x97, 0x20, 0x81, 0x60, 0x59, 0x1a, 0x4a, 0x37, 0x55, 0x71, 0xcc, 0x86, 0x4d,
- 0xe5, 0x24, 0x13, 0xc7, 0x6a, 0xe3, 0x71, 0xec, 0x31, 0x28, 0x3b, 0x4e, 0x80, 0x38, 0x06, 0x67,
- 0x80, 0x0b, 0xb0, 0xcc, 0xb2, 0x4b, 0xe2, 0x6c, 0x58, 0xf6, 0x08, 0xc8, 0x9e, 0xc4, 0x4d, 0xa2,
- 0x88, 0x6e, 0x46, 0x33, 0xf3, 0xbf, 0xf7, 0xfc, 0xfd, 0xbf, 0x07, 0xeb, 0x83, 0x98, 0x87, 0x82,
- 0x85, 0x7d, 0x2b, 0x8a, 0xb9, 0xe0, 0xa4, 0xba, 0x3c, 0xeb, 0x7b, 0x3e, 0xf7, 0x79, 0x71, 0x69,
- 0xe7, 0x3b, 0xa9, 0xeb, 0x07, 0x7e, 0x20, 0x86, 0x69, 0xd7, 0xea, 0xf1, 0x91, 0xed, 0xc7, 0xde,
- 0xc0, 0x0b, 0x3d, 0xbb, 0x9f, 0x5c, 0x04, 0xc2, 0x1e, 0x0a, 0x11, 0xf9, 0x71, 0xd4, 0x2b, 0x37,
- 0x8b, 0x8e, 0x97, 0x5b, 0x3a, 0x46, 0xc1, 0x28, 0x88, 0xed, 0xe8, 0xc2, 0xb7, 0xc7, 0x29, 0x8b,
- 0x03, 0x16, 0xdb, 0x89, 0xf0, 0x44, 0x22, 0x57, 0xd9, 0x67, 0xfc, 0x02, 0xd4, 0xde, 0x2d, 0x60,
- 0x5c, 0xfe, 0xf6, 0x32, 0x60, 0xa1, 0x20, 0xaf, 0xb0, 0x96, 0x8f, 0x77, 0xd8, 0x38, 0x65, 0x89,
- 0x68, 0x40, 0x13, 0xcc, 0x5a, 0xeb, 0x81, 0x55, 0x7e, 0xf2, 0xbd, 0xeb, 0x9e, 0x2d, 0x44, 0x67,
- 0xb5, 0x92, 0x18, 0x58, 0x11, 0x93, 0x88, 0x35, 0xee, 0x34, 0xc1, 0xac, 0xb7, 0xea, 0x56, 0x69,
- 0xdb, 0x9d, 0x44, 0xcc, 0x29, 0x34, 0x62, 0xa0, 0x5a, 0x00, 0xb4, 0x43, 0xaf, 0x7b, 0xc9, 0xfa,
- 0x8d, 0x9d, 0x26, 0x98, 0x55, 0x67, 0xed, 0x8e, 0xec, 0x63, 0x7d, 0x9c, 0xb2, 0x94, 0xb9, 0xc1,
- 0x88, 0x9d, 0x7a, 0x21, 0x4f, 0x1a, 0x95, 0x26, 0x98, 0x3b, 0xce, 0xc6, 0xad, 0xf1, 0x0d, 0x50,
- 0x93, 0xcc, 0x2e, 0x5f, 0xba, 0x20, 0x6f, 0x50, 0x95, 0x4c, 0x49, 0xc4, 0xc3, 0x84, 0x2d, 0xf0,
- 0x1f, 0x6e, 0xe2, 0x4b, 0xd5, 0x59, 0xab, 0x25, 0x3a, 0x56, 0x7b, 0xc5, 0xbc, 0x93, 0xa3, 0xc2,
- 0xc4, 0x7d, 0xa7, 0x3c, 0x13, 0x03, 0xef, 0x16, 0x90, 0x05, 0x71, 0xad, 0xa5, 0x5a, 0x32, 0xc7,
- 0x4e, 0xbe, 0x3a, 0x52, 0x32, 0x5e, 0xe3, 0xa3, 0x53, 0x2e, 0x82, 0xc1, 0x44, 0x52, 0x75, 0x86,
- 0xa9, 0xe8, 0xf3, 0x2f, 0xe1, 0x32, 0x9f, 0xd5, 0xf1, 0xb0, 0x3e, 0xde, 0xa0, 0xf8, 0x78, 0x7b,
- 0xab, 0x44, 0x7b, 0xf6, 0x04, 0x2b, 0x79, 0x8a, 0x44, 0x43, 0x35, 0x37, 0x70, 0xee, 0xb4, 0x3f,
- 0x7c, 0x6c, 0x77, 0x5c, 0x4d, 0x21, 0x88, 0xbb, 0xc7, 0x6d, 0xf7, 0xfc, 0xe4, 0x48, 0x83, 0xd6,
- 0x4f, 0xc0, 0x6a, 0x99, 0xc4, 0x31, 0xde, 0x3b, 0x8b, 0x79, 0x8f, 0x25, 0x09, 0xd1, 0x6f, 0xfe,
- 0xc5, 0x66, 0x60, 0xfa, 0x8a, 0xb6, 0xf9, 0x14, 0x0c, 0xc5, 0x84, 0x03, 0x20, 0x0c, 0xf7, 0xb6,
- 0xb1, 0x91, 0xa7, 0x37, 0x9d, 0xff, 0xb1, 0xad, 0xef, 0xdf, 0x56, 0x26, 0x2d, 0x1e, 0x1e, 0x4e,
- 0x67, 0x54, 0xb9, 0x9a, 0x51, 0xe5, 0x7a, 0x46, 0xe1, 0x6b, 0x46, 0xe1, 0x47, 0x46, 0xe1, 0x77,
- 0x46, 0x61, 0x9a, 0x51, 0xf8, 0x93, 0x51, 0xf8, 0x9b, 0x51, 0xe5, 0x3a, 0xa3, 0xf0, 0x7d, 0x4e,
- 0x95, 0xe9, 0x9c, 0x2a, 0x57, 0x73, 0xaa, 0x7c, 0x52, 0x97, 0xc3, 0x3f, 0x3f, 0x8f, 0xba, 0xdd,
- 0xdd, 0xe2, 0x5d, 0xbf, 0xf8, 0x17, 0x00, 0x00, 0xff, 0xff, 0x90, 0xf8, 0xe3, 0x38, 0x73, 0x03,
- 0x00, 0x00,
+ // 511 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x92, 0xbf, 0x6f, 0xd3, 0x40,
+ 0x14, 0xc7, 0xef, 0x68, 0x29, 0xe6, 0xc5, 0x8a, 0xac, 0x53, 0x41, 0x91, 0x41, 0xd7, 0xc8, 0x82,
+ 0xca, 0x62, 0xb0, 0x4b, 0x90, 0x40, 0x74, 0x2c, 0x0d, 0xa5, 0x4b, 0x55, 0x1c, 0xb3, 0xb0, 0x54,
+ 0x4e, 0x72, 0x71, 0xac, 0x36, 0x3e, 0xc7, 0x3e, 0x83, 0xb2, 0x31, 0x32, 0x32, 0x32, 0xc2, 0xc6,
+ 0xdf, 0xc0, 0x8e, 0xc4, 0x98, 0xb1, 0x23, 0x71, 0x96, 0x8e, 0xfd, 0x13, 0x90, 0x7d, 0x89, 0x9b,
+ 0x44, 0x11, 0x2c, 0xd6, 0xdd, 0xfb, 0xbe, 0x1f, 0x9f, 0xef, 0xf3, 0x41, 0xb5, 0x17, 0xf3, 0x50,
+ 0xb0, 0xb0, 0x6b, 0x45, 0x31, 0x17, 0x9c, 0x28, 0xf3, 0xbb, 0xbe, 0xed, 0x73, 0x9f, 0x17, 0x41,
+ 0x3b, 0x3f, 0x49, 0x5d, 0xdf, 0xf3, 0x03, 0xd1, 0x4f, 0xdb, 0x56, 0x87, 0x0f, 0x6c, 0x3f, 0xf6,
+ 0x7a, 0x5e, 0xe8, 0xd9, 0xdd, 0xe4, 0x3c, 0x10, 0x76, 0x5f, 0x88, 0xc8, 0x8f, 0xa3, 0x4e, 0x79,
+ 0x98, 0x55, 0x3c, 0x5f, 0x53, 0x31, 0x08, 0x06, 0x41, 0x6c, 0x47, 0xe7, 0xbe, 0x3d, 0x4c, 0x59,
+ 0x1c, 0xb0, 0xd8, 0x4e, 0x84, 0x27, 0x12, 0xf9, 0x95, 0x75, 0xc6, 0x2f, 0x0c, 0xda, 0xeb, 0x19,
+ 0x8c, 0xcb, 0x5f, 0x5d, 0x04, 0x2c, 0x14, 0xe4, 0x05, 0x54, 0xf2, 0xf6, 0x0e, 0x1b, 0xa6, 0x2c,
+ 0x11, 0x35, 0x5c, 0xc7, 0x66, 0xa5, 0x71, 0xcf, 0x2a, 0x47, 0xbe, 0x71, 0xdd, 0xd3, 0x99, 0xe8,
+ 0x2c, 0x66, 0x12, 0x03, 0x36, 0xc5, 0x28, 0x62, 0xb5, 0x5b, 0x75, 0x6c, 0x56, 0x1b, 0x55, 0xab,
+ 0xb4, 0xed, 0x8e, 0x22, 0xe6, 0x14, 0x1a, 0x31, 0x40, 0x2d, 0x00, 0x9a, 0xa1, 0xd7, 0xbe, 0x60,
+ 0xdd, 0xda, 0x46, 0x1d, 0x9b, 0x8a, 0xb3, 0x14, 0x23, 0xbb, 0x50, 0x1d, 0xa6, 0x2c, 0x65, 0x6e,
+ 0x30, 0x60, 0x27, 0x5e, 0xc8, 0x93, 0xda, 0x66, 0x1d, 0x9b, 0x1b, 0xce, 0x4a, 0x74, 0x5f, 0xb9,
+ 0xfa, 0xb6, 0x83, 0x3e, 0x7f, 0xdf, 0x41, 0xc6, 0x57, 0x0c, 0x9a, 0xa4, 0x77, 0xf9, 0xdc, 0x0f,
+ 0xd9, 0x07, 0x55, 0xd2, 0x25, 0x11, 0x0f, 0x13, 0x36, 0x33, 0x72, 0x7f, 0xd5, 0x88, 0x54, 0x9d,
+ 0xa5, 0x5c, 0xa2, 0x83, 0xd2, 0x29, 0xfa, 0x1d, 0x1f, 0x16, 0x76, 0xee, 0x3a, 0xe5, 0x9d, 0x18,
+ 0x70, 0xbb, 0xc0, 0x2d, 0xd8, 0x2b, 0x0d, 0xd5, 0x92, 0x1b, 0x6d, 0xe5, 0x5f, 0x47, 0x4a, 0x0b,
+ 0x68, 0x2f, 0xe1, 0xc1, 0x09, 0x17, 0x41, 0x6f, 0x24, 0xf9, 0x5a, 0xfd, 0x54, 0x74, 0xf9, 0xc7,
+ 0x70, 0xbe, 0xb3, 0xc5, 0x41, 0x78, 0x79, 0x90, 0x41, 0xe1, 0xe1, 0xfa, 0x52, 0x09, 0xf9, 0xe4,
+ 0x11, 0x6c, 0xe6, 0x9b, 0x25, 0x1a, 0xa8, 0xb9, 0x95, 0x33, 0xa7, 0xf9, 0xf6, 0x5d, 0xb3, 0xe5,
+ 0x6a, 0x88, 0x00, 0x6c, 0x1d, 0x35, 0xdd, 0xb3, 0xe3, 0x43, 0x0d, 0x37, 0x7e, 0x62, 0x50, 0xca,
+ 0x9d, 0x1c, 0xc1, 0x9d, 0xd3, 0x98, 0x77, 0x58, 0x92, 0x10, 0xfd, 0xe6, 0xff, 0xac, 0xae, 0x4e,
+ 0x5f, 0xd0, 0x56, 0x9f, 0x87, 0x81, 0x4c, 0xbc, 0x87, 0x09, 0x83, 0xed, 0x75, 0x6c, 0xe4, 0xf1,
+ 0x4d, 0xe5, 0x3f, 0x6c, 0xeb, 0xbb, 0xff, 0x4b, 0x93, 0x16, 0x0f, 0x0e, 0xc6, 0x13, 0x8a, 0x2e,
+ 0x27, 0x14, 0x5d, 0x4f, 0x28, 0xfe, 0x94, 0x51, 0xfc, 0x23, 0xa3, 0xf8, 0x77, 0x46, 0xf1, 0x38,
+ 0xa3, 0xf8, 0x4f, 0x46, 0xf1, 0x55, 0x46, 0xd1, 0x75, 0x46, 0xf1, 0x97, 0x29, 0x45, 0xe3, 0x29,
+ 0x45, 0x97, 0x53, 0x8a, 0xde, 0xab, 0xf3, 0xe6, 0x1f, 0x9e, 0x46, 0xed, 0xf6, 0x56, 0xf1, 0xd6,
+ 0x9f, 0xfd, 0x0d, 0x00, 0x00, 0xff, 0xff, 0xfb, 0x7a, 0x61, 0xd0, 0x87, 0x03, 0x00, 0x00,
}
func (x Type) String() string {
@@ -316,69 +298,6 @@ func (x Type) String() string {
}
return strconv.Itoa(int(x))
}
-func (this *FrontendToClient) Equal(that interface{}) bool {
- if that == nil {
- return this == nil
- }
-
- that1, ok := that.(*FrontendToClient)
- if !ok {
- that2, ok := that.(FrontendToClient)
- if ok {
- that1 = &that2
- } else {
- return false
- }
- }
- if that1 == nil {
- return this == nil
- } else if this == nil {
- return false
- }
- if !this.HttpRequest.Equal(that1.HttpRequest) {
- return false
- }
- if this.Type != that1.Type {
- return false
- }
- if this.StatsEnabled != that1.StatsEnabled {
- return false
- }
- if this.QueueTimeNanos != that1.QueueTimeNanos {
- return false
- }
- return true
-}
-func (this *ClientToFrontend) Equal(that interface{}) bool {
- if that == nil {
- return this == nil
- }
-
- that1, ok := that.(*ClientToFrontend)
- if !ok {
- that2, ok := that.(ClientToFrontend)
- if ok {
- that1 = &that2
- } else {
- return false
- }
- }
- if that1 == nil {
- return this == nil
- } else if this == nil {
- return false
- }
- if !this.HttpResponse.Equal(that1.HttpResponse) {
- return false
- }
- if this.ClientID != that1.ClientID {
- return false
- }
- if !this.Stats.Equal(that1.Stats) {
- return false
- }
- return true
-}
func (this *NotifyClientShutdownRequest) Equal(that interface{}) bool {
if that == nil {
return this == nil
@@ -638,115 +557,6 @@ var _Frontend_serviceDesc = grpc.ServiceDesc{
Metadata: "frontend.proto",
}
-func (m *FrontendToClient) Marshal() (dAtA []byte, err error) {
- size := m.Size()
- dAtA = make([]byte, size)
- n, err := m.MarshalToSizedBuffer(dAtA[:size])
- if err != nil {
- return nil, err
- }
- return dAtA[:n], nil
-}
-
-func (m *FrontendToClient) MarshalTo(dAtA []byte) (int, error) {
- size := m.Size()
- return m.MarshalToSizedBuffer(dAtA[:size])
-}
-
-func (m *FrontendToClient) MarshalToSizedBuffer(dAtA []byte) (int, error) {
- i := len(dAtA)
- _ = i
- var l int
- _ = l
- if m.QueueTimeNanos != 0 {
- i = encodeVarintFrontend(dAtA, i, uint64(m.QueueTimeNanos))
- i--
- dAtA[i] = 0x20
- }
- if m.StatsEnabled {
- i--
- if m.StatsEnabled {
- dAtA[i] = 1
- } else {
- dAtA[i] = 0
- }
- i--
- dAtA[i] = 0x18
- }
- if m.Type != 0 {
- i = encodeVarintFrontend(dAtA, i, uint64(m.Type))
- i--
- dAtA[i] = 0x10
- }
- if m.HttpRequest != nil {
- {
- size, err := m.HttpRequest.MarshalToSizedBuffer(dAtA[:i])
- if err != nil {
- return 0, err
- }
- i -= size
- i = encodeVarintFrontend(dAtA, i, uint64(size))
- }
- i--
- dAtA[i] = 0xa
- }
- return len(dAtA) - i, nil
-}
-
-func (m *ClientToFrontend) Marshal() (dAtA []byte, err error) {
- size := m.Size()
- dAtA = make([]byte, size)
- n, err := m.MarshalToSizedBuffer(dAtA[:size])
- if err != nil {
- return nil, err
- }
- return dAtA[:n], nil
-}
-
-func (m *ClientToFrontend) MarshalTo(dAtA []byte) (int, error) {
- size := m.Size()
- return m.MarshalToSizedBuffer(dAtA[:size])
-}
-
-func (m *ClientToFrontend) MarshalToSizedBuffer(dAtA []byte) (int, error) {
- i := len(dAtA)
- _ = i
- var l int
- _ = l
- if m.Stats != nil {
- {
- size, err := m.Stats.MarshalToSizedBuffer(dAtA[:i])
- if err != nil {
- return 0, err
- }
- i -= size
- i = encodeVarintFrontend(dAtA, i, uint64(size))
- }
- i--
- dAtA[i] = 0x1a
- }
- if len(m.ClientID) > 0 {
- i -= len(m.ClientID)
- copy(dAtA[i:], m.ClientID)
- i = encodeVarintFrontend(dAtA, i, uint64(len(m.ClientID)))
- i--
- dAtA[i] = 0x12
- }
- if m.HttpResponse != nil {
- {
- size, err := m.HttpResponse.MarshalToSizedBuffer(dAtA[:i])
- if err != nil {
- return 0, err
- }
- i -= size
- i = encodeVarintFrontend(dAtA, i, uint64(size))
- }
- i--
- dAtA[i] = 0xa
- }
- return len(dAtA) - i, nil
-}
-
func (m *NotifyClientShutdownRequest) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
diff --git a/pkg/frontend/v1/frontendv1pb/frontend.proto b/pkg/frontend/v1/frontendv1pb/frontend.proto
index c232c985455..5d58c9c8bcc 100644
--- a/pkg/frontend/v1/frontendv1pb/frontend.proto
+++ b/pkg/frontend/v1/frontendv1pb/frontend.proto
@@ -33,6 +33,8 @@ enum Type {
}
message FrontendToClient {
+ option (gogoproto.equal) = false;
+ option (gogoproto.marshaler) = false;
httpgrpc.HTTPRequest httpRequest = 1;
Type type = 2;
@@ -45,6 +47,8 @@ message FrontendToClient {
}
message ClientToFrontend {
+ option (gogoproto.equal) = false;
+ option (gogoproto.marshaler) = false;
httpgrpc.HTTPResponse httpResponse = 1;
string clientID = 2;
stats.Stats stats = 3;
diff --git a/pkg/frontend/v2/frontendv2pb/frontend.pb.go b/pkg/frontend/v2/frontendv2pb/frontend.pb.go
index c861bdb1da9..a6cb1733465 100644
--- a/pkg/frontend/v2/frontendv2pb/frontend.pb.go
+++ b/pkg/frontend/v2/frontendv2pb/frontend.pb.go
@@ -47,22 +47,13 @@ func (m *QueryResultRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *QueryResultRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
- if deterministic {
- return xxx_messageInfo_QueryResultRequest.Marshal(b, m, deterministic)
- } else {
- b = b[:cap(b)]
- n, err := m.MarshalToSizedBuffer(b)
- if err != nil {
- return nil, err
- }
- return b[:n], nil
- }
+ return xxx_messageInfo_QueryResultRequest.Marshal(b, m, deterministic)
}
func (m *QueryResultRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_QueryResultRequest.Merge(m, src)
}
func (m *QueryResultRequest) XXX_Size() int {
- return m.Size()
+ return xxx_messageInfo_QueryResultRequest.Size(m)
}
func (m *QueryResultRequest) XXX_DiscardUnknown() {
xxx_messageInfo_QueryResultRequest.DiscardUnknown(m)
@@ -108,22 +99,13 @@ func (m *QueryResultStreamRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *QueryResultStreamRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
- if deterministic {
- return xxx_messageInfo_QueryResultStreamRequest.Marshal(b, m, deterministic)
- } else {
- b = b[:cap(b)]
- n, err := m.MarshalToSizedBuffer(b)
- if err != nil {
- return nil, err
- }
- return b[:n], nil
- }
+ return xxx_messageInfo_QueryResultStreamRequest.Marshal(b, m, deterministic)
}
func (m *QueryResultStreamRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_QueryResultStreamRequest.Merge(m, src)
}
func (m *QueryResultStreamRequest) XXX_Size() int {
- return m.Size()
+ return xxx_messageInfo_QueryResultStreamRequest.Size(m)
}
func (m *QueryResultStreamRequest) XXX_DiscardUnknown() {
xxx_messageInfo_QueryResultStreamRequest.DiscardUnknown(m)
@@ -133,8 +115,6 @@ var xxx_messageInfo_QueryResultStreamRequest proto.InternalMessageInfo
type isQueryResultStreamRequest_Data interface {
isQueryResultStreamRequest_Data()
- Equal(interface{}) bool
- MarshalTo([]byte) (int, error)
Size() int
}
@@ -199,22 +179,13 @@ func (m *QueryResultMetadata) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *QueryResultMetadata) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
- if deterministic {
- return xxx_messageInfo_QueryResultMetadata.Marshal(b, m, deterministic)
- } else {
- b = b[:cap(b)]
- n, err := m.MarshalToSizedBuffer(b)
- if err != nil {
- return nil, err
- }
- return b[:n], nil
- }
+ return xxx_messageInfo_QueryResultMetadata.Marshal(b, m, deterministic)
}
func (m *QueryResultMetadata) XXX_Merge(src proto.Message) {
xxx_messageInfo_QueryResultMetadata.Merge(m, src)
}
func (m *QueryResultMetadata) XXX_Size() int {
- return m.Size()
+ return xxx_messageInfo_QueryResultMetadata.Size(m)
}
func (m *QueryResultMetadata) XXX_DiscardUnknown() {
xxx_messageInfo_QueryResultMetadata.DiscardUnknown(m)
@@ -332,185 +303,41 @@ func init() {
func init() { proto.RegisterFile("frontend.proto", fileDescriptor_eca3873955a29cfe) }
var fileDescriptor_eca3873955a29cfe = []byte{
- // 480 bytes of a gzipped FileDescriptorProto
- 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x93, 0xcf, 0x6e, 0xd3, 0x40,
- 0x10, 0xc6, 0xbd, 0x6d, 0xd2, 0xa2, 0x49, 0xc4, 0x9f, 0xa5, 0x20, 0x2b, 0x12, 0xab, 0xd4, 0x07,
- 0x88, 0x38, 0xd8, 0x28, 0x95, 0x38, 0x70, 0x41, 0x8a, 0x50, 0x15, 0x0e, 0x48, 0x74, 0x9b, 0x13,
- 0xb7, 0x75, 0xbc, 0x75, 0xac, 0x60, 0xaf, 0xbb, 0x5e, 0x23, 0xf9, 0xc6, 0x13, 0x20, 0x1e, 0x83,
- 0x33, 0x4f, 0xc1, 0x09, 0xe5, 0xd8, 0x23, 0x71, 0x2e, 0x1c, 0xfb, 0x08, 0xc8, 0x6b, 0x3b, 0x72,
- 0xa0, 0xa1, 0xb9, 0xac, 0x66, 0x34, 0xdf, 0xb7, 0xf3, 0xf3, 0x8c, 0x17, 0xee, 0x5e, 0x48, 0x11,
- 0x29, 0x1e, 0x79, 0x76, 0x2c, 0x85, 0x12, 0xb8, 0x5b, 0xe7, 0x9f, 0x86, 0xb1, 0xdb, 0x3b, 0xf2,
- 0x85, 0x2f, 0x74, 0xc1, 0x29, 0xa2, 0x52, 0xd3, 0x7b, 0xe1, 0x07, 0x6a, 0x96, 0xba, 0xf6, 0x54,
- 0x84, 0x8e, 0x2f, 0xd9, 0x05, 0x8b, 0x98, 0xe3, 0x25, 0xf3, 0x40, 0x39, 0x33, 0xa5, 0x62, 0x5f,
- 0xc6, 0xd3, 0x75, 0x50, 0x39, 0x5e, 0xde, 0xe0, 0x08, 0x83, 0x30, 0x90, 0x4e, 0x3c, 0xf7, 0x9d,
- 0xcb, 0x94, 0xcb, 0x80, 0x4b, 0x27, 0x51, 0x4c, 0x25, 0xe5, 0x59, 0xfa, 0xac, 0x2f, 0x08, 0xf0,
- 0x59, 0xca, 0x65, 0x46, 0x79, 0x92, 0x7e, 0x54, 0x94, 0x5f, 0xa6, 0x3c, 0x51, 0xd8, 0x84, 0xc3,
- 0xc2, 0x93, 0xbd, 0x7d, 0x63, 0xa2, 0x3e, 0x1a, 0xb4, 0x68, 0x9d, 0xe2, 0x57, 0xd0, 0x2d, 0x5a,
- 0x53, 0x9e, 0xc4, 0x22, 0x4a, 0xb8, 0xb9, 0xd7, 0x47, 0x83, 0xce, 0xf0, 0xb1, 0xbd, 0xe6, 0x19,
- 0x4f, 0x26, 0xef, 0xeb, 0x2a, 0xdd, 0xd0, 0x62, 0x0b, 0xda, 0xba, 0xb7, 0xb9, 0xaf, 0x4d, 0x5d,
- 0xbb, 0x24, 0x39, 0x2f, 0x4e, 0x5a, 0x96, 0xac, 0xef, 0x08, 0xcc, 0x06, 0xd0, 0xb9, 0x92, 0x9c,
- 0x85, 0xb7, 0x63, 0xbd, 0x86, 0x3b, 0x21, 0x57, 0xcc, 0x63, 0x8a, 0x55, 0x48, 0xc7, 0x76, 0x73,
- 0xd0, 0x76, 0xe3, 0xce, 0x77, 0x95, 0x70, 0x6c, 0xd0, 0xb5, 0x09, 0x9f, 0x40, 0xcb, 0x15, 0x5e,
- 0x56, 0xa1, 0x3d, 0xd9, 0x6a, 0x1e, 0x09, 0x2f, 0x1b, 0x1b, 0x54, 0x8b, 0x47, 0x07, 0xd0, 0x2a,
- 0xcc, 0x56, 0x06, 0x0f, 0x6f, 0xb8, 0x1f, 0x63, 0x68, 0x4d, 0x85, 0xc7, 0x35, 0x6b, 0x9b, 0xea,
- 0x18, 0x3f, 0x87, 0xc3, 0x19, 0x67, 0x1e, 0x97, 0x89, 0xb9, 0xd7, 0xdf, 0x1f, 0x74, 0x86, 0xf7,
- 0x1b, 0xa3, 0xd3, 0x05, 0x5a, 0x0b, 0x76, 0x9a, 0xd7, 0x33, 0xb8, 0xf7, 0x17, 0x1d, 0x3e, 0x82,
- 0xf6, 0x74, 0x96, 0x46, 0x73, 0xdd, 0xb7, 0x4b, 0xcb, 0xc4, 0x7a, 0xb4, 0xc1, 0x58, 0xef, 0x64,
- 0xf8, 0x13, 0x01, 0x3e, 0xad, 0xbe, 0xf5, 0x54, 0xc8, 0xb3, 0xf2, 0x4f, 0xc1, 0x13, 0xe8, 0x34,
- 0xd4, 0xb8, 0xbf, 0x75, 0x1e, 0xd5, 0x6a, 0x7a, 0xc7, 0xff, 0x51, 0x94, 0xad, 0x2c, 0x03, 0xbb,
- 0xf0, 0xe0, 0x9f, 0xdd, 0xe2, 0xa7, 0x5b, 0x9d, 0x1b, 0xcb, 0xdf, 0xa9, 0xc3, 0x00, 0x8d, 0x46,
- 0x8b, 0x25, 0x31, 0xae, 0x96, 0xc4, 0xb8, 0x5e, 0x12, 0xf4, 0x39, 0x27, 0xe8, 0x5b, 0x4e, 0xd0,
- 0x8f, 0x9c, 0xa0, 0x45, 0x4e, 0xd0, 0xaf, 0x9c, 0xa0, 0xdf, 0x39, 0x31, 0xae, 0x73, 0x82, 0xbe,
- 0xae, 0x88, 0xb1, 0x58, 0x11, 0xe3, 0x6a, 0x45, 0x8c, 0x0f, 0x1b, 0xaf, 0xd2, 0x3d, 0xd0, 0x8f,
- 0xe3, 0xe4, 0x4f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xca, 0x18, 0x1f, 0x97, 0xbc, 0x03, 0x00, 0x00,
-}
-
-func (this *QueryResultRequest) Equal(that interface{}) bool {
- if that == nil {
- return this == nil
- }
-
- that1, ok := that.(*QueryResultRequest)
- if !ok {
- that2, ok := that.(QueryResultRequest)
- if ok {
- that1 = &that2
- } else {
- return false
- }
- }
- if that1 == nil {
- return this == nil
- } else if this == nil {
- return false
- }
- if this.QueryID != that1.QueryID {
- return false
- }
- if !this.HttpResponse.Equal(that1.HttpResponse) {
- return false
- }
- if !this.Stats.Equal(that1.Stats) {
- return false
- }
- return true
+ // 497 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x93, 0xbf, 0x6f, 0xd3, 0x40,
+ 0x14, 0xc7, 0xef, 0xda, 0xa4, 0xad, 0x2e, 0x11, 0x3f, 0x8e, 0x82, 0xac, 0x48, 0x5c, 0x53, 0x0f,
+ 0x10, 0x31, 0xd8, 0x28, 0x95, 0x18, 0xba, 0x20, 0x45, 0xa8, 0x0a, 0x03, 0x12, 0xbd, 0x66, 0x62,
+ 0x3b, 0xc7, 0x57, 0xc7, 0x0a, 0xf6, 0xb9, 0xe7, 0x33, 0x52, 0x36, 0x24, 0x16, 0x46, 0x46, 0x46,
+ 0xd8, 0xf8, 0x23, 0xf8, 0x03, 0x98, 0x50, 0xc6, 0x8e, 0xc4, 0x59, 0x3a, 0xf6, 0x4f, 0x40, 0x3e,
+ 0xdb, 0xc1, 0x86, 0x06, 0xe8, 0x72, 0x7a, 0x4f, 0xef, 0xfb, 0xbd, 0xf7, 0xd1, 0x7b, 0x77, 0xe8,
+ 0xc6, 0xa9, 0x14, 0xa1, 0xe2, 0xa1, 0x6b, 0x45, 0x52, 0x28, 0x81, 0xdb, 0x65, 0xfe, 0xa6, 0x1f,
+ 0x39, 0x9d, 0x5d, 0x4f, 0x78, 0x42, 0x17, 0xec, 0x2c, 0xca, 0x35, 0x9d, 0xc7, 0x9e, 0xaf, 0x26,
+ 0x89, 0x63, 0x8d, 0x45, 0x60, 0x7b, 0x92, 0x9d, 0xb2, 0x90, 0xd9, 0x6e, 0x3c, 0xf5, 0x95, 0x3d,
+ 0x51, 0x2a, 0xf2, 0x64, 0x34, 0x5e, 0x05, 0x85, 0xe3, 0xc9, 0x15, 0x8e, 0xc0, 0x0f, 0x7c, 0x69,
+ 0x47, 0x53, 0xcf, 0x3e, 0x4b, 0xb8, 0xf4, 0xb9, 0xb4, 0x63, 0xc5, 0x54, 0x9c, 0x9f, 0xb9, 0xcf,
+ 0xfc, 0x08, 0x11, 0x3e, 0x4e, 0xb8, 0x9c, 0x51, 0x1e, 0x27, 0xaf, 0x15, 0xe5, 0x67, 0x09, 0x8f,
+ 0x15, 0x36, 0xd0, 0x76, 0xe6, 0x99, 0x3d, 0x7f, 0x66, 0xc0, 0x2e, 0xec, 0x35, 0x68, 0x99, 0xe2,
+ 0x43, 0xd4, 0xce, 0x5a, 0x53, 0x1e, 0x47, 0x22, 0x8c, 0xb9, 0xb1, 0xd1, 0x85, 0xbd, 0x56, 0xff,
+ 0x9e, 0xb5, 0xe2, 0x19, 0x8e, 0x46, 0x2f, 0xcb, 0x2a, 0xad, 0x69, 0xb1, 0x89, 0x9a, 0xba, 0xb7,
+ 0xb1, 0xa9, 0x4d, 0x6d, 0x2b, 0x27, 0x39, 0xc9, 0x4e, 0x9a, 0x97, 0x0e, 0x77, 0x2e, 0x3e, 0xed,
+ 0x81, 0xf7, 0x9f, 0xf7, 0x80, 0xf9, 0x15, 0x22, 0xa3, 0x82, 0x76, 0xa2, 0x24, 0x67, 0xc1, 0xbf,
+ 0x01, 0x9f, 0xa2, 0x9d, 0x80, 0x2b, 0xe6, 0x32, 0xc5, 0x0a, 0xb8, 0x7d, 0xab, 0x3a, 0x72, 0xab,
+ 0x72, 0xe7, 0x8b, 0x42, 0x38, 0x04, 0x74, 0x65, 0xc2, 0x07, 0xa8, 0xe1, 0x08, 0x77, 0x56, 0x40,
+ 0xde, 0x5f, 0x6b, 0x1e, 0x08, 0x77, 0x36, 0x04, 0x54, 0x8b, 0x7f, 0x61, 0x0f, 0xb6, 0x50, 0x23,
+ 0xbb, 0xc6, 0x7c, 0x07, 0xd1, 0x9d, 0x2b, 0x5a, 0x61, 0x8c, 0x1a, 0x63, 0xe1, 0x72, 0x8d, 0xdd,
+ 0xa4, 0x3a, 0xc6, 0x8f, 0xd0, 0xf6, 0x84, 0x33, 0x97, 0xcb, 0xd8, 0xd8, 0xe8, 0x6e, 0xf6, 0x5a,
+ 0xfd, 0x5b, 0x95, 0x79, 0xea, 0x02, 0x2d, 0x05, 0xd7, 0x1c, 0xe2, 0x43, 0x74, 0xf3, 0x37, 0x64,
+ 0xbc, 0x8b, 0x9a, 0xe3, 0x49, 0x12, 0x4e, 0x35, 0x41, 0x9b, 0xe6, 0x89, 0x79, 0xb7, 0x46, 0x5b,
+ 0xae, 0xac, 0xff, 0x1d, 0x22, 0x7c, 0x54, 0x0c, 0xe0, 0x48, 0xc8, 0xe3, 0xfc, 0x21, 0xe1, 0x11,
+ 0x6a, 0x55, 0xd4, 0xb8, 0xbb, 0x76, 0x48, 0xc5, 0xbe, 0x3a, 0xfb, 0x7f, 0x51, 0xe4, 0xad, 0x4c,
+ 0x80, 0x1d, 0x74, 0xfb, 0x8f, 0x85, 0xe3, 0x07, 0x6b, 0x9d, 0xb5, 0x17, 0xf1, 0x5f, 0x1d, 0x7a,
+ 0x70, 0x30, 0x98, 0x2f, 0x08, 0x38, 0x5f, 0x10, 0x70, 0xb9, 0x20, 0xf0, 0x6d, 0x4a, 0xe0, 0x97,
+ 0x94, 0xc0, 0x6f, 0x29, 0x81, 0xf3, 0x94, 0xc0, 0x1f, 0x29, 0x81, 0x17, 0x29, 0x01, 0x97, 0x29,
+ 0x81, 0x1f, 0x96, 0x04, 0xcc, 0x97, 0x04, 0x9c, 0x2f, 0x09, 0x78, 0x55, 0xfb, 0xb4, 0xce, 0x96,
+ 0xfe, 0x3b, 0x07, 0x3f, 0x03, 0x00, 0x00, 0xff, 0xff, 0xe1, 0xcf, 0x89, 0x8f, 0xdb, 0x03, 0x00,
+ 0x00,
}
-func (this *QueryResultStreamRequest) Equal(that interface{}) bool {
- if that == nil {
- return this == nil
- }
- that1, ok := that.(*QueryResultStreamRequest)
- if !ok {
- that2, ok := that.(QueryResultStreamRequest)
- if ok {
- that1 = &that2
- } else {
- return false
- }
- }
- if that1 == nil {
- return this == nil
- } else if this == nil {
- return false
- }
- if this.QueryID != that1.QueryID {
- return false
- }
- if that1.Data == nil {
- if this.Data != nil {
- return false
- }
- } else if this.Data == nil {
- return false
- } else if !this.Data.Equal(that1.Data) {
- return false
- }
- return true
-}
-func (this *QueryResultStreamRequest_Metadata) Equal(that interface{}) bool {
- if that == nil {
- return this == nil
- }
-
- that1, ok := that.(*QueryResultStreamRequest_Metadata)
- if !ok {
- that2, ok := that.(QueryResultStreamRequest_Metadata)
- if ok {
- that1 = &that2
- } else {
- return false
- }
- }
- if that1 == nil {
- return this == nil
- } else if this == nil {
- return false
- }
- if !this.Metadata.Equal(that1.Metadata) {
- return false
- }
- return true
-}
-func (this *QueryResultStreamRequest_Body) Equal(that interface{}) bool {
- if that == nil {
- return this == nil
- }
-
- that1, ok := that.(*QueryResultStreamRequest_Body)
- if !ok {
- that2, ok := that.(QueryResultStreamRequest_Body)
- if ok {
- that1 = &that2
- } else {
- return false
- }
- }
- if that1 == nil {
- return this == nil
- } else if this == nil {
- return false
- }
- if !this.Body.Equal(that1.Body) {
- return false
- }
- return true
-}
-func (this *QueryResultMetadata) Equal(that interface{}) bool {
- if that == nil {
- return this == nil
- }
-
- that1, ok := that.(*QueryResultMetadata)
- if !ok {
- that2, ok := that.(QueryResultMetadata)
- if ok {
- that1 = &that2
- } else {
- return false
- }
- }
- if that1 == nil {
- return this == nil
- } else if this == nil {
- return false
- }
- if this.Code != that1.Code {
- return false
- }
- if len(this.Headers) != len(that1.Headers) {
- return false
- }
- for i := range this.Headers {
- if !this.Headers[i].Equal(that1.Headers[i]) {
- return false
- }
- }
- if !this.Stats.Equal(that1.Stats) {
- return false
- }
- return true
-}
func (this *QueryResultBody) Equal(that interface{}) bool {
if that == nil {
return this == nil
@@ -796,189 +623,6 @@ var _FrontendForQuerier_serviceDesc = grpc.ServiceDesc{
Metadata: "frontend.proto",
}
-func (m *QueryResultRequest) Marshal() (dAtA []byte, err error) {
- size := m.Size()
- dAtA = make([]byte, size)
- n, err := m.MarshalToSizedBuffer(dAtA[:size])
- if err != nil {
- return nil, err
- }
- return dAtA[:n], nil
-}
-
-func (m *QueryResultRequest) MarshalTo(dAtA []byte) (int, error) {
- size := m.Size()
- return m.MarshalToSizedBuffer(dAtA[:size])
-}
-
-func (m *QueryResultRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
- i := len(dAtA)
- _ = i
- var l int
- _ = l
- if m.Stats != nil {
- {
- size, err := m.Stats.MarshalToSizedBuffer(dAtA[:i])
- if err != nil {
- return 0, err
- }
- i -= size
- i = encodeVarintFrontend(dAtA, i, uint64(size))
- }
- i--
- dAtA[i] = 0x1a
- }
- if m.HttpResponse != nil {
- {
- size, err := m.HttpResponse.MarshalToSizedBuffer(dAtA[:i])
- if err != nil {
- return 0, err
- }
- i -= size
- i = encodeVarintFrontend(dAtA, i, uint64(size))
- }
- i--
- dAtA[i] = 0x12
- }
- if m.QueryID != 0 {
- i = encodeVarintFrontend(dAtA, i, uint64(m.QueryID))
- i--
- dAtA[i] = 0x8
- }
- return len(dAtA) - i, nil
-}
-
-func (m *QueryResultStreamRequest) Marshal() (dAtA []byte, err error) {
- size := m.Size()
- dAtA = make([]byte, size)
- n, err := m.MarshalToSizedBuffer(dAtA[:size])
- if err != nil {
- return nil, err
- }
- return dAtA[:n], nil
-}
-
-func (m *QueryResultStreamRequest) MarshalTo(dAtA []byte) (int, error) {
- size := m.Size()
- return m.MarshalToSizedBuffer(dAtA[:size])
-}
-
-func (m *QueryResultStreamRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
- i := len(dAtA)
- _ = i
- var l int
- _ = l
- if m.Data != nil {
- {
- size := m.Data.Size()
- i -= size
- if _, err := m.Data.MarshalTo(dAtA[i:]); err != nil {
- return 0, err
- }
- }
- }
- if m.QueryID != 0 {
- i = encodeVarintFrontend(dAtA, i, uint64(m.QueryID))
- i--
- dAtA[i] = 0x8
- }
- return len(dAtA) - i, nil
-}
-
-func (m *QueryResultStreamRequest_Metadata) MarshalTo(dAtA []byte) (int, error) {
- return m.MarshalToSizedBuffer(dAtA[:m.Size()])
-}
-
-func (m *QueryResultStreamRequest_Metadata) MarshalToSizedBuffer(dAtA []byte) (int, error) {
- i := len(dAtA)
- if m.Metadata != nil {
- {
- size, err := m.Metadata.MarshalToSizedBuffer(dAtA[:i])
- if err != nil {
- return 0, err
- }
- i -= size
- i = encodeVarintFrontend(dAtA, i, uint64(size))
- }
- i--
- dAtA[i] = 0x12
- }
- return len(dAtA) - i, nil
-}
-func (m *QueryResultStreamRequest_Body) MarshalTo(dAtA []byte) (int, error) {
- return m.MarshalToSizedBuffer(dAtA[:m.Size()])
-}
-
-func (m *QueryResultStreamRequest_Body) MarshalToSizedBuffer(dAtA []byte) (int, error) {
- i := len(dAtA)
- if m.Body != nil {
- {
- size, err := m.Body.MarshalToSizedBuffer(dAtA[:i])
- if err != nil {
- return 0, err
- }
- i -= size
- i = encodeVarintFrontend(dAtA, i, uint64(size))
- }
- i--
- dAtA[i] = 0x1a
- }
- return len(dAtA) - i, nil
-}
-func (m *QueryResultMetadata) Marshal() (dAtA []byte, err error) {
- size := m.Size()
- dAtA = make([]byte, size)
- n, err := m.MarshalToSizedBuffer(dAtA[:size])
- if err != nil {
- return nil, err
- }
- return dAtA[:n], nil
-}
-
-func (m *QueryResultMetadata) MarshalTo(dAtA []byte) (int, error) {
- size := m.Size()
- return m.MarshalToSizedBuffer(dAtA[:size])
-}
-
-func (m *QueryResultMetadata) MarshalToSizedBuffer(dAtA []byte) (int, error) {
- i := len(dAtA)
- _ = i
- var l int
- _ = l
- if m.Stats != nil {
- {
- size, err := m.Stats.MarshalToSizedBuffer(dAtA[:i])
- if err != nil {
- return 0, err
- }
- i -= size
- i = encodeVarintFrontend(dAtA, i, uint64(size))
- }
- i--
- dAtA[i] = 0x1a
- }
- if len(m.Headers) > 0 {
- for iNdEx := len(m.Headers) - 1; iNdEx >= 0; iNdEx-- {
- {
- size, err := m.Headers[iNdEx].MarshalToSizedBuffer(dAtA[:i])
- if err != nil {
- return 0, err
- }
- i -= size
- i = encodeVarintFrontend(dAtA, i, uint64(size))
- }
- i--
- dAtA[i] = 0x12
- }
- }
- if m.Code != 0 {
- i = encodeVarintFrontend(dAtA, i, uint64(m.Code))
- i--
- dAtA[i] = 0x8
- }
- return len(dAtA) - i, nil
-}
-
func (m *QueryResultBody) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
diff --git a/pkg/frontend/v2/frontendv2pb/frontend.proto b/pkg/frontend/v2/frontendv2pb/frontend.proto
index de147278360..32d71bc37c0 100644
--- a/pkg/frontend/v2/frontendv2pb/frontend.proto
+++ b/pkg/frontend/v2/frontendv2pb/frontend.proto
@@ -23,6 +23,8 @@ service FrontendForQuerier {
}
message QueryResultRequest {
+ option (gogoproto.equal) = false;
+ option (gogoproto.marshaler) = false;
uint64 queryID = 1;
httpgrpc.HTTPResponse httpResponse = 2;
stats.Stats stats = 3;
@@ -32,6 +34,8 @@ message QueryResultRequest {
}
message QueryResultStreamRequest {
+ option (gogoproto.equal) = false;
+ option (gogoproto.marshaler) = false;
uint64 queryID = 1;
oneof data {
QueryResultMetadata metadata = 2;
@@ -40,6 +44,8 @@ message QueryResultStreamRequest {
}
message QueryResultMetadata {
+ option (gogoproto.equal) = false;
+ option (gogoproto.marshaler) = false;
int32 code = 1;
repeated httpgrpc.Header headers = 2;
stats.Stats stats = 3;
diff --git a/pkg/scheduler/schedulerpb/scheduler.pb.go b/pkg/scheduler/schedulerpb/scheduler.pb.go
index fb2e838db30..f6bce9e02d8 100644
--- a/pkg/scheduler/schedulerpb/scheduler.pb.go
+++ b/pkg/scheduler/schedulerpb/scheduler.pb.go
@@ -152,22 +152,13 @@ func (m *SchedulerToQuerier) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *SchedulerToQuerier) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
- if deterministic {
- return xxx_messageInfo_SchedulerToQuerier.Marshal(b, m, deterministic)
- } else {
- b = b[:cap(b)]
- n, err := m.MarshalToSizedBuffer(b)
- if err != nil {
- return nil, err
- }
- return b[:n], nil
- }
+ return xxx_messageInfo_SchedulerToQuerier.Marshal(b, m, deterministic)
}
func (m *SchedulerToQuerier) XXX_Merge(src proto.Message) {
xxx_messageInfo_SchedulerToQuerier.Merge(m, src)
}
func (m *SchedulerToQuerier) XXX_Size() int {
- return m.Size()
+ return xxx_messageInfo_SchedulerToQuerier.Size(m)
}
func (m *SchedulerToQuerier) XXX_DiscardUnknown() {
xxx_messageInfo_SchedulerToQuerier.DiscardUnknown(m)
@@ -240,22 +231,13 @@ func (m *FrontendToScheduler) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *FrontendToScheduler) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
- if deterministic {
- return xxx_messageInfo_FrontendToScheduler.Marshal(b, m, deterministic)
- } else {
- b = b[:cap(b)]
- n, err := m.MarshalToSizedBuffer(b)
- if err != nil {
- return nil, err
- }
- return b[:n], nil
- }
+ return xxx_messageInfo_FrontendToScheduler.Marshal(b, m, deterministic)
}
func (m *FrontendToScheduler) XXX_Merge(src proto.Message) {
xxx_messageInfo_FrontendToScheduler.Merge(m, src)
}
func (m *FrontendToScheduler) XXX_Size() int {
- return m.Size()
+ return xxx_messageInfo_FrontendToScheduler.Size(m)
}
func (m *FrontendToScheduler) XXX_DiscardUnknown() {
xxx_messageInfo_FrontendToScheduler.DiscardUnknown(m)
@@ -455,51 +437,51 @@ func init() {
func init() { proto.RegisterFile("scheduler.proto", fileDescriptor_2b3fc28395a6d9c5) }
var fileDescriptor_2b3fc28395a6d9c5 = []byte{
- // 690 bytes of a gzipped FileDescriptorProto
+ // 703 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x94, 0x4f, 0x53, 0xda, 0x40,
- 0x18, 0xc6, 0xb3, 0xfc, 0x53, 0x5e, 0xac, 0xd2, 0x55, 0x5b, 0x64, 0x6c, 0xcc, 0x30, 0x1d, 0x87,
- 0x7a, 0x00, 0x87, 0x1e, 0xda, 0x83, 0xd3, 0x19, 0xaa, 0xb1, 0x32, 0xb5, 0x41, 0x96, 0x30, 0xfd,
- 0x73, 0x61, 0x02, 0x59, 0x21, 0xa3, 0x66, 0x63, 0x36, 0x99, 0x0e, 0xb7, 0x7e, 0x84, 0x7e, 0x8c,
- 0x7e, 0x92, 0x4e, 0x8f, 0x1e, 0x3d, 0xf4, 0x50, 0xe3, 0xa5, 0x47, 0x2f, 0xbd, 0x77, 0x08, 0x81,
- 0x06, 0x0a, 0xea, 0x6d, 0xf7, 0xe5, 0x79, 0xd8, 0x7d, 0x7e, 0xef, 0x9b, 0x85, 0x25, 0xde, 0xee,
- 0x52, 0xdd, 0x3d, 0xa5, 0x76, 0xc1, 0xb2, 0x99, 0xc3, 0x70, 0x6a, 0x54, 0xb0, 0x5a, 0xd9, 0x95,
- 0x0e, 0xeb, 0x30, 0xbf, 0x5e, 0xec, 0xaf, 0x06, 0x92, 0xec, 0x76, 0xc7, 0x70, 0xba, 0x6e, 0xab,
- 0xd0, 0x66, 0x67, 0xc5, 0x8e, 0xad, 0x1d, 0x6b, 0xa6, 0x56, 0xd4, 0xf9, 0x89, 0xe1, 0x14, 0xbb,
- 0x8e, 0x63, 0x75, 0x6c, 0xab, 0x3d, 0x5a, 0x0c, 0x1c, 0xb9, 0x12, 0xe0, 0x9a, 0x4b, 0x6d, 0x83,
- 0xda, 0x2a, 0xab, 0x0f, 0xff, 0x1f, 0xaf, 0x43, 0xf2, 0x7c, 0x50, 0xad, 0xec, 0x65, 0x90, 0x84,
- 0xf2, 0x49, 0xf2, 0xaf, 0x90, 0xfb, 0x83, 0x00, 0x8f, 0xb4, 0x2a, 0x0b, 0xfc, 0x38, 0x03, 0x73,
- 0x7d, 0x4d, 0x2f, 0xb0, 0xc4, 0xc8, 0x70, 0x8b, 0x5f, 0x40, 0xaa, 0x7f, 0x2c, 0xa1, 0xe7, 0x2e,
- 0xe5, 0x4e, 0x26, 0x22, 0xa1, 0x7c, 0xaa, 0xb4, 0x5a, 0x18, 0x5d, 0xe5, 0x40, 0x55, 0x8f, 0x82,
- 0x1f, 0x49, 0x58, 0x89, 0xf3, 0xb0, 0x74, 0x6c, 0x33, 0xd3, 0xa1, 0xa6, 0x5e, 0xd6, 0x75, 0x9b,
- 0x72, 0x9e, 0x89, 0xfa, 0xb7, 0x99, 0x2c, 0xe3, 0x47, 0x90, 0x70, 0xb9, 0x7f, 0xdd, 0x98, 0x2f,
- 0x08, 0x76, 0x38, 0x07, 0x0b, 0xdc, 0xd1, 0x1c, 0x2e, 0x9b, 0x5a, 0xeb, 0x94, 0xea, 0x99, 0xb8,
- 0x84, 0xf2, 0xf3, 0x64, 0xac, 0x86, 0x37, 0x61, 0xf1, 0xdc, 0xa5, 0x2e, 0x55, 0x8d, 0x33, 0xaa,
- 0x68, 0x26, 0xe3, 0x99, 0x84, 0x84, 0xf2, 0x51, 0x32, 0x51, 0xcd, 0x7d, 0x8f, 0xc0, 0xf2, 0x7e,
- 0x70, 0x6e, 0x98, 0xd6, 0x4b, 0x88, 0x39, 0x3d, 0x8b, 0xfa, 0xa9, 0x17, 0x4b, 0x4f, 0x0b, 0xa1,
- 0x3e, 0x15, 0xa6, 0xe8, 0xd5, 0x9e, 0x45, 0x89, 0xef, 0x98, 0x96, 0x2f, 0x32, 0x3d, 0x5f, 0x08,
- 0x6e, 0x74, 0x1c, 0xee, 0xac, 0xe4, 0x13, 0xd0, 0xe3, 0xf7, 0x86, 0x3e, 0x89, 0x2c, 0x31, 0x05,
- 0xd9, 0x0e, 0xac, 0x69, 0xba, 0x6e, 0x38, 0x06, 0x33, 0xb5, 0xd3, 0x5a, 0x1f, 0xd3, 0x9e, 0x71,
- 0x46, 0x4d, 0x6e, 0x30, 0x93, 0x67, 0xe6, 0xa4, 0x68, 0x3e, 0x49, 0x66, 0x0b, 0x72, 0x27, 0xb0,
- 0x1c, 0x9a, 0x9f, 0x21, 0x22, 0xfc, 0x0a, 0x12, 0xfd, 0x43, 0x5c, 0x1e, 0x90, 0xdc, 0x1c, 0x23,
- 0x39, 0xc5, 0x51, 0xf7, 0xd5, 0x24, 0x70, 0xe1, 0x15, 0x88, 0x53, 0xdb, 0x66, 0x76, 0xc0, 0x70,
- 0xb0, 0xc9, 0xed, 0xc0, 0xba, 0xc2, 0x1c, 0xe3, 0xb8, 0x17, 0xcc, 0x69, 0xbd, 0xeb, 0x3a, 0x3a,
- 0xfb, 0x6c, 0x0e, 0xe3, 0xde, 0x3e, 0xeb, 0x1b, 0xf0, 0x64, 0x86, 0x9b, 0x5b, 0xcc, 0xe4, 0x74,
- 0x6b, 0x07, 0x1e, 0xcf, 0xe8, 0x31, 0x9e, 0x87, 0x58, 0x45, 0xa9, 0xa8, 0x69, 0x01, 0xa7, 0x60,
- 0x4e, 0x56, 0x6a, 0x0d, 0xb9, 0x21, 0xa7, 0x11, 0x06, 0x48, 0xec, 0x96, 0x95, 0x5d, 0xf9, 0x30,
- 0x1d, 0xd9, 0x6a, 0xc3, 0xda, 0xcc, 0x5c, 0x38, 0x01, 0x91, 0xea, 0xdb, 0xb4, 0x80, 0x25, 0x58,
- 0x57, 0xab, 0xd5, 0xe6, 0xbb, 0xb2, 0xf2, 0xb1, 0x49, 0xe4, 0x5a, 0x43, 0xae, 0xab, 0xf5, 0xe6,
- 0x91, 0x4c, 0x9a, 0xaa, 0xac, 0x94, 0x15, 0x35, 0x8d, 0x70, 0x12, 0xe2, 0x32, 0x21, 0x55, 0x92,
- 0x8e, 0xe0, 0x87, 0xf0, 0xa0, 0x7e, 0xd0, 0x50, 0xd5, 0x8a, 0xf2, 0xa6, 0xb9, 0x57, 0x7d, 0xaf,
- 0xa4, 0xa3, 0xa5, 0x9f, 0x28, 0xc4, 0x7b, 0x9f, 0xd9, 0xc3, 0x0f, 0xb6, 0x01, 0xa9, 0x60, 0x79,
- 0xc8, 0x98, 0x85, 0x37, 0xc6, 0x70, 0xff, 0xff, 0x2a, 0x64, 0x37, 0x66, 0xf5, 0x23, 0xd0, 0xe6,
- 0x84, 0x3c, 0xda, 0x46, 0xd8, 0x84, 0xd5, 0xa9, 0xc8, 0xf0, 0xb3, 0x31, 0xff, 0x6d, 0x4d, 0xc9,
- 0x6e, 0xdd, 0x47, 0x3a, 0xe8, 0x40, 0xc9, 0x82, 0x95, 0x70, 0xba, 0xd1, 0x38, 0x7d, 0x80, 0x85,
- 0xe1, 0xda, 0xcf, 0x27, 0xdd, 0xf5, 0x61, 0x66, 0xa5, 0xbb, 0x06, 0x6e, 0x90, 0xf0, 0x75, 0xf9,
- 0xe2, 0x4a, 0x14, 0x2e, 0xaf, 0x44, 0xe1, 0xe6, 0x4a, 0x44, 0x5f, 0x3c, 0x11, 0x7d, 0xf3, 0x44,
- 0xf4, 0xc3, 0x13, 0xd1, 0x85, 0x27, 0xa2, 0x5f, 0x9e, 0x88, 0x7e, 0x7b, 0xa2, 0x70, 0xe3, 0x89,
- 0xe8, 0xeb, 0xb5, 0x28, 0x5c, 0x5c, 0x8b, 0xc2, 0xe5, 0xb5, 0x28, 0x7c, 0x0a, 0xbf, 0xdf, 0xad,
- 0x84, 0xff, 0xfc, 0x3e, 0xff, 0x1b, 0x00, 0x00, 0xff, 0xff, 0x68, 0xe9, 0x45, 0x9c, 0xe6, 0x05,
- 0x00, 0x00,
+ 0x18, 0xc6, 0xb3, 0xfc, 0x53, 0x5e, 0xac, 0xd2, 0x55, 0x5b, 0x64, 0x6c, 0xc8, 0x30, 0x1d, 0x87,
+ 0x7a, 0x00, 0x87, 0x1e, 0xda, 0xe9, 0x38, 0x9d, 0xa1, 0x1a, 0x2b, 0x53, 0x1b, 0x24, 0x84, 0xe9,
+ 0x9f, 0x0b, 0x13, 0xc8, 0x0a, 0x19, 0x35, 0x1b, 0xb3, 0xc9, 0x74, 0xb8, 0xf5, 0xd8, 0x63, 0x3f,
+ 0x42, 0x7b, 0xeb, 0x47, 0xe9, 0x91, 0xa3, 0x87, 0x1e, 0x6a, 0xbc, 0x78, 0xf4, 0x1b, 0xb4, 0x43,
+ 0x08, 0x34, 0x50, 0x50, 0x6f, 0xbb, 0x2f, 0xcf, 0x43, 0xf6, 0xf9, 0xbd, 0xef, 0x2e, 0x2c, 0xb1,
+ 0x56, 0x87, 0x68, 0xce, 0x09, 0xb1, 0xf2, 0xa6, 0x45, 0x6d, 0x8a, 0x13, 0xa3, 0x82, 0xd9, 0x4c,
+ 0xaf, 0xb4, 0x69, 0x9b, 0x7a, 0xf5, 0x42, 0x7f, 0x35, 0x90, 0xa4, 0xb7, 0xda, 0xba, 0xdd, 0x71,
+ 0x9a, 0xf9, 0x16, 0x3d, 0x2d, 0xb4, 0x2d, 0xf5, 0x48, 0x35, 0xd4, 0x82, 0xc6, 0x8e, 0x75, 0xbb,
+ 0xd0, 0xb1, 0x6d, 0xb3, 0x6d, 0x99, 0xad, 0xd1, 0x62, 0xe0, 0xc8, 0x16, 0x01, 0x57, 0x1d, 0x62,
+ 0xe9, 0xc4, 0x52, 0x68, 0x6d, 0xf8, 0xff, 0x78, 0x1d, 0xe2, 0x67, 0x83, 0x6a, 0x79, 0x37, 0x85,
+ 0x04, 0x94, 0x8b, 0xcb, 0xff, 0x0a, 0xd9, 0x3f, 0x08, 0xf0, 0x48, 0xab, 0x50, 0xdf, 0x8f, 0x53,
+ 0x30, 0xd7, 0xd7, 0x74, 0x7d, 0x4b, 0x44, 0x1e, 0x6e, 0xf1, 0x33, 0x48, 0xf4, 0x3f, 0x2b, 0x93,
+ 0x33, 0x87, 0x30, 0x3b, 0x15, 0x12, 0x50, 0x2e, 0x51, 0x5c, 0xcd, 0x8f, 0x8e, 0xb2, 0xaf, 0x28,
+ 0x87, 0xfe, 0x8f, 0x72, 0x50, 0x89, 0x73, 0xb0, 0x74, 0x64, 0x51, 0xc3, 0x26, 0x86, 0x56, 0xd2,
+ 0x34, 0x8b, 0x30, 0x96, 0x0a, 0x7b, 0xa7, 0x99, 0x2c, 0xe3, 0x07, 0x10, 0x73, 0x98, 0x77, 0xdc,
+ 0x88, 0x27, 0xf0, 0x77, 0x38, 0x0b, 0x0b, 0xcc, 0x56, 0x6d, 0x26, 0x1a, 0x6a, 0xf3, 0x84, 0x68,
+ 0xa9, 0xa8, 0x80, 0x72, 0xf3, 0xf2, 0x58, 0x0d, 0x6f, 0xc0, 0xe2, 0x99, 0x43, 0x1c, 0xa2, 0xe8,
+ 0xa7, 0x44, 0x52, 0x0d, 0xca, 0x52, 0x31, 0x01, 0xe5, 0xc2, 0xf2, 0x44, 0xf5, 0xc5, 0xfc, 0xd5,
+ 0xb7, 0x0c, 0xf7, 0xe5, 0x7b, 0x86, 0xcb, 0xf6, 0x42, 0xb0, 0xbc, 0xe7, 0x9f, 0x20, 0xc8, 0xed,
+ 0x39, 0x44, 0xec, 0xae, 0x49, 0xbc, 0xfc, 0x8b, 0xc5, 0xc7, 0xf9, 0x40, 0xc7, 0xf2, 0x53, 0xf4,
+ 0x4a, 0xd7, 0x24, 0xb2, 0xe7, 0x98, 0x96, 0x34, 0x34, 0x3d, 0x69, 0x00, 0x73, 0x78, 0x1c, 0xf3,
+ 0x2c, 0x06, 0x13, 0xf8, 0xa3, 0x77, 0xc6, 0x3f, 0x09, 0x2f, 0x36, 0x05, 0xde, 0x36, 0xac, 0xa9,
+ 0x9a, 0xa6, 0xdb, 0x3a, 0x35, 0xd4, 0x93, 0x6a, 0x1f, 0xd8, 0xae, 0x7e, 0x4a, 0x0c, 0xa6, 0x53,
+ 0x83, 0xa5, 0xe6, 0x84, 0x70, 0x2e, 0x2e, 0xcf, 0x16, 0x04, 0x90, 0x1e, 0xc3, 0x72, 0x60, 0xa6,
+ 0x86, 0xb0, 0xf0, 0x4b, 0x88, 0xf5, 0x3f, 0xe7, 0x30, 0x9f, 0xe9, 0xc6, 0x18, 0xd3, 0x29, 0x8e,
+ 0x9a, 0xa7, 0x96, 0x7d, 0x17, 0x5e, 0x81, 0x28, 0xb1, 0x2c, 0x6a, 0xf9, 0x34, 0x07, 0x9b, 0xec,
+ 0x36, 0xac, 0x4b, 0xd4, 0xd6, 0x8f, 0xba, 0xfe, 0xec, 0xd6, 0x3a, 0x8e, 0xad, 0xd1, 0x4f, 0xc6,
+ 0x30, 0xf8, 0xcd, 0xf3, 0x9f, 0x81, 0x47, 0x33, 0xdc, 0xcc, 0xa4, 0x06, 0x23, 0x9b, 0xdb, 0xf0,
+ 0x70, 0x46, 0xb7, 0xf1, 0x3c, 0x44, 0xca, 0x52, 0x59, 0x49, 0x72, 0x38, 0x01, 0x73, 0xa2, 0x54,
+ 0xad, 0x8b, 0x75, 0x31, 0x89, 0x30, 0x40, 0x6c, 0xa7, 0x24, 0xed, 0x88, 0x07, 0xc9, 0xd0, 0x66,
+ 0x0b, 0xd6, 0x66, 0xe6, 0xc2, 0x31, 0x08, 0x55, 0xde, 0x24, 0x39, 0x2c, 0xc0, 0xba, 0x52, 0xa9,
+ 0x34, 0xde, 0x96, 0xa4, 0x0f, 0x0d, 0x59, 0xac, 0xd6, 0xc5, 0x9a, 0x52, 0x6b, 0x1c, 0x8a, 0x72,
+ 0x43, 0x11, 0xa5, 0x92, 0xa4, 0x24, 0x11, 0x8e, 0x43, 0x54, 0x94, 0xe5, 0x8a, 0x9c, 0x0c, 0xe1,
+ 0xfb, 0x70, 0xaf, 0xb6, 0x5f, 0x57, 0x94, 0xb2, 0xf4, 0xba, 0xb1, 0x5b, 0x79, 0x27, 0x25, 0xc3,
+ 0xc5, 0x5f, 0x28, 0xc0, 0x7b, 0x8f, 0x5a, 0xc3, 0x4b, 0x5c, 0x87, 0x84, 0xbf, 0x3c, 0xa0, 0xd4,
+ 0xc4, 0x99, 0x31, 0xdc, 0xff, 0xbf, 0x14, 0xe9, 0xcc, 0xac, 0x7e, 0xf8, 0xda, 0x2c, 0x97, 0x43,
+ 0x5b, 0x08, 0x1b, 0xb0, 0x3a, 0x15, 0x19, 0x7e, 0x32, 0xe6, 0xbf, 0xa9, 0x29, 0xe9, 0xcd, 0xbb,
+ 0x48, 0x07, 0x1d, 0x28, 0x9a, 0xb0, 0x12, 0x4c, 0x37, 0x1a, 0xa7, 0xf7, 0xb0, 0x30, 0x5c, 0x7b,
+ 0xf9, 0x84, 0xdb, 0xae, 0x68, 0x5a, 0xb8, 0x6d, 0xe0, 0x06, 0x09, 0x5f, 0x95, 0x7a, 0x17, 0x3c,
+ 0x77, 0x7e, 0xc1, 0x73, 0xd7, 0x17, 0x3c, 0xfa, 0xec, 0xf2, 0xe8, 0x87, 0xcb, 0xa3, 0x9f, 0x2e,
+ 0x8f, 0x7a, 0x2e, 0x8f, 0x7e, 0xbb, 0x3c, 0xba, 0x72, 0x79, 0xee, 0xda, 0xe5, 0xd1, 0xd7, 0x4b,
+ 0x9e, 0xeb, 0x5d, 0xf2, 0xdc, 0xf9, 0x25, 0xcf, 0x7d, 0x0c, 0xbe, 0xe9, 0xcd, 0x98, 0xf7, 0x24,
+ 0x3f, 0xfd, 0x1b, 0x00, 0x00, 0xff, 0xff, 0xa4, 0x78, 0x2c, 0xd5, 0xfa, 0x05, 0x00, 0x00,
}
func (x FrontendToSchedulerType) String() string {
@@ -540,92 +522,6 @@ func (this *QuerierToScheduler) Equal(that interface{}) bool {
}
return true
}
-func (this *SchedulerToQuerier) Equal(that interface{}) bool {
- if that == nil {
- return this == nil
- }
-
- that1, ok := that.(*SchedulerToQuerier)
- if !ok {
- that2, ok := that.(SchedulerToQuerier)
- if ok {
- that1 = &that2
- } else {
- return false
- }
- }
- if that1 == nil {
- return this == nil
- } else if this == nil {
- return false
- }
- if this.QueryID != that1.QueryID {
- return false
- }
- if !this.HttpRequest.Equal(that1.HttpRequest) {
- return false
- }
- if this.FrontendAddress != that1.FrontendAddress {
- return false
- }
- if this.UserID != that1.UserID {
- return false
- }
- if this.StatsEnabled != that1.StatsEnabled {
- return false
- }
- if this.QueueTimeNanos != that1.QueueTimeNanos {
- return false
- }
- return true
-}
-func (this *FrontendToScheduler) Equal(that interface{}) bool {
- if that == nil {
- return this == nil
- }
-
- that1, ok := that.(*FrontendToScheduler)
- if !ok {
- that2, ok := that.(FrontendToScheduler)
- if ok {
- that1 = &that2
- } else {
- return false
- }
- }
- if that1 == nil {
- return this == nil
- } else if this == nil {
- return false
- }
- if this.Type != that1.Type {
- return false
- }
- if this.FrontendAddress != that1.FrontendAddress {
- return false
- }
- if this.QueryID != that1.QueryID {
- return false
- }
- if this.UserID != that1.UserID {
- return false
- }
- if !this.HttpRequest.Equal(that1.HttpRequest) {
- return false
- }
- if this.StatsEnabled != that1.StatsEnabled {
- return false
- }
- if len(this.AdditionalQueueDimensions) != len(that1.AdditionalQueueDimensions) {
- return false
- }
- for i := range this.AdditionalQueueDimensions {
- if this.AdditionalQueueDimensions[i] != that1.AdditionalQueueDimensions[i] {
- return false
- }
- }
- return true
-}
func (this *SchedulerToFrontend) Equal(that interface{}) bool {
if that == nil {
return this == nil
@@ -1091,153 +987,6 @@ func (m *QuerierToScheduler) MarshalToSizedBuffer(dAtA []byte) (int, error) {
return len(dAtA) - i, nil
}
-func (m *SchedulerToQuerier) Marshal() (dAtA []byte, err error) {
- size := m.Size()
- dAtA = make([]byte, size)
- n, err := m.MarshalToSizedBuffer(dAtA[:size])
- if err != nil {
- return nil, err
- }
- return dAtA[:n], nil
-}
-
-func (m *SchedulerToQuerier) MarshalTo(dAtA []byte) (int, error) {
- size := m.Size()
- return m.MarshalToSizedBuffer(dAtA[:size])
-}
-
-func (m *SchedulerToQuerier) MarshalToSizedBuffer(dAtA []byte) (int, error) {
- i := len(dAtA)
- _ = i
- var l int
- _ = l
- if m.QueueTimeNanos != 0 {
- i = encodeVarintScheduler(dAtA, i, uint64(m.QueueTimeNanos))
- i--
- dAtA[i] = 0x30
- }
- if m.StatsEnabled {
- i--
- if m.StatsEnabled {
- dAtA[i] = 1
- } else {
- dAtA[i] = 0
- }
- i--
- dAtA[i] = 0x28
- }
- if len(m.UserID) > 0 {
- i -= len(m.UserID)
- copy(dAtA[i:], m.UserID)
- i = encodeVarintScheduler(dAtA, i, uint64(len(m.UserID)))
- i--
- dAtA[i] = 0x22
- }
- if len(m.FrontendAddress) > 0 {
- i -= len(m.FrontendAddress)
- copy(dAtA[i:], m.FrontendAddress)
- i = encodeVarintScheduler(dAtA, i, uint64(len(m.FrontendAddress)))
- i--
- dAtA[i] = 0x1a
- }
- if m.HttpRequest != nil {
- {
- size, err := m.HttpRequest.MarshalToSizedBuffer(dAtA[:i])
- if err != nil {
- return 0, err
- }
- i -= size
- i = encodeVarintScheduler(dAtA, i, uint64(size))
- }
- i--
- dAtA[i] = 0x12
- }
- if m.QueryID != 0 {
- i = encodeVarintScheduler(dAtA, i, uint64(m.QueryID))
- i--
- dAtA[i] = 0x8
- }
- return len(dAtA) - i, nil
-}
-
-func (m *FrontendToScheduler) Marshal() (dAtA []byte, err error) {
- size := m.Size()
- dAtA = make([]byte, size)
- n, err := m.MarshalToSizedBuffer(dAtA[:size])
- if err != nil {
- return nil, err
- }
- return dAtA[:n], nil
-}
-
-func (m *FrontendToScheduler) MarshalTo(dAtA []byte) (int, error) {
- size := m.Size()
- return m.MarshalToSizedBuffer(dAtA[:size])
-}
-
-func (m *FrontendToScheduler) MarshalToSizedBuffer(dAtA []byte) (int, error) {
- i := len(dAtA)
- _ = i
- var l int
- _ = l
- if len(m.AdditionalQueueDimensions) > 0 {
- for iNdEx := len(m.AdditionalQueueDimensions) - 1; iNdEx >= 0; iNdEx-- {
- i -= len(m.AdditionalQueueDimensions[iNdEx])
- copy(dAtA[i:], m.AdditionalQueueDimensions[iNdEx])
- i = encodeVarintScheduler(dAtA, i, uint64(len(m.AdditionalQueueDimensions[iNdEx])))
- i--
- dAtA[i] = 0x3a
- }
- }
- if m.StatsEnabled {
- i--
- if m.StatsEnabled {
- dAtA[i] = 1
- } else {
- dAtA[i] = 0
- }
- i--
- dAtA[i] = 0x30
- }
- if m.HttpRequest != nil {
- {
- size, err := m.HttpRequest.MarshalToSizedBuffer(dAtA[:i])
- if err != nil {
- return 0, err
- }
- i -= size
- i = encodeVarintScheduler(dAtA, i, uint64(size))
- }
- i--
- dAtA[i] = 0x2a
- }
- if len(m.UserID) > 0 {
- i -= len(m.UserID)
- copy(dAtA[i:], m.UserID)
- i = encodeVarintScheduler(dAtA, i, uint64(len(m.UserID)))
- i--
- dAtA[i] = 0x22
- }
- if m.QueryID != 0 {
- i = encodeVarintScheduler(dAtA, i, uint64(m.QueryID))
- i--
- dAtA[i] = 0x18
- }
- if len(m.FrontendAddress) > 0 {
- i -= len(m.FrontendAddress)
- copy(dAtA[i:], m.FrontendAddress)
- i = encodeVarintScheduler(dAtA, i, uint64(len(m.FrontendAddress)))
- i--
- dAtA[i] = 0x12
- }
- if m.Type != 0 {
- i = encodeVarintScheduler(dAtA, i, uint64(m.Type))
- i--
- dAtA[i] = 0x8
- }
- return len(dAtA) - i, nil
-}
-
func (m *SchedulerToFrontend) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
diff --git a/pkg/scheduler/schedulerpb/scheduler.proto b/pkg/scheduler/schedulerpb/scheduler.proto
index ff9a8f1180b..fdf220ab915 100644
--- a/pkg/scheduler/schedulerpb/scheduler.proto
+++ b/pkg/scheduler/schedulerpb/scheduler.proto
@@ -36,6 +36,9 @@ message QuerierToScheduler {
}
message SchedulerToQuerier {
+ option (gogoproto.equal) = false;
+ option (gogoproto.marshaler) = false;
+
// Query ID as reported by frontend. When querier sends the response back to frontend (using frontendAddress),
// it identifies the query by using this ID.
uint64 queryID = 1;
@@ -73,6 +76,8 @@ enum FrontendToSchedulerType {
}
message FrontendToScheduler {
+ option (gogoproto.equal) = false;
+ option (gogoproto.marshaler) = false;
FrontendToSchedulerType type = 1;
// Used by INIT message. Will be put into all requests passed to querier.
diff --git a/vendor/github.com/imdario/mergo/.deepsource.toml b/vendor/dario.cat/mergo/.deepsource.toml
similarity index 72%
rename from vendor/github.com/imdario/mergo/.deepsource.toml
rename to vendor/dario.cat/mergo/.deepsource.toml
index 8a0681af855..a8bc979e02e 100644
--- a/vendor/github.com/imdario/mergo/.deepsource.toml
+++ b/vendor/dario.cat/mergo/.deepsource.toml
@@ -9,4 +9,4 @@ name = "go"
enabled = true
[analyzers.meta]
- import_path = "github.com/imdario/mergo"
\ No newline at end of file
+ import_path = "dario.cat/mergo"
\ No newline at end of file
diff --git a/vendor/github.com/imdario/mergo/.gitignore b/vendor/dario.cat/mergo/.gitignore
similarity index 95%
rename from vendor/github.com/imdario/mergo/.gitignore
rename to vendor/dario.cat/mergo/.gitignore
index 529c3412ba9..45ad0f1ae30 100644
--- a/vendor/github.com/imdario/mergo/.gitignore
+++ b/vendor/dario.cat/mergo/.gitignore
@@ -13,6 +13,9 @@
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
+# Golang/Intellij
+.idea
+
# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736
.glide/
diff --git a/vendor/github.com/imdario/mergo/.travis.yml b/vendor/dario.cat/mergo/.travis.yml
similarity index 100%
rename from vendor/github.com/imdario/mergo/.travis.yml
rename to vendor/dario.cat/mergo/.travis.yml
diff --git a/vendor/github.com/imdario/mergo/CODE_OF_CONDUCT.md b/vendor/dario.cat/mergo/CODE_OF_CONDUCT.md
similarity index 100%
rename from vendor/github.com/imdario/mergo/CODE_OF_CONDUCT.md
rename to vendor/dario.cat/mergo/CODE_OF_CONDUCT.md
diff --git a/vendor/github.com/imdario/mergo/CONTRIBUTING.md b/vendor/dario.cat/mergo/CONTRIBUTING.md
similarity index 100%
rename from vendor/github.com/imdario/mergo/CONTRIBUTING.md
rename to vendor/dario.cat/mergo/CONTRIBUTING.md
diff --git a/vendor/github.com/imdario/mergo/LICENSE b/vendor/dario.cat/mergo/LICENSE
similarity index 100%
rename from vendor/github.com/imdario/mergo/LICENSE
rename to vendor/dario.cat/mergo/LICENSE
diff --git a/vendor/github.com/imdario/mergo/README.md b/vendor/dario.cat/mergo/README.md
similarity index 66%
rename from vendor/github.com/imdario/mergo/README.md
rename to vendor/dario.cat/mergo/README.md
index ffbbb62c704..0b3c488893b 100644
--- a/vendor/github.com/imdario/mergo/README.md
+++ b/vendor/dario.cat/mergo/README.md
@@ -44,77 +44,60 @@ Also a lovely [comune](http://en.wikipedia.org/wiki/Mergo) (municipality) in the
## Status
-It is ready for production use. [It is used in several projects by Docker, Google, The Linux Foundation, VMWare, Shopify, Microsoft, etc](https://github.com/imdario/mergo#mergo-in-the-wild).
+Mergo is stable and frozen, ready for production. Check a short list of the projects using at large scale it [here](https://github.com/imdario/mergo#mergo-in-the-wild).
-### Important note
+No new features are accepted. They will be considered for a future v2 that improves the implementation and fixes bugs for corner cases.
+
+### Important notes
+
+#### 1.0.0
+
+In [1.0.0](//github.com/imdario/mergo/releases/tag/1.0.0) Mergo moves to a vanity URL `dario.cat/mergo`. No more v1 versions will be released.
+
+If the vanity URL is causing issues in your project due to a dependency pulling Mergo - it isn't a direct dependency in your project - it is recommended to use [replace](https://github.com/golang/go/wiki/Modules#when-should-i-use-the-replace-directive) to pin the version to the last one with the old import URL:
+
+```
+replace github.com/imdario/mergo => github.com/imdario/mergo v0.3.16
+```
+
+#### 0.3.9
Please keep in mind that a problematic PR broke [0.3.9](//github.com/imdario/mergo/releases/tag/0.3.9). I reverted it in [0.3.10](//github.com/imdario/mergo/releases/tag/0.3.10), and I consider it stable but not bug-free. Also, this version adds support for go modules.
Keep in mind that in [0.3.2](//github.com/imdario/mergo/releases/tag/0.3.2), Mergo changed `Merge()`and `Map()` signatures to support [transformers](#transformers). I added an optional/variadic argument so that it won't break the existing code.
-If you were using Mergo before April 6th, 2015, please check your project works as intended after updating your local copy with ```go get -u github.com/imdario/mergo```. I apologize for any issue caused by its previous behavior and any future bug that Mergo could cause in existing projects after the change (release 0.2.0).
+If you were using Mergo before April 6th, 2015, please check your project works as intended after updating your local copy with ```go get -u dario.cat/mergo```. I apologize for any issue caused by its previous behavior and any future bug that Mergo could cause in existing projects after the change (release 0.2.0).
### Donations
If Mergo is useful to you, consider buying me a coffee, a beer, or making a monthly donation to allow me to keep building great free software. :heart_eyes:
-
### Mergo in the wild
-- [moby/moby](https://github.com/moby/moby)
-- [kubernetes/kubernetes](https://github.com/kubernetes/kubernetes)
-- [vmware/dispatch](https://github.com/vmware/dispatch)
-- [Shopify/themekit](https://github.com/Shopify/themekit)
-- [imdario/zas](https://github.com/imdario/zas)
-- [matcornic/hermes](https://github.com/matcornic/hermes)
-- [OpenBazaar/openbazaar-go](https://github.com/OpenBazaar/openbazaar-go)
-- [kataras/iris](https://github.com/kataras/iris)
-- [michaelsauter/crane](https://github.com/michaelsauter/crane)
-- [go-task/task](https://github.com/go-task/task)
-- [sensu/uchiwa](https://github.com/sensu/uchiwa)
-- [ory/hydra](https://github.com/ory/hydra)
-- [sisatech/vcli](https://github.com/sisatech/vcli)
-- [dairycart/dairycart](https://github.com/dairycart/dairycart)
-- [projectcalico/felix](https://github.com/projectcalico/felix)
-- [resin-os/balena](https://github.com/resin-os/balena)
-- [go-kivik/kivik](https://github.com/go-kivik/kivik)
-- [Telefonica/govice](https://github.com/Telefonica/govice)
-- [supergiant/supergiant](supergiant/supergiant)
-- [SergeyTsalkov/brooce](https://github.com/SergeyTsalkov/brooce)
-- [soniah/dnsmadeeasy](https://github.com/soniah/dnsmadeeasy)
-- [ohsu-comp-bio/funnel](https://github.com/ohsu-comp-bio/funnel)
-- [EagerIO/Stout](https://github.com/EagerIO/Stout)
-- [lynndylanhurley/defsynth-api](https://github.com/lynndylanhurley/defsynth-api)
-- [russross/canvasassignments](https://github.com/russross/canvasassignments)
-- [rdegges/cryptly-api](https://github.com/rdegges/cryptly-api)
-- [casualjim/exeggutor](https://github.com/casualjim/exeggutor)
-- [divshot/gitling](https://github.com/divshot/gitling)
-- [RWJMurphy/gorl](https://github.com/RWJMurphy/gorl)
-- [andrerocker/deploy42](https://github.com/andrerocker/deploy42)
-- [elwinar/rambler](https://github.com/elwinar/rambler)
-- [tmaiaroto/gopartman](https://github.com/tmaiaroto/gopartman)
-- [jfbus/impressionist](https://github.com/jfbus/impressionist)
-- [Jmeyering/zealot](https://github.com/Jmeyering/zealot)
-- [godep-migrator/rigger-host](https://github.com/godep-migrator/rigger-host)
-- [Dronevery/MultiwaySwitch-Go](https://github.com/Dronevery/MultiwaySwitch-Go)
-- [thoas/picfit](https://github.com/thoas/picfit)
-- [mantasmatelis/whooplist-server](https://github.com/mantasmatelis/whooplist-server)
-- [jnuthong/item_search](https://github.com/jnuthong/item_search)
-- [bukalapak/snowboard](https://github.com/bukalapak/snowboard)
-- [containerssh/containerssh](https://github.com/containerssh/containerssh)
-- [goreleaser/goreleaser](https://github.com/goreleaser/goreleaser)
-- [tjpnz/structbot](https://github.com/tjpnz/structbot)
+Mergo is used by [thousands](https://deps.dev/go/dario.cat%2Fmergo/v1.0.0/dependents) [of](https://deps.dev/go/github.com%2Fimdario%2Fmergo/v0.3.16/dependents) [projects](https://deps.dev/go/github.com%2Fimdario%2Fmergo/v0.3.12), including:
+
+* [containerd/containerd](https://github.com/containerd/containerd)
+* [datadog/datadog-agent](https://github.com/datadog/datadog-agent)
+* [docker/cli/](https://github.com/docker/cli/)
+* [goreleaser/goreleaser](https://github.com/goreleaser/goreleaser)
+* [go-micro/go-micro](https://github.com/go-micro/go-micro)
+* [grafana/loki](https://github.com/grafana/loki)
+* [kubernetes/kubernetes](https://github.com/kubernetes/kubernetes)
+* [masterminds/sprig](github.com/Masterminds/sprig)
+* [moby/moby](https://github.com/moby/moby)
+* [slackhq/nebula](https://github.com/slackhq/nebula)
+* [volcano-sh/volcano](https://github.com/volcano-sh/volcano)
## Install
- go get github.com/imdario/mergo
+ go get dario.cat/mergo
// use in your .go code
import (
- "github.com/imdario/mergo"
+ "dario.cat/mergo"
)
## Usage
@@ -135,6 +118,39 @@ if err := mergo.Merge(&dst, src, mergo.WithOverride); err != nil {
}
```
+If you need to override pointers, so the source pointer's value is assigned to the destination's pointer, you must use `WithoutDereference`:
+
+```go
+package main
+
+import (
+ "fmt"
+
+ "dario.cat/mergo"
+)
+
+type Foo struct {
+ A *string
+ B int64
+}
+
+func main() {
+ first := "first"
+ second := "second"
+ src := Foo{
+ A: &first,
+ B: 2,
+ }
+
+ dest := Foo{
+ A: &second,
+ B: 1,
+ }
+
+ mergo.Merge(&dest, src, mergo.WithOverride, mergo.WithoutDereference)
+}
+```
+
Additionally, you can map a `map[string]interface{}` to a struct (and otherwise, from struct to map), following the same restrictions as in `Merge()`. Keys are capitalized to find each corresponding exported field.
```go
@@ -152,7 +168,7 @@ package main
import (
"fmt"
- "github.com/imdario/mergo"
+ "dario.cat/mergo"
)
type Foo struct {
@@ -188,9 +204,9 @@ package main
import (
"fmt"
- "github.com/imdario/mergo"
- "reflect"
- "time"
+ "dario.cat/mergo"
+ "reflect"
+ "time"
)
type timeTransformer struct {
diff --git a/vendor/github.com/imdario/mergo/SECURITY.md b/vendor/dario.cat/mergo/SECURITY.md
similarity index 100%
rename from vendor/github.com/imdario/mergo/SECURITY.md
rename to vendor/dario.cat/mergo/SECURITY.md
diff --git a/vendor/github.com/imdario/mergo/doc.go b/vendor/dario.cat/mergo/doc.go
similarity index 88%
rename from vendor/github.com/imdario/mergo/doc.go
rename to vendor/dario.cat/mergo/doc.go
index fcd985f995d..7d96ec0546d 100644
--- a/vendor/github.com/imdario/mergo/doc.go
+++ b/vendor/dario.cat/mergo/doc.go
@@ -8,30 +8,36 @@ A helper to merge structs and maps in Golang. Useful for configuration default v
Mergo merges same-type structs and maps by setting default values in zero-value fields. Mergo won't merge unexported (private) fields. It will do recursively any exported one. It also won't merge structs inside maps (because they are not addressable using Go reflection).
-Status
+# Status
It is ready for production use. It is used in several projects by Docker, Google, The Linux Foundation, VMWare, Shopify, etc.
-Important note
+# Important notes
+
+1.0.0
+
+In 1.0.0 Mergo moves to a vanity URL `dario.cat/mergo`.
+
+0.3.9
Please keep in mind that a problematic PR broke 0.3.9. We reverted it in 0.3.10. We consider 0.3.10 as stable but not bug-free. . Also, this version adds suppot for go modules.
Keep in mind that in 0.3.2, Mergo changed Merge() and Map() signatures to support transformers. We added an optional/variadic argument so that it won't break the existing code.
-If you were using Mergo before April 6th, 2015, please check your project works as intended after updating your local copy with go get -u github.com/imdario/mergo. I apologize for any issue caused by its previous behavior and any future bug that Mergo could cause in existing projects after the change (release 0.2.0).
+If you were using Mergo before April 6th, 2015, please check your project works as intended after updating your local copy with go get -u dario.cat/mergo. I apologize for any issue caused by its previous behavior and any future bug that Mergo could cause in existing projects after the change (release 0.2.0).
-Install
+# Install
Do your usual installation procedure:
- go get github.com/imdario/mergo
+ go get dario.cat/mergo
- // use in your .go code
- import (
- "github.com/imdario/mergo"
- )
+ // use in your .go code
+ import (
+ "dario.cat/mergo"
+ )
-Usage
+# Usage
You can only merge same-type structs with exported fields initialized as zero value of their type and same-types maps. Mergo won't merge unexported (private) fields but will do recursively any exported one. It won't merge empty structs value as they are zero values too. Also, maps will be merged recursively except for structs inside maps (because they are not addressable using Go reflection).
@@ -59,7 +65,7 @@ Here is a nice example:
import (
"fmt"
- "github.com/imdario/mergo"
+ "dario.cat/mergo"
)
type Foo struct {
@@ -81,7 +87,7 @@ Here is a nice example:
// {two 2}
}
-Transformers
+# Transformers
Transformers allow to merge specific types differently than in the default behavior. In other words, now you can customize how some types are merged. For example, time.Time is a struct; it doesn't have zero value but IsZero can return true because it has fields with zero value. How can we merge a non-zero time.Time?
@@ -89,9 +95,9 @@ Transformers allow to merge specific types differently than in the default behav
import (
"fmt"
- "github.com/imdario/mergo"
- "reflect"
- "time"
+ "dario.cat/mergo"
+ "reflect"
+ "time"
)
type timeTransformer struct {
@@ -127,17 +133,16 @@ Transformers allow to merge specific types differently than in the default behav
// { 2018-01-12 01:15:00 +0000 UTC m=+0.000000001 }
}
-Contact me
+# Contact me
If I can help you, you have an idea or you are using Mergo in your projects, don't hesitate to drop me a line (or a pull request): https://twitter.com/im_dario
-About
+# About
Written by Dario Castañé: https://da.rio.hn
-License
+# License
BSD 3-Clause license, as Go language.
-
*/
package mergo
diff --git a/vendor/github.com/imdario/mergo/map.go b/vendor/dario.cat/mergo/map.go
similarity index 96%
rename from vendor/github.com/imdario/mergo/map.go
rename to vendor/dario.cat/mergo/map.go
index b50d5c2a4e7..759b4f74fd5 100644
--- a/vendor/github.com/imdario/mergo/map.go
+++ b/vendor/dario.cat/mergo/map.go
@@ -58,7 +58,7 @@ func deepMap(dst, src reflect.Value, visited map[uintptr]*visit, depth int, conf
}
fieldName := field.Name
fieldName = changeInitialCase(fieldName, unicode.ToLower)
- if v, ok := dstMap[fieldName]; !ok || (isEmptyValue(reflect.ValueOf(v), !config.ShouldNotDereference) || overwrite) {
+ if _, ok := dstMap[fieldName]; !ok || (!isEmptyValue(reflect.ValueOf(src.Field(i).Interface()), !config.ShouldNotDereference) && overwrite) || config.overwriteWithEmptyValue {
dstMap[fieldName] = src.Field(i).Interface()
}
}
diff --git a/vendor/github.com/imdario/mergo/merge.go b/vendor/dario.cat/mergo/merge.go
similarity index 99%
rename from vendor/github.com/imdario/mergo/merge.go
rename to vendor/dario.cat/mergo/merge.go
index 0ef9b2138c1..fd47c95b2b8 100644
--- a/vendor/github.com/imdario/mergo/merge.go
+++ b/vendor/dario.cat/mergo/merge.go
@@ -269,7 +269,7 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, co
if err = deepMerge(dst.Elem(), src.Elem(), visited, depth+1, config); err != nil {
return
}
- } else {
+ } else if src.Elem().Kind() != reflect.Struct {
if overwriteWithEmptySrc || (overwrite && !src.IsNil()) || dst.IsNil() {
dst.Set(src)
}
diff --git a/vendor/github.com/imdario/mergo/mergo.go b/vendor/dario.cat/mergo/mergo.go
similarity index 100%
rename from vendor/github.com/imdario/mergo/mergo.go
rename to vendor/dario.cat/mergo/mergo.go
diff --git a/vendor/github.com/CrowdStrike/csproto/.gitignore b/vendor/github.com/CrowdStrike/csproto/.gitignore
new file mode 100644
index 00000000000..b08c5d2061d
--- /dev/null
+++ b/vendor/github.com/CrowdStrike/csproto/.gitignore
@@ -0,0 +1,12 @@
+# build/test outputs
+bin/
+dist/
+*.test
+*profile.out
+
+# editor-related files
+.vscode/
+.idea
+
+# Go workspace files
+go.work*
diff --git a/vendor/github.com/CrowdStrike/csproto/.golangci.yml b/vendor/github.com/CrowdStrike/csproto/.golangci.yml
new file mode 100644
index 00000000000..09b6e560b0b
--- /dev/null
+++ b/vendor/github.com/CrowdStrike/csproto/.golangci.yml
@@ -0,0 +1,69 @@
+# options for analysis running
+run:
+ modules-download-mode: readonly
+ deadline: 10m
+ timeout: 10m
+
+issues:
+ exclude-rules:
+ # ignore code duplication in tests
+ - path: _test\.go
+ linters:
+ - dupl
+ # ignore deprecation warnings for golang/protobuf
+ - path: \.go
+ linters:
+ - staticcheck
+ text: '"github.com/golang/protobuf/proto" is deprecated'
+
+# output configuration options
+output:
+ print-issued-lines: false
+ sort-results: true
+ uniq-by-line: false
+
+linters:
+ # these are disabled by default so turn them on
+ enable:
+ - dupl
+ - errname
+ - exhaustive
+ - gochecknoinits
+ - goimports
+ - gosec
+ - lll
+ - nolintlint
+ - predeclared
+ - revive
+ - stylecheck
+ - unconvert
+ - unparam
+
+linters-settings:
+ exhaustive:
+ # check switch statements in generated files also
+ check-generated: false
+ # indicates that switch statements are to be considered exhaustive if a
+ # 'default' case is present, even if all enum members aren't listed in the
+ # switch
+ default-signifies-exhaustive: true
+ goimports:
+ local-prefixes: github.com/CrowdStrike
+ lll:
+ line-length: 200
+ tab-width: 4
+ nolintlint:
+ # allow unused nolint to avoid false positives for linters that are temporarily disabled under go1.18
+ # . see https://github.com/golangci/golangci-lint/issues/2649
+ allow-unused: true
+ require-explanation: true
+ revive:
+ ignore-generated-header: true
+ min-confidence: 0
+ gosec:
+ excludes:
+ # disable "Potential integer overflow when converting between integer types"
+ # - we have to do A LOT of conversions between integer types when encoding/decoding so there
+ # are lots of _potential_ overflows
+ # - more efficient to disable this check globally than for each line
+ - G115
diff --git a/vendor/github.com/CrowdStrike/csproto/.goreleaser.yaml b/vendor/github.com/CrowdStrike/csproto/.goreleaser.yaml
new file mode 100644
index 00000000000..582d021dae1
--- /dev/null
+++ b/vendor/github.com/CrowdStrike/csproto/.goreleaser.yaml
@@ -0,0 +1,64 @@
+project_name: csproto
+before:
+ hooks:
+ - go mod tidy
+builds:
+ - id: protoc-gen-fastmarshal
+ main: ./cmd/protoc-gen-fastmarshal
+ binary: protoc-gen-fastmarshal
+ flags:
+ - -trimpath
+ ldflags:
+ - '-X main.version={{.Version}} -X main.commit={{.FullCommit}} -X main.date={{.CommitDate}} -X main.builtBy=goreleaser'
+ env:
+ - CGO_ENABLED=0
+ goarch:
+ - '386'
+ - amd64
+ - arm
+ - arm64
+ goarm:
+ - '6'
+ - '7'
+ goos:
+ - linux
+ - darwin
+ - windows
+ - id: protodump
+ main: ./cmd/protodump
+ binary: protodump
+ flags:
+ - -trimpath
+ ldflags:
+ - '-X main.version={{.Version}} -X main.commit={{.FullCommit}} -X main.date={{.CommitDate}} -X main.builtBy=goreleaser'
+ env:
+ - CGO_ENABLED=0
+ goarch:
+ - '386'
+ - amd64
+ - arm
+ - arm64
+ goarm:
+ - '6'
+ - '7'
+ goos:
+ - linux
+ - darwin
+ - windows
+archives:
+ - name_template: '{{.ProjectName}}_{{.Version}}_{{title .Os}}_{{if eq .Arch "amd64"}}x86_64{{else if eq .Arch "386"}}i386{{else}}{{.Arch}}{{end}}{{if .Arm}}v{{.Arm}}{{end}}'
+ format_overrides:
+ - goos: windows
+ format: zip
+checksum:
+ name_template: 'checksums.txt'
+snapshot:
+ name_template: "{{ incminor .Version }}-pre.{{.Timestamp}}.{{.ShortCommit}}"
+changelog:
+ use: github-native
+ filters:
+ exclude:
+ - '^(docs|test)(\\(.+\\))?:'
+release:
+ prerelease: auto
+ mode: append
diff --git a/vendor/github.com/CrowdStrike/csproto/CONTRIBUTING.md b/vendor/github.com/CrowdStrike/csproto/CONTRIBUTING.md
new file mode 100644
index 00000000000..3382b25df8c
--- /dev/null
+++ b/vendor/github.com/CrowdStrike/csproto/CONTRIBUTING.md
@@ -0,0 +1,103 @@
+# Contributing
+
+_Welcome!_ We're excited you want to take part in the CrowdStrike community!
+
+Please review this document for details regarding getting started with your first contribution, tools
+you'll need to install as a developer, and our development and Pull Request process. If you have any
+questions, please let us know by posting your question in the [discussion board](https://github.com/CrowdStrike/csproto/discussions).
+
+## Table of Contents
+
+- [Code of Conduct](#code-of-conduct)
+- [How you can contribute](#how-you-can-contribute)
+- [Working with the Code](#working-with-the-code)
+ - [Commit Messages](#commit-message-formatting-and-hygiene)
+ - [Benchmarks](#benchmarks)
+- [Pull Requests](#pull-requests)
+ - [Code Coverage](#code-coverage)
+
+## Code of Conduct
+
+Please refer to CrowdStrike's general [Code of Conduct](https://opensource.crowdstrike.com/code-of-conduct/)
+and [contribution guidelines](https://opensource.crowdstrike.com/contributing/).
+
+## How you can contribute
+
+- See something? Say something! Submit a [bug report](https://github.com/CrowdStrike/csproto/issues/new?assignees=&labels=bug%2Ctriage&template=bug.md&title=) to let the community know what you've experienced or found.
+ - Please propose new features on the discussion board first.
+- Join the [discussion board](https://github.com/CrowdStrike/csproto/discussions) where you can:
+ - [Interact](https://github.com/CrowdStrike/csproto/discussions/categories/general) with other members of the community
+ - [Start a discussion](https://github.com/CrowdStrike/csproto/discussions/categories/ideas) or submit a [feature request](https://github.com/CrowdStrike/csproto/issues/new?assignees=&labels=enhancement%2Ctriage&template=feature_request.md&title=)
+ - Provide [feedback](https://github.com/CrowdStrike/csproto/discussions/categories/q-a)
+ - [Show others](https://github.com/CrowdStrike/csproto/discussions/categories/show-and-tell) how you are using `csproto` today
+- Submit a [Pull Request](#pull-requests)
+
+## Working with the Code
+
+To simplify and standardize things, we use GNU Make to execute local development tasks like building
+and linting the code, running tests and benchmarks, etc.
+
+The table below shows the most common targets:
+
+| Target | Description |
+| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `test` | Runs all tests for the root module and the nested `examples` module |
+| `bench` | Runs the benchmarks in the nested `examples` module |
+| `generate` | Generates the Go code in the nested `examples` module by invoking the appropriate `protoc` plug-ins |
+| `regenerate` | Regenerates the Go code in the nested `examples` module by removing the existing generated code and build artifacts then invoking the appropriate `protoc` plug-ins |
+
+### Prerequisites
+
+We have tried to minimize the "extra" work you'll have to do, but there are a few prerequisites:
+
+- GNU Make
+- Go 1.17 or higher
+- The `protoc` Protobuf compiler
+
+As the exact details of how to install these tools varies from system to system, we have chosen to
+leave that part to you.
+
+### Other Build-Time Tools
+
+All other build-time tooling is installed into a project-level `bin/` folder because we don't want to impact
+any other projects by overwriting binaries in `$GOPATH/bin`. To accomodate that, `Makefile` prepends
+the local `bin/` folder to `$PATH` so that any Make targets will find the build-time tools there. If
+you choose to not use our Make targets, please ensure that you adjust your environment accordingly.
+
+Another twist: we need to generate code using both the "old" (V1 Protobuf API) and "new" (V2 Protobuf API)
+versions of `protoc-gen-go`, so we explicitly rename the resulting binaries in the project-local `bin/`
+folder to `protoc-gen-go-v1` and `protoc-gen-go-v2`, respectively, and use the `--plugin` option to
+`protoc` to point the `--go_out=...` parameter to the "correct" binary when generating code.
+
+### Commit Message Formatting and Hygiene
+
+We use [_Conventional Commits_](https://www.conventionalcommits.org/en/v1.0.0/) formatting for commit
+messages, which we feel leads to a much more informative change history. Please familiarize yourself
+with that specification and format your commit messages accordingly.
+
+Another aspect of achieving a clean, informative commit history is to avoid "noise" in commits.
+Ideally, condense your changes to a single commit with a well-written _Conventional Commits_ message
+before submitting a PR. In the rare case that a single PR is introducing more than one change, each
+change should be a single commit with its own well-written message.
+
+### Benchmarks
+
+The primary purpose of this library is to provide a runtime-independent Protobuf API, but allowing for
+optimal performance is a close second. In fact, we were able to beat both Google's and Gogo's runtime
+performance by as much as 40% by using our `protoc-gen-fastmarshal` code generator.
+
+With that in mind, any changes that negatively impact these benchmarks will likely be rejected. At a
+minimum, changes that decrease performance will receive pushback and will need to be justified explicitly.
+
+## Pull Requests
+
+All code changes should be submitted via a Pull Request targeting the `main` branch. We are not assuming
+that every merged PR creates a release, so we will not be automatically creating new SemVer tags as
+a side effect of merging your Pull Request. Instead, we will manually tag new releases when required.
+
+### Code Coverage
+
+While we feel like achieving and maintaining 100% code coverage is often an untenable goal with
+diminishing returns, any changes that reduce code coverage will receive pushback. We don't want
+people to spend days trying to bump coverage from 97% to 98%, often at the expense of code clarity,
+but that doesn't mean that we're okay with making things worse.
diff --git a/vendor/github.com/CrowdStrike/csproto/LICENSE b/vendor/github.com/CrowdStrike/csproto/LICENSE
new file mode 100644
index 00000000000..4c893340177
--- /dev/null
+++ b/vendor/github.com/CrowdStrike/csproto/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2022 CrowdStrike, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
\ No newline at end of file
diff --git a/vendor/github.com/CrowdStrike/csproto/Makefile b/vendor/github.com/CrowdStrike/csproto/Makefile
new file mode 100644
index 00000000000..adc1ac5793b
--- /dev/null
+++ b/vendor/github.com/CrowdStrike/csproto/Makefile
@@ -0,0 +1,174 @@
+PROJECT_BASE_DIR := $(realpath $(dir $(abspath $(lastword $(MAKEFILE_LIST)))))
+# prepend the project-local bin/ folder to $PATH so that we find build-time tools there
+PATH := ${PROJECT_BASE_DIR}/bin:${PATH}
+
+# metadata for generating "version" info for local builds
+CURRENT_USER ?= $(shell whoami)
+CURRENT_DATE ?= $(shell date -u +'%FT%R:%SZ')
+CURRENT_DATE_DIGITS_ONLY ?= $(shell date -u +'%Y%m%d%H%M%S')
+CURRENT_COMMIT ?= $(shell git rev-parse HEAD)
+CURRENT_COMMIT_SHORT ?= $(shell git rev-parse --short HEAD)
+LOCAL_DEV_VERSION ?= "v0.0.0-devel-${CURRENT_USER}-${CURRENT_DATE_DIGITS_ONLY}-${CURRENT_COMMIT_SHORT}"
+LOCAL_LDFLAGS = -ldflags="-X main.version=${LOCAL_DEV_VERSION} -X main.commit=${CURRENT_COMMIT} -X main.builtBy=${CURRENT_USER} -X main.date=${CURRENT_DATE}"
+
+PROTOC_GEN_GOGO = github.com/gogo/protobuf/protoc-gen-gogo@$(shell go list -f '{{.Version}}' -m github.com/gogo/protobuf)
+PROTOC_GEN_GO_V1 = github.com/golang/protobuf/protoc-gen-go@$(shell go list -f '{{.Version}}' -m github.com/golang/protobuf)
+PROTOC_GEN_GO_V2 = google.golang.org/protobuf/cmd/protoc-gen-go@$(shell go list -f '{{.Version}}' -m google.golang.org/protobuf)
+
+# re-map Protobuf well-known types used in examples to Gogo's package instead of Google's
+# . need 2 variables b/c protoc-gen-gogo (which is using its fork of the github.com/golang/protobuf V1 API)
+# doesn't support the ';type' syntax to explicitly specify the target Go package but protoc-gen-fastmarshal
+# (which is based on the V2 protobuf API) requires it to correctly handle re-mapping the WKT .proto
+# files that have 'go_package' options with different packages specified.
+GOGO_WKT_OPTIONS = ,Mgoogle/protobuf/any.proto=github.com/gogo/protobuf/types,Mgoogle/protobuf/duration.proto=github.com/gogo/protobuf/types,Mgoogle/protobuf/struct.proto=github.com/gogo/protobuf/types,Mgoogle/protobuf/timestamp.proto=github.com/gogo/protobuf/types,Mgoogle/protobuf/wrappers.proto=github.com/gogo/protobuf/types
+FASTMARSHAL_WKT_OPTIONS = ,Mgoogle/protobuf/any.proto=github.com/gogo/protobuf/types\;types,Mgoogle/protobuf/duration.proto=github.com/gogo/protobuf/types\;types,Mgoogle/protobuf/struct.proto=github.com/gogo/protobuf/types\;types,Mgoogle/protobuf/timestamp.proto=github.com/gogo/protobuf/types\;types,Mgoogle/protobuf/wrappers.proto=github.com/gogo/protobuf/types\;types
+
+TEST_OPTS ?= -race
+BENCHMARKS_PATTERN ?= .
+
+.PHONY: test
+test:
+ $(info Running csproto library tests ...)
+ @go test ${TEST_OPTS} ./...
+ $(info Running example tests ...)
+ @cd ${PROJECT_BASE_DIR}/example && go test ${TEST_OPTS} ./...
+
+.PHONY: bench
+bench:
+ @cd ${PROJECT_BASE_DIR}/example &&\
+ go test -run='^$$' -bench=${BENCHMARKS_PATTERN} -benchmem ./proto2 ./proto3
+
+GENERATE_TARGETS =\
+ example-proto2-gogo example-proto2-googlev1 example-proto2-googlev2\
+ example-proto3-gogo example-proto3-googlev1 example-proto3-googlev2\
+ example-permessage-gogo example-permessage-googlev1 example-permessage-googlev2
+.PHONY: generate
+generate: ${GENERATE_TARGETS}
+ $(info Done)
+
+.PHONY: regenerate
+regenerate: clean clean-generated generate
+
+.PHONY: example-proto2-gogo
+example-proto2-gogo: install-protoc-gen-gogo protoc-gen-fastmarshal
+ $(info Generating Protobuf code for example/proto2/gogo ...)
+ @cd ${PROJECT_BASE_DIR}/example/proto2/gogo &&\
+ protoc -I . --gogo_out=paths=source_relative${GOGO_WKT_OPTIONS}:. --fastmarshal_out=paths=source_relative${FASTMARSHAL_WKT_OPTIONS},specialname=Size:. *.proto
+
+.PHONY: example-proto3-gogo
+example-proto3-gogo: install-protoc-gen-gogo protoc-gen-fastmarshal
+ $(info Generating Protobuf code for example/proto3/gogo ...)
+ @cd ${PROJECT_BASE_DIR}/example/proto3/gogo &&\
+ protoc -I . --gogo_out=paths=source_relative${GOGO_WKT_OPTIONS}:. --fastmarshal_out=paths=source_relative${FASTMARSHAL_WKT_OPTIONS}:. *.proto
+
+.PHONY: example-proto2-googlev1
+example-proto2-googlev1: install-protoc-gen-go-v1 protoc-gen-fastmarshal
+ $(info Generating Protobuf code for example/proto2/googlev1 ...)
+ @cd ${PROJECT_BASE_DIR}/example/proto2/googlev1 &&\
+ protoc -I . --plugin=protoc-gen-go=${PROJECT_BASE_DIR}/bin/protoc-gen-go-v1 --go_out=paths=source_relative:. --fastmarshal_out=apiversion=v2,paths=source_relative:. *.proto
+
+.PHONY: example-proto3-googlev1
+example-proto3-googlev1: install-protoc-gen-go-v1 protoc-gen-fastmarshal
+ $(info Generating Protobuf code for example/proto3/googlev1 ...)
+ @cd ${PROJECT_BASE_DIR}/example/proto3/googlev1 &&\
+ protoc -I . --plugin=protoc-gen-go=${PROJECT_BASE_DIR}/bin/protoc-gen-go-v1 --go_out=paths=source_relative:. --fastmarshal_out=apiversion=v2,paths=source_relative:. *.proto
+
+.PHONY: example-proto2-googlev2
+example-proto2-googlev2: install-protoc-gen-go-v2 protoc-gen-fastmarshal
+ $(info Generating Protobuf code for example/proto2/googlev2 ...)
+ @cd ${PROJECT_BASE_DIR}/example/proto2/googlev2 &&\
+ protoc -I . --plugin=protoc-gen-go=${PROJECT_BASE_DIR}/bin/protoc-gen-go-v2 --go_out=paths=source_relative:. --fastmarshal_out=apiversion=v2,paths=source_relative:. *.proto
+
+.PHONY: example-proto3-googlev2
+example-proto3-googlev2: install-protoc-gen-go-v2 protoc-gen-fastmarshal
+ $(info Generating Protobuf code for example/proto3/googlev2 ...)
+ @cd ${PROJECT_BASE_DIR}/example/proto3/googlev2 &&\
+ protoc -I . --plugin=protoc-gen-go=${PROJECT_BASE_DIR}/bin/protoc-gen-go-v2 --go_out=paths=source_relative:. --fastmarshal_out=apiversion=v2,paths=source_relative:. *.proto
+
+.PHONY: example-permessage-gogo
+example-permessage-gogo: install-protoc-gen-gogo protoc-gen-fastmarshal
+ $(info Generating Protobuf code for example/permessage/gogo ...)
+ @cd ${PROJECT_BASE_DIR}/example/permessage/gogo &&\
+ protoc -I . --gogo_out=paths=source_relative${GOGO_WKT_OPTIONS}:. --fastmarshal_out=filepermessage=true,paths=source_relative${FASTMARSHAL_WKT_OPTIONS},specialname=Size:. *.proto
+
+.PHONY: example-permessage-googlev1
+example-permessage-googlev1: install-protoc-gen-go-v1 protoc-gen-fastmarshal
+ $(info Generating Protobuf code for example/permessage/googlev1 ...)
+ @cd ${PROJECT_BASE_DIR}/example/permessage/googlev1 &&\
+ protoc -I . --plugin=protoc-gen-go=${PROJECT_BASE_DIR}/bin/protoc-gen-go-v1 --go_out=paths=source_relative:. --fastmarshal_out=apiversion=v2,filepermessage=true,paths=source_relative:. *.proto
+
+.PHONY: example-permessage-googlev2
+example-permessage-googlev2: install-protoc-gen-go-v2 protoc-gen-fastmarshal
+ $(info Generating Protobuf code for example/permessage/googlev2 ...)
+ @cd ${PROJECT_BASE_DIR}/example/permessage/googlev2 &&\
+ protoc -I . --plugin=protoc-gen-go=${PROJECT_BASE_DIR}/bin/protoc-gen-go-v2 --go_out=paths=source_relative:. --fastmarshal_out=apiversion=v2,filepermessage=true,paths=source_relative:. *.proto
+
+.PHONY: protoc-gen-fastmarshal
+protoc-gen-fastmarshal: export GOBIN=${PROJECT_BASE_DIR}/bin
+protoc-gen-fastmarshal: create-local-bin-dir
+ $(info Building protoc-gen-fastmarshal ...)
+ @cd ${PROJECT_BASE_DIR}/cmd/protoc-gen-fastmarshal &&\
+ go install ${LOCAL_LDFLAGS}
+
+.PHONY: install-protoc-gen-gogo
+install-protoc-gen-gogo: export GOBIN=${PROJECT_BASE_DIR}/bin
+install-protoc-gen-gogo: create-local-bin-dir
+ $(info Installing protoc-gen-gogo ...)
+ @go install ${PROTOC_GEN_GOGO}
+
+.PHONY: install-protoc-gen-go-v1
+install-protoc-gen-go-v1: export GOBIN=${PROJECT_BASE_DIR}/bin
+install-protoc-gen-go-v1: create-local-bin-dir
+ $(info Installing ${PROTOC_GEN_GO_V1} to ${PROJECT_BASE_DIR}/bin/protoc-gen-go-v1 ...)
+ @go install ${PROTOC_GEN_GO_V1}
+ @mv ${PROJECT_BASE_DIR}/bin/protoc-gen-go ${PROJECT_BASE_DIR}/bin/protoc-gen-go-v1
+
+.PHONY: install-protoc-gen-go-v2
+install-protoc-gen-go-v2: export GOBIN=${PROJECT_BASE_DIR}/bin
+install-protoc-gen-go-v2: create-local-bin-dir
+ $(info Installing ${PROTOC_GEN_GO_V2} to ${PROJECT_BASE_DIR}/bin/protoc-gen-go-v2 ...)
+ @go install ${PROTOC_GEN_GO_V2}
+ @mv ${PROJECT_BASE_DIR}/bin/protoc-gen-go ${PROJECT_BASE_DIR}/bin/protoc-gen-go-v2
+
+.PHONY: protodump
+protodump: export GOBIN=${PROJECT_BASE_DIR}/bin
+protodump: create-local-bin-dir
+ $(info Building protodump ...)
+ @cd ${PROJECT_BASE_DIR}/cmd/protodump &&\
+ go install ${LOCAL_LDFLAGS}
+
+.PHONY: create-local-bin-dir
+create-local-bin-dir:
+ @mkdir -p ${PROJECT_BASE_DIR}/bin
+
+.PHONY: clean
+clean:
+ $(info Removing build artifacts ...)
+ @rm -rf ${PROJECT_BASE_DIR}/bin/*
+ @find ${PROJECT_BASE_DIR} \( -name "*.test" -o -name "*profile.out" \) -print -delete
+
+.PHONY: clean-generated
+clean-generated:
+ $(info Removing generated code ...)
+ @find ${PROJECT_BASE_DIR} \( -name "*.pb.go" -o -name "*.fm.go" \) -print -delete
+
+.PHONY: lint
+lint: check-golangci-lint-install
+ @golangci-lint run ./...
+ @cd example && golangci-lint run ./...
+
+.PHONY: check-golangci-lint-install
+check-golangci-lint-install:
+ifeq ("$(shell command -v golangci-lint)", "")
+ $(error golangci-lint was not found. Please install it using the method of your choice. (https://golangci-lint.run/usage/install/#local-installation))
+endif
+
+.PHONY: snapshot
+snapshot: check-goreleaser-install
+ @goreleaser release --snapshot --rm-dist
+
+.PHONY: check-goreleaser-install
+check-goreleaser-install:
+ifeq ("$(shell command -v goreleaser)", "")
+ $(error goreleaser was not found. Please install it using the method of your choice. (https://goreleaser.com/install))
+endif
diff --git a/vendor/github.com/CrowdStrike/csproto/README.md b/vendor/github.com/CrowdStrike/csproto/README.md
new file mode 100644
index 00000000000..c29e3e966f4
--- /dev/null
+++ b/vendor/github.com/CrowdStrike/csproto/README.md
@@ -0,0 +1,504 @@
+# `csproto` - CrowdStrike's Protocol Buffers library
+
+[![GoDoc](https://pkg.go.dev/badge/github.com/CrowdStrike/csproto.svg)](https://pkg.go.dev/github.com/CrowdStrike/csproto)
+
+`csproto` is a Go module that provides a library for working with Protocol Buffers messages along with
+a `protoc` plug-in for generating optimized marshaling and unmarshaling code for those messages.
+
+Like many other companies, CrowdStrike extensively uses Protocol Buffers as an efficient wire format
+for communicating between disparate processes and services. Protocol Buffers' [compatibility guarantees](https://developers.google.com/protocol-buffers/docs/overview#updating)
+and smaller, more efficient binary encoding made it a natural fit for the problems we needed to solve.
+
+As our data volume continued to grow, CrowdStrike started to run into performance limitations in
+[Google's Protobuf library](https://github.com/golang/protobuf) and transitioned to using [Gogo Protobuf](https://github.com/gogo/protobuf)
+in an attempt to overcome the issues. This adjustment proved successful and "Use Gogo Protobuf" became
+the de facto guidance within our development teams.
+
+Fast forward to 2020 when the maintainers of that library announced that they are [looking for people to take over](https://github.com/gogo/protobuf/issues/691).
+Unfortunately, this also coincided with Google releasing [V2](https://blog.golang.org/protobuf-apiv2)
+of their Protobuf API. As new and/or improved functionality was introduced in Google's library, the
+lack of active maintenance on Gogo inevitably led to incompatibilities.
+
+This created a problem for CrowdStrike. We needed to update our system to no longer depend on Gogo
+Protobuf but we had **a lot** of direct dependencies on that code spread throughout our codebase.
+The solution we arrived at is this library. It provides the "core" pieces of the Protocol
+Buffers API as used by consumers without having those consumers _directly_ depend on any particular
+runtime implementation.
+
+If you want to dive right in, there's a handy [migration guide](docs/migration_guide.md). Otherwise, keep reading for all of the technical details.
+
+_Disclaimer: `csproto` is an open source project, not a CrowdStrike product. As such, it carries no
+formal support, expressed or implied. The project is licensed under the MIT open source license._
+
+## Supporting Types Across Runtime Implementations
+
+As part of their V2 API, Google also introduced significant changes to the `protoc` code generation plug-in,
+`protoc-gen-go`. One effect of this change was that code generated using the new plug-in uses the new
+API internally. An unfortunate side effect is that those types are no longer compatible with Gogo's API.
+
+One technical limitation of Protocol Buffers is that deserializing a message requires knowledge of the
+actual message type because the encoded field values only contain the integer field tag. Due to this
+limitation, both Google and Gogo use reflection to read the struct tags on the generated Go types and
+to dynamically assign field values when unmarshaling Protobuf messages.
+
+This dependence on reflection has created a scenario where passing a type generated by the new plug-in
+to Gogo's implementation of `csproto.Unmarshal()` results in failures. Specifically, there are several
+new fields in the generated code and the reflection-based logic in Gogo's library doesn't know how to
+treat them. Additionally, several fields that are used by the V1 API, and consequently Gogo's library,
+are no longer generated.
+
+### A Minimal Protocol Buffers API
+
+After a bit of digging, we came up with what we consider the smallest API necessary to support reading
+and writing Protocol Buffers messages that does not expose any dependence on the runtime implementations.
+
+- `Size(msg interface{}) int`
+ - Calculate the size, in bytes, required to hold the binary representation of `msg`
+- `Marshal(msg interface{}) ([]byte, error)`
+ - Convert the contents of `msg` to the binary representation and return it
+- `Unmarshal(p []byte, msg interface{}) error`
+ - Populate `msg` with the contents of the binary message in `p`
+- `HasExtension(msg interface{}, ext interface{}) bool`
+ - Determine if `msg` contains a proto2 extension field
+- `ClearExtension(msg interface{}, ext interface{})`
+ - Clears a proto2 extension field from `msg`
+- `GetExtension(msg interface{}, ext interface{}) (interface{}, error)`
+ - Return the value of a proto2 extension field from `msg`
+- `SetExtension(msg interface{}, ext interface{}, val interface{}) error`
+ - Assign the value of a proto2 extension field on `msg`
+
+There isn't any common interface shared between Google's two runtimes and Gogo's runtime so our library
+had to use the empty interface for all message and extension definition parameters.
+
+With this minimal API, services and libraries are able to create and consume Protobuf-encoded messages
+without being tightly coupled to any specific runtime. Being able to do this was essential for CrowdStrike
+because it is simply impossible to update everything at once to change which runtime library is in use.
+Instead, we gradually updated all of our libraries and services to use this new runtime-independent API
+so that each of our development teams is able to change out their runtime and code generation dependencies
+independently.
+
+### Don't Recreate Everything
+
+Our intent is not to fully recreate the Protocol Buffers runtime. Instead, `csproto` is built to
+determine which existing runtime is the "correct" one for a given message and to delegate to that implementation.
+
+We take advantage of the fact that the Go types can't change at runtime to minimize the impact of this
+indirection. The underlying type of the `msg` parameter is inspected to determine which of the 3
+supported runtimes (Google V1, Gogo, and Google V2) is correct and we store that value in a lookup
+dictionary so that any given type only has to be inspected once.
+
+Even with this optimization, calling `reflect.TypeOf()` on the message and performing the lookup has
+a cost, over 8% in some scenarios! At CrowdStrike's volume even that difference can add up to a
+non-trivial impact across the system so we needed to find a way to at least break even but, ideally,
+to better the performance.
+
+The benchmarks below for proto2 marshaling were generated on a 2019 MacBook Pro:
+
+```bash
+$ go test -run='^$' -bench=. -benchmem
+goos: darwin
+goarch: amd64
+pkg: github.com/CrowdStrike/csproto/example/proto2
+cpu: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
+BenchmarkEncodeGogo-12 1741834 667.4 ns/op 216 B/op 4 allocs/op
+BenchmarkCustomEncodeGogo-12 1785268 669.2 ns/op 216 B/op 4 allocs/op
+BenchmarkEncodeGoogleV1-12 1326734 921.7 ns/op 176 B/op 1 allocs/op
+BenchmarkCustomEncodeGoogleV1-12 1315390 933.5 ns/op 176 B/op 1 allocs/op
+BenchmarkEncodeGoogleV2-12 1329092 906.9 ns/op 176 B/op 1 allocs/op
+BenchmarkCustomEncodeGoogleV2-12 1306638 923.3 ns/op 176 B/op 1 allocs/op
+```
+
+And for proto3:
+
+```bash
+$ go test -run='^$' -bench=. -benchmem
+goos: darwin
+goarch: amd64
+pkg: github.com/CrowdStrike/csproto/example/proto3
+cpu: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
+BenchmarkEncodeGogo-12 3008721 394.1 ns/op 88 B/op 2 allocs/op
+BenchmarkCustomEncodeGogo-12 2900726 400.1 ns/op 88 B/op 2 allocs/op
+BenchmarkEncodeGoogleV1-12 3109386 388.2 ns/op 80 B/op 1 allocs/op
+BenchmarkCustomEncodeGoogleV1-12 2990907 392.8 ns/op 80 B/op 1 allocs/op
+BenchmarkEncodeGoogleV2-12 3290887 367.7 ns/op 80 B/op 1 allocs/op
+BenchmarkCustomEncodeGoogleV2-12 3003828 398.3 ns/op 80 B/op 1 allocs/op
+```
+
+The table below shows the approximate cost of the indirection across the various combinations of
+Protobuf runtimes:
+
+Cost | proto2 | proto3
+--------- | ------- | ------
+Gogo | +0.27% | +1.52%
+Google V1 | +1.28% | +1.18%
+Google V2 | +1.81% | +8.32%
+
+## Optimized Protobuf Marshaling and Unmarshaling
+
+The marshaling and unmarshaling implemented by both Google and Gogo necessarily relies on runtime reflection.
+Both implementations dynamically query the set of fields on the message type and read the associated
+Protobuf struct tags. This information is then used to match up the field tag and wire type in the
+encoded data to the corresponding field on the message and to assign the field values. This solution
+is generic and can be applied to any/all messages without any changes to the implementation but it is
+necessary slower because it has to inspect each message much more deeply.
+
+Another common source of performance bottlenecks is repeated small allocations. It is, in most cases,
+far more efficient to allocate one buffer large enough to hold all of the data you need than to incrementally
+allocate many smaller buffers.
+
+Before moving on, credit must be given to the Vitess team for their [`vtprotobuf` project](https://github.com/planetscale/vtprotobuf)
+which they covered in [this blog from June of 2021](https://vitess.io/blog/2021-06-03-a-new-protobuf-generator-for-go/).
+That project already implements these strategies and more, only with some constraints that didn't work for us.
+Specifically, `vtprotobuf` is only compatible with things that are already using Google's V2 API. Given
+that the inception of this project for CrowdStrike was due to our dependency on Gogo Protobuf we weren't
+able to make use of their work. We also make significant usage of proto2 extensions, which may or may not
+be supported by the Vitess tooling.
+
+### Protocol Buffers Binary Codec
+
+The first step to improving Protobuf serialization is to implement a binary encoder and decoder that
+avoids the issues noted in the last section. Additionally, the Protocol Buffer
+[encoding spec](https://developers.google.com/protocol-buffers/docs/encoding) has a much smaller surface
+area than the set of all valid Protobuf messages.
+
+#### Encoder
+
+The [`Encoder`](encoder.go) type wraps a pre-allocated byte slice and sequentially writes encoded
+field values to it. It is up to the caller to ensure that the provided buffer is large enough to hold
+the full encoded value. As each encoded field is prefixed by the integer field tag and Protobuf wire
+type, `Encoder`'s API is provided as a set of `EncodeXxx(tag int, val T)` methods, one for each supported
+type of value.
+
+This snippet encodes a boolean `true` value with a field tag of 1:
+
+```go
+// Protobuf binary encoding will require 2 bytes, 1 for the tag/wire type and 1 for the value
+buf := make([]byte, 2)
+enc := csproto.NewEncoder(buf)
+enc.EncodeBool(1, true)
+// buf now contains {0x8, 0x1}
+```
+
+Encoding a full message is similar, but using [`csproto.Size()`](sizeof.go) to calculate the required buffer size.
+
+```go
+msg := SomeMessage{
+ Name: csproto.String("example"),
+ Value: csproto.Int32(42),
+ // assign additional fields
+}
+siz := csproto.Size(msg)
+buf := make([]byte, siz)
+enc := csproto.NewEncoder(buf)
+// encode each field sequentially
+enc.EncodeString(1, msg.Name)
+enc.EncodeInt32(2, msg.Value)
+// ...
+```
+
+#### Decoder
+
+Like `Encoder`, the [`Decoder`](decoder.go) type wraps a byte slice and sequentially reads field
+values from it. The Protobuf encoding does not require fields to be in tag order, or present at all
+for that matter, so decoding a message requires a `for` loop combined with a `switch` statement.
+
+```go
+func decodeExample(p []byte) (SomeMessage, error) {
+ var (
+ msg SomeMessage
+ s string
+ i32 int32
+ )
+ dec := csproto.NewDecoder(p)
+ for dec.More() {
+ tag, wireType, err := dec.DecodeTag()
+ if err != nil {
+ return SomeMessage{}, err
+ }
+ switch tag {
+ case 1: // Name
+ if wireType != csproto.WireTypeLengthDelimited {
+ return SomeMessage{}, fmt.Errorf("invalid wire type %s, expected %s", wireType, csproto.WireTypeLengthDelimited)
+ }
+ s, err = dec.DecodeString()
+ if err != nil {
+ return SomeMessage{}, fmt.Errorf("unable to decode string: %w", err)
+ }
+ msg.Name = csproto.String(s)
+ case 2: // Value
+ if wireType != csproto.WireTypeVarint {
+ return SomeMessage{}, fmt.Errorf("invalid wire type %s, expected %s", wireType, csproto.WireTypeVarint)
+ }
+ i32, err = dec.DecodeInt32()
+ if err != nil {
+ return SomeMessage{}, fmt.Errorf("unable to decode int32: %w", err)
+ }
+ msg.Value = csproto.Int32(i32)
+ default: // unknown/unrecognized field, skip it
+ _, _ = dec.Skip(tag, wireType)
+ }
+ }
+}
+```
+
+Notes:
+
+- The cases in the `switch` statement use `csproto.String()` and `csproto.Int32()` to grab pointers to
+ copies of the decoded values.
+- The example above simply throws away unknown fields which you shouldn't do in practice.
+
+##### Safe vs Fast
+
+By default, `Decoder.DecodeString()` will make a full copy of the decoded string. This is the safest,
+most stable practice but it does come with a small cost in both time and allocations. For scenarios
+where maximum performance is more desirable, `Decoder` supports a "fast" mode that uses `unsafe` to
+return the bytes of wrapped buffer directly, saving the type conversion and allocation to create a
+new `string` value.
+
+```go
+...
+dec := csproto.NewDecoder(p)
+dec.SetMode(proto.DecoderModeFast)
+...
+s, err := dec.DecodeString()
+...
+```
+
+Representative benchmarks from a 2019 MacBook Pro
+
+```bash
+...> go test -run='^$' -bench=DecodeString -benchmem ./proto
+goos: darwin
+goarch: amd64
+pkg: github.com/CrowdStrike/csproto
+cpu: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
+BenchmarkSafeDecodeString-12 37183212 27.33 ns/op 16 B/op 1 allocs/op
+BenchmarkFastDecodeString-12 127437440 9.211 ns/op 0 B/op 0 allocs/op
+```
+
+The trade off for the increased performance is that the behavior is undefined if the wrapped buffer
+is modified after decoding the field values from it.
+
+### Opting In
+
+Now that we have a custom, optimized codec available, we need a way to seamlessly integrate it into
+the developer workflow. We do that by defining several new interfaces which our API functions will
+look for when marshaling or unmarshaling messages.
+
+We define 4 single-method interfaces as integration points:
+
+- `csproto.Sizer`
+ - `Size() int`: calculates the size, in bytes, needed to hold the encoded contents of the message
+ - `csproto.Size()` will call this method if the message satisfies the interface
+- `csproto.Marshaler`
+ - `Marshal() ([]byte, error)`: returns the binary encoding of the message
+ - `csproto.Marshal()` will call this method if the message satisfies the interface
+- `csproto.MarshalerTo`
+ - `MarshalTo([]byte) error`: encodes the message into the provided buffer
+ - `csproto.Marshal()` will call this method, after allocating a sufficiently sized buffer, if the messaage
+ satisfies the interface
+- `csproto.Unmarshaler`
+ - `Unmarshal([]byte) error`: decodes the provided data into the message
+ - `csproto.Unmarshal()` will call this method if the message satisfies the interface
+
+With this in place developers have all of the parts needed to create a fully optimized implementation
+of Protocol Buffer marshaling and unmarshaling. We can make things even better, though, by capitalizing
+on the fact that the Protobuf IDL that developers have already written has all of the information we
+need to generate those optimized implementations.
+
+### The `protoc` plug-in
+
+The final piece of the puzzle is `protoc-gen-fastmarshal`, a `protoc` compiler plug-in that reads the
+Protobuf file descriptor and emits implementations of the `Size`, `Marshal`, `MarshalTo`,
+and `Unmarshal` methods for each message defined in the `.proto` file.
+
+Given this example message
+
+```protobuf
+message Example {
+ string name = 1;
+ int32 result = 2;
+}
+```
+
+the generated code would be roughly as follows
+
+```go
+// Size returns the size, in bytes, required to store the contents of m in Protocol Buffers
+// binary format.
+func (m *Example) Size() int {
+ if m == nil {
+ return 0
+ }
+ var (
+ sz, l int
+ )
+ // Name
+ if m.Name != nil {
+ // key + len + bytes
+ l = len(*m.Name)
+ sz += csproto.SizeOfVarint(uint64(1)) + csproto.SizeOfVarint(uint64(l)) + l
+ }
+ // Result
+ if m.Result != nil {
+ // key + varint
+ sz += csproto.SizeOfVarint(uint64(2)) + csproto.SizeOfVarint(uint64(*m.Result))
+ }
+ // unknown/unrecognized fields
+ sz += len(m.unknownFields)
+ return sz
+}
+// Marshal allocates a buffer, writes the contents of m to it using Protocol Buffers binary
+// format, then returns the the buffer.
+func (m *Example) Marshal() ([]byte, error) {
+ sz := m.Size()
+ buf := make([]byte, sz)
+ err := m.MarshalTo(buf)
+ return buf, err
+}
+// MarshalTo writes the contents of m into dest using Protocol Buffers binary format.
+func (m *Example) MarshalTo(dest []byte) error {
+ var (
+ buf []byte
+ err error
+ )
+ enc := csproto.NewEncoder(dest)
+ if m.Name != nil {
+ enc.EncodeString(1, *m.Name)
+ }
+ if m.Result != nil {
+ enc.EncodeInt32(2, *m.Result)
+ }
+ if len(m.unknownFields) > 0 {
+ enc.EncodeRaw(m.unknownFields)
+ }
+ return nil
+}
+// Unmarshal decodes the Protocol Buffers binary format message in p and populates m with the
+// result.
+func (m *Example) Unmarshal(p []byte) error {
+ if len(p) == 0 {
+ return fmt.Errorf("cannot unmarshal from empty buffer")
+ }
+ var (
+ tag int
+ wt csproto.WireType
+ err error
+ )
+ dec := pbtools.NewDecoder(p)
+ for dec.More() {
+ tag, wt, err = dec.DecodeTag()
+ if err != nil {
+ return err
+ }
+ switch tag {
+ case 1: // Name
+ if wt != csproto.WireTypeLengthDelimited {
+ return fmt.Errorf("invalid message data, expected wire type 2 for tag 1, got %v", wt)
+ }
+ if v, err := dec.DecodeString(); err != nil {
+ return fmt.Errorf("unable to decode string value for tag 1: %w", err)
+ } else {
+ m.Name = csproto.String(v)
+ }
+ case 2: // Result
+ if wt != csproto.WireTypeVarint {
+ return fmt.Errorf("invalid message data, expected wire type 0 for tag 2, got %v", wt)
+ }
+ if v, err := dec.DecodeInt32(); err != nil {
+ return fmt.Errorf("unable to decode int32 value for tag 2: %w", err)
+ } else {
+ m.Result = csproto.Int32(v)
+ }
+ default: // unrecognized/unknown field
+ if skipped, err := dec.Skip(tag, wt); err != nil {
+ return fmt.Errorf("invalid operation skipping tag %v: %w", tag, err)
+ } else {
+ m.unknownFields = append(m.unknownFields, skipped)
+ }
+ }
+ }
+ return nil
+}
+```
+
+### Final Benchmarks
+
+After invoking `protoc-gen-fastmarshal`, the final benchmarks for our examples are:
+
+```bash
+$ go test -run='^$' -bench=. -benchmem ./proto2 ./proto3
+goos: darwin
+goarch: amd64
+pkg: github.com/CrowdStrike/csproto/example/proto2
+cpu: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
+BenchmarkEncodeGogo-12 1932699 597.6 ns/op 352 B/op 2 allocs/op
+BenchmarkCustomEncodeGogo-12 2458599 482.3 ns/op 176 B/op 1 allocs/op
+BenchmarkDecodeGogo-12 622585 1887 ns/op 1376 B/op 34 allocs/op
+BenchmarkCustomDecodeGogo-12 798523 1390 ns/op 1144 B/op 27 allocs/op
+BenchmarkEncodeGoogleV1-12 1298185 925.5 ns/op 176 B/op 1 allocs/op
+BenchmarkCustomEncodeGoogleV1-12 2701975 432.4 ns/op 176 B/op 1 allocs/op
+BenchmarkDecodeGoogleV1-12 616106 1662 ns/op 1176 B/op 28 allocs/op
+BenchmarkCustomDecodeGoogleV1-12 776244 1471 ns/op 1160 B/op 26 allocs/op
+BenchmarkEncodeGoogleV2-12 1331971 911.3 ns/op 176 B/op 1 allocs/op
+BenchmarkCustomEncodeGoogleV2-12 2817786 426.1 ns/op 176 B/op 1 allocs/op
+BenchmarkDecodeGoogleV2-12 671048 1739 ns/op 1176 B/op 28 allocs/op
+BenchmarkCustomDecodeGoogleV2-12 755186 1530 ns/op 1160 B/op 26 allocs/op
+PASS
+ok github.com/CrowdStrike/csproto/example/proto2 12.247s
+
+goos: darwin
+goarch: amd64
+pkg: github.com/CrowdStrike/csproto/example/proto3
+cpu: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
+BenchmarkEncodeGogo-12 3479755 341.0 ns/op 208 B/op 3 allocs/op
+BenchmarkCustomEncodeGogo-12 4824855 248.1 ns/op 112 B/op 2 allocs/op
+BenchmarkDecodeGogo-12 1328734 909.9 ns/op 424 B/op 16 allocs/op
+BenchmarkCustomDecodeGogo-12 1604020 753.5 ns/op 408 B/op 15 allocs/op
+BenchmarkEncodeGoogleV1-12 2599558 450.6 ns/op 96 B/op 1 allocs/op
+BenchmarkCustomEncodeGoogleV1-12 3452514 348.4 ns/op 112 B/op 2 allocs/op
+BenchmarkDecodeGoogleV1-12 962179 1076 ns/op 440 B/op 16 allocs/op
+BenchmarkCustomDecodeGoogleV1-12 1337054 904.2 ns/op 424 B/op 15 allocs/op
+BenchmarkEncodeGoogleV2-12 2741904 433.4 ns/op 96 B/op 1 allocs/op
+BenchmarkCustomEncodeGoogleV2-12 3337425 356.1 ns/op 112 B/op 2 allocs/op
+BenchmarkDecodeGoogleV2-12 1000000 1077 ns/op 440 B/op 16 allocs/op
+BenchmarkCustomDecodeGoogleV2-12 1327365 913.4 ns/op 424 B/op 15 allocs/op
+PASS
+ok github.com/CrowdStrike/csproto/example/proto3 9.186s
+```
+
+As you can see in the table below, the optimized code is faster across the board.
+
+Cost | proto2 (encode) | proto3 (encode) | proto2 (decode) | proto3 (decode)
+--------- | ---------------- | --------------- | --------------- | ---------------
+Gogo | -19.3% | -27.2% | -26.3% | -17.2%
+Google V1 | -53.3% | -22.7% | -11.5% | -16.0%
+Google V2 | -53.3% | -17.8% | -12.0% | -15.2%
+
+### A Warning About `proto2` Extension Fields
+
+Unfortunately, the news is not all good. This library is limited to the public APIs of the three underlying runtimes when working with `proto2` extension fields and those APIs take advantage of unexported features to gain efficiency. Since they are unexported, those efficiency gains are unavailable to the code in `csproto` and the code generated by `protoc-gen-fastmarshal` that calls it.
+
+One significant difference is in `Unmarshal()`. All three runtimes have internal code that delays decoding the bytes of `proto2` extension fields until `GetExtension()` is called. Since `csproto` does not have access to this code, the unmarshaling code generated by `protoc-gen-fastmarshal` has to actually decode the extension field then explicitly call `SetExtension()` with the result. In some cases we've seen this be as much as 30% slower than calling the underlying `proto.Unmarshal()` directly. You can see this in action by removing the calls to `GetExtension()` from [the proto2 Gogo benchmarks](./example/proto2/gogo_benchmarks_test.go) and observing the change in the resulting measurements.
+
+Because of these issues, we advise that projects which rely heavily on `proto2` extension fields **SHOULD NOT** use `protoc-gen-fastmarshal` to generate custom marshal/unmarshal code.
+
+## gRPC
+
+To use with gRPC you will need to register `csproto` as the encoder.
+**NOTE:** If messages do not implement `Marshaler` or `Unmarshaler` then an error will be returned.
+An example is below.
+
+For more information, see [the gRPC documentation](https://github.com/grpc/grpc-go/blob/master/Documentation/encoding.md).
+
+```go
+import (
+ "github.com/CrowdStrike/csproto"
+ "google.golang.org/grpc/encoding"
+ _ "google.golang.org/grpc/encoding/proto"
+)
+
+func init() {
+ encoding.RegisterCodec(csproto.GrpcCodec{})
+}
+```
diff --git a/vendor/github.com/CrowdStrike/csproto/clone.go b/vendor/github.com/CrowdStrike/csproto/clone.go
new file mode 100644
index 00000000000..7b021f869fd
--- /dev/null
+++ b/vendor/github.com/CrowdStrike/csproto/clone.go
@@ -0,0 +1,25 @@
+package csproto
+
+import (
+ gogo "github.com/gogo/protobuf/proto"
+ google "github.com/golang/protobuf/proto" //nolint: staticcheck // we're using this deprecated package intentionally
+ googlev2 "google.golang.org/protobuf/proto"
+)
+
+// Clone returns a deep copy of m, delegating to the appropriate underlying Protobuf API based on
+// the concrete type of m. Since the underlying runtimes return different types, this function returns
+// interface{} and the caller will need to type-assert back to the concrete type of m.
+//
+// If m is not one of the supported message types, this function returns nil.
+func Clone(m interface{}) interface{} {
+ switch MsgType(m) {
+ case MessageTypeGoogle:
+ return googlev2.Clone(m.(googlev2.Message))
+ case MessageTypeGoogleV1:
+ return google.Clone(m.(google.Message))
+ case MessageTypeGogo:
+ return gogo.Clone(m.(gogo.Message))
+ default:
+ return nil
+ }
+}
diff --git a/vendor/github.com/CrowdStrike/csproto/decoder.go b/vendor/github.com/CrowdStrike/csproto/decoder.go
new file mode 100644
index 00000000000..07a1d56d4b4
--- /dev/null
+++ b/vendor/github.com/CrowdStrike/csproto/decoder.go
@@ -0,0 +1,1107 @@
+package csproto
+
+import (
+ "encoding/binary"
+ "errors"
+ "fmt"
+ "io"
+ "math"
+ "unsafe"
+)
+
+var (
+ // ErrInvalidFieldTag is returned by the decoder when it fails to read a varint-encoded field tag/wire type value.
+ ErrInvalidFieldTag = errors.New("unable to read protobuf field tag")
+ // ErrInvalidVarintData is returned by the decoder when it fails to read a varint-encoded value.
+ ErrInvalidVarintData = errors.New("unable to read protobuf varint value")
+ // ErrValueOverflow is returned by DecodeUInt32() or DecodeInt32() when the decoded value is too large for a 32-bit value.
+ ErrValueOverflow = errors.New("value overflow trying to read protobuf varint value")
+ // ErrLenOverflow is returned when the LEN portion of a length-delimited field is larger than 2GB
+ ErrLenOverflow = errors.New("field length cannot be more than 2GB")
+ // ErrInvalidZigZagData is returned by the decoder when it fails to read a zigzag-encoded value.
+ ErrInvalidZigZagData = errors.New("unable to read protobuf zigzag value")
+ // ErrInvalidFixed32Data is returned by the decoder when it fails to read a fixed-size 32-bit value.
+ ErrInvalidFixed32Data = errors.New("unable to read protobuf fixed 32-bit value")
+ // ErrInvalidFixed64Data is returned by the decoder when it fails to read a fixed-size 64-bit value.
+ ErrInvalidFixed64Data = errors.New("unable to read protobuf fixed 64-bit value")
+ // ErrInvalidPackedData is returned by the decoder when it fails to read a packed repeated value.
+ ErrInvalidPackedData = errors.New("unable to read protobuf packed value")
+)
+
+// MaxTagValue is the largest supported protobuf field tag, which is 2^29 - 1 (or 536,870,911)
+const MaxTagValue = 536870911
+
+// length-delimited fields cannot contain more than 2GB
+const maxFieldLen = math.MaxInt32
+
+// DecoderMode defines the behavior of the decoder (safe vs fastest).
+type DecoderMode int
+
+const (
+ // DecoderModeSafe instructs the decoder to only use safe operations when decoding values.
+ DecoderModeSafe DecoderMode = iota
+ // DecoderModeFast instructs the decoder to use unsafe operations to avoid allocations and copying data
+ // for the fastest throughput.
+ //
+ // When using DecoderModeFast, the byte slice passed to the decoder must not be modified after
+ // using the decoder to extract values. The behavior is undefined if the slice is modified.
+ DecoderModeFast
+)
+
+// String returns a string representation of m, "safe" or "fast".
+func (m DecoderMode) String() string {
+ if m == DecoderModeSafe {
+ return "safe"
+ }
+ return "fast"
+}
+
+// Decoder implements a binary Protobuf Decoder by sequentially reading from a provided []byte.
+type Decoder struct {
+ p []byte
+ offset int
+ mode DecoderMode
+}
+
+// NewDecoder initializes a new Protobuf decoder to read the provided buffer.
+func NewDecoder(p []byte) *Decoder {
+ return &Decoder{
+ p: p,
+ offset: 0,
+ }
+}
+
+// Mode returns the current decoding mode, safe vs fastest.
+func (d *Decoder) Mode() DecoderMode {
+ return d.mode
+}
+
+// SetMode configures the decoding behavior, safe vs fastest.
+func (d *Decoder) SetMode(m DecoderMode) {
+ d.mode = m
+}
+
+// Seek sets the position of the next read operation to [offset], interpreted according to [whence]:
+// [io.SeekStart] means relative to the start of the data, [io.SeekCurrent] means relative to the
+// current offset, and [io.SeekEnd] means relative to the end.
+//
+// This low-level operation is provided to support advanced/custom usages of the decoder and it is up
+// to the caller to ensure that the resulting offset will point to a valid location in the data stream.
+func (d *Decoder) Seek(offset int64, whence int) (int64, error) {
+ pos := int(offset)
+ switch whence {
+ case io.SeekStart:
+ // no adjustment needed
+ case io.SeekCurrent:
+ // shift relative to current read offset
+ pos += d.offset
+ case io.SeekEnd:
+ // shift relative to EOF
+ pos += len(d.p)
+ default:
+ return int64(d.offset), fmt.Errorf("invalid value (%d) for whence", whence)
+ }
+ // verify bounds then update the read position
+ if pos < 0 || pos > len(d.p) {
+ return int64(d.offset), fmt.Errorf("seek position (%d) out of bounds", pos)
+ }
+ d.offset = pos
+ return int64(d.offset), nil
+}
+
+// Reset moves the read offset back to the beginning of the encoded data
+func (d *Decoder) Reset() {
+ d.offset = 0
+}
+
+// More indicates if there is more data to be read in the buffer.
+func (d *Decoder) More() bool {
+ return d.offset < len(d.p)
+}
+
+// Offset returns the current read offset
+func (d *Decoder) Offset() int {
+ return d.offset
+}
+
+// DecodeTag decodes a field tag and Protobuf wire type from the stream and returns the values.
+//
+// io.ErrUnexpectedEOF is returned if the operation would read past the end of the data.
+func (d *Decoder) DecodeTag() (tag int, wireType WireType, err error) {
+ if d.offset >= len(d.p) {
+ return 0, WireTypeVarint, io.ErrUnexpectedEOF
+ }
+ v, n, err := DecodeVarint(d.p[d.offset:])
+ if err != nil {
+ return 0, -1, fmt.Errorf("invalid data at byte %d: %w", d.offset, err)
+ }
+ if n < 1 || v < 1 || v > MaxTagValue {
+ return 0, -1, fmt.Errorf("invalid tag value (%d) at byte %d: %w", v, d.offset, ErrInvalidFieldTag)
+ }
+ d.offset += n
+ return int(v >> 3), WireType(v & 0x7), nil
+}
+
+// DecodeBool decodes a boolean value from the stream and returns the value.
+//
+// io.ErrUnexpectedEOF is returned if the operation would read past the end of the data.
+func (d *Decoder) DecodeBool() (b bool, err error) {
+ if d.offset >= len(d.p) {
+ return false, io.ErrUnexpectedEOF
+ }
+ v, n, err := DecodeVarint(d.p[d.offset:])
+ if err != nil {
+ return false, fmt.Errorf("invalid data at byte %d: %w", d.offset, err)
+ }
+ if n == 0 {
+ return false, fmt.Errorf("invalid data at byte %d: %w", d.offset, ErrInvalidVarintData)
+ }
+ d.offset += n
+ return (v != 0), nil
+}
+
+// DecodeString decodes a length-delimited string from the stream and returns the value.
+//
+// io.ErrUnexpectedEOF is returned if the operation would read past the end of the data.
+func (d *Decoder) DecodeString() (string, error) {
+ if d.offset >= len(d.p) {
+ return "", io.ErrUnexpectedEOF
+ }
+ b, err := d.DecodeBytes()
+ if err != nil {
+ return "", fmt.Errorf("invalid data at byte %d: %w", d.offset, err)
+ }
+ switch d.mode {
+ case DecoderModeFast:
+ return *(*string)(unsafe.Pointer(&b)), nil //nolint: gosec // using unsafe on purpose
+
+ default:
+ // safe mode by default
+ return string(b), nil
+ }
+}
+
+// DecodeBytes decodes a length-delimited slice of bytes from the stream and returns the value.
+//
+// io.ErrUnexpectedEOF is returned if the operation would read past the end of the data.
+func (d *Decoder) DecodeBytes() ([]byte, error) {
+ if d.offset >= len(d.p) {
+ return nil, io.ErrUnexpectedEOF
+ }
+
+ l, n, err := DecodeVarint(d.p[d.offset:])
+ switch {
+ case err != nil:
+ return nil, fmt.Errorf("invalid data at byte %d: %w", d.offset, err)
+ case n == 0:
+ return nil, fmt.Errorf("invalid data at byte %d: %w", d.offset, ErrInvalidVarintData)
+ case l > maxFieldLen:
+ return nil, fmt.Errorf("invalid length (%d) for length-delimited field at byte %d: %w", l, d.offset, ErrLenOverflow)
+ default:
+ // length is good
+ }
+
+ nb := int(l)
+ if d.offset+n+nb > len(d.p) {
+ return nil, io.ErrUnexpectedEOF
+ }
+ b := d.p[d.offset+n : d.offset+n+nb]
+ d.offset += n + nb
+ return b, nil
+}
+
+// DecodeUInt32 decodes a varint-encoded 32-bit unsigned integer from the stream and returns the value.
+//
+// io.ErrUnexpectedEOF is returned if the operation would read past the end of the data.
+func (d *Decoder) DecodeUInt32() (uint32, error) {
+ if d.offset >= len(d.p) {
+ return 0, io.ErrUnexpectedEOF
+ }
+ v, n, err := DecodeVarint(d.p[d.offset:])
+ if err != nil {
+ return 0, fmt.Errorf("invalid data at byte %d: %w", d.offset, err)
+ }
+ if n == 0 {
+ return 0, fmt.Errorf("invalid data at byte %d: %w", d.offset, ErrInvalidVarintData)
+ }
+ if v > math.MaxUint32 {
+ return 0, ErrValueOverflow
+ }
+ d.offset += n
+ return uint32(v), nil
+}
+
+// DecodeUInt64 decodes a varint-encoded 64-bit unsigned integer from the stream and returns the value.
+//
+// io.ErrUnexpectedEOF is returned if the operation would read past the end of the data.
+func (d *Decoder) DecodeUInt64() (uint64, error) {
+ if d.offset >= len(d.p) {
+ return 0, io.ErrUnexpectedEOF
+ }
+ v, n, err := DecodeVarint(d.p[d.offset:])
+ if err != nil {
+ return 0, fmt.Errorf("invalid data at byte %d: %w", d.offset, err)
+ }
+ if n == 0 {
+ return 0, fmt.Errorf("invalid data at byte %d: %w", d.offset, ErrInvalidVarintData)
+ }
+ d.offset += n
+ return v, nil
+}
+
+// DecodeInt32 decodes a varint-encoded 32-bit integer from the stream and returns the value.
+//
+// io.ErrUnexpectedEOF is returned if the operation would read past the end of the data.
+func (d *Decoder) DecodeInt32() (int32, error) {
+ if d.offset >= len(d.p) {
+ return 0, io.ErrUnexpectedEOF
+ }
+ v, n, err := DecodeVarint(d.p[d.offset:])
+ if err != nil {
+ return 0, fmt.Errorf("invalid data at byte %d: %w", d.offset, err)
+ }
+ if n == 0 {
+ return 0, fmt.Errorf("invalid data at byte %d: %w", d.offset, ErrInvalidVarintData)
+ }
+ // ensure the result is within [-math.MaxInt32, math.MaxInt32] when converted to a signed value
+ if i64 := int64(v); i64 > math.MaxInt32 || i64 < math.MinInt32 {
+ return 0, ErrValueOverflow
+ }
+ d.offset += n
+ return int32(v), nil
+}
+
+// DecodeInt64 decodes a varint-encoded 64-bit integer from the stream and returns the value.
+//
+// io.ErrUnexpectedEOF is returned if the operation would read past the end of the data.
+func (d *Decoder) DecodeInt64() (int64, error) {
+ if d.offset >= len(d.p) {
+ return 0, io.ErrUnexpectedEOF
+ }
+ v, n, err := DecodeVarint(d.p[d.offset:])
+ if err != nil {
+ return 0, fmt.Errorf("invalid data at byte %d: %w", d.offset, err)
+ }
+ if n == 0 {
+ return 0, fmt.Errorf("invalid data at byte %d: %w", d.offset, ErrInvalidVarintData)
+ }
+ d.offset += n
+ return int64(v), nil
+}
+
+// DecodeSInt32 decodes a zigzag-encoded 32-bit integer from the stream and returns the value.
+//
+// io.ErrUnexpectedEOF is returned if the operation would read past the end of the data.
+func (d *Decoder) DecodeSInt32() (int32, error) {
+ if d.offset >= len(d.p) {
+ return 0, io.ErrUnexpectedEOF
+ }
+ v, n, err := DecodeZigZag32(d.p[d.offset:])
+ if err != nil {
+ return 0, fmt.Errorf("invalid data at byte %d: %w", d.offset, err)
+ }
+ if n == 0 {
+ return 0, fmt.Errorf("invalid data at byte %d: %w", d.offset, ErrInvalidZigZagData)
+ }
+ d.offset += n
+ return v, nil
+}
+
+// DecodeSInt64 decodes a zigzag-encoded 32-bit integer from the stream and returns the value.
+//
+// io.ErrUnexpectedEOF is returned if the operation would read past the end of the data.
+func (d *Decoder) DecodeSInt64() (int64, error) {
+ if d.offset >= len(d.p) {
+ return 0, io.ErrUnexpectedEOF
+ }
+ v, n, err := DecodeZigZag64(d.p[d.offset:])
+ if err != nil {
+ return 0, fmt.Errorf("invalid data at byte %d: %w", d.offset, err)
+ }
+ if n == 0 {
+ return 0, fmt.Errorf("invalid data at byte %d: %w", d.offset, ErrInvalidZigZagData)
+ }
+ d.offset += n
+ return v, nil
+}
+
+// DecodeFixed32 decodes a 4-byte integer from the stream and returns the value.
+//
+// io.ErrUnexpectedEOF is returned if the operation would read past the end of the data.
+func (d *Decoder) DecodeFixed32() (uint32, error) {
+ if d.offset >= len(d.p) {
+ return 0, io.ErrUnexpectedEOF
+ }
+ v, n, err := DecodeFixed32(d.p[d.offset:])
+ if err != nil {
+ return 0, fmt.Errorf("invalid data at byte %d: %w", d.offset, err)
+ }
+ if n == 0 {
+ return 0, fmt.Errorf("invalid data at byte %d: %w", d.offset, ErrInvalidFixed32Data)
+ }
+ d.offset += n
+ return v, nil
+}
+
+// DecodeFixed64 decodes an 8-byte integer from the stream and returns the value.
+//
+// io.ErrUnexpectedEOF is returned if the operation would read past the end of the data.
+func (d *Decoder) DecodeFixed64() (uint64, error) {
+ if d.offset >= len(d.p) {
+ return 0, io.ErrUnexpectedEOF
+ }
+ v, n, err := DecodeFixed64(d.p[d.offset:])
+ if err != nil {
+ return 0, fmt.Errorf("invalid data at byte %d: %w", d.offset, err)
+ }
+ if n == 0 {
+ return 0, fmt.Errorf("invalid data at byte %d: %w", d.offset, ErrInvalidFixed64Data)
+ }
+ d.offset += n
+ return v, nil
+}
+
+// DecodeFloat32 decodes a 4-byte IEEE 754 floating point value from the stream and returns the value.
+//
+// io.ErrUnexpectedEOF is returned if the operation would read past the end of the data.
+func (d *Decoder) DecodeFloat32() (float32, error) {
+ if d.offset >= len(d.p) {
+ return 0, io.ErrUnexpectedEOF
+ }
+ v := binary.LittleEndian.Uint32(d.p[d.offset:])
+ fv := math.Float32frombits(v)
+ d.offset += 4
+ return fv, nil
+}
+
+// DecodeFloat64 decodes an 8-byte IEEE 754 floating point value from the stream and returns the value.
+//
+// io.ErrUnexpectedEOF is returned if the operation would read past the end of the data.
+func (d *Decoder) DecodeFloat64() (float64, error) {
+ if d.offset >= len(d.p) {
+ return 0, io.ErrUnexpectedEOF
+ }
+ v := binary.LittleEndian.Uint64(d.p[d.offset:])
+ fv := math.Float64frombits(v)
+ d.offset += 8
+ return fv, nil
+}
+
+// DecodePackedBool decodes a packed encoded list of boolean values from the stream and returns the value.
+//
+// io.ErrUnexpectedEOF is returned if the operation would read past the end of the data.
+func (d *Decoder) DecodePackedBool() ([]bool, error) {
+ if d.offset >= len(d.p) {
+ return nil, io.ErrUnexpectedEOF
+ }
+ var (
+ l, nRead uint64
+ n int
+ err error
+ res []bool
+ )
+ l, n, err = DecodeVarint(d.p[d.offset:])
+ if err != nil {
+ return nil, fmt.Errorf("invalid data at byte %d: %w", d.offset, err)
+ }
+ if n == 0 {
+ return nil, fmt.Errorf("invalid data at byte %d: %w", d.offset, ErrInvalidVarintData)
+ }
+ d.offset += n
+ packedDataStart := d.offset
+ for nRead < l {
+ if d.offset >= len(d.p) {
+ return nil, io.ErrUnexpectedEOF
+ }
+ v, n, err := DecodeVarint(d.p[d.offset:])
+ if err != nil {
+ return nil, fmt.Errorf("invalid data at byte %d: %w", d.offset, err)
+ }
+ if n == 0 {
+ return nil, fmt.Errorf("invalid data at byte %d: %w", d.offset, ErrInvalidVarintData)
+ }
+ nRead += uint64(n)
+ d.offset += n
+ res = append(res, (v != 0))
+ }
+ if nRead != l {
+ return nil, fmt.Errorf("invalid packed data at byte %d: %w", packedDataStart, ErrInvalidPackedData)
+ }
+ return res, nil
+}
+
+// DecodePackedInt32 decodes a packed encoded list of 32-bit integers from the stream and returns the value.
+//
+// io.ErrUnexpectedEOF is returned if the operation would read past the end of the data.
+func (d *Decoder) DecodePackedInt32() ([]int32, error) { //nolint: dupl // FALSE POSITIVE: this function is NOT a duplicate
+ if d.offset >= len(d.p) {
+ return nil, io.ErrUnexpectedEOF
+ }
+ var (
+ l, nRead uint64
+ n int
+ err error
+ res []int32
+ )
+ l, n, err = DecodeVarint(d.p[d.offset:])
+ if err != nil {
+ return nil, fmt.Errorf("invalid data at byte %d: %w", d.offset, err)
+ }
+ if n == 0 {
+ return nil, fmt.Errorf("invalid data at byte %d: %w", d.offset, ErrInvalidVarintData)
+ }
+ d.offset += n
+ packedDataStart := d.offset
+ for nRead < l {
+ if d.offset >= len(d.p) {
+ return nil, io.ErrUnexpectedEOF
+ }
+ v, n, err := DecodeVarint(d.p[d.offset:])
+ if err != nil {
+ return nil, fmt.Errorf("invalid data at byte %d: %w", d.offset, err)
+ }
+ if n == 0 {
+ return nil, fmt.Errorf("invalid data at byte %d: %w", d.offset, ErrInvalidVarintData)
+ }
+ // ensure the result is within [-math.MaxInt32, math.MaxInt32] when converted to a signed value
+ if v > math.MaxInt32 {
+ return nil, fmt.Errorf("invalid data at byte %d: %w", d.offset, ErrValueOverflow)
+ }
+ nRead += uint64(n)
+ d.offset += n
+ res = append(res, int32(v))
+ }
+ if nRead != l {
+ return nil, fmt.Errorf("invalid packed data at byte %d: %w", packedDataStart, ErrInvalidPackedData)
+ }
+ return res, nil
+}
+
+// DecodePackedInt64 decodes a packed encoded list of 64-bit integers from the stream and returns the value.
+//
+// io.ErrUnexpectedEOF is returned if the operation would read past the end of the data.
+func (d *Decoder) DecodePackedInt64() ([]int64, error) { //nolint: dupl // FALSE POSITIVE: this function is NOT a duplicate
+ if d.offset >= len(d.p) {
+ return nil, io.ErrUnexpectedEOF
+ }
+ var (
+ l, nRead uint64
+ n int
+ err error
+ res []int64
+ )
+ l, n, err = DecodeVarint(d.p[d.offset:])
+ if err != nil {
+ return nil, fmt.Errorf("invalid data at byte %d: %w", d.offset, err)
+ }
+ if n == 0 {
+ return nil, fmt.Errorf("invalid data at byte %d: %w", d.offset, ErrInvalidVarintData)
+ }
+ d.offset += n
+ packedDataStart := d.offset
+ for nRead < l {
+ if d.offset >= len(d.p) {
+ return nil, io.ErrUnexpectedEOF
+ }
+ v, n, err := DecodeVarint(d.p[d.offset:])
+ if err != nil {
+ return nil, fmt.Errorf("invalid data at byte %d: %w", d.offset, err)
+ }
+ if n == 0 {
+ return nil, fmt.Errorf("invalid data at byte %d: %w", d.offset, ErrInvalidVarintData)
+ }
+ if v > math.MaxInt64 {
+ return nil, fmt.Errorf("invalid data at byte %d: %w", d.offset, ErrValueOverflow)
+ }
+ nRead += uint64(n)
+ d.offset += n
+ res = append(res, int64(v))
+ }
+ if nRead != l {
+ return nil, fmt.Errorf("invalid packed data at byte %d: %w", packedDataStart, ErrInvalidPackedData)
+ }
+ return res, nil
+}
+
+// DecodePackedUint32 decodes a packed encoded list of unsigned 32-bit integers from the stream and
+// returns the value.
+//
+// io.ErrUnexpectedEOF is returned if the operation would read past the end of the data.
+func (d *Decoder) DecodePackedUint32() ([]uint32, error) { //nolint: dupl // FALSE POSITIVE: this function is NOT a duplicate
+ if d.offset >= len(d.p) {
+ return nil, io.ErrUnexpectedEOF
+ }
+ var (
+ l, nRead uint64
+ n int
+ err error
+ res []uint32
+ )
+ l, n, err = DecodeVarint(d.p[d.offset:])
+ if err != nil {
+ return nil, fmt.Errorf("invalid data at byte %d: %w", d.offset, err)
+ }
+ if n == 0 {
+ return nil, fmt.Errorf("invalid data at byte %d: %w", d.offset, ErrInvalidVarintData)
+ }
+ d.offset += n
+ packedDataStart := d.offset
+ for nRead < l {
+ if d.offset >= len(d.p) {
+ return nil, io.ErrUnexpectedEOF
+ }
+ v, n, err := DecodeVarint(d.p[d.offset:])
+ if err != nil {
+ return nil, fmt.Errorf("invalid data at byte %d: %w", d.offset, err)
+ }
+ if n == 0 {
+ return nil, fmt.Errorf("invalid data at byte %d: %w", d.offset, ErrInvalidVarintData)
+ }
+ // ensure the result is within [0, math.MaxUInt32]
+ if v > math.MaxUint32 {
+ return nil, fmt.Errorf("invalid data at byte %d: %w", d.offset, ErrValueOverflow)
+ }
+ nRead += uint64(n)
+ d.offset += n
+ res = append(res, uint32(v))
+ }
+ if nRead != l {
+ return nil, fmt.Errorf("invalid packed data at byte %d: %w", packedDataStart, ErrInvalidPackedData)
+ }
+ return res, nil
+}
+
+// DecodePackedUint64 decodes a packed encoded list of unsigned 64-bit integers from the stream and
+// returns the value.
+//
+// io.ErrUnexpectedEOF is returned if the operation would read past the end of the data.
+func (d *Decoder) DecodePackedUint64() ([]uint64, error) { //nolint: dupl // FALSE POSITIVE: this function is NOT a duplicate
+ if d.offset >= len(d.p) {
+ return nil, io.ErrUnexpectedEOF
+ }
+ var (
+ l, nRead uint64
+ n int
+ err error
+ res []uint64
+ )
+ l, n, err = DecodeVarint(d.p[d.offset:])
+ if err != nil {
+ return nil, fmt.Errorf("invalid data at byte %d: %w", d.offset, err)
+ }
+ if n == 0 {
+ return nil, fmt.Errorf("invalid data at byte %d: %w", d.offset, ErrInvalidVarintData)
+ }
+ d.offset += n
+ packedDataStart := d.offset
+ for nRead < l {
+ if d.offset >= len(d.p) {
+ return nil, io.ErrUnexpectedEOF
+ }
+ v, n, err := DecodeVarint(d.p[d.offset:])
+ if err != nil {
+ return nil, fmt.Errorf("invalid data at byte %d: %w", d.offset, err)
+ }
+ if n == 0 {
+ return nil, fmt.Errorf("invalid data at byte %d: %w", d.offset, ErrInvalidVarintData)
+ }
+ nRead += uint64(n)
+ d.offset += n
+ res = append(res, v)
+ }
+ if nRead != l {
+ return nil, fmt.Errorf("invalid packed data at byte %d: %w", packedDataStart, ErrInvalidPackedData)
+ }
+ return res, nil
+}
+
+// DecodePackedSint32 decodes a packed encoded list of 32-bit signed integers from the stream and returns
+// the value.
+//
+// io.ErrUnexpectedEOF is returned if the operation would read past the end of the data.
+func (d *Decoder) DecodePackedSint32() ([]int32, error) { //nolint: dupl // FALSE POSITIVE: this function is NOT a duplicate
+ if d.offset >= len(d.p) {
+ return nil, io.ErrUnexpectedEOF
+ }
+ var (
+ l, nRead uint64
+ n int
+ err error
+ res []int32
+ )
+ l, n, err = DecodeVarint(d.p[d.offset:])
+ if err != nil {
+ return nil, fmt.Errorf("invalid data at byte %d: %w", d.offset, err)
+ }
+ if n == 0 {
+ return nil, fmt.Errorf("invalid data at byte %d: %w", d.offset, ErrInvalidVarintData)
+ }
+ d.offset += n
+ packedDataStart := d.offset
+ for nRead < l {
+ if d.offset >= len(d.p) {
+ return nil, io.ErrUnexpectedEOF
+ }
+ v, n, err := DecodeZigZag32(d.p[d.offset:])
+ if err != nil {
+ return nil, fmt.Errorf("invalid data at byte %d: %w", d.offset, err)
+ }
+ if n == 0 {
+ return nil, fmt.Errorf("invalid data at byte %d: %w", d.offset, ErrInvalidVarintData)
+ }
+ nRead += uint64(n)
+ d.offset += n
+ res = append(res, v)
+ }
+ if nRead != l {
+ return nil, fmt.Errorf("invalid packed data at byte %d: %w", packedDataStart, ErrInvalidPackedData)
+ }
+ return res, nil
+}
+
+// DecodePackedSint64 decodes a packed encoded list of 64-bit signed integers from the stream and returns
+// the value.
+//
+// io.ErrUnexpectedEOF is returned if the operation would read past the end of the data.
+func (d *Decoder) DecodePackedSint64() ([]int64, error) { //nolint: dupl // FALSE POSITIVE: this function is NOT a duplicate
+ if d.offset >= len(d.p) {
+ return nil, io.ErrUnexpectedEOF
+ }
+ var (
+ l, nRead uint64
+ n int
+ err error
+ res []int64
+ )
+ l, n, err = DecodeVarint(d.p[d.offset:])
+ if err != nil {
+ return nil, fmt.Errorf("invalid data at byte %d: %w", d.offset, err)
+ }
+ if n == 0 {
+ return nil, fmt.Errorf("invalid data at byte %d: %w", d.offset, ErrInvalidVarintData)
+ }
+ d.offset += n
+ packedDataStart := d.offset
+ for nRead < l {
+ if d.offset >= len(d.p) {
+ return nil, io.ErrUnexpectedEOF
+ }
+ v, n, err := DecodeZigZag64(d.p[d.offset:])
+ if err != nil {
+ return nil, fmt.Errorf("invalid data at byte %d: %w", d.offset, err)
+ }
+ if n == 0 {
+ return nil, fmt.Errorf("invalid data at byte %d: %w", d.offset, ErrInvalidVarintData)
+ }
+ nRead += uint64(n)
+ d.offset += n
+ res = append(res, v)
+ }
+ if nRead != l {
+ return nil, fmt.Errorf("invalid packed data at byte %d: %w", packedDataStart, ErrInvalidPackedData)
+ }
+ return res, nil
+}
+
+// DecodePackedFixed32 decodes a packed encoded list of 32-bit fixed-width integers from the stream
+// and returns the value.
+//
+// io.ErrUnexpectedEOF is returned if the operation would read past the end of the data.
+func (d *Decoder) DecodePackedFixed32() ([]uint32, error) { //nolint: dupl // FALSE POSITIVE: this function is NOT a duplicate
+ if d.offset >= len(d.p) {
+ return nil, io.ErrUnexpectedEOF
+ }
+ var (
+ l, nRead uint64
+ n int
+ err error
+ res []uint32
+ )
+ l, n, err = DecodeVarint(d.p[d.offset:])
+ if err != nil {
+ return nil, fmt.Errorf("invalid data at byte %d: %w", d.offset, err)
+ }
+ if n == 0 {
+ return nil, fmt.Errorf("invalid data at byte %d: %w", d.offset, ErrInvalidVarintData)
+ }
+ d.offset += n
+ packedDataStart := d.offset
+ for nRead < l {
+ if d.offset >= len(d.p) {
+ return nil, io.ErrUnexpectedEOF
+ }
+ v, n, err := DecodeFixed32(d.p[d.offset:])
+ if err != nil {
+ return nil, fmt.Errorf("invalid data at byte %d: %w", d.offset, err)
+ }
+ if n == 0 {
+ return nil, fmt.Errorf("invalid data at byte %d: %w", d.offset, ErrInvalidVarintData)
+ }
+ nRead += uint64(n)
+ d.offset += n
+ res = append(res, v)
+ }
+ if nRead != l {
+ return nil, fmt.Errorf("invalid packed data at byte %d: %w", packedDataStart, ErrInvalidPackedData)
+ }
+ return res, nil
+}
+
+// DecodePackedFixed64 decodes a packed encoded list of 64-bit fixed-width integers from the stream
+// and returns the value.
+//
+// io.ErrUnexpectedEOF is returned if the operation would read past the end of the data.
+func (d *Decoder) DecodePackedFixed64() ([]uint64, error) { //nolint: dupl // FALSE POSITIVE: this function is NOT a duplicate
+ if d.offset >= len(d.p) {
+ return nil, io.ErrUnexpectedEOF
+ }
+ var (
+ l, nRead uint64
+ n int
+ err error
+ res []uint64
+ )
+ l, n, err = DecodeVarint(d.p[d.offset:])
+ if err != nil {
+ return nil, fmt.Errorf("invalid data at byte %d: %w", d.offset, err)
+ }
+ if n == 0 {
+ return nil, fmt.Errorf("invalid data at byte %d: %w", d.offset, ErrInvalidVarintData)
+ }
+ d.offset += n
+ packedDataStart := d.offset
+ for nRead < l {
+ if d.offset >= len(d.p) {
+ return nil, io.ErrUnexpectedEOF
+ }
+ v, n, err := DecodeFixed64(d.p[d.offset:])
+ if err != nil {
+ return nil, fmt.Errorf("invalid data at byte %d: %w", d.offset, err)
+ }
+ if n == 0 {
+ return nil, fmt.Errorf("invalid data at byte %d: %w", d.offset, ErrInvalidVarintData)
+ }
+ nRead += uint64(n)
+ d.offset += n
+ res = append(res, v)
+ }
+ if nRead != l {
+ return nil, fmt.Errorf("invalid packed data at byte %d: %w", packedDataStart, ErrInvalidPackedData)
+ }
+ return res, nil
+}
+
+// DecodePackedFloat32 decodes a packed encoded list of 32-bit floating point numbers from the stream
+// and returns the value.
+//
+// io.ErrUnexpectedEOF is returned if the operation would read past the end of the data.
+func (d *Decoder) DecodePackedFloat32() ([]float32, error) { //nolint: dupl // FALSE POSITIVE: this function is NOT a duplicate
+ if d.offset >= len(d.p) {
+ return nil, io.ErrUnexpectedEOF
+ }
+ var (
+ l, nRead uint64
+ n int
+ err error
+ res []float32
+ )
+ l, n, err = DecodeVarint(d.p[d.offset:])
+ if err != nil {
+ return nil, fmt.Errorf("invalid data at byte %d: %w", d.offset, err)
+ }
+ if n == 0 {
+ return nil, fmt.Errorf("invalid data at byte %d: %w", d.offset, ErrInvalidVarintData)
+ }
+ d.offset += n
+ packedDataStart := d.offset
+ res = make([]float32, 0, l/4)
+ for nRead < l {
+ if d.offset >= len(d.p) {
+ return nil, io.ErrUnexpectedEOF
+ }
+ v := binary.LittleEndian.Uint32(d.p[d.offset:])
+ nRead += 4
+ d.offset += 4
+ res = append(res, math.Float32frombits(v))
+ }
+ if nRead != l {
+ return nil, fmt.Errorf("invalid packed data at byte %d: %w", packedDataStart, ErrInvalidPackedData)
+ }
+ return res, nil
+}
+
+// DecodePackedFloat64 decodes a packed encoded list of 64-bit floating point numbers from the stream
+// and returns the value.
+//
+// io.ErrUnexpectedEOF is returned if the operation would read past the end of the data.
+func (d *Decoder) DecodePackedFloat64() ([]float64, error) {
+ if d.offset >= len(d.p) {
+ return nil, io.ErrUnexpectedEOF
+ }
+ var (
+ l, nRead uint64
+ n int
+ err error
+ res []float64
+ )
+ l, n, err = DecodeVarint(d.p[d.offset:])
+ if err != nil {
+ return nil, fmt.Errorf("invalid data at byte %d: %w", d.offset, err)
+ }
+ if n == 0 {
+ return nil, fmt.Errorf("invalid data at byte %d: %w", d.offset, ErrInvalidVarintData)
+ }
+ d.offset += n
+ packedDataStart := d.offset
+ for nRead < l {
+ if d.offset >= len(d.p) {
+ return nil, io.ErrUnexpectedEOF
+ }
+ v := binary.LittleEndian.Uint64(d.p[d.offset:])
+ nRead += 8
+ d.offset += 8
+ res = append(res, math.Float64frombits(v))
+ }
+ if nRead != l {
+ return nil, fmt.Errorf("invalid packed data at byte %d: %w", packedDataStart, ErrInvalidPackedData)
+ }
+ return res, nil
+}
+
+// DecodeNested decodes a nested Protobuf message from the stream into m. If m satisfies our csproto.Unmarshaler
+// interface its Unmarshal() method will be called. Otherwise, this method delegates to Marshal().
+//
+// io.ErrUnexpectedEOF is returned if the operation would read past the end of the data.
+func (d *Decoder) DecodeNested(m interface{}) error {
+ if d.offset >= len(d.p) {
+ return io.ErrUnexpectedEOF
+ }
+
+ l, n, err := DecodeVarint(d.p[d.offset:])
+ switch {
+ case err != nil:
+ return fmt.Errorf("invalid data at byte %d: %w", d.offset, err)
+ case n == 0:
+ return fmt.Errorf("invalid data at byte %d: %w", d.offset, ErrInvalidVarintData)
+ case l > maxFieldLen:
+ return fmt.Errorf("invalid length (%d) for length-delimited field at byte %d: %w", l, d.offset, ErrLenOverflow)
+ default:
+ // length is good
+ }
+
+ nb := int(l)
+ if nb < 0 {
+ return fmt.Errorf("csproto: bad byte length %d at byte %d", nb, d.offset)
+ }
+ if d.offset+n+nb > len(d.p) {
+ return io.ErrUnexpectedEOF
+ }
+ switch tv := m.(type) {
+ case Unmarshaler:
+ if err := tv.Unmarshal(d.p[d.offset+n : d.offset+n+nb]); err != nil {
+ return err
+ }
+ default:
+ if err := Unmarshal(d.p[d.offset+n:d.offset+n+nb], m); err != nil {
+ return err
+ }
+ }
+ d.offset += n + nb
+ return nil
+}
+
+// Skip skips over the encoded field value at the current offset, returning the raw bytes so that the
+// caller can decide what to do with the data.
+//
+// The tag and wire type are validated against the provided values and a DecoderSkipError error is
+// returned if they do not match. This check is skipped when using "fast" mode.
+//
+// io.ErrUnexpectedEOF is returned if the operation would advance past the end of the data.
+func (d *Decoder) Skip(tag int, wt WireType) ([]byte, error) {
+ if d.offset >= len(d.p) {
+ return nil, io.ErrUnexpectedEOF
+ }
+ sz := SizeOfTagKey(tag)
+ bof := d.offset - sz
+ // account for skipping the first field
+ if bof < 0 {
+ bof = 0
+ }
+ // validate that the field we're skipping matches the specified tag and wire type
+ // . skip validation in fast mode
+ if d.mode == DecoderModeSafe {
+ v, n, err := DecodeVarint(d.p[bof:])
+ if err != nil {
+ return nil, fmt.Errorf("invalid data at byte %d: %w", bof, err)
+ }
+ if n != sz {
+ return nil, fmt.Errorf("invalid data at byte %d: %w", bof, ErrInvalidVarintData)
+ }
+ thisTag, thisWireType := int(v>>3), WireType(v&0x7)
+ if thisTag != tag || thisWireType != wt {
+ return nil, &DecoderSkipError{
+ ExpectedTag: tag,
+ ExpectedWireType: wt,
+ ActualTag: thisTag,
+ ActualWireType: thisWireType,
+ }
+ }
+ }
+ skipped := 0
+ switch wt {
+ case WireTypeVarint:
+ _, n, err := DecodeVarint(d.p[d.offset:])
+ if err != nil {
+ return nil, fmt.Errorf("invalid data at byte %d: %w", d.offset, err)
+ }
+ skipped = n
+ case WireTypeFixed64:
+ skipped = 8
+ case WireTypeLengthDelimited:
+ l, n, err := DecodeVarint(d.p[d.offset:])
+ switch {
+ case err != nil:
+ return nil, fmt.Errorf("invalid data at byte %d: %w", d.offset, err)
+ case n == 0:
+ return nil, fmt.Errorf("invalid data at byte %d: %w", d.offset, ErrInvalidVarintData)
+ case l > maxFieldLen:
+ return nil, fmt.Errorf("invalid length (%d) for length-delimited field at byte %d: %w", l, d.offset, ErrLenOverflow)
+ default:
+ // length is good
+ }
+
+ skipped = n + int(l)
+
+ case WireTypeFixed32:
+ skipped = 4
+ default:
+ return nil, fmt.Errorf("unsupported wire type value %v at byte %d", wt, d.offset)
+ }
+ if d.offset+skipped > len(d.p) {
+ return nil, io.ErrUnexpectedEOF
+ }
+ d.offset += skipped
+ return d.p[bof:d.offset], nil
+}
+
+// DecodeVarint reads a base-128 [varint encoded] integer from p and returns the value and the number
+// of bytes that were consumed.
+//
+// [varint encoded]: https://developers.google.com/protocol-buffers/docs/encoding#varints
+func DecodeVarint(p []byte) (v uint64, n int, err error) {
+ if len(p) == 0 {
+ return 0, 0, ErrInvalidVarintData
+ }
+ // single-byte values don't need any processing
+ if p[0] < 0x80 {
+ return uint64(p[0]), 1, nil
+ }
+ // 2-9 byte values
+ if len(p) < 10 {
+ for shift := uint(0); shift < 64; shift += 7 {
+ if n >= len(p) {
+ return 0, 0, io.ErrUnexpectedEOF
+ }
+ b := uint64(p[n])
+ n++
+ v |= (b & 0x7f << shift)
+ if (b & 0x80) == 0 {
+ return v, n, nil
+ }
+ }
+ return 0, 0, ErrValueOverflow
+ }
+ // 10-byte values
+ // . we already know the first byte has the high-bit set, so grab it's value then walk bytes 2-10
+ v = uint64(p[0] & 0x7f)
+ for i, shift := 1, 7; i < 10; i, shift = i+1, shift+7 {
+ b := uint64(p[i])
+ v |= (b & 0x7f) << shift
+ if (b & 0x80) == 0 {
+ return v, i + 1, nil
+ }
+ }
+ return 0, 0, ErrValueOverflow
+}
+
+// DecodeZigZag32 reads a base-128 [zig zag encoded] 32-bit integer from p and returns the value and the
+// number of bytes that were consumed.
+//
+// [zig zag encoded]: https://developers.google.com/protocol-buffers/docs/encoding#signed-ints
+func DecodeZigZag32(p []byte) (v int32, n int, err error) {
+ var dv uint64
+ dv, n, err = DecodeVarint(p)
+ if err != nil {
+ return 0, 0, err
+ }
+ if n == 0 {
+ return 0, 0, ErrInvalidVarintData
+ }
+ dv = uint64((uint32(dv) >> 1) ^ uint32((int32(dv&1)<<31)>>31))
+ return int32(dv), n, nil
+}
+
+// DecodeZigZag64 reads a base-128 [zig zag encoded] 64-bit integer from p and returns the value and the
+// number of bytes that were consumed.
+//
+// [zig zag encoded]: https://developers.google.com/protocol-buffers/docs/encoding#signed-ints
+func DecodeZigZag64(p []byte) (v int64, n int, err error) {
+ var dv uint64
+ dv, n, err = DecodeVarint(p)
+ if err != nil {
+ return 0, 0, err
+ }
+ if n == 0 {
+ return 0, 0, ErrInvalidVarintData
+ }
+ dv = (dv >> 1) ^ uint64((int64(dv&1)<<63)>>63)
+ return int64(dv), n, nil
+}
+
+// DecodeFixed32 reads a Protobuf fixed32 or float (4 byte, little endian) value from p and returns the value
+// and the number of bytes consumed.
+func DecodeFixed32(p []byte) (v uint32, n int, err error) {
+ if len(p) < 4 {
+ return 0, 0, io.ErrUnexpectedEOF
+ }
+ // we only care about the first 4 bytes, so help the compiler eliminate bounds checks
+ p = p[:4]
+ v = uint32(p[0])
+ v |= uint32(p[1]) << 8
+ v |= uint32(p[2]) << 16
+ v |= uint32(p[3]) << 24
+ return v, 4, nil
+}
+
+// DecodeFixed64 reads a Protobuf fixed64 or double (8 byte, little endian) value from p and returns the value
+// and the number of bytes consumed.
+func DecodeFixed64(p []byte) (v uint64, n int, err error) {
+ if len(p) < 8 {
+ return 0, 0, io.ErrUnexpectedEOF
+ }
+ // we only care about the first 8 bytes, so help the compiler eliminate bounds checks
+ p = p[:8]
+ v = uint64(p[0])
+ v |= uint64(p[1]) << 8
+ v |= uint64(p[2]) << 16
+ v |= uint64(p[3]) << 24
+ v |= uint64(p[4]) << 32
+ v |= uint64(p[5]) << 40
+ v |= uint64(p[6]) << 48
+ v |= uint64(p[7]) << 56
+ return v, 8, nil
+}
+
+// DecoderSkipError defines an error returned by the decoder's Skip() method when the specified tag and
+// wire type do not match the data in the stream at the current decoder offset.
+type DecoderSkipError struct {
+ ExpectedTag int
+ ExpectedWireType WireType
+ ActualTag int
+ ActualWireType WireType
+}
+
+// Error satisfies the error interface
+func (e *DecoderSkipError) Error() string {
+ return fmt.Sprintf("unexpected tag/wire type (%d, %s), expected (%d, %s)", e.ActualTag, e.ActualWireType, e.ExpectedTag, e.ExpectedWireType)
+}
diff --git a/vendor/github.com/CrowdStrike/csproto/encoder.go b/vendor/github.com/CrowdStrike/csproto/encoder.go
new file mode 100644
index 00000000000..13b992c0473
--- /dev/null
+++ b/vendor/github.com/CrowdStrike/csproto/encoder.go
@@ -0,0 +1,443 @@
+package csproto
+
+import (
+ "encoding/binary"
+ "math"
+ "unsafe"
+)
+
+// Encoder implements a binary Protobuf Encoder by sequentially writing to a wrapped []byte.
+type Encoder struct {
+ p []byte
+ offset int
+}
+
+// NewEncoder initializes a new Protobuf encoder to write to the specified buffer, which must be
+// pre-allocated by the caller with sufficient space to hold the message(s) being written.
+func NewEncoder(p []byte) *Encoder {
+ return &Encoder{
+ p: p,
+ offset: 0,
+ }
+}
+
+// EncodeBool writes a varint-encoded boolean value to the buffer preceded by the varint-encoded tag key.
+func (e *Encoder) EncodeBool(tag int, v bool) {
+ e.offset += EncodeTag(e.p[e.offset:], tag, WireTypeVarint)
+ if v {
+ e.p[e.offset] = 1
+ } else {
+ e.p[e.offset] = 0
+ }
+ e.offset++
+}
+
+// EncodeString writes a length-delimited string value to the buffer preceded by the varint-encoded tag key.
+func (e *Encoder) EncodeString(tag int, s string) {
+ b := e.stringToBytes(s)
+ e.EncodeBytes(tag, b)
+}
+
+// EncodeBytes writes a length-delimited byte slice to the buffer preceded by the varint-encoded tag key.
+func (e *Encoder) EncodeBytes(tag int, v []byte) {
+ e.offset += EncodeTag(e.p[e.offset:], tag, WireTypeLengthDelimited)
+ e.offset += EncodeVarint(e.p[e.offset:], uint64(len(v)))
+ copy(e.p[e.offset:], v)
+ e.offset += len(v)
+}
+
+// EncodeUInt32 writes a varint-encoded 32-bit unsigned integer value to the buffer preceded by the varint-encoded tag key.
+func (e *Encoder) EncodeUInt32(tag int, v uint32) {
+ e.offset += EncodeTag(e.p[e.offset:], tag, WireTypeVarint)
+ e.offset += EncodeVarint(e.p[e.offset:], uint64(v))
+}
+
+// EncodeUInt64 writes a varint-encoded 64-bit unsigned integer value to the buffer preceded by the varint-encoded tag key.
+func (e *Encoder) EncodeUInt64(tag int, v uint64) {
+ e.offset += EncodeTag(e.p[e.offset:], tag, WireTypeVarint)
+ e.offset += EncodeVarint(e.p[e.offset:], v)
+}
+
+// EncodeInt32 writes a varint-encoded 32-bit signed integer value to the buffer preceded by the varint-encoded tag key.
+func (e *Encoder) EncodeInt32(tag int, v int32) {
+ e.offset += EncodeTag(e.p[e.offset:], tag, WireTypeVarint)
+ e.offset += EncodeVarint(e.p[e.offset:], uint64(v))
+}
+
+// EncodeInt64 writes a varint-encoded 64-bit signed integer value to the buffer preceded by the varint-encoded tag key.
+func (e *Encoder) EncodeInt64(tag int, v int64) {
+ e.offset += EncodeTag(e.p[e.offset:], tag, WireTypeVarint)
+ e.offset += EncodeVarint(e.p[e.offset:], uint64(v))
+}
+
+// EncodeSInt32 writes a zigzag-encoded 32-bit signed integer value to the buffer preceded by the varint-encoded tag key.
+func (e *Encoder) EncodeSInt32(tag int, v int32) {
+ e.offset += EncodeTag(e.p[e.offset:], tag, WireTypeVarint)
+ e.offset += EncodeZigZag32(e.p[e.offset:], v)
+}
+
+// EncodeSInt64 writes a zigzag-encoded 64-bit signed integer value to the buffer preceded by the varint-encoded tag key.
+func (e *Encoder) EncodeSInt64(tag int, v int64) {
+ e.offset += EncodeTag(e.p[e.offset:], tag, WireTypeVarint)
+ e.offset += EncodeZigZag64(e.p[e.offset:], v)
+}
+
+// EncodeFixed32 writes a 32-bit unsigned integer value to the buffer using 4 bytes in little endian format,
+// preceded by the varint-encoded tag key.
+func (e *Encoder) EncodeFixed32(tag int, v uint32) {
+ e.offset += EncodeTag(e.p[e.offset:], tag, WireTypeFixed32)
+ e.offset += EncodeFixed32(e.p[e.offset:], v)
+}
+
+// EncodeFixed64 writes a 64-bit unsigned integer value to the buffer using 8 bytes in little endian format,
+// preceded by the varint-encoded tag key.
+func (e *Encoder) EncodeFixed64(tag int, v uint64) {
+ e.offset += EncodeTag(e.p[e.offset:], tag, WireTypeFixed64)
+ e.offset += EncodeFixed64(e.p[e.offset:], v)
+}
+
+// EncodeFloat32 writes a 32-bit IEEE 754 floating point value to the buffer using 4 bytes in little endian format,
+// preceded by the varint-encoded tag key.
+func (e *Encoder) EncodeFloat32(tag int, v float32) {
+ e.offset += EncodeTag(e.p[e.offset:], tag, WireTypeFixed32)
+ binary.LittleEndian.PutUint32(e.p[e.offset:], math.Float32bits(v))
+ e.offset += 4
+}
+
+// EncodeFloat64 writes a 64-bit IEEE 754 floating point value to the buffer using 8 bytes in little endian format,
+// preceded by the varint-encoded tag key.
+func (e *Encoder) EncodeFloat64(tag int, v float64) {
+ e.offset += EncodeTag(e.p[e.offset:], tag, WireTypeFixed64)
+ binary.LittleEndian.PutUint64(e.p[e.offset:], math.Float64bits(v))
+ e.offset += 8
+}
+
+// EncodePackedBool writes a list of booleans to the buffer using packed encoding, preceded by
+// the varint-encoded tag key.
+func (e *Encoder) EncodePackedBool(tag int, vs []bool) {
+ if len(vs) == 0 {
+ return
+ }
+ e.offset += EncodeTag(e.p[e.offset:], tag, WireTypeLengthDelimited)
+ e.offset += EncodeVarint(e.p[e.offset:], uint64(len(vs)))
+ for _, v := range vs {
+ if v {
+ e.p[e.offset] = 1
+ } else {
+ e.p[e.offset] = 0
+ }
+ e.offset++
+ }
+}
+
+// EncodePackedInt32 writes a list of 32-bit integers to the buffer using packed encoding, preceded by
+// the varint-encoded tag key.
+//
+// This operation is O(n^2) because we have to traverse the list of values to calculate the total
+// encoded size and write that size *before* the actual encoded values.
+func (e *Encoder) EncodePackedInt32(tag int, vs []int32) {
+ if len(vs) == 0 {
+ return
+ }
+ e.offset += EncodeTag(e.p[e.offset:], tag, WireTypeLengthDelimited)
+ sz := 0
+ for _, v := range vs {
+ sz += SizeOfVarint(uint64(v))
+ }
+ e.offset += EncodeVarint(e.p[e.offset:], uint64(sz))
+ for _, v := range vs {
+ e.offset += EncodeVarint(e.p[e.offset:], uint64(v))
+ }
+}
+
+// EncodePackedInt64 writes a list of 64-bit integers to the buffer using packed encoding, preceded by
+// the varint-encoded tag key.
+//
+// This operation is O(n^2) because we have to traverse the list of values to calculate the total
+// encoded size and write that size *before* the actual encoded values.
+func (e *Encoder) EncodePackedInt64(tag int, vs []int64) {
+ if len(vs) == 0 {
+ return
+ }
+ e.offset += EncodeTag(e.p[e.offset:], tag, WireTypeLengthDelimited)
+ sz := 0
+ for _, v := range vs {
+ sz += SizeOfVarint(uint64(v))
+ }
+ e.offset += EncodeVarint(e.p[e.offset:], uint64(sz))
+ for _, v := range vs {
+ e.offset += EncodeVarint(e.p[e.offset:], uint64(v))
+ }
+}
+
+// EncodePackedUInt32 writes a list of 32-bit unsigned integers to the buffer using packed encoding,
+// preceded by the varint-encoded tag key.
+//
+// This operation is O(n^2) because we have to traverse the list of values to calculate the total
+// encoded size and write that size *before* the actual encoded values.
+func (e *Encoder) EncodePackedUInt32(tag int, vs []uint32) {
+ if len(vs) == 0 {
+ return
+ }
+ e.offset += EncodeTag(e.p[e.offset:], tag, WireTypeLengthDelimited)
+ sz := 0
+ for _, v := range vs {
+ sz += SizeOfVarint(uint64(v))
+ }
+ e.offset += EncodeVarint(e.p[e.offset:], uint64(sz))
+ for _, v := range vs {
+ e.offset += EncodeVarint(e.p[e.offset:], uint64(v))
+ }
+}
+
+// EncodePackedUInt64 writes a list of 64-bit unsigned integers to the buffer using packed encoding,
+// preceded by the varint-encoded tag key.
+//
+// This operation is O(n^2) because we have to traverse the list of values to calculate the total
+// encoded size and write that size *before* the actual encoded values.
+func (e *Encoder) EncodePackedUInt64(tag int, vs []uint64) {
+ if len(vs) == 0 {
+ return
+ }
+ e.offset += EncodeTag(e.p[e.offset:], tag, WireTypeLengthDelimited)
+ sz := 0
+ for _, v := range vs {
+ sz += SizeOfVarint(v)
+ }
+ e.offset += EncodeVarint(e.p[e.offset:], uint64(sz))
+ for _, v := range vs {
+ e.offset += EncodeVarint(e.p[e.offset:], v)
+ }
+}
+
+// EncodePackedSInt32 writes a list of 32-bit signed integers to the buffer using packed encoding,
+// preceded by the varint-encoded tag key.
+//
+// This operation is O(n^2) because we have to traverse the list of values to calculate the total
+// encoded size and write that size *before* the actual encoded values.
+func (e *Encoder) EncodePackedSInt32(tag int, vs []int32) {
+ if len(vs) == 0 {
+ return
+ }
+ e.offset += EncodeTag(e.p[e.offset:], tag, WireTypeLengthDelimited)
+ sz := 0
+ for _, v := range vs {
+ sz += SizeOfZigZag(uint64(v))
+ }
+ e.offset += EncodeVarint(e.p[e.offset:], uint64(sz))
+ for _, v := range vs {
+ e.offset += EncodeZigZag32(e.p[e.offset:], v)
+ }
+}
+
+// EncodePackedSInt64 writes a list of 64-bit signed integers to the buffer using packed encoding,
+// preceded by the varint-encoded tag key.
+//
+// This operation is O(n^2) because we have to traverse the list of values to calculate the total
+// encoded size and write that size *before* the actual encoded values.
+func (e *Encoder) EncodePackedSInt64(tag int, vs []int64) {
+ if len(vs) == 0 {
+ return
+ }
+ e.offset += EncodeTag(e.p[e.offset:], tag, WireTypeLengthDelimited)
+ sz := 0
+ for _, v := range vs {
+ sz += SizeOfZigZag(uint64(v))
+ }
+ e.offset += EncodeVarint(e.p[e.offset:], uint64(sz))
+ for _, v := range vs {
+ e.offset += EncodeZigZag64(e.p[e.offset:], v)
+ }
+}
+
+// EncodePackedFixed32 writes a list of 32-bit fixed-width unsigned integers to the buffer using packed
+// encoding, preceded by the varint-encoded tag key.
+func (e *Encoder) EncodePackedFixed32(tag int, vs []uint32) {
+ if len(vs) == 0 {
+ return
+ }
+ e.offset += EncodeTag(e.p[e.offset:], tag, WireTypeLengthDelimited)
+ e.offset += EncodeVarint(e.p[e.offset:], uint64(len(vs)*4))
+ for _, v := range vs {
+ binary.LittleEndian.PutUint32(e.p[e.offset:], v)
+ e.offset += 4
+ }
+}
+
+// EncodePackedFixed64 writes a list of 64-bit fixed-width unsigned integers to the buffer using packed
+// encoding, preceded by the varint-encoded tag key.
+func (e *Encoder) EncodePackedFixed64(tag int, vs []uint64) {
+ if len(vs) == 0 {
+ return
+ }
+ e.offset += EncodeTag(e.p[e.offset:], tag, WireTypeLengthDelimited)
+ e.offset += EncodeVarint(e.p[e.offset:], uint64(len(vs)*8))
+ for _, v := range vs {
+ binary.LittleEndian.PutUint64(e.p[e.offset:], v)
+ e.offset += 8
+ }
+}
+
+// EncodePackedSFixed32 writes a list of 32-bit fixed-width signed integers to the buffer using packed
+// encoding, preceded by the varint-encoded tag key.
+func (e *Encoder) EncodePackedSFixed32(tag int, vs []int32) {
+ if len(vs) == 0 {
+ return
+ }
+ e.offset += EncodeTag(e.p[e.offset:], tag, WireTypeLengthDelimited)
+ e.offset += EncodeVarint(e.p[e.offset:], uint64(len(vs)*4))
+ for _, v := range vs {
+ binary.LittleEndian.PutUint32(e.p[e.offset:], uint32(v))
+ e.offset += 4
+ }
+}
+
+// EncodePackedSFixed64 writes a list of 64-bit fixed-width signed integers to the buffer using packed
+// encoding, preceded by the varint-encoded tag key.
+func (e *Encoder) EncodePackedSFixed64(tag int, vs []int64) {
+ if len(vs) == 0 {
+ return
+ }
+ e.offset += EncodeTag(e.p[e.offset:], tag, WireTypeLengthDelimited)
+ e.offset += EncodeVarint(e.p[e.offset:], uint64(len(vs)*8))
+ for _, v := range vs {
+ binary.LittleEndian.PutUint64(e.p[e.offset:], uint64(v))
+ e.offset += 8
+ }
+}
+
+// EncodePackedFloat32 writes a list of 32-bit floating point numbers to the buffer using packed
+// encoding, preceded by the varint-encoded tag key.
+func (e *Encoder) EncodePackedFloat32(tag int, vs []float32) {
+ if len(vs) == 0 {
+ return
+ }
+ e.offset += EncodeTag(e.p[e.offset:], tag, WireTypeLengthDelimited)
+ e.offset += EncodeVarint(e.p[e.offset:], uint64(len(vs)*4))
+ for _, v := range vs {
+ binary.LittleEndian.PutUint32(e.p[e.offset:], math.Float32bits(v))
+ e.offset += 4
+ }
+}
+
+// EncodePackedFloat64 writes a list of 64-bit floating point numbers to the buffer using packed
+// encoding, preceded by the varint-encoded tag key.
+func (e *Encoder) EncodePackedFloat64(tag int, vs []float64) {
+ if len(vs) == 0 {
+ return
+ }
+ e.offset += EncodeTag(e.p[e.offset:], tag, WireTypeLengthDelimited)
+ e.offset += EncodeVarint(e.p[e.offset:], uint64(len(vs)*8))
+ for _, v := range vs {
+ binary.LittleEndian.PutUint64(e.p[e.offset:], math.Float64bits(v))
+ e.offset += 8
+ }
+}
+
+// EncodeNested writes a nested message to the buffer preceded by the varint-encoded tag key.
+func (e *Encoder) EncodeNested(tag int, m interface{}) error {
+ sz := Size(m)
+ e.offset += EncodeTag(e.p[e.offset:], tag, WireTypeLengthDelimited)
+ e.offset += EncodeVarint(e.p[e.offset:], uint64(sz))
+ switch tv := m.(type) {
+ case MarshalerTo:
+ if err := tv.MarshalTo(e.p[e.offset:]); err != nil {
+ return err
+ }
+ e.offset += sz
+ return nil
+ case Marshaler:
+ buf, err := tv.Marshal()
+ if err != nil {
+ return err
+ }
+ copy(e.p[e.offset:], buf)
+ e.offset += sz
+ return nil
+ default:
+ buf, err := Marshal(tv)
+ if err != nil {
+ return err
+ }
+ copy(e.p[e.offset:], buf)
+ e.offset += sz
+ return nil
+ }
+}
+
+// EncodeRaw writes the raw bytes of d into the buffer at the current offset
+func (e *Encoder) EncodeRaw(d []byte) {
+ if l := len(d); l > 0 {
+ copy(e.p[e.offset:], d)
+ e.offset += l
+ }
+}
+
+// EncodeMapEntryHeader writes a map entry header into the buffer, which consists of the specified
+// tag with a wire type of WireTypeLengthDelimited followed by the varint encoded entry size.
+func (e *Encoder) EncodeMapEntryHeader(tag int, size int) {
+ e.offset += EncodeTag(e.p[e.offset:], tag, WireTypeLengthDelimited)
+ e.offset += EncodeVarint(e.p[e.offset:], uint64(size))
+}
+
+// stringToBytes is an optimized convert from a string to a []byte using unsafe.Pointer
+func (e *Encoder) stringToBytes(s string) []byte {
+ return *(*[]byte)(unsafe.Pointer(
+ &struct {
+ string
+ Cap int
+ }{s, len(s)},
+ ))
+}
+
+// EncodeTag combines tag and wireType then encodes the result into dest using the Protobuf
+// varint format and returns the number of bytes written.
+func EncodeTag(dest []byte, tag int, wireType WireType) int {
+ // per the Protobuf spec, the field tag is: (tag << 3) | wireType
+ // ex:
+ // field #1, wire type varint (0) -> 8 (1000 in binary, 0x8 in hex)
+ // field #13, wire type fixed32 (5) -> 109 (1101101 in binary, 0x6d in hex)
+ k := (uint64(tag) << 3) | uint64(wireType)
+ return EncodeVarint(dest, k)
+}
+
+// EncodeVarint encodes v into dest using the Protobuf base-128 varint format and returns the number
+// of bytes written
+func EncodeVarint(dest []byte, v uint64) int {
+ n := 0
+ for v >= 1<<7 {
+ dest[n] = uint8(v&0x7f | 0x80)
+ v >>= 7
+ n++
+ }
+ dest[n] = uint8(v)
+ return n + 1
+}
+
+// EncodeFixed32 encodes v into dest using the Protobuf fixed 32-bit encoding, which is just the 4 bytes
+// of the value in little-endian format, and returns the number of bytes written
+func EncodeFixed32(dest []byte, v uint32) int {
+ binary.LittleEndian.PutUint32(dest, v)
+ return 4
+}
+
+// EncodeFixed64 encodes v into dest using the Protobuf fixed 64-bit encoding, which is just the 8 bytes
+// of the value in little-endian format, and returns the number of bytes written
+func EncodeFixed64(dest []byte, v uint64) int {
+ binary.LittleEndian.PutUint64(dest, v)
+ return 8
+}
+
+// EncodeZigZag32 encodes v into dest using the Protobuf zig/zag encoding for more efficient encoding
+// of negative numbers, and returns the number of bytes written.
+func EncodeZigZag32(dest []byte, v int32) int {
+ zz := uint64((uint32(v) << 1) ^ uint32((v >> 31)))
+ return EncodeVarint(dest, zz)
+}
+
+// EncodeZigZag64 encodes v into dest using the Protobuf zig/zag encoding for more efficient encoding
+// of negative numbers, and returns the number of bytes written.
+func EncodeZigZag64(dest []byte, v int64) int {
+ zz := uint64(v<<1) ^ uint64((v >> 63))
+ return EncodeVarint(dest, zz)
+}
diff --git a/vendor/github.com/CrowdStrike/csproto/equal.go b/vendor/github.com/CrowdStrike/csproto/equal.go
new file mode 100644
index 00000000000..7f69b4e8217
--- /dev/null
+++ b/vendor/github.com/CrowdStrike/csproto/equal.go
@@ -0,0 +1,29 @@
+package csproto
+
+import (
+ gogo "github.com/gogo/protobuf/proto"
+ google "github.com/golang/protobuf/proto" //nolint: staticcheck // we're using this deprecated package intentionally
+ googlev2 "google.golang.org/protobuf/proto"
+)
+
+// Equal returns true iff m1 and m2 are equal.
+//
+// If m1 and m2 are not the same "type" (generated for the same runtime) then they are not equal. Otherwise,
+// we delegate comparison to the appropriate underlying Protobuf API based on the concrete type of the
+// messages
+func Equal(m1, m2 interface{}) bool {
+ t1, t2 := MsgType(m1), MsgType(m2)
+ if t1 != t2 {
+ return false
+ }
+ switch t1 {
+ case MessageTypeGoogleV1:
+ return google.Equal(m1.(google.Message), m2.(google.Message))
+ case MessageTypeGoogle:
+ return googlev2.Equal(m1.(googlev2.Message), m2.(googlev2.Message))
+ case MessageTypeGogo:
+ return gogo.Equal(m1.(gogo.Message), m2.(gogo.Message))
+ default:
+ return false
+ }
+}
diff --git a/vendor/github.com/CrowdStrike/csproto/extensions.go b/vendor/github.com/CrowdStrike/csproto/extensions.go
new file mode 100644
index 00000000000..73bc38a0c66
--- /dev/null
+++ b/vendor/github.com/CrowdStrike/csproto/extensions.go
@@ -0,0 +1,208 @@
+package csproto
+
+import (
+ "fmt"
+
+ gogo "github.com/gogo/protobuf/proto"
+ google "github.com/golang/protobuf/proto" //nolint: staticcheck // we're using this deprecated package intentionally
+ googlev2 "google.golang.org/protobuf/proto"
+ "google.golang.org/protobuf/reflect/protoreflect"
+)
+
+// RangeExtensions iterates through all extension descriptors of a given proto message, calling fn
+// on each iteration. It returns immediately on any error encountered.
+// WARNING: RangeExtensions ranges over all registered extensions and therefore has a very high performance
+// cost. Please consider using individual calls to GetExtension, if possible.
+func RangeExtensions(msg interface{}, fn func(value interface{}, name string, field int32) error) error {
+ msgType := MsgType(msg)
+
+ switch msgType {
+ case MessageTypeGogo:
+ exts, err := gogo.ExtensionDescs(msg.(gogo.Message))
+ if err != nil {
+ return err
+ }
+ for _, ext := range exts {
+ if err = fn(ext, ext.Name, ext.Field); err != nil {
+ return err
+ }
+ }
+ return nil
+ case MessageTypeGoogleV1:
+ exts, err := google.ExtensionDescs(msg.(google.Message))
+ if err != nil {
+ return err
+ }
+ for _, ext := range exts {
+ if err = fn(ext,
+ string(ext.TypeDescriptor().FullName()),
+ int32(ext.TypeDescriptor().Descriptor().Number()),
+ ); err != nil {
+ return err
+ }
+ }
+ return nil
+ case MessageTypeGoogle:
+ var err error
+ googlev2.RangeExtensions(msg.(googlev2.Message), func(t protoreflect.ExtensionType, v interface{}) bool {
+ err = fn(v,
+ string(t.TypeDescriptor().FullName()),
+ int32(t.TypeDescriptor().Descriptor().Number()),
+ )
+ return err == nil
+ })
+ return err
+ case MessageTypeUnknown:
+ return fmt.Errorf("unsupported message type: %T", msg)
+ }
+ return nil
+}
+
+// HasExtension returns true if msg contains the specified proto2 extension field, delegating to the
+// appropriate underlying Protobuf API based on the concrete type of msg.
+func HasExtension(msg interface{}, ext interface{}) bool {
+ switch MsgType(msg) {
+ case MessageTypeGoogleV1:
+ ed, ok := ext.(*google.ExtensionDesc)
+ if !ok {
+ return false
+ }
+ return google.HasExtension(msg.(google.Message), ed)
+ case MessageTypeGoogle:
+ et, ok := ext.(protoreflect.ExtensionType)
+ if !ok {
+ return false
+ }
+ return googlev2.HasExtension(msg.(googlev2.Message), et)
+ case MessageTypeGogo:
+ ed, ok := ext.(*gogo.ExtensionDesc)
+ if !ok {
+ return false
+ }
+ return gogo.HasExtension(msg.(gogo.Message), ed)
+ default:
+ return false
+ }
+}
+
+// ClearExtension removes a proto2 extension field from msg, if it exists, delegating to the appropriate
+// underlying Protobuf API based on the concrete type of msg.
+//
+// This function panics if the provded parameters are invalid, rather than returning an error, to be
+// consistent with the signature of the ClearExtension() functions in the underlying Protobuf runtimes.
+func ClearExtension(msg interface{}, ext interface{}) {
+ switch MsgType(msg) {
+ case MessageTypeGoogleV1:
+ if ed, ok := ext.(*google.ExtensionDesc); ok {
+ google.ClearExtension(msg.(google.Message), ed)
+ return
+ }
+ case MessageTypeGoogle:
+ if et, ok := ext.(protoreflect.ExtensionType); ok {
+ googlev2.ClearExtension(msg.(googlev2.Message), et)
+ return
+ }
+ case MessageTypeGogo:
+ if ed, ok := ext.(*gogo.ExtensionDesc); ok {
+ gogo.ClearExtension(msg.(gogo.Message), ed)
+ return
+ }
+ default:
+ panic(fmt.Sprintf("unsupported message type %T", msg))
+ }
+ // mismatched message and extension defintion types
+ // - ex: a Google V2 message and a Gogo extension definition
+ panic(fmt.Sprintf("invalid proto2 extension definition type %T for a message of type %T", ext, msg))
+}
+
+// GetExtension returns a proto2 extension field from msg, delegating to the appropriate underlying
+// Protobuf API based on the concrete type of msg.
+func GetExtension(msg interface{}, ext interface{}) (interface{}, error) {
+ switch MsgType(msg) {
+ case MessageTypeGoogleV1:
+ ed, ok := ext.(*google.ExtensionDesc)
+ if !ok {
+ return nil, fmt.Errorf("invalid extension description type %T", ext)
+ }
+ return google.GetExtension(msg.(google.Message), ed)
+ case MessageTypeGoogle:
+ et, ok := ext.(protoreflect.ExtensionType)
+ if !ok {
+ return nil, fmt.Errorf("invalid extension type %T", ext)
+ }
+ return googlev2.GetExtension(msg.(googlev2.Message), et), nil
+ case MessageTypeGogo:
+ ed, ok := ext.(*gogo.ExtensionDesc)
+ if !ok {
+ return nil, fmt.Errorf("invalid extension description type %T", ext)
+ }
+ return gogo.GetExtension(msg.(gogo.Message), ed)
+ default:
+ return nil, fmt.Errorf("unsupported message type %T", msg)
+ }
+}
+
+// SetExtension sets a proto2 extension field in msg to the provided value, delegating to the
+// appropriate underlying Protobuf API based on the concrete type of msg.
+func SetExtension(msg interface{}, ext interface{}, val interface{}) error {
+ switch MsgType(msg) {
+ case MessageTypeGoogleV1:
+ ed, ok := ext.(*google.ExtensionDesc)
+ if !ok {
+ return fmt.Errorf("invalid extension description type %T", ext)
+ }
+ return google.SetExtension(msg.(google.Message), ed, val)
+ case MessageTypeGoogle:
+ et, ok := ext.(protoreflect.ExtensionType)
+ if !ok {
+ return fmt.Errorf("invalid extension type %T", ext)
+ }
+ googlev2.SetExtension(msg.(googlev2.Message), et, val)
+ return nil
+ case MessageTypeGogo:
+ ed, ok := ext.(*gogo.ExtensionDesc)
+ if !ok {
+ return fmt.Errorf("invalid extension description type %T", ext)
+ }
+ return gogo.SetExtension(msg.(gogo.Message), ed, val)
+ default:
+ return fmt.Errorf("unsupported message type %T", ext)
+ }
+}
+
+// ClearAllExtensions removes all proto2 extension fields from msg.
+//
+// This operation can be very inefficient, especially for Google V2 messages, so it is generally better
+// to explicitly clear individual extension fields.
+func ClearAllExtensions(msg interface{}) {
+ switch MsgType(msg) {
+ case MessageTypeGoogleV1:
+ google.ClearAllExtensions(msg.(google.Message))
+ case MessageTypeGoogle:
+ // no ClearAllExtensions() API in Google V2 so we have to brute force it :(
+ m := msg.(googlev2.Message)
+ googlev2.RangeExtensions(m, func(xt protoreflect.ExtensionType, _ interface{}) bool {
+ googlev2.ClearExtension(m, xt)
+ return true
+ })
+ case MessageTypeGogo:
+ gogo.ClearAllExtensions(msg.(gogo.Message))
+ default:
+ // no-op
+ }
+}
+
+// ExtensionFieldNumber returns the integer field tag associated with the specified proto2 extension
+// descriptor. If ext is not one of the three supported types, this function returns 0 and an error.
+func ExtensionFieldNumber(ext any) (int, error) {
+ switch tv := ext.(type) {
+ case *gogo.ExtensionDesc:
+ return int(tv.Field), nil
+ case *google.ExtensionDesc:
+ return int(tv.TypeDescriptor().Number()), nil
+ case protoreflect.ExtensionType:
+ return int(tv.TypeDescriptor().Number()), nil
+ default:
+ return 0, fmt.Errorf("unsupported proto2 extension descriptor type %T", ext)
+ }
+}
diff --git a/vendor/github.com/CrowdStrike/csproto/grpc_codec.go b/vendor/github.com/CrowdStrike/csproto/grpc_codec.go
new file mode 100644
index 00000000000..1517518556d
--- /dev/null
+++ b/vendor/github.com/CrowdStrike/csproto/grpc_codec.go
@@ -0,0 +1,20 @@
+package csproto
+
+// GrpcCodec implements gRPC encoding.Codec.
+// See: https://pkg.go.dev/google.golang.org/grpc/encoding#Codec
+type GrpcCodec struct{}
+
+// Marshal returns the wire format of v.
+func (GrpcCodec) Marshal(v interface{}) ([]byte, error) {
+ return Marshal(v)
+}
+
+// Unmarshal parses the wire format into v.
+func (GrpcCodec) Unmarshal(data []byte, v interface{}) error {
+ return Unmarshal(data, v)
+}
+
+// Name returns the name of the Codec implementation.
+func (GrpcCodec) Name() string {
+ return "proto"
+}
diff --git a/vendor/github.com/CrowdStrike/csproto/helpers.go b/vendor/github.com/CrowdStrike/csproto/helpers.go
new file mode 100644
index 00000000000..254f59e5dd2
--- /dev/null
+++ b/vendor/github.com/CrowdStrike/csproto/helpers.go
@@ -0,0 +1,47 @@
+package csproto
+
+// Bool returns a pointer to v (for use when assigning pointer fields on Protobuf message types)
+func Bool(v bool) *bool {
+ return &v
+}
+
+// Int returns a pointer to v as an int32 value (for use when assigning pointer fields on Protobuf message types)
+func Int(v int) *int32 {
+ p := int32(v)
+ return &p
+}
+
+// Int32 returns a pointer to v (for use when assigning pointer fields on Protobuf message types)
+func Int32(v int32) *int32 {
+ return &v
+}
+
+// Int64 returns a pointer to v (for use when assigning pointer fields on Protobuf message types)
+func Int64(v int64) *int64 {
+ return &v
+}
+
+// Uint32 returns a pointer to v (for use when assigning pointer fields on Protobuf message types)
+func Uint32(v uint32) *uint32 {
+ return &v
+}
+
+// Uint64 returns a pointer to v (for use when assigning pointer fields on Protobuf message types)
+func Uint64(v uint64) *uint64 {
+ return &v
+}
+
+// Float32 returns a pointer to v (for use when assigning pointer fields on Protobuf message types)
+func Float32(v float32) *float32 {
+ return &v
+}
+
+// Float64 returns a pointer to v (for use when assigning pointer fields on Protobuf message types)
+func Float64(v float64) *float64 {
+ return &v
+}
+
+// String returns a pointer to v (for use when assigning pointer fields on Protobuf message types)
+func String(v string) *string {
+ return &v
+}
diff --git a/vendor/github.com/CrowdStrike/csproto/helpers_generic.go b/vendor/github.com/CrowdStrike/csproto/helpers_generic.go
new file mode 100644
index 00000000000..21a38547c10
--- /dev/null
+++ b/vendor/github.com/CrowdStrike/csproto/helpers_generic.go
@@ -0,0 +1,27 @@
+//go:build go1.18
+// +build go1.18
+
+package csproto
+
+// NativeTypes defines a generic constraint for the native Go types that need to be converted to
+// pointers when storing values in generated Protobuf message structs.
+//
+// The int32 constraint is "expanded" to ~int32 to support generated Protobuf enum types, which always
+// have an underlying type of int32. While this technically means we will accept types that are not,
+// in fact, Protobuf enums, the utility of making things work for enums outweighs the potential downside
+// of developers intentionally using [PointerTo] to take a pointer to a custom type that happens to
+// be based on int32.
+//
+// Unsized integers (type int) also need to be converted to a pointer, but Protobuf doesn't support
+// unsized integers. Use the [csproto.Int] function instead.
+type NativeTypes interface {
+ bool | ~int32 | int64 | uint32 | uint64 | float32 | float64 | string
+}
+
+// PointerTo makes a copy of v and returns a pointer to that copy.
+//
+// The [NativeTypes] type constraint restricts this function to only types that are valid for Protobuf
+// scalar field values (boolean, integer, float, string, and Protobuf enum).
+func PointerTo[T NativeTypes](v T) *T {
+ return &v
+}
diff --git a/vendor/github.com/CrowdStrike/csproto/json.go b/vendor/github.com/CrowdStrike/csproto/json.go
new file mode 100644
index 00000000000..5e668fdd75d
--- /dev/null
+++ b/vendor/github.com/CrowdStrike/csproto/json.go
@@ -0,0 +1,243 @@
+package csproto
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "reflect"
+
+ gogojson "github.com/gogo/protobuf/jsonpb"
+ gogo "github.com/gogo/protobuf/proto"
+ "github.com/golang/protobuf/jsonpb" //nolint: staticcheck // using this deprecated package intentionally as this is a compatibility shim
+ protov1 "github.com/golang/protobuf/proto" //nolint: staticcheck // using this deprecated package intentionally as this is a compatibility shim
+ "google.golang.org/protobuf/encoding/protojson"
+ protov2 "google.golang.org/protobuf/proto"
+)
+
+// JSONMarshaler returns an implementation of the json.Marshaler interface that formats msg to JSON
+// using the specified options.
+func JSONMarshaler(msg interface{}, opts ...JSONOption) json.Marshaler {
+ m := jsonMarshaler{
+ msg: msg,
+ }
+ for _, o := range opts {
+ o(&m.opts)
+ }
+ return &m
+}
+
+// jsonMarshaler wraps a Protobuf message and satisfies the json.Marshaler interface
+type jsonMarshaler struct {
+ msg interface{}
+ opts jsonOptions
+}
+
+// compile-time interface check
+var _ json.Marshaler = (*jsonMarshaler)(nil)
+
+// MarshalJSON satisfies the json.Marshaler interface
+//
+// If the wrapped message is nil, or a non-nil interface value holding nil, this method returns nil.
+// If the message satisfies the json.Marshaler interface we delegate to it directly. Otherwise,
+// this method calls the appropriate underlying runtime (Gogo vs Google V1 vs Google V2) based on
+// the message's actual type.
+func (m *jsonMarshaler) MarshalJSON() ([]byte, error) {
+ value := reflect.ValueOf(m.msg)
+ if m.msg == nil || value.Kind() == reflect.Ptr && value.IsNil() {
+ return nil, nil
+ }
+
+ // call the message's implementation directly, if present
+ if jm, ok := m.msg.(json.Marshaler); ok {
+ return jm.MarshalJSON()
+ }
+
+ var buf bytes.Buffer
+
+ // Google V2 message?
+ if msg, isV2 := m.msg.(protov2.Message); isV2 {
+ mo := protojson.MarshalOptions{
+ Indent: m.opts.indent,
+ UseEnumNumbers: m.opts.useEnumNumbers,
+ EmitUnpopulated: m.opts.emitZeroValues,
+ }
+ b, err := mo.Marshal(msg)
+ if err != nil {
+ return nil, fmt.Errorf("unable to marshal message to JSON: %w", err)
+ }
+ return b, nil
+ }
+
+ // Google V1 message?
+ if msg, isV1 := m.msg.(protov1.Message); isV1 {
+ jm := jsonpb.Marshaler{
+ Indent: m.opts.indent,
+ EnumsAsInts: m.opts.useEnumNumbers,
+ EmitDefaults: m.opts.emitZeroValues,
+ }
+ if err := jm.Marshal(&buf, msg); err != nil {
+ return nil, fmt.Errorf("unable to marshal message to JSON: %w", err)
+ }
+ return buf.Bytes(), nil
+ }
+
+ // Gogo message?
+ if msg, isGogo := m.msg.(gogo.Message); isGogo {
+ jm := gogojson.Marshaler{
+ Indent: m.opts.indent,
+ EnumsAsInts: m.opts.useEnumNumbers,
+ EmitDefaults: m.opts.emitZeroValues,
+ }
+ if err := jm.Marshal(&buf, msg); err != nil {
+ return nil, fmt.Errorf("unable to marshal message to JSON: %w", err)
+ }
+ return buf.Bytes(), nil
+ }
+
+ return nil, fmt.Errorf("unsupported message type %T", m.msg)
+}
+
+// JSONUnmarshaler returns an implementation of the json.Unmarshaler interface that unmarshals a
+// JSON data stream into msg using the specified options.
+func JSONUnmarshaler(msg interface{}, opts ...JSONOption) json.Unmarshaler {
+ m := jsonUnmarshaler{
+ msg: msg,
+ }
+ for _, o := range opts {
+ o(&m.opts)
+ }
+ return &m
+
+}
+
+// jsonUnmarshaler wraps a Protobuf message and satisfies the json.Unmarshaler interface
+type jsonUnmarshaler struct {
+ msg interface{}
+ opts jsonOptions
+}
+
+// UnmarshalJSON satisfies the json.Unmarshaler interface.
+//
+// If the wrapped message is nil, or a non-nil interface value holding nil, this method returns an error.
+// If the message satisfies the json.Marshaler interface we delegate to it directly. Otherwise,
+// this method calls the appropriate underlying runtime (Gogo vs Google V1 vs Google V2) based on
+// the message's actual type.
+func (m *jsonUnmarshaler) UnmarshalJSON(data []byte) error {
+ if m.msg == nil || reflect.ValueOf(m.msg).IsNil() {
+ return fmt.Errorf("cannot unmarshal into nil")
+ }
+
+ // call the message's implementation directly, if present
+ if jm, ok := m.msg.(json.Unmarshaler); ok {
+ return jm.UnmarshalJSON(data)
+ }
+
+ // Google V2 message?
+ if msg, isV2 := m.msg.(protov2.Message); isV2 {
+ mo := protojson.UnmarshalOptions{
+ AllowPartial: m.opts.allowPartial,
+ DiscardUnknown: m.opts.allowUnknownFields,
+ }
+ if err := mo.Unmarshal(data, msg); err != nil {
+ return fmt.Errorf("unable to unmarshal JSON data: %w", err)
+ }
+ return nil
+ }
+
+ // Google V1 message?
+ if msg, isV1 := m.msg.(protov1.Message); isV1 {
+ jm := jsonpb.Unmarshaler{
+ AllowUnknownFields: m.opts.allowUnknownFields,
+ }
+ if err := jm.Unmarshal(bytes.NewReader(data), msg); err != nil {
+ return fmt.Errorf("unable to unmarshal JSON data: %w", err)
+ }
+ return nil
+ }
+
+ // Gogo message?
+ if msg, isGogo := m.msg.(gogo.Message); isGogo {
+ jm := gogojson.Unmarshaler{
+ AllowUnknownFields: m.opts.allowUnknownFields,
+ }
+ if err := jm.Unmarshal(bytes.NewBuffer(data), msg); err != nil {
+ return fmt.Errorf("unable to unmarshal JSON data: %w", err)
+ }
+ return nil
+ }
+
+ return fmt.Errorf("unsupported message type %T", m.msg)
+}
+
+// JSONOption defines a function that sets a specific JSON formatting option
+type JSONOption func(*jsonOptions)
+
+// JSONIndent returns a JSONOption that configures the JSON indentation.
+//
+// Passing an empty string disables indentation. If not empty, indent must consist of only spaces or
+// tab characters.
+func JSONIndent(indent string) JSONOption {
+ return func(opts *jsonOptions) {
+ opts.indent = indent
+ }
+}
+
+// JSONUseEnumNumbers returns a JSON option that enables or disables outputting integer values rather
+// than the enum names for enum fields.
+func JSONUseEnumNumbers(useNumbers bool) JSONOption {
+ return func(opts *jsonOptions) {
+ opts.useEnumNumbers = useNumbers
+ }
+}
+
+// JSONIncludeZeroValues returns a JSON option that enables or disables including zero-valued fields
+// in the JSON output.
+func JSONIncludeZeroValues(emitZeroValues bool) JSONOption {
+ return func(opts *jsonOptions) {
+ opts.emitZeroValues = emitZeroValues
+ }
+}
+
+// JSONAllowUnknownFields returns a JSON option that configures JSON unmarshaling to skip unknown
+// fields rather than return an error
+func JSONAllowUnknownFields(allow bool) JSONOption {
+ return func(opts *jsonOptions) {
+ opts.allowUnknownFields = allow
+ }
+}
+
+// JSONAllowPartialMessages returns a JSON option that configured JSON unmarshaling to not return an
+// error if unmarshaling data results in required fields not being set on the message.
+//
+// Note: only applies to Google V2 (google.golang.org/protobuf) messages that are using proto2 syntax.
+func JSONAllowPartialMessages(allow bool) JSONOption {
+ return func(opts *jsonOptions) {
+ opts.allowPartial = allow
+ }
+}
+
+// jsonOptions defines the JSON formatting options
+//
+// These options are a subset of those available by each of the three supported runtimes. The supported
+// options consist of the things that are provided by all 3 runtimes in the same manner. If you need
+// the full spectrum of the formatting options you will need to use the appropriate runtime.
+//
+// The zero value results in no indentation, enum values using the enum names, and not including
+// zero-valued fields in the output.
+type jsonOptions struct {
+ // If set, generate multi-line output such that each field is prefixed by indent and terminated
+ // by a newline
+ indent string
+ // If true, enum fields will be output as integers rather than the enum value names
+ useEnumNumbers bool
+ // If true, include zero-valued fields in the JSON output
+ emitZeroValues bool
+
+ // If true, unknown fields will be discarded when unmarshaling rather than unmarshaling returning
+ // an error
+ allowUnknownFields bool
+ // If true, unmarshaled messages with missing required fields will not return an error
+ //
+ // Note: only applies to Google V2 (google.golang.org/protobuf) messages that are using proto2 syntax.
+ allowPartial bool
+}
diff --git a/vendor/github.com/CrowdStrike/csproto/marshal.go b/vendor/github.com/CrowdStrike/csproto/marshal.go
new file mode 100644
index 00000000000..2e4f0a11605
--- /dev/null
+++ b/vendor/github.com/CrowdStrike/csproto/marshal.go
@@ -0,0 +1,99 @@
+package csproto
+
+import (
+ "errors"
+
+ "google.golang.org/protobuf/proto"
+)
+
+var (
+ // ErrMarshaler is returned the Marshal() function when a message is passed in that does not
+ // match any of the supported behaviors
+ ErrMarshaler = errors.New("message does not implement csproto.Marshaler")
+ // ErrUnmarshaler is returned the Unmarshal() function when a message is passed in that does not
+ // match any of the supported behaviors
+ ErrUnmarshaler = errors.New("message does not implement csproto.Unmarshaler")
+)
+
+// ProtoV1Sizer defines the interface for a type that provides custom Protobuf V1 sizing logic.
+type ProtoV1Sizer interface {
+ XXX_Size() int
+}
+
+// ProtoV1Marshaler defines the interface for a type that provides custom Protobuf V1 marshaling logic.
+type ProtoV1Marshaler interface {
+ ProtoV1Sizer
+ XXX_Marshal(b []byte, deterministic bool) ([]byte, error)
+}
+
+// ProtoV1Unmarshaler defines the interface a type that provides custom Protobuf V1 unmarshaling.
+type ProtoV1Unmarshaler interface {
+ XXX_Unmarshal([]byte) error
+}
+
+// Sizer defines a message that can pre-calculate the required size for storing the binary Protobuf
+// encoding of its contents.
+type Sizer interface {
+ // Size returns the size, in bytes, required to serialize a message into binary Protobuf format.
+ Size() int
+}
+
+// Marshaler defines a message that can marshal itself into binary Protobuf format.
+type Marshaler interface {
+ // Marshal allocates a buffer large enough to hold this message, writes the contents of the
+ // message into it, then returns the buffer.
+ Marshal() ([]byte, error)
+}
+
+// MarshalerTo defines a message that can marshal itself into a provided buffer in binary Protobuf format.
+type MarshalerTo interface {
+ // MarshalTo writes the contents of this message into dest using the binary Protobuf encoding.
+ //
+ // It is up to the caller to ensure that the buffer is large enough to hold the serialized message
+ // data.
+ MarshalTo(dest []byte) error
+}
+
+// Unmarshaler defines a message that can unmarshal binary Protobuf data into itself.
+type Unmarshaler interface {
+ // Unmarshal decodes the binary Protobuf data into this message.
+ Unmarshal([]byte) error
+}
+
+// Marshal marshals msg to binary Protobuf format, delegating to the appropriate underlying
+// Protobuf API based on the concrete type of msg.
+func Marshal(msg interface{}) ([]byte, error) {
+ if pm, ok := msg.(Marshaler); ok {
+ return pm.Marshal()
+ }
+
+ if pm, ok := msg.(ProtoV1Marshaler); ok {
+ siz := pm.XXX_Size()
+ b := make([]byte, 0, siz)
+ return pm.XXX_Marshal(b, false)
+ }
+
+ if pm, ok := msg.(proto.Message); ok {
+ return proto.Marshal(pm)
+ }
+
+ return nil, ErrMarshaler
+}
+
+// Unmarshal decodes the specified Protobuf data into msg, delegating to the appropriate underlying
+// Protobuf API based on the concrete type of msg.
+func Unmarshal(data []byte, msg interface{}) error {
+ if pu, ok := msg.(Unmarshaler); ok {
+ return pu.Unmarshal(data)
+ }
+
+ if pu, ok := msg.(ProtoV1Unmarshaler); ok {
+ return pu.XXX_Unmarshal(data)
+ }
+
+ if pm, ok := msg.(proto.Message); ok {
+ return proto.Unmarshal(data, pm)
+ }
+
+ return ErrUnmarshaler
+}
diff --git a/vendor/github.com/CrowdStrike/csproto/marshal_text.go b/vendor/github.com/CrowdStrike/csproto/marshal_text.go
new file mode 100644
index 00000000000..e7d82e6270d
--- /dev/null
+++ b/vendor/github.com/CrowdStrike/csproto/marshal_text.go
@@ -0,0 +1,33 @@
+package csproto
+
+import (
+ "encoding"
+ "fmt"
+
+ gogo "github.com/gogo/protobuf/proto"
+ googlev1 "github.com/golang/protobuf/proto" //nolint: staticcheck // we're using this deprecated package intentionally"
+ "google.golang.org/protobuf/encoding/prototext"
+ "google.golang.org/protobuf/proto"
+)
+
+// MarshalText converts the specified message to prototext string format
+func MarshalText(msg interface{}) (string, error) {
+ if tm, ok := msg.(encoding.TextMarshaler); ok {
+ res, err := tm.MarshalText()
+ if err != nil {
+ return "", err
+ }
+ return string(res), nil
+ }
+
+ switch MsgType(msg) {
+ case MessageTypeGoogle:
+ return prototext.Format(msg.(proto.Message)), nil
+ case MessageTypeGoogleV1:
+ return googlev1.MarshalTextString(msg.(googlev1.Message)), nil
+ case MessageTypeGogo:
+ return gogo.MarshalTextString(msg.(gogo.Message)), nil
+ default:
+ return "", fmt.Errorf("unsupported message type: %T", msg)
+ }
+}
diff --git a/vendor/github.com/CrowdStrike/csproto/message_types.go b/vendor/github.com/CrowdStrike/csproto/message_types.go
new file mode 100644
index 00000000000..b53b4edca1d
--- /dev/null
+++ b/vendor/github.com/CrowdStrike/csproto/message_types.go
@@ -0,0 +1,56 @@
+package csproto
+
+import (
+ "reflect"
+ "sync"
+
+ gogo "github.com/gogo/protobuf/proto"
+ google "google.golang.org/protobuf/proto"
+)
+
+// MessageType defines the types of Protobuf message implementations this API supports.
+type MessageType int
+
+const (
+ // MessageTypeUnknown indicates that we don't know which type of Protobuf message a type is.
+ MessageTypeUnknown MessageType = iota
+ // MessageTypeGogo indicates that a type was generated using Gogo Protobuf.
+ MessageTypeGogo
+ // MessageTypeGoogleV1 indicates that a type was generated using v1 of Google's Protobuf tools.
+ MessageTypeGoogleV1
+ // MessageTypeGoogle indicates that a type was generated using v2 of Google's Protobuf tools.
+ MessageTypeGoogle
+)
+
+var unmarshalMap sync.Map // in-memory cache of the mapping of Go types to MessageType
+
+// MsgType accepts a protobuf message and returns the corresponding MessageType value.
+func MsgType(msg interface{}) MessageType {
+ typ := reflect.TypeOf(msg)
+ val, found := unmarshalMap.Load(typ)
+ if found {
+ return val.(MessageType)
+ }
+ mt := deduceMsgType(msg, typ)
+ unmarshalMap.Store(typ, mt)
+ return mt
+}
+
+func deduceMsgType(msg interface{}, typ reflect.Type) MessageType {
+ // does the message satisfy Google's v2 csproto.Message interface?
+ if _, ok := msg.(google.Message); ok {
+ return MessageTypeGoogle
+ }
+ if typ.Kind() != reflect.Ptr {
+ return MessageTypeUnknown
+ }
+ // does the message satisfy Gogo's csproto.Message interface
+ if gogoMsg, ok := msg.(gogo.Message); ok {
+ // secondary check that the message type is registered with the Gogo runtime b/c
+ // Gogo's csproto.Message and Google's v1 csproto.Message are the same
+ if gogo.MessageName(gogoMsg) != "" {
+ return MessageTypeGogo
+ }
+ }
+ return MessageTypeGoogleV1
+}
diff --git a/vendor/github.com/CrowdStrike/csproto/reset.go b/vendor/github.com/CrowdStrike/csproto/reset.go
new file mode 100644
index 00000000000..d7af8f52b70
--- /dev/null
+++ b/vendor/github.com/CrowdStrike/csproto/reset.go
@@ -0,0 +1,26 @@
+package csproto
+
+import (
+ "fmt"
+
+ "google.golang.org/protobuf/proto"
+)
+
+// Reset clears all fields of m.
+//
+// If m is not a supported message type (either generated by google.golang.org/protobuf/cmd/protoc-gen-go
+// or has a Reset() method) this function panics
+func Reset(m any) {
+ // as of 2022-12-20, both Google (V1 and V2) and Gogo emit a Reset() method on generated types
+ if r, ok := m.(interface{ Reset() }); ok {
+ r.Reset()
+ return
+ }
+ // in case the above changes for Google V2 types, delegate to proto.Reset()
+ if MsgType(m) == MessageTypeGoogle {
+ proto.Reset(m.(proto.Message))
+ return
+ }
+ // anything else is unsupported
+ panic(fmt.Errorf("unsupported message type (%T) passed to csproto.Reset()", m))
+}
diff --git a/vendor/github.com/CrowdStrike/csproto/sizeof.go b/vendor/github.com/CrowdStrike/csproto/sizeof.go
new file mode 100644
index 00000000000..5742863ec0a
--- /dev/null
+++ b/vendor/github.com/CrowdStrike/csproto/sizeof.go
@@ -0,0 +1,39 @@
+package csproto
+
+import (
+ "math/bits"
+
+ "google.golang.org/protobuf/proto"
+)
+
+// SizeOfTagKey returns the number of bytes required to hold the Protobuf varint encoding of k.
+func SizeOfTagKey(k int) int {
+ return SizeOfVarint(uint64(uint(k) << 3))
+}
+
+// SizeOfVarint returns the number of bytes required to hold the Protobuf varint encoding of v.
+func SizeOfVarint(v uint64) int {
+ return (bits.Len64(v|1) + 6) / 7
+}
+
+// SizeOfZigZag returns the number of bytes required to hold the zig zag encoding of v.
+func SizeOfZigZag(v uint64) int {
+ return SizeOfVarint((v << 1) ^ uint64((int64(v) >> 63)))
+}
+
+// Size returns the encoded size of msg.
+func Size(msg interface{}) int {
+ if pm, ok := msg.(Sizer); ok {
+ return pm.Size()
+ }
+
+ if pm, ok := msg.(ProtoV1Sizer); ok {
+ return pm.XXX_Size()
+ }
+
+ if pm, ok := msg.(proto.Message); ok {
+ return proto.Size(pm)
+ }
+
+ return 0
+}
diff --git a/vendor/github.com/CrowdStrike/csproto/tools.go b/vendor/github.com/CrowdStrike/csproto/tools.go
new file mode 100644
index 00000000000..172a604fff5
--- /dev/null
+++ b/vendor/github.com/CrowdStrike/csproto/tools.go
@@ -0,0 +1,9 @@
+//go:build tools
+// +build tools
+
+package csproto
+
+import (
+ _ "github.com/gogo/protobuf/protoc-gen-gogo"
+ _ "google.golang.org/protobuf/cmd/protoc-gen-go"
+)
diff --git a/vendor/github.com/CrowdStrike/csproto/wiretype.go b/vendor/github.com/CrowdStrike/csproto/wiretype.go
new file mode 100644
index 00000000000..a62afc51856
--- /dev/null
+++ b/vendor/github.com/CrowdStrike/csproto/wiretype.go
@@ -0,0 +1,36 @@
+package csproto
+
+// WireType defines the supported values for Protobuf wire encodings.
+type WireType int
+
+const (
+ // WireTypeVarint denotes a value that is encoded using base128 varint encoding.
+ WireTypeVarint WireType = 0
+ // WireTypeFixed64 denotes a value that is encoded using 8 bytes.
+ WireTypeFixed64 WireType = 1
+ // WireTypeLengthDelimited denotes a value that is encoded as a sequence of bytes preceded by a
+ // varint-encoded length.
+ WireTypeLengthDelimited WireType = 2
+ // WireTypeFixed32 denotes a value that is encoded using 4 bytes.
+ WireTypeFixed32 WireType = 5
+
+ // WireTypeStartGroup WireType = 3
+ // WireTypeEndGroup WireType = 4
+)
+
+var (
+ wireTypeToString = map[WireType]string{
+ WireTypeVarint: "varint",
+ WireTypeFixed64: "fixed64",
+ WireTypeLengthDelimited: "length-delimited",
+ WireTypeFixed32: "fixed32",
+ }
+)
+
+// String returns a string representation of wt.
+func (wt WireType) String() string {
+ if s, ok := wireTypeToString[wt]; ok {
+ return s
+ }
+ return "unknown"
+}
diff --git a/vendor/github.com/Masterminds/semver/v3/.golangci.yml b/vendor/github.com/Masterminds/semver/v3/.golangci.yml
index fdbdf1448c3..fbc6332592f 100644
--- a/vendor/github.com/Masterminds/semver/v3/.golangci.yml
+++ b/vendor/github.com/Masterminds/semver/v3/.golangci.yml
@@ -4,23 +4,24 @@ run:
linters:
disable-all: true
enable:
- - deadcode
- - dupl
- - errcheck
- - gofmt
- - goimports
- - golint
- - gosimple
+ - misspell
- govet
+ - staticcheck
+ - errcheck
+ - unparam
- ineffassign
- - misspell
- nakedret
- - structcheck
+ - gocyclo
+ - dupl
+ - goimports
+ - revive
+ - gosec
+ - gosimple
+ - typecheck
- unused
- - varcheck
linters-settings:
gofmt:
simplify: true
dupl:
- threshold: 400
+ threshold: 600
diff --git a/vendor/github.com/Masterminds/semver/v3/CHANGELOG.md b/vendor/github.com/Masterminds/semver/v3/CHANGELOG.md
index 1f90c38d260..f95a504fe70 100644
--- a/vendor/github.com/Masterminds/semver/v3/CHANGELOG.md
+++ b/vendor/github.com/Masterminds/semver/v3/CHANGELOG.md
@@ -1,5 +1,53 @@
# Changelog
+## 3.3.0 (2024-08-27)
+
+### Added
+
+- #238: Add LessThanEqual and GreaterThanEqual functions (thanks @grosser)
+- #213: nil version equality checking (thanks @KnutZuidema)
+
+### Changed
+
+- #241: Simplify StrictNewVersion parsing (thanks @grosser)
+- Testing support up through Go 1.23
+- Minimum version set to 1.21 as this is what's tested now
+- Fuzz testing now supports caching
+
+## 3.2.1 (2023-04-10)
+
+### Changed
+
+- #198: Improved testing around pre-release names
+- #200: Improved code scanning with addition of CodeQL
+- #201: Testing now includes Go 1.20. Go 1.17 has been dropped
+- #202: Migrated Fuzz testing to Go built-in Fuzzing. CI runs daily
+- #203: Docs updated for security details
+
+### Fixed
+
+- #199: Fixed issue with range transformations
+
+## 3.2.0 (2022-11-28)
+
+### Added
+
+- #190: Added text marshaling and unmarshaling
+- #167: Added JSON marshalling for constraints (thanks @SimonTheLeg)
+- #173: Implement encoding.TextMarshaler and encoding.TextUnmarshaler on Version (thanks @MarkRosemaker)
+- #179: Added New() version constructor (thanks @kazhuravlev)
+
+### Changed
+
+- #182/#183: Updated CI testing setup
+
+### Fixed
+
+- #186: Fixing issue where validation of constraint section gave false positives
+- #176: Fix constraints check with *-0 (thanks @mtt0)
+- #181: Fixed Caret operator (^) gives unexpected results when the minor version in constraint is 0 (thanks @arshchimni)
+- #161: Fixed godoc (thanks @afirth)
+
## 3.1.1 (2020-11-23)
### Fixed
diff --git a/vendor/github.com/Masterminds/semver/v3/Makefile b/vendor/github.com/Masterminds/semver/v3/Makefile
index eac19178fbd..9ca87a2c79e 100644
--- a/vendor/github.com/Masterminds/semver/v3/Makefile
+++ b/vendor/github.com/Masterminds/semver/v3/Makefile
@@ -1,7 +1,5 @@
GOPATH=$(shell go env GOPATH)
GOLANGCI_LINT=$(GOPATH)/bin/golangci-lint
-GOFUZZBUILD = $(GOPATH)/bin/go-fuzz-build
-GOFUZZ = $(GOPATH)/bin/go-fuzz
.PHONY: lint
lint: $(GOLANGCI_LINT)
@@ -19,19 +17,15 @@ test-cover:
GO111MODULE=on go test -cover .
.PHONY: fuzz
-fuzz: $(GOFUZZBUILD) $(GOFUZZ)
- @echo "==> Fuzz testing"
- $(GOFUZZBUILD)
- $(GOFUZZ) -workdir=_fuzz
+fuzz:
+ @echo "==> Running Fuzz Tests"
+ go env GOCACHE
+ go test -fuzz=FuzzNewVersion -fuzztime=15s .
+ go test -fuzz=FuzzStrictNewVersion -fuzztime=15s .
+ go test -fuzz=FuzzNewConstraint -fuzztime=15s .
$(GOLANGCI_LINT):
# Install golangci-lint. The configuration for it is in the .golangci.yml
# file in the root of the repository
echo ${GOPATH}
- curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(GOPATH)/bin v1.17.1
-
-$(GOFUZZBUILD):
- cd / && go get -u github.com/dvyukov/go-fuzz/go-fuzz-build
-
-$(GOFUZZ):
- cd / && go get -u github.com/dvyukov/go-fuzz/go-fuzz github.com/dvyukov/go-fuzz/go-fuzz-dep
\ No newline at end of file
+ curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(GOPATH)/bin v1.56.2
diff --git a/vendor/github.com/Masterminds/semver/v3/README.md b/vendor/github.com/Masterminds/semver/v3/README.md
index d8f54dcbd3c..ed56936084b 100644
--- a/vendor/github.com/Masterminds/semver/v3/README.md
+++ b/vendor/github.com/Masterminds/semver/v3/README.md
@@ -13,23 +13,22 @@ Active](https://masterminds.github.io/stability/active.svg)](https://masterminds
[![GoDoc](https://img.shields.io/static/v1?label=godoc&message=reference&color=blue)](https://pkg.go.dev/github.com/Masterminds/semver/v3)
[![Go Report Card](https://goreportcard.com/badge/github.com/Masterminds/semver)](https://goreportcard.com/report/github.com/Masterminds/semver)
-If you are looking for a command line tool for version comparisons please see
-[vert](https://github.com/Masterminds/vert) which uses this library.
-
## Package Versions
+Note, import `github.com/Masterminds/semver/v3` to use the latest version.
+
There are three major versions fo the `semver` package.
-* 3.x.x is the new stable and active version. This version is focused on constraint
+* 3.x.x is the stable and active version. This version is focused on constraint
compatibility for range handling in other tools from other languages. It has
a similar API to the v1 releases. The development of this version is on the master
branch. The documentation for this version is below.
* 2.x was developed primarily for [dep](https://github.com/golang/dep). There are
no tagged releases and the development was performed by [@sdboyer](https://github.com/sdboyer).
There are API breaking changes from v1. This version lives on the [2.x branch](https://github.com/Masterminds/semver/tree/2.x).
-* 1.x.x is the most widely used version with numerous tagged releases. This is the
- previous stable and is still maintained for bug fixes. The development, to fix
- bugs, occurs on the release-1 branch. You can read the documentation [here](https://github.com/Masterminds/semver/blob/release-1/README.md).
+* 1.x.x is the original release. It is no longer maintained. You should use the
+ v3 release instead. You can read the documentation for the 1.x.x release
+ [here](https://github.com/Masterminds/semver/blob/release-1/README.md).
## Parsing Semantic Versions
@@ -78,12 +77,12 @@ There are two methods for comparing versions. One uses comparison methods on
differences to notes between these two methods of comparison.
1. When two versions are compared using functions such as `Compare`, `LessThan`,
- and others it will follow the specification and always include prereleases
+ and others it will follow the specification and always include pre-releases
within the comparison. It will provide an answer that is valid with the
comparison section of the spec at https://semver.org/#spec-item-11
2. When constraint checking is used for checks or validation it will follow a
different set of rules that are common for ranges with tools like npm/js
- and Rust/Cargo. This includes considering prereleases to be invalid if the
+ and Rust/Cargo. This includes considering pre-releases to be invalid if the
ranges does not include one. If you want to have it include pre-releases a
simple solution is to include `-0` in your range.
3. Constraint ranges can have some complex rules including the shorthand use of
@@ -111,7 +110,7 @@ v, err := semver.NewVersion("1.3")
if err != nil {
// Handle version not being parsable.
}
-// Check if the version meets the constraints. The a variable will be true.
+// Check if the version meets the constraints. The variable a will be true.
a := c.Check(v)
```
@@ -135,20 +134,20 @@ The basic comparisons are:
### Working With Prerelease Versions
Pre-releases, for those not familiar with them, are used for software releases
-prior to stable or generally available releases. Examples of prereleases include
-development, alpha, beta, and release candidate releases. A prerelease may be
+prior to stable or generally available releases. Examples of pre-releases include
+development, alpha, beta, and release candidate releases. A pre-release may be
a version such as `1.2.3-beta.1` while the stable release would be `1.2.3`. In the
-order of precedence, prereleases come before their associated releases. In this
+order of precedence, pre-releases come before their associated releases. In this
example `1.2.3-beta.1 < 1.2.3`.
-According to the Semantic Version specification prereleases may not be
+According to the Semantic Version specification, pre-releases may not be
API compliant with their release counterpart. It says,
> A pre-release version indicates that the version is unstable and might not satisfy the intended compatibility requirements as denoted by its associated normal version.
-SemVer comparisons using constraints without a prerelease comparator will skip
-prerelease versions. For example, `>=1.2.3` will skip prereleases when looking
-at a list of releases while `>=1.2.3-0` will evaluate and find prereleases.
+SemVer's comparisons using constraints without a pre-release comparator will skip
+pre-release versions. For example, `>=1.2.3` will skip pre-releases when looking
+at a list of releases while `>=1.2.3-0` will evaluate and find pre-releases.
The reason for the `0` as a pre-release version in the example comparison is
because pre-releases can only contain ASCII alphanumerics and hyphens (along with
@@ -169,6 +168,9 @@ These look like:
* `1.2 - 1.4.5` which is equivalent to `>= 1.2 <= 1.4.5`
* `2.3.4 - 4.5` which is equivalent to `>= 2.3.4 <= 4.5`
+Note that `1.2-1.4.5` without whitespace is parsed completely differently; it's
+parsed as a single constraint `1.2.0` with _prerelease_ `1.4.5`.
+
### Wildcards In Comparisons
The `x`, `X`, and `*` characters can be used as a wildcard character. This works
@@ -242,3 +244,15 @@ for _, m := range msgs {
If you find an issue or want to contribute please file an [issue](https://github.com/Masterminds/semver/issues)
or [create a pull request](https://github.com/Masterminds/semver/pulls).
+
+## Security
+
+Security is an important consideration for this project. The project currently
+uses the following tools to help discover security issues:
+
+* [CodeQL](https://github.com/Masterminds/semver)
+* [gosec](https://github.com/securego/gosec)
+* Daily Fuzz testing
+
+If you believe you have found a security vulnerability you can privately disclose
+it through the [GitHub security page](https://github.com/Masterminds/semver/security).
diff --git a/vendor/github.com/Masterminds/semver/v3/SECURITY.md b/vendor/github.com/Masterminds/semver/v3/SECURITY.md
new file mode 100644
index 00000000000..a30a66b1f74
--- /dev/null
+++ b/vendor/github.com/Masterminds/semver/v3/SECURITY.md
@@ -0,0 +1,19 @@
+# Security Policy
+
+## Supported Versions
+
+The following versions of semver are currently supported:
+
+| Version | Supported |
+| ------- | ------------------ |
+| 3.x | :white_check_mark: |
+| 2.x | :x: |
+| 1.x | :x: |
+
+Fixes are only released for the latest minor version in the form of a patch release.
+
+## Reporting a Vulnerability
+
+You can privately disclose a vulnerability through GitHubs
+[private vulnerability reporting](https://github.com/Masterminds/semver/security/advisories)
+mechanism.
diff --git a/vendor/github.com/Masterminds/semver/v3/constraints.go b/vendor/github.com/Masterminds/semver/v3/constraints.go
index 547613f044f..8461c7ed903 100644
--- a/vendor/github.com/Masterminds/semver/v3/constraints.go
+++ b/vendor/github.com/Masterminds/semver/v3/constraints.go
@@ -134,6 +134,23 @@ func (cs Constraints) String() string {
return strings.Join(buf, " || ")
}
+// UnmarshalText implements the encoding.TextUnmarshaler interface.
+func (cs *Constraints) UnmarshalText(text []byte) error {
+ temp, err := NewConstraint(string(text))
+ if err != nil {
+ return err
+ }
+
+ *cs = *temp
+
+ return nil
+}
+
+// MarshalText implements the encoding.TextMarshaler interface.
+func (cs Constraints) MarshalText() ([]byte, error) {
+ return []byte(cs.String()), nil
+}
+
var constraintOps map[string]cfunc
var constraintRegex *regexp.Regexp
var constraintRangeRegex *regexp.Regexp
@@ -180,8 +197,13 @@ func init() {
ops,
cvRegex))
+ // The first time a constraint shows up will look slightly different from
+ // future times it shows up due to a leading space or comma in a given
+ // string.
validConstraintRegex = regexp.MustCompile(fmt.Sprintf(
- `^(\s*(%s)\s*(%s)\s*\,?)+$`,
+ `^(\s*(%s)\s*(%s)\s*)((?:\s+|,\s*)(%s)\s*(%s)\s*)*$`,
+ ops,
+ cvRegex,
ops,
cvRegex))
}
@@ -233,7 +255,7 @@ func parseConstraint(c string) (*constraint, error) {
patchDirty := false
dirty := false
if isX(m[3]) || m[3] == "" {
- ver = "0.0.0"
+ ver = fmt.Sprintf("0.0.0%s", m[6])
dirty = true
} else if isX(strings.TrimPrefix(m[4], ".")) || m[4] == "" {
minorDirty = true
@@ -534,6 +556,10 @@ func constraintCaret(v *Version, c *constraint) (bool, error) {
}
return false, fmt.Errorf("%s does not have same minor version as %s. Expected minor versions to match when constraint major version is 0", v, c.orig)
}
+ // ^ when the minor is 0 and minor > 0 is =0.0.z
+ if c.con.Minor() == 0 && v.Minor() > 0 {
+ return false, fmt.Errorf("%s does not have same minor version as %s", v, c.orig)
+ }
// At this point the major is 0 and the minor is 0 and not dirty. The patch
// is not dirty so we need to check if they are equal. If they are not equal
@@ -560,7 +586,7 @@ func rewriteRange(i string) string {
}
o := i
for _, v := range m {
- t := fmt.Sprintf(">= %s, <= %s", v[1], v[11])
+ t := fmt.Sprintf(">= %s, <= %s ", v[1], v[11])
o = strings.Replace(o, v[0], t, 1)
}
diff --git a/vendor/github.com/Masterminds/semver/v3/doc.go b/vendor/github.com/Masterminds/semver/v3/doc.go
index 391aa46b76d..74f97caa57f 100644
--- a/vendor/github.com/Masterminds/semver/v3/doc.go
+++ b/vendor/github.com/Masterminds/semver/v3/doc.go
@@ -3,12 +3,12 @@ Package semver provides the ability to work with Semantic Versions (http://semve
Specifically it provides the ability to:
- * Parse semantic versions
- * Sort semantic versions
- * Check if a semantic version fits within a set of constraints
- * Optionally work with a `v` prefix
+ - Parse semantic versions
+ - Sort semantic versions
+ - Check if a semantic version fits within a set of constraints
+ - Optionally work with a `v` prefix
-Parsing Semantic Versions
+# Parsing Semantic Versions
There are two functions that can parse semantic versions. The `StrictNewVersion`
function only parses valid version 2 semantic versions as outlined in the
@@ -21,48 +21,48 @@ that can be sorted, compared, and used in constraints.
When parsing a version an optional error can be returned if there is an issue
parsing the version. For example,
- v, err := semver.NewVersion("1.2.3-beta.1+b345")
+ v, err := semver.NewVersion("1.2.3-beta.1+b345")
The version object has methods to get the parts of the version, compare it to
other versions, convert the version back into a string, and get the original
string. For more details please see the documentation
at https://godoc.org/github.com/Masterminds/semver.
-Sorting Semantic Versions
+# Sorting Semantic Versions
A set of versions can be sorted using the `sort` package from the standard library.
For example,
- raw := []string{"1.2.3", "1.0", "1.3", "2", "0.4.2",}
- vs := make([]*semver.Version, len(raw))
- for i, r := range raw {
- v, err := semver.NewVersion(r)
- if err != nil {
- t.Errorf("Error parsing version: %s", err)
- }
+ raw := []string{"1.2.3", "1.0", "1.3", "2", "0.4.2",}
+ vs := make([]*semver.Version, len(raw))
+ for i, r := range raw {
+ v, err := semver.NewVersion(r)
+ if err != nil {
+ t.Errorf("Error parsing version: %s", err)
+ }
- vs[i] = v
- }
+ vs[i] = v
+ }
- sort.Sort(semver.Collection(vs))
+ sort.Sort(semver.Collection(vs))
-Checking Version Constraints and Comparing Versions
+# Checking Version Constraints and Comparing Versions
There are two methods for comparing versions. One uses comparison methods on
`Version` instances and the other is using Constraints. There are some important
differences to notes between these two methods of comparison.
-1. When two versions are compared using functions such as `Compare`, `LessThan`,
- and others it will follow the specification and always include prereleases
- within the comparison. It will provide an answer valid with the comparison
- spec section at https://semver.org/#spec-item-11
-2. When constraint checking is used for checks or validation it will follow a
- different set of rules that are common for ranges with tools like npm/js
- and Rust/Cargo. This includes considering prereleases to be invalid if the
- ranges does not include on. If you want to have it include pre-releases a
- simple solution is to include `-0` in your range.
-3. Constraint ranges can have some complex rules including the shorthard use of
- ~ and ^. For more details on those see the options below.
+ 1. When two versions are compared using functions such as `Compare`, `LessThan`,
+ and others it will follow the specification and always include prereleases
+ within the comparison. It will provide an answer valid with the comparison
+ spec section at https://semver.org/#spec-item-11
+ 2. When constraint checking is used for checks or validation it will follow a
+ different set of rules that are common for ranges with tools like npm/js
+ and Rust/Cargo. This includes considering prereleases to be invalid if the
+ ranges does not include on. If you want to have it include pre-releases a
+ simple solution is to include `-0` in your range.
+ 3. Constraint ranges can have some complex rules including the shorthard use of
+ ~ and ^. For more details on those see the options below.
There are differences between the two methods or checking versions because the
comparison methods on `Version` follow the specification while comparison ranges
@@ -76,19 +76,19 @@ patters with their versions.
Checking a version against version constraints is one of the most featureful
parts of the package.
- c, err := semver.NewConstraint(">= 1.2.3")
- if err != nil {
- // Handle constraint not being parsable.
- }
+ c, err := semver.NewConstraint(">= 1.2.3")
+ if err != nil {
+ // Handle constraint not being parsable.
+ }
- v, err := semver.NewVersion("1.3")
- if err != nil {
- // Handle version not being parsable.
- }
- // Check if the version meets the constraints. The a variable will be true.
- a := c.Check(v)
+ v, err := semver.NewVersion("1.3")
+ if err != nil {
+ // Handle version not being parsable.
+ }
+ // Check if the version meets the constraints. The a variable will be true.
+ a := c.Check(v)
-Basic Comparisons
+# Basic Comparisons
There are two elements to the comparisons. First, a comparison string is a list
of comma or space separated AND comparisons. These are then separated by || (OR)
@@ -99,31 +99,31 @@ greater than or equal to 4.2.3. This can also be written as
The basic comparisons are:
- * `=`: equal (aliased to no operator)
- * `!=`: not equal
- * `>`: greater than
- * `<`: less than
- * `>=`: greater than or equal to
- * `<=`: less than or equal to
+ - `=`: equal (aliased to no operator)
+ - `!=`: not equal
+ - `>`: greater than
+ - `<`: less than
+ - `>=`: greater than or equal to
+ - `<=`: less than or equal to
-Hyphen Range Comparisons
+# Hyphen Range Comparisons
There are multiple methods to handle ranges and the first is hyphens ranges.
These look like:
- * `1.2 - 1.4.5` which is equivalent to `>= 1.2, <= 1.4.5`
- * `2.3.4 - 4.5` which is equivalent to `>= 2.3.4 <= 4.5`
+ - `1.2 - 1.4.5` which is equivalent to `>= 1.2, <= 1.4.5`
+ - `2.3.4 - 4.5` which is equivalent to `>= 2.3.4 <= 4.5`
-Wildcards In Comparisons
+# Wildcards In Comparisons
The `x`, `X`, and `*` characters can be used as a wildcard character. This works
for all comparison operators. When used on the `=` operator it falls
back to the tilde operation. For example,
- * `1.2.x` is equivalent to `>= 1.2.0 < 1.3.0`
- * `>= 1.2.x` is equivalent to `>= 1.2.0`
- * `<= 2.x` is equivalent to `<= 3`
- * `*` is equivalent to `>= 0.0.0`
+ - `1.2.x` is equivalent to `>= 1.2.0 < 1.3.0`
+ - `>= 1.2.x` is equivalent to `>= 1.2.0`
+ - `<= 2.x` is equivalent to `<= 3`
+ - `*` is equivalent to `>= 0.0.0`
Tilde Range Comparisons (Patch)
@@ -131,11 +131,11 @@ The tilde (`~`) comparison operator is for patch level ranges when a minor
version is specified and major level changes when the minor number is missing.
For example,
- * `~1.2.3` is equivalent to `>= 1.2.3 < 1.3.0`
- * `~1` is equivalent to `>= 1, < 2`
- * `~2.3` is equivalent to `>= 2.3 < 2.4`
- * `~1.2.x` is equivalent to `>= 1.2.0 < 1.3.0`
- * `~1.x` is equivalent to `>= 1 < 2`
+ - `~1.2.3` is equivalent to `>= 1.2.3 < 1.3.0`
+ - `~1` is equivalent to `>= 1, < 2`
+ - `~2.3` is equivalent to `>= 2.3 < 2.4`
+ - `~1.2.x` is equivalent to `>= 1.2.0 < 1.3.0`
+ - `~1.x` is equivalent to `>= 1 < 2`
Caret Range Comparisons (Major)
@@ -144,41 +144,41 @@ The caret (`^`) comparison operator is for major level changes once a stable
as the API stability level. This is useful when comparisons of API versions as a
major change is API breaking. For example,
- * `^1.2.3` is equivalent to `>= 1.2.3, < 2.0.0`
- * `^1.2.x` is equivalent to `>= 1.2.0, < 2.0.0`
- * `^2.3` is equivalent to `>= 2.3, < 3`
- * `^2.x` is equivalent to `>= 2.0.0, < 3`
- * `^0.2.3` is equivalent to `>=0.2.3 <0.3.0`
- * `^0.2` is equivalent to `>=0.2.0 <0.3.0`
- * `^0.0.3` is equivalent to `>=0.0.3 <0.0.4`
- * `^0.0` is equivalent to `>=0.0.0 <0.1.0`
- * `^0` is equivalent to `>=0.0.0 <1.0.0`
+ - `^1.2.3` is equivalent to `>= 1.2.3, < 2.0.0`
+ - `^1.2.x` is equivalent to `>= 1.2.0, < 2.0.0`
+ - `^2.3` is equivalent to `>= 2.3, < 3`
+ - `^2.x` is equivalent to `>= 2.0.0, < 3`
+ - `^0.2.3` is equivalent to `>=0.2.3 <0.3.0`
+ - `^0.2` is equivalent to `>=0.2.0 <0.3.0`
+ - `^0.0.3` is equivalent to `>=0.0.3 <0.0.4`
+ - `^0.0` is equivalent to `>=0.0.0 <0.1.0`
+ - `^0` is equivalent to `>=0.0.0 <1.0.0`
-Validation
+# Validation
In addition to testing a version against a constraint, a version can be validated
against a constraint. When validation fails a slice of errors containing why a
version didn't meet the constraint is returned. For example,
- c, err := semver.NewConstraint("<= 1.2.3, >= 1.4")
- if err != nil {
- // Handle constraint not being parseable.
- }
-
- v, _ := semver.NewVersion("1.3")
- if err != nil {
- // Handle version not being parseable.
- }
-
- // Validate a version against a constraint.
- a, msgs := c.Validate(v)
- // a is false
- for _, m := range msgs {
- fmt.Println(m)
-
- // Loops over the errors which would read
- // "1.3 is greater than 1.2.3"
- // "1.3 is less than 1.4"
- }
+ c, err := semver.NewConstraint("<= 1.2.3, >= 1.4")
+ if err != nil {
+ // Handle constraint not being parseable.
+ }
+
+ v, _ := semver.NewVersion("1.3")
+ if err != nil {
+ // Handle version not being parseable.
+ }
+
+ // Validate a version against a constraint.
+ a, msgs := c.Validate(v)
+ // a is false
+ for _, m := range msgs {
+ fmt.Println(m)
+
+ // Loops over the errors which would read
+ // "1.3 is greater than 1.2.3"
+ // "1.3 is less than 1.4"
+ }
*/
package semver
diff --git a/vendor/github.com/Masterminds/semver/v3/fuzz.go b/vendor/github.com/Masterminds/semver/v3/fuzz.go
deleted file mode 100644
index a242ad70587..00000000000
--- a/vendor/github.com/Masterminds/semver/v3/fuzz.go
+++ /dev/null
@@ -1,22 +0,0 @@
-// +build gofuzz
-
-package semver
-
-func Fuzz(data []byte) int {
- d := string(data)
-
- // Test NewVersion
- _, _ = NewVersion(d)
-
- // Test StrictNewVersion
- _, _ = StrictNewVersion(d)
-
- // Test NewConstraint
- _, _ = NewConstraint(d)
-
- // The return value should be 0 normally, 1 if the priority in future tests
- // should be increased, and -1 if future tests should skip passing in that
- // data. We do not have a reason to change priority so 0 is always returned.
- // There are example tests that do this.
- return 0
-}
diff --git a/vendor/github.com/Masterminds/semver/v3/version.go b/vendor/github.com/Masterminds/semver/v3/version.go
index d6b9cda3eeb..ff499fb6640 100644
--- a/vendor/github.com/Masterminds/semver/v3/version.go
+++ b/vendor/github.com/Masterminds/semver/v3/version.go
@@ -55,14 +55,16 @@ func init() {
versionRegex = regexp.MustCompile("^" + semVerRegex + "$")
}
-const num string = "0123456789"
-const allowed string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-" + num
+const (
+ num string = "0123456789"
+ allowed string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-" + num
+)
// StrictNewVersion parses a given version and returns an instance of Version or
// an error if unable to parse the version. Only parses valid semantic versions.
// Performs checking that can find errors within the version.
-// If you want to coerce a version, such as 1 or 1.2, and perse that as the 1.x
-// releases of semver provided use the NewSemver() function.
+// If you want to coerce a version such as 1 or 1.2 and parse it as the 1.x
+// releases of semver did, use the NewVersion() function.
func StrictNewVersion(v string) (*Version, error) {
// Parsing here does not use RegEx in order to increase performance and reduce
// allocations.
@@ -81,22 +83,23 @@ func StrictNewVersion(v string) (*Version, error) {
original: v,
}
- // check for prerelease or build metadata
- var extra []string
- if strings.ContainsAny(parts[2], "-+") {
- // Start with the build metadata first as it needs to be on the right
- extra = strings.SplitN(parts[2], "+", 2)
- if len(extra) > 1 {
- // build metadata found
- sv.metadata = extra[1]
- parts[2] = extra[0]
+ // Extract build metadata
+ if strings.Contains(parts[2], "+") {
+ extra := strings.SplitN(parts[2], "+", 2)
+ sv.metadata = extra[1]
+ parts[2] = extra[0]
+ if err := validateMetadata(sv.metadata); err != nil {
+ return nil, err
}
+ }
- extra = strings.SplitN(parts[2], "-", 2)
- if len(extra) > 1 {
- // prerelease found
- sv.pre = extra[1]
- parts[2] = extra[0]
+ // Extract build prerelease
+ if strings.Contains(parts[2], "-") {
+ extra := strings.SplitN(parts[2], "-", 2)
+ sv.pre = extra[1]
+ parts[2] = extra[0]
+ if err := validatePrerelease(sv.pre); err != nil {
+ return nil, err
}
}
@@ -112,7 +115,7 @@ func StrictNewVersion(v string) (*Version, error) {
}
}
- // Extract the major, minor, and patch elements onto the returned Version
+ // Extract major, minor, and patch
var err error
sv.major, err = strconv.ParseUint(parts[0], 10, 64)
if err != nil {
@@ -129,23 +132,6 @@ func StrictNewVersion(v string) (*Version, error) {
return nil, err
}
- // No prerelease or build metadata found so returning now as a fastpath.
- if sv.pre == "" && sv.metadata == "" {
- return sv, nil
- }
-
- if sv.pre != "" {
- if err = validatePrerelease(sv.pre); err != nil {
- return nil, err
- }
- }
-
- if sv.metadata != "" {
- if err = validateMetadata(sv.metadata); err != nil {
- return nil, err
- }
- }
-
return sv, nil
}
@@ -207,6 +193,23 @@ func NewVersion(v string) (*Version, error) {
return sv, nil
}
+// New creates a new instance of Version with each of the parts passed in as
+// arguments instead of parsing a version string.
+func New(major, minor, patch uint64, pre, metadata string) *Version {
+ v := Version{
+ major: major,
+ minor: minor,
+ patch: patch,
+ pre: pre,
+ metadata: metadata,
+ original: "",
+ }
+
+ v.original = v.String()
+
+ return &v
+}
+
// MustParse parses a given version and panics on error.
func MustParse(v string) *Version {
sv, err := NewVersion(v)
@@ -267,7 +270,6 @@ func (v Version) Metadata() string {
// originalVPrefix returns the original 'v' prefix if any.
func (v Version) originalVPrefix() string {
-
// Note, only lowercase v is supported as a prefix by the parser.
if v.original != "" && v.original[:1] == "v" {
return v.original[:1]
@@ -363,15 +365,31 @@ func (v *Version) LessThan(o *Version) bool {
return v.Compare(o) < 0
}
+// LessThanEqual tests if one version is less or equal than another one.
+func (v *Version) LessThanEqual(o *Version) bool {
+ return v.Compare(o) <= 0
+}
+
// GreaterThan tests if one version is greater than another one.
func (v *Version) GreaterThan(o *Version) bool {
return v.Compare(o) > 0
}
+// GreaterThanEqual tests if one version is greater or equal than another one.
+func (v *Version) GreaterThanEqual(o *Version) bool {
+ return v.Compare(o) >= 0
+}
+
// Equal tests if two versions are equal to each other.
// Note, versions can be equal with different metadata since metadata
// is not considered part of the comparable version.
func (v *Version) Equal(o *Version) bool {
+ if v == o {
+ return true
+ }
+ if v == nil || o == nil {
+ return false
+ }
return v.Compare(o) == 0
}
@@ -436,6 +454,23 @@ func (v Version) MarshalJSON() ([]byte, error) {
return json.Marshal(v.String())
}
+// UnmarshalText implements the encoding.TextUnmarshaler interface.
+func (v *Version) UnmarshalText(text []byte) error {
+ temp, err := NewVersion(string(text))
+ if err != nil {
+ return err
+ }
+
+ *v = *temp
+
+ return nil
+}
+
+// MarshalText implements the encoding.TextMarshaler interface.
+func (v Version) MarshalText() ([]byte, error) {
+ return []byte(v.String()), nil
+}
+
// Scan implements the SQL.Scanner interface.
func (v *Version) Scan(value interface{}) error {
var s string
@@ -470,7 +505,6 @@ func compareSegment(v, o uint64) int {
}
func comparePrerelease(v, o string) int {
-
// split the prelease versions by their part. The separator, per the spec,
// is a .
sparts := strings.Split(v, ".")
@@ -562,7 +596,6 @@ func comparePrePart(s, o string) int {
return 1
}
return -1
-
}
// Like strings.ContainsAny but does an only instead of any.
diff --git a/vendor/github.com/Masterminds/sprig/v3/CHANGELOG.md b/vendor/github.com/Masterminds/sprig/v3/CHANGELOG.md
index fcdd4e88aed..b5ef766a7af 100644
--- a/vendor/github.com/Masterminds/sprig/v3/CHANGELOG.md
+++ b/vendor/github.com/Masterminds/sprig/v3/CHANGELOG.md
@@ -1,8 +1,39 @@
# Changelog
+## Release 3.3.0 (2024-08-29)
+
+### Added
+
+- #400: added sha512sum function (thanks @itzik-elayev)
+
+### Changed
+
+- #407: Removed duplicate documentation (functions were documentated in 2 places)
+- #290: Corrected copy/paster oops in math documentation (thanks @zzhu41)
+- #369: Corrected template reference in docs (thanks @chey)
+- #375: Added link to URL documenation (thanks @carlpett)
+- #406: Updated the mergo dependency which had a breaking change (which was accounted for)
+- #376: Fixed documentation error (thanks @jheyduk)
+- #404: Updated dependency tree
+- #391: Fixed misspelling (thanks @chrishalbert)
+- #405: Updated Go versions used in testing
+
+## Release 3.2.3 (2022-11-29)
+
+### Changed
+
+- Updated docs (thanks @book987 @aJetHorn @neelayu @pellizzetti @apricote @SaigyoujiYuyuko233 @AlekSi)
+- #348: Updated huandu/xstrings which fixed a snake case bug (thanks @yxxhero)
+- #353: Updated masterminds/semver which included bug fixes
+- #354: Updated golang.org/x/crypto which included bug fixes
+
+## Release 3.2.2 (2021-02-04)
+
+This is a re-release of 3.2.1 to satisfy something with the Go module system.
+
## Release 3.2.1 (2021-02-04)
-### Changed
+### Changed
- Upgraded `Masterminds/goutils` to `v1.1.1`. see the [Security Advisory](https://github.com/Masterminds/goutils/security/advisories/GHSA-xg2h-wx96-xgxr)
@@ -294,7 +325,7 @@ This release adds new functions, including:
- Added `semver` and `semverCompare` for Semantic Versions
- `list` replaces `tuple`
- Fixed issue with `join`
-- Added `first`, `last`, `intial`, `rest`, `prepend`, `append`, `toString`, `toStrings`, `sortAlpha`, `reverse`, `coalesce`, `pluck`, `pick`, `compact`, `keys`, `omit`, `uniq`, `has`, `without`
+- Added `first`, `last`, `initial`, `rest`, `prepend`, `append`, `toString`, `toStrings`, `sortAlpha`, `reverse`, `coalesce`, `pluck`, `pick`, `compact`, `keys`, `omit`, `uniq`, `has`, `without`
## Release 2.9.0 (2017-02-23)
@@ -348,7 +379,7 @@ Because we switched from `int` to `int64` as the return value for all integer ma
- `min` complements `max` (formerly `biggest`)
- `empty` indicates that a value is the empty value for its type
- `tuple` creates a tuple inside of a template: `{{$t := tuple "a", "b" "c"}}`
-- `dict` creates a dictionary inside of a template `{{$d := dict "key1" "val1" "key2" "val2"}}`
+- `dict` creates a dictionary inside of a template `{{$d := dict "key1" "val1" "key2" "val2"}}`
- Date formatters have been added for HTML dates (as used in `date` input fields)
- Integer math functions can convert from a number of types, including `string` (via `strconv.ParseInt`).
diff --git a/vendor/github.com/Masterminds/sprig/v3/README.md b/vendor/github.com/Masterminds/sprig/v3/README.md
index c37ba01c216..3e22c60e1a0 100644
--- a/vendor/github.com/Masterminds/sprig/v3/README.md
+++ b/vendor/github.com/Masterminds/sprig/v3/README.md
@@ -17,10 +17,9 @@ JavaScript libraries, such as [underscore.js](http://underscorejs.org/).
## IMPORTANT NOTES
Sprig leverages [mergo](https://github.com/imdario/mergo) to handle merges. In
-its v0.3.9 release there was a behavior change that impacts merging template
-functions in sprig. It is currently recommended to use v0.3.8 of that package.
-Using v0.3.9 will cause sprig tests to fail. The issue in mergo is tracked at
-https://github.com/imdario/mergo/issues/139.
+its v0.3.9 release, there was a behavior change that impacts merging template
+functions in sprig. It is currently recommended to use v0.3.10 or later of that package.
+Using v0.3.9 will cause sprig tests to fail.
## Package Versions
@@ -51,7 +50,7 @@ To load the Sprig `FuncMap`:
```go
import (
- "github.com/Masterminds/sprig"
+ "github.com/Masterminds/sprig/v3"
"html/template"
)
diff --git a/vendor/github.com/Masterminds/sprig/v3/crypto.go b/vendor/github.com/Masterminds/sprig/v3/crypto.go
index 13a5cd55934..75fe027e4d3 100644
--- a/vendor/github.com/Masterminds/sprig/v3/crypto.go
+++ b/vendor/github.com/Masterminds/sprig/v3/crypto.go
@@ -14,6 +14,7 @@ import (
"crypto/rsa"
"crypto/sha1"
"crypto/sha256"
+ "crypto/sha512"
"crypto/x509"
"crypto/x509/pkix"
"encoding/asn1"
@@ -36,6 +37,11 @@ import (
"golang.org/x/crypto/scrypt"
)
+func sha512sum(input string) string {
+ hash := sha512.Sum512([]byte(input))
+ return hex.EncodeToString(hash[:])
+}
+
func sha256sum(input string) string {
hash := sha256.Sum256([]byte(input))
return hex.EncodeToString(hash[:])
diff --git a/vendor/github.com/Masterminds/sprig/v3/dict.go b/vendor/github.com/Masterminds/sprig/v3/dict.go
index ade88969840..4315b3542ad 100644
--- a/vendor/github.com/Masterminds/sprig/v3/dict.go
+++ b/vendor/github.com/Masterminds/sprig/v3/dict.go
@@ -1,7 +1,7 @@
package sprig
import (
- "github.com/imdario/mergo"
+ "dario.cat/mergo"
"github.com/mitchellh/copystructure"
)
diff --git a/vendor/github.com/Masterminds/sprig/v3/doc.go b/vendor/github.com/Masterminds/sprig/v3/doc.go
index aabb9d4489f..91031d6d197 100644
--- a/vendor/github.com/Masterminds/sprig/v3/doc.go
+++ b/vendor/github.com/Masterminds/sprig/v3/doc.go
@@ -6,7 +6,7 @@ inside of Go `html/template` and `text/template` files.
To add these functions, use the `template.Funcs()` method:
- t := templates.New("foo").Funcs(sprig.FuncMap())
+ t := template.New("foo").Funcs(sprig.FuncMap())
Note that you should add the function map before you parse any template files.
diff --git a/vendor/github.com/Masterminds/sprig/v3/functions.go b/vendor/github.com/Masterminds/sprig/v3/functions.go
index 57fcec1d9ea..cda47d26f27 100644
--- a/vendor/github.com/Masterminds/sprig/v3/functions.go
+++ b/vendor/github.com/Masterminds/sprig/v3/functions.go
@@ -22,8 +22,7 @@ import (
//
// Use this to pass the functions into the template engine:
//
-// tpl := template.New("foo").Funcs(sprig.FuncMap()))
-//
+// tpl := template.New("foo").Funcs(sprig.FuncMap()))
func FuncMap() template.FuncMap {
return HtmlFuncMap()
}
@@ -142,10 +141,13 @@ var genericMap = map[string]interface{}{
"swapcase": util.SwapCase,
"shuffle": xstrings.Shuffle,
"snakecase": xstrings.ToSnakeCase,
- "camelcase": xstrings.ToCamelCase,
- "kebabcase": xstrings.ToKebabCase,
- "wrap": func(l int, s string) string { return util.Wrap(s, l) },
- "wrapWith": func(l int, sep, str string) string { return util.WrapCustom(str, l, sep, true) },
+ // camelcase used to call xstrings.ToCamelCase, but that function had a breaking change in version
+ // 1.5 that moved it from upper camel case to lower camel case. This is a breaking change for sprig.
+ // A new xstrings.ToPascalCase function was added that provided upper camel case.
+ "camelcase": xstrings.ToPascalCase,
+ "kebabcase": xstrings.ToKebabCase,
+ "wrap": func(l int, s string) string { return util.Wrap(s, l) },
+ "wrapWith": func(l int, sep, str string) string { return util.WrapCustom(str, l, sep, true) },
// Switch order so that "foobar" | contains "foo"
"contains": func(substr string, str string) bool { return strings.Contains(str, substr) },
"hasPrefix": func(substr string, str string) bool { return strings.HasPrefix(str, substr) },
@@ -159,6 +161,7 @@ var genericMap = map[string]interface{}{
"plural": plural,
"sha1sum": sha1sum,
"sha256sum": sha256sum,
+ "sha512sum": sha512sum,
"adler32sum": adler32sum,
"toString": strval,
@@ -336,20 +339,20 @@ var genericMap = map[string]interface{}{
"mustChunk": mustChunk,
// Crypto:
- "bcrypt": bcrypt,
- "htpasswd": htpasswd,
- "genPrivateKey": generatePrivateKey,
- "derivePassword": derivePassword,
- "buildCustomCert": buildCustomCertificate,
- "genCA": generateCertificateAuthority,
- "genCAWithKey": generateCertificateAuthorityWithPEMKey,
- "genSelfSignedCert": generateSelfSignedCertificate,
+ "bcrypt": bcrypt,
+ "htpasswd": htpasswd,
+ "genPrivateKey": generatePrivateKey,
+ "derivePassword": derivePassword,
+ "buildCustomCert": buildCustomCertificate,
+ "genCA": generateCertificateAuthority,
+ "genCAWithKey": generateCertificateAuthorityWithPEMKey,
+ "genSelfSignedCert": generateSelfSignedCertificate,
"genSelfSignedCertWithKey": generateSelfSignedCertificateWithPEMKey,
- "genSignedCert": generateSignedCertificate,
- "genSignedCertWithKey": generateSignedCertificateWithPEMKey,
- "encryptAES": encryptAES,
- "decryptAES": decryptAES,
- "randBytes": randBytes,
+ "genSignedCert": generateSignedCertificate,
+ "genSignedCertWithKey": generateSignedCertificateWithPEMKey,
+ "encryptAES": encryptAES,
+ "decryptAES": decryptAES,
+ "randBytes": randBytes,
// UUIDs:
"uuidv4": uuidv4,
diff --git a/vendor/github.com/gogo/protobuf/plugin/compare/compare.go b/vendor/github.com/gogo/protobuf/plugin/compare/compare.go
new file mode 100644
index 00000000000..9ab40ef1508
--- /dev/null
+++ b/vendor/github.com/gogo/protobuf/plugin/compare/compare.go
@@ -0,0 +1,580 @@
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2013, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// 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.
+//
+// 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 compare
+
+import (
+ "github.com/gogo/protobuf/gogoproto"
+ "github.com/gogo/protobuf/proto"
+ descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
+ "github.com/gogo/protobuf/protoc-gen-gogo/generator"
+ "github.com/gogo/protobuf/vanity"
+)
+
+type plugin struct {
+ *generator.Generator
+ generator.PluginImports
+ fmtPkg generator.Single
+ bytesPkg generator.Single
+ sortkeysPkg generator.Single
+ protoPkg generator.Single
+}
+
+func NewPlugin() *plugin {
+ return &plugin{}
+}
+
+func (p *plugin) Name() string {
+ return "compare"
+}
+
+func (p *plugin) Init(g *generator.Generator) {
+ p.Generator = g
+}
+
+func (p *plugin) Generate(file *generator.FileDescriptor) {
+ p.PluginImports = generator.NewPluginImports(p.Generator)
+ p.fmtPkg = p.NewImport("fmt")
+ p.bytesPkg = p.NewImport("bytes")
+ p.sortkeysPkg = p.NewImport("github.com/gogo/protobuf/sortkeys")
+ p.protoPkg = p.NewImport("github.com/gogo/protobuf/proto")
+
+ for _, msg := range file.Messages() {
+ if msg.DescriptorProto.GetOptions().GetMapEntry() {
+ continue
+ }
+ if gogoproto.HasCompare(file.FileDescriptorProto, msg.DescriptorProto) {
+ p.generateMessage(file, msg)
+ }
+ }
+}
+
+func (p *plugin) generateNullableField(fieldname string) {
+ p.P(`if this.`, fieldname, ` != nil && that1.`, fieldname, ` != nil {`)
+ p.In()
+ p.P(`if *this.`, fieldname, ` != *that1.`, fieldname, `{`)
+ p.In()
+ p.P(`if *this.`, fieldname, ` < *that1.`, fieldname, `{`)
+ p.In()
+ p.P(`return -1`)
+ p.Out()
+ p.P(`}`)
+ p.P(`return 1`)
+ p.Out()
+ p.P(`}`)
+ p.Out()
+ p.P(`} else if this.`, fieldname, ` != nil {`)
+ p.In()
+ p.P(`return 1`)
+ p.Out()
+ p.P(`} else if that1.`, fieldname, ` != nil {`)
+ p.In()
+ p.P(`return -1`)
+ p.Out()
+ p.P(`}`)
+}
+
+func (p *plugin) generateMsgNullAndTypeCheck(ccTypeName string) {
+ p.P(`if that == nil {`)
+ p.In()
+ p.P(`if this == nil {`)
+ p.In()
+ p.P(`return 0`)
+ p.Out()
+ p.P(`}`)
+ p.P(`return 1`)
+ p.Out()
+ p.P(`}`)
+ p.P(``)
+ p.P(`that1, ok := that.(*`, ccTypeName, `)`)
+ p.P(`if !ok {`)
+ p.In()
+ p.P(`that2, ok := that.(`, ccTypeName, `)`)
+ p.P(`if ok {`)
+ p.In()
+ p.P(`that1 = &that2`)
+ p.Out()
+ p.P(`} else {`)
+ p.In()
+ p.P(`return 1`)
+ p.Out()
+ p.P(`}`)
+ p.Out()
+ p.P(`}`)
+ p.P(`if that1 == nil {`)
+ p.In()
+ p.P(`if this == nil {`)
+ p.In()
+ p.P(`return 0`)
+ p.Out()
+ p.P(`}`)
+ p.P(`return 1`)
+ p.Out()
+ p.P(`} else if this == nil {`)
+ p.In()
+ p.P(`return -1`)
+ p.Out()
+ p.P(`}`)
+}
+
+func (p *plugin) generateField(file *generator.FileDescriptor, message *generator.Descriptor, field *descriptor.FieldDescriptorProto) {
+ proto3 := gogoproto.IsProto3(file.FileDescriptorProto)
+ fieldname := p.GetOneOfFieldName(message, field)
+ repeated := field.IsRepeated()
+ ctype := gogoproto.IsCustomType(field)
+ nullable := gogoproto.IsNullable(field)
+ // oneof := field.OneofIndex != nil
+ if !repeated {
+ if ctype {
+ if nullable {
+ p.P(`if that1.`, fieldname, ` == nil {`)
+ p.In()
+ p.P(`if this.`, fieldname, ` != nil {`)
+ p.In()
+ p.P(`return 1`)
+ p.Out()
+ p.P(`}`)
+ p.Out()
+ p.P(`} else if this.`, fieldname, ` == nil {`)
+ p.In()
+ p.P(`return -1`)
+ p.Out()
+ p.P(`} else if c := this.`, fieldname, `.Compare(*that1.`, fieldname, `); c != 0 {`)
+ } else {
+ p.P(`if c := this.`, fieldname, `.Compare(that1.`, fieldname, `); c != 0 {`)
+ }
+ p.In()
+ p.P(`return c`)
+ p.Out()
+ p.P(`}`)
+ } else {
+ if field.IsMessage() || p.IsGroup(field) {
+ if nullable {
+ p.P(`if c := this.`, fieldname, `.Compare(that1.`, fieldname, `); c != 0 {`)
+ } else {
+ p.P(`if c := this.`, fieldname, `.Compare(&that1.`, fieldname, `); c != 0 {`)
+ }
+ p.In()
+ p.P(`return c`)
+ p.Out()
+ p.P(`}`)
+ } else if field.IsBytes() {
+ p.P(`if c := `, p.bytesPkg.Use(), `.Compare(this.`, fieldname, `, that1.`, fieldname, `); c != 0 {`)
+ p.In()
+ p.P(`return c`)
+ p.Out()
+ p.P(`}`)
+ } else if field.IsString() {
+ if nullable && !proto3 {
+ p.generateNullableField(fieldname)
+ } else {
+ p.P(`if this.`, fieldname, ` != that1.`, fieldname, `{`)
+ p.In()
+ p.P(`if this.`, fieldname, ` < that1.`, fieldname, `{`)
+ p.In()
+ p.P(`return -1`)
+ p.Out()
+ p.P(`}`)
+ p.P(`return 1`)
+ p.Out()
+ p.P(`}`)
+ }
+ } else if field.IsBool() {
+ if nullable && !proto3 {
+ p.P(`if this.`, fieldname, ` != nil && that1.`, fieldname, ` != nil {`)
+ p.In()
+ p.P(`if *this.`, fieldname, ` != *that1.`, fieldname, `{`)
+ p.In()
+ p.P(`if !*this.`, fieldname, ` {`)
+ p.In()
+ p.P(`return -1`)
+ p.Out()
+ p.P(`}`)
+ p.P(`return 1`)
+ p.Out()
+ p.P(`}`)
+ p.Out()
+ p.P(`} else if this.`, fieldname, ` != nil {`)
+ p.In()
+ p.P(`return 1`)
+ p.Out()
+ p.P(`} else if that1.`, fieldname, ` != nil {`)
+ p.In()
+ p.P(`return -1`)
+ p.Out()
+ p.P(`}`)
+ } else {
+ p.P(`if this.`, fieldname, ` != that1.`, fieldname, `{`)
+ p.In()
+ p.P(`if !this.`, fieldname, ` {`)
+ p.In()
+ p.P(`return -1`)
+ p.Out()
+ p.P(`}`)
+ p.P(`return 1`)
+ p.Out()
+ p.P(`}`)
+ }
+ } else {
+ if nullable && !proto3 {
+ p.generateNullableField(fieldname)
+ } else {
+ p.P(`if this.`, fieldname, ` != that1.`, fieldname, `{`)
+ p.In()
+ p.P(`if this.`, fieldname, ` < that1.`, fieldname, `{`)
+ p.In()
+ p.P(`return -1`)
+ p.Out()
+ p.P(`}`)
+ p.P(`return 1`)
+ p.Out()
+ p.P(`}`)
+ }
+ }
+ }
+ } else {
+ p.P(`if len(this.`, fieldname, `) != len(that1.`, fieldname, `) {`)
+ p.In()
+ p.P(`if len(this.`, fieldname, `) < len(that1.`, fieldname, `) {`)
+ p.In()
+ p.P(`return -1`)
+ p.Out()
+ p.P(`}`)
+ p.P(`return 1`)
+ p.Out()
+ p.P(`}`)
+ p.P(`for i := range this.`, fieldname, ` {`)
+ p.In()
+ if ctype {
+ p.P(`if c := this.`, fieldname, `[i].Compare(that1.`, fieldname, `[i]); c != 0 {`)
+ p.In()
+ p.P(`return c`)
+ p.Out()
+ p.P(`}`)
+ } else {
+ if p.IsMap(field) {
+ m := p.GoMapType(nil, field)
+ valuegoTyp, _ := p.GoType(nil, m.ValueField)
+ valuegoAliasTyp, _ := p.GoType(nil, m.ValueAliasField)
+ nullable, valuegoTyp, valuegoAliasTyp = generator.GoMapValueTypes(field, m.ValueField, valuegoTyp, valuegoAliasTyp)
+
+ mapValue := m.ValueAliasField
+ if mapValue.IsMessage() || p.IsGroup(mapValue) {
+ if nullable && valuegoTyp == valuegoAliasTyp {
+ p.P(`if c := this.`, fieldname, `[i].Compare(that1.`, fieldname, `[i]); c != 0 {`)
+ } else {
+ // Compare() has a pointer receiver, but map value is a value type
+ a := `this.` + fieldname + `[i]`
+ b := `that1.` + fieldname + `[i]`
+ if valuegoTyp != valuegoAliasTyp {
+ // cast back to the type that has the generated methods on it
+ a = `(` + valuegoTyp + `)(` + a + `)`
+ b = `(` + valuegoTyp + `)(` + b + `)`
+ }
+ p.P(`a := `, a)
+ p.P(`b := `, b)
+ if nullable {
+ p.P(`if c := a.Compare(b); c != 0 {`)
+ } else {
+ p.P(`if c := (&a).Compare(&b); c != 0 {`)
+ }
+ }
+ p.In()
+ p.P(`return c`)
+ p.Out()
+ p.P(`}`)
+ } else if mapValue.IsBytes() {
+ p.P(`if c := `, p.bytesPkg.Use(), `.Compare(this.`, fieldname, `[i], that1.`, fieldname, `[i]); c != 0 {`)
+ p.In()
+ p.P(`return c`)
+ p.Out()
+ p.P(`}`)
+ } else if mapValue.IsString() {
+ p.P(`if this.`, fieldname, `[i] != that1.`, fieldname, `[i] {`)
+ p.In()
+ p.P(`if this.`, fieldname, `[i] < that1.`, fieldname, `[i] {`)
+ p.In()
+ p.P(`return -1`)
+ p.Out()
+ p.P(`}`)
+ p.P(`return 1`)
+ p.Out()
+ p.P(`}`)
+ } else {
+ p.P(`if this.`, fieldname, `[i] != that1.`, fieldname, `[i] {`)
+ p.In()
+ p.P(`if this.`, fieldname, `[i] < that1.`, fieldname, `[i] {`)
+ p.In()
+ p.P(`return -1`)
+ p.Out()
+ p.P(`}`)
+ p.P(`return 1`)
+ p.Out()
+ p.P(`}`)
+ }
+ } else if field.IsMessage() || p.IsGroup(field) {
+ if nullable {
+ p.P(`if c := this.`, fieldname, `[i].Compare(that1.`, fieldname, `[i]); c != 0 {`)
+ p.In()
+ p.P(`return c`)
+ p.Out()
+ p.P(`}`)
+ } else {
+ p.P(`if c := this.`, fieldname, `[i].Compare(&that1.`, fieldname, `[i]); c != 0 {`)
+ p.In()
+ p.P(`return c`)
+ p.Out()
+ p.P(`}`)
+ }
+ } else if field.IsBytes() {
+ p.P(`if c := `, p.bytesPkg.Use(), `.Compare(this.`, fieldname, `[i], that1.`, fieldname, `[i]); c != 0 {`)
+ p.In()
+ p.P(`return c`)
+ p.Out()
+ p.P(`}`)
+ } else if field.IsString() {
+ p.P(`if this.`, fieldname, `[i] != that1.`, fieldname, `[i] {`)
+ p.In()
+ p.P(`if this.`, fieldname, `[i] < that1.`, fieldname, `[i] {`)
+ p.In()
+ p.P(`return -1`)
+ p.Out()
+ p.P(`}`)
+ p.P(`return 1`)
+ p.Out()
+ p.P(`}`)
+ } else if field.IsBool() {
+ p.P(`if this.`, fieldname, `[i] != that1.`, fieldname, `[i] {`)
+ p.In()
+ p.P(`if !this.`, fieldname, `[i] {`)
+ p.In()
+ p.P(`return -1`)
+ p.Out()
+ p.P(`}`)
+ p.P(`return 1`)
+ p.Out()
+ p.P(`}`)
+ } else {
+ p.P(`if this.`, fieldname, `[i] != that1.`, fieldname, `[i] {`)
+ p.In()
+ p.P(`if this.`, fieldname, `[i] < that1.`, fieldname, `[i] {`)
+ p.In()
+ p.P(`return -1`)
+ p.Out()
+ p.P(`}`)
+ p.P(`return 1`)
+ p.Out()
+ p.P(`}`)
+ }
+ }
+ p.Out()
+ p.P(`}`)
+ }
+}
+
+func (p *plugin) generateMessage(file *generator.FileDescriptor, message *generator.Descriptor) {
+ ccTypeName := generator.CamelCaseSlice(message.TypeName())
+ p.P(`func (this *`, ccTypeName, `) Compare(that interface{}) int {`)
+ p.In()
+ p.generateMsgNullAndTypeCheck(ccTypeName)
+ oneofs := make(map[string]struct{})
+
+ for _, field := range message.Field {
+ oneof := field.OneofIndex != nil
+ if oneof {
+ fieldname := p.GetFieldName(message, field)
+ if _, ok := oneofs[fieldname]; ok {
+ continue
+ } else {
+ oneofs[fieldname] = struct{}{}
+ }
+ p.P(`if that1.`, fieldname, ` == nil {`)
+ p.In()
+ p.P(`if this.`, fieldname, ` != nil {`)
+ p.In()
+ p.P(`return 1`)
+ p.Out()
+ p.P(`}`)
+ p.Out()
+ p.P(`} else if this.`, fieldname, ` == nil {`)
+ p.In()
+ p.P(`return -1`)
+ p.Out()
+ p.P(`} else {`)
+ p.In()
+
+ // Generate two type switches in order to compare the
+ // types of the oneofs. If they are of the same type
+ // call Compare, otherwise return 1 or -1.
+ p.P(`thisType := -1`)
+ p.P(`switch this.`, fieldname, `.(type) {`)
+ for i, subfield := range message.Field {
+ if *subfield.OneofIndex == *field.OneofIndex {
+ ccTypeName := p.OneOfTypeName(message, subfield)
+ p.P(`case *`, ccTypeName, `:`)
+ p.In()
+ p.P(`thisType = `, i)
+ p.Out()
+ }
+ }
+ p.P(`default:`)
+ p.In()
+ p.P(`panic(fmt.Sprintf("compare: unexpected type %T in oneof", this.`, fieldname, `))`)
+ p.Out()
+ p.P(`}`)
+
+ p.P(`that1Type := -1`)
+ p.P(`switch that1.`, fieldname, `.(type) {`)
+ for i, subfield := range message.Field {
+ if *subfield.OneofIndex == *field.OneofIndex {
+ ccTypeName := p.OneOfTypeName(message, subfield)
+ p.P(`case *`, ccTypeName, `:`)
+ p.In()
+ p.P(`that1Type = `, i)
+ p.Out()
+ }
+ }
+ p.P(`default:`)
+ p.In()
+ p.P(`panic(fmt.Sprintf("compare: unexpected type %T in oneof", that1.`, fieldname, `))`)
+ p.Out()
+ p.P(`}`)
+
+ p.P(`if thisType == that1Type {`)
+ p.In()
+ p.P(`if c := this.`, fieldname, `.Compare(that1.`, fieldname, `); c != 0 {`)
+ p.In()
+ p.P(`return c`)
+ p.Out()
+ p.P(`}`)
+ p.Out()
+ p.P(`} else if thisType < that1Type {`)
+ p.In()
+ p.P(`return -1`)
+ p.Out()
+ p.P(`} else if thisType > that1Type {`)
+ p.In()
+ p.P(`return 1`)
+ p.Out()
+ p.P(`}`)
+ p.Out()
+ p.P(`}`)
+ } else {
+ p.generateField(file, message, field)
+ }
+ }
+ if message.DescriptorProto.HasExtension() {
+ if gogoproto.HasExtensionsMap(file.FileDescriptorProto, message.DescriptorProto) {
+ p.P(`thismap := `, p.protoPkg.Use(), `.GetUnsafeExtensionsMap(this)`)
+ p.P(`thatmap := `, p.protoPkg.Use(), `.GetUnsafeExtensionsMap(that1)`)
+ p.P(`extkeys := make([]int32, 0, len(thismap)+len(thatmap))`)
+ p.P(`for k, _ := range thismap {`)
+ p.In()
+ p.P(`extkeys = append(extkeys, k)`)
+ p.Out()
+ p.P(`}`)
+ p.P(`for k, _ := range thatmap {`)
+ p.In()
+ p.P(`if _, ok := thismap[k]; !ok {`)
+ p.In()
+ p.P(`extkeys = append(extkeys, k)`)
+ p.Out()
+ p.P(`}`)
+ p.Out()
+ p.P(`}`)
+ p.P(p.sortkeysPkg.Use(), `.Int32s(extkeys)`)
+ p.P(`for _, k := range extkeys {`)
+ p.In()
+ p.P(`if v, ok := thismap[k]; ok {`)
+ p.In()
+ p.P(`if v2, ok := thatmap[k]; ok {`)
+ p.In()
+ p.P(`if c := v.Compare(&v2); c != 0 {`)
+ p.In()
+ p.P(`return c`)
+ p.Out()
+ p.P(`}`)
+ p.Out()
+ p.P(`} else {`)
+ p.In()
+ p.P(`return 1`)
+ p.Out()
+ p.P(`}`)
+ p.Out()
+ p.P(`} else {`)
+ p.In()
+ p.P(`return -1`)
+ p.Out()
+ p.P(`}`)
+ p.Out()
+ p.P(`}`)
+ } else {
+ fieldname := "XXX_extensions"
+ p.P(`if c := `, p.bytesPkg.Use(), `.Compare(this.`, fieldname, `, that1.`, fieldname, `); c != 0 {`)
+ p.In()
+ p.P(`return c`)
+ p.Out()
+ p.P(`}`)
+ }
+ }
+ if gogoproto.HasUnrecognized(file.FileDescriptorProto, message.DescriptorProto) {
+ fieldname := "XXX_unrecognized"
+ p.P(`if c := `, p.bytesPkg.Use(), `.Compare(this.`, fieldname, `, that1.`, fieldname, `); c != 0 {`)
+ p.In()
+ p.P(`return c`)
+ p.Out()
+ p.P(`}`)
+ }
+ p.P(`return 0`)
+ p.Out()
+ p.P(`}`)
+
+ //Generate Compare methods for oneof fields
+ m := proto.Clone(message.DescriptorProto).(*descriptor.DescriptorProto)
+ for _, field := range m.Field {
+ oneof := field.OneofIndex != nil
+ if !oneof {
+ continue
+ }
+ ccTypeName := p.OneOfTypeName(message, field)
+ p.P(`func (this *`, ccTypeName, `) Compare(that interface{}) int {`)
+ p.In()
+
+ p.generateMsgNullAndTypeCheck(ccTypeName)
+ vanity.TurnOffNullableForNativeTypes(field)
+ p.generateField(file, message, field)
+
+ p.P(`return 0`)
+ p.Out()
+ p.P(`}`)
+ }
+}
+
+func init() {
+ generator.RegisterPlugin(NewPlugin())
+}
diff --git a/vendor/github.com/gogo/protobuf/plugin/compare/comparetest.go b/vendor/github.com/gogo/protobuf/plugin/compare/comparetest.go
new file mode 100644
index 00000000000..4fbdbc633cd
--- /dev/null
+++ b/vendor/github.com/gogo/protobuf/plugin/compare/comparetest.go
@@ -0,0 +1,118 @@
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2013, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// 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.
+//
+// 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 compare
+
+import (
+ "github.com/gogo/protobuf/gogoproto"
+ "github.com/gogo/protobuf/plugin/testgen"
+ "github.com/gogo/protobuf/protoc-gen-gogo/generator"
+)
+
+type test struct {
+ *generator.Generator
+}
+
+func NewTest(g *generator.Generator) testgen.TestPlugin {
+ return &test{g}
+}
+
+func (p *test) Generate(imports generator.PluginImports, file *generator.FileDescriptor) bool {
+ used := false
+ randPkg := imports.NewImport("math/rand")
+ timePkg := imports.NewImport("time")
+ testingPkg := imports.NewImport("testing")
+ protoPkg := imports.NewImport("github.com/gogo/protobuf/proto")
+ unsafePkg := imports.NewImport("unsafe")
+ if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
+ protoPkg = imports.NewImport("github.com/golang/protobuf/proto")
+ }
+ for _, message := range file.Messages() {
+ ccTypeName := generator.CamelCaseSlice(message.TypeName())
+ if !gogoproto.HasCompare(file.FileDescriptorProto, message.DescriptorProto) {
+ continue
+ }
+ if message.DescriptorProto.GetOptions().GetMapEntry() {
+ continue
+ }
+
+ if gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
+ used = true
+ hasUnsafe := gogoproto.IsUnsafeMarshaler(file.FileDescriptorProto, message.DescriptorProto) ||
+ gogoproto.IsUnsafeUnmarshaler(file.FileDescriptorProto, message.DescriptorProto)
+ p.P(`func Test`, ccTypeName, `Compare(t *`, testingPkg.Use(), `.T) {`)
+ p.In()
+ if hasUnsafe {
+ p.P(`var bigendian uint32 = 0x01020304`)
+ p.P(`if *(*byte)(`, unsafePkg.Use(), `.Pointer(&bigendian)) == 1 {`)
+ p.In()
+ p.P(`t.Skip("unsafe does not work on big endian architectures")`)
+ p.Out()
+ p.P(`}`)
+ }
+ p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(`, timePkg.Use(), `.Now().UnixNano()))`)
+ p.P(`p := NewPopulated`, ccTypeName, `(popr, false)`)
+ p.P(`dAtA, err := `, protoPkg.Use(), `.Marshal(p)`)
+ p.P(`if err != nil {`)
+ p.In()
+ p.P(`panic(err)`)
+ p.Out()
+ p.P(`}`)
+ p.P(`msg := &`, ccTypeName, `{}`)
+ p.P(`if err := `, protoPkg.Use(), `.Unmarshal(dAtA, msg); err != nil {`)
+ p.In()
+ p.P(`panic(err)`)
+ p.Out()
+ p.P(`}`)
+ p.P(`if c := p.Compare(msg); c != 0 {`)
+ p.In()
+ p.P(`t.Fatalf("%#v !Compare %#v, since %d", msg, p, c)`)
+ p.Out()
+ p.P(`}`)
+ p.P(`p2 := NewPopulated`, ccTypeName, `(popr, false)`)
+ p.P(`c := p.Compare(p2)`)
+ p.P(`c2 := p2.Compare(p)`)
+ p.P(`if c != (-1 * c2) {`)
+ p.In()
+ p.P(`t.Errorf("p.Compare(p2) = %d", c)`)
+ p.P(`t.Errorf("p2.Compare(p) = %d", c2)`)
+ p.P(`t.Errorf("p = %#v", p)`)
+ p.P(`t.Errorf("p2 = %#v", p2)`)
+ p.Out()
+ p.P(`}`)
+ p.Out()
+ p.P(`}`)
+ }
+
+ }
+ return used
+}
+
+func init() {
+ testgen.RegisterTestPlugin(NewTest)
+}
diff --git a/vendor/github.com/gogo/protobuf/plugin/defaultcheck/defaultcheck.go b/vendor/github.com/gogo/protobuf/plugin/defaultcheck/defaultcheck.go
new file mode 100644
index 00000000000..486f2877192
--- /dev/null
+++ b/vendor/github.com/gogo/protobuf/plugin/defaultcheck/defaultcheck.go
@@ -0,0 +1,133 @@
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2013, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// 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.
+//
+// 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.
+
+/*
+The defaultcheck plugin is used to check whether nullable is not used incorrectly.
+For instance:
+An error is caused if a nullable field:
+ - has a default value,
+ - is an enum which does not start at zero,
+ - is used for an extension,
+ - is used for a native proto3 type,
+ - is used for a repeated native type.
+
+An error is also caused if a field with a default value is used in a message:
+ - which is a face.
+ - without getters.
+
+It is enabled by the following extensions:
+
+ - nullable
+
+For incorrect usage of nullable with tests see:
+
+ github.com/gogo/protobuf/test/nullableconflict
+
+*/
+package defaultcheck
+
+import (
+ "fmt"
+ "github.com/gogo/protobuf/gogoproto"
+ "github.com/gogo/protobuf/protoc-gen-gogo/generator"
+ "os"
+)
+
+type plugin struct {
+ *generator.Generator
+}
+
+func NewPlugin() *plugin {
+ return &plugin{}
+}
+
+func (p *plugin) Name() string {
+ return "defaultcheck"
+}
+
+func (p *plugin) Init(g *generator.Generator) {
+ p.Generator = g
+}
+
+func (p *plugin) Generate(file *generator.FileDescriptor) {
+ proto3 := gogoproto.IsProto3(file.FileDescriptorProto)
+ for _, msg := range file.Messages() {
+ getters := gogoproto.HasGoGetters(file.FileDescriptorProto, msg.DescriptorProto)
+ face := gogoproto.IsFace(file.FileDescriptorProto, msg.DescriptorProto)
+ for _, field := range msg.GetField() {
+ if len(field.GetDefaultValue()) > 0 {
+ if !getters {
+ fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot have a default value and not have a getter method", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
+ os.Exit(1)
+ }
+ if face {
+ fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot have a default value be in a face", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
+ os.Exit(1)
+ }
+ }
+ if gogoproto.IsNullable(field) {
+ continue
+ }
+ if len(field.GetDefaultValue()) > 0 {
+ fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot be non-nullable and have a default value", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
+ os.Exit(1)
+ }
+ if !field.IsMessage() && !gogoproto.IsCustomType(field) {
+ if field.IsRepeated() {
+ fmt.Fprintf(os.Stderr, "WARNING: field %v.%v is a repeated non-nullable native type, nullable=false has no effect\n", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
+ } else if proto3 {
+ fmt.Fprintf(os.Stderr, "ERROR: field %v.%v is a native type and in proto3 syntax with nullable=false there exists conflicting implementations when encoding zero values", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
+ os.Exit(1)
+ }
+ if field.IsBytes() {
+ fmt.Fprintf(os.Stderr, "WARNING: field %v.%v is a non-nullable bytes type, nullable=false has no effect\n", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
+ }
+ }
+ if !field.IsEnum() {
+ continue
+ }
+ enum := p.ObjectNamed(field.GetTypeName()).(*generator.EnumDescriptor)
+ if len(enum.Value) == 0 || enum.Value[0].GetNumber() != 0 {
+ fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot be non-nullable and be an enum type %v which does not start with zero", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name), enum.GetName())
+ os.Exit(1)
+ }
+ }
+ }
+ for _, e := range file.GetExtension() {
+ if !gogoproto.IsNullable(e) {
+ fmt.Fprintf(os.Stderr, "ERROR: extended field %v cannot be nullable %v", generator.CamelCase(e.GetName()), generator.CamelCase(*e.Name))
+ os.Exit(1)
+ }
+ }
+}
+
+func (p *plugin) GenerateImports(*generator.FileDescriptor) {}
+
+func init() {
+ generator.RegisterPlugin(NewPlugin())
+}
diff --git a/vendor/github.com/gogo/protobuf/plugin/description/description.go b/vendor/github.com/gogo/protobuf/plugin/description/description.go
new file mode 100644
index 00000000000..f72efba6128
--- /dev/null
+++ b/vendor/github.com/gogo/protobuf/plugin/description/description.go
@@ -0,0 +1,201 @@
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2013, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// 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.
+//
+// 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.
+
+/*
+The description (experimental) plugin generates a Description method for each message.
+The Description method returns a populated google_protobuf.FileDescriptorSet struct.
+This contains the description of the files used to generate this message.
+
+It is enabled by the following extensions:
+
+ - description
+ - description_all
+
+The description plugin also generates a test given it is enabled using one of the following extensions:
+
+ - testgen
+ - testgen_all
+
+Let us look at:
+
+ github.com/gogo/protobuf/test/example/example.proto
+
+Btw all the output can be seen at:
+
+ github.com/gogo/protobuf/test/example/*
+
+The following message:
+
+ message B {
+ option (gogoproto.description) = true;
+ optional A A = 1 [(gogoproto.nullable) = false, (gogoproto.embed) = true];
+ repeated bytes G = 2 [(gogoproto.customtype) = "github.com/gogo/protobuf/test/custom.Uint128", (gogoproto.nullable) = false];
+ }
+
+given to the description plugin, will generate the following code:
+
+ func (this *B) Description() (desc *google_protobuf.FileDescriptorSet) {
+ return ExampleDescription()
+ }
+
+and the following test code:
+
+ func TestDescription(t *testing9.T) {
+ ExampleDescription()
+ }
+
+The hope is to use this struct in some way instead of reflect.
+This package is subject to change, since a use has not been figured out yet.
+
+*/
+package description
+
+import (
+ "bytes"
+ "compress/gzip"
+ "fmt"
+ "github.com/gogo/protobuf/gogoproto"
+ "github.com/gogo/protobuf/proto"
+ descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
+ "github.com/gogo/protobuf/protoc-gen-gogo/generator"
+)
+
+type plugin struct {
+ *generator.Generator
+ generator.PluginImports
+}
+
+func NewPlugin() *plugin {
+ return &plugin{}
+}
+
+func (p *plugin) Name() string {
+ return "description"
+}
+
+func (p *plugin) Init(g *generator.Generator) {
+ p.Generator = g
+}
+
+func (p *plugin) Generate(file *generator.FileDescriptor) {
+ used := false
+ localName := generator.FileName(file)
+
+ p.PluginImports = generator.NewPluginImports(p.Generator)
+ descriptorPkg := p.NewImport("github.com/gogo/protobuf/protoc-gen-gogo/descriptor")
+ protoPkg := p.NewImport("github.com/gogo/protobuf/proto")
+ gzipPkg := p.NewImport("compress/gzip")
+ bytesPkg := p.NewImport("bytes")
+ ioutilPkg := p.NewImport("io/ioutil")
+
+ for _, message := range file.Messages() {
+ if !gogoproto.HasDescription(file.FileDescriptorProto, message.DescriptorProto) {
+ continue
+ }
+ if message.DescriptorProto.GetOptions().GetMapEntry() {
+ continue
+ }
+ used = true
+ ccTypeName := generator.CamelCaseSlice(message.TypeName())
+ p.P(`func (this *`, ccTypeName, `) Description() (desc *`, descriptorPkg.Use(), `.FileDescriptorSet) {`)
+ p.In()
+ p.P(`return `, localName, `Description()`)
+ p.Out()
+ p.P(`}`)
+ }
+
+ if used {
+
+ p.P(`func `, localName, `Description() (desc *`, descriptorPkg.Use(), `.FileDescriptorSet) {`)
+ p.In()
+ //Don't generate SourceCodeInfo, since it will create too much code.
+
+ ss := make([]*descriptor.SourceCodeInfo, 0)
+ for _, f := range p.Generator.AllFiles().GetFile() {
+ ss = append(ss, f.SourceCodeInfo)
+ f.SourceCodeInfo = nil
+ }
+ b, err := proto.Marshal(p.Generator.AllFiles())
+ if err != nil {
+ panic(err)
+ }
+ for i, f := range p.Generator.AllFiles().GetFile() {
+ f.SourceCodeInfo = ss[i]
+ }
+ p.P(`d := &`, descriptorPkg.Use(), `.FileDescriptorSet{}`)
+ var buf bytes.Buffer
+ w, _ := gzip.NewWriterLevel(&buf, gzip.BestCompression)
+ w.Write(b)
+ w.Close()
+ b = buf.Bytes()
+ p.P("var gzipped = []byte{")
+ p.In()
+ p.P("// ", len(b), " bytes of a gzipped FileDescriptorSet")
+ for len(b) > 0 {
+ n := 16
+ if n > len(b) {
+ n = len(b)
+ }
+
+ s := ""
+ for _, c := range b[:n] {
+ s += fmt.Sprintf("0x%02x,", c)
+ }
+ p.P(s)
+
+ b = b[n:]
+ }
+ p.Out()
+ p.P("}")
+ p.P(`r := `, bytesPkg.Use(), `.NewReader(gzipped)`)
+ p.P(`gzipr, err := `, gzipPkg.Use(), `.NewReader(r)`)
+ p.P(`if err != nil {`)
+ p.In()
+ p.P(`panic(err)`)
+ p.Out()
+ p.P(`}`)
+ p.P(`ungzipped, err := `, ioutilPkg.Use(), `.ReadAll(gzipr)`)
+ p.P(`if err != nil {`)
+ p.In()
+ p.P(`panic(err)`)
+ p.Out()
+ p.P(`}`)
+ p.P(`if err := `, protoPkg.Use(), `.Unmarshal(ungzipped, d); err != nil {`)
+ p.In()
+ p.P(`panic(err)`)
+ p.Out()
+ p.P(`}`)
+ p.P(`return d`)
+ p.Out()
+ p.P(`}`)
+ }
+}
+
+func init() {
+ generator.RegisterPlugin(NewPlugin())
+}
diff --git a/vendor/github.com/gogo/protobuf/plugin/description/descriptiontest.go b/vendor/github.com/gogo/protobuf/plugin/description/descriptiontest.go
new file mode 100644
index 00000000000..babcd311da4
--- /dev/null
+++ b/vendor/github.com/gogo/protobuf/plugin/description/descriptiontest.go
@@ -0,0 +1,73 @@
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2013, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// 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.
+//
+// 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 description
+
+import (
+ "github.com/gogo/protobuf/gogoproto"
+ "github.com/gogo/protobuf/plugin/testgen"
+ "github.com/gogo/protobuf/protoc-gen-gogo/generator"
+)
+
+type test struct {
+ *generator.Generator
+}
+
+func NewTest(g *generator.Generator) testgen.TestPlugin {
+ return &test{g}
+}
+
+func (p *test) Generate(imports generator.PluginImports, file *generator.FileDescriptor) bool {
+ used := false
+ testingPkg := imports.NewImport("testing")
+ for _, message := range file.Messages() {
+ if !gogoproto.HasDescription(file.FileDescriptorProto, message.DescriptorProto) ||
+ !gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
+ continue
+ }
+ if message.DescriptorProto.GetOptions().GetMapEntry() {
+ continue
+ }
+ used = true
+ }
+
+ if used {
+ localName := generator.FileName(file)
+ p.P(`func Test`, localName, `Description(t *`, testingPkg.Use(), `.T) {`)
+ p.In()
+ p.P(localName, `Description()`)
+ p.Out()
+ p.P(`}`)
+
+ }
+ return used
+}
+
+func init() {
+ testgen.RegisterTestPlugin(NewTest)
+}
diff --git a/vendor/github.com/gogo/protobuf/plugin/embedcheck/embedcheck.go b/vendor/github.com/gogo/protobuf/plugin/embedcheck/embedcheck.go
new file mode 100644
index 00000000000..bc68efe12c7
--- /dev/null
+++ b/vendor/github.com/gogo/protobuf/plugin/embedcheck/embedcheck.go
@@ -0,0 +1,200 @@
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2013, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// 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.
+//
+// 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.
+
+/*
+The embedcheck plugin is used to check whether embed is not used incorrectly.
+For instance:
+An embedded message has a generated string method, but the is a member of a message which does not.
+This causes a warning.
+An error is caused by a namespace conflict.
+
+It is enabled by the following extensions:
+
+ - embed
+ - embed_all
+
+For incorrect usage of embed with tests see:
+
+ github.com/gogo/protobuf/test/embedconflict
+
+*/
+package embedcheck
+
+import (
+ "fmt"
+ "os"
+
+ "github.com/gogo/protobuf/gogoproto"
+ "github.com/gogo/protobuf/protoc-gen-gogo/generator"
+)
+
+type plugin struct {
+ *generator.Generator
+}
+
+func NewPlugin() *plugin {
+ return &plugin{}
+}
+
+func (p *plugin) Name() string {
+ return "embedcheck"
+}
+
+func (p *plugin) Init(g *generator.Generator) {
+ p.Generator = g
+}
+
+var overwriters []map[string]gogoproto.EnableFunc = []map[string]gogoproto.EnableFunc{
+ {
+ "stringer": gogoproto.IsStringer,
+ },
+ {
+ "gostring": gogoproto.HasGoString,
+ },
+ {
+ "equal": gogoproto.HasEqual,
+ },
+ {
+ "verboseequal": gogoproto.HasVerboseEqual,
+ },
+ {
+ "size": gogoproto.IsSizer,
+ "protosizer": gogoproto.IsProtoSizer,
+ },
+ {
+ "unmarshaler": gogoproto.IsUnmarshaler,
+ "unsafe_unmarshaler": gogoproto.IsUnsafeUnmarshaler,
+ },
+ {
+ "marshaler": gogoproto.IsMarshaler,
+ "unsafe_marshaler": gogoproto.IsUnsafeMarshaler,
+ },
+}
+
+func (p *plugin) Generate(file *generator.FileDescriptor) {
+ for _, msg := range file.Messages() {
+ for _, os := range overwriters {
+ possible := true
+ for _, overwriter := range os {
+ if overwriter(file.FileDescriptorProto, msg.DescriptorProto) {
+ possible = false
+ }
+ }
+ if possible {
+ p.checkOverwrite(msg, os)
+ }
+ }
+ p.checkNameSpace(msg)
+ for _, field := range msg.GetField() {
+ if gogoproto.IsEmbed(field) && gogoproto.IsCustomName(field) {
+ fmt.Fprintf(os.Stderr, "ERROR: field %v with custom name %v cannot be embedded", *field.Name, gogoproto.GetCustomName(field))
+ os.Exit(1)
+ }
+ }
+ p.checkRepeated(msg)
+ }
+ for _, e := range file.GetExtension() {
+ if gogoproto.IsEmbed(e) {
+ fmt.Fprintf(os.Stderr, "ERROR: extended field %v cannot be embedded", generator.CamelCase(*e.Name))
+ os.Exit(1)
+ }
+ }
+}
+
+func (p *plugin) checkNameSpace(message *generator.Descriptor) map[string]bool {
+ ccTypeName := generator.CamelCaseSlice(message.TypeName())
+ names := make(map[string]bool)
+ for _, field := range message.Field {
+ fieldname := generator.CamelCase(*field.Name)
+ if field.IsMessage() && gogoproto.IsEmbed(field) {
+ desc := p.ObjectNamed(field.GetTypeName())
+ moreNames := p.checkNameSpace(desc.(*generator.Descriptor))
+ for another := range moreNames {
+ if names[another] {
+ fmt.Fprintf(os.Stderr, "ERROR: duplicate embedded fieldname %v in type %v\n", fieldname, ccTypeName)
+ os.Exit(1)
+ }
+ names[another] = true
+ }
+ } else {
+ if names[fieldname] {
+ fmt.Fprintf(os.Stderr, "ERROR: duplicate embedded fieldname %v in type %v\n", fieldname, ccTypeName)
+ os.Exit(1)
+ }
+ names[fieldname] = true
+ }
+ }
+ return names
+}
+
+func (p *plugin) checkOverwrite(message *generator.Descriptor, enablers map[string]gogoproto.EnableFunc) {
+ ccTypeName := generator.CamelCaseSlice(message.TypeName())
+ names := []string{}
+ for name := range enablers {
+ names = append(names, name)
+ }
+ for _, field := range message.Field {
+ if field.IsMessage() && gogoproto.IsEmbed(field) {
+ fieldname := generator.CamelCase(*field.Name)
+ desc := p.ObjectNamed(field.GetTypeName())
+ msg := desc.(*generator.Descriptor)
+ for errStr, enabled := range enablers {
+ if enabled(msg.File().FileDescriptorProto, msg.DescriptorProto) {
+ fmt.Fprintf(os.Stderr, "WARNING: found non-%v %v with embedded %v %v\n", names, ccTypeName, errStr, fieldname)
+ }
+ }
+ p.checkOverwrite(msg, enablers)
+ }
+ }
+}
+
+func (p *plugin) checkRepeated(message *generator.Descriptor) {
+ ccTypeName := generator.CamelCaseSlice(message.TypeName())
+ for _, field := range message.Field {
+ if !gogoproto.IsEmbed(field) {
+ continue
+ }
+ if field.IsBytes() {
+ fieldname := generator.CamelCase(*field.Name)
+ fmt.Fprintf(os.Stderr, "ERROR: found embedded bytes field %s in message %s\n", fieldname, ccTypeName)
+ os.Exit(1)
+ }
+ if !field.IsRepeated() {
+ continue
+ }
+ fieldname := generator.CamelCase(*field.Name)
+ fmt.Fprintf(os.Stderr, "ERROR: found repeated embedded field %s in message %s\n", fieldname, ccTypeName)
+ os.Exit(1)
+ }
+}
+
+func (p *plugin) GenerateImports(*generator.FileDescriptor) {}
+
+func init() {
+ generator.RegisterPlugin(NewPlugin())
+}
diff --git a/vendor/github.com/gogo/protobuf/plugin/enumstringer/enumstringer.go b/vendor/github.com/gogo/protobuf/plugin/enumstringer/enumstringer.go
new file mode 100644
index 00000000000..04d6e547fc3
--- /dev/null
+++ b/vendor/github.com/gogo/protobuf/plugin/enumstringer/enumstringer.go
@@ -0,0 +1,104 @@
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2013, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// 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.
+//
+// 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.
+
+/*
+The enumstringer (experimental) plugin generates a String method for each enum.
+
+It is enabled by the following extensions:
+
+ - enum_stringer
+ - enum_stringer_all
+
+This package is subject to change.
+
+*/
+package enumstringer
+
+import (
+ "github.com/gogo/protobuf/gogoproto"
+ "github.com/gogo/protobuf/protoc-gen-gogo/generator"
+)
+
+type enumstringer struct {
+ *generator.Generator
+ generator.PluginImports
+ atleastOne bool
+ localName string
+}
+
+func NewEnumStringer() *enumstringer {
+ return &enumstringer{}
+}
+
+func (p *enumstringer) Name() string {
+ return "enumstringer"
+}
+
+func (p *enumstringer) Init(g *generator.Generator) {
+ p.Generator = g
+}
+
+func (p *enumstringer) Generate(file *generator.FileDescriptor) {
+ p.PluginImports = generator.NewPluginImports(p.Generator)
+ p.atleastOne = false
+
+ p.localName = generator.FileName(file)
+
+ strconvPkg := p.NewImport("strconv")
+
+ for _, enum := range file.Enums() {
+ if !gogoproto.IsEnumStringer(file.FileDescriptorProto, enum.EnumDescriptorProto) {
+ continue
+ }
+ if gogoproto.IsGoEnumStringer(file.FileDescriptorProto, enum.EnumDescriptorProto) {
+ panic("Go enum stringer conflicts with new enumstringer plugin: please use gogoproto.goproto_enum_stringer or gogoproto.goproto_enum_string_all and set it to false")
+ }
+ p.atleastOne = true
+ ccTypeName := generator.CamelCaseSlice(enum.TypeName())
+ p.P("func (x ", ccTypeName, ") String() string {")
+ p.In()
+ p.P(`s, ok := `, ccTypeName, `_name[int32(x)]`)
+ p.P(`if ok {`)
+ p.In()
+ p.P(`return s`)
+ p.Out()
+ p.P(`}`)
+ p.P(`return `, strconvPkg.Use(), `.Itoa(int(x))`)
+ p.Out()
+ p.P(`}`)
+ }
+
+ if !p.atleastOne {
+ return
+ }
+
+}
+
+func init() {
+ generator.RegisterPlugin(NewEnumStringer())
+}
diff --git a/vendor/github.com/gogo/protobuf/plugin/equal/equal.go b/vendor/github.com/gogo/protobuf/plugin/equal/equal.go
new file mode 100644
index 00000000000..6358fc99ad1
--- /dev/null
+++ b/vendor/github.com/gogo/protobuf/plugin/equal/equal.go
@@ -0,0 +1,694 @@
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2013, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// 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.
+//
+// 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.
+
+/*
+The equal plugin generates an Equal and a VerboseEqual method for each message.
+These equal methods are quite obvious.
+The only difference is that VerboseEqual returns a non nil error if it is not equal.
+This error contains more detail on exactly which part of the message was not equal to the other message.
+The idea is that this is useful for debugging.
+
+Equal is enabled using the following extensions:
+
+ - equal
+ - equal_all
+
+While VerboseEqual is enable dusing the following extensions:
+
+ - verbose_equal
+ - verbose_equal_all
+
+The equal plugin also generates a test given it is enabled using one of the following extensions:
+
+ - testgen
+ - testgen_all
+
+Let us look at:
+
+ github.com/gogo/protobuf/test/example/example.proto
+
+Btw all the output can be seen at:
+
+ github.com/gogo/protobuf/test/example/*
+
+The following message:
+
+ option (gogoproto.equal_all) = true;
+ option (gogoproto.verbose_equal_all) = true;
+
+ message B {
+ optional A A = 1 [(gogoproto.nullable) = false, (gogoproto.embed) = true];
+ repeated bytes G = 2 [(gogoproto.customtype) = "github.com/gogo/protobuf/test/custom.Uint128", (gogoproto.nullable) = false];
+ }
+
+given to the equal plugin, will generate the following code:
+
+ func (this *B) VerboseEqual(that interface{}) error {
+ if that == nil {
+ if this == nil {
+ return nil
+ }
+ return fmt2.Errorf("that == nil && this != nil")
+ }
+
+ that1, ok := that.(*B)
+ if !ok {
+ return fmt2.Errorf("that is not of type *B")
+ }
+ if that1 == nil {
+ if this == nil {
+ return nil
+ }
+ return fmt2.Errorf("that is type *B but is nil && this != nil")
+ } else if this == nil {
+ return fmt2.Errorf("that is type *B but is not nil && this == nil")
+ }
+ if !this.A.Equal(&that1.A) {
+ return fmt2.Errorf("A this(%v) Not Equal that(%v)", this.A, that1.A)
+ }
+ if len(this.G) != len(that1.G) {
+ return fmt2.Errorf("G this(%v) Not Equal that(%v)", len(this.G), len(that1.G))
+ }
+ for i := range this.G {
+ if !this.G[i].Equal(that1.G[i]) {
+ return fmt2.Errorf("G this[%v](%v) Not Equal that[%v](%v)", i, this.G[i], i, that1.G[i])
+ }
+ }
+ if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) {
+ return fmt2.Errorf("XXX_unrecognized this(%v) Not Equal that(%v)", this.XXX_unrecognized, that1.XXX_unrecognized)
+ }
+ return nil
+ }
+
+ func (this *B) Equal(that interface{}) bool {
+ if that == nil {
+ return this == nil
+ }
+
+ that1, ok := that.(*B)
+ if !ok {
+ return false
+ }
+ if that1 == nil {
+ return this == nil
+ } else if this == nil {
+ return false
+ }
+ if !this.A.Equal(&that1.A) {
+ return false
+ }
+ if len(this.G) != len(that1.G) {
+ return false
+ }
+ for i := range this.G {
+ if !this.G[i].Equal(that1.G[i]) {
+ return false
+ }
+ }
+ if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) {
+ return false
+ }
+ return true
+ }
+
+and the following test code:
+
+ func TestBVerboseEqual(t *testing8.T) {
+ popr := math_rand8.New(math_rand8.NewSource(time8.Now().UnixNano()))
+ p := NewPopulatedB(popr, false)
+ dAtA, err := github_com_gogo_protobuf_proto2.Marshal(p)
+ if err != nil {
+ panic(err)
+ }
+ msg := &B{}
+ if err := github_com_gogo_protobuf_proto2.Unmarshal(dAtA, msg); err != nil {
+ panic(err)
+ }
+ if err := p.VerboseEqual(msg); err != nil {
+ t.Fatalf("%#v !VerboseEqual %#v, since %v", msg, p, err)
+ }
+
+*/
+package equal
+
+import (
+ "github.com/gogo/protobuf/gogoproto"
+ "github.com/gogo/protobuf/proto"
+ descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
+ "github.com/gogo/protobuf/protoc-gen-gogo/generator"
+ "github.com/gogo/protobuf/vanity"
+)
+
+type plugin struct {
+ *generator.Generator
+ generator.PluginImports
+ fmtPkg generator.Single
+ bytesPkg generator.Single
+ protoPkg generator.Single
+}
+
+func NewPlugin() *plugin {
+ return &plugin{}
+}
+
+func (p *plugin) Name() string {
+ return "equal"
+}
+
+func (p *plugin) Init(g *generator.Generator) {
+ p.Generator = g
+}
+
+func (p *plugin) Generate(file *generator.FileDescriptor) {
+ p.PluginImports = generator.NewPluginImports(p.Generator)
+ p.fmtPkg = p.NewImport("fmt")
+ p.bytesPkg = p.NewImport("bytes")
+ p.protoPkg = p.NewImport("github.com/gogo/protobuf/proto")
+
+ for _, msg := range file.Messages() {
+ if msg.DescriptorProto.GetOptions().GetMapEntry() {
+ continue
+ }
+ if gogoproto.HasVerboseEqual(file.FileDescriptorProto, msg.DescriptorProto) {
+ p.generateMessage(file, msg, true)
+ }
+ if gogoproto.HasEqual(file.FileDescriptorProto, msg.DescriptorProto) {
+ p.generateMessage(file, msg, false)
+ }
+ }
+}
+
+func (p *plugin) generateNullableField(fieldname string, verbose bool) {
+ p.P(`if this.`, fieldname, ` != nil && that1.`, fieldname, ` != nil {`)
+ p.In()
+ p.P(`if *this.`, fieldname, ` != *that1.`, fieldname, `{`)
+ p.In()
+ if verbose {
+ p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, ` this(%v) Not Equal that(%v)", *this.`, fieldname, `, *that1.`, fieldname, `)`)
+ } else {
+ p.P(`return false`)
+ }
+ p.Out()
+ p.P(`}`)
+ p.Out()
+ p.P(`} else if this.`, fieldname, ` != nil {`)
+ p.In()
+ if verbose {
+ p.P(`return `, p.fmtPkg.Use(), `.Errorf("this.`, fieldname, ` == nil && that.`, fieldname, ` != nil")`)
+ } else {
+ p.P(`return false`)
+ }
+ p.Out()
+ p.P(`} else if that1.`, fieldname, ` != nil {`)
+}
+
+func (p *plugin) generateMsgNullAndTypeCheck(ccTypeName string, verbose bool) {
+ p.P(`if that == nil {`)
+ p.In()
+ if verbose {
+ p.P(`if this == nil {`)
+ p.In()
+ p.P(`return nil`)
+ p.Out()
+ p.P(`}`)
+ p.P(`return `, p.fmtPkg.Use(), `.Errorf("that == nil && this != nil")`)
+ } else {
+ p.P(`return this == nil`)
+ }
+ p.Out()
+ p.P(`}`)
+ p.P(``)
+ p.P(`that1, ok := that.(*`, ccTypeName, `)`)
+ p.P(`if !ok {`)
+ p.In()
+ p.P(`that2, ok := that.(`, ccTypeName, `)`)
+ p.P(`if ok {`)
+ p.In()
+ p.P(`that1 = &that2`)
+ p.Out()
+ p.P(`} else {`)
+ p.In()
+ if verbose {
+ p.P(`return `, p.fmtPkg.Use(), `.Errorf("that is not of type *`, ccTypeName, `")`)
+ } else {
+ p.P(`return false`)
+ }
+ p.Out()
+ p.P(`}`)
+ p.Out()
+ p.P(`}`)
+ p.P(`if that1 == nil {`)
+ p.In()
+ if verbose {
+ p.P(`if this == nil {`)
+ p.In()
+ p.P(`return nil`)
+ p.Out()
+ p.P(`}`)
+ p.P(`return `, p.fmtPkg.Use(), `.Errorf("that is type *`, ccTypeName, ` but is nil && this != nil")`)
+ } else {
+ p.P(`return this == nil`)
+ }
+ p.Out()
+ p.P(`} else if this == nil {`)
+ p.In()
+ if verbose {
+ p.P(`return `, p.fmtPkg.Use(), `.Errorf("that is type *`, ccTypeName, ` but is not nil && this == nil")`)
+ } else {
+ p.P(`return false`)
+ }
+ p.Out()
+ p.P(`}`)
+}
+
+func (p *plugin) generateField(file *generator.FileDescriptor, message *generator.Descriptor, field *descriptor.FieldDescriptorProto, verbose bool) {
+ proto3 := gogoproto.IsProto3(file.FileDescriptorProto)
+ fieldname := p.GetOneOfFieldName(message, field)
+ repeated := field.IsRepeated()
+ ctype := gogoproto.IsCustomType(field)
+ nullable := gogoproto.IsNullable(field)
+ isNormal := (gogoproto.IsStdDuration(field) ||
+ gogoproto.IsStdDouble(field) ||
+ gogoproto.IsStdFloat(field) ||
+ gogoproto.IsStdInt64(field) ||
+ gogoproto.IsStdUInt64(field) ||
+ gogoproto.IsStdInt32(field) ||
+ gogoproto.IsStdUInt32(field) ||
+ gogoproto.IsStdBool(field) ||
+ gogoproto.IsStdString(field))
+ isBytes := gogoproto.IsStdBytes(field)
+ isTimestamp := gogoproto.IsStdTime(field)
+ // oneof := field.OneofIndex != nil
+ if !repeated {
+ if ctype || isTimestamp {
+ if nullable {
+ p.P(`if that1.`, fieldname, ` == nil {`)
+ p.In()
+ p.P(`if this.`, fieldname, ` != nil {`)
+ p.In()
+ if verbose {
+ p.P(`return `, p.fmtPkg.Use(), `.Errorf("this.`, fieldname, ` != nil && that1.`, fieldname, ` == nil")`)
+ } else {
+ p.P(`return false`)
+ }
+ p.Out()
+ p.P(`}`)
+ p.Out()
+ p.P(`} else if !this.`, fieldname, `.Equal(*that1.`, fieldname, `) {`)
+ } else {
+ p.P(`if !this.`, fieldname, `.Equal(that1.`, fieldname, `) {`)
+ }
+ p.In()
+ if verbose {
+ p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, ` this(%v) Not Equal that(%v)", this.`, fieldname, `, that1.`, fieldname, `)`)
+ } else {
+ p.P(`return false`)
+ }
+ p.Out()
+ p.P(`}`)
+ } else if isNormal {
+ if nullable {
+ p.generateNullableField(fieldname, verbose)
+ } else {
+ p.P(`if this.`, fieldname, ` != that1.`, fieldname, `{`)
+ }
+ p.In()
+ if verbose {
+ p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, ` this(%v) Not Equal that(%v)", this.`, fieldname, `, that1.`, fieldname, `)`)
+ } else {
+ p.P(`return false`)
+ }
+ p.Out()
+ p.P(`}`)
+ } else if isBytes {
+ if nullable {
+ p.P(`if that1.`, fieldname, ` == nil {`)
+ p.In()
+ p.P(`if this.`, fieldname, ` != nil {`)
+ p.In()
+ if verbose {
+ p.P(`return `, p.fmtPkg.Use(), `.Errorf("this.`, fieldname, ` != nil && that1.`, fieldname, ` == nil")`)
+ } else {
+ p.P(`return false`)
+ }
+ p.Out()
+ p.P(`}`)
+ p.Out()
+ p.P(`} else if !`, p.bytesPkg.Use(), `.Equal(*this.`, fieldname, `, *that1.`, fieldname, `) {`)
+ } else {
+ p.P(`if !`, p.bytesPkg.Use(), `.Equal(this.`, fieldname, `, that1.`, fieldname, `) {`)
+ }
+ p.In()
+ if verbose {
+ p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, ` this(%v) Not Equal that(%v)", this.`, fieldname, `, that1.`, fieldname, `)`)
+ } else {
+ p.P(`return false`)
+ }
+ p.Out()
+ p.P(`}`)
+ } else {
+ if field.IsMessage() || p.IsGroup(field) {
+ if nullable {
+ p.P(`if !this.`, fieldname, `.Equal(that1.`, fieldname, `) {`)
+ } else {
+ p.P(`if !this.`, fieldname, `.Equal(&that1.`, fieldname, `) {`)
+ }
+ } else if field.IsBytes() {
+ p.P(`if !`, p.bytesPkg.Use(), `.Equal(this.`, fieldname, `, that1.`, fieldname, `) {`)
+ } else if field.IsString() {
+ if nullable && !proto3 {
+ p.generateNullableField(fieldname, verbose)
+ } else {
+ p.P(`if this.`, fieldname, ` != that1.`, fieldname, `{`)
+ }
+ } else {
+ if nullable && !proto3 {
+ p.generateNullableField(fieldname, verbose)
+ } else {
+ p.P(`if this.`, fieldname, ` != that1.`, fieldname, `{`)
+ }
+ }
+ p.In()
+ if verbose {
+ p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, ` this(%v) Not Equal that(%v)", this.`, fieldname, `, that1.`, fieldname, `)`)
+ } else {
+ p.P(`return false`)
+ }
+ p.Out()
+ p.P(`}`)
+ }
+ } else {
+ p.P(`if len(this.`, fieldname, `) != len(that1.`, fieldname, `) {`)
+ p.In()
+ if verbose {
+ p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, ` this(%v) Not Equal that(%v)", len(this.`, fieldname, `), len(that1.`, fieldname, `))`)
+ } else {
+ p.P(`return false`)
+ }
+ p.Out()
+ p.P(`}`)
+ p.P(`for i := range this.`, fieldname, ` {`)
+ p.In()
+ if ctype && !p.IsMap(field) {
+ p.P(`if !this.`, fieldname, `[i].Equal(that1.`, fieldname, `[i]) {`)
+ } else if isTimestamp {
+ if nullable {
+ p.P(`if !this.`, fieldname, `[i].Equal(*that1.`, fieldname, `[i]) {`)
+ } else {
+ p.P(`if !this.`, fieldname, `[i].Equal(that1.`, fieldname, `[i]) {`)
+ }
+ } else if isNormal {
+ if nullable {
+ p.P(`if dthis, dthat := this.`, fieldname, `[i], that1.`, fieldname, `[i]; (dthis != nil && dthat != nil && *dthis != *dthat) || (dthis != nil && dthat == nil) || (dthis == nil && dthat != nil) {`)
+ } else {
+ p.P(`if this.`, fieldname, `[i] != that1.`, fieldname, `[i] {`)
+ }
+ } else if isBytes {
+ if nullable {
+ p.P(`if !`, p.bytesPkg.Use(), `.Equal(*this.`, fieldname, `[i], *that1.`, fieldname, `[i]) {`)
+ } else {
+ p.P(`if !`, p.bytesPkg.Use(), `.Equal(this.`, fieldname, `[i], that1.`, fieldname, `[i]) {`)
+ }
+ } else {
+ if p.IsMap(field) {
+ m := p.GoMapType(nil, field)
+ valuegoTyp, _ := p.GoType(nil, m.ValueField)
+ valuegoAliasTyp, _ := p.GoType(nil, m.ValueAliasField)
+ nullable, valuegoTyp, valuegoAliasTyp = generator.GoMapValueTypes(field, m.ValueField, valuegoTyp, valuegoAliasTyp)
+
+ mapValue := m.ValueAliasField
+ mapValueNormal := (gogoproto.IsStdDuration(mapValue) ||
+ gogoproto.IsStdDouble(mapValue) ||
+ gogoproto.IsStdFloat(mapValue) ||
+ gogoproto.IsStdInt64(mapValue) ||
+ gogoproto.IsStdUInt64(mapValue) ||
+ gogoproto.IsStdInt32(mapValue) ||
+ gogoproto.IsStdUInt32(mapValue) ||
+ gogoproto.IsStdBool(mapValue) ||
+ gogoproto.IsStdString(mapValue))
+ mapValueBytes := gogoproto.IsStdBytes(mapValue)
+ if mapValue.IsMessage() || p.IsGroup(mapValue) {
+ if nullable && valuegoTyp == valuegoAliasTyp {
+ p.P(`if !this.`, fieldname, `[i].Equal(that1.`, fieldname, `[i]) {`)
+ } else {
+ // Equal() has a pointer receiver, but map value is a value type
+ a := `this.` + fieldname + `[i]`
+ b := `that1.` + fieldname + `[i]`
+ if !mapValueNormal && !mapValueBytes && valuegoTyp != valuegoAliasTyp {
+ // cast back to the type that has the generated methods on it
+ a = `(` + valuegoTyp + `)(` + a + `)`
+ b = `(` + valuegoTyp + `)(` + b + `)`
+ }
+ p.P(`a := `, a)
+ p.P(`b := `, b)
+ if mapValueNormal {
+ if nullable {
+ p.P(`if *a != *b {`)
+ } else {
+ p.P(`if a != b {`)
+ }
+ } else if mapValueBytes {
+ if nullable {
+ p.P(`if !`, p.bytesPkg.Use(), `.Equal(*a, *b) {`)
+ } else {
+ p.P(`if !`, p.bytesPkg.Use(), `.Equal(a, b) {`)
+ }
+ } else if nullable {
+ p.P(`if !a.Equal(b) {`)
+ } else {
+ p.P(`if !(&a).Equal(&b) {`)
+ }
+ }
+ } else if mapValue.IsBytes() {
+ if ctype {
+ if nullable {
+ p.P(`if !this.`, fieldname, `[i].Equal(*that1.`, fieldname, `[i]) { //nullable`)
+ } else {
+ p.P(`if !this.`, fieldname, `[i].Equal(that1.`, fieldname, `[i]) { //not nullable`)
+ }
+ } else {
+ p.P(`if !`, p.bytesPkg.Use(), `.Equal(this.`, fieldname, `[i], that1.`, fieldname, `[i]) {`)
+ }
+ } else if mapValue.IsString() {
+ p.P(`if this.`, fieldname, `[i] != that1.`, fieldname, `[i] {`)
+ } else {
+ p.P(`if this.`, fieldname, `[i] != that1.`, fieldname, `[i] {`)
+ }
+ } else if field.IsMessage() || p.IsGroup(field) {
+ if nullable {
+ p.P(`if !this.`, fieldname, `[i].Equal(that1.`, fieldname, `[i]) {`)
+ } else {
+ p.P(`if !this.`, fieldname, `[i].Equal(&that1.`, fieldname, `[i]) {`)
+ }
+ } else if field.IsBytes() {
+ p.P(`if !`, p.bytesPkg.Use(), `.Equal(this.`, fieldname, `[i], that1.`, fieldname, `[i]) {`)
+ } else if field.IsString() {
+ p.P(`if this.`, fieldname, `[i] != that1.`, fieldname, `[i] {`)
+ } else {
+ p.P(`if this.`, fieldname, `[i] != that1.`, fieldname, `[i] {`)
+ }
+ }
+ p.In()
+ if verbose {
+ p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, ` this[%v](%v) Not Equal that[%v](%v)", i, this.`, fieldname, `[i], i, that1.`, fieldname, `[i])`)
+ } else {
+ p.P(`return false`)
+ }
+ p.Out()
+ p.P(`}`)
+ p.Out()
+ p.P(`}`)
+ }
+}
+
+func (p *plugin) generateMessage(file *generator.FileDescriptor, message *generator.Descriptor, verbose bool) {
+ ccTypeName := generator.CamelCaseSlice(message.TypeName())
+ if verbose {
+ p.P(`func (this *`, ccTypeName, `) VerboseEqual(that interface{}) error {`)
+ } else {
+ p.P(`func (this *`, ccTypeName, `) Equal(that interface{}) bool {`)
+ }
+ p.In()
+ p.generateMsgNullAndTypeCheck(ccTypeName, verbose)
+ oneofs := make(map[string]struct{})
+
+ for _, field := range message.Field {
+ oneof := field.OneofIndex != nil
+ if oneof {
+ fieldname := p.GetFieldName(message, field)
+ if _, ok := oneofs[fieldname]; ok {
+ continue
+ } else {
+ oneofs[fieldname] = struct{}{}
+ }
+ p.P(`if that1.`, fieldname, ` == nil {`)
+ p.In()
+ p.P(`if this.`, fieldname, ` != nil {`)
+ p.In()
+ if verbose {
+ p.P(`return `, p.fmtPkg.Use(), `.Errorf("this.`, fieldname, ` != nil && that1.`, fieldname, ` == nil")`)
+ } else {
+ p.P(`return false`)
+ }
+ p.Out()
+ p.P(`}`)
+ p.Out()
+ p.P(`} else if this.`, fieldname, ` == nil {`)
+ p.In()
+ if verbose {
+ p.P(`return `, p.fmtPkg.Use(), `.Errorf("this.`, fieldname, ` == nil && that1.`, fieldname, ` != nil")`)
+ } else {
+ p.P(`return false`)
+ }
+ p.Out()
+ if verbose {
+ p.P(`} else if err := this.`, fieldname, `.VerboseEqual(that1.`, fieldname, `); err != nil {`)
+ } else {
+ p.P(`} else if !this.`, fieldname, `.Equal(that1.`, fieldname, `) {`)
+ }
+ p.In()
+ if verbose {
+ p.P(`return err`)
+ } else {
+ p.P(`return false`)
+ }
+ p.Out()
+ p.P(`}`)
+ } else {
+ p.generateField(file, message, field, verbose)
+ }
+ }
+ if message.DescriptorProto.HasExtension() {
+ if gogoproto.HasExtensionsMap(file.FileDescriptorProto, message.DescriptorProto) {
+ fieldname := "XXX_InternalExtensions"
+ p.P(`thismap := `, p.protoPkg.Use(), `.GetUnsafeExtensionsMap(this)`)
+ p.P(`thatmap := `, p.protoPkg.Use(), `.GetUnsafeExtensionsMap(that1)`)
+ p.P(`for k, v := range thismap {`)
+ p.In()
+ p.P(`if v2, ok := thatmap[k]; ok {`)
+ p.In()
+ p.P(`if !v.Equal(&v2) {`)
+ p.In()
+ if verbose {
+ p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, ` this[%v](%v) Not Equal that[%v](%v)", k, thismap[k], k, thatmap[k])`)
+ } else {
+ p.P(`return false`)
+ }
+ p.Out()
+ p.P(`}`)
+ p.Out()
+ p.P(`} else {`)
+ p.In()
+ if verbose {
+ p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, `[%v] Not In that", k)`)
+ } else {
+ p.P(`return false`)
+ }
+ p.Out()
+ p.P(`}`)
+ p.Out()
+ p.P(`}`)
+
+ p.P(`for k, _ := range thatmap {`)
+ p.In()
+ p.P(`if _, ok := thismap[k]; !ok {`)
+ p.In()
+ if verbose {
+ p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, `[%v] Not In this", k)`)
+ } else {
+ p.P(`return false`)
+ }
+ p.Out()
+ p.P(`}`)
+ p.Out()
+ p.P(`}`)
+ } else {
+ fieldname := "XXX_extensions"
+ p.P(`if !`, p.bytesPkg.Use(), `.Equal(this.`, fieldname, `, that1.`, fieldname, `) {`)
+ p.In()
+ if verbose {
+ p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, ` this(%v) Not Equal that(%v)", this.`, fieldname, `, that1.`, fieldname, `)`)
+ } else {
+ p.P(`return false`)
+ }
+ p.Out()
+ p.P(`}`)
+ }
+ }
+ if gogoproto.HasUnrecognized(file.FileDescriptorProto, message.DescriptorProto) {
+ fieldname := "XXX_unrecognized"
+ p.P(`if !`, p.bytesPkg.Use(), `.Equal(this.`, fieldname, `, that1.`, fieldname, `) {`)
+ p.In()
+ if verbose {
+ p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, ` this(%v) Not Equal that(%v)", this.`, fieldname, `, that1.`, fieldname, `)`)
+ } else {
+ p.P(`return false`)
+ }
+ p.Out()
+ p.P(`}`)
+ }
+ if verbose {
+ p.P(`return nil`)
+ } else {
+ p.P(`return true`)
+ }
+ p.Out()
+ p.P(`}`)
+
+ //Generate Equal methods for oneof fields
+ m := proto.Clone(message.DescriptorProto).(*descriptor.DescriptorProto)
+ for _, field := range m.Field {
+ oneof := field.OneofIndex != nil
+ if !oneof {
+ continue
+ }
+ ccTypeName := p.OneOfTypeName(message, field)
+ if verbose {
+ p.P(`func (this *`, ccTypeName, `) VerboseEqual(that interface{}) error {`)
+ } else {
+ p.P(`func (this *`, ccTypeName, `) Equal(that interface{}) bool {`)
+ }
+ p.In()
+
+ p.generateMsgNullAndTypeCheck(ccTypeName, verbose)
+ vanity.TurnOffNullableForNativeTypes(field)
+ p.generateField(file, message, field, verbose)
+
+ if verbose {
+ p.P(`return nil`)
+ } else {
+ p.P(`return true`)
+ }
+ p.Out()
+ p.P(`}`)
+ }
+}
+
+func init() {
+ generator.RegisterPlugin(NewPlugin())
+}
diff --git a/vendor/github.com/gogo/protobuf/plugin/equal/equaltest.go b/vendor/github.com/gogo/protobuf/plugin/equal/equaltest.go
new file mode 100644
index 00000000000..1233647a56d
--- /dev/null
+++ b/vendor/github.com/gogo/protobuf/plugin/equal/equaltest.go
@@ -0,0 +1,109 @@
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2013, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// 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.
+//
+// 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 equal
+
+import (
+ "github.com/gogo/protobuf/gogoproto"
+ "github.com/gogo/protobuf/plugin/testgen"
+ "github.com/gogo/protobuf/protoc-gen-gogo/generator"
+)
+
+type test struct {
+ *generator.Generator
+}
+
+func NewTest(g *generator.Generator) testgen.TestPlugin {
+ return &test{g}
+}
+
+func (p *test) Generate(imports generator.PluginImports, file *generator.FileDescriptor) bool {
+ used := false
+ randPkg := imports.NewImport("math/rand")
+ timePkg := imports.NewImport("time")
+ testingPkg := imports.NewImport("testing")
+ protoPkg := imports.NewImport("github.com/gogo/protobuf/proto")
+ unsafePkg := imports.NewImport("unsafe")
+ if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
+ protoPkg = imports.NewImport("github.com/golang/protobuf/proto")
+ }
+ for _, message := range file.Messages() {
+ ccTypeName := generator.CamelCaseSlice(message.TypeName())
+ if !gogoproto.HasVerboseEqual(file.FileDescriptorProto, message.DescriptorProto) {
+ continue
+ }
+ if message.DescriptorProto.GetOptions().GetMapEntry() {
+ continue
+ }
+
+ if gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
+ used = true
+ hasUnsafe := gogoproto.IsUnsafeMarshaler(file.FileDescriptorProto, message.DescriptorProto) ||
+ gogoproto.IsUnsafeUnmarshaler(file.FileDescriptorProto, message.DescriptorProto)
+ p.P(`func Test`, ccTypeName, `VerboseEqual(t *`, testingPkg.Use(), `.T) {`)
+ p.In()
+ if hasUnsafe {
+ if hasUnsafe {
+ p.P(`var bigendian uint32 = 0x01020304`)
+ p.P(`if *(*byte)(`, unsafePkg.Use(), `.Pointer(&bigendian)) == 1 {`)
+ p.In()
+ p.P(`t.Skip("unsafe does not work on big endian architectures")`)
+ p.Out()
+ p.P(`}`)
+ }
+ }
+ p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(`, timePkg.Use(), `.Now().UnixNano()))`)
+ p.P(`p := NewPopulated`, ccTypeName, `(popr, false)`)
+ p.P(`dAtA, err := `, protoPkg.Use(), `.Marshal(p)`)
+ p.P(`if err != nil {`)
+ p.In()
+ p.P(`panic(err)`)
+ p.Out()
+ p.P(`}`)
+ p.P(`msg := &`, ccTypeName, `{}`)
+ p.P(`if err := `, protoPkg.Use(), `.Unmarshal(dAtA, msg); err != nil {`)
+ p.In()
+ p.P(`panic(err)`)
+ p.Out()
+ p.P(`}`)
+ p.P(`if err := p.VerboseEqual(msg); err != nil {`)
+ p.In()
+ p.P(`t.Fatalf("%#v !VerboseEqual %#v, since %v", msg, p, err)`)
+ p.Out()
+ p.P(`}`)
+ p.Out()
+ p.P(`}`)
+ }
+
+ }
+ return used
+}
+
+func init() {
+ testgen.RegisterTestPlugin(NewTest)
+}
diff --git a/vendor/github.com/gogo/protobuf/plugin/face/face.go b/vendor/github.com/gogo/protobuf/plugin/face/face.go
new file mode 100644
index 00000000000..a0293452652
--- /dev/null
+++ b/vendor/github.com/gogo/protobuf/plugin/face/face.go
@@ -0,0 +1,233 @@
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2013, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// 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.
+//
+// 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.
+
+/*
+The face plugin generates a function will be generated which can convert a structure which satisfies an interface (face) to the specified structure.
+This interface contains getters for each of the fields in the struct.
+The specified struct is also generated with the getters.
+This means that getters should be turned off so as not to conflict with face getters.
+This allows it to satisfy its own face.
+
+It is enabled by the following extensions:
+
+ - face
+ - face_all
+
+Turn off getters by using the following extensions:
+
+ - getters
+ - getters_all
+
+The face plugin also generates a test given it is enabled using one of the following extensions:
+
+ - testgen
+ - testgen_all
+
+Let us look at:
+
+ github.com/gogo/protobuf/test/example/example.proto
+
+Btw all the output can be seen at:
+
+ github.com/gogo/protobuf/test/example/*
+
+The following message:
+
+ message A {
+ option (gogoproto.face) = true;
+ option (gogoproto.goproto_getters) = false;
+ optional string Description = 1 [(gogoproto.nullable) = false];
+ optional int64 Number = 2 [(gogoproto.nullable) = false];
+ optional bytes Id = 3 [(gogoproto.customtype) = "github.com/gogo/protobuf/test/custom.Uuid", (gogoproto.nullable) = false];
+ }
+
+given to the face plugin, will generate the following code:
+
+ type AFace interface {
+ Proto() github_com_gogo_protobuf_proto.Message
+ GetDescription() string
+ GetNumber() int64
+ GetId() github_com_gogo_protobuf_test_custom.Uuid
+ }
+
+ func (this *A) Proto() github_com_gogo_protobuf_proto.Message {
+ return this
+ }
+
+ func (this *A) TestProto() github_com_gogo_protobuf_proto.Message {
+ return NewAFromFace(this)
+ }
+
+ func (this *A) GetDescription() string {
+ return this.Description
+ }
+
+ func (this *A) GetNumber() int64 {
+ return this.Number
+ }
+
+ func (this *A) GetId() github_com_gogo_protobuf_test_custom.Uuid {
+ return this.Id
+ }
+
+ func NewAFromFace(that AFace) *A {
+ this := &A{}
+ this.Description = that.GetDescription()
+ this.Number = that.GetNumber()
+ this.Id = that.GetId()
+ return this
+ }
+
+and the following test code:
+
+ func TestAFace(t *testing7.T) {
+ popr := math_rand7.New(math_rand7.NewSource(time7.Now().UnixNano()))
+ p := NewPopulatedA(popr, true)
+ msg := p.TestProto()
+ if !p.Equal(msg) {
+ t.Fatalf("%#v !Face Equal %#v", msg, p)
+ }
+ }
+
+The struct A, representing the message, will also be generated just like always.
+As you can see A satisfies its own Face, AFace.
+
+Creating another struct which satisfies AFace is very easy.
+Simply create all these methods specified in AFace.
+Implementing The Proto method is done with the helper function NewAFromFace:
+
+ func (this *MyStruct) Proto() proto.Message {
+ return NewAFromFace(this)
+ }
+
+just the like TestProto method which is used to test the NewAFromFace function.
+
+*/
+package face
+
+import (
+ "github.com/gogo/protobuf/gogoproto"
+ "github.com/gogo/protobuf/protoc-gen-gogo/generator"
+)
+
+type plugin struct {
+ *generator.Generator
+ generator.PluginImports
+}
+
+func NewPlugin() *plugin {
+ return &plugin{}
+}
+
+func (p *plugin) Name() string {
+ return "face"
+}
+
+func (p *plugin) Init(g *generator.Generator) {
+ p.Generator = g
+}
+
+func (p *plugin) Generate(file *generator.FileDescriptor) {
+ p.PluginImports = generator.NewPluginImports(p.Generator)
+ protoPkg := p.NewImport("github.com/gogo/protobuf/proto")
+ if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
+ protoPkg = p.NewImport("github.com/golang/protobuf/proto")
+ }
+ for _, message := range file.Messages() {
+ if !gogoproto.IsFace(file.FileDescriptorProto, message.DescriptorProto) {
+ continue
+ }
+ if message.DescriptorProto.GetOptions().GetMapEntry() {
+ continue
+ }
+ if message.DescriptorProto.HasExtension() {
+ panic("face does not support message with extensions")
+ }
+ if gogoproto.HasGoGetters(file.FileDescriptorProto, message.DescriptorProto) {
+ panic("face requires getters to be disabled please use gogoproto.getters or gogoproto.getters_all and set it to false")
+ }
+ ccTypeName := generator.CamelCaseSlice(message.TypeName())
+ p.P(`type `, ccTypeName, `Face interface{`)
+ p.In()
+ p.P(`Proto() `, protoPkg.Use(), `.Message`)
+ for _, field := range message.Field {
+ fieldname := p.GetFieldName(message, field)
+ goTyp, _ := p.GoType(message, field)
+ if p.IsMap(field) {
+ m := p.GoMapType(nil, field)
+ goTyp = m.GoType
+ }
+ p.P(`Get`, fieldname, `() `, goTyp)
+ }
+ p.Out()
+ p.P(`}`)
+ p.P(``)
+ p.P(`func (this *`, ccTypeName, `) Proto() `, protoPkg.Use(), `.Message {`)
+ p.In()
+ p.P(`return this`)
+ p.Out()
+ p.P(`}`)
+ p.P(``)
+ p.P(`func (this *`, ccTypeName, `) TestProto() `, protoPkg.Use(), `.Message {`)
+ p.In()
+ p.P(`return New`, ccTypeName, `FromFace(this)`)
+ p.Out()
+ p.P(`}`)
+ p.P(``)
+ for _, field := range message.Field {
+ fieldname := p.GetFieldName(message, field)
+ goTyp, _ := p.GoType(message, field)
+ if p.IsMap(field) {
+ m := p.GoMapType(nil, field)
+ goTyp = m.GoType
+ }
+ p.P(`func (this *`, ccTypeName, `) Get`, fieldname, `() `, goTyp, `{`)
+ p.In()
+ p.P(` return this.`, fieldname)
+ p.Out()
+ p.P(`}`)
+ p.P(``)
+ }
+ p.P(``)
+ p.P(`func New`, ccTypeName, `FromFace(that `, ccTypeName, `Face) *`, ccTypeName, ` {`)
+ p.In()
+ p.P(`this := &`, ccTypeName, `{}`)
+ for _, field := range message.Field {
+ fieldname := p.GetFieldName(message, field)
+ p.P(`this.`, fieldname, ` = that.Get`, fieldname, `()`)
+ }
+ p.P(`return this`)
+ p.Out()
+ p.P(`}`)
+ p.P(``)
+ }
+}
+
+func init() {
+ generator.RegisterPlugin(NewPlugin())
+}
diff --git a/vendor/github.com/gogo/protobuf/plugin/face/facetest.go b/vendor/github.com/gogo/protobuf/plugin/face/facetest.go
new file mode 100644
index 00000000000..467cc0a6640
--- /dev/null
+++ b/vendor/github.com/gogo/protobuf/plugin/face/facetest.go
@@ -0,0 +1,82 @@
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2013, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// 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.
+//
+// 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 face
+
+import (
+ "github.com/gogo/protobuf/gogoproto"
+ "github.com/gogo/protobuf/plugin/testgen"
+ "github.com/gogo/protobuf/protoc-gen-gogo/generator"
+)
+
+type test struct {
+ *generator.Generator
+}
+
+func NewTest(g *generator.Generator) testgen.TestPlugin {
+ return &test{g}
+}
+
+func (p *test) Generate(imports generator.PluginImports, file *generator.FileDescriptor) bool {
+ used := false
+ randPkg := imports.NewImport("math/rand")
+ timePkg := imports.NewImport("time")
+ testingPkg := imports.NewImport("testing")
+ for _, message := range file.Messages() {
+ ccTypeName := generator.CamelCaseSlice(message.TypeName())
+ if !gogoproto.IsFace(file.FileDescriptorProto, message.DescriptorProto) {
+ continue
+ }
+ if message.DescriptorProto.GetOptions().GetMapEntry() {
+ continue
+ }
+
+ if gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
+ used = true
+
+ p.P(`func Test`, ccTypeName, `Face(t *`, testingPkg.Use(), `.T) {`)
+ p.In()
+ p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(`, timePkg.Use(), `.Now().UnixNano()))`)
+ p.P(`p := NewPopulated`, ccTypeName, `(popr, true)`)
+ p.P(`msg := p.TestProto()`)
+ p.P(`if !p.Equal(msg) {`)
+ p.In()
+ p.P(`t.Fatalf("%#v !Face Equal %#v", msg, p)`)
+ p.Out()
+ p.P(`}`)
+ p.Out()
+ p.P(`}`)
+ }
+
+ }
+ return used
+}
+
+func init() {
+ testgen.RegisterTestPlugin(NewTest)
+}
diff --git a/vendor/github.com/gogo/protobuf/plugin/gostring/gostring.go b/vendor/github.com/gogo/protobuf/plugin/gostring/gostring.go
new file mode 100644
index 00000000000..bc89a7b871d
--- /dev/null
+++ b/vendor/github.com/gogo/protobuf/plugin/gostring/gostring.go
@@ -0,0 +1,386 @@
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2013, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// 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.
+//
+// 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.
+
+/*
+The gostring plugin generates a GoString method for each message.
+The GoString method is called whenever you use a fmt.Printf as such:
+
+ fmt.Printf("%#v", mymessage)
+
+or whenever you actually call GoString()
+The output produced by the GoString method can be copied from the output into code and used to set a variable.
+It is totally valid Go Code and is populated exactly as the struct that was printed out.
+
+It is enabled by the following extensions:
+
+ - gostring
+ - gostring_all
+
+The gostring plugin also generates a test given it is enabled using one of the following extensions:
+
+ - testgen
+ - testgen_all
+
+Let us look at:
+
+ github.com/gogo/protobuf/test/example/example.proto
+
+Btw all the output can be seen at:
+
+ github.com/gogo/protobuf/test/example/*
+
+The following message:
+
+ option (gogoproto.gostring_all) = true;
+
+ message A {
+ optional string Description = 1 [(gogoproto.nullable) = false];
+ optional int64 Number = 2 [(gogoproto.nullable) = false];
+ optional bytes Id = 3 [(gogoproto.customtype) = "github.com/gogo/protobuf/test/custom.Uuid", (gogoproto.nullable) = false];
+ }
+
+given to the gostring plugin, will generate the following code:
+
+ func (this *A) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := strings1.Join([]string{`&test.A{` + `Description:` + fmt1.Sprintf("%#v", this.Description), `Number:` + fmt1.Sprintf("%#v", this.Number), `Id:` + fmt1.Sprintf("%#v", this.Id), `XXX_unrecognized:` + fmt1.Sprintf("%#v", this.XXX_unrecognized) + `}`}, ", ")
+ return s
+ }
+
+and the following test code:
+
+ func TestAGoString(t *testing6.T) {
+ popr := math_rand6.New(math_rand6.NewSource(time6.Now().UnixNano()))
+ p := NewPopulatedA(popr, false)
+ s1 := p.GoString()
+ s2 := fmt2.Sprintf("%#v", p)
+ if s1 != s2 {
+ t.Fatalf("GoString want %v got %v", s1, s2)
+ }
+ _, err := go_parser.ParseExpr(s1)
+ if err != nil {
+ panic(err)
+ }
+ }
+
+Typically fmt.Printf("%#v") will stop to print when it reaches a pointer and
+not print their values, while the generated GoString method will always print all values, recursively.
+
+*/
+package gostring
+
+import (
+ "fmt"
+ "os"
+ "strconv"
+ "strings"
+
+ "github.com/gogo/protobuf/gogoproto"
+ "github.com/gogo/protobuf/protoc-gen-gogo/generator"
+)
+
+type gostring struct {
+ *generator.Generator
+ generator.PluginImports
+ atleastOne bool
+ localName string
+ overwrite bool
+}
+
+func NewGoString() *gostring {
+ return &gostring{}
+}
+
+func (p *gostring) Name() string {
+ return "gostring"
+}
+
+func (p *gostring) Overwrite() {
+ p.overwrite = true
+}
+
+func (p *gostring) Init(g *generator.Generator) {
+ p.Generator = g
+}
+
+func (p *gostring) Generate(file *generator.FileDescriptor) {
+ proto3 := gogoproto.IsProto3(file.FileDescriptorProto)
+ p.PluginImports = generator.NewPluginImports(p.Generator)
+ p.atleastOne = false
+
+ p.localName = generator.FileName(file)
+
+ fmtPkg := p.NewImport("fmt")
+ stringsPkg := p.NewImport("strings")
+ protoPkg := p.NewImport("github.com/gogo/protobuf/proto")
+ if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
+ protoPkg = p.NewImport("github.com/golang/protobuf/proto")
+ }
+ sortPkg := p.NewImport("sort")
+ strconvPkg := p.NewImport("strconv")
+ reflectPkg := p.NewImport("reflect")
+ sortKeysPkg := p.NewImport("github.com/gogo/protobuf/sortkeys")
+
+ extensionToGoStringUsed := false
+ for _, message := range file.Messages() {
+ if !p.overwrite && !gogoproto.HasGoString(file.FileDescriptorProto, message.DescriptorProto) {
+ continue
+ }
+ if message.DescriptorProto.GetOptions().GetMapEntry() {
+ continue
+ }
+ p.atleastOne = true
+ packageName := file.GoPackageName()
+
+ ccTypeName := generator.CamelCaseSlice(message.TypeName())
+ p.P(`func (this *`, ccTypeName, `) GoString() string {`)
+ p.In()
+ p.P(`if this == nil {`)
+ p.In()
+ p.P(`return "nil"`)
+ p.Out()
+ p.P(`}`)
+
+ p.P(`s := make([]string, 0, `, strconv.Itoa(len(message.Field)+4), `)`)
+ p.P(`s = append(s, "&`, packageName, ".", ccTypeName, `{")`)
+
+ oneofs := make(map[string]struct{})
+ for _, field := range message.Field {
+ nullable := gogoproto.IsNullable(field)
+ repeated := field.IsRepeated()
+ fieldname := p.GetFieldName(message, field)
+ oneof := field.OneofIndex != nil
+ if oneof {
+ if _, ok := oneofs[fieldname]; ok {
+ continue
+ } else {
+ oneofs[fieldname] = struct{}{}
+ }
+ p.P(`if this.`, fieldname, ` != nil {`)
+ p.In()
+ p.P(`s = append(s, "`, fieldname, `: " + `, fmtPkg.Use(), `.Sprintf("%#v", this.`, fieldname, `) + ",\n")`)
+ p.Out()
+ p.P(`}`)
+ } else if p.IsMap(field) {
+ m := p.GoMapType(nil, field)
+ mapgoTyp, keyField, keyAliasField := m.GoType, m.KeyField, m.KeyAliasField
+ keysName := `keysFor` + fieldname
+ keygoTyp, _ := p.GoType(nil, keyField)
+ keygoTyp = strings.Replace(keygoTyp, "*", "", 1)
+ keygoAliasTyp, _ := p.GoType(nil, keyAliasField)
+ keygoAliasTyp = strings.Replace(keygoAliasTyp, "*", "", 1)
+ keyCapTyp := generator.CamelCase(keygoTyp)
+ p.P(keysName, ` := make([]`, keygoTyp, `, 0, len(this.`, fieldname, `))`)
+ p.P(`for k, _ := range this.`, fieldname, ` {`)
+ p.In()
+ if keygoAliasTyp == keygoTyp {
+ p.P(keysName, ` = append(`, keysName, `, k)`)
+ } else {
+ p.P(keysName, ` = append(`, keysName, `, `, keygoTyp, `(k))`)
+ }
+ p.Out()
+ p.P(`}`)
+ p.P(sortKeysPkg.Use(), `.`, keyCapTyp, `s(`, keysName, `)`)
+ mapName := `mapStringFor` + fieldname
+ p.P(mapName, ` := "`, mapgoTyp, `{"`)
+ p.P(`for _, k := range `, keysName, ` {`)
+ p.In()
+ if keygoAliasTyp == keygoTyp {
+ p.P(mapName, ` += fmt.Sprintf("%#v: %#v,", k, this.`, fieldname, `[k])`)
+ } else {
+ p.P(mapName, ` += fmt.Sprintf("%#v: %#v,", k, this.`, fieldname, `[`, keygoAliasTyp, `(k)])`)
+ }
+ p.Out()
+ p.P(`}`)
+ p.P(mapName, ` += "}"`)
+ p.P(`if this.`, fieldname, ` != nil {`)
+ p.In()
+ p.P(`s = append(s, "`, fieldname, `: " + `, mapName, `+ ",\n")`)
+ p.Out()
+ p.P(`}`)
+ } else if (field.IsMessage() && !gogoproto.IsCustomType(field) && !gogoproto.IsStdType(field)) || p.IsGroup(field) {
+ if nullable || repeated {
+ p.P(`if this.`, fieldname, ` != nil {`)
+ p.In()
+ }
+ if nullable {
+ p.P(`s = append(s, "`, fieldname, `: " + `, fmtPkg.Use(), `.Sprintf("%#v", this.`, fieldname, `) + ",\n")`)
+ } else if repeated {
+ if nullable {
+ p.P(`s = append(s, "`, fieldname, `: " + `, fmtPkg.Use(), `.Sprintf("%#v", this.`, fieldname, `) + ",\n")`)
+ } else {
+ goTyp, _ := p.GoType(message, field)
+ goTyp = strings.Replace(goTyp, "[]", "", 1)
+ p.P("vs := make([]", goTyp, ", len(this.", fieldname, "))")
+ p.P("for i := range vs {")
+ p.In()
+ p.P("vs[i] = this.", fieldname, "[i]")
+ p.Out()
+ p.P("}")
+ p.P(`s = append(s, "`, fieldname, `: " + `, fmtPkg.Use(), `.Sprintf("%#v", vs) + ",\n")`)
+ }
+ } else {
+ p.P(`s = append(s, "`, fieldname, `: " + `, stringsPkg.Use(), `.Replace(this.`, fieldname, `.GoString()`, ",`&`,``,1)", ` + ",\n")`)
+ }
+ if nullable || repeated {
+ p.Out()
+ p.P(`}`)
+ }
+ } else {
+ if !proto3 && (nullable || repeated) {
+ p.P(`if this.`, fieldname, ` != nil {`)
+ p.In()
+ }
+ if field.IsEnum() {
+ if nullable && !repeated && !proto3 {
+ goTyp, _ := p.GoType(message, field)
+ p.P(`s = append(s, "`, fieldname, `: " + valueToGoString`, p.localName, `(this.`, fieldname, `,"`, generator.GoTypeToName(goTyp), `"`, `) + ",\n")`)
+ } else {
+ p.P(`s = append(s, "`, fieldname, `: " + `, fmtPkg.Use(), `.Sprintf("%#v", this.`, fieldname, `) + ",\n")`)
+ }
+ } else {
+ if nullable && !repeated && !proto3 {
+ goTyp, _ := p.GoType(message, field)
+ p.P(`s = append(s, "`, fieldname, `: " + valueToGoString`, p.localName, `(this.`, fieldname, `,"`, generator.GoTypeToName(goTyp), `"`, `) + ",\n")`)
+ } else {
+ p.P(`s = append(s, "`, fieldname, `: " + `, fmtPkg.Use(), `.Sprintf("%#v", this.`, fieldname, `) + ",\n")`)
+ }
+ }
+ if !proto3 && (nullable || repeated) {
+ p.Out()
+ p.P(`}`)
+ }
+ }
+ }
+ if message.DescriptorProto.HasExtension() {
+ if gogoproto.HasExtensionsMap(file.FileDescriptorProto, message.DescriptorProto) {
+ p.P(`s = append(s, "XXX_InternalExtensions: " + extensionToGoString`, p.localName, `(this) + ",\n")`)
+ extensionToGoStringUsed = true
+ } else {
+ p.P(`if this.XXX_extensions != nil {`)
+ p.In()
+ p.P(`s = append(s, "XXX_extensions: " + `, fmtPkg.Use(), `.Sprintf("%#v", this.XXX_extensions) + ",\n")`)
+ p.Out()
+ p.P(`}`)
+ }
+ }
+ if gogoproto.HasUnrecognized(file.FileDescriptorProto, message.DescriptorProto) {
+ p.P(`if this.XXX_unrecognized != nil {`)
+ p.In()
+ p.P(`s = append(s, "XXX_unrecognized:" + `, fmtPkg.Use(), `.Sprintf("%#v", this.XXX_unrecognized) + ",\n")`)
+ p.Out()
+ p.P(`}`)
+ }
+
+ p.P(`s = append(s, "}")`)
+ p.P(`return `, stringsPkg.Use(), `.Join(s, "")`)
+ p.Out()
+ p.P(`}`)
+
+ //Generate GoString methods for oneof fields
+ for _, field := range message.Field {
+ oneof := field.OneofIndex != nil
+ if !oneof {
+ continue
+ }
+ ccTypeName := p.OneOfTypeName(message, field)
+ p.P(`func (this *`, ccTypeName, `) GoString() string {`)
+ p.In()
+ p.P(`if this == nil {`)
+ p.In()
+ p.P(`return "nil"`)
+ p.Out()
+ p.P(`}`)
+ fieldname := p.GetOneOfFieldName(message, field)
+ outStr := strings.Join([]string{
+ "s := ",
+ stringsPkg.Use(), ".Join([]string{`&", packageName, ".", ccTypeName, "{` + \n",
+ "`", fieldname, ":` + ", fmtPkg.Use(), `.Sprintf("%#v", this.`, fieldname, `)`,
+ " + `}`",
+ `}`,
+ `,", "`,
+ `)`}, "")
+ p.P(outStr)
+ p.P(`return s`)
+ p.Out()
+ p.P(`}`)
+ }
+ }
+
+ if !p.atleastOne {
+ return
+ }
+
+ p.P(`func valueToGoString`, p.localName, `(v interface{}, typ string) string {`)
+ p.In()
+ p.P(`rv := `, reflectPkg.Use(), `.ValueOf(v)`)
+ p.P(`if rv.IsNil() {`)
+ p.In()
+ p.P(`return "nil"`)
+ p.Out()
+ p.P(`}`)
+ p.P(`pv := `, reflectPkg.Use(), `.Indirect(rv).Interface()`)
+ p.P(`return `, fmtPkg.Use(), `.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv)`)
+ p.Out()
+ p.P(`}`)
+
+ if extensionToGoStringUsed {
+ if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
+ fmt.Fprintf(os.Stderr, "The GoString plugin for messages with extensions requires importing gogoprotobuf. Please see file %s", file.GetName())
+ os.Exit(1)
+ }
+ p.P(`func extensionToGoString`, p.localName, `(m `, protoPkg.Use(), `.Message) string {`)
+ p.In()
+ p.P(`e := `, protoPkg.Use(), `.GetUnsafeExtensionsMap(m)`)
+ p.P(`if e == nil { return "nil" }`)
+ p.P(`s := "proto.NewUnsafeXXX_InternalExtensions(map[int32]proto.Extension{"`)
+ p.P(`keys := make([]int, 0, len(e))`)
+ p.P(`for k := range e {`)
+ p.In()
+ p.P(`keys = append(keys, int(k))`)
+ p.Out()
+ p.P(`}`)
+ p.P(sortPkg.Use(), `.Ints(keys)`)
+ p.P(`ss := []string{}`)
+ p.P(`for _, k := range keys {`)
+ p.In()
+ p.P(`ss = append(ss, `, strconvPkg.Use(), `.Itoa(k) + ": " + e[int32(k)].GoString())`)
+ p.Out()
+ p.P(`}`)
+ p.P(`s+=`, stringsPkg.Use(), `.Join(ss, ",") + "})"`)
+ p.P(`return s`)
+ p.Out()
+ p.P(`}`)
+ }
+}
+
+func init() {
+ generator.RegisterPlugin(NewGoString())
+}
diff --git a/vendor/github.com/gogo/protobuf/plugin/gostring/gostringtest.go b/vendor/github.com/gogo/protobuf/plugin/gostring/gostringtest.go
new file mode 100644
index 00000000000..c790e590880
--- /dev/null
+++ b/vendor/github.com/gogo/protobuf/plugin/gostring/gostringtest.go
@@ -0,0 +1,90 @@
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2013, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// 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.
+//
+// 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 gostring
+
+import (
+ "github.com/gogo/protobuf/gogoproto"
+ "github.com/gogo/protobuf/plugin/testgen"
+ "github.com/gogo/protobuf/protoc-gen-gogo/generator"
+)
+
+type test struct {
+ *generator.Generator
+}
+
+func NewTest(g *generator.Generator) testgen.TestPlugin {
+ return &test{g}
+}
+
+func (p *test) Generate(imports generator.PluginImports, file *generator.FileDescriptor) bool {
+ used := false
+ randPkg := imports.NewImport("math/rand")
+ timePkg := imports.NewImport("time")
+ testingPkg := imports.NewImport("testing")
+ fmtPkg := imports.NewImport("fmt")
+ parserPkg := imports.NewImport("go/parser")
+ for _, message := range file.Messages() {
+ ccTypeName := generator.CamelCaseSlice(message.TypeName())
+ if !gogoproto.HasGoString(file.FileDescriptorProto, message.DescriptorProto) {
+ continue
+ }
+ if message.DescriptorProto.GetOptions().GetMapEntry() {
+ continue
+ }
+
+ if gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
+ used = true
+ p.P(`func Test`, ccTypeName, `GoString(t *`, testingPkg.Use(), `.T) {`)
+ p.In()
+ p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(`, timePkg.Use(), `.Now().UnixNano()))`)
+ p.P(`p := NewPopulated`, ccTypeName, `(popr, false)`)
+ p.P(`s1 := p.GoString()`)
+ p.P(`s2 := `, fmtPkg.Use(), `.Sprintf("%#v", p)`)
+ p.P(`if s1 != s2 {`)
+ p.In()
+ p.P(`t.Fatalf("GoString want %v got %v", s1, s2)`)
+ p.Out()
+ p.P(`}`)
+ p.P(`_, err := `, parserPkg.Use(), `.ParseExpr(s1)`)
+ p.P(`if err != nil {`)
+ p.In()
+ p.P(`t.Fatal(err)`)
+ p.Out()
+ p.P(`}`)
+ p.Out()
+ p.P(`}`)
+ }
+
+ }
+ return used
+}
+
+func init() {
+ testgen.RegisterTestPlugin(NewTest)
+}
diff --git a/vendor/github.com/gogo/protobuf/plugin/marshalto/marshalto.go b/vendor/github.com/gogo/protobuf/plugin/marshalto/marshalto.go
new file mode 100644
index 00000000000..f82c28c281e
--- /dev/null
+++ b/vendor/github.com/gogo/protobuf/plugin/marshalto/marshalto.go
@@ -0,0 +1,1140 @@
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2013, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// 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.
+//
+// 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.
+
+/*
+The marshalto plugin generates a Marshal and MarshalTo method for each message.
+The `Marshal() ([]byte, error)` method results in the fact that the message
+implements the Marshaler interface.
+This allows proto.Marshal to be faster by calling the generated Marshal method rather than using reflect to Marshal the struct.
+
+If is enabled by the following extensions:
+
+ - marshaler
+ - marshaler_all
+
+Or the following extensions:
+
+ - unsafe_marshaler
+ - unsafe_marshaler_all
+
+That is if you want to use the unsafe package in your generated code.
+The speed up using the unsafe package is not very significant.
+
+The generation of marshalling tests are enabled using one of the following extensions:
+
+ - testgen
+ - testgen_all
+
+And benchmarks given it is enabled using one of the following extensions:
+
+ - benchgen
+ - benchgen_all
+
+Let us look at:
+
+ github.com/gogo/protobuf/test/example/example.proto
+
+Btw all the output can be seen at:
+
+ github.com/gogo/protobuf/test/example/*
+
+The following message:
+
+option (gogoproto.marshaler_all) = true;
+
+message B {
+ option (gogoproto.description) = true;
+ optional A A = 1 [(gogoproto.nullable) = false, (gogoproto.embed) = true];
+ repeated bytes G = 2 [(gogoproto.customtype) = "github.com/gogo/protobuf/test/custom.Uint128", (gogoproto.nullable) = false];
+}
+
+given to the marshalto plugin, will generate the following code:
+
+ func (m *B) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+ }
+
+ func (m *B) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+ }
+
+ func (m *B) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if m.XXX_unrecognized != nil {
+ i -= len(m.XXX_unrecognized)
+ copy(dAtA[i:], m.XXX_unrecognized)
+ }
+ if len(m.G) > 0 {
+ for iNdEx := len(m.G) - 1; iNdEx >= 0; iNdEx-- {
+ {
+ size := m.G[iNdEx].Size()
+ i -= size
+ if _, err := m.G[iNdEx].MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintExample(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x12
+ }
+ }
+ {
+ size, err := m.A.MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintExample(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0xa
+ return len(dAtA) - i, nil
+ }
+
+As shown above Marshal calculates the size of the not yet marshalled message
+and allocates the appropriate buffer.
+This is followed by calling the MarshalToSizedBuffer method which requires a preallocated buffer, and marshals backwards.
+The MarshalTo method allows a user to rather preallocated a reusable buffer.
+
+The Size method is generated using the size plugin and the gogoproto.sizer, gogoproto.sizer_all extensions.
+The user can also using the generated Size method to check that his reusable buffer is still big enough.
+
+The generated tests and benchmarks will keep you safe and show that this is really a significant speed improvement.
+
+An additional message-level option `stable_marshaler` (and the file-level
+option `stable_marshaler_all`) exists which causes the generated marshalling
+code to behave deterministically. Today, this only changes the serialization of
+maps; they are serialized in sort order.
+*/
+package marshalto
+
+import (
+ "fmt"
+ "sort"
+ "strconv"
+ "strings"
+
+ "github.com/gogo/protobuf/gogoproto"
+ "github.com/gogo/protobuf/proto"
+ descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
+ "github.com/gogo/protobuf/protoc-gen-gogo/generator"
+ "github.com/gogo/protobuf/vanity"
+)
+
+type NumGen interface {
+ Next() string
+ Current() string
+}
+
+type numGen struct {
+ index int
+}
+
+func NewNumGen() NumGen {
+ return &numGen{0}
+}
+
+func (this *numGen) Next() string {
+ this.index++
+ return this.Current()
+}
+
+func (this *numGen) Current() string {
+ return strconv.Itoa(this.index)
+}
+
+type marshalto struct {
+ *generator.Generator
+ generator.PluginImports
+ atleastOne bool
+ errorsPkg generator.Single
+ protoPkg generator.Single
+ sortKeysPkg generator.Single
+ mathPkg generator.Single
+ typesPkg generator.Single
+ binaryPkg generator.Single
+ localName string
+}
+
+func NewMarshal() *marshalto {
+ return &marshalto{}
+}
+
+func (p *marshalto) Name() string {
+ return "marshalto"
+}
+
+func (p *marshalto) Init(g *generator.Generator) {
+ p.Generator = g
+}
+
+func (p *marshalto) callFixed64(varName ...string) {
+ p.P(`i -= 8`)
+ p.P(p.binaryPkg.Use(), `.LittleEndian.PutUint64(dAtA[i:], uint64(`, strings.Join(varName, ""), `))`)
+}
+
+func (p *marshalto) callFixed32(varName ...string) {
+ p.P(`i -= 4`)
+ p.P(p.binaryPkg.Use(), `.LittleEndian.PutUint32(dAtA[i:], uint32(`, strings.Join(varName, ""), `))`)
+}
+
+func (p *marshalto) callVarint(varName ...string) {
+ p.P(`i = encodeVarint`, p.localName, `(dAtA, i, uint64(`, strings.Join(varName, ""), `))`)
+}
+
+func (p *marshalto) encodeKey(fieldNumber int32, wireType int) {
+ x := uint32(fieldNumber)<<3 | uint32(wireType)
+ i := 0
+ keybuf := make([]byte, 0)
+ for i = 0; x > 127; i++ {
+ keybuf = append(keybuf, 0x80|uint8(x&0x7F))
+ x >>= 7
+ }
+ keybuf = append(keybuf, uint8(x))
+ for i = len(keybuf) - 1; i >= 0; i-- {
+ p.P(`i--`)
+ p.P(`dAtA[i] = `, fmt.Sprintf("%#v", keybuf[i]))
+ }
+}
+
+func keySize(fieldNumber int32, wireType int) int {
+ x := uint32(fieldNumber)<<3 | uint32(wireType)
+ size := 0
+ for size = 0; x > 127; size++ {
+ x >>= 7
+ }
+ size++
+ return size
+}
+
+func wireToType(wire string) int {
+ switch wire {
+ case "fixed64":
+ return proto.WireFixed64
+ case "fixed32":
+ return proto.WireFixed32
+ case "varint":
+ return proto.WireVarint
+ case "bytes":
+ return proto.WireBytes
+ case "group":
+ return proto.WireBytes
+ case "zigzag32":
+ return proto.WireVarint
+ case "zigzag64":
+ return proto.WireVarint
+ }
+ panic("unreachable")
+}
+
+func (p *marshalto) mapField(numGen NumGen, field *descriptor.FieldDescriptorProto, kvField *descriptor.FieldDescriptorProto, varName string, protoSizer bool) {
+ switch kvField.GetType() {
+ case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
+ p.callFixed64(p.mathPkg.Use(), `.Float64bits(float64(`, varName, `))`)
+ case descriptor.FieldDescriptorProto_TYPE_FLOAT:
+ p.callFixed32(p.mathPkg.Use(), `.Float32bits(float32(`, varName, `))`)
+ case descriptor.FieldDescriptorProto_TYPE_INT64,
+ descriptor.FieldDescriptorProto_TYPE_UINT64,
+ descriptor.FieldDescriptorProto_TYPE_INT32,
+ descriptor.FieldDescriptorProto_TYPE_UINT32,
+ descriptor.FieldDescriptorProto_TYPE_ENUM:
+ p.callVarint(varName)
+ case descriptor.FieldDescriptorProto_TYPE_FIXED64,
+ descriptor.FieldDescriptorProto_TYPE_SFIXED64:
+ p.callFixed64(varName)
+ case descriptor.FieldDescriptorProto_TYPE_FIXED32,
+ descriptor.FieldDescriptorProto_TYPE_SFIXED32:
+ p.callFixed32(varName)
+ case descriptor.FieldDescriptorProto_TYPE_BOOL:
+ p.P(`i--`)
+ p.P(`if `, varName, ` {`)
+ p.In()
+ p.P(`dAtA[i] = 1`)
+ p.Out()
+ p.P(`} else {`)
+ p.In()
+ p.P(`dAtA[i] = 0`)
+ p.Out()
+ p.P(`}`)
+ case descriptor.FieldDescriptorProto_TYPE_STRING,
+ descriptor.FieldDescriptorProto_TYPE_BYTES:
+ if gogoproto.IsCustomType(field) && kvField.IsBytes() {
+ p.forward(varName, true, protoSizer)
+ } else {
+ p.P(`i -= len(`, varName, `)`)
+ p.P(`copy(dAtA[i:], `, varName, `)`)
+ p.callVarint(`len(`, varName, `)`)
+ }
+ case descriptor.FieldDescriptorProto_TYPE_SINT32:
+ p.callVarint(`(uint32(`, varName, `) << 1) ^ uint32((`, varName, ` >> 31))`)
+ case descriptor.FieldDescriptorProto_TYPE_SINT64:
+ p.callVarint(`(uint64(`, varName, `) << 1) ^ uint64((`, varName, ` >> 63))`)
+ case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
+ if !p.marshalAllSizeOf(kvField, `(*`+varName+`)`, numGen.Next()) {
+ if gogoproto.IsCustomType(field) {
+ p.forward(varName, true, protoSizer)
+ } else {
+ p.backward(varName, true)
+ }
+ }
+
+ }
+}
+
+type orderFields []*descriptor.FieldDescriptorProto
+
+func (this orderFields) Len() int {
+ return len(this)
+}
+
+func (this orderFields) Less(i, j int) bool {
+ return this[i].GetNumber() < this[j].GetNumber()
+}
+
+func (this orderFields) Swap(i, j int) {
+ this[i], this[j] = this[j], this[i]
+}
+
+func (p *marshalto) generateField(proto3 bool, numGen NumGen, file *generator.FileDescriptor, message *generator.Descriptor, field *descriptor.FieldDescriptorProto) {
+ fieldname := p.GetOneOfFieldName(message, field)
+ nullable := gogoproto.IsNullable(field)
+ repeated := field.IsRepeated()
+ required := field.IsRequired()
+
+ protoSizer := gogoproto.IsProtoSizer(file.FileDescriptorProto, message.DescriptorProto)
+ doNilCheck := gogoproto.NeedsNilCheck(proto3, field)
+ if required && nullable {
+ p.P(`if m.`, fieldname, `== nil {`)
+ p.In()
+ if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
+ p.P(`return 0, new(`, p.protoPkg.Use(), `.RequiredNotSetError)`)
+ } else {
+ p.P(`return 0, `, p.protoPkg.Use(), `.NewRequiredNotSetError("`, field.GetName(), `")`)
+ }
+ p.Out()
+ p.P(`} else {`)
+ } else if repeated {
+ p.P(`if len(m.`, fieldname, `) > 0 {`)
+ p.In()
+ } else if doNilCheck {
+ p.P(`if m.`, fieldname, ` != nil {`)
+ p.In()
+ }
+ packed := field.IsPacked() || (proto3 && field.IsPacked3())
+ wireType := field.WireType()
+ fieldNumber := field.GetNumber()
+ if packed {
+ wireType = proto.WireBytes
+ }
+ switch *field.Type {
+ case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
+ if packed {
+ val := p.reverseListRange(`m.`, fieldname)
+ p.P(`f`, numGen.Next(), ` := `, p.mathPkg.Use(), `.Float64bits(float64(`, val, `))`)
+ p.callFixed64("f" + numGen.Current())
+ p.Out()
+ p.P(`}`)
+ p.callVarint(`len(m.`, fieldname, `) * 8`)
+ p.encodeKey(fieldNumber, wireType)
+ } else if repeated {
+ val := p.reverseListRange(`m.`, fieldname)
+ p.P(`f`, numGen.Next(), ` := `, p.mathPkg.Use(), `.Float64bits(float64(`, val, `))`)
+ p.callFixed64("f" + numGen.Current())
+ p.encodeKey(fieldNumber, wireType)
+ p.Out()
+ p.P(`}`)
+ } else if proto3 {
+ p.P(`if m.`, fieldname, ` != 0 {`)
+ p.In()
+ p.callFixed64(p.mathPkg.Use(), `.Float64bits(float64(m.`+fieldname, `))`)
+ p.encodeKey(fieldNumber, wireType)
+ p.Out()
+ p.P(`}`)
+ } else if !nullable {
+ p.callFixed64(p.mathPkg.Use(), `.Float64bits(float64(m.`+fieldname, `))`)
+ p.encodeKey(fieldNumber, wireType)
+ } else {
+ p.callFixed64(p.mathPkg.Use(), `.Float64bits(float64(*m.`+fieldname, `))`)
+ p.encodeKey(fieldNumber, wireType)
+ }
+ case descriptor.FieldDescriptorProto_TYPE_FLOAT:
+ if packed {
+ val := p.reverseListRange(`m.`, fieldname)
+ p.P(`f`, numGen.Next(), ` := `, p.mathPkg.Use(), `.Float32bits(float32(`, val, `))`)
+ p.callFixed32("f" + numGen.Current())
+ p.Out()
+ p.P(`}`)
+ p.callVarint(`len(m.`, fieldname, `) * 4`)
+ p.encodeKey(fieldNumber, wireType)
+ } else if repeated {
+ val := p.reverseListRange(`m.`, fieldname)
+ p.P(`f`, numGen.Next(), ` := `, p.mathPkg.Use(), `.Float32bits(float32(`, val, `))`)
+ p.callFixed32("f" + numGen.Current())
+ p.encodeKey(fieldNumber, wireType)
+ p.Out()
+ p.P(`}`)
+ } else if proto3 {
+ p.P(`if m.`, fieldname, ` != 0 {`)
+ p.In()
+ p.callFixed32(p.mathPkg.Use(), `.Float32bits(float32(m.`+fieldname, `))`)
+ p.encodeKey(fieldNumber, wireType)
+ p.Out()
+ p.P(`}`)
+ } else if !nullable {
+ p.callFixed32(p.mathPkg.Use(), `.Float32bits(float32(m.`+fieldname, `))`)
+ p.encodeKey(fieldNumber, wireType)
+ } else {
+ p.callFixed32(p.mathPkg.Use(), `.Float32bits(float32(*m.`+fieldname, `))`)
+ p.encodeKey(fieldNumber, wireType)
+ }
+ case descriptor.FieldDescriptorProto_TYPE_INT64,
+ descriptor.FieldDescriptorProto_TYPE_UINT64,
+ descriptor.FieldDescriptorProto_TYPE_INT32,
+ descriptor.FieldDescriptorProto_TYPE_UINT32,
+ descriptor.FieldDescriptorProto_TYPE_ENUM:
+ if packed {
+ jvar := "j" + numGen.Next()
+ p.P(`dAtA`, numGen.Next(), ` := make([]byte, len(m.`, fieldname, `)*10)`)
+ p.P(`var `, jvar, ` int`)
+ if *field.Type == descriptor.FieldDescriptorProto_TYPE_INT64 ||
+ *field.Type == descriptor.FieldDescriptorProto_TYPE_INT32 {
+ p.P(`for _, num1 := range m.`, fieldname, ` {`)
+ p.In()
+ p.P(`num := uint64(num1)`)
+ } else {
+ p.P(`for _, num := range m.`, fieldname, ` {`)
+ p.In()
+ }
+ p.P(`for num >= 1<<7 {`)
+ p.In()
+ p.P(`dAtA`, numGen.Current(), `[`, jvar, `] = uint8(uint64(num)&0x7f|0x80)`)
+ p.P(`num >>= 7`)
+ p.P(jvar, `++`)
+ p.Out()
+ p.P(`}`)
+ p.P(`dAtA`, numGen.Current(), `[`, jvar, `] = uint8(num)`)
+ p.P(jvar, `++`)
+ p.Out()
+ p.P(`}`)
+ p.P(`i -= `, jvar)
+ p.P(`copy(dAtA[i:], dAtA`, numGen.Current(), `[:`, jvar, `])`)
+ p.callVarint(jvar)
+ p.encodeKey(fieldNumber, wireType)
+ } else if repeated {
+ val := p.reverseListRange(`m.`, fieldname)
+ p.callVarint(val)
+ p.encodeKey(fieldNumber, wireType)
+ p.Out()
+ p.P(`}`)
+ } else if proto3 {
+ p.P(`if m.`, fieldname, ` != 0 {`)
+ p.In()
+ p.callVarint(`m.`, fieldname)
+ p.encodeKey(fieldNumber, wireType)
+ p.Out()
+ p.P(`}`)
+ } else if !nullable {
+ p.callVarint(`m.`, fieldname)
+ p.encodeKey(fieldNumber, wireType)
+ } else {
+ p.callVarint(`*m.`, fieldname)
+ p.encodeKey(fieldNumber, wireType)
+ }
+ case descriptor.FieldDescriptorProto_TYPE_FIXED64,
+ descriptor.FieldDescriptorProto_TYPE_SFIXED64:
+ if packed {
+ val := p.reverseListRange(`m.`, fieldname)
+ p.callFixed64(val)
+ p.Out()
+ p.P(`}`)
+ p.callVarint(`len(m.`, fieldname, `) * 8`)
+ p.encodeKey(fieldNumber, wireType)
+ } else if repeated {
+ val := p.reverseListRange(`m.`, fieldname)
+ p.callFixed64(val)
+ p.encodeKey(fieldNumber, wireType)
+ p.Out()
+ p.P(`}`)
+ } else if proto3 {
+ p.P(`if m.`, fieldname, ` != 0 {`)
+ p.In()
+ p.callFixed64("m." + fieldname)
+ p.encodeKey(fieldNumber, wireType)
+ p.Out()
+ p.P(`}`)
+ } else if !nullable {
+ p.callFixed64("m." + fieldname)
+ p.encodeKey(fieldNumber, wireType)
+ } else {
+ p.callFixed64("*m." + fieldname)
+ p.encodeKey(fieldNumber, wireType)
+ }
+ case descriptor.FieldDescriptorProto_TYPE_FIXED32,
+ descriptor.FieldDescriptorProto_TYPE_SFIXED32:
+ if packed {
+ val := p.reverseListRange(`m.`, fieldname)
+ p.callFixed32(val)
+ p.Out()
+ p.P(`}`)
+ p.callVarint(`len(m.`, fieldname, `) * 4`)
+ p.encodeKey(fieldNumber, wireType)
+ } else if repeated {
+ val := p.reverseListRange(`m.`, fieldname)
+ p.callFixed32(val)
+ p.encodeKey(fieldNumber, wireType)
+ p.Out()
+ p.P(`}`)
+ } else if proto3 {
+ p.P(`if m.`, fieldname, ` != 0 {`)
+ p.In()
+ p.callFixed32("m." + fieldname)
+ p.encodeKey(fieldNumber, wireType)
+ p.Out()
+ p.P(`}`)
+ } else if !nullable {
+ p.callFixed32("m." + fieldname)
+ p.encodeKey(fieldNumber, wireType)
+ } else {
+ p.callFixed32("*m." + fieldname)
+ p.encodeKey(fieldNumber, wireType)
+ }
+ case descriptor.FieldDescriptorProto_TYPE_BOOL:
+ if packed {
+ val := p.reverseListRange(`m.`, fieldname)
+ p.P(`i--`)
+ p.P(`if `, val, ` {`)
+ p.In()
+ p.P(`dAtA[i] = 1`)
+ p.Out()
+ p.P(`} else {`)
+ p.In()
+ p.P(`dAtA[i] = 0`)
+ p.Out()
+ p.P(`}`)
+ p.Out()
+ p.P(`}`)
+ p.callVarint(`len(m.`, fieldname, `)`)
+ p.encodeKey(fieldNumber, wireType)
+ } else if repeated {
+ val := p.reverseListRange(`m.`, fieldname)
+ p.P(`i--`)
+ p.P(`if `, val, ` {`)
+ p.In()
+ p.P(`dAtA[i] = 1`)
+ p.Out()
+ p.P(`} else {`)
+ p.In()
+ p.P(`dAtA[i] = 0`)
+ p.Out()
+ p.P(`}`)
+ p.encodeKey(fieldNumber, wireType)
+ p.Out()
+ p.P(`}`)
+ } else if proto3 {
+ p.P(`if m.`, fieldname, ` {`)
+ p.In()
+ p.P(`i--`)
+ p.P(`if m.`, fieldname, ` {`)
+ p.In()
+ p.P(`dAtA[i] = 1`)
+ p.Out()
+ p.P(`} else {`)
+ p.In()
+ p.P(`dAtA[i] = 0`)
+ p.Out()
+ p.P(`}`)
+ p.encodeKey(fieldNumber, wireType)
+ p.Out()
+ p.P(`}`)
+ } else if !nullable {
+ p.P(`i--`)
+ p.P(`if m.`, fieldname, ` {`)
+ p.In()
+ p.P(`dAtA[i] = 1`)
+ p.Out()
+ p.P(`} else {`)
+ p.In()
+ p.P(`dAtA[i] = 0`)
+ p.Out()
+ p.P(`}`)
+ p.encodeKey(fieldNumber, wireType)
+ } else {
+ p.P(`i--`)
+ p.P(`if *m.`, fieldname, ` {`)
+ p.In()
+ p.P(`dAtA[i] = 1`)
+ p.Out()
+ p.P(`} else {`)
+ p.In()
+ p.P(`dAtA[i] = 0`)
+ p.Out()
+ p.P(`}`)
+ p.encodeKey(fieldNumber, wireType)
+ }
+ case descriptor.FieldDescriptorProto_TYPE_STRING:
+ if repeated {
+ val := p.reverseListRange(`m.`, fieldname)
+ p.P(`i -= len(`, val, `)`)
+ p.P(`copy(dAtA[i:], `, val, `)`)
+ p.callVarint(`len(`, val, `)`)
+ p.encodeKey(fieldNumber, wireType)
+ p.Out()
+ p.P(`}`)
+ } else if proto3 {
+ p.P(`if len(m.`, fieldname, `) > 0 {`)
+ p.In()
+ p.P(`i -= len(m.`, fieldname, `)`)
+ p.P(`copy(dAtA[i:], m.`, fieldname, `)`)
+ p.callVarint(`len(m.`, fieldname, `)`)
+ p.encodeKey(fieldNumber, wireType)
+ p.Out()
+ p.P(`}`)
+ } else if !nullable {
+ p.P(`i -= len(m.`, fieldname, `)`)
+ p.P(`copy(dAtA[i:], m.`, fieldname, `)`)
+ p.callVarint(`len(m.`, fieldname, `)`)
+ p.encodeKey(fieldNumber, wireType)
+ } else {
+ p.P(`i -= len(*m.`, fieldname, `)`)
+ p.P(`copy(dAtA[i:], *m.`, fieldname, `)`)
+ p.callVarint(`len(*m.`, fieldname, `)`)
+ p.encodeKey(fieldNumber, wireType)
+ }
+ case descriptor.FieldDescriptorProto_TYPE_GROUP:
+ panic(fmt.Errorf("marshaler does not support group %v", fieldname))
+ case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
+ if p.IsMap(field) {
+ m := p.GoMapType(nil, field)
+ keygoTyp, keywire := p.GoType(nil, m.KeyField)
+ keygoAliasTyp, _ := p.GoType(nil, m.KeyAliasField)
+ // keys may not be pointers
+ keygoTyp = strings.Replace(keygoTyp, "*", "", 1)
+ keygoAliasTyp = strings.Replace(keygoAliasTyp, "*", "", 1)
+ keyCapTyp := generator.CamelCase(keygoTyp)
+ valuegoTyp, valuewire := p.GoType(nil, m.ValueField)
+ valuegoAliasTyp, _ := p.GoType(nil, m.ValueAliasField)
+ nullable, valuegoTyp, valuegoAliasTyp = generator.GoMapValueTypes(field, m.ValueField, valuegoTyp, valuegoAliasTyp)
+ var val string
+ if gogoproto.IsStableMarshaler(file.FileDescriptorProto, message.DescriptorProto) {
+ keysName := `keysFor` + fieldname
+ p.P(keysName, ` := make([]`, keygoTyp, `, 0, len(m.`, fieldname, `))`)
+ p.P(`for k := range m.`, fieldname, ` {`)
+ p.In()
+ p.P(keysName, ` = append(`, keysName, `, `, keygoTyp, `(k))`)
+ p.Out()
+ p.P(`}`)
+ p.P(p.sortKeysPkg.Use(), `.`, keyCapTyp, `s(`, keysName, `)`)
+ val = p.reverseListRange(keysName)
+ } else {
+ p.P(`for k := range m.`, fieldname, ` {`)
+ val = "k"
+ p.In()
+ }
+ if gogoproto.IsStableMarshaler(file.FileDescriptorProto, message.DescriptorProto) {
+ p.P(`v := m.`, fieldname, `[`, keygoAliasTyp, `(`, val, `)]`)
+ } else {
+ p.P(`v := m.`, fieldname, `[`, val, `]`)
+ }
+ p.P(`baseI := i`)
+ accessor := `v`
+
+ if m.ValueField.GetType() == descriptor.FieldDescriptorProto_TYPE_MESSAGE {
+ if valuegoTyp != valuegoAliasTyp && !gogoproto.IsStdType(m.ValueAliasField) {
+ if nullable {
+ // cast back to the type that has the generated methods on it
+ accessor = `((` + valuegoTyp + `)(` + accessor + `))`
+ } else {
+ accessor = `((*` + valuegoTyp + `)(&` + accessor + `))`
+ }
+ } else if !nullable {
+ accessor = `(&v)`
+ }
+ }
+
+ nullableMsg := nullable && (m.ValueField.GetType() == descriptor.FieldDescriptorProto_TYPE_MESSAGE ||
+ gogoproto.IsCustomType(field) && m.ValueField.IsBytes())
+ plainBytes := m.ValueField.IsBytes() && !gogoproto.IsCustomType(field)
+ if nullableMsg {
+ p.P(`if `, accessor, ` != nil { `)
+ p.In()
+ } else if plainBytes {
+ if proto3 {
+ p.P(`if len(`, accessor, `) > 0 {`)
+ } else {
+ p.P(`if `, accessor, ` != nil {`)
+ }
+ p.In()
+ }
+ p.mapField(numGen, field, m.ValueAliasField, accessor, protoSizer)
+ p.encodeKey(2, wireToType(valuewire))
+ if nullableMsg || plainBytes {
+ p.Out()
+ p.P(`}`)
+ }
+
+ p.mapField(numGen, field, m.KeyField, val, protoSizer)
+ p.encodeKey(1, wireToType(keywire))
+
+ p.callVarint(`baseI - i`)
+
+ p.encodeKey(fieldNumber, wireType)
+ p.Out()
+ p.P(`}`)
+ } else if repeated {
+ val := p.reverseListRange(`m.`, fieldname)
+ sizeOfVarName := val
+ if gogoproto.IsNullable(field) {
+ sizeOfVarName = `*` + val
+ }
+ if !p.marshalAllSizeOf(field, sizeOfVarName, ``) {
+ if gogoproto.IsCustomType(field) {
+ p.forward(val, true, protoSizer)
+ } else {
+ p.backward(val, true)
+ }
+ }
+ p.encodeKey(fieldNumber, wireType)
+ p.Out()
+ p.P(`}`)
+ } else {
+ sizeOfVarName := `m.` + fieldname
+ if gogoproto.IsNullable(field) {
+ sizeOfVarName = `*` + sizeOfVarName
+ }
+ if !p.marshalAllSizeOf(field, sizeOfVarName, numGen.Next()) {
+ if gogoproto.IsCustomType(field) {
+ p.forward(`m.`+fieldname, true, protoSizer)
+ } else {
+ p.backward(`m.`+fieldname, true)
+ }
+ }
+ p.encodeKey(fieldNumber, wireType)
+ }
+ case descriptor.FieldDescriptorProto_TYPE_BYTES:
+ if !gogoproto.IsCustomType(field) {
+ if repeated {
+ val := p.reverseListRange(`m.`, fieldname)
+ p.P(`i -= len(`, val, `)`)
+ p.P(`copy(dAtA[i:], `, val, `)`)
+ p.callVarint(`len(`, val, `)`)
+ p.encodeKey(fieldNumber, wireType)
+ p.Out()
+ p.P(`}`)
+ } else if proto3 {
+ p.P(`if len(m.`, fieldname, `) > 0 {`)
+ p.In()
+ p.P(`i -= len(m.`, fieldname, `)`)
+ p.P(`copy(dAtA[i:], m.`, fieldname, `)`)
+ p.callVarint(`len(m.`, fieldname, `)`)
+ p.encodeKey(fieldNumber, wireType)
+ p.Out()
+ p.P(`}`)
+ } else {
+ p.P(`i -= len(m.`, fieldname, `)`)
+ p.P(`copy(dAtA[i:], m.`, fieldname, `)`)
+ p.callVarint(`len(m.`, fieldname, `)`)
+ p.encodeKey(fieldNumber, wireType)
+ }
+ } else {
+ if repeated {
+ val := p.reverseListRange(`m.`, fieldname)
+ p.forward(val, true, protoSizer)
+ p.encodeKey(fieldNumber, wireType)
+ p.Out()
+ p.P(`}`)
+ } else {
+ p.forward(`m.`+fieldname, true, protoSizer)
+ p.encodeKey(fieldNumber, wireType)
+ }
+ }
+ case descriptor.FieldDescriptorProto_TYPE_SINT32:
+ if packed {
+ datavar := "dAtA" + numGen.Next()
+ jvar := "j" + numGen.Next()
+ p.P(datavar, ` := make([]byte, len(m.`, fieldname, ")*5)")
+ p.P(`var `, jvar, ` int`)
+ p.P(`for _, num := range m.`, fieldname, ` {`)
+ p.In()
+ xvar := "x" + numGen.Next()
+ p.P(xvar, ` := (uint32(num) << 1) ^ uint32((num >> 31))`)
+ p.P(`for `, xvar, ` >= 1<<7 {`)
+ p.In()
+ p.P(datavar, `[`, jvar, `] = uint8(uint64(`, xvar, `)&0x7f|0x80)`)
+ p.P(jvar, `++`)
+ p.P(xvar, ` >>= 7`)
+ p.Out()
+ p.P(`}`)
+ p.P(datavar, `[`, jvar, `] = uint8(`, xvar, `)`)
+ p.P(jvar, `++`)
+ p.Out()
+ p.P(`}`)
+ p.P(`i -= `, jvar)
+ p.P(`copy(dAtA[i:], `, datavar, `[:`, jvar, `])`)
+ p.callVarint(jvar)
+ p.encodeKey(fieldNumber, wireType)
+ } else if repeated {
+ val := p.reverseListRange(`m.`, fieldname)
+ p.P(`x`, numGen.Next(), ` := (uint32(`, val, `) << 1) ^ uint32((`, val, ` >> 31))`)
+ p.callVarint(`x`, numGen.Current())
+ p.encodeKey(fieldNumber, wireType)
+ p.Out()
+ p.P(`}`)
+ } else if proto3 {
+ p.P(`if m.`, fieldname, ` != 0 {`)
+ p.In()
+ p.callVarint(`(uint32(m.`, fieldname, `) << 1) ^ uint32((m.`, fieldname, ` >> 31))`)
+ p.encodeKey(fieldNumber, wireType)
+ p.Out()
+ p.P(`}`)
+ } else if !nullable {
+ p.callVarint(`(uint32(m.`, fieldname, `) << 1) ^ uint32((m.`, fieldname, ` >> 31))`)
+ p.encodeKey(fieldNumber, wireType)
+ } else {
+ p.callVarint(`(uint32(*m.`, fieldname, `) << 1) ^ uint32((*m.`, fieldname, ` >> 31))`)
+ p.encodeKey(fieldNumber, wireType)
+ }
+ case descriptor.FieldDescriptorProto_TYPE_SINT64:
+ if packed {
+ jvar := "j" + numGen.Next()
+ xvar := "x" + numGen.Next()
+ datavar := "dAtA" + numGen.Next()
+ p.P(`var `, jvar, ` int`)
+ p.P(datavar, ` := make([]byte, len(m.`, fieldname, `)*10)`)
+ p.P(`for _, num := range m.`, fieldname, ` {`)
+ p.In()
+ p.P(xvar, ` := (uint64(num) << 1) ^ uint64((num >> 63))`)
+ p.P(`for `, xvar, ` >= 1<<7 {`)
+ p.In()
+ p.P(datavar, `[`, jvar, `] = uint8(uint64(`, xvar, `)&0x7f|0x80)`)
+ p.P(jvar, `++`)
+ p.P(xvar, ` >>= 7`)
+ p.Out()
+ p.P(`}`)
+ p.P(datavar, `[`, jvar, `] = uint8(`, xvar, `)`)
+ p.P(jvar, `++`)
+ p.Out()
+ p.P(`}`)
+ p.P(`i -= `, jvar)
+ p.P(`copy(dAtA[i:], `, datavar, `[:`, jvar, `])`)
+ p.callVarint(jvar)
+ p.encodeKey(fieldNumber, wireType)
+ } else if repeated {
+ val := p.reverseListRange(`m.`, fieldname)
+ p.P(`x`, numGen.Next(), ` := (uint64(`, val, `) << 1) ^ uint64((`, val, ` >> 63))`)
+ p.callVarint("x" + numGen.Current())
+ p.encodeKey(fieldNumber, wireType)
+ p.Out()
+ p.P(`}`)
+ } else if proto3 {
+ p.P(`if m.`, fieldname, ` != 0 {`)
+ p.In()
+ p.callVarint(`(uint64(m.`, fieldname, `) << 1) ^ uint64((m.`, fieldname, ` >> 63))`)
+ p.encodeKey(fieldNumber, wireType)
+ p.Out()
+ p.P(`}`)
+ } else if !nullable {
+ p.callVarint(`(uint64(m.`, fieldname, `) << 1) ^ uint64((m.`, fieldname, ` >> 63))`)
+ p.encodeKey(fieldNumber, wireType)
+ } else {
+ p.callVarint(`(uint64(*m.`, fieldname, `) << 1) ^ uint64((*m.`, fieldname, ` >> 63))`)
+ p.encodeKey(fieldNumber, wireType)
+ }
+ default:
+ panic("not implemented")
+ }
+ if (required && nullable) || repeated || doNilCheck {
+ p.Out()
+ p.P(`}`)
+ }
+}
+
+func (p *marshalto) Generate(file *generator.FileDescriptor) {
+ numGen := NewNumGen()
+ p.PluginImports = generator.NewPluginImports(p.Generator)
+
+ p.atleastOne = false
+ p.localName = generator.FileName(file)
+
+ p.mathPkg = p.NewImport("math")
+ p.sortKeysPkg = p.NewImport("github.com/gogo/protobuf/sortkeys")
+ p.protoPkg = p.NewImport("github.com/gogo/protobuf/proto")
+ if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
+ p.protoPkg = p.NewImport("github.com/golang/protobuf/proto")
+ }
+ p.errorsPkg = p.NewImport("errors")
+ p.binaryPkg = p.NewImport("encoding/binary")
+ p.typesPkg = p.NewImport("github.com/gogo/protobuf/types")
+
+ for _, message := range file.Messages() {
+ if message.DescriptorProto.GetOptions().GetMapEntry() {
+ continue
+ }
+ ccTypeName := generator.CamelCaseSlice(message.TypeName())
+ if !gogoproto.IsMarshaler(file.FileDescriptorProto, message.DescriptorProto) &&
+ !gogoproto.IsUnsafeMarshaler(file.FileDescriptorProto, message.DescriptorProto) {
+ continue
+ }
+ p.atleastOne = true
+
+ p.P(`func (m *`, ccTypeName, `) Marshal() (dAtA []byte, err error) {`)
+ p.In()
+ if gogoproto.IsProtoSizer(file.FileDescriptorProto, message.DescriptorProto) {
+ p.P(`size := m.ProtoSize()`)
+ } else {
+ p.P(`size := m.Size()`)
+ }
+ p.P(`dAtA = make([]byte, size)`)
+ p.P(`n, err := m.MarshalToSizedBuffer(dAtA[:size])`)
+ p.P(`if err != nil {`)
+ p.In()
+ p.P(`return nil, err`)
+ p.Out()
+ p.P(`}`)
+ p.P(`return dAtA[:n], nil`)
+ p.Out()
+ p.P(`}`)
+ p.P(``)
+ p.P(`func (m *`, ccTypeName, `) MarshalTo(dAtA []byte) (int, error) {`)
+ p.In()
+ if gogoproto.IsProtoSizer(file.FileDescriptorProto, message.DescriptorProto) {
+ p.P(`size := m.ProtoSize()`)
+ } else {
+ p.P(`size := m.Size()`)
+ }
+ p.P(`return m.MarshalToSizedBuffer(dAtA[:size])`)
+ p.Out()
+ p.P(`}`)
+ p.P(``)
+ p.P(`func (m *`, ccTypeName, `) MarshalToSizedBuffer(dAtA []byte) (int, error) {`)
+ p.In()
+ p.P(`i := len(dAtA)`)
+ p.P(`_ = i`)
+ p.P(`var l int`)
+ p.P(`_ = l`)
+ if gogoproto.HasUnrecognized(file.FileDescriptorProto, message.DescriptorProto) {
+ p.P(`if m.XXX_unrecognized != nil {`)
+ p.In()
+ p.P(`i -= len(m.XXX_unrecognized)`)
+ p.P(`copy(dAtA[i:], m.XXX_unrecognized)`)
+ p.Out()
+ p.P(`}`)
+ }
+ if message.DescriptorProto.HasExtension() {
+ if gogoproto.HasExtensionsMap(file.FileDescriptorProto, message.DescriptorProto) {
+ p.P(`if n, err := `, p.protoPkg.Use(), `.EncodeInternalExtensionBackwards(m, dAtA[:i]); err != nil {`)
+ p.In()
+ p.P(`return 0, err`)
+ p.Out()
+ p.P(`} else {`)
+ p.In()
+ p.P(`i -= n`)
+ p.Out()
+ p.P(`}`)
+ } else {
+ p.P(`if m.XXX_extensions != nil {`)
+ p.In()
+ p.P(`i -= len(m.XXX_extensions)`)
+ p.P(`copy(dAtA[i:], m.XXX_extensions)`)
+ p.Out()
+ p.P(`}`)
+ }
+ }
+ fields := orderFields(message.GetField())
+ sort.Sort(fields)
+ oneofs := make(map[string]struct{})
+ for i := len(message.Field) - 1; i >= 0; i-- {
+ field := message.Field[i]
+ oneof := field.OneofIndex != nil
+ if !oneof {
+ proto3 := gogoproto.IsProto3(file.FileDescriptorProto)
+ p.generateField(proto3, numGen, file, message, field)
+ } else {
+ fieldname := p.GetFieldName(message, field)
+ if _, ok := oneofs[fieldname]; !ok {
+ oneofs[fieldname] = struct{}{}
+ p.P(`if m.`, fieldname, ` != nil {`)
+ p.In()
+ p.forward(`m.`+fieldname, false, gogoproto.IsProtoSizer(file.FileDescriptorProto, message.DescriptorProto))
+ p.Out()
+ p.P(`}`)
+ }
+ }
+ }
+ p.P(`return len(dAtA) - i, nil`)
+ p.Out()
+ p.P(`}`)
+ p.P()
+
+ //Generate MarshalTo methods for oneof fields
+ m := proto.Clone(message.DescriptorProto).(*descriptor.DescriptorProto)
+ for _, field := range m.Field {
+ oneof := field.OneofIndex != nil
+ if !oneof {
+ continue
+ }
+ ccTypeName := p.OneOfTypeName(message, field)
+ p.P(`func (m *`, ccTypeName, `) MarshalTo(dAtA []byte) (int, error) {`)
+ p.In()
+ if gogoproto.IsProtoSizer(file.FileDescriptorProto, message.DescriptorProto) {
+ p.P(`size := m.ProtoSize()`)
+ } else {
+ p.P(`size := m.Size()`)
+ }
+ p.P(`return m.MarshalToSizedBuffer(dAtA[:size])`)
+ p.Out()
+ p.P(`}`)
+ p.P(``)
+ p.P(`func (m *`, ccTypeName, `) MarshalToSizedBuffer(dAtA []byte) (int, error) {`)
+ p.In()
+ p.P(`i := len(dAtA)`)
+ vanity.TurnOffNullableForNativeTypes(field)
+ p.generateField(false, numGen, file, message, field)
+ p.P(`return len(dAtA) - i, nil`)
+ p.Out()
+ p.P(`}`)
+ }
+ }
+
+ if p.atleastOne {
+ p.P(`func encodeVarint`, p.localName, `(dAtA []byte, offset int, v uint64) int {`)
+ p.In()
+ p.P(`offset -= sov`, p.localName, `(v)`)
+ p.P(`base := offset`)
+ p.P(`for v >= 1<<7 {`)
+ p.In()
+ p.P(`dAtA[offset] = uint8(v&0x7f|0x80)`)
+ p.P(`v >>= 7`)
+ p.P(`offset++`)
+ p.Out()
+ p.P(`}`)
+ p.P(`dAtA[offset] = uint8(v)`)
+ p.P(`return base`)
+ p.Out()
+ p.P(`}`)
+ }
+
+}
+
+func (p *marshalto) reverseListRange(expression ...string) string {
+ exp := strings.Join(expression, "")
+ p.P(`for iNdEx := len(`, exp, `) - 1; iNdEx >= 0; iNdEx-- {`)
+ p.In()
+ return exp + `[iNdEx]`
+}
+
+func (p *marshalto) marshalAllSizeOf(field *descriptor.FieldDescriptorProto, varName, num string) bool {
+ if gogoproto.IsStdTime(field) {
+ p.marshalSizeOf(`StdTimeMarshalTo`, `SizeOfStdTime`, varName, num)
+ } else if gogoproto.IsStdDuration(field) {
+ p.marshalSizeOf(`StdDurationMarshalTo`, `SizeOfStdDuration`, varName, num)
+ } else if gogoproto.IsStdDouble(field) {
+ p.marshalSizeOf(`StdDoubleMarshalTo`, `SizeOfStdDouble`, varName, num)
+ } else if gogoproto.IsStdFloat(field) {
+ p.marshalSizeOf(`StdFloatMarshalTo`, `SizeOfStdFloat`, varName, num)
+ } else if gogoproto.IsStdInt64(field) {
+ p.marshalSizeOf(`StdInt64MarshalTo`, `SizeOfStdInt64`, varName, num)
+ } else if gogoproto.IsStdUInt64(field) {
+ p.marshalSizeOf(`StdUInt64MarshalTo`, `SizeOfStdUInt64`, varName, num)
+ } else if gogoproto.IsStdInt32(field) {
+ p.marshalSizeOf(`StdInt32MarshalTo`, `SizeOfStdInt32`, varName, num)
+ } else if gogoproto.IsStdUInt32(field) {
+ p.marshalSizeOf(`StdUInt32MarshalTo`, `SizeOfStdUInt32`, varName, num)
+ } else if gogoproto.IsStdBool(field) {
+ p.marshalSizeOf(`StdBoolMarshalTo`, `SizeOfStdBool`, varName, num)
+ } else if gogoproto.IsStdString(field) {
+ p.marshalSizeOf(`StdStringMarshalTo`, `SizeOfStdString`, varName, num)
+ } else if gogoproto.IsStdBytes(field) {
+ p.marshalSizeOf(`StdBytesMarshalTo`, `SizeOfStdBytes`, varName, num)
+ } else {
+ return false
+ }
+ return true
+}
+
+func (p *marshalto) marshalSizeOf(marshal, size, varName, num string) {
+ p.P(`n`, num, `, err`, num, ` := `, p.typesPkg.Use(), `.`, marshal, `(`, varName, `, dAtA[i-`, p.typesPkg.Use(), `.`, size, `(`, varName, `):])`)
+ p.P(`if err`, num, ` != nil {`)
+ p.In()
+ p.P(`return 0, err`, num)
+ p.Out()
+ p.P(`}`)
+ p.P(`i -= n`, num)
+ p.callVarint(`n`, num)
+}
+
+func (p *marshalto) backward(varName string, varInt bool) {
+ p.P(`{`)
+ p.In()
+ p.P(`size, err := `, varName, `.MarshalToSizedBuffer(dAtA[:i])`)
+ p.P(`if err != nil {`)
+ p.In()
+ p.P(`return 0, err`)
+ p.Out()
+ p.P(`}`)
+ p.P(`i -= size`)
+ if varInt {
+ p.callVarint(`size`)
+ }
+ p.Out()
+ p.P(`}`)
+}
+
+func (p *marshalto) forward(varName string, varInt, protoSizer bool) {
+ p.P(`{`)
+ p.In()
+ if protoSizer {
+ p.P(`size := `, varName, `.ProtoSize()`)
+ } else {
+ p.P(`size := `, varName, `.Size()`)
+ }
+ p.P(`i -= size`)
+ p.P(`if _, err := `, varName, `.MarshalTo(dAtA[i:]); err != nil {`)
+ p.In()
+ p.P(`return 0, err`)
+ p.Out()
+ p.P(`}`)
+ p.Out()
+ if varInt {
+ p.callVarint(`size`)
+ }
+ p.P(`}`)
+}
+
+func init() {
+ generator.RegisterPlugin(NewMarshal())
+}
diff --git a/vendor/github.com/gogo/protobuf/plugin/oneofcheck/oneofcheck.go b/vendor/github.com/gogo/protobuf/plugin/oneofcheck/oneofcheck.go
new file mode 100644
index 00000000000..0f822e8a8ac
--- /dev/null
+++ b/vendor/github.com/gogo/protobuf/plugin/oneofcheck/oneofcheck.go
@@ -0,0 +1,93 @@
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2013, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// 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.
+//
+// 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.
+
+/*
+The oneofcheck plugin is used to check whether oneof is not used incorrectly.
+For instance:
+An error is caused if a oneof field:
+ - is used in a face
+ - is an embedded field
+
+*/
+package oneofcheck
+
+import (
+ "fmt"
+ "github.com/gogo/protobuf/gogoproto"
+ "github.com/gogo/protobuf/protoc-gen-gogo/generator"
+ "os"
+)
+
+type plugin struct {
+ *generator.Generator
+}
+
+func NewPlugin() *plugin {
+ return &plugin{}
+}
+
+func (p *plugin) Name() string {
+ return "oneofcheck"
+}
+
+func (p *plugin) Init(g *generator.Generator) {
+ p.Generator = g
+}
+
+func (p *plugin) Generate(file *generator.FileDescriptor) {
+ for _, msg := range file.Messages() {
+ face := gogoproto.IsFace(file.FileDescriptorProto, msg.DescriptorProto)
+ for _, field := range msg.GetField() {
+ if field.OneofIndex == nil {
+ continue
+ }
+ if face {
+ fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot be in a face and oneof\n", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
+ os.Exit(1)
+ }
+ if gogoproto.IsEmbed(field) {
+ fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot be in an oneof and an embedded field\n", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
+ os.Exit(1)
+ }
+ if !gogoproto.IsNullable(field) {
+ fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot be in an oneof and a non-nullable field\n", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
+ os.Exit(1)
+ }
+ if gogoproto.IsUnion(file.FileDescriptorProto, msg.DescriptorProto) {
+ fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot be in an oneof and in an union (deprecated)\n", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
+ os.Exit(1)
+ }
+ }
+ }
+}
+
+func (p *plugin) GenerateImports(*generator.FileDescriptor) {}
+
+func init() {
+ generator.RegisterPlugin(NewPlugin())
+}
diff --git a/vendor/github.com/gogo/protobuf/plugin/populate/populate.go b/vendor/github.com/gogo/protobuf/plugin/populate/populate.go
new file mode 100644
index 00000000000..da705945c33
--- /dev/null
+++ b/vendor/github.com/gogo/protobuf/plugin/populate/populate.go
@@ -0,0 +1,815 @@
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2013, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// 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.
+//
+// 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.
+
+/*
+The populate plugin generates a NewPopulated function.
+This function returns a newly populated structure.
+
+It is enabled by the following extensions:
+
+ - populate
+ - populate_all
+
+Let us look at:
+
+ github.com/gogo/protobuf/test/example/example.proto
+
+Btw all the output can be seen at:
+
+ github.com/gogo/protobuf/test/example/*
+
+The following message:
+
+ option (gogoproto.populate_all) = true;
+
+ message B {
+ optional A A = 1 [(gogoproto.nullable) = false, (gogoproto.embed) = true];
+ repeated bytes G = 2 [(gogoproto.customtype) = "github.com/gogo/protobuf/test/custom.Uint128", (gogoproto.nullable) = false];
+ }
+
+given to the populate plugin, will generate code the following code:
+
+ func NewPopulatedB(r randyExample, easy bool) *B {
+ this := &B{}
+ v2 := NewPopulatedA(r, easy)
+ this.A = *v2
+ if r.Intn(10) != 0 {
+ v3 := r.Intn(10)
+ this.G = make([]github_com_gogo_protobuf_test_custom.Uint128, v3)
+ for i := 0; i < v3; i++ {
+ v4 := github_com_gogo_protobuf_test_custom.NewPopulatedUint128(r)
+ this.G[i] = *v4
+ }
+ }
+ if !easy && r.Intn(10) != 0 {
+ this.XXX_unrecognized = randUnrecognizedExample(r, 3)
+ }
+ return this
+ }
+
+The idea that is useful for testing.
+Most of the other plugins' generated test code uses it.
+You will still be able to use the generated test code of other packages
+if you turn off the popluate plugin and write your own custom NewPopulated function.
+
+If the easy flag is not set the XXX_unrecognized and XXX_extensions fields are also populated.
+These have caused problems with JSON marshalling and unmarshalling tests.
+
+*/
+package populate
+
+import (
+ "fmt"
+ "math"
+ "strconv"
+ "strings"
+
+ "github.com/gogo/protobuf/gogoproto"
+ "github.com/gogo/protobuf/proto"
+ descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
+ "github.com/gogo/protobuf/protoc-gen-gogo/generator"
+ "github.com/gogo/protobuf/vanity"
+)
+
+type VarGen interface {
+ Next() string
+ Current() string
+}
+
+type varGen struct {
+ index int64
+}
+
+func NewVarGen() VarGen {
+ return &varGen{0}
+}
+
+func (this *varGen) Next() string {
+ this.index++
+ return fmt.Sprintf("v%d", this.index)
+}
+
+func (this *varGen) Current() string {
+ return fmt.Sprintf("v%d", this.index)
+}
+
+type plugin struct {
+ *generator.Generator
+ generator.PluginImports
+ varGen VarGen
+ atleastOne bool
+ localName string
+ typesPkg generator.Single
+}
+
+func NewPlugin() *plugin {
+ return &plugin{}
+}
+
+func (p *plugin) Name() string {
+ return "populate"
+}
+
+func (p *plugin) Init(g *generator.Generator) {
+ p.Generator = g
+}
+
+func value(typeName string, fieldType descriptor.FieldDescriptorProto_Type) string {
+ switch fieldType {
+ case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
+ return typeName + "(r.Float64())"
+ case descriptor.FieldDescriptorProto_TYPE_FLOAT:
+ return typeName + "(r.Float32())"
+ case descriptor.FieldDescriptorProto_TYPE_INT64,
+ descriptor.FieldDescriptorProto_TYPE_SFIXED64,
+ descriptor.FieldDescriptorProto_TYPE_SINT64:
+ return typeName + "(r.Int63())"
+ case descriptor.FieldDescriptorProto_TYPE_UINT64,
+ descriptor.FieldDescriptorProto_TYPE_FIXED64:
+ return typeName + "(uint64(r.Uint32()))"
+ case descriptor.FieldDescriptorProto_TYPE_INT32,
+ descriptor.FieldDescriptorProto_TYPE_SINT32,
+ descriptor.FieldDescriptorProto_TYPE_SFIXED32,
+ descriptor.FieldDescriptorProto_TYPE_ENUM:
+ return typeName + "(r.Int31())"
+ case descriptor.FieldDescriptorProto_TYPE_UINT32,
+ descriptor.FieldDescriptorProto_TYPE_FIXED32:
+ return typeName + "(r.Uint32())"
+ case descriptor.FieldDescriptorProto_TYPE_BOOL:
+ return typeName + `(bool(r.Intn(2) == 0))`
+ case descriptor.FieldDescriptorProto_TYPE_STRING,
+ descriptor.FieldDescriptorProto_TYPE_GROUP,
+ descriptor.FieldDescriptorProto_TYPE_MESSAGE,
+ descriptor.FieldDescriptorProto_TYPE_BYTES:
+ }
+ panic(fmt.Errorf("unexpected type %v", typeName))
+}
+
+func negative(fieldType descriptor.FieldDescriptorProto_Type) bool {
+ switch fieldType {
+ case descriptor.FieldDescriptorProto_TYPE_UINT64,
+ descriptor.FieldDescriptorProto_TYPE_FIXED64,
+ descriptor.FieldDescriptorProto_TYPE_UINT32,
+ descriptor.FieldDescriptorProto_TYPE_FIXED32,
+ descriptor.FieldDescriptorProto_TYPE_BOOL:
+ return false
+ }
+ return true
+}
+
+func (p *plugin) getFuncName(goTypName string, field *descriptor.FieldDescriptorProto) string {
+ funcName := "NewPopulated" + goTypName
+ goTypNames := strings.Split(goTypName, ".")
+ if len(goTypNames) == 2 {
+ funcName = goTypNames[0] + ".NewPopulated" + goTypNames[1]
+ } else if len(goTypNames) != 1 {
+ panic(fmt.Errorf("unreachable: too many dots in %v", goTypName))
+ }
+ if field != nil {
+ switch {
+ case gogoproto.IsStdTime(field):
+ funcName = p.typesPkg.Use() + ".NewPopulatedStdTime"
+ case gogoproto.IsStdDuration(field):
+ funcName = p.typesPkg.Use() + ".NewPopulatedStdDuration"
+ case gogoproto.IsStdDouble(field):
+ funcName = p.typesPkg.Use() + ".NewPopulatedStdDouble"
+ case gogoproto.IsStdFloat(field):
+ funcName = p.typesPkg.Use() + ".NewPopulatedStdFloat"
+ case gogoproto.IsStdInt64(field):
+ funcName = p.typesPkg.Use() + ".NewPopulatedStdInt64"
+ case gogoproto.IsStdUInt64(field):
+ funcName = p.typesPkg.Use() + ".NewPopulatedStdUInt64"
+ case gogoproto.IsStdInt32(field):
+ funcName = p.typesPkg.Use() + ".NewPopulatedStdInt32"
+ case gogoproto.IsStdUInt32(field):
+ funcName = p.typesPkg.Use() + ".NewPopulatedStdUInt32"
+ case gogoproto.IsStdBool(field):
+ funcName = p.typesPkg.Use() + ".NewPopulatedStdBool"
+ case gogoproto.IsStdString(field):
+ funcName = p.typesPkg.Use() + ".NewPopulatedStdString"
+ case gogoproto.IsStdBytes(field):
+ funcName = p.typesPkg.Use() + ".NewPopulatedStdBytes"
+ }
+ }
+ return funcName
+}
+
+func (p *plugin) getFuncCall(goTypName string, field *descriptor.FieldDescriptorProto) string {
+ funcName := p.getFuncName(goTypName, field)
+ funcCall := funcName + "(r, easy)"
+ return funcCall
+}
+
+func (p *plugin) getCustomFuncCall(goTypName string) string {
+ funcName := p.getFuncName(goTypName, nil)
+ funcCall := funcName + "(r)"
+ return funcCall
+}
+
+func (p *plugin) getEnumVal(field *descriptor.FieldDescriptorProto, goTyp string) string {
+ enum := p.ObjectNamed(field.GetTypeName()).(*generator.EnumDescriptor)
+ l := len(enum.Value)
+ values := make([]string, l)
+ for i := range enum.Value {
+ values[i] = strconv.Itoa(int(*enum.Value[i].Number))
+ }
+ arr := "[]int32{" + strings.Join(values, ",") + "}"
+ val := strings.Join([]string{generator.GoTypeToName(goTyp), `(`, arr, `[r.Intn(`, fmt.Sprintf("%d", l), `)])`}, "")
+ return val
+}
+
+func (p *plugin) GenerateField(file *generator.FileDescriptor, message *generator.Descriptor, field *descriptor.FieldDescriptorProto) {
+ proto3 := gogoproto.IsProto3(file.FileDescriptorProto)
+ goTyp, _ := p.GoType(message, field)
+ fieldname := p.GetOneOfFieldName(message, field)
+ goTypName := generator.GoTypeToName(goTyp)
+ if p.IsMap(field) {
+ m := p.GoMapType(nil, field)
+ keygoTyp, _ := p.GoType(nil, m.KeyField)
+ keygoTyp = strings.Replace(keygoTyp, "*", "", 1)
+ keygoAliasTyp, _ := p.GoType(nil, m.KeyAliasField)
+ keygoAliasTyp = strings.Replace(keygoAliasTyp, "*", "", 1)
+
+ valuegoTyp, _ := p.GoType(nil, m.ValueField)
+ valuegoAliasTyp, _ := p.GoType(nil, m.ValueAliasField)
+ keytypName := generator.GoTypeToName(keygoTyp)
+ keygoAliasTyp = generator.GoTypeToName(keygoAliasTyp)
+ valuetypAliasName := generator.GoTypeToName(valuegoAliasTyp)
+
+ nullable, valuegoTyp, valuegoAliasTyp := generator.GoMapValueTypes(field, m.ValueField, valuegoTyp, valuegoAliasTyp)
+
+ p.P(p.varGen.Next(), ` := r.Intn(10)`)
+ p.P(`this.`, fieldname, ` = make(`, m.GoType, `)`)
+ p.P(`for i := 0; i < `, p.varGen.Current(), `; i++ {`)
+ p.In()
+ keyval := ""
+ if m.KeyField.IsString() {
+ keyval = fmt.Sprintf("randString%v(r)", p.localName)
+ } else {
+ keyval = value(keytypName, m.KeyField.GetType())
+ }
+ if keygoAliasTyp != keygoTyp {
+ keyval = keygoAliasTyp + `(` + keyval + `)`
+ }
+ if m.ValueField.IsMessage() || p.IsGroup(field) ||
+ (m.ValueField.IsBytes() && gogoproto.IsCustomType(field)) {
+ s := `this.` + fieldname + `[` + keyval + `] = `
+ if gogoproto.IsStdType(field) {
+ valuegoTyp = valuegoAliasTyp
+ }
+ funcCall := p.getCustomFuncCall(goTypName)
+ if !gogoproto.IsCustomType(field) {
+ goTypName = generator.GoTypeToName(valuegoTyp)
+ funcCall = p.getFuncCall(goTypName, m.ValueAliasField)
+ }
+ if !nullable {
+ funcCall = `*` + funcCall
+ }
+ if valuegoTyp != valuegoAliasTyp {
+ funcCall = `(` + valuegoAliasTyp + `)(` + funcCall + `)`
+ }
+ s += funcCall
+ p.P(s)
+ } else if m.ValueField.IsEnum() {
+ s := `this.` + fieldname + `[` + keyval + `]` + ` = ` + p.getEnumVal(m.ValueField, valuegoTyp)
+ p.P(s)
+ } else if m.ValueField.IsBytes() {
+ count := p.varGen.Next()
+ p.P(count, ` := r.Intn(100)`)
+ p.P(p.varGen.Next(), ` := `, keyval)
+ p.P(`this.`, fieldname, `[`, p.varGen.Current(), `] = make(`, valuegoTyp, `, `, count, `)`)
+ p.P(`for i := 0; i < `, count, `; i++ {`)
+ p.In()
+ p.P(`this.`, fieldname, `[`, p.varGen.Current(), `][i] = byte(r.Intn(256))`)
+ p.Out()
+ p.P(`}`)
+ } else if m.ValueField.IsString() {
+ s := `this.` + fieldname + `[` + keyval + `]` + ` = ` + fmt.Sprintf("randString%v(r)", p.localName)
+ p.P(s)
+ } else {
+ p.P(p.varGen.Next(), ` := `, keyval)
+ p.P(`this.`, fieldname, `[`, p.varGen.Current(), `] = `, value(valuetypAliasName, m.ValueField.GetType()))
+ if negative(m.ValueField.GetType()) {
+ p.P(`if r.Intn(2) == 0 {`)
+ p.In()
+ p.P(`this.`, fieldname, `[`, p.varGen.Current(), `] *= -1`)
+ p.Out()
+ p.P(`}`)
+ }
+ }
+ p.Out()
+ p.P(`}`)
+ } else if gogoproto.IsCustomType(field) {
+ funcCall := p.getCustomFuncCall(goTypName)
+ if field.IsRepeated() {
+ p.P(p.varGen.Next(), ` := r.Intn(10)`)
+ p.P(`this.`, fieldname, ` = make(`, goTyp, `, `, p.varGen.Current(), `)`)
+ p.P(`for i := 0; i < `, p.varGen.Current(), `; i++ {`)
+ p.In()
+ p.P(p.varGen.Next(), `:= `, funcCall)
+ p.P(`this.`, fieldname, `[i] = *`, p.varGen.Current())
+ p.Out()
+ p.P(`}`)
+ } else if gogoproto.IsNullable(field) {
+ p.P(`this.`, fieldname, ` = `, funcCall)
+ } else {
+ p.P(p.varGen.Next(), `:= `, funcCall)
+ p.P(`this.`, fieldname, ` = *`, p.varGen.Current())
+ }
+ } else if field.IsMessage() || p.IsGroup(field) {
+ funcCall := p.getFuncCall(goTypName, field)
+ if field.IsRepeated() {
+ p.P(p.varGen.Next(), ` := r.Intn(5)`)
+ p.P(`this.`, fieldname, ` = make(`, goTyp, `, `, p.varGen.Current(), `)`)
+ p.P(`for i := 0; i < `, p.varGen.Current(), `; i++ {`)
+ p.In()
+ if gogoproto.IsNullable(field) {
+ p.P(`this.`, fieldname, `[i] = `, funcCall)
+ } else {
+ p.P(p.varGen.Next(), `:= `, funcCall)
+ p.P(`this.`, fieldname, `[i] = *`, p.varGen.Current())
+ }
+ p.Out()
+ p.P(`}`)
+ } else {
+ if gogoproto.IsNullable(field) {
+ p.P(`this.`, fieldname, ` = `, funcCall)
+ } else {
+ p.P(p.varGen.Next(), `:= `, funcCall)
+ p.P(`this.`, fieldname, ` = *`, p.varGen.Current())
+ }
+ }
+ } else {
+ if field.IsEnum() {
+ val := p.getEnumVal(field, goTyp)
+ if field.IsRepeated() {
+ p.P(p.varGen.Next(), ` := r.Intn(10)`)
+ p.P(`this.`, fieldname, ` = make(`, goTyp, `, `, p.varGen.Current(), `)`)
+ p.P(`for i := 0; i < `, p.varGen.Current(), `; i++ {`)
+ p.In()
+ p.P(`this.`, fieldname, `[i] = `, val)
+ p.Out()
+ p.P(`}`)
+ } else if !gogoproto.IsNullable(field) || proto3 {
+ p.P(`this.`, fieldname, ` = `, val)
+ } else {
+ p.P(p.varGen.Next(), ` := `, val)
+ p.P(`this.`, fieldname, ` = &`, p.varGen.Current())
+ }
+ } else if field.IsBytes() {
+ if field.IsRepeated() {
+ p.P(p.varGen.Next(), ` := r.Intn(10)`)
+ p.P(`this.`, fieldname, ` = make(`, goTyp, `, `, p.varGen.Current(), `)`)
+ p.P(`for i := 0; i < `, p.varGen.Current(), `; i++ {`)
+ p.In()
+ p.P(p.varGen.Next(), ` := r.Intn(100)`)
+ p.P(`this.`, fieldname, `[i] = make([]byte,`, p.varGen.Current(), `)`)
+ p.P(`for j := 0; j < `, p.varGen.Current(), `; j++ {`)
+ p.In()
+ p.P(`this.`, fieldname, `[i][j] = byte(r.Intn(256))`)
+ p.Out()
+ p.P(`}`)
+ p.Out()
+ p.P(`}`)
+ } else {
+ p.P(p.varGen.Next(), ` := r.Intn(100)`)
+ p.P(`this.`, fieldname, ` = make(`, goTyp, `, `, p.varGen.Current(), `)`)
+ p.P(`for i := 0; i < `, p.varGen.Current(), `; i++ {`)
+ p.In()
+ p.P(`this.`, fieldname, `[i] = byte(r.Intn(256))`)
+ p.Out()
+ p.P(`}`)
+ }
+ } else if field.IsString() {
+ typName := generator.GoTypeToName(goTyp)
+ val := fmt.Sprintf("%s(randString%v(r))", typName, p.localName)
+ if field.IsRepeated() {
+ p.P(p.varGen.Next(), ` := r.Intn(10)`)
+ p.P(`this.`, fieldname, ` = make(`, goTyp, `, `, p.varGen.Current(), `)`)
+ p.P(`for i := 0; i < `, p.varGen.Current(), `; i++ {`)
+ p.In()
+ p.P(`this.`, fieldname, `[i] = `, val)
+ p.Out()
+ p.P(`}`)
+ } else if !gogoproto.IsNullable(field) || proto3 {
+ p.P(`this.`, fieldname, ` = `, val)
+ } else {
+ p.P(p.varGen.Next(), `:= `, val)
+ p.P(`this.`, fieldname, ` = &`, p.varGen.Current())
+ }
+ } else {
+ typName := generator.GoTypeToName(goTyp)
+ if field.IsRepeated() {
+ p.P(p.varGen.Next(), ` := r.Intn(10)`)
+ p.P(`this.`, fieldname, ` = make(`, goTyp, `, `, p.varGen.Current(), `)`)
+ p.P(`for i := 0; i < `, p.varGen.Current(), `; i++ {`)
+ p.In()
+ p.P(`this.`, fieldname, `[i] = `, value(typName, field.GetType()))
+ if negative(field.GetType()) {
+ p.P(`if r.Intn(2) == 0 {`)
+ p.In()
+ p.P(`this.`, fieldname, `[i] *= -1`)
+ p.Out()
+ p.P(`}`)
+ }
+ p.Out()
+ p.P(`}`)
+ } else if !gogoproto.IsNullable(field) || proto3 {
+ p.P(`this.`, fieldname, ` = `, value(typName, field.GetType()))
+ if negative(field.GetType()) {
+ p.P(`if r.Intn(2) == 0 {`)
+ p.In()
+ p.P(`this.`, fieldname, ` *= -1`)
+ p.Out()
+ p.P(`}`)
+ }
+ } else {
+ p.P(p.varGen.Next(), ` := `, value(typName, field.GetType()))
+ if negative(field.GetType()) {
+ p.P(`if r.Intn(2) == 0 {`)
+ p.In()
+ p.P(p.varGen.Current(), ` *= -1`)
+ p.Out()
+ p.P(`}`)
+ }
+ p.P(`this.`, fieldname, ` = &`, p.varGen.Current())
+ }
+ }
+ }
+}
+
+func (p *plugin) hasLoop(pkg string, field *descriptor.FieldDescriptorProto, visited []*generator.Descriptor, excludes []*generator.Descriptor) *generator.Descriptor {
+ if field.IsMessage() || p.IsGroup(field) || p.IsMap(field) {
+ var fieldMessage *generator.Descriptor
+ if p.IsMap(field) {
+ m := p.GoMapType(nil, field)
+ if !m.ValueField.IsMessage() {
+ return nil
+ }
+ fieldMessage = p.ObjectNamed(m.ValueField.GetTypeName()).(*generator.Descriptor)
+ } else {
+ fieldMessage = p.ObjectNamed(field.GetTypeName()).(*generator.Descriptor)
+ }
+ fieldTypeName := generator.CamelCaseSlice(fieldMessage.TypeName())
+ for _, message := range visited {
+ messageTypeName := generator.CamelCaseSlice(message.TypeName())
+ if fieldTypeName == messageTypeName {
+ for _, e := range excludes {
+ if fieldTypeName == generator.CamelCaseSlice(e.TypeName()) {
+ return nil
+ }
+ }
+ return fieldMessage
+ }
+ }
+
+ for _, f := range fieldMessage.Field {
+ if strings.HasPrefix(f.GetTypeName(), "."+pkg) {
+ visited = append(visited, fieldMessage)
+ loopTo := p.hasLoop(pkg, f, visited, excludes)
+ if loopTo != nil {
+ return loopTo
+ }
+ }
+ }
+ }
+ return nil
+}
+
+func (p *plugin) loops(pkg string, field *descriptor.FieldDescriptorProto, message *generator.Descriptor) int {
+ //fmt.Fprintf(os.Stderr, "loops %v %v\n", field.GetTypeName(), generator.CamelCaseSlice(message.TypeName()))
+ excludes := []*generator.Descriptor{}
+ loops := 0
+ for {
+ visited := []*generator.Descriptor{}
+ loopTo := p.hasLoop(pkg, field, visited, excludes)
+ if loopTo == nil {
+ break
+ }
+ //fmt.Fprintf(os.Stderr, "loopTo %v\n", generator.CamelCaseSlice(loopTo.TypeName()))
+ excludes = append(excludes, loopTo)
+ loops++
+ }
+ return loops
+}
+
+func (p *plugin) Generate(file *generator.FileDescriptor) {
+ p.atleastOne = false
+ p.PluginImports = generator.NewPluginImports(p.Generator)
+ p.varGen = NewVarGen()
+ proto3 := gogoproto.IsProto3(file.FileDescriptorProto)
+ p.typesPkg = p.NewImport("github.com/gogo/protobuf/types")
+ p.localName = generator.FileName(file)
+ protoPkg := p.NewImport("github.com/gogo/protobuf/proto")
+ if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
+ protoPkg = p.NewImport("github.com/golang/protobuf/proto")
+ }
+
+ for _, message := range file.Messages() {
+ if !gogoproto.HasPopulate(file.FileDescriptorProto, message.DescriptorProto) {
+ continue
+ }
+ if message.DescriptorProto.GetOptions().GetMapEntry() {
+ continue
+ }
+ p.atleastOne = true
+ ccTypeName := generator.CamelCaseSlice(message.TypeName())
+ loopLevels := make([]int, len(message.Field))
+ maxLoopLevel := 0
+ for i, field := range message.Field {
+ loopLevels[i] = p.loops(file.GetPackage(), field, message)
+ if loopLevels[i] > maxLoopLevel {
+ maxLoopLevel = loopLevels[i]
+ }
+ }
+ ranTotal := 0
+ for i := range loopLevels {
+ ranTotal += int(math.Pow10(maxLoopLevel - loopLevels[i]))
+ }
+ p.P(`func NewPopulated`, ccTypeName, `(r randy`, p.localName, `, easy bool) *`, ccTypeName, ` {`)
+ p.In()
+ p.P(`this := &`, ccTypeName, `{}`)
+ if gogoproto.IsUnion(message.File().FileDescriptorProto, message.DescriptorProto) && len(message.Field) > 0 {
+ p.P(`fieldNum := r.Intn(`, fmt.Sprintf("%d", ranTotal), `)`)
+ p.P(`switch fieldNum {`)
+ k := 0
+ for i, field := range message.Field {
+ is := []string{}
+ ran := int(math.Pow10(maxLoopLevel - loopLevels[i]))
+ for j := 0; j < ran; j++ {
+ is = append(is, fmt.Sprintf("%d", j+k))
+ }
+ k += ran
+ p.P(`case `, strings.Join(is, ","), `:`)
+ p.In()
+ p.GenerateField(file, message, field)
+ p.Out()
+ }
+ p.P(`}`)
+ } else {
+ var maxFieldNumber int32
+ oneofs := make(map[string]struct{})
+ for fieldIndex, field := range message.Field {
+ if field.GetNumber() > maxFieldNumber {
+ maxFieldNumber = field.GetNumber()
+ }
+ oneof := field.OneofIndex != nil
+ if !oneof {
+ if field.IsRequired() || (!gogoproto.IsNullable(field) && !field.IsRepeated()) || (proto3 && !field.IsMessage()) {
+ p.GenerateField(file, message, field)
+ } else {
+ if loopLevels[fieldIndex] > 0 {
+ p.P(`if r.Intn(5) == 0 {`)
+ } else {
+ p.P(`if r.Intn(5) != 0 {`)
+ }
+ p.In()
+ p.GenerateField(file, message, field)
+ p.Out()
+ p.P(`}`)
+ }
+ } else {
+ fieldname := p.GetFieldName(message, field)
+ if _, ok := oneofs[fieldname]; ok {
+ continue
+ } else {
+ oneofs[fieldname] = struct{}{}
+ }
+ fieldNumbers := []int32{}
+ for _, f := range message.Field {
+ fname := p.GetFieldName(message, f)
+ if fname == fieldname {
+ fieldNumbers = append(fieldNumbers, f.GetNumber())
+ }
+ }
+
+ p.P(`oneofNumber_`, fieldname, ` := `, fmt.Sprintf("%#v", fieldNumbers), `[r.Intn(`, strconv.Itoa(len(fieldNumbers)), `)]`)
+ p.P(`switch oneofNumber_`, fieldname, ` {`)
+ for _, f := range message.Field {
+ fname := p.GetFieldName(message, f)
+ if fname != fieldname {
+ continue
+ }
+ p.P(`case `, strconv.Itoa(int(f.GetNumber())), `:`)
+ p.In()
+ ccTypeName := p.OneOfTypeName(message, f)
+ p.P(`this.`, fname, ` = NewPopulated`, ccTypeName, `(r, easy)`)
+ p.Out()
+ }
+ p.P(`}`)
+ }
+ }
+ if message.DescriptorProto.HasExtension() {
+ p.P(`if !easy && r.Intn(10) != 0 {`)
+ p.In()
+ p.P(`l := r.Intn(5)`)
+ p.P(`for i := 0; i < l; i++ {`)
+ p.In()
+ if len(message.DescriptorProto.GetExtensionRange()) > 1 {
+ p.P(`eIndex := r.Intn(`, strconv.Itoa(len(message.DescriptorProto.GetExtensionRange())), `)`)
+ p.P(`fieldNumber := 0`)
+ p.P(`switch eIndex {`)
+ for i, e := range message.DescriptorProto.GetExtensionRange() {
+ p.P(`case `, strconv.Itoa(i), `:`)
+ p.In()
+ p.P(`fieldNumber = r.Intn(`, strconv.Itoa(int(e.GetEnd()-e.GetStart())), `) + `, strconv.Itoa(int(e.GetStart())))
+ p.Out()
+ if e.GetEnd() > maxFieldNumber {
+ maxFieldNumber = e.GetEnd()
+ }
+ }
+ p.P(`}`)
+ } else {
+ e := message.DescriptorProto.GetExtensionRange()[0]
+ p.P(`fieldNumber := r.Intn(`, strconv.Itoa(int(e.GetEnd()-e.GetStart())), `) + `, strconv.Itoa(int(e.GetStart())))
+ if e.GetEnd() > maxFieldNumber {
+ maxFieldNumber = e.GetEnd()
+ }
+ }
+ p.P(`wire := r.Intn(4)`)
+ p.P(`if wire == 3 { wire = 5 }`)
+ p.P(`dAtA := randField`, p.localName, `(nil, r, fieldNumber, wire)`)
+ p.P(protoPkg.Use(), `.SetRawExtension(this, int32(fieldNumber), dAtA)`)
+ p.Out()
+ p.P(`}`)
+ p.Out()
+ p.P(`}`)
+ }
+
+ if maxFieldNumber < (1 << 10) {
+ p.P(`if !easy && r.Intn(10) != 0 {`)
+ p.In()
+ if gogoproto.HasUnrecognized(file.FileDescriptorProto, message.DescriptorProto) {
+ p.P(`this.XXX_unrecognized = randUnrecognized`, p.localName, `(r, `, strconv.Itoa(int(maxFieldNumber+1)), `)`)
+ }
+ p.Out()
+ p.P(`}`)
+ }
+ }
+ p.P(`return this`)
+ p.Out()
+ p.P(`}`)
+ p.P(``)
+
+ //Generate NewPopulated functions for oneof fields
+ m := proto.Clone(message.DescriptorProto).(*descriptor.DescriptorProto)
+ for _, f := range m.Field {
+ oneof := f.OneofIndex != nil
+ if !oneof {
+ continue
+ }
+ ccTypeName := p.OneOfTypeName(message, f)
+ p.P(`func NewPopulated`, ccTypeName, `(r randy`, p.localName, `, easy bool) *`, ccTypeName, ` {`)
+ p.In()
+ p.P(`this := &`, ccTypeName, `{}`)
+ vanity.TurnOffNullableForNativeTypes(f)
+ p.GenerateField(file, message, f)
+ p.P(`return this`)
+ p.Out()
+ p.P(`}`)
+ }
+ }
+
+ if !p.atleastOne {
+ return
+ }
+
+ p.P(`type randy`, p.localName, ` interface {`)
+ p.In()
+ p.P(`Float32() float32`)
+ p.P(`Float64() float64`)
+ p.P(`Int63() int64`)
+ p.P(`Int31() int32`)
+ p.P(`Uint32() uint32`)
+ p.P(`Intn(n int) int`)
+ p.Out()
+ p.P(`}`)
+
+ p.P(`func randUTF8Rune`, p.localName, `(r randy`, p.localName, `) rune {`)
+ p.In()
+ p.P(`ru := r.Intn(62)`)
+ p.P(`if ru < 10 {`)
+ p.In()
+ p.P(`return rune(ru+48)`)
+ p.Out()
+ p.P(`} else if ru < 36 {`)
+ p.In()
+ p.P(`return rune(ru+55)`)
+ p.Out()
+ p.P(`}`)
+ p.P(`return rune(ru+61)`)
+ p.Out()
+ p.P(`}`)
+
+ p.P(`func randString`, p.localName, `(r randy`, p.localName, `) string {`)
+ p.In()
+ p.P(p.varGen.Next(), ` := r.Intn(100)`)
+ p.P(`tmps := make([]rune, `, p.varGen.Current(), `)`)
+ p.P(`for i := 0; i < `, p.varGen.Current(), `; i++ {`)
+ p.In()
+ p.P(`tmps[i] = randUTF8Rune`, p.localName, `(r)`)
+ p.Out()
+ p.P(`}`)
+ p.P(`return string(tmps)`)
+ p.Out()
+ p.P(`}`)
+
+ p.P(`func randUnrecognized`, p.localName, `(r randy`, p.localName, `, maxFieldNumber int) (dAtA []byte) {`)
+ p.In()
+ p.P(`l := r.Intn(5)`)
+ p.P(`for i := 0; i < l; i++ {`)
+ p.In()
+ p.P(`wire := r.Intn(4)`)
+ p.P(`if wire == 3 { wire = 5 }`)
+ p.P(`fieldNumber := maxFieldNumber + r.Intn(100)`)
+ p.P(`dAtA = randField`, p.localName, `(dAtA, r, fieldNumber, wire)`)
+ p.Out()
+ p.P(`}`)
+ p.P(`return dAtA`)
+ p.Out()
+ p.P(`}`)
+
+ p.P(`func randField`, p.localName, `(dAtA []byte, r randy`, p.localName, `, fieldNumber int, wire int) []byte {`)
+ p.In()
+ p.P(`key := uint32(fieldNumber)<<3 | uint32(wire)`)
+ p.P(`switch wire {`)
+ p.P(`case 0:`)
+ p.In()
+ p.P(`dAtA = encodeVarintPopulate`, p.localName, `(dAtA, uint64(key))`)
+ p.P(p.varGen.Next(), ` := r.Int63()`)
+ p.P(`if r.Intn(2) == 0 {`)
+ p.In()
+ p.P(p.varGen.Current(), ` *= -1`)
+ p.Out()
+ p.P(`}`)
+ p.P(`dAtA = encodeVarintPopulate`, p.localName, `(dAtA, uint64(`, p.varGen.Current(), `))`)
+ p.Out()
+ p.P(`case 1:`)
+ p.In()
+ p.P(`dAtA = encodeVarintPopulate`, p.localName, `(dAtA, uint64(key))`)
+ p.P(`dAtA = append(dAtA, byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)))`)
+ p.Out()
+ p.P(`case 2:`)
+ p.In()
+ p.P(`dAtA = encodeVarintPopulate`, p.localName, `(dAtA, uint64(key))`)
+ p.P(`ll := r.Intn(100)`)
+ p.P(`dAtA = encodeVarintPopulate`, p.localName, `(dAtA, uint64(ll))`)
+ p.P(`for j := 0; j < ll; j++ {`)
+ p.In()
+ p.P(`dAtA = append(dAtA, byte(r.Intn(256)))`)
+ p.Out()
+ p.P(`}`)
+ p.Out()
+ p.P(`default:`)
+ p.In()
+ p.P(`dAtA = encodeVarintPopulate`, p.localName, `(dAtA, uint64(key))`)
+ p.P(`dAtA = append(dAtA, byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)))`)
+ p.Out()
+ p.P(`}`)
+ p.P(`return dAtA`)
+ p.Out()
+ p.P(`}`)
+
+ p.P(`func encodeVarintPopulate`, p.localName, `(dAtA []byte, v uint64) []byte {`)
+ p.In()
+ p.P(`for v >= 1<<7 {`)
+ p.In()
+ p.P(`dAtA = append(dAtA, uint8(uint64(v)&0x7f|0x80))`)
+ p.P(`v >>= 7`)
+ p.Out()
+ p.P(`}`)
+ p.P(`dAtA = append(dAtA, uint8(v))`)
+ p.P(`return dAtA`)
+ p.Out()
+ p.P(`}`)
+
+}
+
+func init() {
+ generator.RegisterPlugin(NewPlugin())
+}
diff --git a/vendor/github.com/gogo/protobuf/plugin/size/size.go b/vendor/github.com/gogo/protobuf/plugin/size/size.go
new file mode 100644
index 00000000000..1650b438751
--- /dev/null
+++ b/vendor/github.com/gogo/protobuf/plugin/size/size.go
@@ -0,0 +1,696 @@
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2013, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// 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.
+//
+// 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.
+
+/*
+The size plugin generates a Size or ProtoSize method for each message.
+This is useful with the MarshalTo method generated by the marshalto plugin and the
+gogoproto.marshaler and gogoproto.marshaler_all extensions.
+
+It is enabled by the following extensions:
+
+ - sizer
+ - sizer_all
+ - protosizer
+ - protosizer_all
+
+The size plugin also generates a test given it is enabled using one of the following extensions:
+
+ - testgen
+ - testgen_all
+
+And a benchmark given it is enabled using one of the following extensions:
+
+ - benchgen
+ - benchgen_all
+
+Let us look at:
+
+ github.com/gogo/protobuf/test/example/example.proto
+
+Btw all the output can be seen at:
+
+ github.com/gogo/protobuf/test/example/*
+
+The following message:
+
+ option (gogoproto.sizer_all) = true;
+
+ message B {
+ option (gogoproto.description) = true;
+ optional A A = 1 [(gogoproto.nullable) = false, (gogoproto.embed) = true];
+ repeated bytes G = 2 [(gogoproto.customtype) = "github.com/gogo/protobuf/test/custom.Uint128", (gogoproto.nullable) = false];
+ }
+
+given to the size plugin, will generate the following code:
+
+ func (m *B) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = m.A.Size()
+ n += 1 + l + sovExample(uint64(l))
+ if len(m.G) > 0 {
+ for _, e := range m.G {
+ l = e.Size()
+ n += 1 + l + sovExample(uint64(l))
+ }
+ }
+ if m.XXX_unrecognized != nil {
+ n += len(m.XXX_unrecognized)
+ }
+ return n
+ }
+
+and the following test code:
+
+ func TestBSize(t *testing5.T) {
+ popr := math_rand5.New(math_rand5.NewSource(time5.Now().UnixNano()))
+ p := NewPopulatedB(popr, true)
+ dAtA, err := github_com_gogo_protobuf_proto2.Marshal(p)
+ if err != nil {
+ panic(err)
+ }
+ size := p.Size()
+ if len(dAtA) != size {
+ t.Fatalf("size %v != marshalled size %v", size, len(dAtA))
+ }
+ }
+
+ func BenchmarkBSize(b *testing5.B) {
+ popr := math_rand5.New(math_rand5.NewSource(616))
+ total := 0
+ pops := make([]*B, 1000)
+ for i := 0; i < 1000; i++ {
+ pops[i] = NewPopulatedB(popr, false)
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ total += pops[i%1000].Size()
+ }
+ b.SetBytes(int64(total / b.N))
+ }
+
+The sovExample function is a size of varint function for the example.pb.go file.
+
+*/
+package size
+
+import (
+ "fmt"
+ "os"
+ "strconv"
+ "strings"
+
+ "github.com/gogo/protobuf/gogoproto"
+ "github.com/gogo/protobuf/proto"
+ descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
+ "github.com/gogo/protobuf/protoc-gen-gogo/generator"
+ "github.com/gogo/protobuf/vanity"
+)
+
+type size struct {
+ *generator.Generator
+ generator.PluginImports
+ atleastOne bool
+ localName string
+ typesPkg generator.Single
+ bitsPkg generator.Single
+}
+
+func NewSize() *size {
+ return &size{}
+}
+
+func (p *size) Name() string {
+ return "size"
+}
+
+func (p *size) Init(g *generator.Generator) {
+ p.Generator = g
+}
+
+func wireToType(wire string) int {
+ switch wire {
+ case "fixed64":
+ return proto.WireFixed64
+ case "fixed32":
+ return proto.WireFixed32
+ case "varint":
+ return proto.WireVarint
+ case "bytes":
+ return proto.WireBytes
+ case "group":
+ return proto.WireBytes
+ case "zigzag32":
+ return proto.WireVarint
+ case "zigzag64":
+ return proto.WireVarint
+ }
+ panic("unreachable")
+}
+
+func keySize(fieldNumber int32, wireType int) int {
+ x := uint32(fieldNumber)<<3 | uint32(wireType)
+ size := 0
+ for size = 0; x > 127; size++ {
+ x >>= 7
+ }
+ size++
+ return size
+}
+
+func (p *size) sizeVarint() {
+ p.P(`
+ func sov`, p.localName, `(x uint64) (n int) {
+ return (`, p.bitsPkg.Use(), `.Len64(x | 1) + 6)/ 7
+ }`)
+}
+
+func (p *size) sizeZigZag() {
+ p.P(`func soz`, p.localName, `(x uint64) (n int) {
+ return sov`, p.localName, `(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+ }`)
+}
+
+func (p *size) std(field *descriptor.FieldDescriptorProto, name string) (string, bool) {
+ ptr := ""
+ if gogoproto.IsNullable(field) {
+ ptr = "*"
+ }
+ if gogoproto.IsStdTime(field) {
+ return p.typesPkg.Use() + `.SizeOfStdTime(` + ptr + name + `)`, true
+ } else if gogoproto.IsStdDuration(field) {
+ return p.typesPkg.Use() + `.SizeOfStdDuration(` + ptr + name + `)`, true
+ } else if gogoproto.IsStdDouble(field) {
+ return p.typesPkg.Use() + `.SizeOfStdDouble(` + ptr + name + `)`, true
+ } else if gogoproto.IsStdFloat(field) {
+ return p.typesPkg.Use() + `.SizeOfStdFloat(` + ptr + name + `)`, true
+ } else if gogoproto.IsStdInt64(field) {
+ return p.typesPkg.Use() + `.SizeOfStdInt64(` + ptr + name + `)`, true
+ } else if gogoproto.IsStdUInt64(field) {
+ return p.typesPkg.Use() + `.SizeOfStdUInt64(` + ptr + name + `)`, true
+ } else if gogoproto.IsStdInt32(field) {
+ return p.typesPkg.Use() + `.SizeOfStdInt32(` + ptr + name + `)`, true
+ } else if gogoproto.IsStdUInt32(field) {
+ return p.typesPkg.Use() + `.SizeOfStdUInt32(` + ptr + name + `)`, true
+ } else if gogoproto.IsStdBool(field) {
+ return p.typesPkg.Use() + `.SizeOfStdBool(` + ptr + name + `)`, true
+ } else if gogoproto.IsStdString(field) {
+ return p.typesPkg.Use() + `.SizeOfStdString(` + ptr + name + `)`, true
+ } else if gogoproto.IsStdBytes(field) {
+ return p.typesPkg.Use() + `.SizeOfStdBytes(` + ptr + name + `)`, true
+ }
+ return "", false
+}
+
+func (p *size) generateField(proto3 bool, file *generator.FileDescriptor, message *generator.Descriptor, field *descriptor.FieldDescriptorProto, sizeName string) {
+ fieldname := p.GetOneOfFieldName(message, field)
+ nullable := gogoproto.IsNullable(field)
+ repeated := field.IsRepeated()
+ doNilCheck := gogoproto.NeedsNilCheck(proto3, field)
+ if repeated {
+ p.P(`if len(m.`, fieldname, `) > 0 {`)
+ p.In()
+ } else if doNilCheck {
+ p.P(`if m.`, fieldname, ` != nil {`)
+ p.In()
+ }
+ packed := field.IsPacked() || (proto3 && field.IsPacked3())
+ _, wire := p.GoType(message, field)
+ wireType := wireToType(wire)
+ fieldNumber := field.GetNumber()
+ if packed {
+ wireType = proto.WireBytes
+ }
+ key := keySize(fieldNumber, wireType)
+ switch *field.Type {
+ case descriptor.FieldDescriptorProto_TYPE_DOUBLE,
+ descriptor.FieldDescriptorProto_TYPE_FIXED64,
+ descriptor.FieldDescriptorProto_TYPE_SFIXED64:
+ if packed {
+ p.P(`n+=`, strconv.Itoa(key), `+sov`, p.localName, `(uint64(len(m.`, fieldname, `)*8))`, `+len(m.`, fieldname, `)*8`)
+ } else if repeated {
+ p.P(`n+=`, strconv.Itoa(key+8), `*len(m.`, fieldname, `)`)
+ } else if proto3 {
+ p.P(`if m.`, fieldname, ` != 0 {`)
+ p.In()
+ p.P(`n+=`, strconv.Itoa(key+8))
+ p.Out()
+ p.P(`}`)
+ } else if nullable {
+ p.P(`n+=`, strconv.Itoa(key+8))
+ } else {
+ p.P(`n+=`, strconv.Itoa(key+8))
+ }
+ case descriptor.FieldDescriptorProto_TYPE_FLOAT,
+ descriptor.FieldDescriptorProto_TYPE_FIXED32,
+ descriptor.FieldDescriptorProto_TYPE_SFIXED32:
+ if packed {
+ p.P(`n+=`, strconv.Itoa(key), `+sov`, p.localName, `(uint64(len(m.`, fieldname, `)*4))`, `+len(m.`, fieldname, `)*4`)
+ } else if repeated {
+ p.P(`n+=`, strconv.Itoa(key+4), `*len(m.`, fieldname, `)`)
+ } else if proto3 {
+ p.P(`if m.`, fieldname, ` != 0 {`)
+ p.In()
+ p.P(`n+=`, strconv.Itoa(key+4))
+ p.Out()
+ p.P(`}`)
+ } else if nullable {
+ p.P(`n+=`, strconv.Itoa(key+4))
+ } else {
+ p.P(`n+=`, strconv.Itoa(key+4))
+ }
+ case descriptor.FieldDescriptorProto_TYPE_INT64,
+ descriptor.FieldDescriptorProto_TYPE_UINT64,
+ descriptor.FieldDescriptorProto_TYPE_UINT32,
+ descriptor.FieldDescriptorProto_TYPE_ENUM,
+ descriptor.FieldDescriptorProto_TYPE_INT32:
+ if packed {
+ p.P(`l = 0`)
+ p.P(`for _, e := range m.`, fieldname, ` {`)
+ p.In()
+ p.P(`l+=sov`, p.localName, `(uint64(e))`)
+ p.Out()
+ p.P(`}`)
+ p.P(`n+=`, strconv.Itoa(key), `+sov`, p.localName, `(uint64(l))+l`)
+ } else if repeated {
+ p.P(`for _, e := range m.`, fieldname, ` {`)
+ p.In()
+ p.P(`n+=`, strconv.Itoa(key), `+sov`, p.localName, `(uint64(e))`)
+ p.Out()
+ p.P(`}`)
+ } else if proto3 {
+ p.P(`if m.`, fieldname, ` != 0 {`)
+ p.In()
+ p.P(`n+=`, strconv.Itoa(key), `+sov`, p.localName, `(uint64(m.`, fieldname, `))`)
+ p.Out()
+ p.P(`}`)
+ } else if nullable {
+ p.P(`n+=`, strconv.Itoa(key), `+sov`, p.localName, `(uint64(*m.`, fieldname, `))`)
+ } else {
+ p.P(`n+=`, strconv.Itoa(key), `+sov`, p.localName, `(uint64(m.`, fieldname, `))`)
+ }
+ case descriptor.FieldDescriptorProto_TYPE_BOOL:
+ if packed {
+ p.P(`n+=`, strconv.Itoa(key), `+sov`, p.localName, `(uint64(len(m.`, fieldname, `)))`, `+len(m.`, fieldname, `)*1`)
+ } else if repeated {
+ p.P(`n+=`, strconv.Itoa(key+1), `*len(m.`, fieldname, `)`)
+ } else if proto3 {
+ p.P(`if m.`, fieldname, ` {`)
+ p.In()
+ p.P(`n+=`, strconv.Itoa(key+1))
+ p.Out()
+ p.P(`}`)
+ } else if nullable {
+ p.P(`n+=`, strconv.Itoa(key+1))
+ } else {
+ p.P(`n+=`, strconv.Itoa(key+1))
+ }
+ case descriptor.FieldDescriptorProto_TYPE_STRING:
+ if repeated {
+ p.P(`for _, s := range m.`, fieldname, ` { `)
+ p.In()
+ p.P(`l = len(s)`)
+ p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
+ p.Out()
+ p.P(`}`)
+ } else if proto3 {
+ p.P(`l=len(m.`, fieldname, `)`)
+ p.P(`if l > 0 {`)
+ p.In()
+ p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
+ p.Out()
+ p.P(`}`)
+ } else if nullable {
+ p.P(`l=len(*m.`, fieldname, `)`)
+ p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
+ } else {
+ p.P(`l=len(m.`, fieldname, `)`)
+ p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
+ }
+ case descriptor.FieldDescriptorProto_TYPE_GROUP:
+ panic(fmt.Errorf("size does not support group %v", fieldname))
+ case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
+ if p.IsMap(field) {
+ m := p.GoMapType(nil, field)
+ _, keywire := p.GoType(nil, m.KeyAliasField)
+ valuegoTyp, _ := p.GoType(nil, m.ValueField)
+ valuegoAliasTyp, valuewire := p.GoType(nil, m.ValueAliasField)
+ _, fieldwire := p.GoType(nil, field)
+
+ nullable, valuegoTyp, valuegoAliasTyp = generator.GoMapValueTypes(field, m.ValueField, valuegoTyp, valuegoAliasTyp)
+
+ fieldKeySize := keySize(field.GetNumber(), wireToType(fieldwire))
+ keyKeySize := keySize(1, wireToType(keywire))
+ valueKeySize := keySize(2, wireToType(valuewire))
+ p.P(`for k, v := range m.`, fieldname, ` { `)
+ p.In()
+ p.P(`_ = k`)
+ p.P(`_ = v`)
+ sum := []string{strconv.Itoa(keyKeySize)}
+ switch m.KeyField.GetType() {
+ case descriptor.FieldDescriptorProto_TYPE_DOUBLE,
+ descriptor.FieldDescriptorProto_TYPE_FIXED64,
+ descriptor.FieldDescriptorProto_TYPE_SFIXED64:
+ sum = append(sum, `8`)
+ case descriptor.FieldDescriptorProto_TYPE_FLOAT,
+ descriptor.FieldDescriptorProto_TYPE_FIXED32,
+ descriptor.FieldDescriptorProto_TYPE_SFIXED32:
+ sum = append(sum, `4`)
+ case descriptor.FieldDescriptorProto_TYPE_INT64,
+ descriptor.FieldDescriptorProto_TYPE_UINT64,
+ descriptor.FieldDescriptorProto_TYPE_UINT32,
+ descriptor.FieldDescriptorProto_TYPE_ENUM,
+ descriptor.FieldDescriptorProto_TYPE_INT32:
+ sum = append(sum, `sov`+p.localName+`(uint64(k))`)
+ case descriptor.FieldDescriptorProto_TYPE_BOOL:
+ sum = append(sum, `1`)
+ case descriptor.FieldDescriptorProto_TYPE_STRING,
+ descriptor.FieldDescriptorProto_TYPE_BYTES:
+ sum = append(sum, `len(k)+sov`+p.localName+`(uint64(len(k)))`)
+ case descriptor.FieldDescriptorProto_TYPE_SINT32,
+ descriptor.FieldDescriptorProto_TYPE_SINT64:
+ sum = append(sum, `soz`+p.localName+`(uint64(k))`)
+ }
+ switch m.ValueField.GetType() {
+ case descriptor.FieldDescriptorProto_TYPE_DOUBLE,
+ descriptor.FieldDescriptorProto_TYPE_FIXED64,
+ descriptor.FieldDescriptorProto_TYPE_SFIXED64:
+ sum = append(sum, strconv.Itoa(valueKeySize))
+ sum = append(sum, strconv.Itoa(8))
+ case descriptor.FieldDescriptorProto_TYPE_FLOAT,
+ descriptor.FieldDescriptorProto_TYPE_FIXED32,
+ descriptor.FieldDescriptorProto_TYPE_SFIXED32:
+ sum = append(sum, strconv.Itoa(valueKeySize))
+ sum = append(sum, strconv.Itoa(4))
+ case descriptor.FieldDescriptorProto_TYPE_INT64,
+ descriptor.FieldDescriptorProto_TYPE_UINT64,
+ descriptor.FieldDescriptorProto_TYPE_UINT32,
+ descriptor.FieldDescriptorProto_TYPE_ENUM,
+ descriptor.FieldDescriptorProto_TYPE_INT32:
+ sum = append(sum, strconv.Itoa(valueKeySize))
+ sum = append(sum, `sov`+p.localName+`(uint64(v))`)
+ case descriptor.FieldDescriptorProto_TYPE_BOOL:
+ sum = append(sum, strconv.Itoa(valueKeySize))
+ sum = append(sum, `1`)
+ case descriptor.FieldDescriptorProto_TYPE_STRING:
+ sum = append(sum, strconv.Itoa(valueKeySize))
+ sum = append(sum, `len(v)+sov`+p.localName+`(uint64(len(v)))`)
+ case descriptor.FieldDescriptorProto_TYPE_BYTES:
+ if gogoproto.IsCustomType(field) {
+ p.P(`l = 0`)
+ if nullable {
+ p.P(`if v != nil {`)
+ p.In()
+ }
+ p.P(`l = v.`, sizeName, `()`)
+ p.P(`l += `, strconv.Itoa(valueKeySize), ` + sov`+p.localName+`(uint64(l))`)
+ if nullable {
+ p.Out()
+ p.P(`}`)
+ }
+ sum = append(sum, `l`)
+ } else {
+ p.P(`l = 0`)
+ if proto3 {
+ p.P(`if len(v) > 0 {`)
+ } else {
+ p.P(`if v != nil {`)
+ }
+ p.In()
+ p.P(`l = `, strconv.Itoa(valueKeySize), ` + len(v)+sov`+p.localName+`(uint64(len(v)))`)
+ p.Out()
+ p.P(`}`)
+ sum = append(sum, `l`)
+ }
+ case descriptor.FieldDescriptorProto_TYPE_SINT32,
+ descriptor.FieldDescriptorProto_TYPE_SINT64:
+ sum = append(sum, strconv.Itoa(valueKeySize))
+ sum = append(sum, `soz`+p.localName+`(uint64(v))`)
+ case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
+ stdSizeCall, stdOk := p.std(m.ValueAliasField, "v")
+ if nullable {
+ p.P(`l = 0`)
+ p.P(`if v != nil {`)
+ p.In()
+ if stdOk {
+ p.P(`l = `, stdSizeCall)
+ } else if valuegoTyp != valuegoAliasTyp {
+ p.P(`l = ((`, valuegoTyp, `)(v)).`, sizeName, `()`)
+ } else {
+ p.P(`l = v.`, sizeName, `()`)
+ }
+ p.P(`l += `, strconv.Itoa(valueKeySize), ` + sov`+p.localName+`(uint64(l))`)
+ p.Out()
+ p.P(`}`)
+ sum = append(sum, `l`)
+ } else {
+ if stdOk {
+ p.P(`l = `, stdSizeCall)
+ } else if valuegoTyp != valuegoAliasTyp {
+ p.P(`l = ((*`, valuegoTyp, `)(&v)).`, sizeName, `()`)
+ } else {
+ p.P(`l = v.`, sizeName, `()`)
+ }
+ sum = append(sum, strconv.Itoa(valueKeySize))
+ sum = append(sum, `l+sov`+p.localName+`(uint64(l))`)
+ }
+ }
+ p.P(`mapEntrySize := `, strings.Join(sum, "+"))
+ p.P(`n+=mapEntrySize+`, fieldKeySize, `+sov`, p.localName, `(uint64(mapEntrySize))`)
+ p.Out()
+ p.P(`}`)
+ } else if repeated {
+ p.P(`for _, e := range m.`, fieldname, ` { `)
+ p.In()
+ stdSizeCall, stdOk := p.std(field, "e")
+ if stdOk {
+ p.P(`l=`, stdSizeCall)
+ } else {
+ p.P(`l=e.`, sizeName, `()`)
+ }
+ p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
+ p.Out()
+ p.P(`}`)
+ } else {
+ stdSizeCall, stdOk := p.std(field, "m."+fieldname)
+ if stdOk {
+ p.P(`l=`, stdSizeCall)
+ } else {
+ p.P(`l=m.`, fieldname, `.`, sizeName, `()`)
+ }
+ p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
+ }
+ case descriptor.FieldDescriptorProto_TYPE_BYTES:
+ if !gogoproto.IsCustomType(field) {
+ if repeated {
+ p.P(`for _, b := range m.`, fieldname, ` { `)
+ p.In()
+ p.P(`l = len(b)`)
+ p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
+ p.Out()
+ p.P(`}`)
+ } else if proto3 {
+ p.P(`l=len(m.`, fieldname, `)`)
+ p.P(`if l > 0 {`)
+ p.In()
+ p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
+ p.Out()
+ p.P(`}`)
+ } else {
+ p.P(`l=len(m.`, fieldname, `)`)
+ p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
+ }
+ } else {
+ if repeated {
+ p.P(`for _, e := range m.`, fieldname, ` { `)
+ p.In()
+ p.P(`l=e.`, sizeName, `()`)
+ p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
+ p.Out()
+ p.P(`}`)
+ } else {
+ p.P(`l=m.`, fieldname, `.`, sizeName, `()`)
+ p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
+ }
+ }
+ case descriptor.FieldDescriptorProto_TYPE_SINT32,
+ descriptor.FieldDescriptorProto_TYPE_SINT64:
+ if packed {
+ p.P(`l = 0`)
+ p.P(`for _, e := range m.`, fieldname, ` {`)
+ p.In()
+ p.P(`l+=soz`, p.localName, `(uint64(e))`)
+ p.Out()
+ p.P(`}`)
+ p.P(`n+=`, strconv.Itoa(key), `+sov`, p.localName, `(uint64(l))+l`)
+ } else if repeated {
+ p.P(`for _, e := range m.`, fieldname, ` {`)
+ p.In()
+ p.P(`n+=`, strconv.Itoa(key), `+soz`, p.localName, `(uint64(e))`)
+ p.Out()
+ p.P(`}`)
+ } else if proto3 {
+ p.P(`if m.`, fieldname, ` != 0 {`)
+ p.In()
+ p.P(`n+=`, strconv.Itoa(key), `+soz`, p.localName, `(uint64(m.`, fieldname, `))`)
+ p.Out()
+ p.P(`}`)
+ } else if nullable {
+ p.P(`n+=`, strconv.Itoa(key), `+soz`, p.localName, `(uint64(*m.`, fieldname, `))`)
+ } else {
+ p.P(`n+=`, strconv.Itoa(key), `+soz`, p.localName, `(uint64(m.`, fieldname, `))`)
+ }
+ default:
+ panic("not implemented")
+ }
+ if repeated || doNilCheck {
+ p.Out()
+ p.P(`}`)
+ }
+}
+
+func (p *size) Generate(file *generator.FileDescriptor) {
+ p.PluginImports = generator.NewPluginImports(p.Generator)
+ p.atleastOne = false
+ p.localName = generator.FileName(file)
+ p.typesPkg = p.NewImport("github.com/gogo/protobuf/types")
+ protoPkg := p.NewImport("github.com/gogo/protobuf/proto")
+ p.bitsPkg = p.NewImport("math/bits")
+ if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
+ protoPkg = p.NewImport("github.com/golang/protobuf/proto")
+ }
+ for _, message := range file.Messages() {
+ sizeName := ""
+ if gogoproto.IsSizer(file.FileDescriptorProto, message.DescriptorProto) && gogoproto.IsProtoSizer(file.FileDescriptorProto, message.DescriptorProto) {
+ fmt.Fprintf(os.Stderr, "ERROR: message %v cannot support both sizer and protosizer plugins\n", generator.CamelCase(*message.Name))
+ os.Exit(1)
+ }
+ if gogoproto.IsSizer(file.FileDescriptorProto, message.DescriptorProto) {
+ sizeName = "Size"
+ } else if gogoproto.IsProtoSizer(file.FileDescriptorProto, message.DescriptorProto) {
+ sizeName = "ProtoSize"
+ } else {
+ continue
+ }
+ if message.DescriptorProto.GetOptions().GetMapEntry() {
+ continue
+ }
+ p.atleastOne = true
+ ccTypeName := generator.CamelCaseSlice(message.TypeName())
+ p.P(`func (m *`, ccTypeName, `) `, sizeName, `() (n int) {`)
+ p.In()
+ p.P(`if m == nil {`)
+ p.In()
+ p.P(`return 0`)
+ p.Out()
+ p.P(`}`)
+ p.P(`var l int`)
+ p.P(`_ = l`)
+ oneofs := make(map[string]struct{})
+ for _, field := range message.Field {
+ oneof := field.OneofIndex != nil
+ if !oneof {
+ proto3 := gogoproto.IsProto3(file.FileDescriptorProto)
+ p.generateField(proto3, file, message, field, sizeName)
+ } else {
+ fieldname := p.GetFieldName(message, field)
+ if _, ok := oneofs[fieldname]; ok {
+ continue
+ } else {
+ oneofs[fieldname] = struct{}{}
+ }
+ p.P(`if m.`, fieldname, ` != nil {`)
+ p.In()
+ p.P(`n+=m.`, fieldname, `.`, sizeName, `()`)
+ p.Out()
+ p.P(`}`)
+ }
+ }
+ if message.DescriptorProto.HasExtension() {
+ if gogoproto.HasExtensionsMap(file.FileDescriptorProto, message.DescriptorProto) {
+ p.P(`n += `, protoPkg.Use(), `.SizeOfInternalExtension(m)`)
+ } else {
+ p.P(`if m.XXX_extensions != nil {`)
+ p.In()
+ p.P(`n+=len(m.XXX_extensions)`)
+ p.Out()
+ p.P(`}`)
+ }
+ }
+ if gogoproto.HasUnrecognized(file.FileDescriptorProto, message.DescriptorProto) {
+ p.P(`if m.XXX_unrecognized != nil {`)
+ p.In()
+ p.P(`n+=len(m.XXX_unrecognized)`)
+ p.Out()
+ p.P(`}`)
+ }
+ p.P(`return n`)
+ p.Out()
+ p.P(`}`)
+ p.P()
+
+ //Generate Size methods for oneof fields
+ m := proto.Clone(message.DescriptorProto).(*descriptor.DescriptorProto)
+ for _, f := range m.Field {
+ oneof := f.OneofIndex != nil
+ if !oneof {
+ continue
+ }
+ ccTypeName := p.OneOfTypeName(message, f)
+ p.P(`func (m *`, ccTypeName, `) `, sizeName, `() (n int) {`)
+ p.In()
+ p.P(`if m == nil {`)
+ p.In()
+ p.P(`return 0`)
+ p.Out()
+ p.P(`}`)
+ p.P(`var l int`)
+ p.P(`_ = l`)
+ vanity.TurnOffNullableForNativeTypes(f)
+ p.generateField(false, file, message, f, sizeName)
+ p.P(`return n`)
+ p.Out()
+ p.P(`}`)
+ }
+ }
+
+ if !p.atleastOne {
+ return
+ }
+
+ p.sizeVarint()
+ p.sizeZigZag()
+
+}
+
+func init() {
+ generator.RegisterPlugin(NewSize())
+}
diff --git a/vendor/github.com/gogo/protobuf/plugin/size/sizetest.go b/vendor/github.com/gogo/protobuf/plugin/size/sizetest.go
new file mode 100644
index 00000000000..1df98730007
--- /dev/null
+++ b/vendor/github.com/gogo/protobuf/plugin/size/sizetest.go
@@ -0,0 +1,134 @@
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2013, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// 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.
+//
+// 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 size
+
+import (
+ "github.com/gogo/protobuf/gogoproto"
+ "github.com/gogo/protobuf/plugin/testgen"
+ "github.com/gogo/protobuf/protoc-gen-gogo/generator"
+)
+
+type test struct {
+ *generator.Generator
+}
+
+func NewTest(g *generator.Generator) testgen.TestPlugin {
+ return &test{g}
+}
+
+func (p *test) Generate(imports generator.PluginImports, file *generator.FileDescriptor) bool {
+ used := false
+ randPkg := imports.NewImport("math/rand")
+ timePkg := imports.NewImport("time")
+ testingPkg := imports.NewImport("testing")
+ protoPkg := imports.NewImport("github.com/gogo/protobuf/proto")
+ if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
+ protoPkg = imports.NewImport("github.com/golang/protobuf/proto")
+ }
+ for _, message := range file.Messages() {
+ ccTypeName := generator.CamelCaseSlice(message.TypeName())
+ sizeName := ""
+ if gogoproto.IsSizer(file.FileDescriptorProto, message.DescriptorProto) {
+ sizeName = "Size"
+ } else if gogoproto.IsProtoSizer(file.FileDescriptorProto, message.DescriptorProto) {
+ sizeName = "ProtoSize"
+ } else {
+ continue
+ }
+ if message.DescriptorProto.GetOptions().GetMapEntry() {
+ continue
+ }
+
+ if gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
+ used = true
+ p.P(`func Test`, ccTypeName, sizeName, `(t *`, testingPkg.Use(), `.T) {`)
+ p.In()
+ p.P(`seed := `, timePkg.Use(), `.Now().UnixNano()`)
+ p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(seed))`)
+ p.P(`p := NewPopulated`, ccTypeName, `(popr, true)`)
+ p.P(`size2 := `, protoPkg.Use(), `.Size(p)`)
+ p.P(`dAtA, err := `, protoPkg.Use(), `.Marshal(p)`)
+ p.P(`if err != nil {`)
+ p.In()
+ p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`)
+ p.Out()
+ p.P(`}`)
+ p.P(`size := p.`, sizeName, `()`)
+ p.P(`if len(dAtA) != size {`)
+ p.In()
+ p.P(`t.Errorf("seed = %d, size %v != marshalled size %v", seed, size, len(dAtA))`)
+ p.Out()
+ p.P(`}`)
+ p.P(`if size2 != size {`)
+ p.In()
+ p.P(`t.Errorf("seed = %d, size %v != before marshal proto.Size %v", seed, size, size2)`)
+ p.Out()
+ p.P(`}`)
+ p.P(`size3 := `, protoPkg.Use(), `.Size(p)`)
+ p.P(`if size3 != size {`)
+ p.In()
+ p.P(`t.Errorf("seed = %d, size %v != after marshal proto.Size %v", seed, size, size3)`)
+ p.Out()
+ p.P(`}`)
+ p.Out()
+ p.P(`}`)
+ p.P()
+ }
+
+ if gogoproto.HasBenchGen(file.FileDescriptorProto, message.DescriptorProto) {
+ used = true
+ p.P(`func Benchmark`, ccTypeName, sizeName, `(b *`, testingPkg.Use(), `.B) {`)
+ p.In()
+ p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(616))`)
+ p.P(`total := 0`)
+ p.P(`pops := make([]*`, ccTypeName, `, 1000)`)
+ p.P(`for i := 0; i < 1000; i++ {`)
+ p.In()
+ p.P(`pops[i] = NewPopulated`, ccTypeName, `(popr, false)`)
+ p.Out()
+ p.P(`}`)
+ p.P(`b.ResetTimer()`)
+ p.P(`for i := 0; i < b.N; i++ {`)
+ p.In()
+ p.P(`total += pops[i%1000].`, sizeName, `()`)
+ p.Out()
+ p.P(`}`)
+ p.P(`b.SetBytes(int64(total / b.N))`)
+ p.Out()
+ p.P(`}`)
+ p.P()
+ }
+
+ }
+ return used
+}
+
+func init() {
+ testgen.RegisterTestPlugin(NewTest)
+}
diff --git a/vendor/github.com/gogo/protobuf/plugin/stringer/stringer.go b/vendor/github.com/gogo/protobuf/plugin/stringer/stringer.go
new file mode 100644
index 00000000000..df9792c7c4f
--- /dev/null
+++ b/vendor/github.com/gogo/protobuf/plugin/stringer/stringer.go
@@ -0,0 +1,347 @@
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2013, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// 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.
+//
+// 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.
+
+/*
+The stringer plugin generates a String method for each message.
+
+It is enabled by the following extensions:
+
+ - stringer
+ - stringer_all
+
+The stringer plugin also generates a test given it is enabled using one of the following extensions:
+
+ - testgen
+ - testgen_all
+
+Let us look at:
+
+ github.com/gogo/protobuf/test/example/example.proto
+
+Btw all the output can be seen at:
+
+ github.com/gogo/protobuf/test/example/*
+
+The following message:
+
+ option (gogoproto.goproto_stringer_all) = false;
+ option (gogoproto.stringer_all) = true;
+
+ message A {
+ optional string Description = 1 [(gogoproto.nullable) = false];
+ optional int64 Number = 2 [(gogoproto.nullable) = false];
+ optional bytes Id = 3 [(gogoproto.customtype) = "github.com/gogo/protobuf/test/custom.Uuid", (gogoproto.nullable) = false];
+ }
+
+given to the stringer stringer, will generate the following code:
+
+ func (this *A) String() string {
+ if this == nil {
+ return "nil"
+ }
+ s := strings.Join([]string{`&A{`,
+ `Description:` + fmt.Sprintf("%v", this.Description) + `,`,
+ `Number:` + fmt.Sprintf("%v", this.Number) + `,`,
+ `Id:` + fmt.Sprintf("%v", this.Id) + `,`,
+ `XXX_unrecognized:` + fmt.Sprintf("%v", this.XXX_unrecognized) + `,`,
+ `}`,
+ }, "")
+ return s
+ }
+
+and the following test code:
+
+ func TestAStringer(t *testing4.T) {
+ popr := math_rand4.New(math_rand4.NewSource(time4.Now().UnixNano()))
+ p := NewPopulatedA(popr, false)
+ s1 := p.String()
+ s2 := fmt1.Sprintf("%v", p)
+ if s1 != s2 {
+ t.Fatalf("String want %v got %v", s1, s2)
+ }
+ }
+
+Typically fmt.Printf("%v") will stop to print when it reaches a pointer and
+not print their values, while the generated String method will always print all values, recursively.
+
+*/
+package stringer
+
+import (
+ "github.com/gogo/protobuf/gogoproto"
+ "github.com/gogo/protobuf/protoc-gen-gogo/generator"
+ "strings"
+)
+
+type stringer struct {
+ *generator.Generator
+ generator.PluginImports
+ atleastOne bool
+ localName string
+}
+
+func NewStringer() *stringer {
+ return &stringer{}
+}
+
+func (p *stringer) Name() string {
+ return "stringer"
+}
+
+func (p *stringer) Init(g *generator.Generator) {
+ p.Generator = g
+}
+
+func (p *stringer) Generate(file *generator.FileDescriptor) {
+ proto3 := gogoproto.IsProto3(file.FileDescriptorProto)
+ p.PluginImports = generator.NewPluginImports(p.Generator)
+ p.atleastOne = false
+
+ p.localName = generator.FileName(file)
+
+ fmtPkg := p.NewImport("fmt")
+ stringsPkg := p.NewImport("strings")
+ reflectPkg := p.NewImport("reflect")
+ sortKeysPkg := p.NewImport("github.com/gogo/protobuf/sortkeys")
+ protoPkg := p.NewImport("github.com/gogo/protobuf/proto")
+ for _, message := range file.Messages() {
+ if !gogoproto.IsStringer(file.FileDescriptorProto, message.DescriptorProto) {
+ continue
+ }
+ if gogoproto.EnabledGoStringer(file.FileDescriptorProto, message.DescriptorProto) {
+ panic("old string method needs to be disabled, please use gogoproto.goproto_stringer or gogoproto.goproto_stringer_all and set it to false")
+ }
+ if message.DescriptorProto.GetOptions().GetMapEntry() {
+ continue
+ }
+ p.atleastOne = true
+ ccTypeName := generator.CamelCaseSlice(message.TypeName())
+ p.P(`func (this *`, ccTypeName, `) String() string {`)
+ p.In()
+ p.P(`if this == nil {`)
+ p.In()
+ p.P(`return "nil"`)
+ p.Out()
+ p.P(`}`)
+ for _, field := range message.Field {
+ if p.IsMap(field) || !field.IsRepeated() {
+ continue
+ }
+ if (field.IsMessage() && !gogoproto.IsCustomType(field)) || p.IsGroup(field) {
+ nullable := gogoproto.IsNullable(field)
+ desc := p.ObjectNamed(field.GetTypeName())
+ msgname := p.TypeName(desc)
+ msgnames := strings.Split(msgname, ".")
+ typeName := msgnames[len(msgnames)-1]
+ fieldMessageDesc := file.GetMessage(msgname)
+ gogoStringer := false
+ if fieldMessageDesc != nil {
+ gogoStringer = gogoproto.IsStringer(file.FileDescriptorProto, fieldMessageDesc)
+ }
+ fieldname := p.GetFieldName(message, field)
+ stringfunc := fmtPkg.Use() + `.Sprintf("%v", f)`
+ if gogoStringer {
+ stringfunc = `f.String()`
+ }
+ repeatedName := `repeatedStringFor` + fieldname
+ if nullable {
+ p.P(repeatedName, ` := "[]*`, typeName, `{"`)
+ } else {
+ p.P(repeatedName, ` := "[]`, typeName, `{"`)
+ }
+
+ p.P(`for _, f := range `, `this.`, fieldname, ` {`)
+ p.In()
+ if nullable {
+ p.P(repeatedName, " += ", stringsPkg.Use(), `.Replace(`, stringfunc, `, "`, typeName, `","`, msgname, `"`, ", 1)", ` + ","`)
+ } else if gogoStringer {
+ p.P(repeatedName, " += ", stringsPkg.Use(), `.Replace(`, stringsPkg.Use(), `.Replace(`, stringfunc, `, "`, typeName, `","`, msgname, `"`, ", 1),`&`,``,1)", ` + ","`)
+ } else {
+ p.P(repeatedName, " += ", stringfunc, ` + ","`)
+ }
+ p.Out()
+ p.P(`}`)
+ p.P(repeatedName, ` += "}"`)
+ }
+ }
+ for _, field := range message.Field {
+ if !p.IsMap(field) {
+ continue
+ }
+ fieldname := p.GetFieldName(message, field)
+
+ m := p.GoMapType(nil, field)
+ mapgoTyp, keyField, keyAliasField := m.GoType, m.KeyField, m.KeyAliasField
+ keysName := `keysFor` + fieldname
+ keygoTyp, _ := p.GoType(nil, keyField)
+ keygoTyp = strings.Replace(keygoTyp, "*", "", 1)
+ keygoAliasTyp, _ := p.GoType(nil, keyAliasField)
+ keygoAliasTyp = strings.Replace(keygoAliasTyp, "*", "", 1)
+ keyCapTyp := generator.CamelCase(keygoTyp)
+ p.P(keysName, ` := make([]`, keygoTyp, `, 0, len(this.`, fieldname, `))`)
+ p.P(`for k, _ := range this.`, fieldname, ` {`)
+ p.In()
+ if keygoAliasTyp == keygoTyp {
+ p.P(keysName, ` = append(`, keysName, `, k)`)
+ } else {
+ p.P(keysName, ` = append(`, keysName, `, `, keygoTyp, `(k))`)
+ }
+ p.Out()
+ p.P(`}`)
+ p.P(sortKeysPkg.Use(), `.`, keyCapTyp, `s(`, keysName, `)`)
+ mapName := `mapStringFor` + fieldname
+ p.P(mapName, ` := "`, mapgoTyp, `{"`)
+ p.P(`for _, k := range `, keysName, ` {`)
+ p.In()
+ if keygoAliasTyp == keygoTyp {
+ p.P(mapName, ` += fmt.Sprintf("%v: %v,", k, this.`, fieldname, `[k])`)
+ } else {
+ p.P(mapName, ` += fmt.Sprintf("%v: %v,", k, this.`, fieldname, `[`, keygoAliasTyp, `(k)])`)
+ }
+ p.Out()
+ p.P(`}`)
+ p.P(mapName, ` += "}"`)
+ }
+ p.P("s := ", stringsPkg.Use(), ".Join([]string{`&", ccTypeName, "{`,")
+ oneofs := make(map[string]struct{})
+ for _, field := range message.Field {
+ nullable := gogoproto.IsNullable(field)
+ repeated := field.IsRepeated()
+ fieldname := p.GetFieldName(message, field)
+ oneof := field.OneofIndex != nil
+ if oneof {
+ if _, ok := oneofs[fieldname]; ok {
+ continue
+ } else {
+ oneofs[fieldname] = struct{}{}
+ }
+ p.P("`", fieldname, ":`", ` + `, fmtPkg.Use(), `.Sprintf("%v", this.`, fieldname, ") + `,", "`,")
+ } else if p.IsMap(field) {
+ mapName := `mapStringFor` + fieldname
+ p.P("`", fieldname, ":`", ` + `, mapName, " + `,", "`,")
+ } else if (field.IsMessage() && !gogoproto.IsCustomType(field)) || p.IsGroup(field) {
+ desc := p.ObjectNamed(field.GetTypeName())
+ msgname := p.TypeName(desc)
+ msgnames := strings.Split(msgname, ".")
+ typeName := msgnames[len(msgnames)-1]
+ fieldMessageDesc := file.GetMessage(msgname)
+ gogoStringer := false
+ if fieldMessageDesc != nil {
+ gogoStringer = gogoproto.IsStringer(file.FileDescriptorProto, fieldMessageDesc)
+ }
+ stringfunc := fmtPkg.Use() + `.Sprintf("%v", this.` + fieldname + `)`
+ if gogoStringer {
+ stringfunc = `this.` + fieldname + `.String()`
+ }
+ if nullable && !repeated {
+ p.P("`", fieldname, ":`", ` + `, stringsPkg.Use(), `.Replace(`, stringfunc, `, "`, typeName, `","`, msgname, `"`, ", 1) + `,", "`,")
+ } else if repeated {
+ repeatedName := `repeatedStringFor` + fieldname
+ p.P("`", fieldname, ":`", ` + `, repeatedName, " + `,", "`,")
+ } else {
+ p.P("`", fieldname, ":`", ` + `, stringsPkg.Use(), `.Replace(`, stringsPkg.Use(), `.Replace(`, stringfunc, `, "`, typeName, `","`, msgname, `"`, ", 1),`&`,``,1) + `,", "`,")
+ }
+ } else {
+ if nullable && !repeated && !proto3 {
+ p.P("`", fieldname, ":`", ` + valueToString`, p.localName, `(this.`, fieldname, ") + `,", "`,")
+ } else {
+ p.P("`", fieldname, ":`", ` + `, fmtPkg.Use(), `.Sprintf("%v", this.`, fieldname, ") + `,", "`,")
+ }
+ }
+ }
+ if message.DescriptorProto.HasExtension() {
+ if gogoproto.HasExtensionsMap(file.FileDescriptorProto, message.DescriptorProto) {
+ p.P("`XXX_InternalExtensions:` + ", protoPkg.Use(), ".StringFromInternalExtension(this) + `,`,")
+ } else {
+ p.P("`XXX_extensions:` + ", protoPkg.Use(), ".StringFromExtensionsBytes(this.XXX_extensions) + `,`,")
+ }
+ }
+ if gogoproto.HasUnrecognized(file.FileDescriptorProto, message.DescriptorProto) {
+ p.P("`XXX_unrecognized:` + ", fmtPkg.Use(), `.Sprintf("%v", this.XXX_unrecognized) + `, "`,`,")
+ }
+ p.P("`}`,")
+ p.P(`}`, `,""`, ")")
+ p.P(`return s`)
+ p.Out()
+ p.P(`}`)
+
+ //Generate String methods for oneof fields
+ for _, field := range message.Field {
+ oneof := field.OneofIndex != nil
+ if !oneof {
+ continue
+ }
+ ccTypeName := p.OneOfTypeName(message, field)
+ p.P(`func (this *`, ccTypeName, `) String() string {`)
+ p.In()
+ p.P(`if this == nil {`)
+ p.In()
+ p.P(`return "nil"`)
+ p.Out()
+ p.P(`}`)
+ p.P("s := ", stringsPkg.Use(), ".Join([]string{`&", ccTypeName, "{`,")
+ fieldname := p.GetOneOfFieldName(message, field)
+ if field.IsMessage() || p.IsGroup(field) {
+ desc := p.ObjectNamed(field.GetTypeName())
+ msgname := p.TypeName(desc)
+ msgnames := strings.Split(msgname, ".")
+ typeName := msgnames[len(msgnames)-1]
+ p.P("`", fieldname, ":`", ` + `, stringsPkg.Use(), `.Replace(`, fmtPkg.Use(), `.Sprintf("%v", this.`, fieldname, `), "`, typeName, `","`, msgname, `"`, ", 1) + `,", "`,")
+ } else {
+ p.P("`", fieldname, ":`", ` + `, fmtPkg.Use(), `.Sprintf("%v", this.`, fieldname, ") + `,", "`,")
+ }
+ p.P("`}`,")
+ p.P(`}`, `,""`, ")")
+ p.P(`return s`)
+ p.Out()
+ p.P(`}`)
+ }
+ }
+
+ if !p.atleastOne {
+ return
+ }
+
+ p.P(`func valueToString`, p.localName, `(v interface{}) string {`)
+ p.In()
+ p.P(`rv := `, reflectPkg.Use(), `.ValueOf(v)`)
+ p.P(`if rv.IsNil() {`)
+ p.In()
+ p.P(`return "nil"`)
+ p.Out()
+ p.P(`}`)
+ p.P(`pv := `, reflectPkg.Use(), `.Indirect(rv).Interface()`)
+ p.P(`return `, fmtPkg.Use(), `.Sprintf("*%v", pv)`)
+ p.Out()
+ p.P(`}`)
+
+}
+
+func init() {
+ generator.RegisterPlugin(NewStringer())
+}
diff --git a/vendor/github.com/gogo/protobuf/plugin/stringer/stringertest.go b/vendor/github.com/gogo/protobuf/plugin/stringer/stringertest.go
new file mode 100644
index 00000000000..0912a22df63
--- /dev/null
+++ b/vendor/github.com/gogo/protobuf/plugin/stringer/stringertest.go
@@ -0,0 +1,83 @@
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2013, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// 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.
+//
+// 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 stringer
+
+import (
+ "github.com/gogo/protobuf/gogoproto"
+ "github.com/gogo/protobuf/plugin/testgen"
+ "github.com/gogo/protobuf/protoc-gen-gogo/generator"
+)
+
+type test struct {
+ *generator.Generator
+}
+
+func NewTest(g *generator.Generator) testgen.TestPlugin {
+ return &test{g}
+}
+
+func (p *test) Generate(imports generator.PluginImports, file *generator.FileDescriptor) bool {
+ used := false
+ randPkg := imports.NewImport("math/rand")
+ timePkg := imports.NewImport("time")
+ testingPkg := imports.NewImport("testing")
+ fmtPkg := imports.NewImport("fmt")
+ for _, message := range file.Messages() {
+ ccTypeName := generator.CamelCaseSlice(message.TypeName())
+ if !gogoproto.IsStringer(file.FileDescriptorProto, message.DescriptorProto) {
+ continue
+ }
+ if message.DescriptorProto.GetOptions().GetMapEntry() {
+ continue
+ }
+
+ if gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
+ used = true
+ p.P(`func Test`, ccTypeName, `Stringer(t *`, testingPkg.Use(), `.T) {`)
+ p.In()
+ p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(`, timePkg.Use(), `.Now().UnixNano()))`)
+ p.P(`p := NewPopulated`, ccTypeName, `(popr, false)`)
+ p.P(`s1 := p.String()`)
+ p.P(`s2 := `, fmtPkg.Use(), `.Sprintf("%v", p)`)
+ p.P(`if s1 != s2 {`)
+ p.In()
+ p.P(`t.Fatalf("String want %v got %v", s1, s2)`)
+ p.Out()
+ p.P(`}`)
+ p.Out()
+ p.P(`}`)
+ }
+
+ }
+ return used
+}
+
+func init() {
+ testgen.RegisterTestPlugin(NewTest)
+}
diff --git a/vendor/github.com/gogo/protobuf/plugin/testgen/testgen.go b/vendor/github.com/gogo/protobuf/plugin/testgen/testgen.go
new file mode 100644
index 00000000000..e0a9287e560
--- /dev/null
+++ b/vendor/github.com/gogo/protobuf/plugin/testgen/testgen.go
@@ -0,0 +1,608 @@
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2013, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// 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.
+//
+// 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.
+
+/*
+The testgen plugin generates Test and Benchmark functions for each message.
+
+Tests are enabled using the following extensions:
+
+ - testgen
+ - testgen_all
+
+Benchmarks are enabled using the following extensions:
+
+ - benchgen
+ - benchgen_all
+
+Let us look at:
+
+ github.com/gogo/protobuf/test/example/example.proto
+
+Btw all the output can be seen at:
+
+ github.com/gogo/protobuf/test/example/*
+
+The following message:
+
+ option (gogoproto.testgen_all) = true;
+ option (gogoproto.benchgen_all) = true;
+
+ message A {
+ optional string Description = 1 [(gogoproto.nullable) = false];
+ optional int64 Number = 2 [(gogoproto.nullable) = false];
+ optional bytes Id = 3 [(gogoproto.customtype) = "github.com/gogo/protobuf/test/custom.Uuid", (gogoproto.nullable) = false];
+ }
+
+given to the testgen plugin, will generate the following test code:
+
+ func TestAProto(t *testing.T) {
+ popr := math_rand.New(math_rand.NewSource(time.Now().UnixNano()))
+ p := NewPopulatedA(popr, false)
+ dAtA, err := github_com_gogo_protobuf_proto.Marshal(p)
+ if err != nil {
+ panic(err)
+ }
+ msg := &A{}
+ if err := github_com_gogo_protobuf_proto.Unmarshal(dAtA, msg); err != nil {
+ panic(err)
+ }
+ for i := range dAtA {
+ dAtA[i] = byte(popr.Intn(256))
+ }
+ if err := p.VerboseEqual(msg); err != nil {
+ t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err)
+ }
+ if !p.Equal(msg) {
+ t.Fatalf("%#v !Proto %#v", msg, p)
+ }
+ }
+
+ func BenchmarkAProtoMarshal(b *testing.B) {
+ popr := math_rand.New(math_rand.NewSource(616))
+ total := 0
+ pops := make([]*A, 10000)
+ for i := 0; i < 10000; i++ {
+ pops[i] = NewPopulatedA(popr, false)
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ dAtA, err := github_com_gogo_protobuf_proto.Marshal(pops[i%10000])
+ if err != nil {
+ panic(err)
+ }
+ total += len(dAtA)
+ }
+ b.SetBytes(int64(total / b.N))
+ }
+
+ func BenchmarkAProtoUnmarshal(b *testing.B) {
+ popr := math_rand.New(math_rand.NewSource(616))
+ total := 0
+ datas := make([][]byte, 10000)
+ for i := 0; i < 10000; i++ {
+ dAtA, err := github_com_gogo_protobuf_proto.Marshal(NewPopulatedA(popr, false))
+ if err != nil {
+ panic(err)
+ }
+ datas[i] = dAtA
+ }
+ msg := &A{}
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ total += len(datas[i%10000])
+ if err := github_com_gogo_protobuf_proto.Unmarshal(datas[i%10000], msg); err != nil {
+ panic(err)
+ }
+ }
+ b.SetBytes(int64(total / b.N))
+ }
+
+
+ func TestAJSON(t *testing1.T) {
+ popr := math_rand1.New(math_rand1.NewSource(time1.Now().UnixNano()))
+ p := NewPopulatedA(popr, true)
+ jsondata, err := encoding_json.Marshal(p)
+ if err != nil {
+ panic(err)
+ }
+ msg := &A{}
+ err = encoding_json.Unmarshal(jsondata, msg)
+ if err != nil {
+ panic(err)
+ }
+ if err := p.VerboseEqual(msg); err != nil {
+ t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err)
+ }
+ if !p.Equal(msg) {
+ t.Fatalf("%#v !Json Equal %#v", msg, p)
+ }
+ }
+
+ func TestAProtoText(t *testing2.T) {
+ popr := math_rand2.New(math_rand2.NewSource(time2.Now().UnixNano()))
+ p := NewPopulatedA(popr, true)
+ dAtA := github_com_gogo_protobuf_proto1.MarshalTextString(p)
+ msg := &A{}
+ if err := github_com_gogo_protobuf_proto1.UnmarshalText(dAtA, msg); err != nil {
+ panic(err)
+ }
+ if err := p.VerboseEqual(msg); err != nil {
+ t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err)
+ }
+ if !p.Equal(msg) {
+ t.Fatalf("%#v !Proto %#v", msg, p)
+ }
+ }
+
+ func TestAProtoCompactText(t *testing2.T) {
+ popr := math_rand2.New(math_rand2.NewSource(time2.Now().UnixNano()))
+ p := NewPopulatedA(popr, true)
+ dAtA := github_com_gogo_protobuf_proto1.CompactTextString(p)
+ msg := &A{}
+ if err := github_com_gogo_protobuf_proto1.UnmarshalText(dAtA, msg); err != nil {
+ panic(err)
+ }
+ if err := p.VerboseEqual(msg); err != nil {
+ t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err)
+ }
+ if !p.Equal(msg) {
+ t.Fatalf("%#v !Proto %#v", msg, p)
+ }
+ }
+
+Other registered tests are also generated.
+Tests are registered to this test plugin by calling the following function.
+
+ func RegisterTestPlugin(newFunc NewTestPlugin)
+
+where NewTestPlugin is:
+
+ type NewTestPlugin func(g *generator.Generator) TestPlugin
+
+and TestPlugin is an interface:
+
+ type TestPlugin interface {
+ Generate(imports generator.PluginImports, file *generator.FileDescriptor) (used bool)
+ }
+
+Plugins that use this interface include:
+
+ - populate
+ - gostring
+ - equal
+ - union
+ - and more
+
+Please look at these plugins as examples of how to create your own.
+A good idea is to let each plugin generate its own tests.
+
+*/
+package testgen
+
+import (
+ "github.com/gogo/protobuf/gogoproto"
+ "github.com/gogo/protobuf/protoc-gen-gogo/generator"
+)
+
+type TestPlugin interface {
+ Generate(imports generator.PluginImports, file *generator.FileDescriptor) (used bool)
+}
+
+type NewTestPlugin func(g *generator.Generator) TestPlugin
+
+var testplugins = make([]NewTestPlugin, 0)
+
+func RegisterTestPlugin(newFunc NewTestPlugin) {
+ testplugins = append(testplugins, newFunc)
+}
+
+type plugin struct {
+ *generator.Generator
+ generator.PluginImports
+ tests []TestPlugin
+}
+
+func NewPlugin() *plugin {
+ return &plugin{}
+}
+
+func (p *plugin) Name() string {
+ return "testgen"
+}
+
+func (p *plugin) Init(g *generator.Generator) {
+ p.Generator = g
+ p.tests = make([]TestPlugin, 0, len(testplugins))
+ for i := range testplugins {
+ p.tests = append(p.tests, testplugins[i](g))
+ }
+}
+
+func (p *plugin) Generate(file *generator.FileDescriptor) {
+ p.PluginImports = generator.NewPluginImports(p.Generator)
+ atLeastOne := false
+ for i := range p.tests {
+ used := p.tests[i].Generate(p.PluginImports, file)
+ if used {
+ atLeastOne = true
+ }
+ }
+ if atLeastOne {
+ p.P(`//These tests are generated by github.com/gogo/protobuf/plugin/testgen`)
+ }
+}
+
+type testProto struct {
+ *generator.Generator
+}
+
+func newProto(g *generator.Generator) TestPlugin {
+ return &testProto{g}
+}
+
+func (p *testProto) Generate(imports generator.PluginImports, file *generator.FileDescriptor) bool {
+ used := false
+ testingPkg := imports.NewImport("testing")
+ randPkg := imports.NewImport("math/rand")
+ timePkg := imports.NewImport("time")
+ protoPkg := imports.NewImport("github.com/gogo/protobuf/proto")
+ if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
+ protoPkg = imports.NewImport("github.com/golang/protobuf/proto")
+ }
+ for _, message := range file.Messages() {
+ ccTypeName := generator.CamelCaseSlice(message.TypeName())
+ if message.DescriptorProto.GetOptions().GetMapEntry() {
+ continue
+ }
+ if gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
+ used = true
+
+ p.P(`func Test`, ccTypeName, `Proto(t *`, testingPkg.Use(), `.T) {`)
+ p.In()
+ p.P(`seed := `, timePkg.Use(), `.Now().UnixNano()`)
+ p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(seed))`)
+ p.P(`p := NewPopulated`, ccTypeName, `(popr, false)`)
+ p.P(`dAtA, err := `, protoPkg.Use(), `.Marshal(p)`)
+ p.P(`if err != nil {`)
+ p.In()
+ p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`)
+ p.Out()
+ p.P(`}`)
+ p.P(`msg := &`, ccTypeName, `{}`)
+ p.P(`if err := `, protoPkg.Use(), `.Unmarshal(dAtA, msg); err != nil {`)
+ p.In()
+ p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`)
+ p.Out()
+ p.P(`}`)
+ p.P(`littlefuzz := make([]byte, len(dAtA))`)
+ p.P(`copy(littlefuzz, dAtA)`)
+ p.P(`for i := range dAtA {`)
+ p.In()
+ p.P(`dAtA[i] = byte(popr.Intn(256))`)
+ p.Out()
+ p.P(`}`)
+ if gogoproto.HasVerboseEqual(file.FileDescriptorProto, message.DescriptorProto) {
+ p.P(`if err := p.VerboseEqual(msg); err != nil {`)
+ p.In()
+ p.P(`t.Fatalf("seed = %d, %#v !VerboseProto %#v, since %v", seed, msg, p, err)`)
+ p.Out()
+ p.P(`}`)
+ }
+ p.P(`if !p.Equal(msg) {`)
+ p.In()
+ p.P(`t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p)`)
+ p.Out()
+ p.P(`}`)
+ p.P(`if len(littlefuzz) > 0 {`)
+ p.In()
+ p.P(`fuzzamount := 100`)
+ p.P(`for i := 0; i < fuzzamount; i++ {`)
+ p.In()
+ p.P(`littlefuzz[popr.Intn(len(littlefuzz))] = byte(popr.Intn(256))`)
+ p.P(`littlefuzz = append(littlefuzz, byte(popr.Intn(256)))`)
+ p.Out()
+ p.P(`}`)
+ p.P(`// shouldn't panic`)
+ p.P(`_ = `, protoPkg.Use(), `.Unmarshal(littlefuzz, msg)`)
+ p.Out()
+ p.P(`}`)
+ p.Out()
+ p.P(`}`)
+ p.P()
+ }
+
+ if gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
+ if gogoproto.IsMarshaler(file.FileDescriptorProto, message.DescriptorProto) || gogoproto.IsUnsafeMarshaler(file.FileDescriptorProto, message.DescriptorProto) {
+ p.P(`func Test`, ccTypeName, `MarshalTo(t *`, testingPkg.Use(), `.T) {`)
+ p.In()
+ p.P(`seed := `, timePkg.Use(), `.Now().UnixNano()`)
+ p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(seed))`)
+ p.P(`p := NewPopulated`, ccTypeName, `(popr, false)`)
+ if gogoproto.IsProtoSizer(file.FileDescriptorProto, message.DescriptorProto) {
+ p.P(`size := p.ProtoSize()`)
+ } else {
+ p.P(`size := p.Size()`)
+ }
+ p.P(`dAtA := make([]byte, size)`)
+ p.P(`for i := range dAtA {`)
+ p.In()
+ p.P(`dAtA[i] = byte(popr.Intn(256))`)
+ p.Out()
+ p.P(`}`)
+ p.P(`_, err := p.MarshalTo(dAtA)`)
+ p.P(`if err != nil {`)
+ p.In()
+ p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`)
+ p.Out()
+ p.P(`}`)
+ p.P(`msg := &`, ccTypeName, `{}`)
+ p.P(`if err := `, protoPkg.Use(), `.Unmarshal(dAtA, msg); err != nil {`)
+ p.In()
+ p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`)
+ p.Out()
+ p.P(`}`)
+ p.P(`for i := range dAtA {`)
+ p.In()
+ p.P(`dAtA[i] = byte(popr.Intn(256))`)
+ p.Out()
+ p.P(`}`)
+ if gogoproto.HasVerboseEqual(file.FileDescriptorProto, message.DescriptorProto) {
+ p.P(`if err := p.VerboseEqual(msg); err != nil {`)
+ p.In()
+ p.P(`t.Fatalf("seed = %d, %#v !VerboseProto %#v, since %v", seed, msg, p, err)`)
+ p.Out()
+ p.P(`}`)
+ }
+ p.P(`if !p.Equal(msg) {`)
+ p.In()
+ p.P(`t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p)`)
+ p.Out()
+ p.P(`}`)
+ p.Out()
+ p.P(`}`)
+ p.P()
+ }
+ }
+
+ if gogoproto.HasBenchGen(file.FileDescriptorProto, message.DescriptorProto) {
+ used = true
+ p.P(`func Benchmark`, ccTypeName, `ProtoMarshal(b *`, testingPkg.Use(), `.B) {`)
+ p.In()
+ p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(616))`)
+ p.P(`total := 0`)
+ p.P(`pops := make([]*`, ccTypeName, `, 10000)`)
+ p.P(`for i := 0; i < 10000; i++ {`)
+ p.In()
+ p.P(`pops[i] = NewPopulated`, ccTypeName, `(popr, false)`)
+ p.Out()
+ p.P(`}`)
+ p.P(`b.ResetTimer()`)
+ p.P(`for i := 0; i < b.N; i++ {`)
+ p.In()
+ p.P(`dAtA, err := `, protoPkg.Use(), `.Marshal(pops[i%10000])`)
+ p.P(`if err != nil {`)
+ p.In()
+ p.P(`panic(err)`)
+ p.Out()
+ p.P(`}`)
+ p.P(`total += len(dAtA)`)
+ p.Out()
+ p.P(`}`)
+ p.P(`b.SetBytes(int64(total / b.N))`)
+ p.Out()
+ p.P(`}`)
+ p.P()
+
+ p.P(`func Benchmark`, ccTypeName, `ProtoUnmarshal(b *`, testingPkg.Use(), `.B) {`)
+ p.In()
+ p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(616))`)
+ p.P(`total := 0`)
+ p.P(`datas := make([][]byte, 10000)`)
+ p.P(`for i := 0; i < 10000; i++ {`)
+ p.In()
+ p.P(`dAtA, err := `, protoPkg.Use(), `.Marshal(NewPopulated`, ccTypeName, `(popr, false))`)
+ p.P(`if err != nil {`)
+ p.In()
+ p.P(`panic(err)`)
+ p.Out()
+ p.P(`}`)
+ p.P(`datas[i] = dAtA`)
+ p.Out()
+ p.P(`}`)
+ p.P(`msg := &`, ccTypeName, `{}`)
+ p.P(`b.ResetTimer()`)
+ p.P(`for i := 0; i < b.N; i++ {`)
+ p.In()
+ p.P(`total += len(datas[i%10000])`)
+ p.P(`if err := `, protoPkg.Use(), `.Unmarshal(datas[i%10000], msg); err != nil {`)
+ p.In()
+ p.P(`panic(err)`)
+ p.Out()
+ p.P(`}`)
+ p.Out()
+ p.P(`}`)
+ p.P(`b.SetBytes(int64(total / b.N))`)
+ p.Out()
+ p.P(`}`)
+ p.P()
+ }
+ }
+ return used
+}
+
+type testJson struct {
+ *generator.Generator
+}
+
+func newJson(g *generator.Generator) TestPlugin {
+ return &testJson{g}
+}
+
+func (p *testJson) Generate(imports generator.PluginImports, file *generator.FileDescriptor) bool {
+ used := false
+ testingPkg := imports.NewImport("testing")
+ randPkg := imports.NewImport("math/rand")
+ timePkg := imports.NewImport("time")
+ jsonPkg := imports.NewImport("github.com/gogo/protobuf/jsonpb")
+ for _, message := range file.Messages() {
+ ccTypeName := generator.CamelCaseSlice(message.TypeName())
+ if message.DescriptorProto.GetOptions().GetMapEntry() {
+ continue
+ }
+ if gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
+ used = true
+ p.P(`func Test`, ccTypeName, `JSON(t *`, testingPkg.Use(), `.T) {`)
+ p.In()
+ p.P(`seed := `, timePkg.Use(), `.Now().UnixNano()`)
+ p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(seed))`)
+ p.P(`p := NewPopulated`, ccTypeName, `(popr, true)`)
+ p.P(`marshaler := `, jsonPkg.Use(), `.Marshaler{}`)
+ p.P(`jsondata, err := marshaler.MarshalToString(p)`)
+ p.P(`if err != nil {`)
+ p.In()
+ p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`)
+ p.Out()
+ p.P(`}`)
+ p.P(`msg := &`, ccTypeName, `{}`)
+ p.P(`err = `, jsonPkg.Use(), `.UnmarshalString(jsondata, msg)`)
+ p.P(`if err != nil {`)
+ p.In()
+ p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`)
+ p.Out()
+ p.P(`}`)
+ if gogoproto.HasVerboseEqual(file.FileDescriptorProto, message.DescriptorProto) {
+ p.P(`if err := p.VerboseEqual(msg); err != nil {`)
+ p.In()
+ p.P(`t.Fatalf("seed = %d, %#v !VerboseProto %#v, since %v", seed, msg, p, err)`)
+ p.Out()
+ p.P(`}`)
+ }
+ p.P(`if !p.Equal(msg) {`)
+ p.In()
+ p.P(`t.Fatalf("seed = %d, %#v !Json Equal %#v", seed, msg, p)`)
+ p.Out()
+ p.P(`}`)
+ p.Out()
+ p.P(`}`)
+ }
+ }
+ return used
+}
+
+type testText struct {
+ *generator.Generator
+}
+
+func newText(g *generator.Generator) TestPlugin {
+ return &testText{g}
+}
+
+func (p *testText) Generate(imports generator.PluginImports, file *generator.FileDescriptor) bool {
+ used := false
+ testingPkg := imports.NewImport("testing")
+ randPkg := imports.NewImport("math/rand")
+ timePkg := imports.NewImport("time")
+ protoPkg := imports.NewImport("github.com/gogo/protobuf/proto")
+ if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
+ protoPkg = imports.NewImport("github.com/golang/protobuf/proto")
+ }
+ //fmtPkg := imports.NewImport("fmt")
+ for _, message := range file.Messages() {
+ ccTypeName := generator.CamelCaseSlice(message.TypeName())
+ if message.DescriptorProto.GetOptions().GetMapEntry() {
+ continue
+ }
+ if gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
+ used = true
+
+ p.P(`func Test`, ccTypeName, `ProtoText(t *`, testingPkg.Use(), `.T) {`)
+ p.In()
+ p.P(`seed := `, timePkg.Use(), `.Now().UnixNano()`)
+ p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(seed))`)
+ p.P(`p := NewPopulated`, ccTypeName, `(popr, true)`)
+ p.P(`dAtA := `, protoPkg.Use(), `.MarshalTextString(p)`)
+ p.P(`msg := &`, ccTypeName, `{}`)
+ p.P(`if err := `, protoPkg.Use(), `.UnmarshalText(dAtA, msg); err != nil {`)
+ p.In()
+ p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`)
+ p.Out()
+ p.P(`}`)
+ if gogoproto.HasVerboseEqual(file.FileDescriptorProto, message.DescriptorProto) {
+ p.P(`if err := p.VerboseEqual(msg); err != nil {`)
+ p.In()
+ p.P(`t.Fatalf("seed = %d, %#v !VerboseProto %#v, since %v", seed, msg, p, err)`)
+ p.Out()
+ p.P(`}`)
+ }
+ p.P(`if !p.Equal(msg) {`)
+ p.In()
+ p.P(`t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p)`)
+ p.Out()
+ p.P(`}`)
+ p.Out()
+ p.P(`}`)
+ p.P()
+
+ p.P(`func Test`, ccTypeName, `ProtoCompactText(t *`, testingPkg.Use(), `.T) {`)
+ p.In()
+ p.P(`seed := `, timePkg.Use(), `.Now().UnixNano()`)
+ p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(seed))`)
+ p.P(`p := NewPopulated`, ccTypeName, `(popr, true)`)
+ p.P(`dAtA := `, protoPkg.Use(), `.CompactTextString(p)`)
+ p.P(`msg := &`, ccTypeName, `{}`)
+ p.P(`if err := `, protoPkg.Use(), `.UnmarshalText(dAtA, msg); err != nil {`)
+ p.In()
+ p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`)
+ p.Out()
+ p.P(`}`)
+ if gogoproto.HasVerboseEqual(file.FileDescriptorProto, message.DescriptorProto) {
+ p.P(`if err := p.VerboseEqual(msg); err != nil {`)
+ p.In()
+ p.P(`t.Fatalf("seed = %d, %#v !VerboseProto %#v, since %v", seed, msg, p, err)`)
+ p.Out()
+ p.P(`}`)
+ }
+ p.P(`if !p.Equal(msg) {`)
+ p.In()
+ p.P(`t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p)`)
+ p.Out()
+ p.P(`}`)
+ p.Out()
+ p.P(`}`)
+ p.P()
+
+ }
+ }
+ return used
+}
+
+func init() {
+ RegisterTestPlugin(newProto)
+ RegisterTestPlugin(newJson)
+ RegisterTestPlugin(newText)
+}
diff --git a/vendor/github.com/gogo/protobuf/plugin/union/union.go b/vendor/github.com/gogo/protobuf/plugin/union/union.go
new file mode 100644
index 00000000000..90def721c9d
--- /dev/null
+++ b/vendor/github.com/gogo/protobuf/plugin/union/union.go
@@ -0,0 +1,209 @@
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2013, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// 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.
+//
+// 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.
+
+/*
+The onlyone plugin generates code for the onlyone extension.
+All fields must be nullable and only one of the fields may be set, like a union.
+Two methods are generated
+
+ GetValue() interface{}
+
+and
+
+ SetValue(v interface{}) (set bool)
+
+These provide easier interaction with a onlyone.
+
+The onlyone extension is not called union as this causes compile errors in the C++ generated code.
+There can only be one ;)
+
+It is enabled by the following extensions:
+
+ - onlyone
+ - onlyone_all
+
+The onlyone plugin also generates a test given it is enabled using one of the following extensions:
+
+ - testgen
+ - testgen_all
+
+Lets look at:
+
+ github.com/gogo/protobuf/test/example/example.proto
+
+Btw all the output can be seen at:
+
+ github.com/gogo/protobuf/test/example/*
+
+The following message:
+
+ message U {
+ option (gogoproto.onlyone) = true;
+ optional A A = 1;
+ optional B B = 2;
+ }
+
+given to the onlyone plugin, will generate code which looks a lot like this:
+
+ func (this *U) GetValue() interface{} {
+ if this.A != nil {
+ return this.A
+ }
+ if this.B != nil {
+ return this.B
+ }
+ return nil
+ }
+
+ func (this *U) SetValue(value interface{}) bool {
+ switch vt := value.(type) {
+ case *A:
+ this.A = vt
+ case *B:
+ this.B = vt
+ default:
+ return false
+ }
+ return true
+ }
+
+and the following test code:
+
+ func TestUUnion(t *testing.T) {
+ popr := math_rand.New(math_rand.NewSource(time.Now().UnixNano()))
+ p := NewPopulatedU(popr)
+ v := p.GetValue()
+ msg := &U{}
+ if !msg.SetValue(v) {
+ t.Fatalf("Union: Could not set Value")
+ }
+ if !p.Equal(msg) {
+ t.Fatalf("%#v !Union Equal %#v", msg, p)
+ }
+ }
+
+*/
+package union
+
+import (
+ "github.com/gogo/protobuf/gogoproto"
+ "github.com/gogo/protobuf/protoc-gen-gogo/generator"
+)
+
+type union struct {
+ *generator.Generator
+ generator.PluginImports
+}
+
+func NewUnion() *union {
+ return &union{}
+}
+
+func (p *union) Name() string {
+ return "union"
+}
+
+func (p *union) Init(g *generator.Generator) {
+ p.Generator = g
+}
+
+func (p *union) Generate(file *generator.FileDescriptor) {
+ p.PluginImports = generator.NewPluginImports(p.Generator)
+
+ for _, message := range file.Messages() {
+ if !gogoproto.IsUnion(file.FileDescriptorProto, message.DescriptorProto) {
+ continue
+ }
+ if message.DescriptorProto.HasExtension() {
+ panic("onlyone does not currently support extensions")
+ }
+ if message.DescriptorProto.GetOptions().GetMapEntry() {
+ continue
+ }
+
+ ccTypeName := generator.CamelCaseSlice(message.TypeName())
+ p.P(`func (this *`, ccTypeName, `) GetValue() interface{} {`)
+ p.In()
+ for _, field := range message.Field {
+ fieldname := p.GetFieldName(message, field)
+ if fieldname == "Value" {
+ panic("cannot have a onlyone message " + ccTypeName + " with a field named Value")
+ }
+ p.P(`if this.`, fieldname, ` != nil {`)
+ p.In()
+ p.P(`return this.`, fieldname)
+ p.Out()
+ p.P(`}`)
+ }
+ p.P(`return nil`)
+ p.Out()
+ p.P(`}`)
+ p.P(``)
+ p.P(`func (this *`, ccTypeName, `) SetValue(value interface{}) bool {`)
+ p.In()
+ p.P(`switch vt := value.(type) {`)
+ p.In()
+ for _, field := range message.Field {
+ fieldname := p.GetFieldName(message, field)
+ goTyp, _ := p.GoType(message, field)
+ p.P(`case `, goTyp, `:`)
+ p.In()
+ p.P(`this.`, fieldname, ` = vt`)
+ p.Out()
+ }
+ p.P(`default:`)
+ p.In()
+ for _, field := range message.Field {
+ fieldname := p.GetFieldName(message, field)
+ if field.IsMessage() {
+ goTyp, _ := p.GoType(message, field)
+ obj := p.ObjectNamed(field.GetTypeName()).(*generator.Descriptor)
+
+ if gogoproto.IsUnion(obj.File().FileDescriptorProto, obj.DescriptorProto) {
+ p.P(`this.`, fieldname, ` = new(`, generator.GoTypeToName(goTyp), `)`)
+ p.P(`if set := this.`, fieldname, `.SetValue(value); set {`)
+ p.In()
+ p.P(`return true`)
+ p.Out()
+ p.P(`}`)
+ p.P(`this.`, fieldname, ` = nil`)
+ }
+ }
+ }
+ p.P(`return false`)
+ p.Out()
+ p.P(`}`)
+ p.P(`return true`)
+ p.Out()
+ p.P(`}`)
+ }
+}
+
+func init() {
+ generator.RegisterPlugin(NewUnion())
+}
diff --git a/vendor/github.com/gogo/protobuf/plugin/union/uniontest.go b/vendor/github.com/gogo/protobuf/plugin/union/uniontest.go
new file mode 100644
index 00000000000..949cf833850
--- /dev/null
+++ b/vendor/github.com/gogo/protobuf/plugin/union/uniontest.go
@@ -0,0 +1,86 @@
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2013, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// 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.
+//
+// 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 union
+
+import (
+ "github.com/gogo/protobuf/gogoproto"
+ "github.com/gogo/protobuf/plugin/testgen"
+ "github.com/gogo/protobuf/protoc-gen-gogo/generator"
+)
+
+type test struct {
+ *generator.Generator
+}
+
+func NewTest(g *generator.Generator) testgen.TestPlugin {
+ return &test{g}
+}
+
+func (p *test) Generate(imports generator.PluginImports, file *generator.FileDescriptor) bool {
+ used := false
+ randPkg := imports.NewImport("math/rand")
+ timePkg := imports.NewImport("time")
+ testingPkg := imports.NewImport("testing")
+ for _, message := range file.Messages() {
+ if !gogoproto.IsUnion(file.FileDescriptorProto, message.DescriptorProto) ||
+ !gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
+ continue
+ }
+ if message.DescriptorProto.GetOptions().GetMapEntry() {
+ continue
+ }
+ used = true
+ ccTypeName := generator.CamelCaseSlice(message.TypeName())
+
+ p.P(`func Test`, ccTypeName, `OnlyOne(t *`, testingPkg.Use(), `.T) {`)
+ p.In()
+ p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(`, timePkg.Use(), `.Now().UnixNano()))`)
+ p.P(`p := NewPopulated`, ccTypeName, `(popr, true)`)
+ p.P(`v := p.GetValue()`)
+ p.P(`msg := &`, ccTypeName, `{}`)
+ p.P(`if !msg.SetValue(v) {`)
+ p.In()
+ p.P(`t.Fatalf("OnlyOne: Could not set Value")`)
+ p.Out()
+ p.P(`}`)
+ p.P(`if !p.Equal(msg) {`)
+ p.In()
+ p.P(`t.Fatalf("%#v !OnlyOne Equal %#v", msg, p)`)
+ p.Out()
+ p.P(`}`)
+ p.Out()
+ p.P(`}`)
+
+ }
+ return used
+}
+
+func init() {
+ testgen.RegisterTestPlugin(NewTest)
+}
diff --git a/vendor/github.com/gogo/protobuf/plugin/unmarshal/unmarshal.go b/vendor/github.com/gogo/protobuf/plugin/unmarshal/unmarshal.go
new file mode 100644
index 00000000000..fae67de4fd9
--- /dev/null
+++ b/vendor/github.com/gogo/protobuf/plugin/unmarshal/unmarshal.go
@@ -0,0 +1,1657 @@
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2013, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// 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.
+//
+// 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.
+
+/*
+The unmarshal plugin generates a Unmarshal method for each message.
+The `Unmarshal([]byte) error` method results in the fact that the message
+implements the Unmarshaler interface.
+The allows proto.Unmarshal to be faster by calling the generated Unmarshal method rather than using reflect.
+
+If is enabled by the following extensions:
+
+ - unmarshaler
+ - unmarshaler_all
+
+Or the following extensions:
+
+ - unsafe_unmarshaler
+ - unsafe_unmarshaler_all
+
+That is if you want to use the unsafe package in your generated code.
+The speed up using the unsafe package is not very significant.
+
+The generation of unmarshalling tests are enabled using one of the following extensions:
+
+ - testgen
+ - testgen_all
+
+And benchmarks given it is enabled using one of the following extensions:
+
+ - benchgen
+ - benchgen_all
+
+Let us look at:
+
+ github.com/gogo/protobuf/test/example/example.proto
+
+Btw all the output can be seen at:
+
+ github.com/gogo/protobuf/test/example/*
+
+The following message:
+
+ option (gogoproto.unmarshaler_all) = true;
+
+ message B {
+ option (gogoproto.description) = true;
+ optional A A = 1 [(gogoproto.nullable) = false, (gogoproto.embed) = true];
+ repeated bytes G = 2 [(gogoproto.customtype) = "github.com/gogo/protobuf/test/custom.Uint128", (gogoproto.nullable) = false];
+ }
+
+given to the unmarshal plugin, will generate the following code:
+
+ func (m *B) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return proto.ErrWrongType
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if err := m.A.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return proto.ErrWrongType
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.G = append(m.G, github_com_gogo_protobuf_test_custom.Uint128{})
+ if err := m.G[len(m.G)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ var sizeOfWire int
+ for {
+ sizeOfWire++
+ wire >>= 7
+ if wire == 0 {
+ break
+ }
+ }
+ iNdEx -= sizeOfWire
+ skippy, err := skip(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+ iNdEx += skippy
+ }
+ }
+ return nil
+ }
+
+Remember when using this code to call proto.Unmarshal.
+This will call m.Reset and invoke the generated Unmarshal method for you.
+If you call m.Unmarshal without m.Reset you could be merging protocol buffers.
+
+*/
+package unmarshal
+
+import (
+ "fmt"
+ "strconv"
+ "strings"
+
+ "github.com/gogo/protobuf/gogoproto"
+ "github.com/gogo/protobuf/proto"
+ descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
+ "github.com/gogo/protobuf/protoc-gen-gogo/generator"
+)
+
+type unmarshal struct {
+ *generator.Generator
+ generator.PluginImports
+ atleastOne bool
+ ioPkg generator.Single
+ mathPkg generator.Single
+ typesPkg generator.Single
+ binaryPkg generator.Single
+ localName string
+}
+
+func NewUnmarshal() *unmarshal {
+ return &unmarshal{}
+}
+
+func (p *unmarshal) Name() string {
+ return "unmarshal"
+}
+
+func (p *unmarshal) Init(g *generator.Generator) {
+ p.Generator = g
+}
+
+func (p *unmarshal) decodeVarint(varName string, typName string) {
+ p.P(`for shift := uint(0); ; shift += 7 {`)
+ p.In()
+ p.P(`if shift >= 64 {`)
+ p.In()
+ p.P(`return ErrIntOverflow` + p.localName)
+ p.Out()
+ p.P(`}`)
+ p.P(`if iNdEx >= l {`)
+ p.In()
+ p.P(`return `, p.ioPkg.Use(), `.ErrUnexpectedEOF`)
+ p.Out()
+ p.P(`}`)
+ p.P(`b := dAtA[iNdEx]`)
+ p.P(`iNdEx++`)
+ p.P(varName, ` |= `, typName, `(b&0x7F) << shift`)
+ p.P(`if b < 0x80 {`)
+ p.In()
+ p.P(`break`)
+ p.Out()
+ p.P(`}`)
+ p.Out()
+ p.P(`}`)
+}
+
+func (p *unmarshal) decodeFixed32(varName string, typeName string) {
+ p.P(`if (iNdEx+4) > l {`)
+ p.In()
+ p.P(`return `, p.ioPkg.Use(), `.ErrUnexpectedEOF`)
+ p.Out()
+ p.P(`}`)
+ p.P(varName, ` = `, typeName, `(`, p.binaryPkg.Use(), `.LittleEndian.Uint32(dAtA[iNdEx:]))`)
+ p.P(`iNdEx += 4`)
+}
+
+func (p *unmarshal) decodeFixed64(varName string, typeName string) {
+ p.P(`if (iNdEx+8) > l {`)
+ p.In()
+ p.P(`return `, p.ioPkg.Use(), `.ErrUnexpectedEOF`)
+ p.Out()
+ p.P(`}`)
+ p.P(varName, ` = `, typeName, `(`, p.binaryPkg.Use(), `.LittleEndian.Uint64(dAtA[iNdEx:]))`)
+ p.P(`iNdEx += 8`)
+}
+
+func (p *unmarshal) declareMapField(varName string, nullable bool, customType bool, field *descriptor.FieldDescriptorProto) {
+ switch field.GetType() {
+ case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
+ p.P(`var `, varName, ` float64`)
+ case descriptor.FieldDescriptorProto_TYPE_FLOAT:
+ p.P(`var `, varName, ` float32`)
+ case descriptor.FieldDescriptorProto_TYPE_INT64:
+ p.P(`var `, varName, ` int64`)
+ case descriptor.FieldDescriptorProto_TYPE_UINT64:
+ p.P(`var `, varName, ` uint64`)
+ case descriptor.FieldDescriptorProto_TYPE_INT32:
+ p.P(`var `, varName, ` int32`)
+ case descriptor.FieldDescriptorProto_TYPE_FIXED64:
+ p.P(`var `, varName, ` uint64`)
+ case descriptor.FieldDescriptorProto_TYPE_FIXED32:
+ p.P(`var `, varName, ` uint32`)
+ case descriptor.FieldDescriptorProto_TYPE_BOOL:
+ p.P(`var `, varName, ` bool`)
+ case descriptor.FieldDescriptorProto_TYPE_STRING:
+ cast, _ := p.GoType(nil, field)
+ cast = strings.Replace(cast, "*", "", 1)
+ p.P(`var `, varName, ` `, cast)
+ case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
+ if gogoproto.IsStdTime(field) {
+ p.P(varName, ` := new(time.Time)`)
+ } else if gogoproto.IsStdDuration(field) {
+ p.P(varName, ` := new(time.Duration)`)
+ } else if gogoproto.IsStdDouble(field) {
+ p.P(varName, ` := new(float64)`)
+ } else if gogoproto.IsStdFloat(field) {
+ p.P(varName, ` := new(float32)`)
+ } else if gogoproto.IsStdInt64(field) {
+ p.P(varName, ` := new(int64)`)
+ } else if gogoproto.IsStdUInt64(field) {
+ p.P(varName, ` := new(uint64)`)
+ } else if gogoproto.IsStdInt32(field) {
+ p.P(varName, ` := new(int32)`)
+ } else if gogoproto.IsStdUInt32(field) {
+ p.P(varName, ` := new(uint32)`)
+ } else if gogoproto.IsStdBool(field) {
+ p.P(varName, ` := new(bool)`)
+ } else if gogoproto.IsStdString(field) {
+ p.P(varName, ` := new(string)`)
+ } else if gogoproto.IsStdBytes(field) {
+ p.P(varName, ` := new([]byte)`)
+ } else {
+ desc := p.ObjectNamed(field.GetTypeName())
+ msgname := p.TypeName(desc)
+ if nullable {
+ p.P(`var `, varName, ` *`, msgname)
+ } else {
+ p.P(varName, ` := &`, msgname, `{}`)
+ }
+ }
+ case descriptor.FieldDescriptorProto_TYPE_BYTES:
+ if customType {
+ _, ctyp, err := generator.GetCustomType(field)
+ if err != nil {
+ panic(err)
+ }
+ p.P(`var `, varName, `1 `, ctyp)
+ p.P(`var `, varName, ` = &`, varName, `1`)
+ } else {
+ p.P(varName, ` := []byte{}`)
+ }
+ case descriptor.FieldDescriptorProto_TYPE_UINT32:
+ p.P(`var `, varName, ` uint32`)
+ case descriptor.FieldDescriptorProto_TYPE_ENUM:
+ typName := p.TypeName(p.ObjectNamed(field.GetTypeName()))
+ p.P(`var `, varName, ` `, typName)
+ case descriptor.FieldDescriptorProto_TYPE_SFIXED32:
+ p.P(`var `, varName, ` int32`)
+ case descriptor.FieldDescriptorProto_TYPE_SFIXED64:
+ p.P(`var `, varName, ` int64`)
+ case descriptor.FieldDescriptorProto_TYPE_SINT32:
+ p.P(`var `, varName, ` int32`)
+ case descriptor.FieldDescriptorProto_TYPE_SINT64:
+ p.P(`var `, varName, ` int64`)
+ }
+}
+
+func (p *unmarshal) mapField(varName string, customType bool, field *descriptor.FieldDescriptorProto) {
+ switch field.GetType() {
+ case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
+ p.P(`var `, varName, `temp uint64`)
+ p.decodeFixed64(varName+"temp", "uint64")
+ p.P(varName, ` = `, p.mathPkg.Use(), `.Float64frombits(`, varName, `temp)`)
+ case descriptor.FieldDescriptorProto_TYPE_FLOAT:
+ p.P(`var `, varName, `temp uint32`)
+ p.decodeFixed32(varName+"temp", "uint32")
+ p.P(varName, ` = `, p.mathPkg.Use(), `.Float32frombits(`, varName, `temp)`)
+ case descriptor.FieldDescriptorProto_TYPE_INT64:
+ p.decodeVarint(varName, "int64")
+ case descriptor.FieldDescriptorProto_TYPE_UINT64:
+ p.decodeVarint(varName, "uint64")
+ case descriptor.FieldDescriptorProto_TYPE_INT32:
+ p.decodeVarint(varName, "int32")
+ case descriptor.FieldDescriptorProto_TYPE_FIXED64:
+ p.decodeFixed64(varName, "uint64")
+ case descriptor.FieldDescriptorProto_TYPE_FIXED32:
+ p.decodeFixed32(varName, "uint32")
+ case descriptor.FieldDescriptorProto_TYPE_BOOL:
+ p.P(`var `, varName, `temp int`)
+ p.decodeVarint(varName+"temp", "int")
+ p.P(varName, ` = bool(`, varName, `temp != 0)`)
+ case descriptor.FieldDescriptorProto_TYPE_STRING:
+ p.P(`var stringLen`, varName, ` uint64`)
+ p.decodeVarint("stringLen"+varName, "uint64")
+ p.P(`intStringLen`, varName, ` := int(stringLen`, varName, `)`)
+ p.P(`if intStringLen`, varName, ` < 0 {`)
+ p.In()
+ p.P(`return ErrInvalidLength` + p.localName)
+ p.Out()
+ p.P(`}`)
+ p.P(`postStringIndex`, varName, ` := iNdEx + intStringLen`, varName)
+ p.P(`if postStringIndex`, varName, ` < 0 {`)
+ p.In()
+ p.P(`return ErrInvalidLength` + p.localName)
+ p.Out()
+ p.P(`}`)
+ p.P(`if postStringIndex`, varName, ` > l {`)
+ p.In()
+ p.P(`return `, p.ioPkg.Use(), `.ErrUnexpectedEOF`)
+ p.Out()
+ p.P(`}`)
+ cast, _ := p.GoType(nil, field)
+ cast = strings.Replace(cast, "*", "", 1)
+ p.P(varName, ` = `, cast, `(dAtA[iNdEx:postStringIndex`, varName, `])`)
+ p.P(`iNdEx = postStringIndex`, varName)
+ case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
+ p.P(`var mapmsglen int`)
+ p.decodeVarint("mapmsglen", "int")
+ p.P(`if mapmsglen < 0 {`)
+ p.In()
+ p.P(`return ErrInvalidLength` + p.localName)
+ p.Out()
+ p.P(`}`)
+ p.P(`postmsgIndex := iNdEx + mapmsglen`)
+ p.P(`if postmsgIndex < 0 {`)
+ p.In()
+ p.P(`return ErrInvalidLength` + p.localName)
+ p.Out()
+ p.P(`}`)
+ p.P(`if postmsgIndex > l {`)
+ p.In()
+ p.P(`return `, p.ioPkg.Use(), `.ErrUnexpectedEOF`)
+ p.Out()
+ p.P(`}`)
+ buf := `dAtA[iNdEx:postmsgIndex]`
+ if gogoproto.IsStdTime(field) {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdTimeUnmarshal(`, varName, `, `, buf, `); err != nil {`)
+ } else if gogoproto.IsStdDuration(field) {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdDurationUnmarshal(`, varName, `, `, buf, `); err != nil {`)
+ } else if gogoproto.IsStdDouble(field) {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdDoubleUnmarshal(`, varName, `, `, buf, `); err != nil {`)
+ } else if gogoproto.IsStdFloat(field) {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdFloatUnmarshal(`, varName, `, `, buf, `); err != nil {`)
+ } else if gogoproto.IsStdInt64(field) {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdInt64Unmarshal(`, varName, `, `, buf, `); err != nil {`)
+ } else if gogoproto.IsStdUInt64(field) {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdUInt64Unmarshal(`, varName, `, `, buf, `); err != nil {`)
+ } else if gogoproto.IsStdInt32(field) {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdInt32Unmarshal(`, varName, `, `, buf, `); err != nil {`)
+ } else if gogoproto.IsStdUInt32(field) {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdUInt32Unmarshal(`, varName, `, `, buf, `); err != nil {`)
+ } else if gogoproto.IsStdBool(field) {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdBoolUnmarshal(`, varName, `, `, buf, `); err != nil {`)
+ } else if gogoproto.IsStdString(field) {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdStringUnmarshal(`, varName, `, `, buf, `); err != nil {`)
+ } else if gogoproto.IsStdBytes(field) {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdBytesUnmarshal(`, varName, `, `, buf, `); err != nil {`)
+ } else {
+ desc := p.ObjectNamed(field.GetTypeName())
+ msgname := p.TypeName(desc)
+ p.P(varName, ` = &`, msgname, `{}`)
+ p.P(`if err := `, varName, `.Unmarshal(`, buf, `); err != nil {`)
+ }
+ p.In()
+ p.P(`return err`)
+ p.Out()
+ p.P(`}`)
+ p.P(`iNdEx = postmsgIndex`)
+ case descriptor.FieldDescriptorProto_TYPE_BYTES:
+ p.P(`var mapbyteLen uint64`)
+ p.decodeVarint("mapbyteLen", "uint64")
+ p.P(`intMapbyteLen := int(mapbyteLen)`)
+ p.P(`if intMapbyteLen < 0 {`)
+ p.In()
+ p.P(`return ErrInvalidLength` + p.localName)
+ p.Out()
+ p.P(`}`)
+ p.P(`postbytesIndex := iNdEx + intMapbyteLen`)
+ p.P(`if postbytesIndex < 0 {`)
+ p.In()
+ p.P(`return ErrInvalidLength` + p.localName)
+ p.Out()
+ p.P(`}`)
+ p.P(`if postbytesIndex > l {`)
+ p.In()
+ p.P(`return `, p.ioPkg.Use(), `.ErrUnexpectedEOF`)
+ p.Out()
+ p.P(`}`)
+ if customType {
+ p.P(`if err := `, varName, `.Unmarshal(dAtA[iNdEx:postbytesIndex]); err != nil {`)
+ p.In()
+ p.P(`return err`)
+ p.Out()
+ p.P(`}`)
+ } else {
+ p.P(varName, ` = make([]byte, mapbyteLen)`)
+ p.P(`copy(`, varName, `, dAtA[iNdEx:postbytesIndex])`)
+ }
+ p.P(`iNdEx = postbytesIndex`)
+ case descriptor.FieldDescriptorProto_TYPE_UINT32:
+ p.decodeVarint(varName, "uint32")
+ case descriptor.FieldDescriptorProto_TYPE_ENUM:
+ typName := p.TypeName(p.ObjectNamed(field.GetTypeName()))
+ p.decodeVarint(varName, typName)
+ case descriptor.FieldDescriptorProto_TYPE_SFIXED32:
+ p.decodeFixed32(varName, "int32")
+ case descriptor.FieldDescriptorProto_TYPE_SFIXED64:
+ p.decodeFixed64(varName, "int64")
+ case descriptor.FieldDescriptorProto_TYPE_SINT32:
+ p.P(`var `, varName, `temp int32`)
+ p.decodeVarint(varName+"temp", "int32")
+ p.P(varName, `temp = int32((uint32(`, varName, `temp) >> 1) ^ uint32(((`, varName, `temp&1)<<31)>>31))`)
+ p.P(varName, ` = int32(`, varName, `temp)`)
+ case descriptor.FieldDescriptorProto_TYPE_SINT64:
+ p.P(`var `, varName, `temp uint64`)
+ p.decodeVarint(varName+"temp", "uint64")
+ p.P(varName, `temp = (`, varName, `temp >> 1) ^ uint64((int64(`, varName, `temp&1)<<63)>>63)`)
+ p.P(varName, ` = int64(`, varName, `temp)`)
+ }
+}
+
+func (p *unmarshal) noStarOrSliceType(msg *generator.Descriptor, field *descriptor.FieldDescriptorProto) string {
+ typ, _ := p.GoType(msg, field)
+ if typ[0] == '*' {
+ return typ[1:]
+ }
+ if typ[0] == '[' && typ[1] == ']' {
+ return typ[2:]
+ }
+ return typ
+}
+
+func (p *unmarshal) field(file *generator.FileDescriptor, msg *generator.Descriptor, field *descriptor.FieldDescriptorProto, fieldname string, proto3 bool) {
+ repeated := field.IsRepeated()
+ nullable := gogoproto.IsNullable(field)
+ typ := p.noStarOrSliceType(msg, field)
+ oneof := field.OneofIndex != nil
+ switch *field.Type {
+ case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
+ p.P(`var v uint64`)
+ p.decodeFixed64("v", "uint64")
+ if oneof {
+ p.P(`m.`, fieldname, ` = &`, p.OneOfTypeName(msg, field), `{`, typ, "(", p.mathPkg.Use(), `.Float64frombits(v))}`)
+ } else if repeated {
+ p.P(`v2 := `, typ, "(", p.mathPkg.Use(), `.Float64frombits(v))`)
+ p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, v2)`)
+ } else if proto3 || !nullable {
+ p.P(`m.`, fieldname, ` = `, typ, "(", p.mathPkg.Use(), `.Float64frombits(v))`)
+ } else {
+ p.P(`v2 := `, typ, "(", p.mathPkg.Use(), `.Float64frombits(v))`)
+ p.P(`m.`, fieldname, ` = &v2`)
+ }
+ case descriptor.FieldDescriptorProto_TYPE_FLOAT:
+ p.P(`var v uint32`)
+ p.decodeFixed32("v", "uint32")
+ if oneof {
+ p.P(`m.`, fieldname, ` = &`, p.OneOfTypeName(msg, field), `{`, typ, "(", p.mathPkg.Use(), `.Float32frombits(v))}`)
+ } else if repeated {
+ p.P(`v2 := `, typ, "(", p.mathPkg.Use(), `.Float32frombits(v))`)
+ p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, v2)`)
+ } else if proto3 || !nullable {
+ p.P(`m.`, fieldname, ` = `, typ, "(", p.mathPkg.Use(), `.Float32frombits(v))`)
+ } else {
+ p.P(`v2 := `, typ, "(", p.mathPkg.Use(), `.Float32frombits(v))`)
+ p.P(`m.`, fieldname, ` = &v2`)
+ }
+ case descriptor.FieldDescriptorProto_TYPE_INT64:
+ if oneof {
+ p.P(`var v `, typ)
+ p.decodeVarint("v", typ)
+ p.P(`m.`, fieldname, ` = &`, p.OneOfTypeName(msg, field), `{v}`)
+ } else if repeated {
+ p.P(`var v `, typ)
+ p.decodeVarint("v", typ)
+ p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, v)`)
+ } else if proto3 || !nullable {
+ p.P(`m.`, fieldname, ` = 0`)
+ p.decodeVarint("m."+fieldname, typ)
+ } else {
+ p.P(`var v `, typ)
+ p.decodeVarint("v", typ)
+ p.P(`m.`, fieldname, ` = &v`)
+ }
+ case descriptor.FieldDescriptorProto_TYPE_UINT64:
+ if oneof {
+ p.P(`var v `, typ)
+ p.decodeVarint("v", typ)
+ p.P(`m.`, fieldname, ` = &`, p.OneOfTypeName(msg, field), `{v}`)
+ } else if repeated {
+ p.P(`var v `, typ)
+ p.decodeVarint("v", typ)
+ p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, v)`)
+ } else if proto3 || !nullable {
+ p.P(`m.`, fieldname, ` = 0`)
+ p.decodeVarint("m."+fieldname, typ)
+ } else {
+ p.P(`var v `, typ)
+ p.decodeVarint("v", typ)
+ p.P(`m.`, fieldname, ` = &v`)
+ }
+ case descriptor.FieldDescriptorProto_TYPE_INT32:
+ if oneof {
+ p.P(`var v `, typ)
+ p.decodeVarint("v", typ)
+ p.P(`m.`, fieldname, ` = &`, p.OneOfTypeName(msg, field), `{v}`)
+ } else if repeated {
+ p.P(`var v `, typ)
+ p.decodeVarint("v", typ)
+ p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, v)`)
+ } else if proto3 || !nullable {
+ p.P(`m.`, fieldname, ` = 0`)
+ p.decodeVarint("m."+fieldname, typ)
+ } else {
+ p.P(`var v `, typ)
+ p.decodeVarint("v", typ)
+ p.P(`m.`, fieldname, ` = &v`)
+ }
+ case descriptor.FieldDescriptorProto_TYPE_FIXED64:
+ if oneof {
+ p.P(`var v `, typ)
+ p.decodeFixed64("v", typ)
+ p.P(`m.`, fieldname, ` = &`, p.OneOfTypeName(msg, field), `{v}`)
+ } else if repeated {
+ p.P(`var v `, typ)
+ p.decodeFixed64("v", typ)
+ p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, v)`)
+ } else if proto3 || !nullable {
+ p.P(`m.`, fieldname, ` = 0`)
+ p.decodeFixed64("m."+fieldname, typ)
+ } else {
+ p.P(`var v `, typ)
+ p.decodeFixed64("v", typ)
+ p.P(`m.`, fieldname, ` = &v`)
+ }
+ case descriptor.FieldDescriptorProto_TYPE_FIXED32:
+ if oneof {
+ p.P(`var v `, typ)
+ p.decodeFixed32("v", typ)
+ p.P(`m.`, fieldname, ` = &`, p.OneOfTypeName(msg, field), `{v}`)
+ } else if repeated {
+ p.P(`var v `, typ)
+ p.decodeFixed32("v", typ)
+ p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, v)`)
+ } else if proto3 || !nullable {
+ p.P(`m.`, fieldname, ` = 0`)
+ p.decodeFixed32("m."+fieldname, typ)
+ } else {
+ p.P(`var v `, typ)
+ p.decodeFixed32("v", typ)
+ p.P(`m.`, fieldname, ` = &v`)
+ }
+ case descriptor.FieldDescriptorProto_TYPE_BOOL:
+ p.P(`var v int`)
+ p.decodeVarint("v", "int")
+ if oneof {
+ p.P(`b := `, typ, `(v != 0)`)
+ p.P(`m.`, fieldname, ` = &`, p.OneOfTypeName(msg, field), `{b}`)
+ } else if repeated {
+ p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, `, typ, `(v != 0))`)
+ } else if proto3 || !nullable {
+ p.P(`m.`, fieldname, ` = `, typ, `(v != 0)`)
+ } else {
+ p.P(`b := `, typ, `(v != 0)`)
+ p.P(`m.`, fieldname, ` = &b`)
+ }
+ case descriptor.FieldDescriptorProto_TYPE_STRING:
+ p.P(`var stringLen uint64`)
+ p.decodeVarint("stringLen", "uint64")
+ p.P(`intStringLen := int(stringLen)`)
+ p.P(`if intStringLen < 0 {`)
+ p.In()
+ p.P(`return ErrInvalidLength` + p.localName)
+ p.Out()
+ p.P(`}`)
+ p.P(`postIndex := iNdEx + intStringLen`)
+ p.P(`if postIndex < 0 {`)
+ p.In()
+ p.P(`return ErrInvalidLength` + p.localName)
+ p.Out()
+ p.P(`}`)
+ p.P(`if postIndex > l {`)
+ p.In()
+ p.P(`return `, p.ioPkg.Use(), `.ErrUnexpectedEOF`)
+ p.Out()
+ p.P(`}`)
+ if oneof {
+ p.P(`m.`, fieldname, ` = &`, p.OneOfTypeName(msg, field), `{`, typ, `(dAtA[iNdEx:postIndex])}`)
+ } else if repeated {
+ p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, `, typ, `(dAtA[iNdEx:postIndex]))`)
+ } else if proto3 || !nullable {
+ p.P(`m.`, fieldname, ` = `, typ, `(dAtA[iNdEx:postIndex])`)
+ } else {
+ p.P(`s := `, typ, `(dAtA[iNdEx:postIndex])`)
+ p.P(`m.`, fieldname, ` = &s`)
+ }
+ p.P(`iNdEx = postIndex`)
+ case descriptor.FieldDescriptorProto_TYPE_GROUP:
+ panic(fmt.Errorf("unmarshaler does not support group %v", fieldname))
+ case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
+ desc := p.ObjectNamed(field.GetTypeName())
+ msgname := p.TypeName(desc)
+ p.P(`var msglen int`)
+ p.decodeVarint("msglen", "int")
+ p.P(`if msglen < 0 {`)
+ p.In()
+ p.P(`return ErrInvalidLength` + p.localName)
+ p.Out()
+ p.P(`}`)
+ p.P(`postIndex := iNdEx + msglen`)
+ p.P(`if postIndex < 0 {`)
+ p.In()
+ p.P(`return ErrInvalidLength` + p.localName)
+ p.Out()
+ p.P(`}`)
+ p.P(`if postIndex > l {`)
+ p.In()
+ p.P(`return `, p.ioPkg.Use(), `.ErrUnexpectedEOF`)
+ p.Out()
+ p.P(`}`)
+ if oneof {
+ buf := `dAtA[iNdEx:postIndex]`
+ if gogoproto.IsStdTime(field) {
+ if nullable {
+ p.P(`v := new(time.Time)`)
+ p.P(`if err := `, p.typesPkg.Use(), `.StdTimeUnmarshal(v, `, buf, `); err != nil {`)
+ } else {
+ p.P(`v := time.Time{}`)
+ p.P(`if err := `, p.typesPkg.Use(), `.StdTimeUnmarshal(&v, `, buf, `); err != nil {`)
+ }
+ } else if gogoproto.IsStdDuration(field) {
+ if nullable {
+ p.P(`v := new(time.Duration)`)
+ p.P(`if err := `, p.typesPkg.Use(), `.StdDurationUnmarshal(v, `, buf, `); err != nil {`)
+ } else {
+ p.P(`v := time.Duration(0)`)
+ p.P(`if err := `, p.typesPkg.Use(), `.StdDurationUnmarshal(&v, `, buf, `); err != nil {`)
+ }
+ } else if gogoproto.IsStdDouble(field) {
+ if nullable {
+ p.P(`v := new(float64)`)
+ p.P(`if err := `, p.typesPkg.Use(), `.StdDoubleUnmarshal(v, `, buf, `); err != nil {`)
+ } else {
+ p.P(`v := 0`)
+ p.P(`if err := `, p.typesPkg.Use(), `.StdDoubleUnmarshal(&v, `, buf, `); err != nil {`)
+ }
+ } else if gogoproto.IsStdFloat(field) {
+ if nullable {
+ p.P(`v := new(float32)`)
+ p.P(`if err := `, p.typesPkg.Use(), `.StdFloatUnmarshal(v, `, buf, `); err != nil {`)
+ } else {
+ p.P(`v := 0`)
+ p.P(`if err := `, p.typesPkg.Use(), `.StdFloatUnmarshal(&v, `, buf, `); err != nil {`)
+ }
+ } else if gogoproto.IsStdInt64(field) {
+ if nullable {
+ p.P(`v := new(int64)`)
+ p.P(`if err := `, p.typesPkg.Use(), `.StdInt64Unmarshal(v, `, buf, `); err != nil {`)
+ } else {
+ p.P(`v := 0`)
+ p.P(`if err := `, p.typesPkg.Use(), `.StdInt64Unmarshal(&v, `, buf, `); err != nil {`)
+ }
+ } else if gogoproto.IsStdUInt64(field) {
+ if nullable {
+ p.P(`v := new(uint64)`)
+ p.P(`if err := `, p.typesPkg.Use(), `.StdUInt64Unmarshal(v, `, buf, `); err != nil {`)
+ } else {
+ p.P(`v := 0`)
+ p.P(`if err := `, p.typesPkg.Use(), `.StdUInt64Unmarshal(&v, `, buf, `); err != nil {`)
+ }
+ } else if gogoproto.IsStdInt32(field) {
+ if nullable {
+ p.P(`v := new(int32)`)
+ p.P(`if err := `, p.typesPkg.Use(), `.StdInt32Unmarshal(v, `, buf, `); err != nil {`)
+ } else {
+ p.P(`v := 0`)
+ p.P(`if err := `, p.typesPkg.Use(), `.StdInt32Unmarshal(&v, `, buf, `); err != nil {`)
+ }
+ } else if gogoproto.IsStdUInt32(field) {
+ if nullable {
+ p.P(`v := new(uint32)`)
+ p.P(`if err := `, p.typesPkg.Use(), `.StdUInt32Unmarshal(v, `, buf, `); err != nil {`)
+ } else {
+ p.P(`v := 0`)
+ p.P(`if err := `, p.typesPkg.Use(), `.StdUInt32Unmarshal(&v, `, buf, `); err != nil {`)
+ }
+ } else if gogoproto.IsStdBool(field) {
+ if nullable {
+ p.P(`v := new(bool)`)
+ p.P(`if err := `, p.typesPkg.Use(), `.StdBoolUnmarshal(v, `, buf, `); err != nil {`)
+ } else {
+ p.P(`v := false`)
+ p.P(`if err := `, p.typesPkg.Use(), `.StdBoolUnmarshal(&v, `, buf, `); err != nil {`)
+ }
+ } else if gogoproto.IsStdString(field) {
+ if nullable {
+ p.P(`v := new(string)`)
+ p.P(`if err := `, p.typesPkg.Use(), `.StdStringUnmarshal(v, `, buf, `); err != nil {`)
+ } else {
+ p.P(`v := ""`)
+ p.P(`if err := `, p.typesPkg.Use(), `.StdStringUnmarshal(&v, `, buf, `); err != nil {`)
+ }
+ } else if gogoproto.IsStdBytes(field) {
+ if nullable {
+ p.P(`v := new([]byte)`)
+ p.P(`if err := `, p.typesPkg.Use(), `.StdBytesUnmarshal(v, `, buf, `); err != nil {`)
+ } else {
+ p.P(`var v []byte`)
+ p.P(`if err := `, p.typesPkg.Use(), `.StdBytesUnmarshal(&v, `, buf, `); err != nil {`)
+ }
+ } else {
+ p.P(`v := &`, msgname, `{}`)
+ p.P(`if err := v.Unmarshal(`, buf, `); err != nil {`)
+ }
+ p.In()
+ p.P(`return err`)
+ p.Out()
+ p.P(`}`)
+ p.P(`m.`, fieldname, ` = &`, p.OneOfTypeName(msg, field), `{v}`)
+ } else if p.IsMap(field) {
+ m := p.GoMapType(nil, field)
+
+ keygoTyp, _ := p.GoType(nil, m.KeyField)
+ keygoAliasTyp, _ := p.GoType(nil, m.KeyAliasField)
+ // keys may not be pointers
+ keygoTyp = strings.Replace(keygoTyp, "*", "", 1)
+ keygoAliasTyp = strings.Replace(keygoAliasTyp, "*", "", 1)
+
+ valuegoTyp, _ := p.GoType(nil, m.ValueField)
+ valuegoAliasTyp, _ := p.GoType(nil, m.ValueAliasField)
+
+ // if the map type is an alias and key or values are aliases (type Foo map[Bar]Baz),
+ // we need to explicitly record their use here.
+ if gogoproto.IsCastKey(field) {
+ p.RecordTypeUse(m.KeyAliasField.GetTypeName())
+ }
+ if gogoproto.IsCastValue(field) {
+ p.RecordTypeUse(m.ValueAliasField.GetTypeName())
+ }
+
+ nullable, valuegoTyp, valuegoAliasTyp = generator.GoMapValueTypes(field, m.ValueField, valuegoTyp, valuegoAliasTyp)
+ if gogoproto.IsStdType(field) {
+ valuegoTyp = valuegoAliasTyp
+ }
+
+ p.P(`if m.`, fieldname, ` == nil {`)
+ p.In()
+ p.P(`m.`, fieldname, ` = make(`, m.GoType, `)`)
+ p.Out()
+ p.P(`}`)
+
+ p.declareMapField("mapkey", false, false, m.KeyAliasField)
+ p.declareMapField("mapvalue", nullable, gogoproto.IsCustomType(field), m.ValueAliasField)
+ p.P(`for iNdEx < postIndex {`)
+ p.In()
+
+ p.P(`entryPreIndex := iNdEx`)
+ p.P(`var wire uint64`)
+ p.decodeVarint("wire", "uint64")
+ p.P(`fieldNum := int32(wire >> 3)`)
+
+ p.P(`if fieldNum == 1 {`)
+ p.In()
+ p.mapField("mapkey", false, m.KeyAliasField)
+ p.Out()
+ p.P(`} else if fieldNum == 2 {`)
+ p.In()
+ p.mapField("mapvalue", gogoproto.IsCustomType(field), m.ValueAliasField)
+ p.Out()
+ p.P(`} else {`)
+ p.In()
+ p.P(`iNdEx = entryPreIndex`)
+ p.P(`skippy, err := skip`, p.localName, `(dAtA[iNdEx:])`)
+ p.P(`if err != nil {`)
+ p.In()
+ p.P(`return err`)
+ p.Out()
+ p.P(`}`)
+ p.P(`if (skippy < 0) || (iNdEx + skippy) < 0 {`)
+ p.In()
+ p.P(`return ErrInvalidLength`, p.localName)
+ p.Out()
+ p.P(`}`)
+ p.P(`if (iNdEx + skippy) > postIndex {`)
+ p.In()
+ p.P(`return `, p.ioPkg.Use(), `.ErrUnexpectedEOF`)
+ p.Out()
+ p.P(`}`)
+ p.P(`iNdEx += skippy`)
+ p.Out()
+ p.P(`}`)
+
+ p.Out()
+ p.P(`}`)
+
+ s := `m.` + fieldname
+ if keygoTyp == keygoAliasTyp {
+ s += `[mapkey]`
+ } else {
+ s += `[` + keygoAliasTyp + `(mapkey)]`
+ }
+
+ v := `mapvalue`
+ if (m.ValueField.IsMessage() || gogoproto.IsCustomType(field)) && !nullable {
+ v = `*` + v
+ }
+ if valuegoTyp != valuegoAliasTyp {
+ v = `((` + valuegoAliasTyp + `)(` + v + `))`
+ }
+
+ p.P(s, ` = `, v)
+ } else if repeated {
+ if gogoproto.IsStdTime(field) {
+ if nullable {
+ p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, new(time.Time))`)
+ } else {
+ p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, time.Time{})`)
+ }
+ } else if gogoproto.IsStdDuration(field) {
+ if nullable {
+ p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, new(time.Duration))`)
+ } else {
+ p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, time.Duration(0))`)
+ }
+ } else if gogoproto.IsStdDouble(field) {
+ if nullable {
+ p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, new(float64))`)
+ } else {
+ p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, 0)`)
+ }
+ } else if gogoproto.IsStdFloat(field) {
+ if nullable {
+ p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, new(float32))`)
+ } else {
+ p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, 0)`)
+ }
+ } else if gogoproto.IsStdInt64(field) {
+ if nullable {
+ p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, new(int64))`)
+ } else {
+ p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, 0)`)
+ }
+ } else if gogoproto.IsStdUInt64(field) {
+ if nullable {
+ p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, new(uint64))`)
+ } else {
+ p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, 0)`)
+ }
+ } else if gogoproto.IsStdInt32(field) {
+ if nullable {
+ p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, new(int32))`)
+ } else {
+ p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, 0)`)
+ }
+ } else if gogoproto.IsStdUInt32(field) {
+ if nullable {
+ p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, new(uint32))`)
+ } else {
+ p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, 0)`)
+ }
+ } else if gogoproto.IsStdBool(field) {
+ if nullable {
+ p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, new(bool))`)
+ } else {
+ p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, false)`)
+ }
+ } else if gogoproto.IsStdString(field) {
+ if nullable {
+ p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, new(string))`)
+ } else {
+ p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, "")`)
+ }
+ } else if gogoproto.IsStdBytes(field) {
+ if nullable {
+ p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, new([]byte))`)
+ } else {
+ p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, []byte{})`)
+ }
+ } else if nullable && !gogoproto.IsCustomType(field) {
+ p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, &`, msgname, `{})`)
+ } else {
+ goType, _ := p.GoType(nil, field)
+ // remove the slice from the type, i.e. []*T -> *T
+ goType = goType[2:]
+ p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, `, goType, `{})`)
+ }
+ varName := `m.` + fieldname + `[len(m.` + fieldname + `)-1]`
+ buf := `dAtA[iNdEx:postIndex]`
+ if gogoproto.IsStdTime(field) {
+ if nullable {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdTimeUnmarshal(`, varName, `,`, buf, `); err != nil {`)
+ } else {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdTimeUnmarshal(&(`, varName, `),`, buf, `); err != nil {`)
+ }
+ } else if gogoproto.IsStdDuration(field) {
+ if nullable {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdDurationUnmarshal(`, varName, `,`, buf, `); err != nil {`)
+ } else {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdDurationUnmarshal(&(`, varName, `),`, buf, `); err != nil {`)
+ }
+ } else if gogoproto.IsStdDouble(field) {
+ if nullable {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdDoubleUnmarshal(`, varName, `,`, buf, `); err != nil {`)
+ } else {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdDoubleUnmarshal(&(`, varName, `),`, buf, `); err != nil {`)
+ }
+ } else if gogoproto.IsStdFloat(field) {
+ if nullable {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdFloatUnmarshal(`, varName, `,`, buf, `); err != nil {`)
+ } else {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdFloatUnmarshal(&(`, varName, `),`, buf, `); err != nil {`)
+ }
+ } else if gogoproto.IsStdInt64(field) {
+ if nullable {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdInt64Unmarshal(`, varName, `,`, buf, `); err != nil {`)
+ } else {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdInt64Unmarshal(&(`, varName, `),`, buf, `); err != nil {`)
+ }
+ } else if gogoproto.IsStdUInt64(field) {
+ if nullable {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdUInt64Unmarshal(`, varName, `,`, buf, `); err != nil {`)
+ } else {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdUInt64Unmarshal(&(`, varName, `),`, buf, `); err != nil {`)
+ }
+ } else if gogoproto.IsStdInt32(field) {
+ if nullable {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdInt32Unmarshal(`, varName, `,`, buf, `); err != nil {`)
+ } else {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdInt32Unmarshal(&(`, varName, `),`, buf, `); err != nil {`)
+ }
+ } else if gogoproto.IsStdUInt32(field) {
+ if nullable {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdUInt32Unmarshal(`, varName, `,`, buf, `); err != nil {`)
+ } else {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdUInt32Unmarshal(&(`, varName, `),`, buf, `); err != nil {`)
+ }
+ } else if gogoproto.IsStdBool(field) {
+ if nullable {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdBoolUnmarshal(`, varName, `,`, buf, `); err != nil {`)
+ } else {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdBoolUnmarshal(&(`, varName, `),`, buf, `); err != nil {`)
+ }
+ } else if gogoproto.IsStdString(field) {
+ if nullable {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdStringUnmarshal(`, varName, `,`, buf, `); err != nil {`)
+ } else {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdStringUnmarshal(&(`, varName, `),`, buf, `); err != nil {`)
+ }
+ } else if gogoproto.IsStdBytes(field) {
+ if nullable {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdBytesUnmarshal(`, varName, `,`, buf, `); err != nil {`)
+ } else {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdBytesUnmarshal(&(`, varName, `),`, buf, `); err != nil {`)
+ }
+ } else {
+ p.P(`if err := `, varName, `.Unmarshal(`, buf, `); err != nil {`)
+ }
+ p.In()
+ p.P(`return err`)
+ p.Out()
+ p.P(`}`)
+ } else if nullable {
+ p.P(`if m.`, fieldname, ` == nil {`)
+ p.In()
+ if gogoproto.IsStdTime(field) {
+ p.P(`m.`, fieldname, ` = new(time.Time)`)
+ } else if gogoproto.IsStdDuration(field) {
+ p.P(`m.`, fieldname, ` = new(time.Duration)`)
+ } else if gogoproto.IsStdDouble(field) {
+ p.P(`m.`, fieldname, ` = new(float64)`)
+ } else if gogoproto.IsStdFloat(field) {
+ p.P(`m.`, fieldname, ` = new(float32)`)
+ } else if gogoproto.IsStdInt64(field) {
+ p.P(`m.`, fieldname, ` = new(int64)`)
+ } else if gogoproto.IsStdUInt64(field) {
+ p.P(`m.`, fieldname, ` = new(uint64)`)
+ } else if gogoproto.IsStdInt32(field) {
+ p.P(`m.`, fieldname, ` = new(int32)`)
+ } else if gogoproto.IsStdUInt32(field) {
+ p.P(`m.`, fieldname, ` = new(uint32)`)
+ } else if gogoproto.IsStdBool(field) {
+ p.P(`m.`, fieldname, ` = new(bool)`)
+ } else if gogoproto.IsStdString(field) {
+ p.P(`m.`, fieldname, ` = new(string)`)
+ } else if gogoproto.IsStdBytes(field) {
+ p.P(`m.`, fieldname, ` = new([]byte)`)
+ } else {
+ goType, _ := p.GoType(nil, field)
+ // remove the star from the type
+ p.P(`m.`, fieldname, ` = &`, goType[1:], `{}`)
+ }
+ p.Out()
+ p.P(`}`)
+ if gogoproto.IsStdTime(field) {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdTimeUnmarshal(m.`, fieldname, `, dAtA[iNdEx:postIndex]); err != nil {`)
+ } else if gogoproto.IsStdDuration(field) {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdDurationUnmarshal(m.`, fieldname, `, dAtA[iNdEx:postIndex]); err != nil {`)
+ } else if gogoproto.IsStdDouble(field) {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdDoubleUnmarshal(m.`, fieldname, `, dAtA[iNdEx:postIndex]); err != nil {`)
+ } else if gogoproto.IsStdFloat(field) {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdFloatUnmarshal(m.`, fieldname, `, dAtA[iNdEx:postIndex]); err != nil {`)
+ } else if gogoproto.IsStdInt64(field) {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdInt64Unmarshal(m.`, fieldname, `, dAtA[iNdEx:postIndex]); err != nil {`)
+ } else if gogoproto.IsStdUInt64(field) {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdUInt64Unmarshal(m.`, fieldname, `, dAtA[iNdEx:postIndex]); err != nil {`)
+ } else if gogoproto.IsStdInt32(field) {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdInt32Unmarshal(m.`, fieldname, `, dAtA[iNdEx:postIndex]); err != nil {`)
+ } else if gogoproto.IsStdUInt32(field) {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdUInt32Unmarshal(m.`, fieldname, `, dAtA[iNdEx:postIndex]); err != nil {`)
+ } else if gogoproto.IsStdBool(field) {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdBoolUnmarshal(m.`, fieldname, `, dAtA[iNdEx:postIndex]); err != nil {`)
+ } else if gogoproto.IsStdString(field) {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdStringUnmarshal(m.`, fieldname, `, dAtA[iNdEx:postIndex]); err != nil {`)
+ } else if gogoproto.IsStdBytes(field) {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdBytesUnmarshal(m.`, fieldname, `, dAtA[iNdEx:postIndex]); err != nil {`)
+ } else {
+ p.P(`if err := m.`, fieldname, `.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {`)
+ }
+ p.In()
+ p.P(`return err`)
+ p.Out()
+ p.P(`}`)
+ } else {
+ if gogoproto.IsStdTime(field) {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdTimeUnmarshal(&m.`, fieldname, `, dAtA[iNdEx:postIndex]); err != nil {`)
+ } else if gogoproto.IsStdDuration(field) {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdDurationUnmarshal(&m.`, fieldname, `, dAtA[iNdEx:postIndex]); err != nil {`)
+ } else if gogoproto.IsStdDouble(field) {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdDoubleUnmarshal(&m.`, fieldname, `, dAtA[iNdEx:postIndex]); err != nil {`)
+ } else if gogoproto.IsStdFloat(field) {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdFloatUnmarshal(&m.`, fieldname, `, dAtA[iNdEx:postIndex]); err != nil {`)
+ } else if gogoproto.IsStdInt64(field) {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdInt64Unmarshal(&m.`, fieldname, `, dAtA[iNdEx:postIndex]); err != nil {`)
+ } else if gogoproto.IsStdUInt64(field) {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdUInt64Unmarshal(&m.`, fieldname, `, dAtA[iNdEx:postIndex]); err != nil {`)
+ } else if gogoproto.IsStdInt32(field) {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdInt32Unmarshal(&m.`, fieldname, `, dAtA[iNdEx:postIndex]); err != nil {`)
+ } else if gogoproto.IsStdUInt32(field) {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdUInt32Unmarshal(&m.`, fieldname, `, dAtA[iNdEx:postIndex]); err != nil {`)
+ } else if gogoproto.IsStdBool(field) {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdBoolUnmarshal(&m.`, fieldname, `, dAtA[iNdEx:postIndex]); err != nil {`)
+ } else if gogoproto.IsStdString(field) {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdStringUnmarshal(&m.`, fieldname, `, dAtA[iNdEx:postIndex]); err != nil {`)
+ } else if gogoproto.IsStdBytes(field) {
+ p.P(`if err := `, p.typesPkg.Use(), `.StdBytesUnmarshal(&m.`, fieldname, `, dAtA[iNdEx:postIndex]); err != nil {`)
+ } else {
+ p.P(`if err := m.`, fieldname, `.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {`)
+ }
+ p.In()
+ p.P(`return err`)
+ p.Out()
+ p.P(`}`)
+ }
+ p.P(`iNdEx = postIndex`)
+
+ case descriptor.FieldDescriptorProto_TYPE_BYTES:
+ p.P(`var byteLen int`)
+ p.decodeVarint("byteLen", "int")
+ p.P(`if byteLen < 0 {`)
+ p.In()
+ p.P(`return ErrInvalidLength` + p.localName)
+ p.Out()
+ p.P(`}`)
+ p.P(`postIndex := iNdEx + byteLen`)
+ p.P(`if postIndex < 0 {`)
+ p.In()
+ p.P(`return ErrInvalidLength` + p.localName)
+ p.Out()
+ p.P(`}`)
+ p.P(`if postIndex > l {`)
+ p.In()
+ p.P(`return `, p.ioPkg.Use(), `.ErrUnexpectedEOF`)
+ p.Out()
+ p.P(`}`)
+ if !gogoproto.IsCustomType(field) {
+ if oneof {
+ p.P(`v := make([]byte, postIndex-iNdEx)`)
+ p.P(`copy(v, dAtA[iNdEx:postIndex])`)
+ p.P(`m.`, fieldname, ` = &`, p.OneOfTypeName(msg, field), `{v}`)
+ } else if repeated {
+ p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, make([]byte, postIndex-iNdEx))`)
+ p.P(`copy(m.`, fieldname, `[len(m.`, fieldname, `)-1], dAtA[iNdEx:postIndex])`)
+ } else {
+ p.P(`m.`, fieldname, ` = append(m.`, fieldname, `[:0] , dAtA[iNdEx:postIndex]...)`)
+ p.P(`if m.`, fieldname, ` == nil {`)
+ p.In()
+ p.P(`m.`, fieldname, ` = []byte{}`)
+ p.Out()
+ p.P(`}`)
+ }
+ } else {
+ _, ctyp, err := generator.GetCustomType(field)
+ if err != nil {
+ panic(err)
+ }
+ if oneof {
+ p.P(`var vv `, ctyp)
+ p.P(`v := &vv`)
+ p.P(`if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {`)
+ p.In()
+ p.P(`return err`)
+ p.Out()
+ p.P(`}`)
+ p.P(`m.`, fieldname, ` = &`, p.OneOfTypeName(msg, field), `{*v}`)
+ } else if repeated {
+ p.P(`var v `, ctyp)
+ p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, v)`)
+ p.P(`if err := m.`, fieldname, `[len(m.`, fieldname, `)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {`)
+ p.In()
+ p.P(`return err`)
+ p.Out()
+ p.P(`}`)
+ } else if nullable {
+ p.P(`var v `, ctyp)
+ p.P(`m.`, fieldname, ` = &v`)
+ p.P(`if err := m.`, fieldname, `.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {`)
+ p.In()
+ p.P(`return err`)
+ p.Out()
+ p.P(`}`)
+ } else {
+ p.P(`if err := m.`, fieldname, `.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {`)
+ p.In()
+ p.P(`return err`)
+ p.Out()
+ p.P(`}`)
+ }
+ }
+ p.P(`iNdEx = postIndex`)
+ case descriptor.FieldDescriptorProto_TYPE_UINT32:
+ if oneof {
+ p.P(`var v `, typ)
+ p.decodeVarint("v", typ)
+ p.P(`m.`, fieldname, ` = &`, p.OneOfTypeName(msg, field), `{v}`)
+ } else if repeated {
+ p.P(`var v `, typ)
+ p.decodeVarint("v", typ)
+ p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, v)`)
+ } else if proto3 || !nullable {
+ p.P(`m.`, fieldname, ` = 0`)
+ p.decodeVarint("m."+fieldname, typ)
+ } else {
+ p.P(`var v `, typ)
+ p.decodeVarint("v", typ)
+ p.P(`m.`, fieldname, ` = &v`)
+ }
+ case descriptor.FieldDescriptorProto_TYPE_ENUM:
+ typName := p.TypeName(p.ObjectNamed(field.GetTypeName()))
+ if oneof {
+ p.P(`var v `, typName)
+ p.decodeVarint("v", typName)
+ p.P(`m.`, fieldname, ` = &`, p.OneOfTypeName(msg, field), `{v}`)
+ } else if repeated {
+ p.P(`var v `, typName)
+ p.decodeVarint("v", typName)
+ p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, v)`)
+ } else if proto3 || !nullable {
+ p.P(`m.`, fieldname, ` = 0`)
+ p.decodeVarint("m."+fieldname, typName)
+ } else {
+ p.P(`var v `, typName)
+ p.decodeVarint("v", typName)
+ p.P(`m.`, fieldname, ` = &v`)
+ }
+ case descriptor.FieldDescriptorProto_TYPE_SFIXED32:
+ if oneof {
+ p.P(`var v `, typ)
+ p.decodeFixed32("v", typ)
+ p.P(`m.`, fieldname, ` = &`, p.OneOfTypeName(msg, field), `{v}`)
+ } else if repeated {
+ p.P(`var v `, typ)
+ p.decodeFixed32("v", typ)
+ p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, v)`)
+ } else if proto3 || !nullable {
+ p.P(`m.`, fieldname, ` = 0`)
+ p.decodeFixed32("m."+fieldname, typ)
+ } else {
+ p.P(`var v `, typ)
+ p.decodeFixed32("v", typ)
+ p.P(`m.`, fieldname, ` = &v`)
+ }
+ case descriptor.FieldDescriptorProto_TYPE_SFIXED64:
+ if oneof {
+ p.P(`var v `, typ)
+ p.decodeFixed64("v", typ)
+ p.P(`m.`, fieldname, ` = &`, p.OneOfTypeName(msg, field), `{v}`)
+ } else if repeated {
+ p.P(`var v `, typ)
+ p.decodeFixed64("v", typ)
+ p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, v)`)
+ } else if proto3 || !nullable {
+ p.P(`m.`, fieldname, ` = 0`)
+ p.decodeFixed64("m."+fieldname, typ)
+ } else {
+ p.P(`var v `, typ)
+ p.decodeFixed64("v", typ)
+ p.P(`m.`, fieldname, ` = &v`)
+ }
+ case descriptor.FieldDescriptorProto_TYPE_SINT32:
+ p.P(`var v `, typ)
+ p.decodeVarint("v", typ)
+ p.P(`v = `, typ, `((uint32(v) >> 1) ^ uint32(((v&1)<<31)>>31))`)
+ if oneof {
+ p.P(`m.`, fieldname, ` = &`, p.OneOfTypeName(msg, field), `{v}`)
+ } else if repeated {
+ p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, v)`)
+ } else if proto3 || !nullable {
+ p.P(`m.`, fieldname, ` = v`)
+ } else {
+ p.P(`m.`, fieldname, ` = &v`)
+ }
+ case descriptor.FieldDescriptorProto_TYPE_SINT64:
+ p.P(`var v uint64`)
+ p.decodeVarint("v", "uint64")
+ p.P(`v = (v >> 1) ^ uint64((int64(v&1)<<63)>>63)`)
+ if oneof {
+ p.P(`m.`, fieldname, ` = &`, p.OneOfTypeName(msg, field), `{`, typ, `(v)}`)
+ } else if repeated {
+ p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, `, typ, `(v))`)
+ } else if proto3 || !nullable {
+ p.P(`m.`, fieldname, ` = `, typ, `(v)`)
+ } else {
+ p.P(`v2 := `, typ, `(v)`)
+ p.P(`m.`, fieldname, ` = &v2`)
+ }
+ default:
+ panic("not implemented")
+ }
+}
+
+func (p *unmarshal) Generate(file *generator.FileDescriptor) {
+ proto3 := gogoproto.IsProto3(file.FileDescriptorProto)
+ p.PluginImports = generator.NewPluginImports(p.Generator)
+ p.atleastOne = false
+ p.localName = generator.FileName(file)
+
+ p.ioPkg = p.NewImport("io")
+ p.mathPkg = p.NewImport("math")
+ p.typesPkg = p.NewImport("github.com/gogo/protobuf/types")
+ p.binaryPkg = p.NewImport("encoding/binary")
+ fmtPkg := p.NewImport("fmt")
+ protoPkg := p.NewImport("github.com/gogo/protobuf/proto")
+ if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
+ protoPkg = p.NewImport("github.com/golang/protobuf/proto")
+ }
+
+ for _, message := range file.Messages() {
+ ccTypeName := generator.CamelCaseSlice(message.TypeName())
+ if !gogoproto.IsUnmarshaler(file.FileDescriptorProto, message.DescriptorProto) &&
+ !gogoproto.IsUnsafeUnmarshaler(file.FileDescriptorProto, message.DescriptorProto) {
+ continue
+ }
+ if message.DescriptorProto.GetOptions().GetMapEntry() {
+ continue
+ }
+ p.atleastOne = true
+
+ // build a map required field_id -> bitmask offset
+ rfMap := make(map[int32]uint)
+ rfNextId := uint(0)
+ for _, field := range message.Field {
+ if field.IsRequired() {
+ rfMap[field.GetNumber()] = rfNextId
+ rfNextId++
+ }
+ }
+ rfCount := len(rfMap)
+
+ p.P(`func (m *`, ccTypeName, `) Unmarshal(dAtA []byte) error {`)
+ p.In()
+ if rfCount > 0 {
+ p.P(`var hasFields [`, strconv.Itoa(1+(rfCount-1)/64), `]uint64`)
+ }
+ p.P(`l := len(dAtA)`)
+ p.P(`iNdEx := 0`)
+ p.P(`for iNdEx < l {`)
+ p.In()
+ p.P(`preIndex := iNdEx`)
+ p.P(`var wire uint64`)
+ p.decodeVarint("wire", "uint64")
+ p.P(`fieldNum := int32(wire >> 3)`)
+ if len(message.Field) > 0 || !message.IsGroup() {
+ p.P(`wireType := int(wire & 0x7)`)
+ }
+ if !message.IsGroup() {
+ p.P(`if wireType == `, strconv.Itoa(proto.WireEndGroup), ` {`)
+ p.In()
+ p.P(`return `, fmtPkg.Use(), `.Errorf("proto: `+message.GetName()+`: wiretype end group for non-group")`)
+ p.Out()
+ p.P(`}`)
+ }
+ p.P(`if fieldNum <= 0 {`)
+ p.In()
+ p.P(`return `, fmtPkg.Use(), `.Errorf("proto: `+message.GetName()+`: illegal tag %d (wire type %d)", fieldNum, wire)`)
+ p.Out()
+ p.P(`}`)
+ p.P(`switch fieldNum {`)
+ p.In()
+ for _, field := range message.Field {
+ fieldname := p.GetFieldName(message, field)
+ errFieldname := fieldname
+ if field.OneofIndex != nil {
+ errFieldname = p.GetOneOfFieldName(message, field)
+ }
+ possiblyPacked := field.IsScalar() && field.IsRepeated()
+ p.P(`case `, strconv.Itoa(int(field.GetNumber())), `:`)
+ p.In()
+ wireType := field.WireType()
+ if possiblyPacked {
+ p.P(`if wireType == `, strconv.Itoa(wireType), `{`)
+ p.In()
+ p.field(file, message, field, fieldname, false)
+ p.Out()
+ p.P(`} else if wireType == `, strconv.Itoa(proto.WireBytes), `{`)
+ p.In()
+ p.P(`var packedLen int`)
+ p.decodeVarint("packedLen", "int")
+ p.P(`if packedLen < 0 {`)
+ p.In()
+ p.P(`return ErrInvalidLength` + p.localName)
+ p.Out()
+ p.P(`}`)
+ p.P(`postIndex := iNdEx + packedLen`)
+ p.P(`if postIndex < 0 {`)
+ p.In()
+ p.P(`return ErrInvalidLength` + p.localName)
+ p.Out()
+ p.P(`}`)
+ p.P(`if postIndex > l {`)
+ p.In()
+ p.P(`return `, p.ioPkg.Use(), `.ErrUnexpectedEOF`)
+ p.Out()
+ p.P(`}`)
+
+ p.P(`var elementCount int`)
+ switch *field.Type {
+ case descriptor.FieldDescriptorProto_TYPE_DOUBLE, descriptor.FieldDescriptorProto_TYPE_FIXED64, descriptor.FieldDescriptorProto_TYPE_SFIXED64:
+ p.P(`elementCount = packedLen/`, 8)
+ case descriptor.FieldDescriptorProto_TYPE_FLOAT, descriptor.FieldDescriptorProto_TYPE_FIXED32, descriptor.FieldDescriptorProto_TYPE_SFIXED32:
+ p.P(`elementCount = packedLen/`, 4)
+ case descriptor.FieldDescriptorProto_TYPE_INT64, descriptor.FieldDescriptorProto_TYPE_UINT64, descriptor.FieldDescriptorProto_TYPE_INT32, descriptor.FieldDescriptorProto_TYPE_UINT32, descriptor.FieldDescriptorProto_TYPE_SINT32, descriptor.FieldDescriptorProto_TYPE_SINT64:
+ p.P(`var count int`)
+ p.P(`for _, integer := range dAtA[iNdEx:postIndex] {`)
+ p.In()
+ p.P(`if integer < 128 {`)
+ p.In()
+ p.P(`count++`)
+ p.Out()
+ p.P(`}`)
+ p.Out()
+ p.P(`}`)
+ p.P(`elementCount = count`)
+ case descriptor.FieldDescriptorProto_TYPE_BOOL:
+ p.P(`elementCount = packedLen`)
+ }
+ p.P(`if elementCount != 0 && len(m.`, fieldname, `) == 0 {`)
+ p.In()
+ p.P(`m.`, fieldname, ` = make([]`, p.noStarOrSliceType(message, field), `, 0, elementCount)`)
+ p.Out()
+ p.P(`}`)
+
+ p.P(`for iNdEx < postIndex {`)
+ p.In()
+ p.field(file, message, field, fieldname, false)
+ p.Out()
+ p.P(`}`)
+ p.Out()
+ p.P(`} else {`)
+ p.In()
+ p.P(`return ` + fmtPkg.Use() + `.Errorf("proto: wrong wireType = %d for field ` + errFieldname + `", wireType)`)
+ p.Out()
+ p.P(`}`)
+ } else {
+ p.P(`if wireType != `, strconv.Itoa(wireType), `{`)
+ p.In()
+ p.P(`return ` + fmtPkg.Use() + `.Errorf("proto: wrong wireType = %d for field ` + errFieldname + `", wireType)`)
+ p.Out()
+ p.P(`}`)
+ p.field(file, message, field, fieldname, proto3)
+ }
+
+ if field.IsRequired() {
+ fieldBit, ok := rfMap[field.GetNumber()]
+ if !ok {
+ panic("field is required, but no bit registered")
+ }
+ p.P(`hasFields[`, strconv.Itoa(int(fieldBit/64)), `] |= uint64(`, fmt.Sprintf("0x%08x", uint64(1)<<(fieldBit%64)), `)`)
+ }
+ }
+ p.Out()
+ p.P(`default:`)
+ p.In()
+ if message.DescriptorProto.HasExtension() {
+ c := []string{}
+ for _, erange := range message.GetExtensionRange() {
+ c = append(c, `((fieldNum >= `+strconv.Itoa(int(erange.GetStart()))+") && (fieldNum<"+strconv.Itoa(int(erange.GetEnd()))+`))`)
+ }
+ p.P(`if `, strings.Join(c, "||"), `{`)
+ p.In()
+ p.P(`var sizeOfWire int`)
+ p.P(`for {`)
+ p.In()
+ p.P(`sizeOfWire++`)
+ p.P(`wire >>= 7`)
+ p.P(`if wire == 0 {`)
+ p.In()
+ p.P(`break`)
+ p.Out()
+ p.P(`}`)
+ p.Out()
+ p.P(`}`)
+ p.P(`iNdEx-=sizeOfWire`)
+ p.P(`skippy, err := skip`, p.localName+`(dAtA[iNdEx:])`)
+ p.P(`if err != nil {`)
+ p.In()
+ p.P(`return err`)
+ p.Out()
+ p.P(`}`)
+ p.P(`if (skippy < 0) || (iNdEx + skippy) < 0 {`)
+ p.In()
+ p.P(`return ErrInvalidLength`, p.localName)
+ p.Out()
+ p.P(`}`)
+ p.P(`if (iNdEx + skippy) > l {`)
+ p.In()
+ p.P(`return `, p.ioPkg.Use(), `.ErrUnexpectedEOF`)
+ p.Out()
+ p.P(`}`)
+ p.P(protoPkg.Use(), `.AppendExtension(m, int32(fieldNum), dAtA[iNdEx:iNdEx+skippy])`)
+ p.P(`iNdEx += skippy`)
+ p.Out()
+ p.P(`} else {`)
+ p.In()
+ }
+ p.P(`iNdEx=preIndex`)
+ p.P(`skippy, err := skip`, p.localName, `(dAtA[iNdEx:])`)
+ p.P(`if err != nil {`)
+ p.In()
+ p.P(`return err`)
+ p.Out()
+ p.P(`}`)
+ p.P(`if (skippy < 0) || (iNdEx + skippy) < 0 {`)
+ p.In()
+ p.P(`return ErrInvalidLength`, p.localName)
+ p.Out()
+ p.P(`}`)
+ p.P(`if (iNdEx + skippy) > l {`)
+ p.In()
+ p.P(`return `, p.ioPkg.Use(), `.ErrUnexpectedEOF`)
+ p.Out()
+ p.P(`}`)
+ if gogoproto.HasUnrecognized(file.FileDescriptorProto, message.DescriptorProto) {
+ p.P(`m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)`)
+ }
+ p.P(`iNdEx += skippy`)
+ p.Out()
+ if message.DescriptorProto.HasExtension() {
+ p.Out()
+ p.P(`}`)
+ }
+ p.Out()
+ p.P(`}`)
+ p.Out()
+ p.P(`}`)
+
+ for _, field := range message.Field {
+ if !field.IsRequired() {
+ continue
+ }
+
+ fieldBit, ok := rfMap[field.GetNumber()]
+ if !ok {
+ panic("field is required, but no bit registered")
+ }
+
+ p.P(`if hasFields[`, strconv.Itoa(int(fieldBit/64)), `] & uint64(`, fmt.Sprintf("0x%08x", uint64(1)<<(fieldBit%64)), `) == 0 {`)
+ p.In()
+ if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
+ p.P(`return new(`, protoPkg.Use(), `.RequiredNotSetError)`)
+ } else {
+ p.P(`return `, protoPkg.Use(), `.NewRequiredNotSetError("`, field.GetName(), `")`)
+ }
+ p.Out()
+ p.P(`}`)
+ }
+ p.P()
+ p.P(`if iNdEx > l {`)
+ p.In()
+ p.P(`return ` + p.ioPkg.Use() + `.ErrUnexpectedEOF`)
+ p.Out()
+ p.P(`}`)
+ p.P(`return nil`)
+ p.Out()
+ p.P(`}`)
+ }
+ if !p.atleastOne {
+ return
+ }
+
+ p.P(`func skip` + p.localName + `(dAtA []byte) (n int, err error) {
+ l := len(dAtA)
+ iNdEx := 0
+ depth := 0
+ for iNdEx < l {
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflow` + p.localName + `
+ }
+ if iNdEx >= l {
+ return 0, ` + p.ioPkg.Use() + `.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ wireType := int(wire & 0x7)
+ switch wireType {
+ case 0:
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflow` + p.localName + `
+ }
+ if iNdEx >= l {
+ return 0, ` + p.ioPkg.Use() + `.ErrUnexpectedEOF
+ }
+ iNdEx++
+ if dAtA[iNdEx-1] < 0x80 {
+ break
+ }
+ }
+ case 1:
+ iNdEx += 8
+ case 2:
+ var length int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflow` + p.localName + `
+ }
+ if iNdEx >= l {
+ return 0, ` + p.ioPkg.Use() + `.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ length |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if length < 0 {
+ return 0, ErrInvalidLength` + p.localName + `
+ }
+ iNdEx += length
+ case 3:
+ depth++
+ case 4:
+ if depth == 0 {
+ return 0, ErrUnexpectedEndOfGroup` + p.localName + `
+ }
+ depth--
+ case 5:
+ iNdEx += 4
+ default:
+ return 0, ` + fmtPkg.Use() + `.Errorf("proto: illegal wireType %d", wireType)
+ }
+ if iNdEx < 0 {
+ return 0, ErrInvalidLength` + p.localName + `
+ }
+ if depth == 0 {
+ return iNdEx, nil
+ }
+ }
+ return 0, ` + p.ioPkg.Use() + `.ErrUnexpectedEOF
+ }
+
+ var (
+ ErrInvalidLength` + p.localName + ` = ` + fmtPkg.Use() + `.Errorf("proto: negative length found during unmarshaling")
+ ErrIntOverflow` + p.localName + ` = ` + fmtPkg.Use() + `.Errorf("proto: integer overflow")
+ ErrUnexpectedEndOfGroup` + p.localName + ` = ` + fmtPkg.Use() + `.Errorf("proto: unexpected end of group")
+ )
+ `)
+}
+
+func init() {
+ generator.RegisterPlugin(NewUnmarshal())
+}
diff --git a/vendor/github.com/gogo/protobuf/protoc-gen-gogo/Makefile b/vendor/github.com/gogo/protobuf/protoc-gen-gogo/Makefile
new file mode 100644
index 00000000000..52e2d4e7047
--- /dev/null
+++ b/vendor/github.com/gogo/protobuf/protoc-gen-gogo/Makefile
@@ -0,0 +1,41 @@
+# Go support for Protocol Buffers - Google's data interchange format
+#
+# Copyright 2010 The Go Authors. All rights reserved.
+# https://github.com/golang/protobuf
+#
+# 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.
+
+all: test
+
+test:
+ go test
+ make -C testdata test
+
+regenerate:
+ go test --regenerate
+ make -C descriptor regenerate
+ make -C plugin regenerate
diff --git a/vendor/github.com/gogo/protobuf/protoc-gen-gogo/doc.go b/vendor/github.com/gogo/protobuf/protoc-gen-gogo/doc.go
new file mode 100644
index 00000000000..15c7cf43c28
--- /dev/null
+++ b/vendor/github.com/gogo/protobuf/protoc-gen-gogo/doc.go
@@ -0,0 +1,51 @@
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2010 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// 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.
+
+/*
+ A plugin for the Google protocol buffer compiler to generate Go code.
+ Run it by building this program and putting it in your path with the name
+ protoc-gen-gogo
+ That word 'gogo' at the end becomes part of the option string set for the
+ protocol compiler, so once the protocol compiler (protoc) is installed
+ you can run
+ protoc --gogo_out=output_directory input_directory/file.proto
+ to generate Go bindings for the protocol defined by file.proto.
+ With that input, the output will be written to
+ output_directory/go_package/file.pb.go
+
+ The generated code is documented in the package comment for
+ the library.
+
+ See the README and documentation for protocol buffers to learn more:
+ https://developers.google.com/protocol-buffers/
+
+*/
+package documentation
diff --git a/vendor/github.com/gogo/protobuf/protoc-gen-gogo/generator/generator.go b/vendor/github.com/gogo/protobuf/protoc-gen-gogo/generator/generator.go
new file mode 100644
index 00000000000..ab07ed61ef0
--- /dev/null
+++ b/vendor/github.com/gogo/protobuf/protoc-gen-gogo/generator/generator.go
@@ -0,0 +1,3444 @@
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2013, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2010 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// 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.
+
+/*
+ The code generator for the plugin for the Google protocol buffer compiler.
+ It generates Go code from the protocol buffer description files read by the
+ main routine.
+*/
+package generator
+
+import (
+ "bufio"
+ "bytes"
+ "compress/gzip"
+ "crypto/sha256"
+ "encoding/hex"
+ "fmt"
+ "go/ast"
+ "go/build"
+ "go/parser"
+ "go/printer"
+ "go/token"
+ "log"
+ "os"
+ "path"
+ "sort"
+ "strconv"
+ "strings"
+ "unicode"
+ "unicode/utf8"
+
+ "github.com/gogo/protobuf/gogoproto"
+ "github.com/gogo/protobuf/proto"
+ descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
+ "github.com/gogo/protobuf/protoc-gen-gogo/generator/internal/remap"
+ plugin "github.com/gogo/protobuf/protoc-gen-gogo/plugin"
+)
+
+// generatedCodeVersion indicates a version of the generated code.
+// It is incremented whenever an incompatibility between the generated code and
+// proto package is introduced; the generated code references
+// a constant, proto.ProtoPackageIsVersionN (where N is generatedCodeVersion).
+const generatedCodeVersion = 3
+
+// A Plugin provides functionality to add to the output during Go code generation,
+// such as to produce RPC stubs.
+type Plugin interface {
+ // Name identifies the plugin.
+ Name() string
+ // Init is called once after data structures are built but before
+ // code generation begins.
+ Init(g *Generator)
+ // Generate produces the code generated by the plugin for this file,
+ // except for the imports, by calling the generator's methods P, In, and Out.
+ Generate(file *FileDescriptor)
+ // GenerateImports produces the import declarations for this file.
+ // It is called after Generate.
+ GenerateImports(file *FileDescriptor)
+}
+
+type pluginSlice []Plugin
+
+func (ps pluginSlice) Len() int {
+ return len(ps)
+}
+
+func (ps pluginSlice) Less(i, j int) bool {
+ return ps[i].Name() < ps[j].Name()
+}
+
+func (ps pluginSlice) Swap(i, j int) {
+ ps[i], ps[j] = ps[j], ps[i]
+}
+
+var plugins pluginSlice
+
+// RegisterPlugin installs a (second-order) plugin to be run when the Go output is generated.
+// It is typically called during initialization.
+func RegisterPlugin(p Plugin) {
+ plugins = append(plugins, p)
+}
+
+// A GoImportPath is the import path of a Go package. e.g., "google.golang.org/genproto/protobuf".
+type GoImportPath string
+
+func (p GoImportPath) String() string { return strconv.Quote(string(p)) }
+
+// A GoPackageName is the name of a Go package. e.g., "protobuf".
+type GoPackageName string
+
+// Each type we import as a protocol buffer (other than FileDescriptorProto) needs
+// a pointer to the FileDescriptorProto that represents it. These types achieve that
+// wrapping by placing each Proto inside a struct with the pointer to its File. The
+// structs have the same names as their contents, with "Proto" removed.
+// FileDescriptor is used to store the things that it points to.
+
+// The file and package name method are common to messages and enums.
+type common struct {
+ file *FileDescriptor // File this object comes from.
+}
+
+// GoImportPath is the import path of the Go package containing the type.
+func (c *common) GoImportPath() GoImportPath {
+ return c.file.importPath
+}
+
+func (c *common) File() *FileDescriptor { return c.file }
+
+func fileIsProto3(file *descriptor.FileDescriptorProto) bool {
+ return file.GetSyntax() == "proto3"
+}
+
+func (c *common) proto3() bool { return fileIsProto3(c.file.FileDescriptorProto) }
+
+// Descriptor represents a protocol buffer message.
+type Descriptor struct {
+ common
+ *descriptor.DescriptorProto
+ parent *Descriptor // The containing message, if any.
+ nested []*Descriptor // Inner messages, if any.
+ enums []*EnumDescriptor // Inner enums, if any.
+ ext []*ExtensionDescriptor // Extensions, if any.
+ typename []string // Cached typename vector.
+ index int // The index into the container, whether the file or another message.
+ path string // The SourceCodeInfo path as comma-separated integers.
+ group bool
+}
+
+// TypeName returns the elements of the dotted type name.
+// The package name is not part of this name.
+func (d *Descriptor) TypeName() []string {
+ if d.typename != nil {
+ return d.typename
+ }
+ n := 0
+ for parent := d; parent != nil; parent = parent.parent {
+ n++
+ }
+ s := make([]string, n)
+ for parent := d; parent != nil; parent = parent.parent {
+ n--
+ s[n] = parent.GetName()
+ }
+ d.typename = s
+ return s
+}
+
+func (d *Descriptor) allowOneof() bool {
+ return true
+}
+
+// EnumDescriptor describes an enum. If it's at top level, its parent will be nil.
+// Otherwise it will be the descriptor of the message in which it is defined.
+type EnumDescriptor struct {
+ common
+ *descriptor.EnumDescriptorProto
+ parent *Descriptor // The containing message, if any.
+ typename []string // Cached typename vector.
+ index int // The index into the container, whether the file or a message.
+ path string // The SourceCodeInfo path as comma-separated integers.
+}
+
+// TypeName returns the elements of the dotted type name.
+// The package name is not part of this name.
+func (e *EnumDescriptor) TypeName() (s []string) {
+ if e.typename != nil {
+ return e.typename
+ }
+ name := e.GetName()
+ if e.parent == nil {
+ s = make([]string, 1)
+ } else {
+ pname := e.parent.TypeName()
+ s = make([]string, len(pname)+1)
+ copy(s, pname)
+ }
+ s[len(s)-1] = name
+ e.typename = s
+ return s
+}
+
+// alias provides the TypeName corrected for the application of any naming
+// extensions on the enum type. It should be used for generating references to
+// the Go types and for calculating prefixes.
+func (e *EnumDescriptor) alias() (s []string) {
+ s = e.TypeName()
+ if gogoproto.IsEnumCustomName(e.EnumDescriptorProto) {
+ s[len(s)-1] = gogoproto.GetEnumCustomName(e.EnumDescriptorProto)
+ }
+
+ return
+}
+
+// Everything but the last element of the full type name, CamelCased.
+// The values of type Foo.Bar are call Foo_value1... not Foo_Bar_value1... .
+func (e *EnumDescriptor) prefix() string {
+ typeName := e.alias()
+ if e.parent == nil {
+ // If the enum is not part of a message, the prefix is just the type name.
+ return CamelCase(typeName[len(typeName)-1]) + "_"
+ }
+ return CamelCaseSlice(typeName[0:len(typeName)-1]) + "_"
+}
+
+// The integer value of the named constant in this enumerated type.
+func (e *EnumDescriptor) integerValueAsString(name string) string {
+ for _, c := range e.Value {
+ if c.GetName() == name {
+ return fmt.Sprint(c.GetNumber())
+ }
+ }
+ log.Fatal("cannot find value for enum constant")
+ return ""
+}
+
+// ExtensionDescriptor describes an extension. If it's at top level, its parent will be nil.
+// Otherwise it will be the descriptor of the message in which it is defined.
+type ExtensionDescriptor struct {
+ common
+ *descriptor.FieldDescriptorProto
+ parent *Descriptor // The containing message, if any.
+}
+
+// TypeName returns the elements of the dotted type name.
+// The package name is not part of this name.
+func (e *ExtensionDescriptor) TypeName() (s []string) {
+ name := e.GetName()
+ if e.parent == nil {
+ // top-level extension
+ s = make([]string, 1)
+ } else {
+ pname := e.parent.TypeName()
+ s = make([]string, len(pname)+1)
+ copy(s, pname)
+ }
+ s[len(s)-1] = name
+ return s
+}
+
+// DescName returns the variable name used for the generated descriptor.
+func (e *ExtensionDescriptor) DescName() string {
+ // The full type name.
+ typeName := e.TypeName()
+ // Each scope of the extension is individually CamelCased, and all are joined with "_" with an "E_" prefix.
+ for i, s := range typeName {
+ typeName[i] = CamelCase(s)
+ }
+ return "E_" + strings.Join(typeName, "_")
+}
+
+// ImportedDescriptor describes a type that has been publicly imported from another file.
+type ImportedDescriptor struct {
+ common
+ o Object
+}
+
+func (id *ImportedDescriptor) TypeName() []string { return id.o.TypeName() }
+
+// FileDescriptor describes an protocol buffer descriptor file (.proto).
+// It includes slices of all the messages and enums defined within it.
+// Those slices are constructed by WrapTypes.
+type FileDescriptor struct {
+ *descriptor.FileDescriptorProto
+ desc []*Descriptor // All the messages defined in this file.
+ enum []*EnumDescriptor // All the enums defined in this file.
+ ext []*ExtensionDescriptor // All the top-level extensions defined in this file.
+ imp []*ImportedDescriptor // All types defined in files publicly imported by this file.
+
+ // Comments, stored as a map of path (comma-separated integers) to the comment.
+ comments map[string]*descriptor.SourceCodeInfo_Location
+
+ // The full list of symbols that are exported,
+ // as a map from the exported object to its symbols.
+ // This is used for supporting public imports.
+ exported map[Object][]symbol
+
+ importPath GoImportPath // Import path of this file's package.
+ packageName GoPackageName // Name of this file's Go package.
+
+ proto3 bool // whether to generate proto3 code for this file
+}
+
+// VarName is the variable name we'll use in the generated code to refer
+// to the compressed bytes of this descriptor. It is not exported, so
+// it is only valid inside the generated package.
+func (d *FileDescriptor) VarName() string {
+ h := sha256.Sum256([]byte(d.GetName()))
+ return fmt.Sprintf("fileDescriptor_%s", hex.EncodeToString(h[:8]))
+}
+
+// goPackageOption interprets the file's go_package option.
+// If there is no go_package, it returns ("", "", false).
+// If there's a simple name, it returns ("", pkg, true).
+// If the option implies an import path, it returns (impPath, pkg, true).
+func (d *FileDescriptor) goPackageOption() (impPath GoImportPath, pkg GoPackageName, ok bool) {
+ opt := d.GetOptions().GetGoPackage()
+ if opt == "" {
+ return "", "", false
+ }
+ // A semicolon-delimited suffix delimits the import path and package name.
+ sc := strings.Index(opt, ";")
+ if sc >= 0 {
+ return GoImportPath(opt[:sc]), cleanPackageName(opt[sc+1:]), true
+ }
+ // The presence of a slash implies there's an import path.
+ slash := strings.LastIndex(opt, "/")
+ if slash >= 0 {
+ return GoImportPath(opt), cleanPackageName(opt[slash+1:]), true
+ }
+ return "", cleanPackageName(opt), true
+}
+
+// goFileName returns the output name for the generated Go file.
+func (d *FileDescriptor) goFileName(pathType pathType) string {
+ name := *d.Name
+ if ext := path.Ext(name); ext == ".proto" || ext == ".protodevel" {
+ name = name[:len(name)-len(ext)]
+ }
+ name += ".pb.go"
+
+ if pathType == pathTypeSourceRelative {
+ return name
+ }
+
+ // Does the file have a "go_package" option?
+ // If it does, it may override the filename.
+ if impPath, _, ok := d.goPackageOption(); ok && impPath != "" {
+ // Replace the existing dirname with the declared import path.
+ _, name = path.Split(name)
+ name = path.Join(string(impPath), name)
+ return name
+ }
+
+ return name
+}
+
+func (d *FileDescriptor) addExport(obj Object, sym symbol) {
+ d.exported[obj] = append(d.exported[obj], sym)
+}
+
+// symbol is an interface representing an exported Go symbol.
+type symbol interface {
+ // GenerateAlias should generate an appropriate alias
+ // for the symbol from the named package.
+ GenerateAlias(g *Generator, filename string, pkg GoPackageName)
+}
+
+type messageSymbol struct {
+ sym string
+ hasExtensions, isMessageSet bool
+ oneofTypes []string
+}
+
+type getterSymbol struct {
+ name string
+ typ string
+ typeName string // canonical name in proto world; empty for proto.Message and similar
+ genType bool // whether typ contains a generated type (message/group/enum)
+}
+
+func (ms *messageSymbol) GenerateAlias(g *Generator, filename string, pkg GoPackageName) {
+ g.P("// ", ms.sym, " from public import ", filename)
+ g.P("type ", ms.sym, " = ", pkg, ".", ms.sym)
+ for _, name := range ms.oneofTypes {
+ g.P("type ", name, " = ", pkg, ".", name)
+ }
+}
+
+type enumSymbol struct {
+ name string
+ proto3 bool // Whether this came from a proto3 file.
+}
+
+func (es enumSymbol) GenerateAlias(g *Generator, filename string, pkg GoPackageName) {
+ s := es.name
+ g.P("// ", s, " from public import ", filename)
+ g.P("type ", s, " = ", pkg, ".", s)
+ g.P("var ", s, "_name = ", pkg, ".", s, "_name")
+ g.P("var ", s, "_value = ", pkg, ".", s, "_value")
+}
+
+type constOrVarSymbol struct {
+ sym string
+ typ string // either "const" or "var"
+ cast string // if non-empty, a type cast is required (used for enums)
+}
+
+func (cs constOrVarSymbol) GenerateAlias(g *Generator, filename string, pkg GoPackageName) {
+ v := string(pkg) + "." + cs.sym
+ if cs.cast != "" {
+ v = cs.cast + "(" + v + ")"
+ }
+ g.P(cs.typ, " ", cs.sym, " = ", v)
+}
+
+// Object is an interface abstracting the abilities shared by enums, messages, extensions and imported objects.
+type Object interface {
+ GoImportPath() GoImportPath
+ TypeName() []string
+ File() *FileDescriptor
+}
+
+// Generator is the type whose methods generate the output, stored in the associated response structure.
+type Generator struct {
+ *bytes.Buffer
+
+ Request *plugin.CodeGeneratorRequest // The input.
+ Response *plugin.CodeGeneratorResponse // The output.
+
+ Param map[string]string // Command-line parameters.
+ PackageImportPath string // Go import path of the package we're generating code for
+ ImportPrefix string // String to prefix to imported package file names.
+ ImportMap map[string]string // Mapping from .proto file name to import path
+
+ Pkg map[string]string // The names under which we import support packages
+
+ outputImportPath GoImportPath // Package we're generating code for.
+ allFiles []*FileDescriptor // All files in the tree
+ allFilesByName map[string]*FileDescriptor // All files by filename.
+ genFiles []*FileDescriptor // Those files we will generate output for.
+ file *FileDescriptor // The file we are compiling now.
+ packageNames map[GoImportPath]GoPackageName // Imported package names in the current file.
+ usedPackages map[GoImportPath]bool // Packages used in current file.
+ usedPackageNames map[GoPackageName]bool // Package names used in the current file.
+ addedImports map[GoImportPath]bool // Additional imports to emit.`
+ typeNameToObject map[string]Object // Key is a fully-qualified name in input syntax.
+ init []string // Lines to emit in the init function.
+ indent string
+ pathType pathType // How to generate output filenames.
+ writeOutput bool
+ annotateCode bool // whether to store annotations
+ annotations []*descriptor.GeneratedCodeInfo_Annotation // annotations to store
+
+ customImports []string
+ writtenImports map[string]bool // For de-duplicating written imports
+}
+
+type pathType int
+
+const (
+ pathTypeImport pathType = iota
+ pathTypeSourceRelative
+)
+
+// New creates a new generator and allocates the request and response protobufs.
+func New() *Generator {
+ g := new(Generator)
+ g.Buffer = new(bytes.Buffer)
+ g.Request = new(plugin.CodeGeneratorRequest)
+ g.Response = new(plugin.CodeGeneratorResponse)
+ g.writtenImports = make(map[string]bool)
+ g.addedImports = make(map[GoImportPath]bool)
+ return g
+}
+
+// Error reports a problem, including an error, and exits the program.
+func (g *Generator) Error(err error, msgs ...string) {
+ s := strings.Join(msgs, " ") + ":" + err.Error()
+ log.Print("protoc-gen-gogo: error:", s)
+ os.Exit(1)
+}
+
+// Fail reports a problem and exits the program.
+func (g *Generator) Fail(msgs ...string) {
+ s := strings.Join(msgs, " ")
+ log.Print("protoc-gen-gogo: error:", s)
+ os.Exit(1)
+}
+
+// CommandLineParameters breaks the comma-separated list of key=value pairs
+// in the parameter (a member of the request protobuf) into a key/value map.
+// It then sets file name mappings defined by those entries.
+func (g *Generator) CommandLineParameters(parameter string) {
+ g.Param = make(map[string]string)
+ for _, p := range strings.Split(parameter, ",") {
+ if i := strings.Index(p, "="); i < 0 {
+ g.Param[p] = ""
+ } else {
+ g.Param[p[0:i]] = p[i+1:]
+ }
+ }
+
+ g.ImportMap = make(map[string]string)
+ pluginList := "none" // Default list of plugin names to enable (empty means all).
+ for k, v := range g.Param {
+ switch k {
+ case "import_prefix":
+ g.ImportPrefix = v
+ case "import_path":
+ g.PackageImportPath = v
+ case "paths":
+ switch v {
+ case "import":
+ g.pathType = pathTypeImport
+ case "source_relative":
+ g.pathType = pathTypeSourceRelative
+ default:
+ g.Fail(fmt.Sprintf(`Unknown path type %q: want "import" or "source_relative".`, v))
+ }
+ case "plugins":
+ pluginList = v
+ case "annotate_code":
+ if v == "true" {
+ g.annotateCode = true
+ }
+ default:
+ if len(k) > 0 && k[0] == 'M' {
+ g.ImportMap[k[1:]] = v
+ }
+ }
+ }
+ if pluginList == "" {
+ return
+ }
+ if pluginList == "none" {
+ pluginList = ""
+ }
+ gogoPluginNames := []string{"unmarshal", "unsafeunmarshaler", "union", "stringer", "size", "protosizer", "populate", "marshalto", "unsafemarshaler", "gostring", "face", "equal", "enumstringer", "embedcheck", "description", "defaultcheck", "oneofcheck", "compare"}
+ pluginList = strings.Join(append(gogoPluginNames, pluginList), "+")
+ if pluginList != "" {
+ // Amend the set of plugins.
+ enabled := make(map[string]bool)
+ for _, name := range strings.Split(pluginList, "+") {
+ enabled[name] = true
+ }
+ var nplugins pluginSlice
+ for _, p := range plugins {
+ if enabled[p.Name()] {
+ nplugins = append(nplugins, p)
+ }
+ }
+ sort.Sort(nplugins)
+ plugins = nplugins
+ }
+}
+
+// DefaultPackageName returns the package name printed for the object.
+// If its file is in a different package, it returns the package name we're using for this file, plus ".".
+// Otherwise it returns the empty string.
+func (g *Generator) DefaultPackageName(obj Object) string {
+ importPath := obj.GoImportPath()
+ if importPath == g.outputImportPath {
+ return ""
+ }
+ return string(g.GoPackageName(importPath)) + "."
+}
+
+// GoPackageName returns the name used for a package.
+func (g *Generator) GoPackageName(importPath GoImportPath) GoPackageName {
+ if name, ok := g.packageNames[importPath]; ok {
+ return name
+ }
+ name := cleanPackageName(baseName(string(importPath)))
+ for i, orig := 1, name; g.usedPackageNames[name] || isGoPredeclaredIdentifier[string(name)]; i++ {
+ name = orig + GoPackageName(strconv.Itoa(i))
+ }
+ if g.packageNames == nil {
+ g.packageNames = make(map[GoImportPath]GoPackageName)
+ }
+ g.packageNames[importPath] = name
+ if g.usedPackageNames == nil {
+ g.usedPackageNames = make(map[GoPackageName]bool)
+ }
+ g.usedPackageNames[name] = true
+ return name
+}
+
+// AddImport adds a package to the generated file's import section.
+// It returns the name used for the package.
+func (g *Generator) AddImport(importPath GoImportPath) GoPackageName {
+ g.addedImports[importPath] = true
+ return g.GoPackageName(importPath)
+}
+
+var globalPackageNames = map[GoPackageName]bool{
+ "fmt": true,
+ "math": true,
+ "proto": true,
+}
+
+// Create and remember a guaranteed unique package name. Pkg is the candidate name.
+// The FileDescriptor parameter is unused.
+func RegisterUniquePackageName(pkg string, f *FileDescriptor) string {
+ name := cleanPackageName(pkg)
+ for i, orig := 1, name; globalPackageNames[name]; i++ {
+ name = orig + GoPackageName(strconv.Itoa(i))
+ }
+ globalPackageNames[name] = true
+ return string(name)
+}
+
+var isGoKeyword = map[string]bool{
+ "break": true,
+ "case": true,
+ "chan": true,
+ "const": true,
+ "continue": true,
+ "default": true,
+ "else": true,
+ "defer": true,
+ "fallthrough": true,
+ "for": true,
+ "func": true,
+ "go": true,
+ "goto": true,
+ "if": true,
+ "import": true,
+ "interface": true,
+ "map": true,
+ "package": true,
+ "range": true,
+ "return": true,
+ "select": true,
+ "struct": true,
+ "switch": true,
+ "type": true,
+ "var": true,
+}
+
+var isGoPredeclaredIdentifier = map[string]bool{
+ "append": true,
+ "bool": true,
+ "byte": true,
+ "cap": true,
+ "close": true,
+ "complex": true,
+ "complex128": true,
+ "complex64": true,
+ "copy": true,
+ "delete": true,
+ "error": true,
+ "false": true,
+ "float32": true,
+ "float64": true,
+ "imag": true,
+ "int": true,
+ "int16": true,
+ "int32": true,
+ "int64": true,
+ "int8": true,
+ "iota": true,
+ "len": true,
+ "make": true,
+ "new": true,
+ "nil": true,
+ "panic": true,
+ "print": true,
+ "println": true,
+ "real": true,
+ "recover": true,
+ "rune": true,
+ "string": true,
+ "true": true,
+ "uint": true,
+ "uint16": true,
+ "uint32": true,
+ "uint64": true,
+ "uint8": true,
+ "uintptr": true,
+}
+
+func cleanPackageName(name string) GoPackageName {
+ name = strings.Map(badToUnderscore, name)
+ // Identifier must not be keyword: insert _.
+ if isGoKeyword[name] {
+ name = "_" + name
+ }
+ // Identifier must not begin with digit: insert _.
+ if r, _ := utf8.DecodeRuneInString(name); unicode.IsDigit(r) {
+ name = "_" + name
+ }
+ return GoPackageName(name)
+}
+
+// defaultGoPackage returns the package name to use,
+// derived from the import path of the package we're building code for.
+func (g *Generator) defaultGoPackage() GoPackageName {
+ p := g.PackageImportPath
+ if i := strings.LastIndex(p, "/"); i >= 0 {
+ p = p[i+1:]
+ }
+ return cleanPackageName(p)
+}
+
+// SetPackageNames sets the package name for this run.
+// The package name must agree across all files being generated.
+// It also defines unique package names for all imported files.
+func (g *Generator) SetPackageNames() {
+ g.outputImportPath = g.genFiles[0].importPath
+
+ defaultPackageNames := make(map[GoImportPath]GoPackageName)
+ for _, f := range g.genFiles {
+ if _, p, ok := f.goPackageOption(); ok {
+ defaultPackageNames[f.importPath] = p
+ }
+ }
+ for _, f := range g.genFiles {
+ if _, p, ok := f.goPackageOption(); ok {
+ // Source file: option go_package = "quux/bar";
+ f.packageName = p
+ } else if p, ok := defaultPackageNames[f.importPath]; ok {
+ // A go_package option in another file in the same package.
+ //
+ // This is a poor choice in general, since every source file should
+ // contain a go_package option. Supported mainly for historical
+ // compatibility.
+ f.packageName = p
+ } else if p := g.defaultGoPackage(); p != "" {
+ // Command-line: import_path=quux/bar.
+ //
+ // The import_path flag sets a package name for files which don't
+ // contain a go_package option.
+ f.packageName = p
+ } else if p := f.GetPackage(); p != "" {
+ // Source file: package quux.bar;
+ f.packageName = cleanPackageName(p)
+ } else {
+ // Source filename.
+ f.packageName = cleanPackageName(baseName(f.GetName()))
+ }
+ }
+
+ // Check that all files have a consistent package name and import path.
+ for _, f := range g.genFiles[1:] {
+ if a, b := g.genFiles[0].importPath, f.importPath; a != b {
+ g.Fail(fmt.Sprintf("inconsistent package import paths: %v, %v", a, b))
+ }
+ if a, b := g.genFiles[0].packageName, f.packageName; a != b {
+ g.Fail(fmt.Sprintf("inconsistent package names: %v, %v", a, b))
+ }
+ }
+
+ // Names of support packages. These never vary (if there are conflicts,
+ // we rename the conflicting package), so this could be removed someday.
+ g.Pkg = map[string]string{
+ "fmt": "fmt",
+ "math": "math",
+ "proto": "proto",
+ "golang_proto": "golang_proto",
+ }
+}
+
+// WrapTypes walks the incoming data, wrapping DescriptorProtos, EnumDescriptorProtos
+// and FileDescriptorProtos into file-referenced objects within the Generator.
+// It also creates the list of files to generate and so should be called before GenerateAllFiles.
+func (g *Generator) WrapTypes() {
+ g.allFiles = make([]*FileDescriptor, 0, len(g.Request.ProtoFile))
+ g.allFilesByName = make(map[string]*FileDescriptor, len(g.allFiles))
+ genFileNames := make(map[string]bool)
+ for _, n := range g.Request.FileToGenerate {
+ genFileNames[n] = true
+ }
+ for _, f := range g.Request.ProtoFile {
+ fd := &FileDescriptor{
+ FileDescriptorProto: f,
+ exported: make(map[Object][]symbol),
+ proto3: fileIsProto3(f),
+ }
+ // The import path may be set in a number of ways.
+ if substitution, ok := g.ImportMap[f.GetName()]; ok {
+ // Command-line: M=foo.proto=quux/bar.
+ //
+ // Explicit mapping of source file to import path.
+ fd.importPath = GoImportPath(substitution)
+ } else if genFileNames[f.GetName()] && g.PackageImportPath != "" {
+ // Command-line: import_path=quux/bar.
+ //
+ // The import_path flag sets the import path for every file that
+ // we generate code for.
+ fd.importPath = GoImportPath(g.PackageImportPath)
+ } else if p, _, _ := fd.goPackageOption(); p != "" {
+ // Source file: option go_package = "quux/bar";
+ //
+ // The go_package option sets the import path. Most users should use this.
+ fd.importPath = p
+ } else {
+ // Source filename.
+ //
+ // Last resort when nothing else is available.
+ fd.importPath = GoImportPath(path.Dir(f.GetName()))
+ }
+ // We must wrap the descriptors before we wrap the enums
+ fd.desc = wrapDescriptors(fd)
+ g.buildNestedDescriptors(fd.desc)
+ fd.enum = wrapEnumDescriptors(fd, fd.desc)
+ g.buildNestedEnums(fd.desc, fd.enum)
+ fd.ext = wrapExtensions(fd)
+ extractComments(fd)
+ g.allFiles = append(g.allFiles, fd)
+ g.allFilesByName[f.GetName()] = fd
+ }
+ for _, fd := range g.allFiles {
+ fd.imp = wrapImported(fd, g)
+ }
+
+ g.genFiles = make([]*FileDescriptor, 0, len(g.Request.FileToGenerate))
+ for _, fileName := range g.Request.FileToGenerate {
+ fd := g.allFilesByName[fileName]
+ if fd == nil {
+ g.Fail("could not find file named", fileName)
+ }
+ g.genFiles = append(g.genFiles, fd)
+ }
+}
+
+// Scan the descriptors in this file. For each one, build the slice of nested descriptors
+func (g *Generator) buildNestedDescriptors(descs []*Descriptor) {
+ for _, desc := range descs {
+ if len(desc.NestedType) != 0 {
+ for _, nest := range descs {
+ if nest.parent == desc {
+ desc.nested = append(desc.nested, nest)
+ }
+ }
+ if len(desc.nested) != len(desc.NestedType) {
+ g.Fail("internal error: nesting failure for", desc.GetName())
+ }
+ }
+ }
+}
+
+func (g *Generator) buildNestedEnums(descs []*Descriptor, enums []*EnumDescriptor) {
+ for _, desc := range descs {
+ if len(desc.EnumType) != 0 {
+ for _, enum := range enums {
+ if enum.parent == desc {
+ desc.enums = append(desc.enums, enum)
+ }
+ }
+ if len(desc.enums) != len(desc.EnumType) {
+ g.Fail("internal error: enum nesting failure for", desc.GetName())
+ }
+ }
+ }
+}
+
+// Construct the Descriptor
+func newDescriptor(desc *descriptor.DescriptorProto, parent *Descriptor, file *FileDescriptor, index int) *Descriptor {
+ d := &Descriptor{
+ common: common{file},
+ DescriptorProto: desc,
+ parent: parent,
+ index: index,
+ }
+ if parent == nil {
+ d.path = fmt.Sprintf("%d,%d", messagePath, index)
+ } else {
+ d.path = fmt.Sprintf("%s,%d,%d", parent.path, messageMessagePath, index)
+ }
+
+ // The only way to distinguish a group from a message is whether
+ // the containing message has a TYPE_GROUP field that matches.
+ if parent != nil {
+ parts := d.TypeName()
+ if file.Package != nil {
+ parts = append([]string{*file.Package}, parts...)
+ }
+ exp := "." + strings.Join(parts, ".")
+ for _, field := range parent.Field {
+ if field.GetType() == descriptor.FieldDescriptorProto_TYPE_GROUP && field.GetTypeName() == exp {
+ d.group = true
+ break
+ }
+ }
+ }
+
+ for _, field := range desc.Extension {
+ d.ext = append(d.ext, &ExtensionDescriptor{common{file}, field, d})
+ }
+
+ return d
+}
+
+// Return a slice of all the Descriptors defined within this file
+func wrapDescriptors(file *FileDescriptor) []*Descriptor {
+ sl := make([]*Descriptor, 0, len(file.MessageType)+10)
+ for i, desc := range file.MessageType {
+ sl = wrapThisDescriptor(sl, desc, nil, file, i)
+ }
+ return sl
+}
+
+// Wrap this Descriptor, recursively
+func wrapThisDescriptor(sl []*Descriptor, desc *descriptor.DescriptorProto, parent *Descriptor, file *FileDescriptor, index int) []*Descriptor {
+ sl = append(sl, newDescriptor(desc, parent, file, index))
+ me := sl[len(sl)-1]
+ for i, nested := range desc.NestedType {
+ sl = wrapThisDescriptor(sl, nested, me, file, i)
+ }
+ return sl
+}
+
+// Construct the EnumDescriptor
+func newEnumDescriptor(desc *descriptor.EnumDescriptorProto, parent *Descriptor, file *FileDescriptor, index int) *EnumDescriptor {
+ ed := &EnumDescriptor{
+ common: common{file},
+ EnumDescriptorProto: desc,
+ parent: parent,
+ index: index,
+ }
+ if parent == nil {
+ ed.path = fmt.Sprintf("%d,%d", enumPath, index)
+ } else {
+ ed.path = fmt.Sprintf("%s,%d,%d", parent.path, messageEnumPath, index)
+ }
+ return ed
+}
+
+// Return a slice of all the EnumDescriptors defined within this file
+func wrapEnumDescriptors(file *FileDescriptor, descs []*Descriptor) []*EnumDescriptor {
+ sl := make([]*EnumDescriptor, 0, len(file.EnumType)+10)
+ // Top-level enums.
+ for i, enum := range file.EnumType {
+ sl = append(sl, newEnumDescriptor(enum, nil, file, i))
+ }
+ // Enums within messages. Enums within embedded messages appear in the outer-most message.
+ for _, nested := range descs {
+ for i, enum := range nested.EnumType {
+ sl = append(sl, newEnumDescriptor(enum, nested, file, i))
+ }
+ }
+ return sl
+}
+
+// Return a slice of all the top-level ExtensionDescriptors defined within this file.
+func wrapExtensions(file *FileDescriptor) []*ExtensionDescriptor {
+ var sl []*ExtensionDescriptor
+ for _, field := range file.Extension {
+ sl = append(sl, &ExtensionDescriptor{common{file}, field, nil})
+ }
+ return sl
+}
+
+// Return a slice of all the types that are publicly imported into this file.
+func wrapImported(file *FileDescriptor, g *Generator) (sl []*ImportedDescriptor) {
+ for _, index := range file.PublicDependency {
+ df := g.fileByName(file.Dependency[index])
+ for _, d := range df.desc {
+ if d.GetOptions().GetMapEntry() {
+ continue
+ }
+ sl = append(sl, &ImportedDescriptor{common{file}, d})
+ }
+ for _, e := range df.enum {
+ sl = append(sl, &ImportedDescriptor{common{file}, e})
+ }
+ for _, ext := range df.ext {
+ sl = append(sl, &ImportedDescriptor{common{file}, ext})
+ }
+ }
+ return
+}
+
+func extractComments(file *FileDescriptor) {
+ file.comments = make(map[string]*descriptor.SourceCodeInfo_Location)
+ for _, loc := range file.GetSourceCodeInfo().GetLocation() {
+ if loc.LeadingComments == nil {
+ continue
+ }
+ var p []string
+ for _, n := range loc.Path {
+ p = append(p, strconv.Itoa(int(n)))
+ }
+ file.comments[strings.Join(p, ",")] = loc
+ }
+}
+
+// BuildTypeNameMap builds the map from fully qualified type names to objects.
+// The key names for the map come from the input data, which puts a period at the beginning.
+// It should be called after SetPackageNames and before GenerateAllFiles.
+func (g *Generator) BuildTypeNameMap() {
+ g.typeNameToObject = make(map[string]Object)
+ for _, f := range g.allFiles {
+ // The names in this loop are defined by the proto world, not us, so the
+ // package name may be empty. If so, the dotted package name of X will
+ // be ".X"; otherwise it will be ".pkg.X".
+ dottedPkg := "." + f.GetPackage()
+ if dottedPkg != "." {
+ dottedPkg += "."
+ }
+ for _, enum := range f.enum {
+ name := dottedPkg + dottedSlice(enum.TypeName())
+ g.typeNameToObject[name] = enum
+ }
+ for _, desc := range f.desc {
+ name := dottedPkg + dottedSlice(desc.TypeName())
+ g.typeNameToObject[name] = desc
+ }
+ }
+}
+
+// ObjectNamed, given a fully-qualified input type name as it appears in the input data,
+// returns the descriptor for the message or enum with that name.
+func (g *Generator) ObjectNamed(typeName string) Object {
+ o, ok := g.typeNameToObject[typeName]
+ if !ok {
+ g.Fail("can't find object with type", typeName)
+ }
+ return o
+}
+
+// AnnotatedAtoms is a list of atoms (as consumed by P) that records the file name and proto AST path from which they originated.
+type AnnotatedAtoms struct {
+ source string
+ path string
+ atoms []interface{}
+}
+
+// Annotate records the file name and proto AST path of a list of atoms
+// so that a later call to P can emit a link from each atom to its origin.
+func Annotate(file *FileDescriptor, path string, atoms ...interface{}) *AnnotatedAtoms {
+ return &AnnotatedAtoms{source: *file.Name, path: path, atoms: atoms}
+}
+
+// printAtom prints the (atomic, non-annotation) argument to the generated output.
+func (g *Generator) printAtom(v interface{}) {
+ switch v := v.(type) {
+ case string:
+ g.WriteString(v)
+ case *string:
+ g.WriteString(*v)
+ case bool:
+ fmt.Fprint(g, v)
+ case *bool:
+ fmt.Fprint(g, *v)
+ case int:
+ fmt.Fprint(g, v)
+ case *int32:
+ fmt.Fprint(g, *v)
+ case *int64:
+ fmt.Fprint(g, *v)
+ case float64:
+ fmt.Fprint(g, v)
+ case *float64:
+ fmt.Fprint(g, *v)
+ case GoPackageName:
+ g.WriteString(string(v))
+ case GoImportPath:
+ g.WriteString(strconv.Quote(string(v)))
+ default:
+ g.Fail(fmt.Sprintf("unknown type in printer: %T", v))
+ }
+}
+
+// P prints the arguments to the generated output. It handles strings and int32s, plus
+// handling indirections because they may be *string, etc. Any inputs of type AnnotatedAtoms may emit
+// annotations in a .meta file in addition to outputting the atoms themselves (if g.annotateCode
+// is true).
+func (g *Generator) P(str ...interface{}) {
+ if !g.writeOutput {
+ return
+ }
+ g.WriteString(g.indent)
+ for _, v := range str {
+ switch v := v.(type) {
+ case *AnnotatedAtoms:
+ begin := int32(g.Len())
+ for _, v := range v.atoms {
+ g.printAtom(v)
+ }
+ if g.annotateCode {
+ end := int32(g.Len())
+ var path []int32
+ for _, token := range strings.Split(v.path, ",") {
+ val, err := strconv.ParseInt(token, 10, 32)
+ if err != nil {
+ g.Fail("could not parse proto AST path: ", err.Error())
+ }
+ path = append(path, int32(val))
+ }
+ g.annotations = append(g.annotations, &descriptor.GeneratedCodeInfo_Annotation{
+ Path: path,
+ SourceFile: &v.source,
+ Begin: &begin,
+ End: &end,
+ })
+ }
+ default:
+ g.printAtom(v)
+ }
+ }
+ g.WriteByte('\n')
+}
+
+// addInitf stores the given statement to be printed inside the file's init function.
+// The statement is given as a format specifier and arguments.
+func (g *Generator) addInitf(stmt string, a ...interface{}) {
+ g.init = append(g.init, fmt.Sprintf(stmt, a...))
+}
+
+func (g *Generator) PrintImport(alias GoPackageName, pkg GoImportPath) {
+ statement := string(alias) + " " + strconv.Quote(string(pkg))
+ if g.writtenImports[statement] {
+ return
+ }
+ g.P(statement)
+ g.writtenImports[statement] = true
+}
+
+// In Indents the output one tab stop.
+func (g *Generator) In() { g.indent += "\t" }
+
+// Out unindents the output one tab stop.
+func (g *Generator) Out() {
+ if len(g.indent) > 0 {
+ g.indent = g.indent[1:]
+ }
+}
+
+// GenerateAllFiles generates the output for all the files we're outputting.
+func (g *Generator) GenerateAllFiles() {
+ // Initialize the plugins
+ for _, p := range plugins {
+ p.Init(g)
+ }
+ // Generate the output. The generator runs for every file, even the files
+ // that we don't generate output for, so that we can collate the full list
+ // of exported symbols to support public imports.
+ genFileMap := make(map[*FileDescriptor]bool, len(g.genFiles))
+ for _, file := range g.genFiles {
+ genFileMap[file] = true
+ }
+ for _, file := range g.allFiles {
+ g.Reset()
+ g.annotations = nil
+ g.writeOutput = genFileMap[file]
+ g.generate(file)
+ if !g.writeOutput {
+ continue
+ }
+ fname := file.goFileName(g.pathType)
+ g.Response.File = append(g.Response.File, &plugin.CodeGeneratorResponse_File{
+ Name: proto.String(fname),
+ Content: proto.String(g.String()),
+ })
+ if g.annotateCode {
+ // Store the generated code annotations in text, as the protoc plugin protocol requires that
+ // strings contain valid UTF-8.
+ g.Response.File = append(g.Response.File, &plugin.CodeGeneratorResponse_File{
+ Name: proto.String(file.goFileName(g.pathType) + ".meta"),
+ Content: proto.String(proto.CompactTextString(&descriptor.GeneratedCodeInfo{Annotation: g.annotations})),
+ })
+ }
+ }
+}
+
+// Run all the plugins associated with the file.
+func (g *Generator) runPlugins(file *FileDescriptor) {
+ for _, p := range plugins {
+ p.Generate(file)
+ }
+}
+
+// Fill the response protocol buffer with the generated output for all the files we're
+// supposed to generate.
+func (g *Generator) generate(file *FileDescriptor) {
+ g.customImports = make([]string, 0)
+ g.file = file
+ g.usedPackages = make(map[GoImportPath]bool)
+ g.packageNames = make(map[GoImportPath]GoPackageName)
+ g.usedPackageNames = make(map[GoPackageName]bool)
+ g.addedImports = make(map[GoImportPath]bool)
+ for name := range globalPackageNames {
+ g.usedPackageNames[name] = true
+ }
+
+ g.P("// This is a compile-time assertion to ensure that this generated file")
+ g.P("// is compatible with the proto package it is being compiled against.")
+ g.P("// A compilation error at this line likely means your copy of the")
+ g.P("// proto package needs to be updated.")
+ if gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
+ g.P("const _ = ", g.Pkg["proto"], ".GoGoProtoPackageIsVersion", generatedCodeVersion, " // please upgrade the proto package")
+ } else {
+ g.P("const _ = ", g.Pkg["proto"], ".ProtoPackageIsVersion", generatedCodeVersion, " // please upgrade the proto package")
+ }
+ g.P()
+ // Reset on each file
+ g.writtenImports = make(map[string]bool)
+ for _, td := range g.file.imp {
+ g.generateImported(td)
+ }
+ for _, enum := range g.file.enum {
+ g.generateEnum(enum)
+ }
+ for _, desc := range g.file.desc {
+ // Don't generate virtual messages for maps.
+ if desc.GetOptions().GetMapEntry() {
+ continue
+ }
+ g.generateMessage(desc)
+ }
+ for _, ext := range g.file.ext {
+ g.generateExtension(ext)
+ }
+ g.generateInitFunction()
+ g.generateFileDescriptor(file)
+
+ // Run the plugins before the imports so we know which imports are necessary.
+ g.runPlugins(file)
+
+ // Generate header and imports last, though they appear first in the output.
+ rem := g.Buffer
+ remAnno := g.annotations
+ g.Buffer = new(bytes.Buffer)
+ g.annotations = nil
+ g.generateHeader()
+ g.generateImports()
+ if !g.writeOutput {
+ return
+ }
+ // Adjust the offsets for annotations displaced by the header and imports.
+ for _, anno := range remAnno {
+ *anno.Begin += int32(g.Len())
+ *anno.End += int32(g.Len())
+ g.annotations = append(g.annotations, anno)
+ }
+ g.Write(rem.Bytes())
+
+ // Reformat generated code and patch annotation locations.
+ fset := token.NewFileSet()
+ original := g.Bytes()
+ if g.annotateCode {
+ // make a copy independent of g; we'll need it after Reset.
+ original = append([]byte(nil), original...)
+ }
+ fileAST, err := parser.ParseFile(fset, "", original, parser.ParseComments)
+ if err != nil {
+ // Print out the bad code with line numbers.
+ // This should never happen in practice, but it can while changing generated code,
+ // so consider this a debugging aid.
+ var src bytes.Buffer
+ s := bufio.NewScanner(bytes.NewReader(original))
+ for line := 1; s.Scan(); line++ {
+ fmt.Fprintf(&src, "%5d\t%s\n", line, s.Bytes())
+ }
+ if serr := s.Err(); serr != nil {
+ g.Fail("bad Go source code was generated:", err.Error(), "\n"+string(original))
+ } else {
+ g.Fail("bad Go source code was generated:", err.Error(), "\n"+src.String())
+ }
+ }
+ ast.SortImports(fset, fileAST)
+ g.Reset()
+ err = (&printer.Config{Mode: printer.TabIndent | printer.UseSpaces, Tabwidth: 8}).Fprint(g, fset, fileAST)
+ if err != nil {
+ g.Fail("generated Go source code could not be reformatted:", err.Error())
+ }
+ if g.annotateCode {
+ m, err := remap.Compute(original, g.Bytes())
+ if err != nil {
+ g.Fail("formatted generated Go source code could not be mapped back to the original code:", err.Error())
+ }
+ for _, anno := range g.annotations {
+ new, ok := m.Find(int(*anno.Begin), int(*anno.End))
+ if !ok {
+ g.Fail("span in formatted generated Go source code could not be mapped back to the original code")
+ }
+ *anno.Begin = int32(new.Pos)
+ *anno.End = int32(new.End)
+ }
+ }
+}
+
+// Generate the header, including package definition
+func (g *Generator) generateHeader() {
+ g.P("// Code generated by protoc-gen-gogo. DO NOT EDIT.")
+ if g.file.GetOptions().GetDeprecated() {
+ g.P("// ", *g.file.Name, " is a deprecated file.")
+ } else {
+ g.P("// source: ", *g.file.Name)
+ }
+ g.P()
+ g.PrintComments(strconv.Itoa(packagePath))
+ g.P()
+ g.P("package ", g.file.packageName)
+ g.P()
+}
+
+// deprecationComment is the standard comment added to deprecated
+// messages, fields, enums, and enum values.
+var deprecationComment = "// Deprecated: Do not use."
+
+// PrintComments prints any comments from the source .proto file.
+// The path is a comma-separated list of integers.
+// It returns an indication of whether any comments were printed.
+// See descriptor.proto for its format.
+func (g *Generator) PrintComments(path string) bool {
+ if !g.writeOutput {
+ return false
+ }
+ if c, ok := g.makeComments(path); ok {
+ g.P(c)
+ return true
+ }
+ return false
+}
+
+// makeComments generates the comment string for the field, no "\n" at the end
+func (g *Generator) makeComments(path string) (string, bool) {
+ loc, ok := g.file.comments[path]
+ if !ok {
+ return "", false
+ }
+ w := new(bytes.Buffer)
+ nl := ""
+ for _, line := range strings.Split(strings.TrimSuffix(loc.GetLeadingComments(), "\n"), "\n") {
+ fmt.Fprintf(w, "%s//%s", nl, line)
+ nl = "\n"
+ }
+ return w.String(), true
+}
+
+// Comments returns any comments from the source .proto file and empty string if comments not found.
+// The path is a comma-separated list of intergers.
+// See descriptor.proto for its format.
+func (g *Generator) Comments(path string) string {
+ loc, ok := g.file.comments[path]
+ if !ok {
+ return ""
+ }
+ text := strings.TrimSuffix(loc.GetLeadingComments(), "\n")
+ return text
+}
+
+func (g *Generator) fileByName(filename string) *FileDescriptor {
+ return g.allFilesByName[filename]
+}
+
+// weak returns whether the ith import of the current file is a weak import.
+func (g *Generator) weak(i int32) bool {
+ for _, j := range g.file.WeakDependency {
+ if j == i {
+ return true
+ }
+ }
+ return false
+}
+
+// Generate the imports
+func (g *Generator) generateImports() {
+ imports := make(map[GoImportPath]GoPackageName)
+ for i, s := range g.file.Dependency {
+ fd := g.fileByName(s)
+ importPath := fd.importPath
+ // Do not import our own package.
+ if importPath == g.file.importPath {
+ continue
+ }
+ // Do not import weak imports.
+ if g.weak(int32(i)) {
+ continue
+ }
+ // Do not import a package twice.
+ if _, ok := imports[importPath]; ok {
+ continue
+ }
+ // We need to import all the dependencies, even if we don't reference them,
+ // because other code and tools depend on having the full transitive closure
+ // of protocol buffer types in the binary.
+ packageName := g.GoPackageName(importPath)
+ if _, ok := g.usedPackages[importPath]; !ok {
+ packageName = "_"
+ }
+ imports[importPath] = packageName
+ }
+ for importPath := range g.addedImports {
+ imports[importPath] = g.GoPackageName(importPath)
+ }
+ // We almost always need a proto import. Rather than computing when we
+ // do, which is tricky when there's a plugin, just import it and
+ // reference it later. The same argument applies to the fmt and math packages.
+ g.P("import (")
+ g.PrintImport(GoPackageName(g.Pkg["fmt"]), "fmt")
+ g.PrintImport(GoPackageName(g.Pkg["math"]), "math")
+ if gogoproto.ImportsGoGoProto(g.file.FileDescriptorProto) {
+ g.PrintImport(GoPackageName(g.Pkg["proto"]), GoImportPath(g.ImportPrefix)+GoImportPath("github.com/gogo/protobuf/proto"))
+ if gogoproto.RegistersGolangProto(g.file.FileDescriptorProto) {
+ g.PrintImport(GoPackageName(g.Pkg["golang_proto"]), GoImportPath(g.ImportPrefix)+GoImportPath("github.com/golang/protobuf/proto"))
+ }
+ } else {
+ g.PrintImport(GoPackageName(g.Pkg["proto"]), GoImportPath(g.ImportPrefix)+GoImportPath("github.com/golang/protobuf/proto"))
+ }
+ for importPath, packageName := range imports {
+ g.P(packageName, " ", GoImportPath(g.ImportPrefix)+importPath)
+ }
+ // Custom gogo imports
+ for _, s := range g.customImports {
+ s1 := strings.Map(badToUnderscore, s)
+ g.PrintImport(GoPackageName(s1), GoImportPath(s))
+ }
+ // gogo plugin imports
+ // TODO: may need to worry about uniqueness across plugins and could change this
+ // to use the `addedImports` technique
+ for _, p := range plugins {
+ p.GenerateImports(g.file)
+ }
+ g.P(")")
+
+ g.P("// Reference imports to suppress errors if they are not otherwise used.")
+ g.P("var _ = ", g.Pkg["proto"], ".Marshal")
+ if gogoproto.ImportsGoGoProto(g.file.FileDescriptorProto) && gogoproto.RegistersGolangProto(g.file.FileDescriptorProto) {
+ g.P("var _ = ", g.Pkg["golang_proto"], ".Marshal")
+ }
+ g.P("var _ = ", g.Pkg["fmt"], ".Errorf")
+ g.P("var _ = ", g.Pkg["math"], ".Inf")
+ for _, cimport := range g.customImports {
+ if cimport == "time" {
+ g.P("var _ = time.Kitchen")
+ break
+ }
+ }
+ g.P()
+}
+
+func (g *Generator) generateImported(id *ImportedDescriptor) {
+ df := id.o.File()
+ filename := *df.Name
+ if df.importPath == g.file.importPath {
+ // Don't generate type aliases for files in the same Go package as this one.
+ return
+ }
+ if !supportTypeAliases {
+ g.Fail(fmt.Sprintf("%s: public imports require at least go1.9", filename))
+ }
+ g.usedPackages[df.importPath] = true
+
+ for _, sym := range df.exported[id.o] {
+ sym.GenerateAlias(g, filename, g.GoPackageName(df.importPath))
+ }
+ g.P()
+}
+
+// Generate the enum definitions for this EnumDescriptor.
+func (g *Generator) generateEnum(enum *EnumDescriptor) {
+ // The full type name
+ typeName := enum.alias()
+ // The full type name, CamelCased.
+ ccTypeName := CamelCaseSlice(typeName)
+ ccPrefix := enum.prefix()
+
+ deprecatedEnum := ""
+ if enum.GetOptions().GetDeprecated() {
+ deprecatedEnum = deprecationComment
+ }
+
+ g.PrintComments(enum.path)
+ if !gogoproto.EnabledGoEnumPrefix(enum.file.FileDescriptorProto, enum.EnumDescriptorProto) {
+ ccPrefix = ""
+ }
+
+ if gogoproto.HasEnumDecl(enum.file.FileDescriptorProto, enum.EnumDescriptorProto) {
+ g.P("type ", Annotate(enum.file, enum.path, ccTypeName), " int32", deprecatedEnum)
+ g.file.addExport(enum, enumSymbol{ccTypeName, enum.proto3()})
+ g.P("const (")
+ g.In()
+ for i, e := range enum.Value {
+ etorPath := fmt.Sprintf("%s,%d,%d", enum.path, enumValuePath, i)
+ g.PrintComments(etorPath)
+
+ deprecatedValue := ""
+ if e.GetOptions().GetDeprecated() {
+ deprecatedValue = deprecationComment
+ }
+ name := *e.Name
+ if gogoproto.IsEnumValueCustomName(e) {
+ name = gogoproto.GetEnumValueCustomName(e)
+ }
+ name = ccPrefix + name
+
+ g.P(Annotate(enum.file, etorPath, name), " ", ccTypeName, " = ", e.Number, " ", deprecatedValue)
+ g.file.addExport(enum, constOrVarSymbol{name, "const", ccTypeName})
+ }
+ g.Out()
+ g.P(")")
+ }
+ g.P()
+ g.P("var ", ccTypeName, "_name = map[int32]string{")
+ g.In()
+ generated := make(map[int32]bool) // avoid duplicate values
+ for _, e := range enum.Value {
+ duplicate := ""
+ if _, present := generated[*e.Number]; present {
+ duplicate = "// Duplicate value: "
+ }
+ g.P(duplicate, e.Number, ": ", strconv.Quote(*e.Name), ",")
+ generated[*e.Number] = true
+ }
+ g.Out()
+ g.P("}")
+ g.P()
+ g.P("var ", ccTypeName, "_value = map[string]int32{")
+ g.In()
+ for _, e := range enum.Value {
+ g.P(strconv.Quote(*e.Name), ": ", e.Number, ",")
+ }
+ g.Out()
+ g.P("}")
+ g.P()
+
+ if !enum.proto3() {
+ g.P("func (x ", ccTypeName, ") Enum() *", ccTypeName, " {")
+ g.In()
+ g.P("p := new(", ccTypeName, ")")
+ g.P("*p = x")
+ g.P("return p")
+ g.Out()
+ g.P("}")
+ g.P()
+ }
+
+ if gogoproto.IsGoEnumStringer(g.file.FileDescriptorProto, enum.EnumDescriptorProto) {
+ g.P("func (x ", ccTypeName, ") String() string {")
+ g.In()
+ g.P("return ", g.Pkg["proto"], ".EnumName(", ccTypeName, "_name, int32(x))")
+ g.Out()
+ g.P("}")
+ g.P()
+ }
+
+ if !enum.proto3() && !gogoproto.IsGoEnumStringer(g.file.FileDescriptorProto, enum.EnumDescriptorProto) {
+ g.P("func (x ", ccTypeName, ") MarshalJSON() ([]byte, error) {")
+ g.In()
+ g.P("return ", g.Pkg["proto"], ".MarshalJSONEnum(", ccTypeName, "_name, int32(x))")
+ g.Out()
+ g.P("}")
+ g.P()
+ }
+ if !enum.proto3() {
+ g.P("func (x *", ccTypeName, ") UnmarshalJSON(data []byte) error {")
+ g.In()
+ g.P("value, err := ", g.Pkg["proto"], ".UnmarshalJSONEnum(", ccTypeName, `_value, data, "`, ccTypeName, `")`)
+ g.P("if err != nil {")
+ g.In()
+ g.P("return err")
+ g.Out()
+ g.P("}")
+ g.P("*x = ", ccTypeName, "(value)")
+ g.P("return nil")
+ g.Out()
+ g.P("}")
+ g.P()
+ }
+
+ var indexes []string
+ for m := enum.parent; m != nil; m = m.parent {
+ // XXX: skip groups?
+ indexes = append([]string{strconv.Itoa(m.index)}, indexes...)
+ }
+ indexes = append(indexes, strconv.Itoa(enum.index))
+ g.P("func (", ccTypeName, ") EnumDescriptor() ([]byte, []int) {")
+ g.In()
+ g.P("return ", g.file.VarName(), ", []int{", strings.Join(indexes, ", "), "}")
+ g.Out()
+ g.P("}")
+ g.P()
+ if enum.file.GetPackage() == "google.protobuf" && enum.GetName() == "NullValue" {
+ g.P("func (", ccTypeName, `) XXX_WellKnownType() string { return "`, enum.GetName(), `" }`)
+ g.P()
+ }
+
+ g.generateEnumRegistration(enum)
+}
+
+// The tag is a string like "varint,2,opt,name=fieldname,def=7" that
+// identifies details of the field for the protocol buffer marshaling and unmarshaling
+// code. The fields are:
+// wire encoding
+// protocol tag number
+// opt,req,rep for optional, required, or repeated
+// packed whether the encoding is "packed" (optional; repeated primitives only)
+// name= the original declared name
+// enum= the name of the enum type if it is an enum-typed field.
+// proto3 if this field is in a proto3 message
+// def= string representation of the default value, if any.
+// The default value must be in a representation that can be used at run-time
+// to generate the default value. Thus bools become 0 and 1, for instance.
+func (g *Generator) goTag(message *Descriptor, field *descriptor.FieldDescriptorProto, wiretype string) string {
+ optrepreq := ""
+ switch {
+ case isOptional(field):
+ optrepreq = "opt"
+ case isRequired(field):
+ optrepreq = "req"
+ case isRepeated(field):
+ optrepreq = "rep"
+ }
+ var defaultValue string
+ if dv := field.DefaultValue; dv != nil { // set means an explicit default
+ defaultValue = *dv
+ // Some types need tweaking.
+ switch *field.Type {
+ case descriptor.FieldDescriptorProto_TYPE_BOOL:
+ if defaultValue == "true" {
+ defaultValue = "1"
+ } else {
+ defaultValue = "0"
+ }
+ case descriptor.FieldDescriptorProto_TYPE_STRING,
+ descriptor.FieldDescriptorProto_TYPE_BYTES:
+ // Nothing to do. Quoting is done for the whole tag.
+ case descriptor.FieldDescriptorProto_TYPE_ENUM:
+ // For enums we need to provide the integer constant.
+ obj := g.ObjectNamed(field.GetTypeName())
+ if id, ok := obj.(*ImportedDescriptor); ok {
+ // It is an enum that was publicly imported.
+ // We need the underlying type.
+ obj = id.o
+ }
+ enum, ok := obj.(*EnumDescriptor)
+ if !ok {
+ log.Printf("obj is a %T", obj)
+ if id, ok := obj.(*ImportedDescriptor); ok {
+ log.Printf("id.o is a %T", id.o)
+ }
+ g.Fail("unknown enum type", CamelCaseSlice(obj.TypeName()))
+ }
+ defaultValue = enum.integerValueAsString(defaultValue)
+ case descriptor.FieldDescriptorProto_TYPE_FLOAT:
+ if def := defaultValue; def != "inf" && def != "-inf" && def != "nan" {
+ if f, err := strconv.ParseFloat(defaultValue, 32); err == nil {
+ defaultValue = fmt.Sprint(float32(f))
+ }
+ }
+ case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
+ if def := defaultValue; def != "inf" && def != "-inf" && def != "nan" {
+ if f, err := strconv.ParseFloat(defaultValue, 64); err == nil {
+ defaultValue = fmt.Sprint(f)
+ }
+ }
+ }
+ defaultValue = ",def=" + defaultValue
+ }
+ enum := ""
+ if *field.Type == descriptor.FieldDescriptorProto_TYPE_ENUM {
+ // We avoid using obj.goPackageNamehe
+ // original (proto-world) package name.
+ obj := g.ObjectNamed(field.GetTypeName())
+ if id, ok := obj.(*ImportedDescriptor); ok {
+ obj = id.o
+ }
+ enum = ",enum="
+ if pkg := obj.File().GetPackage(); pkg != "" {
+ enum += pkg + "."
+ }
+ enum += CamelCaseSlice(obj.TypeName())
+ }
+ packed := ""
+ if (field.Options != nil && field.Options.GetPacked()) ||
+ // Per https://developers.google.com/protocol-buffers/docs/proto3#simple:
+ // "In proto3, repeated fields of scalar numeric types use packed encoding by default."
+ (message.proto3() && (field.Options == nil || field.Options.Packed == nil) &&
+ isRepeated(field) && IsScalar(field)) {
+ packed = ",packed"
+ }
+ fieldName := field.GetName()
+ name := fieldName
+ if *field.Type == descriptor.FieldDescriptorProto_TYPE_GROUP {
+ // We must use the type name for groups instead of
+ // the field name to preserve capitalization.
+ // type_name in FieldDescriptorProto is fully-qualified,
+ // but we only want the local part.
+ name = *field.TypeName
+ if i := strings.LastIndex(name, "."); i >= 0 {
+ name = name[i+1:]
+ }
+ }
+ if json := field.GetJsonName(); field.Extendee == nil && json != "" && json != name {
+ // TODO: escaping might be needed, in which case
+ // perhaps this should be in its own "json" tag.
+ name += ",json=" + json
+ }
+ name = ",name=" + name
+
+ embed := ""
+ if gogoproto.IsEmbed(field) {
+ embed = ",embedded=" + fieldName
+ }
+
+ ctype := ""
+ if gogoproto.IsCustomType(field) {
+ ctype = ",customtype=" + gogoproto.GetCustomType(field)
+ }
+
+ casttype := ""
+ if gogoproto.IsCastType(field) {
+ casttype = ",casttype=" + gogoproto.GetCastType(field)
+ }
+
+ castkey := ""
+ if gogoproto.IsCastKey(field) {
+ castkey = ",castkey=" + gogoproto.GetCastKey(field)
+ }
+
+ castvalue := ""
+ if gogoproto.IsCastValue(field) {
+ castvalue = ",castvalue=" + gogoproto.GetCastValue(field)
+ // record the original message type for jsonpb reconstruction
+ desc := g.ObjectNamed(field.GetTypeName())
+ if d, ok := desc.(*Descriptor); ok && d.GetOptions().GetMapEntry() {
+ valueField := d.Field[1]
+ if valueField.IsMessage() {
+ castvalue += ",castvaluetype=" + strings.TrimPrefix(valueField.GetTypeName(), ".")
+ }
+ }
+ }
+
+ if message.proto3() {
+ name += ",proto3"
+ }
+ oneof := ""
+ if field.OneofIndex != nil {
+ oneof = ",oneof"
+ }
+ stdtime := ""
+ if gogoproto.IsStdTime(field) {
+ stdtime = ",stdtime"
+ }
+ stdduration := ""
+ if gogoproto.IsStdDuration(field) {
+ stdduration = ",stdduration"
+ }
+ wktptr := ""
+ if gogoproto.IsWktPtr(field) {
+ wktptr = ",wktptr"
+ }
+ return strconv.Quote(fmt.Sprintf("%s,%d,%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+ wiretype,
+ field.GetNumber(),
+ optrepreq,
+ packed,
+ name,
+ enum,
+ oneof,
+ defaultValue,
+ embed,
+ ctype,
+ casttype,
+ castkey,
+ castvalue,
+ stdtime,
+ stdduration,
+ wktptr))
+}
+
+func needsStar(field *descriptor.FieldDescriptorProto, proto3 bool, allowOneOf bool) bool {
+ if isRepeated(field) &&
+ (*field.Type != descriptor.FieldDescriptorProto_TYPE_MESSAGE || gogoproto.IsCustomType(field)) &&
+ (*field.Type != descriptor.FieldDescriptorProto_TYPE_GROUP) {
+ return false
+ }
+ if *field.Type == descriptor.FieldDescriptorProto_TYPE_BYTES && !gogoproto.IsCustomType(field) {
+ return false
+ }
+ if !gogoproto.IsNullable(field) {
+ return false
+ }
+ if field.OneofIndex != nil && allowOneOf &&
+ (*field.Type != descriptor.FieldDescriptorProto_TYPE_MESSAGE) &&
+ (*field.Type != descriptor.FieldDescriptorProto_TYPE_GROUP) {
+ return false
+ }
+ if proto3 &&
+ (*field.Type != descriptor.FieldDescriptorProto_TYPE_MESSAGE) &&
+ (*field.Type != descriptor.FieldDescriptorProto_TYPE_GROUP) &&
+ !gogoproto.IsCustomType(field) {
+ return false
+ }
+ return true
+}
+
+// TypeName is the printed name appropriate for an item. If the object is in the current file,
+// TypeName drops the package name and underscores the rest.
+// Otherwise the object is from another package; and the result is the underscored
+// package name followed by the item name.
+// The result always has an initial capital.
+func (g *Generator) TypeName(obj Object) string {
+ return g.DefaultPackageName(obj) + CamelCaseSlice(obj.TypeName())
+}
+
+// GoType returns a string representing the type name, and the wire type
+func (g *Generator) GoType(message *Descriptor, field *descriptor.FieldDescriptorProto) (typ string, wire string) {
+ // TODO: Options.
+ switch *field.Type {
+ case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
+ typ, wire = "float64", "fixed64"
+ case descriptor.FieldDescriptorProto_TYPE_FLOAT:
+ typ, wire = "float32", "fixed32"
+ case descriptor.FieldDescriptorProto_TYPE_INT64:
+ typ, wire = "int64", "varint"
+ case descriptor.FieldDescriptorProto_TYPE_UINT64:
+ typ, wire = "uint64", "varint"
+ case descriptor.FieldDescriptorProto_TYPE_INT32:
+ typ, wire = "int32", "varint"
+ case descriptor.FieldDescriptorProto_TYPE_UINT32:
+ typ, wire = "uint32", "varint"
+ case descriptor.FieldDescriptorProto_TYPE_FIXED64:
+ typ, wire = "uint64", "fixed64"
+ case descriptor.FieldDescriptorProto_TYPE_FIXED32:
+ typ, wire = "uint32", "fixed32"
+ case descriptor.FieldDescriptorProto_TYPE_BOOL:
+ typ, wire = "bool", "varint"
+ case descriptor.FieldDescriptorProto_TYPE_STRING:
+ typ, wire = "string", "bytes"
+ case descriptor.FieldDescriptorProto_TYPE_GROUP:
+ desc := g.ObjectNamed(field.GetTypeName())
+ typ, wire = g.TypeName(desc), "group"
+ case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
+ desc := g.ObjectNamed(field.GetTypeName())
+ typ, wire = g.TypeName(desc), "bytes"
+ case descriptor.FieldDescriptorProto_TYPE_BYTES:
+ typ, wire = "[]byte", "bytes"
+ case descriptor.FieldDescriptorProto_TYPE_ENUM:
+ desc := g.ObjectNamed(field.GetTypeName())
+ typ, wire = g.TypeName(desc), "varint"
+ case descriptor.FieldDescriptorProto_TYPE_SFIXED32:
+ typ, wire = "int32", "fixed32"
+ case descriptor.FieldDescriptorProto_TYPE_SFIXED64:
+ typ, wire = "int64", "fixed64"
+ case descriptor.FieldDescriptorProto_TYPE_SINT32:
+ typ, wire = "int32", "zigzag32"
+ case descriptor.FieldDescriptorProto_TYPE_SINT64:
+ typ, wire = "int64", "zigzag64"
+ default:
+ g.Fail("unknown type for", field.GetName())
+ }
+ switch {
+ case gogoproto.IsCustomType(field) && gogoproto.IsCastType(field):
+ g.Fail(field.GetName() + " cannot be custom type and cast type")
+ case gogoproto.IsCustomType(field):
+ var packageName string
+ var err error
+ packageName, typ, err = getCustomType(field)
+ if err != nil {
+ g.Fail(err.Error())
+ }
+ if len(packageName) > 0 {
+ g.customImports = append(g.customImports, packageName)
+ }
+ case gogoproto.IsCastType(field):
+ var packageName string
+ var err error
+ packageName, typ, err = getCastType(field)
+ if err != nil {
+ g.Fail(err.Error())
+ }
+ if len(packageName) > 0 {
+ g.customImports = append(g.customImports, packageName)
+ }
+ case gogoproto.IsStdTime(field):
+ g.customImports = append(g.customImports, "time")
+ typ = "time.Time"
+ case gogoproto.IsStdDuration(field):
+ g.customImports = append(g.customImports, "time")
+ typ = "time.Duration"
+ case gogoproto.IsStdDouble(field):
+ typ = "float64"
+ case gogoproto.IsStdFloat(field):
+ typ = "float32"
+ case gogoproto.IsStdInt64(field):
+ typ = "int64"
+ case gogoproto.IsStdUInt64(field):
+ typ = "uint64"
+ case gogoproto.IsStdInt32(field):
+ typ = "int32"
+ case gogoproto.IsStdUInt32(field):
+ typ = "uint32"
+ case gogoproto.IsStdBool(field):
+ typ = "bool"
+ case gogoproto.IsStdString(field):
+ typ = "string"
+ case gogoproto.IsStdBytes(field):
+ typ = "[]byte"
+ }
+ if needsStar(field, g.file.proto3 && field.Extendee == nil, message != nil && message.allowOneof()) {
+ typ = "*" + typ
+ }
+ if isRepeated(field) {
+ typ = "[]" + typ
+ }
+ return
+}
+
+// GoMapDescriptor is a full description of the map output struct.
+type GoMapDescriptor struct {
+ GoType string
+
+ KeyField *descriptor.FieldDescriptorProto
+ KeyAliasField *descriptor.FieldDescriptorProto
+ KeyTag string
+
+ ValueField *descriptor.FieldDescriptorProto
+ ValueAliasField *descriptor.FieldDescriptorProto
+ ValueTag string
+}
+
+func (g *Generator) GoMapType(d *Descriptor, field *descriptor.FieldDescriptorProto) *GoMapDescriptor {
+ if d == nil {
+ byName := g.ObjectNamed(field.GetTypeName())
+ desc, ok := byName.(*Descriptor)
+ if byName == nil || !ok || !desc.GetOptions().GetMapEntry() {
+ g.Fail(fmt.Sprintf("field %s is not a map", field.GetTypeName()))
+ return nil
+ }
+ d = desc
+ }
+
+ m := &GoMapDescriptor{
+ KeyField: d.Field[0],
+ ValueField: d.Field[1],
+ }
+
+ // Figure out the Go types and tags for the key and value types.
+ m.KeyAliasField, m.ValueAliasField = g.GetMapKeyField(field, m.KeyField), g.GetMapValueField(field, m.ValueField)
+ keyType, keyWire := g.GoType(d, m.KeyAliasField)
+ valType, valWire := g.GoType(d, m.ValueAliasField)
+
+ m.KeyTag, m.ValueTag = g.goTag(d, m.KeyField, keyWire), g.goTag(d, m.ValueField, valWire)
+
+ if gogoproto.IsCastType(field) {
+ var packageName string
+ var err error
+ packageName, typ, err := getCastType(field)
+ if err != nil {
+ g.Fail(err.Error())
+ }
+ if len(packageName) > 0 {
+ g.customImports = append(g.customImports, packageName)
+ }
+ m.GoType = typ
+ return m
+ }
+
+ // We don't use stars, except for message-typed values.
+ // Message and enum types are the only two possibly foreign types used in maps,
+ // so record their use. They are not permitted as map keys.
+ keyType = strings.TrimPrefix(keyType, "*")
+ switch *m.ValueAliasField.Type {
+ case descriptor.FieldDescriptorProto_TYPE_ENUM:
+ valType = strings.TrimPrefix(valType, "*")
+ g.RecordTypeUse(m.ValueAliasField.GetTypeName())
+ case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
+ if !gogoproto.IsNullable(m.ValueAliasField) {
+ valType = strings.TrimPrefix(valType, "*")
+ }
+ if !gogoproto.IsStdType(m.ValueAliasField) && !gogoproto.IsCustomType(field) && !gogoproto.IsCastType(field) {
+ g.RecordTypeUse(m.ValueAliasField.GetTypeName())
+ }
+ default:
+ if gogoproto.IsCustomType(m.ValueAliasField) {
+ if !gogoproto.IsNullable(m.ValueAliasField) {
+ valType = strings.TrimPrefix(valType, "*")
+ }
+ if !gogoproto.IsStdType(field) {
+ g.RecordTypeUse(m.ValueAliasField.GetTypeName())
+ }
+ } else {
+ valType = strings.TrimPrefix(valType, "*")
+ }
+ }
+
+ m.GoType = fmt.Sprintf("map[%s]%s", keyType, valType)
+ return m
+}
+
+func (g *Generator) RecordTypeUse(t string) {
+ if _, ok := g.typeNameToObject[t]; !ok {
+ return
+ }
+ importPath := g.ObjectNamed(t).GoImportPath()
+ if importPath == g.outputImportPath {
+ // Don't record use of objects in our package.
+ return
+ }
+ g.AddImport(importPath)
+ g.usedPackages[importPath] = true
+}
+
+// Method names that may be generated. Fields with these names get an
+// underscore appended. Any change to this set is a potential incompatible
+// API change because it changes generated field names.
+var methodNames = [...]string{
+ "Reset",
+ "String",
+ "ProtoMessage",
+ "Marshal",
+ "Unmarshal",
+ "ExtensionRangeArray",
+ "ExtensionMap",
+ "Descriptor",
+ "MarshalTo",
+ "Equal",
+ "VerboseEqual",
+ "GoString",
+ "ProtoSize",
+}
+
+// Names of messages in the `google.protobuf` package for which
+// we will generate XXX_WellKnownType methods.
+var wellKnownTypes = map[string]bool{
+ "Any": true,
+ "Duration": true,
+ "Empty": true,
+ "Struct": true,
+ "Timestamp": true,
+
+ "Value": true,
+ "ListValue": true,
+ "DoubleValue": true,
+ "FloatValue": true,
+ "Int64Value": true,
+ "UInt64Value": true,
+ "Int32Value": true,
+ "UInt32Value": true,
+ "BoolValue": true,
+ "StringValue": true,
+ "BytesValue": true,
+}
+
+// getterDefault finds the default value for the field to return from a getter,
+// regardless of if it's a built in default or explicit from the source. Returns e.g. "nil", `""`, "Default_MessageType_FieldName"
+func (g *Generator) getterDefault(field *descriptor.FieldDescriptorProto, goMessageType, goTypeName string) string {
+ if isRepeated(field) {
+ return "nil"
+ }
+ if def := field.GetDefaultValue(); def != "" {
+ defaultConstant := g.defaultConstantName(goMessageType, field.GetName())
+ if *field.Type != descriptor.FieldDescriptorProto_TYPE_BYTES {
+ return defaultConstant
+ }
+ return "append([]byte(nil), " + defaultConstant + "...)"
+ }
+ switch *field.Type {
+ case descriptor.FieldDescriptorProto_TYPE_GROUP,
+ descriptor.FieldDescriptorProto_TYPE_MESSAGE:
+ if field.OneofIndex != nil {
+ return "nil"
+ } else {
+ if !gogoproto.IsNullable(field) && (gogoproto.IsStdDuration(field) ||
+ gogoproto.IsStdDouble(field) || gogoproto.IsStdFloat(field) ||
+ gogoproto.IsStdInt64(field) || gogoproto.IsStdUInt64(field) ||
+ gogoproto.IsStdInt32(field) || gogoproto.IsStdUInt32(field)) {
+ return "0"
+ } else if !gogoproto.IsNullable(field) && gogoproto.IsStdBool(field) {
+ return "false"
+ } else if !gogoproto.IsNullable(field) && gogoproto.IsStdString(field) {
+ return "\"\""
+ } else if !gogoproto.IsNullable(field) && gogoproto.IsStdBytes(field) {
+ return "[]byte{}"
+ } else {
+ return goTypeName + "{}"
+ }
+ }
+ case descriptor.FieldDescriptorProto_TYPE_BOOL:
+ return "false"
+ case descriptor.FieldDescriptorProto_TYPE_STRING:
+ return "\"\""
+ case descriptor.FieldDescriptorProto_TYPE_BYTES:
+ // This is only possible for oneof fields.
+ return "nil"
+ case descriptor.FieldDescriptorProto_TYPE_ENUM:
+ // The default default for an enum is the first value in the enum,
+ // not zero.
+ obj := g.ObjectNamed(field.GetTypeName())
+ var enum *EnumDescriptor
+ if id, ok := obj.(*ImportedDescriptor); ok {
+ // The enum type has been publicly imported.
+ enum, _ = id.o.(*EnumDescriptor)
+ } else {
+ enum, _ = obj.(*EnumDescriptor)
+ }
+ if enum == nil {
+ log.Printf("don't know how to generate getter for %s", field.GetName())
+ return "nil"
+ }
+ if len(enum.Value) == 0 {
+ return "0 // empty enum"
+ } else {
+ first := enum.Value[0].GetName()
+ if gogoproto.IsEnumValueCustomName(enum.Value[0]) {
+ first = gogoproto.GetEnumValueCustomName(enum.Value[0])
+ }
+ if gogoproto.EnabledGoEnumPrefix(enum.file.FileDescriptorProto, enum.EnumDescriptorProto) {
+ return g.DefaultPackageName(obj) + enum.prefix() + first
+ } else {
+ return g.DefaultPackageName(obj) + first
+ }
+ }
+ default:
+ return "0"
+ }
+}
+
+// defaultConstantName builds the name of the default constant from the message
+// type name and the untouched field name, e.g. "Default_MessageType_FieldName"
+func (g *Generator) defaultConstantName(goMessageType, protoFieldName string) string {
+ return "Default_" + goMessageType + "_" + CamelCase(protoFieldName)
+}
+
+// The different types of fields in a message and how to actually print them
+// Most of the logic for generateMessage is in the methods of these types.
+//
+// Note that the content of the field is irrelevant, a simpleField can contain
+// anything from a scalar to a group (which is just a message).
+//
+// Extension fields (and message sets) are however handled separately.
+//
+// simpleField - a field that is neiter weak nor oneof, possibly repeated
+// oneofField - field containing list of subfields:
+// - oneofSubField - a field within the oneof
+
+// msgCtx contains the context for the generator functions.
+type msgCtx struct {
+ goName string // Go struct name of the message, e.g. MessageName
+ message *Descriptor // The descriptor for the message
+}
+
+// fieldCommon contains data common to all types of fields.
+type fieldCommon struct {
+ goName string // Go name of field, e.g. "FieldName" or "Descriptor_"
+ protoName string // Name of field in proto language, e.g. "field_name" or "descriptor"
+ getterName string // Name of the getter, e.g. "GetFieldName" or "GetDescriptor_"
+ goType string // The Go type as a string, e.g. "*int32" or "*OtherMessage"
+ tags string // The tag string/annotation for the type, e.g. `protobuf:"varint,8,opt,name=region_id,json=regionId"`
+ fullPath string // The full path of the field as used by Annotate etc, e.g. "4,0,2,0"
+ protoField *descriptor.FieldDescriptorProto // gogo. Passing in the fieldDescriptor in for gogo options. TODO rethink this, we might need a better way of getting options.
+}
+
+// getProtoName gets the proto name of a field, e.g. "field_name" or "descriptor".
+func (f *fieldCommon) getProtoName() string {
+ return f.protoName
+}
+
+// getGoType returns the go type of the field as a string, e.g. "*int32".
+func (f *fieldCommon) getGoType() string {
+ return f.goType
+}
+
+// simpleField is not weak, not a oneof, not an extension. Can be required, optional or repeated.
+type simpleField struct {
+ fieldCommon
+ protoTypeName string // Proto type name, empty if primitive, e.g. ".google.protobuf.Duration"
+ protoType descriptor.FieldDescriptorProto_Type // Actual type enum value, e.g. descriptor.FieldDescriptorProto_TYPE_FIXED64
+ deprecated string // Deprecation comment, if any, e.g. "// Deprecated: Do not use."
+ getterDef string // Default for getters, e.g. "nil", `""` or "Default_MessageType_FieldName"
+ protoDef string // Default value as defined in the proto file, e.g "yoshi" or "5"
+ comment string // The full comment for the field, e.g. "// Useful information"
+}
+
+// decl prints the declaration of the field in the struct (if any).
+func (f *simpleField) decl(g *Generator, mc *msgCtx) {
+ g.P(f.comment, Annotate(mc.message.file, f.fullPath, f.goName), "\t", f.goType, "\t`", f.tags, "`", f.deprecated)
+}
+
+// getter prints the getter for the field.
+func (f *simpleField) getter(g *Generator, mc *msgCtx) {
+ oneof := false
+ if !oneof && !gogoproto.HasGoGetters(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
+ return
+ }
+ if gogoproto.IsEmbed(f.protoField) || gogoproto.IsCustomType(f.protoField) {
+ return
+ }
+ if f.deprecated != "" {
+ g.P(f.deprecated)
+ }
+ g.generateGet(mc, f.protoField, f.protoType, false, f.goName, f.goType, "", "", f.fullPath, f.getterName, f.getterDef)
+}
+
+// setter prints the setter method of the field.
+func (f *simpleField) setter(g *Generator, mc *msgCtx) {
+ // No setter for regular fields yet
+}
+
+// getProtoDef returns the default value explicitly stated in the proto file, e.g "yoshi" or "5".
+func (f *simpleField) getProtoDef() string {
+ return f.protoDef
+}
+
+// getProtoTypeName returns the protobuf type name for the field as returned by field.GetTypeName(), e.g. ".google.protobuf.Duration".
+func (f *simpleField) getProtoTypeName() string {
+ return f.protoTypeName
+}
+
+// getProtoType returns the *field.Type value, e.g. descriptor.FieldDescriptorProto_TYPE_FIXED64.
+func (f *simpleField) getProtoType() descriptor.FieldDescriptorProto_Type {
+ return f.protoType
+}
+
+func (f *simpleField) getProto() *descriptor.FieldDescriptorProto {
+ return f.protoField
+}
+
+// oneofSubFields are kept slize held by each oneofField. They do not appear in the top level slize of fields for the message.
+type oneofSubField struct {
+ fieldCommon
+ protoTypeName string // Proto type name, empty if primitive, e.g. ".google.protobuf.Duration"
+ protoType descriptor.FieldDescriptorProto_Type // Actual type enum value, e.g. descriptor.FieldDescriptorProto_TYPE_FIXED64
+ oneofTypeName string // Type name of the enclosing struct, e.g. "MessageName_FieldName"
+ fieldNumber int // Actual field number, as defined in proto, e.g. 12
+ getterDef string // Default for getters, e.g. "nil", `""` or "Default_MessageType_FieldName"
+ protoDef string // Default value as defined in the proto file, e.g "yoshi" or "5"
+ deprecated string // Deprecation comment, if any.
+}
+
+// typedNil prints a nil casted to the pointer to this field.
+// - for XXX_OneofWrappers
+func (f *oneofSubField) typedNil(g *Generator) {
+ g.P("(*", f.oneofTypeName, ")(nil),")
+}
+
+// getProtoDef returns the default value explicitly stated in the proto file, e.g "yoshi" or "5".
+func (f *oneofSubField) getProtoDef() string {
+ return f.protoDef
+}
+
+// getProtoTypeName returns the protobuf type name for the field as returned by field.GetTypeName(), e.g. ".google.protobuf.Duration".
+func (f *oneofSubField) getProtoTypeName() string {
+ return f.protoTypeName
+}
+
+// getProtoType returns the *field.Type value, e.g. descriptor.FieldDescriptorProto_TYPE_FIXED64.
+func (f *oneofSubField) getProtoType() descriptor.FieldDescriptorProto_Type {
+ return f.protoType
+}
+
+func (f *oneofSubField) getProto() *descriptor.FieldDescriptorProto {
+ return f.protoField
+}
+
+// oneofField represents the oneof on top level.
+// The alternative fields within the oneof are represented by oneofSubField.
+type oneofField struct {
+ fieldCommon
+ subFields []*oneofSubField // All the possible oneof fields
+ comment string // The full comment for the field, e.g. "// Types that are valid to be assigned to MyOneof:\n\\"
+}
+
+// decl prints the declaration of the field in the struct (if any).
+func (f *oneofField) decl(g *Generator, mc *msgCtx) {
+ comment := f.comment
+ for _, sf := range f.subFields {
+ comment += "//\t*" + sf.oneofTypeName + "\n"
+ }
+ g.P(comment, Annotate(mc.message.file, f.fullPath, f.goName), " ", f.goType, " `", f.tags, "`")
+}
+
+// getter for a oneof field will print additional discriminators and interfaces for the oneof,
+// also it prints all the getters for the sub fields.
+func (f *oneofField) getter(g *Generator, mc *msgCtx) {
+ oneof := true
+ if !oneof && !gogoproto.HasGoGetters(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
+ return
+ }
+
+ for _, sf := range f.subFields {
+ if gogoproto.IsEmbed(sf.protoField) || gogoproto.IsCustomType(sf.protoField) {
+ continue
+ }
+ if sf.deprecated != "" {
+ g.P(sf.deprecated)
+ }
+ g.generateGet(mc, sf.protoField, sf.protoType, true, sf.goName, sf.goType, f.goName, sf.oneofTypeName, sf.fullPath, sf.getterName, sf.getterDef)
+ }
+}
+
+// setter prints the setter method of the field.
+func (f *oneofField) setter(g *Generator, mc *msgCtx) {
+ // No setters for oneof yet
+}
+
+// topLevelField interface implemented by all types of fields on the top level (not oneofSubField).
+type topLevelField interface {
+ decl(g *Generator, mc *msgCtx) // print declaration within the struct
+ getter(g *Generator, mc *msgCtx) // print getter
+ setter(g *Generator, mc *msgCtx) // print setter if applicable
+}
+
+// defField interface implemented by all types of fields that can have defaults (not oneofField, but instead oneofSubField).
+type defField interface {
+ getProtoDef() string // default value explicitly stated in the proto file, e.g "yoshi" or "5"
+ getProtoName() string // proto name of a field, e.g. "field_name" or "descriptor"
+ getGoType() string // go type of the field as a string, e.g. "*int32"
+ getProtoTypeName() string // protobuf type name for the field, e.g. ".google.protobuf.Duration"
+ getProtoType() descriptor.FieldDescriptorProto_Type // *field.Type value, e.g. descriptor.FieldDescriptorProto_TYPE_FIXED64
+ getProto() *descriptor.FieldDescriptorProto
+}
+
+// generateDefaultConstants adds constants for default values if needed, which is only if the default value is.
+// explicit in the proto.
+func (g *Generator) generateDefaultConstants(mc *msgCtx, topLevelFields []topLevelField) {
+ // Collect fields that can have defaults
+ dFields := []defField{}
+ for _, pf := range topLevelFields {
+ if f, ok := pf.(*oneofField); ok {
+ for _, osf := range f.subFields {
+ dFields = append(dFields, osf)
+ }
+ continue
+ }
+ dFields = append(dFields, pf.(defField))
+ }
+ for _, df := range dFields {
+ def := df.getProtoDef()
+ if def == "" {
+ continue
+ }
+ if !gogoproto.IsNullable(df.getProto()) {
+ g.Fail("illegal default value: ", df.getProtoName(), " in ", mc.message.GetName(), " is not nullable and is thus not allowed to have a default value")
+ }
+ fieldname := g.defaultConstantName(mc.goName, df.getProtoName())
+ typename := df.getGoType()
+ if typename[0] == '*' {
+ typename = typename[1:]
+ }
+ kind := "const "
+ switch {
+ case typename == "bool":
+ case typename == "string":
+ def = strconv.Quote(def)
+ case typename == "[]byte":
+ def = "[]byte(" + strconv.Quote(unescape(def)) + ")"
+ kind = "var "
+ case def == "inf", def == "-inf", def == "nan":
+ // These names are known to, and defined by, the protocol language.
+ switch def {
+ case "inf":
+ def = "math.Inf(1)"
+ case "-inf":
+ def = "math.Inf(-1)"
+ case "nan":
+ def = "math.NaN()"
+ }
+ if df.getProtoType() == descriptor.FieldDescriptorProto_TYPE_FLOAT {
+ def = "float32(" + def + ")"
+ }
+ kind = "var "
+ case df.getProtoType() == descriptor.FieldDescriptorProto_TYPE_FLOAT:
+ if f, err := strconv.ParseFloat(def, 32); err == nil {
+ def = fmt.Sprint(float32(f))
+ }
+ case df.getProtoType() == descriptor.FieldDescriptorProto_TYPE_DOUBLE:
+ if f, err := strconv.ParseFloat(def, 64); err == nil {
+ def = fmt.Sprint(f)
+ }
+ case df.getProtoType() == descriptor.FieldDescriptorProto_TYPE_ENUM:
+ // Must be an enum. Need to construct the prefixed name.
+ obj := g.ObjectNamed(df.getProtoTypeName())
+ var enum *EnumDescriptor
+ if id, ok := obj.(*ImportedDescriptor); ok {
+ // The enum type has been publicly imported.
+ enum, _ = id.o.(*EnumDescriptor)
+ } else {
+ enum, _ = obj.(*EnumDescriptor)
+ }
+ if enum == nil {
+ log.Printf("don't know how to generate constant for %s", fieldname)
+ continue
+ }
+
+ // hunt down the actual enum corresponding to the default
+ var enumValue *descriptor.EnumValueDescriptorProto
+ for _, ev := range enum.Value {
+ if def == ev.GetName() {
+ enumValue = ev
+ }
+ }
+
+ if enumValue != nil {
+ if gogoproto.IsEnumValueCustomName(enumValue) {
+ def = gogoproto.GetEnumValueCustomName(enumValue)
+ }
+ } else {
+ g.Fail(fmt.Sprintf("could not resolve default enum value for %v.%v", g.DefaultPackageName(obj), def))
+ }
+
+ if gogoproto.EnabledGoEnumPrefix(enum.file.FileDescriptorProto, enum.EnumDescriptorProto) {
+ def = g.DefaultPackageName(obj) + enum.prefix() + def
+ } else {
+ def = g.DefaultPackageName(obj) + def
+ }
+ }
+ g.P(kind, fieldname, " ", typename, " = ", def)
+ g.file.addExport(mc.message, constOrVarSymbol{fieldname, kind, ""})
+ }
+ g.P()
+}
+
+// generateGet generates the getter for both the simpleField and oneofSubField.
+// We did not want to duplicate the code since it is quite intricate so we came
+// up with this ugly method. At least the logic is in one place. This can be reworked.
+func (g *Generator) generateGet(mc *msgCtx, protoField *descriptor.FieldDescriptorProto, protoType descriptor.FieldDescriptorProto_Type,
+ oneof bool, fname, tname, uname, oneoftname, fullpath, gname, def string) {
+ star := ""
+ if (protoType != descriptor.FieldDescriptorProto_TYPE_MESSAGE) &&
+ (protoType != descriptor.FieldDescriptorProto_TYPE_GROUP) &&
+ needsStar(protoField, g.file.proto3, mc.message != nil && mc.message.allowOneof()) && tname[0] == '*' {
+ tname = tname[1:]
+ star = "*"
+ }
+ typeDefaultIsNil := false // whether this field type's default value is a literal nil unless specified
+ switch protoType {
+ case descriptor.FieldDescriptorProto_TYPE_BYTES:
+ typeDefaultIsNil = def == "nil"
+ case descriptor.FieldDescriptorProto_TYPE_GROUP, descriptor.FieldDescriptorProto_TYPE_MESSAGE:
+ typeDefaultIsNil = gogoproto.IsNullable(protoField)
+ }
+ if isRepeated(protoField) {
+ typeDefaultIsNil = true
+ }
+ g.P("func (m *", mc.goName, ") ", Annotate(mc.message.file, fullpath, gname), "() "+tname+" {")
+ if !oneof && typeDefaultIsNil {
+ // A bytes field with no explicit default needs less generated code,
+ // as does a message or group field, or a repeated field.
+ g.P("if m != nil {")
+ g.In()
+ g.P("return m." + fname)
+ g.Out()
+ g.P("}")
+ g.P("return nil")
+ g.Out()
+ g.P("}")
+ g.P()
+ return
+ }
+ if !gogoproto.IsNullable(protoField) {
+ g.P("if m != nil {")
+ g.In()
+ g.P("return m." + fname)
+ g.Out()
+ g.P("}")
+ } else if !oneof {
+ if mc.message.proto3() {
+ g.P("if m != nil {")
+ } else {
+ g.P("if m != nil && m." + fname + " != nil {")
+ }
+ g.In()
+ g.P("return " + star + "m." + fname)
+ g.Out()
+ g.P("}")
+ } else {
+ uname := uname
+ tname := oneoftname
+ g.P("if x, ok := m.Get", uname, "().(*", tname, "); ok {")
+ g.P("return x.", fname)
+ g.P("}")
+ }
+ g.P("return ", def)
+ g.Out()
+ g.P("}")
+ g.P()
+}
+
+// generateInternalStructFields just adds the XXX_ fields to the message struct.
+func (g *Generator) generateInternalStructFields(mc *msgCtx, topLevelFields []topLevelField) {
+ if gogoproto.HasUnkeyed(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
+ g.P("XXX_NoUnkeyedLiteral\tstruct{} `json:\"-\"`") // prevent unkeyed struct literals
+ }
+ if len(mc.message.ExtensionRange) > 0 {
+ if gogoproto.HasExtensionsMap(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
+ messageset := ""
+ if opts := mc.message.Options; opts != nil && opts.GetMessageSetWireFormat() {
+ messageset = "protobuf_messageset:\"1\" "
+ }
+ g.P(g.Pkg["proto"], ".XXX_InternalExtensions `", messageset, "json:\"-\"`")
+ } else {
+ g.P("XXX_extensions\t\t[]byte `protobuf:\"bytes,0,opt\" json:\"-\"`")
+ }
+ }
+ if gogoproto.HasUnrecognized(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
+ g.P("XXX_unrecognized\t[]byte `json:\"-\"`")
+ }
+ if gogoproto.HasSizecache(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
+ g.P("XXX_sizecache\tint32 `json:\"-\"`")
+ }
+}
+
+// generateOneofFuncs adds all the utility functions for oneof, including marshalling, unmarshalling and sizer.
+func (g *Generator) generateOneofFuncs(mc *msgCtx, topLevelFields []topLevelField) {
+ ofields := []*oneofField{}
+ for _, f := range topLevelFields {
+ if o, ok := f.(*oneofField); ok {
+ ofields = append(ofields, o)
+ }
+ }
+ if len(ofields) == 0 {
+ return
+ }
+
+ // OneofFuncs
+ g.P("// XXX_OneofWrappers is for the internal use of the proto package.")
+ g.P("func (*", mc.goName, ") XXX_OneofWrappers() []interface{} {")
+ g.P("return []interface{}{")
+ for _, of := range ofields {
+ for _, sf := range of.subFields {
+ sf.typedNil(g)
+ }
+ }
+ g.P("}")
+ g.P("}")
+ g.P()
+}
+
+func (g *Generator) generateOneofDecls(mc *msgCtx, topLevelFields []topLevelField) {
+ ofields := []*oneofField{}
+ for _, f := range topLevelFields {
+ if o, ok := f.(*oneofField); ok {
+ ofields = append(ofields, o)
+ }
+ }
+ if len(ofields) == 0 {
+ return
+ }
+ // Oneof per-field types, discriminants and getters.
+ // Generate unexported named types for the discriminant interfaces.
+ // We shouldn't have to do this, but there was (~19 Aug 2015) a compiler/linker bug
+ // that was triggered by using anonymous interfaces here.
+ // TODO: Revisit this and consider reverting back to anonymous interfaces.
+ // for oi := range message.OneofDecl {
+ for _, of := range ofields {
+ dname := of.goType
+ g.P("type ", dname, " interface {")
+ g.In()
+ g.P(dname, "()")
+ if gogoproto.HasEqual(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
+ g.P(`Equal(interface{}) bool`)
+ }
+ if gogoproto.HasVerboseEqual(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
+ g.P(`VerboseEqual(interface{}) error`)
+ }
+ if gogoproto.IsMarshaler(g.file.FileDescriptorProto, mc.message.DescriptorProto) ||
+ gogoproto.IsUnsafeMarshaler(g.file.FileDescriptorProto, mc.message.DescriptorProto) ||
+ gogoproto.IsStableMarshaler(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
+ g.P(`MarshalTo([]byte) (int, error)`)
+ }
+ if gogoproto.IsSizer(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
+ g.P(`Size() int`)
+ }
+ if gogoproto.IsProtoSizer(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
+ g.P(`ProtoSize() int`)
+ }
+ if gogoproto.HasCompare(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
+ g.P(`Compare(interface{}) int`)
+ }
+ g.Out()
+ g.P("}")
+ }
+ g.P()
+ for _, of := range ofields {
+ for i, sf := range of.subFields {
+ fieldFullPath := fmt.Sprintf("%s,%d,%d", mc.message.path, messageFieldPath, i)
+ g.P("type ", Annotate(mc.message.file, fieldFullPath, sf.oneofTypeName), " struct{ ", Annotate(mc.message.file, fieldFullPath, sf.goName), " ", sf.goType, " `", sf.tags, "` }")
+ if !gogoproto.IsStdType(sf.protoField) && !gogoproto.IsCustomType(sf.protoField) && !gogoproto.IsCastType(sf.protoField) {
+ g.RecordTypeUse(sf.protoField.GetTypeName())
+ }
+ }
+ }
+ g.P()
+ for _, of := range ofields {
+ for _, sf := range of.subFields {
+ g.P("func (*", sf.oneofTypeName, ") ", of.goType, "() {}")
+ }
+ }
+ g.P()
+ for _, of := range ofields {
+ fname := of.goName
+ g.P("func (m *", mc.goName, ") Get", fname, "() ", of.goType, " {")
+ g.P("if m != nil { return m.", fname, " }")
+ g.P("return nil")
+ g.P("}")
+ }
+ g.P()
+}
+
+// generateMessageStruct adds the actual struct with it's members (but not methods) to the output.
+func (g *Generator) generateMessageStruct(mc *msgCtx, topLevelFields []topLevelField) {
+ comments := g.PrintComments(mc.message.path)
+
+ // Guarantee deprecation comments appear after user-provided comments.
+ if mc.message.GetOptions().GetDeprecated() {
+ if comments {
+ // Convention: Separate deprecation comments from original
+ // comments with an empty line.
+ g.P("//")
+ }
+ g.P(deprecationComment)
+ }
+ g.P("type ", Annotate(mc.message.file, mc.message.path, mc.goName), " struct {")
+ for _, pf := range topLevelFields {
+ pf.decl(g, mc)
+ }
+ g.generateInternalStructFields(mc, topLevelFields)
+ g.P("}")
+}
+
+// generateGetters adds getters for all fields, including oneofs and weak fields when applicable.
+func (g *Generator) generateGetters(mc *msgCtx, topLevelFields []topLevelField) {
+ for _, pf := range topLevelFields {
+ pf.getter(g, mc)
+
+ }
+}
+
+// generateSetters add setters for all fields, including oneofs and weak fields when applicable.
+func (g *Generator) generateSetters(mc *msgCtx, topLevelFields []topLevelField) {
+ for _, pf := range topLevelFields {
+ pf.setter(g, mc)
+ }
+}
+
+// generateCommonMethods adds methods to the message that are not on a per field basis.
+func (g *Generator) generateCommonMethods(mc *msgCtx) {
+ // Reset, String and ProtoMessage methods.
+ g.P("func (m *", mc.goName, ") Reset() { *m = ", mc.goName, "{} }")
+ if gogoproto.EnabledGoStringer(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
+ g.P("func (m *", mc.goName, ") String() string { return ", g.Pkg["proto"], ".CompactTextString(m) }")
+ }
+ g.P("func (*", mc.goName, ") ProtoMessage() {}")
+ var indexes []string
+ for m := mc.message; m != nil; m = m.parent {
+ indexes = append([]string{strconv.Itoa(m.index)}, indexes...)
+ }
+ g.P("func (*", mc.goName, ") Descriptor() ([]byte, []int) {")
+ g.P("return ", g.file.VarName(), ", []int{", strings.Join(indexes, ", "), "}")
+ g.P("}")
+ // TODO: Revisit the decision to use a XXX_WellKnownType method
+ // if we change proto.MessageName to work with multiple equivalents.
+ if mc.message.file.GetPackage() == "google.protobuf" && wellKnownTypes[mc.message.GetName()] {
+ g.P("func (*", mc.goName, `) XXX_WellKnownType() string { return "`, mc.message.GetName(), `" }`)
+ }
+
+ // Extension support methods
+ if len(mc.message.ExtensionRange) > 0 {
+ g.P()
+ g.P("var extRange_", mc.goName, " = []", g.Pkg["proto"], ".ExtensionRange{")
+ g.In()
+ for _, r := range mc.message.ExtensionRange {
+ end := fmt.Sprint(*r.End - 1) // make range inclusive on both ends
+ g.P("{Start: ", r.Start, ", End: ", end, "},")
+ }
+ g.Out()
+ g.P("}")
+ g.P("func (*", mc.goName, ") ExtensionRangeArray() []", g.Pkg["proto"], ".ExtensionRange {")
+ g.In()
+ g.P("return extRange_", mc.goName)
+ g.Out()
+ g.P("}")
+ g.P()
+ if !gogoproto.HasExtensionsMap(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
+ g.P("func (m *", mc.goName, ") GetExtensions() *[]byte {")
+ g.In()
+ g.P("if m.XXX_extensions == nil {")
+ g.In()
+ g.P("m.XXX_extensions = make([]byte, 0)")
+ g.Out()
+ g.P("}")
+ g.P("return &m.XXX_extensions")
+ g.Out()
+ g.P("}")
+ }
+ }
+
+ // TODO: It does not scale to keep adding another method for every
+ // operation on protos that we want to switch over to using the
+ // table-driven approach. Instead, we should only add a single method
+ // that allows getting access to the *InternalMessageInfo struct and then
+ // calling Unmarshal, Marshal, Merge, Size, and Discard directly on that.
+
+ // Wrapper for table-driven marshaling and unmarshaling.
+ g.P("func (m *", mc.goName, ") XXX_Unmarshal(b []byte) error {")
+ g.In()
+ if gogoproto.IsUnmarshaler(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
+ g.P("return m.Unmarshal(b)")
+ } else {
+ g.P("return xxx_messageInfo_", mc.goName, ".Unmarshal(m, b)")
+ }
+ g.Out()
+ g.P("}")
+
+ g.P("func (m *", mc.goName, ") XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {")
+ g.In()
+ if gogoproto.IsMarshaler(g.file.FileDescriptorProto, mc.message.DescriptorProto) ||
+ gogoproto.IsUnsafeMarshaler(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
+ if gogoproto.IsStableMarshaler(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
+ g.P("b = b[:cap(b)]")
+ g.P("n, err := m.MarshalToSizedBuffer(b)")
+ g.P("if err != nil {")
+ g.In()
+ g.P("return nil, err")
+ g.Out()
+ g.P("}")
+ g.P("return b[:n], nil")
+ } else {
+ g.P("if deterministic {")
+ g.In()
+ g.P("return xxx_messageInfo_", mc.goName, ".Marshal(b, m, deterministic)")
+ g.P("} else {")
+ g.In()
+ g.P("b = b[:cap(b)]")
+ g.P("n, err := m.MarshalToSizedBuffer(b)")
+ g.P("if err != nil {")
+ g.In()
+ g.P("return nil, err")
+ g.Out()
+ g.P("}")
+ g.Out()
+ g.P("return b[:n], nil")
+ g.Out()
+ g.P("}")
+ }
+ } else {
+ g.P("return xxx_messageInfo_", mc.goName, ".Marshal(b, m, deterministic)")
+ }
+ g.Out()
+ g.P("}")
+
+ g.P("func (m *", mc.goName, ") XXX_Merge(src ", g.Pkg["proto"], ".Message) {")
+ g.In()
+ g.P("xxx_messageInfo_", mc.goName, ".Merge(m, src)")
+ g.Out()
+ g.P("}")
+
+ g.P("func (m *", mc.goName, ") XXX_Size() int {") // avoid name clash with "Size" field in some message
+ g.In()
+ if (gogoproto.IsMarshaler(g.file.FileDescriptorProto, mc.message.DescriptorProto) ||
+ gogoproto.IsUnsafeMarshaler(g.file.FileDescriptorProto, mc.message.DescriptorProto)) &&
+ gogoproto.IsSizer(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
+ g.P("return m.Size()")
+ } else if (gogoproto.IsMarshaler(g.file.FileDescriptorProto, mc.message.DescriptorProto) ||
+ gogoproto.IsUnsafeMarshaler(g.file.FileDescriptorProto, mc.message.DescriptorProto)) &&
+ gogoproto.IsProtoSizer(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
+ g.P("return m.ProtoSize()")
+ } else {
+ g.P("return xxx_messageInfo_", mc.goName, ".Size(m)")
+ }
+ g.Out()
+ g.P("}")
+
+ g.P("func (m *", mc.goName, ") XXX_DiscardUnknown() {")
+ g.In()
+ g.P("xxx_messageInfo_", mc.goName, ".DiscardUnknown(m)")
+ g.Out()
+ g.P("}")
+
+ g.P("var xxx_messageInfo_", mc.goName, " ", g.Pkg["proto"], ".InternalMessageInfo")
+}
+
+// Generate the type and default constant definitions for this Descriptor.
+func (g *Generator) generateMessage(message *Descriptor) {
+ topLevelFields := []topLevelField{}
+ oFields := make(map[int32]*oneofField)
+ // The full type name
+ typeName := message.TypeName()
+ // The full type name, CamelCased.
+ goTypeName := CamelCaseSlice(typeName)
+
+ usedNames := make(map[string]bool)
+ for _, n := range methodNames {
+ usedNames[n] = true
+ }
+ if !gogoproto.IsProtoSizer(message.file.FileDescriptorProto, message.DescriptorProto) {
+ usedNames["Size"] = true
+ }
+
+ // allocNames finds a conflict-free variation of the given strings,
+ // consistently mutating their suffixes.
+ // It returns the same number of strings.
+ allocNames := func(ns ...string) []string {
+ Loop:
+ for {
+ for _, n := range ns {
+ if usedNames[n] {
+ for i := range ns {
+ ns[i] += "_"
+ }
+ continue Loop
+ }
+ }
+ for _, n := range ns {
+ usedNames[n] = true
+ }
+ return ns
+ }
+ }
+
+ mapFieldTypes := make(map[*descriptor.FieldDescriptorProto]string) // keep track of the map fields to be added later
+
+ for i, field := range message.Field {
+ // Allocate the getter and the field at the same time so name
+ // collisions create field/method consistent names.
+ // TODO: This allocation occurs based on the order of the fields
+ // in the proto file, meaning that a change in the field
+ // ordering can change generated Method/Field names.
+ base := CamelCase(*field.Name)
+ if gogoproto.IsCustomName(field) {
+ base = gogoproto.GetCustomName(field)
+ }
+ ns := allocNames(base, "Get"+base)
+ fieldName, fieldGetterName := ns[0], ns[1]
+
+ typename, wiretype := g.GoType(message, field)
+ jsonName := *field.Name
+ jsonTag := jsonName + ",omitempty"
+ repeatedNativeType := (!field.IsMessage() && !gogoproto.IsCustomType(field) && field.IsRepeated())
+ if !gogoproto.IsNullable(field) && !repeatedNativeType {
+ jsonTag = jsonName
+ }
+ gogoJsonTag := gogoproto.GetJsonTag(field)
+ if gogoJsonTag != nil {
+ jsonTag = *gogoJsonTag
+ }
+ gogoMoreTags := gogoproto.GetMoreTags(field)
+ moreTags := ""
+ if gogoMoreTags != nil {
+ moreTags = " " + *gogoMoreTags
+ }
+ tag := fmt.Sprintf("protobuf:%s json:%q%s", g.goTag(message, field, wiretype), jsonTag, moreTags)
+ if *field.Type == descriptor.FieldDescriptorProto_TYPE_MESSAGE && gogoproto.IsEmbed(field) {
+ fieldName = ""
+ }
+
+ oneof := field.OneofIndex != nil && message.allowOneof()
+ if oneof && oFields[*field.OneofIndex] == nil {
+ odp := message.OneofDecl[int(*field.OneofIndex)]
+ base := CamelCase(odp.GetName())
+ names := allocNames(base, "Get"+base)
+ fname, gname := names[0], names[1]
+
+ // This is the first field of a oneof we haven't seen before.
+ // Generate the union field.
+ oneofFullPath := fmt.Sprintf("%s,%d,%d", message.path, messageOneofPath, *field.OneofIndex)
+ c, ok := g.makeComments(oneofFullPath)
+ if ok {
+ c += "\n//\n"
+ }
+ c += "// Types that are valid to be assigned to " + fname + ":\n"
+ // Generate the rest of this comment later,
+ // when we've computed any disambiguation.
+
+ dname := "is" + goTypeName + "_" + fname
+ oneOftag := `protobuf_oneof:"` + odp.GetName() + `"`
+ of := oneofField{
+ fieldCommon: fieldCommon{
+ goName: fname,
+ getterName: gname,
+ goType: dname,
+ tags: oneOftag,
+ protoName: odp.GetName(),
+ fullPath: oneofFullPath,
+ protoField: field,
+ },
+ comment: c,
+ }
+ topLevelFields = append(topLevelFields, &of)
+ oFields[*field.OneofIndex] = &of
+ }
+
+ if *field.Type == descriptor.FieldDescriptorProto_TYPE_MESSAGE {
+ desc := g.ObjectNamed(field.GetTypeName())
+ if d, ok := desc.(*Descriptor); ok && d.GetOptions().GetMapEntry() {
+ m := g.GoMapType(d, field)
+ typename = m.GoType
+ mapFieldTypes[field] = typename // record for the getter generation
+
+ tag += fmt.Sprintf(" protobuf_key:%s protobuf_val:%s", m.KeyTag, m.ValueTag)
+ }
+ }
+ goTyp, _ := g.GoType(message, field)
+ fieldDeprecated := ""
+ if field.GetOptions().GetDeprecated() {
+ fieldDeprecated = deprecationComment
+ }
+ dvalue := g.getterDefault(field, goTypeName, GoTypeToName(goTyp))
+ if oneof {
+ tname := goTypeName + "_" + fieldName
+ // It is possible for this to collide with a message or enum
+ // nested in this message. Check for collisions.
+ for {
+ ok := true
+ for _, desc := range message.nested {
+ if CamelCaseSlice(desc.TypeName()) == tname {
+ ok = false
+ break
+ }
+ }
+ for _, enum := range message.enums {
+ if CamelCaseSlice(enum.TypeName()) == tname {
+ ok = false
+ break
+ }
+ }
+ if !ok {
+ tname += "_"
+ continue
+ }
+ break
+ }
+
+ oneofField := oFields[*field.OneofIndex]
+ sf := oneofSubField{
+ fieldCommon: fieldCommon{
+ goName: fieldName,
+ getterName: fieldGetterName,
+ goType: typename,
+ tags: tag,
+ protoName: field.GetName(),
+ fullPath: fmt.Sprintf("%s,%d,%d", message.path, messageFieldPath, i),
+ protoField: field,
+ },
+ protoTypeName: field.GetTypeName(),
+ fieldNumber: int(*field.Number),
+ protoType: *field.Type,
+ getterDef: dvalue,
+ protoDef: field.GetDefaultValue(),
+ oneofTypeName: tname,
+ deprecated: fieldDeprecated,
+ }
+
+ oneofField.subFields = append(oneofField.subFields, &sf)
+ if !gogoproto.IsStdType(field) && !gogoproto.IsCustomType(field) && !gogoproto.IsCastType(field) {
+ g.RecordTypeUse(field.GetTypeName())
+ }
+ continue
+ }
+
+ fieldFullPath := fmt.Sprintf("%s,%d,%d", message.path, messageFieldPath, i)
+ c, ok := g.makeComments(fieldFullPath)
+ if ok {
+ c += "\n"
+ }
+ rf := simpleField{
+ fieldCommon: fieldCommon{
+ goName: fieldName,
+ getterName: fieldGetterName,
+ goType: typename,
+ tags: tag,
+ protoName: field.GetName(),
+ fullPath: fieldFullPath,
+ protoField: field,
+ },
+ protoTypeName: field.GetTypeName(),
+ protoType: *field.Type,
+ deprecated: fieldDeprecated,
+ getterDef: dvalue,
+ protoDef: field.GetDefaultValue(),
+ comment: c,
+ }
+ var pf topLevelField = &rf
+
+ topLevelFields = append(topLevelFields, pf)
+
+ if gogoproto.HasTypeDecl(message.file.FileDescriptorProto, message.DescriptorProto) {
+ if !gogoproto.IsStdType(field) && !gogoproto.IsCustomType(field) && !gogoproto.IsCastType(field) {
+ g.RecordTypeUse(field.GetTypeName())
+ }
+ } else {
+ // Even if the type does not need to be generated, we need to iterate
+ // over all its fields to be able to mark as used any imported types
+ // used by those fields.
+ for _, mfield := range message.Field {
+ if !gogoproto.IsStdType(mfield) && !gogoproto.IsCustomType(mfield) && !gogoproto.IsCastType(mfield) {
+ g.RecordTypeUse(mfield.GetTypeName())
+ }
+ }
+ }
+ }
+
+ mc := &msgCtx{
+ goName: goTypeName,
+ message: message,
+ }
+
+ if gogoproto.HasTypeDecl(message.file.FileDescriptorProto, message.DescriptorProto) {
+ g.generateMessageStruct(mc, topLevelFields)
+ g.P()
+ }
+ g.generateCommonMethods(mc)
+ g.P()
+ g.generateDefaultConstants(mc, topLevelFields)
+ g.P()
+ g.generateOneofDecls(mc, topLevelFields)
+ g.P()
+ g.generateGetters(mc, topLevelFields)
+ g.P()
+ g.generateSetters(mc, topLevelFields)
+ g.P()
+ g.generateOneofFuncs(mc, topLevelFields)
+ g.P()
+
+ var oneofTypes []string
+ for _, f := range topLevelFields {
+ if of, ok := f.(*oneofField); ok {
+ for _, osf := range of.subFields {
+ oneofTypes = append(oneofTypes, osf.oneofTypeName)
+ }
+ }
+ }
+
+ opts := message.Options
+ ms := &messageSymbol{
+ sym: goTypeName,
+ hasExtensions: len(message.ExtensionRange) > 0,
+ isMessageSet: opts != nil && opts.GetMessageSetWireFormat(),
+ oneofTypes: oneofTypes,
+ }
+ g.file.addExport(message, ms)
+
+ for _, ext := range message.ext {
+ g.generateExtension(ext)
+ }
+
+ fullName := strings.Join(message.TypeName(), ".")
+ if g.file.Package != nil {
+ fullName = *g.file.Package + "." + fullName
+ }
+
+ g.addInitf("%s.RegisterType((*%s)(nil), %q)", g.Pkg["proto"], goTypeName, fullName)
+ if gogoproto.ImportsGoGoProto(g.file.FileDescriptorProto) && gogoproto.RegistersGolangProto(g.file.FileDescriptorProto) {
+ g.addInitf("%s.RegisterType((*%s)(nil), %q)", g.Pkg["golang_proto"], goTypeName, fullName)
+ }
+ if gogoproto.HasMessageName(g.file.FileDescriptorProto, message.DescriptorProto) {
+ g.P("func (*", goTypeName, ") XXX_MessageName() string {")
+ g.In()
+ g.P("return ", strconv.Quote(fullName))
+ g.Out()
+ g.P("}")
+ }
+ // Register types for native map types.
+ for _, k := range mapFieldKeys(mapFieldTypes) {
+ fullName := strings.TrimPrefix(*k.TypeName, ".")
+ g.addInitf("%s.RegisterMapType((%s)(nil), %q)", g.Pkg["proto"], mapFieldTypes[k], fullName)
+ if gogoproto.ImportsGoGoProto(g.file.FileDescriptorProto) && gogoproto.RegistersGolangProto(g.file.FileDescriptorProto) {
+ g.addInitf("%s.RegisterMapType((%s)(nil), %q)", g.Pkg["golang_proto"], mapFieldTypes[k], fullName)
+ }
+ }
+}
+
+type byTypeName []*descriptor.FieldDescriptorProto
+
+func (a byTypeName) Len() int { return len(a) }
+func (a byTypeName) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
+func (a byTypeName) Less(i, j int) bool { return *a[i].TypeName < *a[j].TypeName }
+
+// mapFieldKeys returns the keys of m in a consistent order.
+func mapFieldKeys(m map[*descriptor.FieldDescriptorProto]string) []*descriptor.FieldDescriptorProto {
+ keys := make([]*descriptor.FieldDescriptorProto, 0, len(m))
+ for k := range m {
+ keys = append(keys, k)
+ }
+ sort.Sort(byTypeName(keys))
+ return keys
+}
+
+var escapeChars = [256]byte{
+ 'a': '\a', 'b': '\b', 'f': '\f', 'n': '\n', 'r': '\r', 't': '\t', 'v': '\v', '\\': '\\', '"': '"', '\'': '\'', '?': '?',
+}
+
+// unescape reverses the "C" escaping that protoc does for default values of bytes fields.
+// It is best effort in that it effectively ignores malformed input. Seemingly invalid escape
+// sequences are conveyed, unmodified, into the decoded result.
+func unescape(s string) string {
+ // NB: Sadly, we can't use strconv.Unquote because protoc will escape both
+ // single and double quotes, but strconv.Unquote only allows one or the
+ // other (based on actual surrounding quotes of its input argument).
+
+ var out []byte
+ for len(s) > 0 {
+ // regular character, or too short to be valid escape
+ if s[0] != '\\' || len(s) < 2 {
+ out = append(out, s[0])
+ s = s[1:]
+ } else if c := escapeChars[s[1]]; c != 0 {
+ // escape sequence
+ out = append(out, c)
+ s = s[2:]
+ } else if s[1] == 'x' || s[1] == 'X' {
+ // hex escape, e.g. "\x80
+ if len(s) < 4 {
+ // too short to be valid
+ out = append(out, s[:2]...)
+ s = s[2:]
+ continue
+ }
+ v, err := strconv.ParseUint(s[2:4], 16, 8)
+ if err != nil {
+ out = append(out, s[:4]...)
+ } else {
+ out = append(out, byte(v))
+ }
+ s = s[4:]
+ } else if '0' <= s[1] && s[1] <= '7' {
+ // octal escape, can vary from 1 to 3 octal digits; e.g., "\0" "\40" or "\164"
+ // so consume up to 2 more bytes or up to end-of-string
+ n := len(s[1:]) - len(strings.TrimLeft(s[1:], "01234567"))
+ if n > 3 {
+ n = 3
+ }
+ v, err := strconv.ParseUint(s[1:1+n], 8, 8)
+ if err != nil {
+ out = append(out, s[:1+n]...)
+ } else {
+ out = append(out, byte(v))
+ }
+ s = s[1+n:]
+ } else {
+ // bad escape, just propagate the slash as-is
+ out = append(out, s[0])
+ s = s[1:]
+ }
+ }
+
+ return string(out)
+}
+
+func (g *Generator) generateExtension(ext *ExtensionDescriptor) {
+ ccTypeName := ext.DescName()
+
+ extObj := g.ObjectNamed(*ext.Extendee)
+ var extDesc *Descriptor
+ if id, ok := extObj.(*ImportedDescriptor); ok {
+ // This is extending a publicly imported message.
+ // We need the underlying type for goTag.
+ extDesc = id.o.(*Descriptor)
+ } else {
+ extDesc = extObj.(*Descriptor)
+ }
+ extendedType := "*" + g.TypeName(extObj) // always use the original
+ field := ext.FieldDescriptorProto
+ fieldType, wireType := g.GoType(ext.parent, field)
+ tag := g.goTag(extDesc, field, wireType)
+ g.RecordTypeUse(*ext.Extendee)
+ if n := ext.FieldDescriptorProto.TypeName; n != nil {
+ // foreign extension type
+ g.RecordTypeUse(*n)
+ }
+
+ typeName := ext.TypeName()
+
+ // Special case for proto2 message sets: If this extension is extending
+ // proto2.bridge.MessageSet, and its final name component is "message_set_extension",
+ // then drop that last component.
+ //
+ // TODO: This should be implemented in the text formatter rather than the generator.
+ // In addition, the situation for when to apply this special case is implemented
+ // differently in other languages:
+ // https://github.com/google/protobuf/blob/aff10976/src/google/protobuf/text_format.cc#L1560
+ if extDesc.GetOptions().GetMessageSetWireFormat() && typeName[len(typeName)-1] == "message_set_extension" {
+ typeName = typeName[:len(typeName)-1]
+ }
+
+ // For text formatting, the package must be exactly what the .proto file declares,
+ // ignoring overrides such as the go_package option, and with no dot/underscore mapping.
+ extName := strings.Join(typeName, ".")
+ if g.file.Package != nil {
+ extName = *g.file.Package + "." + extName
+ }
+
+ g.P("var ", ccTypeName, " = &", g.Pkg["proto"], ".ExtensionDesc{")
+ g.In()
+ g.P("ExtendedType: (", extendedType, ")(nil),")
+ g.P("ExtensionType: (", fieldType, ")(nil),")
+ g.P("Field: ", field.Number, ",")
+ g.P(`Name: "`, extName, `",`)
+ g.P("Tag: ", tag, ",")
+ g.P(`Filename: "`, g.file.GetName(), `",`)
+
+ g.Out()
+ g.P("}")
+ g.P()
+
+ g.addInitf("%s.RegisterExtension(%s)", g.Pkg["proto"], ext.DescName())
+
+ g.file.addExport(ext, constOrVarSymbol{ccTypeName, "var", ""})
+}
+
+func (g *Generator) generateInitFunction() {
+ if len(g.init) == 0 {
+ return
+ }
+ g.P("func init() {")
+ g.In()
+ for _, l := range g.init {
+ g.P(l)
+ }
+ g.Out()
+ g.P("}")
+ g.init = nil
+}
+
+func (g *Generator) generateFileDescriptor(file *FileDescriptor) {
+ // Make a copy and trim source_code_info data.
+ // TODO: Trim this more when we know exactly what we need.
+ pb := proto.Clone(file.FileDescriptorProto).(*descriptor.FileDescriptorProto)
+ pb.SourceCodeInfo = nil
+
+ b, err := proto.Marshal(pb)
+ if err != nil {
+ g.Fail(err.Error())
+ }
+
+ var buf bytes.Buffer
+ w, _ := gzip.NewWriterLevel(&buf, gzip.BestCompression)
+ w.Write(b)
+ w.Close()
+ b = buf.Bytes()
+
+ v := file.VarName()
+ g.P()
+ g.P("func init() { ", g.Pkg["proto"], ".RegisterFile(", strconv.Quote(*file.Name), ", ", v, ") }")
+ if gogoproto.ImportsGoGoProto(g.file.FileDescriptorProto) && gogoproto.RegistersGolangProto(g.file.FileDescriptorProto) {
+ g.P("func init() { ", g.Pkg["golang_proto"], ".RegisterFile(", strconv.Quote(*file.Name), ", ", v, ") }")
+ }
+ g.P("var ", v, " = []byte{")
+ g.In()
+ g.P("// ", len(b), " bytes of a gzipped FileDescriptorProto")
+ for len(b) > 0 {
+ n := 16
+ if n > len(b) {
+ n = len(b)
+ }
+
+ s := ""
+ for _, c := range b[:n] {
+ s += fmt.Sprintf("0x%02x,", c)
+ }
+ g.P(s)
+
+ b = b[n:]
+ }
+ g.Out()
+ g.P("}")
+}
+
+func (g *Generator) generateEnumRegistration(enum *EnumDescriptor) {
+ // // We always print the full (proto-world) package name here.
+ pkg := enum.File().GetPackage()
+ if pkg != "" {
+ pkg += "."
+ }
+ // The full type name
+ typeName := enum.TypeName()
+ // The full type name, CamelCased.
+ ccTypeName := CamelCaseSlice(typeName)
+ g.addInitf("%s.RegisterEnum(%q, %[3]s_name, %[3]s_value)", g.Pkg["proto"], pkg+ccTypeName, ccTypeName)
+ if gogoproto.ImportsGoGoProto(g.file.FileDescriptorProto) && gogoproto.RegistersGolangProto(g.file.FileDescriptorProto) {
+ g.addInitf("%s.RegisterEnum(%q, %[3]s_name, %[3]s_value)", g.Pkg["golang_proto"], pkg+ccTypeName, ccTypeName)
+ }
+}
+
+// And now lots of helper functions.
+
+// Is c an ASCII lower-case letter?
+func isASCIILower(c byte) bool {
+ return 'a' <= c && c <= 'z'
+}
+
+// Is c an ASCII digit?
+func isASCIIDigit(c byte) bool {
+ return '0' <= c && c <= '9'
+}
+
+// CamelCase returns the CamelCased name.
+// If there is an interior underscore followed by a lower case letter,
+// drop the underscore and convert the letter to upper case.
+// There is a remote possibility of this rewrite causing a name collision,
+// but it's so remote we're prepared to pretend it's nonexistent - since the
+// C++ generator lowercases names, it's extremely unlikely to have two fields
+// with different capitalizations.
+// In short, _my_field_name_2 becomes XMyFieldName_2.
+func CamelCase(s string) string {
+ if s == "" {
+ return ""
+ }
+ t := make([]byte, 0, 32)
+ i := 0
+ if s[0] == '_' {
+ // Need a capital letter; drop the '_'.
+ t = append(t, 'X')
+ i++
+ }
+ // Invariant: if the next letter is lower case, it must be converted
+ // to upper case.
+ // That is, we process a word at a time, where words are marked by _ or
+ // upper case letter. Digits are treated as words.
+ for ; i < len(s); i++ {
+ c := s[i]
+ if c == '_' && i+1 < len(s) && isASCIILower(s[i+1]) {
+ continue // Skip the underscore in s.
+ }
+ if isASCIIDigit(c) {
+ t = append(t, c)
+ continue
+ }
+ // Assume we have a letter now - if not, it's a bogus identifier.
+ // The next word is a sequence of characters that must start upper case.
+ if isASCIILower(c) {
+ c ^= ' ' // Make it a capital letter.
+ }
+ t = append(t, c) // Guaranteed not lower case.
+ // Accept lower case sequence that follows.
+ for i+1 < len(s) && isASCIILower(s[i+1]) {
+ i++
+ t = append(t, s[i])
+ }
+ }
+ return string(t)
+}
+
+// CamelCaseSlice is like CamelCase, but the argument is a slice of strings to
+// be joined with "_".
+func CamelCaseSlice(elem []string) string { return CamelCase(strings.Join(elem, "_")) }
+
+// dottedSlice turns a sliced name into a dotted name.
+func dottedSlice(elem []string) string { return strings.Join(elem, ".") }
+
+// Is this field optional?
+func isOptional(field *descriptor.FieldDescriptorProto) bool {
+ return field.Label != nil && *field.Label == descriptor.FieldDescriptorProto_LABEL_OPTIONAL
+}
+
+// Is this field required?
+func isRequired(field *descriptor.FieldDescriptorProto) bool {
+ return field.Label != nil && *field.Label == descriptor.FieldDescriptorProto_LABEL_REQUIRED
+}
+
+// Is this field repeated?
+func isRepeated(field *descriptor.FieldDescriptorProto) bool {
+ return field.Label != nil && *field.Label == descriptor.FieldDescriptorProto_LABEL_REPEATED
+}
+
+// Is this field a scalar numeric type?
+func IsScalar(field *descriptor.FieldDescriptorProto) bool {
+ if field.Type == nil {
+ return false
+ }
+ switch *field.Type {
+ case descriptor.FieldDescriptorProto_TYPE_DOUBLE,
+ descriptor.FieldDescriptorProto_TYPE_FLOAT,
+ descriptor.FieldDescriptorProto_TYPE_INT64,
+ descriptor.FieldDescriptorProto_TYPE_UINT64,
+ descriptor.FieldDescriptorProto_TYPE_INT32,
+ descriptor.FieldDescriptorProto_TYPE_FIXED64,
+ descriptor.FieldDescriptorProto_TYPE_FIXED32,
+ descriptor.FieldDescriptorProto_TYPE_BOOL,
+ descriptor.FieldDescriptorProto_TYPE_UINT32,
+ descriptor.FieldDescriptorProto_TYPE_ENUM,
+ descriptor.FieldDescriptorProto_TYPE_SFIXED32,
+ descriptor.FieldDescriptorProto_TYPE_SFIXED64,
+ descriptor.FieldDescriptorProto_TYPE_SINT32,
+ descriptor.FieldDescriptorProto_TYPE_SINT64:
+ return true
+ default:
+ return false
+ }
+}
+
+// badToUnderscore is the mapping function used to generate Go names from package names,
+// which can be dotted in the input .proto file. It replaces non-identifier characters such as
+// dot or dash with underscore.
+func badToUnderscore(r rune) rune {
+ if unicode.IsLetter(r) || unicode.IsDigit(r) || r == '_' {
+ return r
+ }
+ return '_'
+}
+
+// baseName returns the last path element of the name, with the last dotted suffix removed.
+func baseName(name string) string {
+ // First, find the last element
+ if i := strings.LastIndex(name, "/"); i >= 0 {
+ name = name[i+1:]
+ }
+ // Now drop the suffix
+ if i := strings.LastIndex(name, "."); i >= 0 {
+ name = name[0:i]
+ }
+ return name
+}
+
+// The SourceCodeInfo message describes the location of elements of a parsed
+// .proto file by way of a "path", which is a sequence of integers that
+// describe the route from a FileDescriptorProto to the relevant submessage.
+// The path alternates between a field number of a repeated field, and an index
+// into that repeated field. The constants below define the field numbers that
+// are used.
+//
+// See descriptor.proto for more information about this.
+const (
+ // tag numbers in FileDescriptorProto
+ packagePath = 2 // package
+ messagePath = 4 // message_type
+ enumPath = 5 // enum_type
+ // tag numbers in DescriptorProto
+ messageFieldPath = 2 // field
+ messageMessagePath = 3 // nested_type
+ messageEnumPath = 4 // enum_type
+ messageOneofPath = 8 // oneof_decl
+ // tag numbers in EnumDescriptorProto
+ enumValuePath = 2 // value
+)
+
+var supportTypeAliases bool
+
+func init() {
+ for _, tag := range build.Default.ReleaseTags {
+ if tag == "go1.9" {
+ supportTypeAliases = true
+ return
+ }
+ }
+}
diff --git a/vendor/github.com/gogo/protobuf/protoc-gen-gogo/generator/helper.go b/vendor/github.com/gogo/protobuf/protoc-gen-gogo/generator/helper.go
new file mode 100644
index 00000000000..7091e281cb1
--- /dev/null
+++ b/vendor/github.com/gogo/protobuf/protoc-gen-gogo/generator/helper.go
@@ -0,0 +1,461 @@
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2013, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// 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.
+//
+// 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 generator
+
+import (
+ "bytes"
+ "go/parser"
+ "go/printer"
+ "go/token"
+ "path"
+ "strings"
+
+ "github.com/gogo/protobuf/gogoproto"
+ "github.com/gogo/protobuf/proto"
+ descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
+ plugin "github.com/gogo/protobuf/protoc-gen-gogo/plugin"
+)
+
+func (d *FileDescriptor) Messages() []*Descriptor {
+ return d.desc
+}
+
+func (d *FileDescriptor) Enums() []*EnumDescriptor {
+ return d.enum
+}
+
+func (d *Descriptor) IsGroup() bool {
+ return d.group
+}
+
+func (g *Generator) IsGroup(field *descriptor.FieldDescriptorProto) bool {
+ if d, ok := g.typeNameToObject[field.GetTypeName()].(*Descriptor); ok {
+ return d.IsGroup()
+ }
+ return false
+}
+
+func (g *Generator) TypeNameByObject(typeName string) Object {
+ o, ok := g.typeNameToObject[typeName]
+ if !ok {
+ g.Fail("can't find object with type", typeName)
+ }
+ return o
+}
+
+func (g *Generator) OneOfTypeName(message *Descriptor, field *descriptor.FieldDescriptorProto) string {
+ typeName := message.TypeName()
+ ccTypeName := CamelCaseSlice(typeName)
+ fieldName := g.GetOneOfFieldName(message, field)
+ tname := ccTypeName + "_" + fieldName
+ // It is possible for this to collide with a message or enum
+ // nested in this message. Check for collisions.
+ ok := true
+ for _, desc := range message.nested {
+ if strings.Join(desc.TypeName(), "_") == tname {
+ ok = false
+ break
+ }
+ }
+ for _, enum := range message.enums {
+ if strings.Join(enum.TypeName(), "_") == tname {
+ ok = false
+ break
+ }
+ }
+ if !ok {
+ tname += "_"
+ }
+ return tname
+}
+
+type PluginImports interface {
+ NewImport(pkg string) Single
+ GenerateImports(file *FileDescriptor)
+}
+
+type pluginImports struct {
+ generator *Generator
+ singles []Single
+}
+
+func NewPluginImports(generator *Generator) *pluginImports {
+ return &pluginImports{generator, make([]Single, 0)}
+}
+
+func (this *pluginImports) NewImport(pkg string) Single {
+ imp := newImportedPackage(this.generator.ImportPrefix, pkg)
+ this.singles = append(this.singles, imp)
+ return imp
+}
+
+func (this *pluginImports) GenerateImports(file *FileDescriptor) {
+ for _, s := range this.singles {
+ if s.IsUsed() {
+ this.generator.PrintImport(GoPackageName(s.Name()), GoImportPath(s.Location()))
+ }
+ }
+}
+
+type Single interface {
+ Use() string
+ IsUsed() bool
+ Name() string
+ Location() string
+}
+
+type importedPackage struct {
+ used bool
+ pkg string
+ name string
+ importPrefix string
+}
+
+func newImportedPackage(importPrefix string, pkg string) *importedPackage {
+ return &importedPackage{
+ pkg: pkg,
+ importPrefix: importPrefix,
+ }
+}
+
+func (this *importedPackage) Use() string {
+ if !this.used {
+ this.name = string(cleanPackageName(this.pkg))
+ this.used = true
+ }
+ return this.name
+}
+
+func (this *importedPackage) IsUsed() bool {
+ return this.used
+}
+
+func (this *importedPackage) Name() string {
+ return this.name
+}
+
+func (this *importedPackage) Location() string {
+ return this.importPrefix + this.pkg
+}
+
+func (g *Generator) GetFieldName(message *Descriptor, field *descriptor.FieldDescriptorProto) string {
+ goTyp, _ := g.GoType(message, field)
+ fieldname := CamelCase(*field.Name)
+ if gogoproto.IsCustomName(field) {
+ fieldname = gogoproto.GetCustomName(field)
+ }
+ if gogoproto.IsEmbed(field) {
+ fieldname = EmbedFieldName(goTyp)
+ }
+ if field.OneofIndex != nil {
+ fieldname = message.OneofDecl[int(*field.OneofIndex)].GetName()
+ fieldname = CamelCase(fieldname)
+ }
+ for _, f := range methodNames {
+ if f == fieldname {
+ return fieldname + "_"
+ }
+ }
+ if !gogoproto.IsProtoSizer(message.file.FileDescriptorProto, message.DescriptorProto) {
+ if fieldname == "Size" {
+ return fieldname + "_"
+ }
+ }
+ return fieldname
+}
+
+func (g *Generator) GetOneOfFieldName(message *Descriptor, field *descriptor.FieldDescriptorProto) string {
+ goTyp, _ := g.GoType(message, field)
+ fieldname := CamelCase(*field.Name)
+ if gogoproto.IsCustomName(field) {
+ fieldname = gogoproto.GetCustomName(field)
+ }
+ if gogoproto.IsEmbed(field) {
+ fieldname = EmbedFieldName(goTyp)
+ }
+ for _, f := range methodNames {
+ if f == fieldname {
+ return fieldname + "_"
+ }
+ }
+ if !gogoproto.IsProtoSizer(message.file.FileDescriptorProto, message.DescriptorProto) {
+ if fieldname == "Size" {
+ return fieldname + "_"
+ }
+ }
+ return fieldname
+}
+
+func (g *Generator) IsMap(field *descriptor.FieldDescriptorProto) bool {
+ if !field.IsMessage() {
+ return false
+ }
+ byName := g.ObjectNamed(field.GetTypeName())
+ desc, ok := byName.(*Descriptor)
+ if byName == nil || !ok || !desc.GetOptions().GetMapEntry() {
+ return false
+ }
+ return true
+}
+
+func (g *Generator) GetMapKeyField(field, keyField *descriptor.FieldDescriptorProto) *descriptor.FieldDescriptorProto {
+ if !gogoproto.IsCastKey(field) {
+ return keyField
+ }
+ keyField = proto.Clone(keyField).(*descriptor.FieldDescriptorProto)
+ if keyField.Options == nil {
+ keyField.Options = &descriptor.FieldOptions{}
+ }
+ keyType := gogoproto.GetCastKey(field)
+ if err := proto.SetExtension(keyField.Options, gogoproto.E_Casttype, &keyType); err != nil {
+ g.Fail(err.Error())
+ }
+ return keyField
+}
+
+func (g *Generator) GetMapValueField(field, valField *descriptor.FieldDescriptorProto) *descriptor.FieldDescriptorProto {
+ if gogoproto.IsCustomType(field) && gogoproto.IsCastValue(field) {
+ g.Fail("cannot have a customtype and casttype: ", field.String())
+ }
+ valField = proto.Clone(valField).(*descriptor.FieldDescriptorProto)
+ if valField.Options == nil {
+ valField.Options = &descriptor.FieldOptions{}
+ }
+
+ stdtime := gogoproto.IsStdTime(field)
+ if stdtime {
+ if err := proto.SetExtension(valField.Options, gogoproto.E_Stdtime, &stdtime); err != nil {
+ g.Fail(err.Error())
+ }
+ }
+
+ stddur := gogoproto.IsStdDuration(field)
+ if stddur {
+ if err := proto.SetExtension(valField.Options, gogoproto.E_Stdduration, &stddur); err != nil {
+ g.Fail(err.Error())
+ }
+ }
+
+ wktptr := gogoproto.IsWktPtr(field)
+ if wktptr {
+ if err := proto.SetExtension(valField.Options, gogoproto.E_Wktpointer, &wktptr); err != nil {
+ g.Fail(err.Error())
+ }
+ }
+
+ if valType := gogoproto.GetCastValue(field); len(valType) > 0 {
+ if err := proto.SetExtension(valField.Options, gogoproto.E_Casttype, &valType); err != nil {
+ g.Fail(err.Error())
+ }
+ }
+ if valType := gogoproto.GetCustomType(field); len(valType) > 0 {
+ if err := proto.SetExtension(valField.Options, gogoproto.E_Customtype, &valType); err != nil {
+ g.Fail(err.Error())
+ }
+ }
+
+ nullable := gogoproto.IsNullable(field)
+ if err := proto.SetExtension(valField.Options, gogoproto.E_Nullable, &nullable); err != nil {
+ g.Fail(err.Error())
+ }
+ return valField
+}
+
+// GoMapValueTypes returns the map value Go type and the alias map value Go type (for casting), taking into
+// account whether the map is nullable or the value is a message.
+func GoMapValueTypes(mapField, valueField *descriptor.FieldDescriptorProto, goValueType, goValueAliasType string) (nullable bool, outGoType string, outGoAliasType string) {
+ nullable = gogoproto.IsNullable(mapField) && (valueField.IsMessage() || gogoproto.IsCustomType(mapField))
+ if nullable {
+ // ensure the non-aliased Go value type is a pointer for consistency
+ if strings.HasPrefix(goValueType, "*") {
+ outGoType = goValueType
+ } else {
+ outGoType = "*" + goValueType
+ }
+ outGoAliasType = goValueAliasType
+ } else {
+ outGoType = strings.Replace(goValueType, "*", "", 1)
+ outGoAliasType = strings.Replace(goValueAliasType, "*", "", 1)
+ }
+ return
+}
+
+func GoTypeToName(goTyp string) string {
+ return strings.Replace(strings.Replace(goTyp, "*", "", -1), "[]", "", -1)
+}
+
+func EmbedFieldName(goTyp string) string {
+ goTyp = GoTypeToName(goTyp)
+ goTyps := strings.Split(goTyp, ".")
+ if len(goTyps) == 1 {
+ return goTyp
+ }
+ if len(goTyps) == 2 {
+ return goTyps[1]
+ }
+ panic("unreachable")
+}
+
+func (g *Generator) GeneratePlugin(p Plugin) {
+ plugins = []Plugin{p}
+ p.Init(g)
+ // Generate the output. The generator runs for every file, even the files
+ // that we don't generate output for, so that we can collate the full list
+ // of exported symbols to support public imports.
+ genFileMap := make(map[*FileDescriptor]bool, len(g.genFiles))
+ for _, file := range g.genFiles {
+ genFileMap[file] = true
+ }
+ for _, file := range g.allFiles {
+ g.Reset()
+ g.writeOutput = genFileMap[file]
+ g.generatePlugin(file, p)
+ if !g.writeOutput {
+ continue
+ }
+ g.Response.File = append(g.Response.File, &plugin.CodeGeneratorResponse_File{
+ Name: proto.String(file.goFileName(g.pathType)),
+ Content: proto.String(g.String()),
+ })
+ }
+}
+
+func (g *Generator) SetFile(filename string) {
+ g.file = g.fileByName(filename)
+}
+
+func (g *Generator) generatePlugin(file *FileDescriptor, p Plugin) {
+ g.writtenImports = make(map[string]bool)
+ g.usedPackages = make(map[GoImportPath]bool)
+ g.packageNames = make(map[GoImportPath]GoPackageName)
+ g.usedPackageNames = make(map[GoPackageName]bool)
+ g.addedImports = make(map[GoImportPath]bool)
+ g.file = file
+
+ // Run the plugins before the imports so we know which imports are necessary.
+ p.Generate(file)
+
+ // Generate header and imports last, though they appear first in the output.
+ rem := g.Buffer
+ g.Buffer = new(bytes.Buffer)
+ g.generateHeader()
+ // p.GenerateImports(g.file)
+ g.generateImports()
+ if !g.writeOutput {
+ return
+ }
+ g.Write(rem.Bytes())
+
+ // Reformat generated code.
+ contents := string(g.Buffer.Bytes())
+ fset := token.NewFileSet()
+ ast, err := parser.ParseFile(fset, "", g, parser.ParseComments)
+ if err != nil {
+ g.Fail("bad Go source code was generated:", contents, err.Error())
+ return
+ }
+ g.Reset()
+ err = (&printer.Config{Mode: printer.TabIndent | printer.UseSpaces, Tabwidth: 8}).Fprint(g, fset, ast)
+ if err != nil {
+ g.Fail("generated Go source code could not be reformatted:", err.Error())
+ }
+}
+
+func GetCustomType(field *descriptor.FieldDescriptorProto) (packageName string, typ string, err error) {
+ return getCustomType(field)
+}
+
+func getCustomType(field *descriptor.FieldDescriptorProto) (packageName string, typ string, err error) {
+ if field.Options != nil {
+ var v interface{}
+ v, err = proto.GetExtension(field.Options, gogoproto.E_Customtype)
+ if err == nil && v.(*string) != nil {
+ ctype := *(v.(*string))
+ packageName, typ = splitCPackageType(ctype)
+ return packageName, typ, nil
+ }
+ }
+ return "", "", err
+}
+
+func splitCPackageType(ctype string) (packageName string, typ string) {
+ ss := strings.Split(ctype, ".")
+ if len(ss) == 1 {
+ return "", ctype
+ }
+ packageName = strings.Join(ss[0:len(ss)-1], ".")
+ typeName := ss[len(ss)-1]
+ importStr := strings.Map(badToUnderscore, packageName)
+ typ = importStr + "." + typeName
+ return packageName, typ
+}
+
+func getCastType(field *descriptor.FieldDescriptorProto) (packageName string, typ string, err error) {
+ if field.Options != nil {
+ var v interface{}
+ v, err = proto.GetExtension(field.Options, gogoproto.E_Casttype)
+ if err == nil && v.(*string) != nil {
+ ctype := *(v.(*string))
+ packageName, typ = splitCPackageType(ctype)
+ return packageName, typ, nil
+ }
+ }
+ return "", "", err
+}
+
+func FileName(file *FileDescriptor) string {
+ fname := path.Base(file.FileDescriptorProto.GetName())
+ fname = strings.Replace(fname, ".proto", "", -1)
+ fname = strings.Replace(fname, "-", "_", -1)
+ fname = strings.Replace(fname, ".", "_", -1)
+ return CamelCase(fname)
+}
+
+func (g *Generator) AllFiles() *descriptor.FileDescriptorSet {
+ set := &descriptor.FileDescriptorSet{}
+ set.File = make([]*descriptor.FileDescriptorProto, len(g.allFiles))
+ for i := range g.allFiles {
+ set.File[i] = g.allFiles[i].FileDescriptorProto
+ }
+ return set
+}
+
+func (d *Descriptor) Path() string {
+ return d.path
+}
+
+func (g *Generator) useTypes() string {
+ pkg := strings.Map(badToUnderscore, "github.com/gogo/protobuf/types")
+ g.customImports = append(g.customImports, "github.com/gogo/protobuf/types")
+ return pkg
+}
+
+func (d *FileDescriptor) GoPackageName() string {
+ return string(d.packageName)
+}
diff --git a/vendor/github.com/gogo/protobuf/protoc-gen-gogo/generator/internal/remap/remap.go b/vendor/github.com/gogo/protobuf/protoc-gen-gogo/generator/internal/remap/remap.go
new file mode 100644
index 00000000000..a9b61036cc0
--- /dev/null
+++ b/vendor/github.com/gogo/protobuf/protoc-gen-gogo/generator/internal/remap/remap.go
@@ -0,0 +1,117 @@
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2017 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// 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 remap handles tracking the locations of Go tokens in a source text
+across a rewrite by the Go formatter.
+*/
+package remap
+
+import (
+ "fmt"
+ "go/scanner"
+ "go/token"
+)
+
+// A Location represents a span of byte offsets in the source text.
+type Location struct {
+ Pos, End int // End is exclusive
+}
+
+// A Map represents a mapping between token locations in an input source text
+// and locations in the correspnding output text.
+type Map map[Location]Location
+
+// Find reports whether the specified span is recorded by m, and if so returns
+// the new location it was mapped to. If the input span was not found, the
+// returned location is the same as the input.
+func (m Map) Find(pos, end int) (Location, bool) {
+ key := Location{
+ Pos: pos,
+ End: end,
+ }
+ if loc, ok := m[key]; ok {
+ return loc, true
+ }
+ return key, false
+}
+
+func (m Map) add(opos, oend, npos, nend int) {
+ m[Location{Pos: opos, End: oend}] = Location{Pos: npos, End: nend}
+}
+
+// Compute constructs a location mapping from input to output. An error is
+// reported if any of the tokens of output cannot be mapped.
+func Compute(input, output []byte) (Map, error) {
+ itok := tokenize(input)
+ otok := tokenize(output)
+ if len(itok) != len(otok) {
+ return nil, fmt.Errorf("wrong number of tokens, %d ≠ %d", len(itok), len(otok))
+ }
+ m := make(Map)
+ for i, ti := range itok {
+ to := otok[i]
+ if ti.Token != to.Token {
+ return nil, fmt.Errorf("token %d type mismatch: %s ≠ %s", i+1, ti, to)
+ }
+ m.add(ti.pos, ti.end, to.pos, to.end)
+ }
+ return m, nil
+}
+
+// tokinfo records the span and type of a source token.
+type tokinfo struct {
+ pos, end int
+ token.Token
+}
+
+func tokenize(src []byte) []tokinfo {
+ fs := token.NewFileSet()
+ var s scanner.Scanner
+ s.Init(fs.AddFile("src", fs.Base(), len(src)), src, nil, scanner.ScanComments)
+ var info []tokinfo
+ for {
+ pos, next, lit := s.Scan()
+ switch next {
+ case token.SEMICOLON:
+ continue
+ }
+ info = append(info, tokinfo{
+ pos: int(pos - 1),
+ end: int(pos + token.Pos(len(lit)) - 1),
+ Token: next,
+ })
+ if next == token.EOF {
+ break
+ }
+ }
+ return info
+}
diff --git a/vendor/github.com/gogo/protobuf/protoc-gen-gogo/grpc/grpc.go b/vendor/github.com/gogo/protobuf/protoc-gen-gogo/grpc/grpc.go
new file mode 100644
index 00000000000..cf527f8e015
--- /dev/null
+++ b/vendor/github.com/gogo/protobuf/protoc-gen-gogo/grpc/grpc.go
@@ -0,0 +1,536 @@
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2015 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// 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 grpc outputs gRPC service descriptions in Go code.
+// It runs as a plugin for the Go protocol buffer compiler plugin.
+// It is linked in to protoc-gen-go.
+package grpc
+
+import (
+ "fmt"
+ "strconv"
+ "strings"
+
+ pb "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
+ "github.com/gogo/protobuf/protoc-gen-gogo/generator"
+)
+
+// generatedCodeVersion indicates a version of the generated code.
+// It is incremented whenever an incompatibility between the generated code and
+// the grpc package is introduced; the generated code references
+// a constant, grpc.SupportPackageIsVersionN (where N is generatedCodeVersion).
+const generatedCodeVersion = 4
+
+// Paths for packages used by code generated in this file,
+// relative to the import_prefix of the generator.Generator.
+const (
+ contextPkgPath = "context"
+ grpcPkgPath = "google.golang.org/grpc"
+ codePkgPath = "google.golang.org/grpc/codes"
+ statusPkgPath = "google.golang.org/grpc/status"
+)
+
+func init() {
+ generator.RegisterPlugin(new(grpc))
+}
+
+// grpc is an implementation of the Go protocol buffer compiler's
+// plugin architecture. It generates bindings for gRPC support.
+type grpc struct {
+ gen *generator.Generator
+}
+
+// Name returns the name of this plugin, "grpc".
+func (g *grpc) Name() string {
+ return "grpc"
+}
+
+// The names for packages imported in the generated code.
+// They may vary from the final path component of the import path
+// if the name is used by other packages.
+var (
+ contextPkg string
+ grpcPkg string
+)
+
+// Init initializes the plugin.
+func (g *grpc) Init(gen *generator.Generator) {
+ g.gen = gen
+}
+
+// Given a type name defined in a .proto, return its object.
+// Also record that we're using it, to guarantee the associated import.
+func (g *grpc) objectNamed(name string) generator.Object {
+ g.gen.RecordTypeUse(name)
+ return g.gen.ObjectNamed(name)
+}
+
+// Given a type name defined in a .proto, return its name as we will print it.
+func (g *grpc) typeName(str string) string {
+ return g.gen.TypeName(g.objectNamed(str))
+}
+
+// P forwards to g.gen.P.
+func (g *grpc) P(args ...interface{}) { g.gen.P(args...) }
+
+// Generate generates code for the services in the given file.
+func (g *grpc) Generate(file *generator.FileDescriptor) {
+ if len(file.FileDescriptorProto.Service) == 0 {
+ return
+ }
+
+ contextPkg = string(g.gen.AddImport(contextPkgPath))
+ grpcPkg = string(g.gen.AddImport(grpcPkgPath))
+
+ g.P("// Reference imports to suppress errors if they are not otherwise used.")
+ g.P("var _ ", contextPkg, ".Context")
+ g.P("var _ ", grpcPkg, ".ClientConn")
+ g.P()
+
+ // Assert version compatibility.
+ g.P("// This is a compile-time assertion to ensure that this generated file")
+ g.P("// is compatible with the grpc package it is being compiled against.")
+ g.P("const _ = ", grpcPkg, ".SupportPackageIsVersion", generatedCodeVersion)
+ g.P()
+
+ for i, service := range file.FileDescriptorProto.Service {
+ g.generateService(file, service, i)
+ }
+}
+
+// GenerateImports generates the import declaration for this file.
+func (g *grpc) GenerateImports(file *generator.FileDescriptor) {}
+
+// reservedClientName records whether a client name is reserved on the client side.
+var reservedClientName = map[string]bool{
+ // TODO: do we need any in gRPC?
+}
+
+func unexport(s string) string { return strings.ToLower(s[:1]) + s[1:] }
+
+// deprecationComment is the standard comment added to deprecated
+// messages, fields, enums, and enum values.
+var deprecationComment = "// Deprecated: Do not use."
+
+// generateService generates all the code for the named service.
+func (g *grpc) generateService(file *generator.FileDescriptor, service *pb.ServiceDescriptorProto, index int) {
+ path := fmt.Sprintf("6,%d", index) // 6 means service.
+
+ origServName := service.GetName()
+ fullServName := origServName
+ if pkg := file.GetPackage(); pkg != "" {
+ fullServName = pkg + "." + fullServName
+ }
+ servName := generator.CamelCase(origServName)
+ deprecated := service.GetOptions().GetDeprecated()
+
+ g.P()
+ g.P(fmt.Sprintf(`// %sClient is the client API for %s service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.`, servName, servName))
+
+ // Client interface.
+ if deprecated {
+ g.P("//")
+ g.P(deprecationComment)
+ }
+ g.P("type ", servName, "Client interface {")
+ for i, method := range service.Method {
+ g.gen.PrintComments(fmt.Sprintf("%s,2,%d", path, i)) // 2 means method in a service.
+ g.P(g.generateClientSignature(servName, method))
+ }
+ g.P("}")
+ g.P()
+
+ // Client structure.
+ g.P("type ", unexport(servName), "Client struct {")
+ g.P("cc *", grpcPkg, ".ClientConn")
+ g.P("}")
+ g.P()
+
+ // NewClient factory.
+ if deprecated {
+ g.P(deprecationComment)
+ }
+ g.P("func New", servName, "Client (cc *", grpcPkg, ".ClientConn) ", servName, "Client {")
+ g.P("return &", unexport(servName), "Client{cc}")
+ g.P("}")
+ g.P()
+
+ var methodIndex, streamIndex int
+ serviceDescVar := "_" + servName + "_serviceDesc"
+ // Client method implementations.
+ for _, method := range service.Method {
+ var descExpr string
+ if !method.GetServerStreaming() && !method.GetClientStreaming() {
+ // Unary RPC method
+ descExpr = fmt.Sprintf("&%s.Methods[%d]", serviceDescVar, methodIndex)
+ methodIndex++
+ } else {
+ // Streaming RPC method
+ descExpr = fmt.Sprintf("&%s.Streams[%d]", serviceDescVar, streamIndex)
+ streamIndex++
+ }
+ g.generateClientMethod(servName, fullServName, serviceDescVar, method, descExpr)
+ }
+
+ // Server interface.
+ serverType := servName + "Server"
+ g.P("// ", serverType, " is the server API for ", servName, " service.")
+ if deprecated {
+ g.P("//")
+ g.P(deprecationComment)
+ }
+ g.P("type ", serverType, " interface {")
+ for i, method := range service.Method {
+ g.gen.PrintComments(fmt.Sprintf("%s,2,%d", path, i)) // 2 means method in a service.
+ g.P(g.generateServerSignature(servName, method))
+ }
+ g.P("}")
+ g.P()
+
+ // Server Unimplemented struct for forward compatability.
+ if deprecated {
+ g.P(deprecationComment)
+ }
+ g.generateUnimplementedServer(servName, service)
+
+ // Server registration.
+ if deprecated {
+ g.P(deprecationComment)
+ }
+ g.P("func Register", servName, "Server(s *", grpcPkg, ".Server, srv ", serverType, ") {")
+ g.P("s.RegisterService(&", serviceDescVar, `, srv)`)
+ g.P("}")
+ g.P()
+
+ // Server handler implementations.
+ var handlerNames []string
+ for _, method := range service.Method {
+ hname := g.generateServerMethod(servName, fullServName, method)
+ handlerNames = append(handlerNames, hname)
+ }
+
+ // Service descriptor.
+ g.P("var ", serviceDescVar, " = ", grpcPkg, ".ServiceDesc {")
+ g.P("ServiceName: ", strconv.Quote(fullServName), ",")
+ g.P("HandlerType: (*", serverType, ")(nil),")
+ g.P("Methods: []", grpcPkg, ".MethodDesc{")
+ for i, method := range service.Method {
+ if method.GetServerStreaming() || method.GetClientStreaming() {
+ continue
+ }
+ g.P("{")
+ g.P("MethodName: ", strconv.Quote(method.GetName()), ",")
+ g.P("Handler: ", handlerNames[i], ",")
+ g.P("},")
+ }
+ g.P("},")
+ g.P("Streams: []", grpcPkg, ".StreamDesc{")
+ for i, method := range service.Method {
+ if !method.GetServerStreaming() && !method.GetClientStreaming() {
+ continue
+ }
+ g.P("{")
+ g.P("StreamName: ", strconv.Quote(method.GetName()), ",")
+ g.P("Handler: ", handlerNames[i], ",")
+ if method.GetServerStreaming() {
+ g.P("ServerStreams: true,")
+ }
+ if method.GetClientStreaming() {
+ g.P("ClientStreams: true,")
+ }
+ g.P("},")
+ }
+ g.P("},")
+ g.P("Metadata: \"", file.GetName(), "\",")
+ g.P("}")
+ g.P()
+}
+
+// generateUnimplementedServer creates the unimplemented server struct
+func (g *grpc) generateUnimplementedServer(servName string, service *pb.ServiceDescriptorProto) {
+ serverType := servName + "Server"
+ g.P("// Unimplemented", serverType, " can be embedded to have forward compatible implementations.")
+ g.P("type Unimplemented", serverType, " struct {")
+ g.P("}")
+ g.P()
+ // UnimplementedServer's concrete methods
+ for _, method := range service.Method {
+ g.generateServerMethodConcrete(servName, method)
+ }
+ g.P()
+}
+
+// generateServerMethodConcrete returns unimplemented methods which ensure forward compatibility
+func (g *grpc) generateServerMethodConcrete(servName string, method *pb.MethodDescriptorProto) {
+ header := g.generateServerSignatureWithParamNames(servName, method)
+ g.P("func (*Unimplemented", servName, "Server) ", header, " {")
+ var nilArg string
+ if !method.GetServerStreaming() && !method.GetClientStreaming() {
+ nilArg = "nil, "
+ }
+ methName := generator.CamelCase(method.GetName())
+ statusPkg := string(g.gen.AddImport(statusPkgPath))
+ codePkg := string(g.gen.AddImport(codePkgPath))
+ g.P("return ", nilArg, statusPkg, `.Errorf(`, codePkg, `.Unimplemented, "method `, methName, ` not implemented")`)
+ g.P("}")
+}
+
+// generateClientSignature returns the client-side signature for a method.
+func (g *grpc) generateClientSignature(servName string, method *pb.MethodDescriptorProto) string {
+ origMethName := method.GetName()
+ methName := generator.CamelCase(origMethName)
+ if reservedClientName[methName] {
+ methName += "_"
+ }
+ reqArg := ", in *" + g.typeName(method.GetInputType())
+ if method.GetClientStreaming() {
+ reqArg = ""
+ }
+ respName := "*" + g.typeName(method.GetOutputType())
+ if method.GetServerStreaming() || method.GetClientStreaming() {
+ respName = servName + "_" + generator.CamelCase(origMethName) + "Client"
+ }
+ return fmt.Sprintf("%s(ctx %s.Context%s, opts ...%s.CallOption) (%s, error)", methName, contextPkg, reqArg, grpcPkg, respName)
+}
+
+func (g *grpc) generateClientMethod(servName, fullServName, serviceDescVar string, method *pb.MethodDescriptorProto, descExpr string) {
+ sname := fmt.Sprintf("/%s/%s", fullServName, method.GetName())
+ methName := generator.CamelCase(method.GetName())
+ inType := g.typeName(method.GetInputType())
+ outType := g.typeName(method.GetOutputType())
+
+ if method.GetOptions().GetDeprecated() {
+ g.P(deprecationComment)
+ }
+ g.P("func (c *", unexport(servName), "Client) ", g.generateClientSignature(servName, method), "{")
+ if !method.GetServerStreaming() && !method.GetClientStreaming() {
+ g.P("out := new(", outType, ")")
+ // TODO: Pass descExpr to Invoke.
+ g.P(`err := c.cc.Invoke(ctx, "`, sname, `", in, out, opts...)`)
+ g.P("if err != nil { return nil, err }")
+ g.P("return out, nil")
+ g.P("}")
+ g.P()
+ return
+ }
+ streamType := unexport(servName) + methName + "Client"
+ g.P("stream, err := c.cc.NewStream(ctx, ", descExpr, `, "`, sname, `", opts...)`)
+ g.P("if err != nil { return nil, err }")
+ g.P("x := &", streamType, "{stream}")
+ if !method.GetClientStreaming() {
+ g.P("if err := x.ClientStream.SendMsg(in); err != nil { return nil, err }")
+ g.P("if err := x.ClientStream.CloseSend(); err != nil { return nil, err }")
+ }
+ g.P("return x, nil")
+ g.P("}")
+ g.P()
+
+ genSend := method.GetClientStreaming()
+ genRecv := method.GetServerStreaming()
+ genCloseAndRecv := !method.GetServerStreaming()
+
+ // Stream auxiliary types and methods.
+ g.P("type ", servName, "_", methName, "Client interface {")
+ if genSend {
+ g.P("Send(*", inType, ") error")
+ }
+ if genRecv {
+ g.P("Recv() (*", outType, ", error)")
+ }
+ if genCloseAndRecv {
+ g.P("CloseAndRecv() (*", outType, ", error)")
+ }
+ g.P(grpcPkg, ".ClientStream")
+ g.P("}")
+ g.P()
+
+ g.P("type ", streamType, " struct {")
+ g.P(grpcPkg, ".ClientStream")
+ g.P("}")
+ g.P()
+
+ if genSend {
+ g.P("func (x *", streamType, ") Send(m *", inType, ") error {")
+ g.P("return x.ClientStream.SendMsg(m)")
+ g.P("}")
+ g.P()
+ }
+ if genRecv {
+ g.P("func (x *", streamType, ") Recv() (*", outType, ", error) {")
+ g.P("m := new(", outType, ")")
+ g.P("if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err }")
+ g.P("return m, nil")
+ g.P("}")
+ g.P()
+ }
+ if genCloseAndRecv {
+ g.P("func (x *", streamType, ") CloseAndRecv() (*", outType, ", error) {")
+ g.P("if err := x.ClientStream.CloseSend(); err != nil { return nil, err }")
+ g.P("m := new(", outType, ")")
+ g.P("if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err }")
+ g.P("return m, nil")
+ g.P("}")
+ g.P()
+ }
+}
+
+// generateServerSignatureWithParamNames returns the server-side signature for a method with parameter names.
+func (g *grpc) generateServerSignatureWithParamNames(servName string, method *pb.MethodDescriptorProto) string {
+ origMethName := method.GetName()
+ methName := generator.CamelCase(origMethName)
+ if reservedClientName[methName] {
+ methName += "_"
+ }
+
+ var reqArgs []string
+ ret := "error"
+ if !method.GetServerStreaming() && !method.GetClientStreaming() {
+ reqArgs = append(reqArgs, "ctx "+contextPkg+".Context")
+ ret = "(*" + g.typeName(method.GetOutputType()) + ", error)"
+ }
+ if !method.GetClientStreaming() {
+ reqArgs = append(reqArgs, "req *"+g.typeName(method.GetInputType()))
+ }
+ if method.GetServerStreaming() || method.GetClientStreaming() {
+ reqArgs = append(reqArgs, "srv "+servName+"_"+generator.CamelCase(origMethName)+"Server")
+ }
+
+ return methName + "(" + strings.Join(reqArgs, ", ") + ") " + ret
+}
+
+// generateServerSignature returns the server-side signature for a method.
+func (g *grpc) generateServerSignature(servName string, method *pb.MethodDescriptorProto) string {
+ origMethName := method.GetName()
+ methName := generator.CamelCase(origMethName)
+ if reservedClientName[methName] {
+ methName += "_"
+ }
+
+ var reqArgs []string
+ ret := "error"
+ if !method.GetServerStreaming() && !method.GetClientStreaming() {
+ reqArgs = append(reqArgs, contextPkg+".Context")
+ ret = "(*" + g.typeName(method.GetOutputType()) + ", error)"
+ }
+ if !method.GetClientStreaming() {
+ reqArgs = append(reqArgs, "*"+g.typeName(method.GetInputType()))
+ }
+ if method.GetServerStreaming() || method.GetClientStreaming() {
+ reqArgs = append(reqArgs, servName+"_"+generator.CamelCase(origMethName)+"Server")
+ }
+
+ return methName + "(" + strings.Join(reqArgs, ", ") + ") " + ret
+}
+
+func (g *grpc) generateServerMethod(servName, fullServName string, method *pb.MethodDescriptorProto) string {
+ methName := generator.CamelCase(method.GetName())
+ hname := fmt.Sprintf("_%s_%s_Handler", servName, methName)
+ inType := g.typeName(method.GetInputType())
+ outType := g.typeName(method.GetOutputType())
+
+ if !method.GetServerStreaming() && !method.GetClientStreaming() {
+ g.P("func ", hname, "(srv interface{}, ctx ", contextPkg, ".Context, dec func(interface{}) error, interceptor ", grpcPkg, ".UnaryServerInterceptor) (interface{}, error) {")
+ g.P("in := new(", inType, ")")
+ g.P("if err := dec(in); err != nil { return nil, err }")
+ g.P("if interceptor == nil { return srv.(", servName, "Server).", methName, "(ctx, in) }")
+ g.P("info := &", grpcPkg, ".UnaryServerInfo{")
+ g.P("Server: srv,")
+ g.P("FullMethod: ", strconv.Quote(fmt.Sprintf("/%s/%s", fullServName, methName)), ",")
+ g.P("}")
+ g.P("handler := func(ctx ", contextPkg, ".Context, req interface{}) (interface{}, error) {")
+ g.P("return srv.(", servName, "Server).", methName, "(ctx, req.(*", inType, "))")
+ g.P("}")
+ g.P("return interceptor(ctx, in, info, handler)")
+ g.P("}")
+ g.P()
+ return hname
+ }
+ streamType := unexport(servName) + methName + "Server"
+ g.P("func ", hname, "(srv interface{}, stream ", grpcPkg, ".ServerStream) error {")
+ if !method.GetClientStreaming() {
+ g.P("m := new(", inType, ")")
+ g.P("if err := stream.RecvMsg(m); err != nil { return err }")
+ g.P("return srv.(", servName, "Server).", methName, "(m, &", streamType, "{stream})")
+ } else {
+ g.P("return srv.(", servName, "Server).", methName, "(&", streamType, "{stream})")
+ }
+ g.P("}")
+ g.P()
+
+ genSend := method.GetServerStreaming()
+ genSendAndClose := !method.GetServerStreaming()
+ genRecv := method.GetClientStreaming()
+
+ // Stream auxiliary types and methods.
+ g.P("type ", servName, "_", methName, "Server interface {")
+ if genSend {
+ g.P("Send(*", outType, ") error")
+ }
+ if genSendAndClose {
+ g.P("SendAndClose(*", outType, ") error")
+ }
+ if genRecv {
+ g.P("Recv() (*", inType, ", error)")
+ }
+ g.P(grpcPkg, ".ServerStream")
+ g.P("}")
+ g.P()
+
+ g.P("type ", streamType, " struct {")
+ g.P(grpcPkg, ".ServerStream")
+ g.P("}")
+ g.P()
+
+ if genSend {
+ g.P("func (x *", streamType, ") Send(m *", outType, ") error {")
+ g.P("return x.ServerStream.SendMsg(m)")
+ g.P("}")
+ g.P()
+ }
+ if genSendAndClose {
+ g.P("func (x *", streamType, ") SendAndClose(m *", outType, ") error {")
+ g.P("return x.ServerStream.SendMsg(m)")
+ g.P("}")
+ g.P()
+ }
+ if genRecv {
+ g.P("func (x *", streamType, ") Recv() (*", inType, ", error) {")
+ g.P("m := new(", inType, ")")
+ g.P("if err := x.ServerStream.RecvMsg(m); err != nil { return nil, err }")
+ g.P("return m, nil")
+ g.P("}")
+ g.P()
+ }
+
+ return hname
+}
diff --git a/vendor/github.com/gogo/protobuf/protoc-gen-gogo/main.go b/vendor/github.com/gogo/protobuf/protoc-gen-gogo/main.go
new file mode 100644
index 00000000000..dd8e795030c
--- /dev/null
+++ b/vendor/github.com/gogo/protobuf/protoc-gen-gogo/main.go
@@ -0,0 +1,57 @@
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2010 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// 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.
+
+// protoc-gen-go is a plugin for the Google protocol buffer compiler to generate
+// Go code. Run it by building this program and putting it in your path with
+// the name
+// protoc-gen-gogo
+// That word 'gogo' at the end becomes part of the option string set for the
+// protocol compiler, so once the protocol compiler (protoc) is installed
+// you can run
+// protoc --gogo_out=output_directory input_directory/file.proto
+// to generate Go bindings for the protocol defined by file.proto.
+// With that input, the output will be written to
+// output_directory/file.pb.go
+//
+// The generated code is documented in the package comment for
+// the library.
+//
+// See the README and documentation for protocol buffers to learn more:
+// https://developers.google.com/protocol-buffers/
+package main
+
+import (
+ "github.com/gogo/protobuf/vanity/command"
+)
+
+func main() {
+ command.Write(command.Generate(command.Read()))
+}
diff --git a/vendor/github.com/gogo/protobuf/protoc-gen-gogo/plugin/Makefile b/vendor/github.com/gogo/protobuf/protoc-gen-gogo/plugin/Makefile
new file mode 100644
index 00000000000..95234a75539
--- /dev/null
+++ b/vendor/github.com/gogo/protobuf/protoc-gen-gogo/plugin/Makefile
@@ -0,0 +1,37 @@
+# Go support for Protocol Buffers - Google's data interchange format
+#
+# Copyright 2010 The Go Authors. All rights reserved.
+# https://github.com/golang/protobuf
+#
+# 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.
+
+# Not stored here, but plugin.proto is in https://github.com/google/protobuf/
+# at src/google/protobuf/compiler/plugin.proto
+# Also we need to fix an import.
+regenerate:
+ go install github.com/gogo/protobuf/protoc-gen-gogo
+ protoc --gogo_out=Mgoogle/protobuf/descriptor.proto=github.com/gogo/protobuf/protoc-gen-gogo/descriptor:. -I=../../protobuf/google/protobuf/compiler/:../../protobuf/ ../../protobuf/google/protobuf/compiler/plugin.proto
diff --git a/vendor/github.com/gogo/protobuf/protoc-gen-gogo/plugin/plugin.pb.go b/vendor/github.com/gogo/protobuf/protoc-gen-gogo/plugin/plugin.pb.go
new file mode 100644
index 00000000000..8c9cb58b0dd
--- /dev/null
+++ b/vendor/github.com/gogo/protobuf/protoc-gen-gogo/plugin/plugin.pb.go
@@ -0,0 +1,365 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: plugin.proto
+
+package plugin_go
+
+import (
+ fmt "fmt"
+ proto "github.com/gogo/protobuf/proto"
+ descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
+ math "math"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
+
+// The version number of protocol compiler.
+type Version struct {
+ Major *int32 `protobuf:"varint,1,opt,name=major" json:"major,omitempty"`
+ Minor *int32 `protobuf:"varint,2,opt,name=minor" json:"minor,omitempty"`
+ Patch *int32 `protobuf:"varint,3,opt,name=patch" json:"patch,omitempty"`
+ // A suffix for alpha, beta or rc release, e.g., "alpha-1", "rc2". It should
+ // be empty for mainline stable releases.
+ Suffix *string `protobuf:"bytes,4,opt,name=suffix" json:"suffix,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *Version) Reset() { *m = Version{} }
+func (m *Version) String() string { return proto.CompactTextString(m) }
+func (*Version) ProtoMessage() {}
+func (*Version) Descriptor() ([]byte, []int) {
+ return fileDescriptor_22a625af4bc1cc87, []int{0}
+}
+func (m *Version) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_Version.Unmarshal(m, b)
+}
+func (m *Version) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_Version.Marshal(b, m, deterministic)
+}
+func (m *Version) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Version.Merge(m, src)
+}
+func (m *Version) XXX_Size() int {
+ return xxx_messageInfo_Version.Size(m)
+}
+func (m *Version) XXX_DiscardUnknown() {
+ xxx_messageInfo_Version.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Version proto.InternalMessageInfo
+
+func (m *Version) GetMajor() int32 {
+ if m != nil && m.Major != nil {
+ return *m.Major
+ }
+ return 0
+}
+
+func (m *Version) GetMinor() int32 {
+ if m != nil && m.Minor != nil {
+ return *m.Minor
+ }
+ return 0
+}
+
+func (m *Version) GetPatch() int32 {
+ if m != nil && m.Patch != nil {
+ return *m.Patch
+ }
+ return 0
+}
+
+func (m *Version) GetSuffix() string {
+ if m != nil && m.Suffix != nil {
+ return *m.Suffix
+ }
+ return ""
+}
+
+// An encoded CodeGeneratorRequest is written to the plugin's stdin.
+type CodeGeneratorRequest struct {
+ // The .proto files that were explicitly listed on the command-line. The
+ // code generator should generate code only for these files. Each file's
+ // descriptor will be included in proto_file, below.
+ FileToGenerate []string `protobuf:"bytes,1,rep,name=file_to_generate,json=fileToGenerate" json:"file_to_generate,omitempty"`
+ // The generator parameter passed on the command-line.
+ Parameter *string `protobuf:"bytes,2,opt,name=parameter" json:"parameter,omitempty"`
+ // FileDescriptorProtos for all files in files_to_generate and everything
+ // they import. The files will appear in topological order, so each file
+ // appears before any file that imports it.
+ //
+ // protoc guarantees that all proto_files will be written after
+ // the fields above, even though this is not technically guaranteed by the
+ // protobuf wire format. This theoretically could allow a plugin to stream
+ // in the FileDescriptorProtos and handle them one by one rather than read
+ // the entire set into memory at once. However, as of this writing, this
+ // is not similarly optimized on protoc's end -- it will store all fields in
+ // memory at once before sending them to the plugin.
+ //
+ // Type names of fields and extensions in the FileDescriptorProto are always
+ // fully qualified.
+ ProtoFile []*descriptor.FileDescriptorProto `protobuf:"bytes,15,rep,name=proto_file,json=protoFile" json:"proto_file,omitempty"`
+ // The version number of protocol compiler.
+ CompilerVersion *Version `protobuf:"bytes,3,opt,name=compiler_version,json=compilerVersion" json:"compiler_version,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *CodeGeneratorRequest) Reset() { *m = CodeGeneratorRequest{} }
+func (m *CodeGeneratorRequest) String() string { return proto.CompactTextString(m) }
+func (*CodeGeneratorRequest) ProtoMessage() {}
+func (*CodeGeneratorRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_22a625af4bc1cc87, []int{1}
+}
+func (m *CodeGeneratorRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_CodeGeneratorRequest.Unmarshal(m, b)
+}
+func (m *CodeGeneratorRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_CodeGeneratorRequest.Marshal(b, m, deterministic)
+}
+func (m *CodeGeneratorRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_CodeGeneratorRequest.Merge(m, src)
+}
+func (m *CodeGeneratorRequest) XXX_Size() int {
+ return xxx_messageInfo_CodeGeneratorRequest.Size(m)
+}
+func (m *CodeGeneratorRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_CodeGeneratorRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_CodeGeneratorRequest proto.InternalMessageInfo
+
+func (m *CodeGeneratorRequest) GetFileToGenerate() []string {
+ if m != nil {
+ return m.FileToGenerate
+ }
+ return nil
+}
+
+func (m *CodeGeneratorRequest) GetParameter() string {
+ if m != nil && m.Parameter != nil {
+ return *m.Parameter
+ }
+ return ""
+}
+
+func (m *CodeGeneratorRequest) GetProtoFile() []*descriptor.FileDescriptorProto {
+ if m != nil {
+ return m.ProtoFile
+ }
+ return nil
+}
+
+func (m *CodeGeneratorRequest) GetCompilerVersion() *Version {
+ if m != nil {
+ return m.CompilerVersion
+ }
+ return nil
+}
+
+// The plugin writes an encoded CodeGeneratorResponse to stdout.
+type CodeGeneratorResponse struct {
+ // Error message. If non-empty, code generation failed. The plugin process
+ // should exit with status code zero even if it reports an error in this way.
+ //
+ // This should be used to indicate errors in .proto files which prevent the
+ // code generator from generating correct code. Errors which indicate a
+ // problem in protoc itself -- such as the input CodeGeneratorRequest being
+ // unparseable -- should be reported by writing a message to stderr and
+ // exiting with a non-zero status code.
+ Error *string `protobuf:"bytes,1,opt,name=error" json:"error,omitempty"`
+ File []*CodeGeneratorResponse_File `protobuf:"bytes,15,rep,name=file" json:"file,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *CodeGeneratorResponse) Reset() { *m = CodeGeneratorResponse{} }
+func (m *CodeGeneratorResponse) String() string { return proto.CompactTextString(m) }
+func (*CodeGeneratorResponse) ProtoMessage() {}
+func (*CodeGeneratorResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptor_22a625af4bc1cc87, []int{2}
+}
+func (m *CodeGeneratorResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_CodeGeneratorResponse.Unmarshal(m, b)
+}
+func (m *CodeGeneratorResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_CodeGeneratorResponse.Marshal(b, m, deterministic)
+}
+func (m *CodeGeneratorResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_CodeGeneratorResponse.Merge(m, src)
+}
+func (m *CodeGeneratorResponse) XXX_Size() int {
+ return xxx_messageInfo_CodeGeneratorResponse.Size(m)
+}
+func (m *CodeGeneratorResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_CodeGeneratorResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_CodeGeneratorResponse proto.InternalMessageInfo
+
+func (m *CodeGeneratorResponse) GetError() string {
+ if m != nil && m.Error != nil {
+ return *m.Error
+ }
+ return ""
+}
+
+func (m *CodeGeneratorResponse) GetFile() []*CodeGeneratorResponse_File {
+ if m != nil {
+ return m.File
+ }
+ return nil
+}
+
+// Represents a single generated file.
+type CodeGeneratorResponse_File struct {
+ // The file name, relative to the output directory. The name must not
+ // contain "." or ".." components and must be relative, not be absolute (so,
+ // the file cannot lie outside the output directory). "/" must be used as
+ // the path separator, not "\".
+ //
+ // If the name is omitted, the content will be appended to the previous
+ // file. This allows the generator to break large files into small chunks,
+ // and allows the generated text to be streamed back to protoc so that large
+ // files need not reside completely in memory at one time. Note that as of
+ // this writing protoc does not optimize for this -- it will read the entire
+ // CodeGeneratorResponse before writing files to disk.
+ Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
+ // If non-empty, indicates that the named file should already exist, and the
+ // content here is to be inserted into that file at a defined insertion
+ // point. This feature allows a code generator to extend the output
+ // produced by another code generator. The original generator may provide
+ // insertion points by placing special annotations in the file that look
+ // like:
+ // @@protoc_insertion_point(NAME)
+ // The annotation can have arbitrary text before and after it on the line,
+ // which allows it to be placed in a comment. NAME should be replaced with
+ // an identifier naming the point -- this is what other generators will use
+ // as the insertion_point. Code inserted at this point will be placed
+ // immediately above the line containing the insertion point (thus multiple
+ // insertions to the same point will come out in the order they were added).
+ // The double-@ is intended to make it unlikely that the generated code
+ // could contain things that look like insertion points by accident.
+ //
+ // For example, the C++ code generator places the following line in the
+ // .pb.h files that it generates:
+ // // @@protoc_insertion_point(namespace_scope)
+ // This line appears within the scope of the file's package namespace, but
+ // outside of any particular class. Another plugin can then specify the
+ // insertion_point "namespace_scope" to generate additional classes or
+ // other declarations that should be placed in this scope.
+ //
+ // Note that if the line containing the insertion point begins with
+ // whitespace, the same whitespace will be added to every line of the
+ // inserted text. This is useful for languages like Python, where
+ // indentation matters. In these languages, the insertion point comment
+ // should be indented the same amount as any inserted code will need to be
+ // in order to work correctly in that context.
+ //
+ // The code generator that generates the initial file and the one which
+ // inserts into it must both run as part of a single invocation of protoc.
+ // Code generators are executed in the order in which they appear on the
+ // command line.
+ //
+ // If |insertion_point| is present, |name| must also be present.
+ InsertionPoint *string `protobuf:"bytes,2,opt,name=insertion_point,json=insertionPoint" json:"insertion_point,omitempty"`
+ // The file contents.
+ Content *string `protobuf:"bytes,15,opt,name=content" json:"content,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *CodeGeneratorResponse_File) Reset() { *m = CodeGeneratorResponse_File{} }
+func (m *CodeGeneratorResponse_File) String() string { return proto.CompactTextString(m) }
+func (*CodeGeneratorResponse_File) ProtoMessage() {}
+func (*CodeGeneratorResponse_File) Descriptor() ([]byte, []int) {
+ return fileDescriptor_22a625af4bc1cc87, []int{2, 0}
+}
+func (m *CodeGeneratorResponse_File) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_CodeGeneratorResponse_File.Unmarshal(m, b)
+}
+func (m *CodeGeneratorResponse_File) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_CodeGeneratorResponse_File.Marshal(b, m, deterministic)
+}
+func (m *CodeGeneratorResponse_File) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_CodeGeneratorResponse_File.Merge(m, src)
+}
+func (m *CodeGeneratorResponse_File) XXX_Size() int {
+ return xxx_messageInfo_CodeGeneratorResponse_File.Size(m)
+}
+func (m *CodeGeneratorResponse_File) XXX_DiscardUnknown() {
+ xxx_messageInfo_CodeGeneratorResponse_File.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_CodeGeneratorResponse_File proto.InternalMessageInfo
+
+func (m *CodeGeneratorResponse_File) GetName() string {
+ if m != nil && m.Name != nil {
+ return *m.Name
+ }
+ return ""
+}
+
+func (m *CodeGeneratorResponse_File) GetInsertionPoint() string {
+ if m != nil && m.InsertionPoint != nil {
+ return *m.InsertionPoint
+ }
+ return ""
+}
+
+func (m *CodeGeneratorResponse_File) GetContent() string {
+ if m != nil && m.Content != nil {
+ return *m.Content
+ }
+ return ""
+}
+
+func init() {
+ proto.RegisterType((*Version)(nil), "google.protobuf.compiler.Version")
+ proto.RegisterType((*CodeGeneratorRequest)(nil), "google.protobuf.compiler.CodeGeneratorRequest")
+ proto.RegisterType((*CodeGeneratorResponse)(nil), "google.protobuf.compiler.CodeGeneratorResponse")
+ proto.RegisterType((*CodeGeneratorResponse_File)(nil), "google.protobuf.compiler.CodeGeneratorResponse.File")
+}
+
+func init() { proto.RegisterFile("plugin.proto", fileDescriptor_22a625af4bc1cc87) }
+
+var fileDescriptor_22a625af4bc1cc87 = []byte{
+ // 383 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x92, 0xcd, 0x6a, 0xd5, 0x40,
+ 0x14, 0xc7, 0x89, 0x37, 0xb5, 0xe4, 0xb4, 0x34, 0x65, 0xa8, 0x32, 0x94, 0x2e, 0xe2, 0x45, 0x30,
+ 0xab, 0x14, 0x8a, 0xe0, 0xbe, 0x15, 0x75, 0xe1, 0xe2, 0x32, 0x88, 0x0b, 0x41, 0x42, 0x4c, 0x4f,
+ 0xe2, 0x48, 0x32, 0x67, 0x9c, 0x99, 0x88, 0x4f, 0xea, 0x7b, 0xf8, 0x06, 0x32, 0x1f, 0xa9, 0x72,
+ 0xf1, 0xee, 0xe6, 0xff, 0x3b, 0xf3, 0x71, 0xce, 0x8f, 0x81, 0x53, 0x3d, 0x2d, 0xa3, 0x54, 0x8d,
+ 0x36, 0xe4, 0x88, 0xf1, 0x91, 0x68, 0x9c, 0x30, 0xa6, 0x2f, 0xcb, 0xd0, 0xf4, 0x34, 0x6b, 0x39,
+ 0xa1, 0xb9, 0xac, 0x62, 0xe5, 0x7a, 0xad, 0x5c, 0xdf, 0xa3, 0xed, 0x8d, 0xd4, 0x8e, 0x4c, 0xdc,
+ 0xbd, 0xed, 0xe1, 0xf8, 0x23, 0x1a, 0x2b, 0x49, 0xb1, 0x0b, 0x38, 0x9a, 0xbb, 0x6f, 0x64, 0x78,
+ 0x56, 0x65, 0xf5, 0x91, 0x88, 0x21, 0x50, 0xa9, 0xc8, 0xf0, 0x47, 0x89, 0xfa, 0xe0, 0xa9, 0xee,
+ 0x5c, 0xff, 0x95, 0x6f, 0x22, 0x0d, 0x81, 0x3d, 0x85, 0xc7, 0x76, 0x19, 0x06, 0xf9, 0x93, 0xe7,
+ 0x55, 0x56, 0x17, 0x22, 0xa5, 0xed, 0xef, 0x0c, 0x2e, 0xee, 0xe8, 0x1e, 0xdf, 0xa2, 0x42, 0xd3,
+ 0x39, 0x32, 0x02, 0xbf, 0x2f, 0x68, 0x1d, 0xab, 0xe1, 0x7c, 0x90, 0x13, 0xb6, 0x8e, 0xda, 0x31,
+ 0xd6, 0x90, 0x67, 0xd5, 0xa6, 0x2e, 0xc4, 0x99, 0xe7, 0x1f, 0x28, 0x9d, 0x40, 0x76, 0x05, 0x85,
+ 0xee, 0x4c, 0x37, 0xa3, 0xc3, 0xd8, 0x4a, 0x21, 0xfe, 0x02, 0x76, 0x07, 0x10, 0xc6, 0x69, 0xfd,
+ 0x29, 0x5e, 0x56, 0x9b, 0xfa, 0xe4, 0xe6, 0x79, 0xb3, 0xaf, 0xe5, 0x8d, 0x9c, 0xf0, 0xf5, 0x83,
+ 0x80, 0x9d, 0xc7, 0xa2, 0x08, 0x55, 0x5f, 0x61, 0xef, 0xe1, 0x7c, 0x15, 0xd7, 0xfe, 0x88, 0x4e,
+ 0xc2, 0x78, 0x27, 0x37, 0xcf, 0x9a, 0x43, 0x86, 0x9b, 0x24, 0x4f, 0x94, 0x2b, 0x49, 0x60, 0xfb,
+ 0x2b, 0x83, 0x27, 0x7b, 0x33, 0x5b, 0x4d, 0xca, 0xa2, 0x77, 0x87, 0xc6, 0x24, 0xcf, 0x85, 0x88,
+ 0x81, 0xbd, 0x83, 0xfc, 0x9f, 0xe6, 0x5f, 0x1e, 0x7e, 0xf1, 0xbf, 0x97, 0x86, 0xd9, 0x44, 0xb8,
+ 0xe1, 0xf2, 0x33, 0xe4, 0x61, 0x1e, 0x06, 0xb9, 0xea, 0x66, 0x4c, 0xcf, 0x84, 0x35, 0x7b, 0x01,
+ 0xa5, 0x54, 0x16, 0x8d, 0x93, 0xa4, 0x5a, 0x4d, 0x52, 0xb9, 0x24, 0xf3, 0xec, 0x01, 0xef, 0x3c,
+ 0x65, 0x1c, 0x8e, 0x7b, 0x52, 0x0e, 0x95, 0xe3, 0x65, 0xd8, 0xb0, 0xc6, 0xdb, 0x57, 0x70, 0xd5,
+ 0xd3, 0x7c, 0xb0, 0xbf, 0xdb, 0xd3, 0x5d, 0xf8, 0x9b, 0x41, 0xaf, 0xfd, 0x54, 0xc4, 0x9f, 0xda,
+ 0x8e, 0xf4, 0x27, 0x00, 0x00, 0xff, 0xff, 0x7a, 0x72, 0x3d, 0x18, 0xb5, 0x02, 0x00, 0x00,
+}
diff --git a/vendor/github.com/gogo/protobuf/vanity/command/command.go b/vendor/github.com/gogo/protobuf/vanity/command/command.go
new file mode 100644
index 00000000000..eeca42ba0d0
--- /dev/null
+++ b/vendor/github.com/gogo/protobuf/vanity/command/command.go
@@ -0,0 +1,161 @@
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2015, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// 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.
+//
+// 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 command
+
+import (
+ "fmt"
+ "go/format"
+ "io/ioutil"
+ "os"
+ "strings"
+
+ _ "github.com/gogo/protobuf/plugin/compare"
+ _ "github.com/gogo/protobuf/plugin/defaultcheck"
+ _ "github.com/gogo/protobuf/plugin/description"
+ _ "github.com/gogo/protobuf/plugin/embedcheck"
+ _ "github.com/gogo/protobuf/plugin/enumstringer"
+ _ "github.com/gogo/protobuf/plugin/equal"
+ _ "github.com/gogo/protobuf/plugin/face"
+ _ "github.com/gogo/protobuf/plugin/gostring"
+ _ "github.com/gogo/protobuf/plugin/marshalto"
+ _ "github.com/gogo/protobuf/plugin/oneofcheck"
+ _ "github.com/gogo/protobuf/plugin/populate"
+ _ "github.com/gogo/protobuf/plugin/size"
+ _ "github.com/gogo/protobuf/plugin/stringer"
+ "github.com/gogo/protobuf/plugin/testgen"
+ _ "github.com/gogo/protobuf/plugin/union"
+ _ "github.com/gogo/protobuf/plugin/unmarshal"
+ "github.com/gogo/protobuf/proto"
+ "github.com/gogo/protobuf/protoc-gen-gogo/generator"
+ _ "github.com/gogo/protobuf/protoc-gen-gogo/grpc"
+ plugin "github.com/gogo/protobuf/protoc-gen-gogo/plugin"
+)
+
+func Read() *plugin.CodeGeneratorRequest {
+ g := generator.New()
+ data, err := ioutil.ReadAll(os.Stdin)
+ if err != nil {
+ g.Error(err, "reading input")
+ }
+
+ if err := proto.Unmarshal(data, g.Request); err != nil {
+ g.Error(err, "parsing input proto")
+ }
+
+ if len(g.Request.FileToGenerate) == 0 {
+ g.Fail("no files to generate")
+ }
+ return g.Request
+}
+
+// filenameSuffix replaces the .pb.go at the end of each filename.
+func GeneratePlugin(req *plugin.CodeGeneratorRequest, p generator.Plugin, filenameSuffix string) *plugin.CodeGeneratorResponse {
+ g := generator.New()
+ g.Request = req
+ if len(g.Request.FileToGenerate) == 0 {
+ g.Fail("no files to generate")
+ }
+
+ g.CommandLineParameters(g.Request.GetParameter())
+
+ g.WrapTypes()
+ g.SetPackageNames()
+ g.BuildTypeNameMap()
+ g.GeneratePlugin(p)
+
+ for i := 0; i < len(g.Response.File); i++ {
+ g.Response.File[i].Name = proto.String(
+ strings.Replace(*g.Response.File[i].Name, ".pb.go", filenameSuffix, -1),
+ )
+ }
+ if err := goformat(g.Response); err != nil {
+ g.Error(err)
+ }
+ return g.Response
+}
+
+func goformat(resp *plugin.CodeGeneratorResponse) error {
+ for i := 0; i < len(resp.File); i++ {
+ formatted, err := format.Source([]byte(resp.File[i].GetContent()))
+ if err != nil {
+ return fmt.Errorf("go format error: %v", err)
+ }
+ fmts := string(formatted)
+ resp.File[i].Content = &fmts
+ }
+ return nil
+}
+
+func Generate(req *plugin.CodeGeneratorRequest) *plugin.CodeGeneratorResponse {
+ // Begin by allocating a generator. The request and response structures are stored there
+ // so we can do error handling easily - the response structure contains the field to
+ // report failure.
+ g := generator.New()
+ g.Request = req
+
+ g.CommandLineParameters(g.Request.GetParameter())
+
+ // Create a wrapped version of the Descriptors and EnumDescriptors that
+ // point to the file that defines them.
+ g.WrapTypes()
+
+ g.SetPackageNames()
+ g.BuildTypeNameMap()
+
+ g.GenerateAllFiles()
+
+ if err := goformat(g.Response); err != nil {
+ g.Error(err)
+ }
+
+ testReq := proto.Clone(req).(*plugin.CodeGeneratorRequest)
+
+ testResp := GeneratePlugin(testReq, testgen.NewPlugin(), "pb_test.go")
+
+ for i := 0; i < len(testResp.File); i++ {
+ if strings.Contains(*testResp.File[i].Content, `//These tests are generated by github.com/gogo/protobuf/plugin/testgen`) {
+ g.Response.File = append(g.Response.File, testResp.File[i])
+ }
+ }
+
+ return g.Response
+}
+
+func Write(resp *plugin.CodeGeneratorResponse) {
+ g := generator.New()
+ // Send back the results.
+ data, err := proto.Marshal(resp)
+ if err != nil {
+ g.Error(err, "failed to marshal output proto")
+ }
+ _, err = os.Stdout.Write(data)
+ if err != nil {
+ g.Error(err, "failed to write output proto")
+ }
+}
diff --git a/vendor/github.com/gogo/protobuf/vanity/enum.go b/vendor/github.com/gogo/protobuf/vanity/enum.go
new file mode 100644
index 00000000000..466d07b54eb
--- /dev/null
+++ b/vendor/github.com/gogo/protobuf/vanity/enum.go
@@ -0,0 +1,78 @@
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2015, The GoGo Authors. rights reserved.
+// http://github.com/gogo/protobuf
+//
+// 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.
+//
+// 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 vanity
+
+import (
+ "github.com/gogo/protobuf/gogoproto"
+ "github.com/gogo/protobuf/proto"
+ descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
+)
+
+func EnumHasBoolExtension(enum *descriptor.EnumDescriptorProto, extension *proto.ExtensionDesc) bool {
+ if enum.Options == nil {
+ return false
+ }
+ value, err := proto.GetExtension(enum.Options, extension)
+ if err != nil {
+ return false
+ }
+ if value == nil {
+ return false
+ }
+ if value.(*bool) == nil {
+ return false
+ }
+ return true
+}
+
+func SetBoolEnumOption(extension *proto.ExtensionDesc, value bool) func(enum *descriptor.EnumDescriptorProto) {
+ return func(enum *descriptor.EnumDescriptorProto) {
+ if EnumHasBoolExtension(enum, extension) {
+ return
+ }
+ if enum.Options == nil {
+ enum.Options = &descriptor.EnumOptions{}
+ }
+ if err := proto.SetExtension(enum.Options, extension, &value); err != nil {
+ panic(err)
+ }
+ }
+}
+
+func TurnOffGoEnumPrefix(enum *descriptor.EnumDescriptorProto) {
+ SetBoolEnumOption(gogoproto.E_GoprotoEnumPrefix, false)(enum)
+}
+
+func TurnOffGoEnumStringer(enum *descriptor.EnumDescriptorProto) {
+ SetBoolEnumOption(gogoproto.E_GoprotoEnumStringer, false)(enum)
+}
+
+func TurnOnEnumStringer(enum *descriptor.EnumDescriptorProto) {
+ SetBoolEnumOption(gogoproto.E_EnumStringer, true)(enum)
+}
diff --git a/vendor/github.com/gogo/protobuf/vanity/field.go b/vendor/github.com/gogo/protobuf/vanity/field.go
new file mode 100644
index 00000000000..62cdddfabb4
--- /dev/null
+++ b/vendor/github.com/gogo/protobuf/vanity/field.go
@@ -0,0 +1,90 @@
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2015, The GoGo Authors. rights reserved.
+// http://github.com/gogo/protobuf
+//
+// 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.
+//
+// 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 vanity
+
+import (
+ "github.com/gogo/protobuf/gogoproto"
+ "github.com/gogo/protobuf/proto"
+ descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
+)
+
+func FieldHasBoolExtension(field *descriptor.FieldDescriptorProto, extension *proto.ExtensionDesc) bool {
+ if field.Options == nil {
+ return false
+ }
+ value, err := proto.GetExtension(field.Options, extension)
+ if err != nil {
+ return false
+ }
+ if value == nil {
+ return false
+ }
+ if value.(*bool) == nil {
+ return false
+ }
+ return true
+}
+
+func SetBoolFieldOption(extension *proto.ExtensionDesc, value bool) func(field *descriptor.FieldDescriptorProto) {
+ return func(field *descriptor.FieldDescriptorProto) {
+ if FieldHasBoolExtension(field, extension) {
+ return
+ }
+ if field.Options == nil {
+ field.Options = &descriptor.FieldOptions{}
+ }
+ if err := proto.SetExtension(field.Options, extension, &value); err != nil {
+ panic(err)
+ }
+ }
+}
+
+func TurnOffNullable(field *descriptor.FieldDescriptorProto) {
+ if field.IsRepeated() && !field.IsMessage() {
+ return
+ }
+ SetBoolFieldOption(gogoproto.E_Nullable, false)(field)
+}
+
+func TurnOffNullableForNativeTypes(field *descriptor.FieldDescriptorProto) {
+ if field.IsRepeated() || field.IsMessage() {
+ return
+ }
+ SetBoolFieldOption(gogoproto.E_Nullable, false)(field)
+}
+
+func TurnOffNullableForNativeTypesWithoutDefaultsOnly(field *descriptor.FieldDescriptorProto) {
+ if field.IsRepeated() || field.IsMessage() {
+ return
+ }
+ if field.DefaultValue != nil {
+ return
+ }
+ SetBoolFieldOption(gogoproto.E_Nullable, false)(field)
+}
diff --git a/vendor/github.com/gogo/protobuf/vanity/file.go b/vendor/github.com/gogo/protobuf/vanity/file.go
new file mode 100644
index 00000000000..2055c66152e
--- /dev/null
+++ b/vendor/github.com/gogo/protobuf/vanity/file.go
@@ -0,0 +1,197 @@
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2015, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// 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.
+//
+// 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 vanity
+
+import (
+ "path/filepath"
+
+ "github.com/gogo/protobuf/gogoproto"
+ "github.com/gogo/protobuf/proto"
+ descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
+)
+
+func NotGoogleProtobufDescriptorProto(file *descriptor.FileDescriptorProto) bool {
+ // can not just check if file.GetName() == "google/protobuf/descriptor.proto" because we do not want to assume compile path
+ _, fileName := filepath.Split(file.GetName())
+ return !(file.GetPackage() == "google.protobuf" && fileName == "descriptor.proto")
+}
+
+func FilterFiles(files []*descriptor.FileDescriptorProto, f func(file *descriptor.FileDescriptorProto) bool) []*descriptor.FileDescriptorProto {
+ filtered := make([]*descriptor.FileDescriptorProto, 0, len(files))
+ for i := range files {
+ if !f(files[i]) {
+ continue
+ }
+ filtered = append(filtered, files[i])
+ }
+ return filtered
+}
+
+func FileHasBoolExtension(file *descriptor.FileDescriptorProto, extension *proto.ExtensionDesc) bool {
+ if file.Options == nil {
+ return false
+ }
+ value, err := proto.GetExtension(file.Options, extension)
+ if err != nil {
+ return false
+ }
+ if value == nil {
+ return false
+ }
+ if value.(*bool) == nil {
+ return false
+ }
+ return true
+}
+
+func SetBoolFileOption(extension *proto.ExtensionDesc, value bool) func(file *descriptor.FileDescriptorProto) {
+ return func(file *descriptor.FileDescriptorProto) {
+ if FileHasBoolExtension(file, extension) {
+ return
+ }
+ if file.Options == nil {
+ file.Options = &descriptor.FileOptions{}
+ }
+ if err := proto.SetExtension(file.Options, extension, &value); err != nil {
+ panic(err)
+ }
+ }
+}
+
+func TurnOffGoGettersAll(file *descriptor.FileDescriptorProto) {
+ SetBoolFileOption(gogoproto.E_GoprotoGettersAll, false)(file)
+}
+
+func TurnOffGoEnumPrefixAll(file *descriptor.FileDescriptorProto) {
+ SetBoolFileOption(gogoproto.E_GoprotoEnumPrefixAll, false)(file)
+}
+
+func TurnOffGoStringerAll(file *descriptor.FileDescriptorProto) {
+ SetBoolFileOption(gogoproto.E_GoprotoStringerAll, false)(file)
+}
+
+func TurnOnVerboseEqualAll(file *descriptor.FileDescriptorProto) {
+ SetBoolFileOption(gogoproto.E_VerboseEqualAll, true)(file)
+}
+
+func TurnOnFaceAll(file *descriptor.FileDescriptorProto) {
+ SetBoolFileOption(gogoproto.E_FaceAll, true)(file)
+}
+
+func TurnOnGoStringAll(file *descriptor.FileDescriptorProto) {
+ SetBoolFileOption(gogoproto.E_GostringAll, true)(file)
+}
+
+func TurnOnPopulateAll(file *descriptor.FileDescriptorProto) {
+ SetBoolFileOption(gogoproto.E_PopulateAll, true)(file)
+}
+
+func TurnOnStringerAll(file *descriptor.FileDescriptorProto) {
+ SetBoolFileOption(gogoproto.E_StringerAll, true)(file)
+}
+
+func TurnOnEqualAll(file *descriptor.FileDescriptorProto) {
+ SetBoolFileOption(gogoproto.E_EqualAll, true)(file)
+}
+
+func TurnOnDescriptionAll(file *descriptor.FileDescriptorProto) {
+ SetBoolFileOption(gogoproto.E_DescriptionAll, true)(file)
+}
+
+func TurnOnTestGenAll(file *descriptor.FileDescriptorProto) {
+ SetBoolFileOption(gogoproto.E_TestgenAll, true)(file)
+}
+
+func TurnOnBenchGenAll(file *descriptor.FileDescriptorProto) {
+ SetBoolFileOption(gogoproto.E_BenchgenAll, true)(file)
+}
+
+func TurnOnMarshalerAll(file *descriptor.FileDescriptorProto) {
+ SetBoolFileOption(gogoproto.E_MarshalerAll, true)(file)
+}
+
+func TurnOnUnmarshalerAll(file *descriptor.FileDescriptorProto) {
+ SetBoolFileOption(gogoproto.E_UnmarshalerAll, true)(file)
+}
+
+func TurnOnStable_MarshalerAll(file *descriptor.FileDescriptorProto) {
+ SetBoolFileOption(gogoproto.E_StableMarshalerAll, true)(file)
+}
+
+func TurnOnSizerAll(file *descriptor.FileDescriptorProto) {
+ SetBoolFileOption(gogoproto.E_SizerAll, true)(file)
+}
+
+func TurnOffGoEnumStringerAll(file *descriptor.FileDescriptorProto) {
+ SetBoolFileOption(gogoproto.E_GoprotoEnumStringerAll, false)(file)
+}
+
+func TurnOnEnumStringerAll(file *descriptor.FileDescriptorProto) {
+ SetBoolFileOption(gogoproto.E_EnumStringerAll, true)(file)
+}
+
+func TurnOnUnsafeUnmarshalerAll(file *descriptor.FileDescriptorProto) {
+ SetBoolFileOption(gogoproto.E_UnsafeUnmarshalerAll, true)(file)
+}
+
+func TurnOnUnsafeMarshalerAll(file *descriptor.FileDescriptorProto) {
+ SetBoolFileOption(gogoproto.E_UnsafeMarshalerAll, true)(file)
+}
+
+func TurnOffGoExtensionsMapAll(file *descriptor.FileDescriptorProto) {
+ SetBoolFileOption(gogoproto.E_GoprotoExtensionsMapAll, false)(file)
+}
+
+func TurnOffGoUnrecognizedAll(file *descriptor.FileDescriptorProto) {
+ SetBoolFileOption(gogoproto.E_GoprotoUnrecognizedAll, false)(file)
+}
+
+func TurnOffGoUnkeyedAll(file *descriptor.FileDescriptorProto) {
+ SetBoolFileOption(gogoproto.E_GoprotoUnkeyedAll, false)(file)
+}
+
+func TurnOffGoSizecacheAll(file *descriptor.FileDescriptorProto) {
+ SetBoolFileOption(gogoproto.E_GoprotoSizecacheAll, false)(file)
+}
+
+func TurnOffGogoImport(file *descriptor.FileDescriptorProto) {
+ SetBoolFileOption(gogoproto.E_GogoprotoImport, false)(file)
+}
+
+func TurnOnCompareAll(file *descriptor.FileDescriptorProto) {
+ SetBoolFileOption(gogoproto.E_CompareAll, true)(file)
+}
+
+func TurnOnMessageNameAll(file *descriptor.FileDescriptorProto) {
+ SetBoolFileOption(gogoproto.E_MessagenameAll, true)(file)
+}
+
+func TurnOnGoRegistration(file *descriptor.FileDescriptorProto) {
+ SetBoolFileOption(gogoproto.E_GoprotoRegistration, true)(file)
+}
diff --git a/vendor/github.com/gogo/protobuf/vanity/foreach.go b/vendor/github.com/gogo/protobuf/vanity/foreach.go
new file mode 100644
index 00000000000..888b6d04d59
--- /dev/null
+++ b/vendor/github.com/gogo/protobuf/vanity/foreach.go
@@ -0,0 +1,125 @@
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2015, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// 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.
+//
+// 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 vanity
+
+import descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
+
+func ForEachFile(files []*descriptor.FileDescriptorProto, f func(file *descriptor.FileDescriptorProto)) {
+ for _, file := range files {
+ f(file)
+ }
+}
+
+func OnlyProto2(files []*descriptor.FileDescriptorProto) []*descriptor.FileDescriptorProto {
+ outs := make([]*descriptor.FileDescriptorProto, 0, len(files))
+ for i, file := range files {
+ if file.GetSyntax() == "proto3" {
+ continue
+ }
+ outs = append(outs, files[i])
+ }
+ return outs
+}
+
+func OnlyProto3(files []*descriptor.FileDescriptorProto) []*descriptor.FileDescriptorProto {
+ outs := make([]*descriptor.FileDescriptorProto, 0, len(files))
+ for i, file := range files {
+ if file.GetSyntax() != "proto3" {
+ continue
+ }
+ outs = append(outs, files[i])
+ }
+ return outs
+}
+
+func ForEachMessageInFiles(files []*descriptor.FileDescriptorProto, f func(msg *descriptor.DescriptorProto)) {
+ for _, file := range files {
+ ForEachMessage(file.MessageType, f)
+ }
+}
+
+func ForEachMessage(msgs []*descriptor.DescriptorProto, f func(msg *descriptor.DescriptorProto)) {
+ for _, msg := range msgs {
+ f(msg)
+ ForEachMessage(msg.NestedType, f)
+ }
+}
+
+func ForEachFieldInFilesExcludingExtensions(files []*descriptor.FileDescriptorProto, f func(field *descriptor.FieldDescriptorProto)) {
+ for _, file := range files {
+ ForEachFieldExcludingExtensions(file.MessageType, f)
+ }
+}
+
+func ForEachFieldInFiles(files []*descriptor.FileDescriptorProto, f func(field *descriptor.FieldDescriptorProto)) {
+ for _, file := range files {
+ for _, ext := range file.Extension {
+ f(ext)
+ }
+ ForEachField(file.MessageType, f)
+ }
+}
+
+func ForEachFieldExcludingExtensions(msgs []*descriptor.DescriptorProto, f func(field *descriptor.FieldDescriptorProto)) {
+ for _, msg := range msgs {
+ for _, field := range msg.Field {
+ f(field)
+ }
+ ForEachField(msg.NestedType, f)
+ }
+}
+
+func ForEachField(msgs []*descriptor.DescriptorProto, f func(field *descriptor.FieldDescriptorProto)) {
+ for _, msg := range msgs {
+ for _, field := range msg.Field {
+ f(field)
+ }
+ for _, ext := range msg.Extension {
+ f(ext)
+ }
+ ForEachField(msg.NestedType, f)
+ }
+}
+
+func ForEachEnumInFiles(files []*descriptor.FileDescriptorProto, f func(enum *descriptor.EnumDescriptorProto)) {
+ for _, file := range files {
+ for _, enum := range file.EnumType {
+ f(enum)
+ }
+ }
+}
+
+func ForEachEnum(msgs []*descriptor.DescriptorProto, f func(field *descriptor.EnumDescriptorProto)) {
+ for _, msg := range msgs {
+ for _, field := range msg.EnumType {
+ f(field)
+ }
+ ForEachEnum(msg.NestedType, f)
+ }
+}
diff --git a/vendor/github.com/gogo/protobuf/vanity/msg.go b/vendor/github.com/gogo/protobuf/vanity/msg.go
new file mode 100644
index 00000000000..390ff5ad44f
--- /dev/null
+++ b/vendor/github.com/gogo/protobuf/vanity/msg.go
@@ -0,0 +1,154 @@
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2015, The GoGo Authors. rights reserved.
+// http://github.com/gogo/protobuf
+//
+// 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.
+//
+// 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 vanity
+
+import (
+ "github.com/gogo/protobuf/gogoproto"
+ "github.com/gogo/protobuf/proto"
+ descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
+)
+
+func MessageHasBoolExtension(msg *descriptor.DescriptorProto, extension *proto.ExtensionDesc) bool {
+ if msg.Options == nil {
+ return false
+ }
+ value, err := proto.GetExtension(msg.Options, extension)
+ if err != nil {
+ return false
+ }
+ if value == nil {
+ return false
+ }
+ if value.(*bool) == nil {
+ return false
+ }
+ return true
+}
+
+func SetBoolMessageOption(extension *proto.ExtensionDesc, value bool) func(msg *descriptor.DescriptorProto) {
+ return func(msg *descriptor.DescriptorProto) {
+ if MessageHasBoolExtension(msg, extension) {
+ return
+ }
+ if msg.Options == nil {
+ msg.Options = &descriptor.MessageOptions{}
+ }
+ if err := proto.SetExtension(msg.Options, extension, &value); err != nil {
+ panic(err)
+ }
+ }
+}
+
+func TurnOffGoGetters(msg *descriptor.DescriptorProto) {
+ SetBoolMessageOption(gogoproto.E_GoprotoGetters, false)(msg)
+}
+
+func TurnOffGoStringer(msg *descriptor.DescriptorProto) {
+ SetBoolMessageOption(gogoproto.E_GoprotoStringer, false)(msg)
+}
+
+func TurnOnVerboseEqual(msg *descriptor.DescriptorProto) {
+ SetBoolMessageOption(gogoproto.E_VerboseEqual, true)(msg)
+}
+
+func TurnOnFace(msg *descriptor.DescriptorProto) {
+ SetBoolMessageOption(gogoproto.E_Face, true)(msg)
+}
+
+func TurnOnGoString(msg *descriptor.DescriptorProto) {
+ SetBoolMessageOption(gogoproto.E_Face, true)(msg)
+}
+
+func TurnOnPopulate(msg *descriptor.DescriptorProto) {
+ SetBoolMessageOption(gogoproto.E_Populate, true)(msg)
+}
+
+func TurnOnStringer(msg *descriptor.DescriptorProto) {
+ SetBoolMessageOption(gogoproto.E_Stringer, true)(msg)
+}
+
+func TurnOnEqual(msg *descriptor.DescriptorProto) {
+ SetBoolMessageOption(gogoproto.E_Equal, true)(msg)
+}
+
+func TurnOnDescription(msg *descriptor.DescriptorProto) {
+ SetBoolMessageOption(gogoproto.E_Description, true)(msg)
+}
+
+func TurnOnTestGen(msg *descriptor.DescriptorProto) {
+ SetBoolMessageOption(gogoproto.E_Testgen, true)(msg)
+}
+
+func TurnOnBenchGen(msg *descriptor.DescriptorProto) {
+ SetBoolMessageOption(gogoproto.E_Benchgen, true)(msg)
+}
+
+func TurnOnMarshaler(msg *descriptor.DescriptorProto) {
+ SetBoolMessageOption(gogoproto.E_Marshaler, true)(msg)
+}
+
+func TurnOnUnmarshaler(msg *descriptor.DescriptorProto) {
+ SetBoolMessageOption(gogoproto.E_Unmarshaler, true)(msg)
+}
+
+func TurnOnSizer(msg *descriptor.DescriptorProto) {
+ SetBoolMessageOption(gogoproto.E_Sizer, true)(msg)
+}
+
+func TurnOnUnsafeUnmarshaler(msg *descriptor.DescriptorProto) {
+ SetBoolMessageOption(gogoproto.E_UnsafeUnmarshaler, true)(msg)
+}
+
+func TurnOnUnsafeMarshaler(msg *descriptor.DescriptorProto) {
+ SetBoolMessageOption(gogoproto.E_UnsafeMarshaler, true)(msg)
+}
+
+func TurnOffGoExtensionsMap(msg *descriptor.DescriptorProto) {
+ SetBoolMessageOption(gogoproto.E_GoprotoExtensionsMap, false)(msg)
+}
+
+func TurnOffGoUnrecognized(msg *descriptor.DescriptorProto) {
+ SetBoolMessageOption(gogoproto.E_GoprotoUnrecognized, false)(msg)
+}
+
+func TurnOffGoUnkeyed(msg *descriptor.DescriptorProto) {
+ SetBoolMessageOption(gogoproto.E_GoprotoUnkeyed, false)(msg)
+}
+
+func TurnOffGoSizecache(msg *descriptor.DescriptorProto) {
+ SetBoolMessageOption(gogoproto.E_GoprotoSizecache, false)(msg)
+}
+
+func TurnOnCompare(msg *descriptor.DescriptorProto) {
+ SetBoolMessageOption(gogoproto.E_Compare, true)(msg)
+}
+
+func TurnOnMessageName(msg *descriptor.DescriptorProto) {
+ SetBoolMessageOption(gogoproto.E_Messagename, true)(msg)
+}
diff --git a/vendor/github.com/golang/protobuf/jsonpb/decode.go b/vendor/github.com/golang/protobuf/jsonpb/decode.go
new file mode 100644
index 00000000000..c6f66f10393
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/jsonpb/decode.go
@@ -0,0 +1,531 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package jsonpb
+
+import (
+ "encoding/json"
+ "errors"
+ "fmt"
+ "io"
+ "math"
+ "reflect"
+ "strconv"
+ "strings"
+ "time"
+
+ "github.com/golang/protobuf/proto"
+ "google.golang.org/protobuf/encoding/protojson"
+ protoV2 "google.golang.org/protobuf/proto"
+ "google.golang.org/protobuf/reflect/protoreflect"
+ "google.golang.org/protobuf/reflect/protoregistry"
+)
+
+const wrapJSONUnmarshalV2 = false
+
+// UnmarshalNext unmarshals the next JSON object from d into m.
+func UnmarshalNext(d *json.Decoder, m proto.Message) error {
+ return new(Unmarshaler).UnmarshalNext(d, m)
+}
+
+// Unmarshal unmarshals a JSON object from r into m.
+func Unmarshal(r io.Reader, m proto.Message) error {
+ return new(Unmarshaler).Unmarshal(r, m)
+}
+
+// UnmarshalString unmarshals a JSON object from s into m.
+func UnmarshalString(s string, m proto.Message) error {
+ return new(Unmarshaler).Unmarshal(strings.NewReader(s), m)
+}
+
+// Unmarshaler is a configurable object for converting from a JSON
+// representation to a protocol buffer object.
+type Unmarshaler struct {
+ // AllowUnknownFields specifies whether to allow messages to contain
+ // unknown JSON fields, as opposed to failing to unmarshal.
+ AllowUnknownFields bool
+
+ // AnyResolver is used to resolve the google.protobuf.Any well-known type.
+ // If unset, the global registry is used by default.
+ AnyResolver AnyResolver
+}
+
+// JSONPBUnmarshaler is implemented by protobuf messages that customize the way
+// they are unmarshaled from JSON. Messages that implement this should also
+// implement JSONPBMarshaler so that the custom format can be produced.
+//
+// The JSON unmarshaling must follow the JSON to proto specification:
+//
+// https://developers.google.com/protocol-buffers/docs/proto3#json
+//
+// Deprecated: Custom types should implement protobuf reflection instead.
+type JSONPBUnmarshaler interface {
+ UnmarshalJSONPB(*Unmarshaler, []byte) error
+}
+
+// Unmarshal unmarshals a JSON object from r into m.
+func (u *Unmarshaler) Unmarshal(r io.Reader, m proto.Message) error {
+ return u.UnmarshalNext(json.NewDecoder(r), m)
+}
+
+// UnmarshalNext unmarshals the next JSON object from d into m.
+func (u *Unmarshaler) UnmarshalNext(d *json.Decoder, m proto.Message) error {
+ if m == nil {
+ return errors.New("invalid nil message")
+ }
+
+ // Parse the next JSON object from the stream.
+ raw := json.RawMessage{}
+ if err := d.Decode(&raw); err != nil {
+ return err
+ }
+
+ // Check for custom unmarshalers first since they may not properly
+ // implement protobuf reflection that the logic below relies on.
+ if jsu, ok := m.(JSONPBUnmarshaler); ok {
+ return jsu.UnmarshalJSONPB(u, raw)
+ }
+
+ mr := proto.MessageReflect(m)
+
+ // NOTE: For historical reasons, a top-level null is treated as a noop.
+ // This is incorrect, but kept for compatibility.
+ if string(raw) == "null" && mr.Descriptor().FullName() != "google.protobuf.Value" {
+ return nil
+ }
+
+ if wrapJSONUnmarshalV2 {
+ // NOTE: If input message is non-empty, we need to preserve merge semantics
+ // of the old jsonpb implementation. These semantics are not supported by
+ // the protobuf JSON specification.
+ isEmpty := true
+ mr.Range(func(protoreflect.FieldDescriptor, protoreflect.Value) bool {
+ isEmpty = false // at least one iteration implies non-empty
+ return false
+ })
+ if !isEmpty {
+ // Perform unmarshaling into a newly allocated, empty message.
+ mr = mr.New()
+
+ // Use a defer to copy all unmarshaled fields into the original message.
+ dst := proto.MessageReflect(m)
+ defer mr.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {
+ dst.Set(fd, v)
+ return true
+ })
+ }
+
+ // Unmarshal using the v2 JSON unmarshaler.
+ opts := protojson.UnmarshalOptions{
+ DiscardUnknown: u.AllowUnknownFields,
+ }
+ if u.AnyResolver != nil {
+ opts.Resolver = anyResolver{u.AnyResolver}
+ }
+ return opts.Unmarshal(raw, mr.Interface())
+ } else {
+ if err := u.unmarshalMessage(mr, raw); err != nil {
+ return err
+ }
+ return protoV2.CheckInitialized(mr.Interface())
+ }
+}
+
+func (u *Unmarshaler) unmarshalMessage(m protoreflect.Message, in []byte) error {
+ md := m.Descriptor()
+ fds := md.Fields()
+
+ if jsu, ok := proto.MessageV1(m.Interface()).(JSONPBUnmarshaler); ok {
+ return jsu.UnmarshalJSONPB(u, in)
+ }
+
+ if string(in) == "null" && md.FullName() != "google.protobuf.Value" {
+ return nil
+ }
+
+ switch wellKnownType(md.FullName()) {
+ case "Any":
+ var jsonObject map[string]json.RawMessage
+ if err := json.Unmarshal(in, &jsonObject); err != nil {
+ return err
+ }
+
+ rawTypeURL, ok := jsonObject["@type"]
+ if !ok {
+ return errors.New("Any JSON doesn't have '@type'")
+ }
+ typeURL, err := unquoteString(string(rawTypeURL))
+ if err != nil {
+ return fmt.Errorf("can't unmarshal Any's '@type': %q", rawTypeURL)
+ }
+ m.Set(fds.ByNumber(1), protoreflect.ValueOfString(typeURL))
+
+ var m2 protoreflect.Message
+ if u.AnyResolver != nil {
+ mi, err := u.AnyResolver.Resolve(typeURL)
+ if err != nil {
+ return err
+ }
+ m2 = proto.MessageReflect(mi)
+ } else {
+ mt, err := protoregistry.GlobalTypes.FindMessageByURL(typeURL)
+ if err != nil {
+ if err == protoregistry.NotFound {
+ return fmt.Errorf("could not resolve Any message type: %v", typeURL)
+ }
+ return err
+ }
+ m2 = mt.New()
+ }
+
+ if wellKnownType(m2.Descriptor().FullName()) != "" {
+ rawValue, ok := jsonObject["value"]
+ if !ok {
+ return errors.New("Any JSON doesn't have 'value'")
+ }
+ if err := u.unmarshalMessage(m2, rawValue); err != nil {
+ return fmt.Errorf("can't unmarshal Any nested proto %v: %v", typeURL, err)
+ }
+ } else {
+ delete(jsonObject, "@type")
+ rawJSON, err := json.Marshal(jsonObject)
+ if err != nil {
+ return fmt.Errorf("can't generate JSON for Any's nested proto to be unmarshaled: %v", err)
+ }
+ if err = u.unmarshalMessage(m2, rawJSON); err != nil {
+ return fmt.Errorf("can't unmarshal Any nested proto %v: %v", typeURL, err)
+ }
+ }
+
+ rawWire, err := protoV2.Marshal(m2.Interface())
+ if err != nil {
+ return fmt.Errorf("can't marshal proto %v into Any.Value: %v", typeURL, err)
+ }
+ m.Set(fds.ByNumber(2), protoreflect.ValueOfBytes(rawWire))
+ return nil
+ case "BoolValue", "BytesValue", "StringValue",
+ "Int32Value", "UInt32Value", "FloatValue",
+ "Int64Value", "UInt64Value", "DoubleValue":
+ fd := fds.ByNumber(1)
+ v, err := u.unmarshalValue(m.NewField(fd), in, fd)
+ if err != nil {
+ return err
+ }
+ m.Set(fd, v)
+ return nil
+ case "Duration":
+ v, err := unquoteString(string(in))
+ if err != nil {
+ return err
+ }
+ d, err := time.ParseDuration(v)
+ if err != nil {
+ return fmt.Errorf("bad Duration: %v", err)
+ }
+
+ sec := d.Nanoseconds() / 1e9
+ nsec := d.Nanoseconds() % 1e9
+ m.Set(fds.ByNumber(1), protoreflect.ValueOfInt64(int64(sec)))
+ m.Set(fds.ByNumber(2), protoreflect.ValueOfInt32(int32(nsec)))
+ return nil
+ case "Timestamp":
+ v, err := unquoteString(string(in))
+ if err != nil {
+ return err
+ }
+ t, err := time.Parse(time.RFC3339Nano, v)
+ if err != nil {
+ return fmt.Errorf("bad Timestamp: %v", err)
+ }
+
+ sec := t.Unix()
+ nsec := t.Nanosecond()
+ m.Set(fds.ByNumber(1), protoreflect.ValueOfInt64(int64(sec)))
+ m.Set(fds.ByNumber(2), protoreflect.ValueOfInt32(int32(nsec)))
+ return nil
+ case "Value":
+ switch {
+ case string(in) == "null":
+ m.Set(fds.ByNumber(1), protoreflect.ValueOfEnum(0))
+ case string(in) == "true":
+ m.Set(fds.ByNumber(4), protoreflect.ValueOfBool(true))
+ case string(in) == "false":
+ m.Set(fds.ByNumber(4), protoreflect.ValueOfBool(false))
+ case hasPrefixAndSuffix('"', in, '"'):
+ s, err := unquoteString(string(in))
+ if err != nil {
+ return fmt.Errorf("unrecognized type for Value %q", in)
+ }
+ m.Set(fds.ByNumber(3), protoreflect.ValueOfString(s))
+ case hasPrefixAndSuffix('[', in, ']'):
+ v := m.Mutable(fds.ByNumber(6))
+ return u.unmarshalMessage(v.Message(), in)
+ case hasPrefixAndSuffix('{', in, '}'):
+ v := m.Mutable(fds.ByNumber(5))
+ return u.unmarshalMessage(v.Message(), in)
+ default:
+ f, err := strconv.ParseFloat(string(in), 0)
+ if err != nil {
+ return fmt.Errorf("unrecognized type for Value %q", in)
+ }
+ m.Set(fds.ByNumber(2), protoreflect.ValueOfFloat64(f))
+ }
+ return nil
+ case "ListValue":
+ var jsonArray []json.RawMessage
+ if err := json.Unmarshal(in, &jsonArray); err != nil {
+ return fmt.Errorf("bad ListValue: %v", err)
+ }
+
+ lv := m.Mutable(fds.ByNumber(1)).List()
+ for _, raw := range jsonArray {
+ ve := lv.NewElement()
+ if err := u.unmarshalMessage(ve.Message(), raw); err != nil {
+ return err
+ }
+ lv.Append(ve)
+ }
+ return nil
+ case "Struct":
+ var jsonObject map[string]json.RawMessage
+ if err := json.Unmarshal(in, &jsonObject); err != nil {
+ return fmt.Errorf("bad StructValue: %v", err)
+ }
+
+ mv := m.Mutable(fds.ByNumber(1)).Map()
+ for key, raw := range jsonObject {
+ kv := protoreflect.ValueOf(key).MapKey()
+ vv := mv.NewValue()
+ if err := u.unmarshalMessage(vv.Message(), raw); err != nil {
+ return fmt.Errorf("bad value in StructValue for key %q: %v", key, err)
+ }
+ mv.Set(kv, vv)
+ }
+ return nil
+ }
+
+ var jsonObject map[string]json.RawMessage
+ if err := json.Unmarshal(in, &jsonObject); err != nil {
+ return err
+ }
+
+ // Handle known fields.
+ for i := 0; i < fds.Len(); i++ {
+ fd := fds.Get(i)
+ if fd.IsWeak() && fd.Message().IsPlaceholder() {
+ continue // weak reference is not linked in
+ }
+
+ // Search for any raw JSON value associated with this field.
+ var raw json.RawMessage
+ name := string(fd.Name())
+ if fd.Kind() == protoreflect.GroupKind {
+ name = string(fd.Message().Name())
+ }
+ if v, ok := jsonObject[name]; ok {
+ delete(jsonObject, name)
+ raw = v
+ }
+ name = string(fd.JSONName())
+ if v, ok := jsonObject[name]; ok {
+ delete(jsonObject, name)
+ raw = v
+ }
+
+ field := m.NewField(fd)
+ // Unmarshal the field value.
+ if raw == nil || (string(raw) == "null" && !isSingularWellKnownValue(fd) && !isSingularJSONPBUnmarshaler(field, fd)) {
+ continue
+ }
+ v, err := u.unmarshalValue(field, raw, fd)
+ if err != nil {
+ return err
+ }
+ m.Set(fd, v)
+ }
+
+ // Handle extension fields.
+ for name, raw := range jsonObject {
+ if !strings.HasPrefix(name, "[") || !strings.HasSuffix(name, "]") {
+ continue
+ }
+
+ // Resolve the extension field by name.
+ xname := protoreflect.FullName(name[len("[") : len(name)-len("]")])
+ xt, _ := protoregistry.GlobalTypes.FindExtensionByName(xname)
+ if xt == nil && isMessageSet(md) {
+ xt, _ = protoregistry.GlobalTypes.FindExtensionByName(xname.Append("message_set_extension"))
+ }
+ if xt == nil {
+ continue
+ }
+ delete(jsonObject, name)
+ fd := xt.TypeDescriptor()
+ if fd.ContainingMessage().FullName() != m.Descriptor().FullName() {
+ return fmt.Errorf("extension field %q does not extend message %q", xname, m.Descriptor().FullName())
+ }
+
+ field := m.NewField(fd)
+ // Unmarshal the field value.
+ if raw == nil || (string(raw) == "null" && !isSingularWellKnownValue(fd) && !isSingularJSONPBUnmarshaler(field, fd)) {
+ continue
+ }
+ v, err := u.unmarshalValue(field, raw, fd)
+ if err != nil {
+ return err
+ }
+ m.Set(fd, v)
+ }
+
+ if !u.AllowUnknownFields && len(jsonObject) > 0 {
+ for name := range jsonObject {
+ return fmt.Errorf("unknown field %q in %v", name, md.FullName())
+ }
+ }
+ return nil
+}
+
+func isSingularWellKnownValue(fd protoreflect.FieldDescriptor) bool {
+ if fd.Cardinality() == protoreflect.Repeated {
+ return false
+ }
+ if md := fd.Message(); md != nil {
+ return md.FullName() == "google.protobuf.Value"
+ }
+ if ed := fd.Enum(); ed != nil {
+ return ed.FullName() == "google.protobuf.NullValue"
+ }
+ return false
+}
+
+func isSingularJSONPBUnmarshaler(v protoreflect.Value, fd protoreflect.FieldDescriptor) bool {
+ if fd.Message() != nil && fd.Cardinality() != protoreflect.Repeated {
+ _, ok := proto.MessageV1(v.Interface()).(JSONPBUnmarshaler)
+ return ok
+ }
+ return false
+}
+
+func (u *Unmarshaler) unmarshalValue(v protoreflect.Value, in []byte, fd protoreflect.FieldDescriptor) (protoreflect.Value, error) {
+ switch {
+ case fd.IsList():
+ var jsonArray []json.RawMessage
+ if err := json.Unmarshal(in, &jsonArray); err != nil {
+ return v, err
+ }
+ lv := v.List()
+ for _, raw := range jsonArray {
+ ve, err := u.unmarshalSingularValue(lv.NewElement(), raw, fd)
+ if err != nil {
+ return v, err
+ }
+ lv.Append(ve)
+ }
+ return v, nil
+ case fd.IsMap():
+ var jsonObject map[string]json.RawMessage
+ if err := json.Unmarshal(in, &jsonObject); err != nil {
+ return v, err
+ }
+ kfd := fd.MapKey()
+ vfd := fd.MapValue()
+ mv := v.Map()
+ for key, raw := range jsonObject {
+ var kv protoreflect.MapKey
+ if kfd.Kind() == protoreflect.StringKind {
+ kv = protoreflect.ValueOf(key).MapKey()
+ } else {
+ v, err := u.unmarshalSingularValue(kfd.Default(), []byte(key), kfd)
+ if err != nil {
+ return v, err
+ }
+ kv = v.MapKey()
+ }
+
+ vv, err := u.unmarshalSingularValue(mv.NewValue(), raw, vfd)
+ if err != nil {
+ return v, err
+ }
+ mv.Set(kv, vv)
+ }
+ return v, nil
+ default:
+ return u.unmarshalSingularValue(v, in, fd)
+ }
+}
+
+var nonFinite = map[string]float64{
+ `"NaN"`: math.NaN(),
+ `"Infinity"`: math.Inf(+1),
+ `"-Infinity"`: math.Inf(-1),
+}
+
+func (u *Unmarshaler) unmarshalSingularValue(v protoreflect.Value, in []byte, fd protoreflect.FieldDescriptor) (protoreflect.Value, error) {
+ switch fd.Kind() {
+ case protoreflect.BoolKind:
+ return unmarshalValue(in, new(bool))
+ case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
+ return unmarshalValue(trimQuote(in), new(int32))
+ case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
+ return unmarshalValue(trimQuote(in), new(int64))
+ case protoreflect.Uint32Kind, protoreflect.Fixed32Kind:
+ return unmarshalValue(trimQuote(in), new(uint32))
+ case protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
+ return unmarshalValue(trimQuote(in), new(uint64))
+ case protoreflect.FloatKind:
+ if f, ok := nonFinite[string(in)]; ok {
+ return protoreflect.ValueOfFloat32(float32(f)), nil
+ }
+ return unmarshalValue(trimQuote(in), new(float32))
+ case protoreflect.DoubleKind:
+ if f, ok := nonFinite[string(in)]; ok {
+ return protoreflect.ValueOfFloat64(float64(f)), nil
+ }
+ return unmarshalValue(trimQuote(in), new(float64))
+ case protoreflect.StringKind:
+ return unmarshalValue(in, new(string))
+ case protoreflect.BytesKind:
+ return unmarshalValue(in, new([]byte))
+ case protoreflect.EnumKind:
+ if hasPrefixAndSuffix('"', in, '"') {
+ vd := fd.Enum().Values().ByName(protoreflect.Name(trimQuote(in)))
+ if vd == nil {
+ return v, fmt.Errorf("unknown value %q for enum %s", in, fd.Enum().FullName())
+ }
+ return protoreflect.ValueOfEnum(vd.Number()), nil
+ }
+ return unmarshalValue(in, new(protoreflect.EnumNumber))
+ case protoreflect.MessageKind, protoreflect.GroupKind:
+ err := u.unmarshalMessage(v.Message(), in)
+ return v, err
+ default:
+ panic(fmt.Sprintf("invalid kind %v", fd.Kind()))
+ }
+}
+
+func unmarshalValue(in []byte, v interface{}) (protoreflect.Value, error) {
+ err := json.Unmarshal(in, v)
+ return protoreflect.ValueOf(reflect.ValueOf(v).Elem().Interface()), err
+}
+
+func unquoteString(in string) (out string, err error) {
+ err = json.Unmarshal([]byte(in), &out)
+ return out, err
+}
+
+func hasPrefixAndSuffix(prefix byte, in []byte, suffix byte) bool {
+ if len(in) >= 2 && in[0] == prefix && in[len(in)-1] == suffix {
+ return true
+ }
+ return false
+}
+
+// trimQuote is like unquoteString but simply strips surrounding quotes.
+// This is incorrect, but is behavior done by the legacy implementation.
+func trimQuote(in []byte) []byte {
+ if len(in) >= 2 && in[0] == '"' && in[len(in)-1] == '"' {
+ in = in[1 : len(in)-1]
+ }
+ return in
+}
diff --git a/vendor/github.com/golang/protobuf/jsonpb/encode.go b/vendor/github.com/golang/protobuf/jsonpb/encode.go
new file mode 100644
index 00000000000..e9438a93f33
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/jsonpb/encode.go
@@ -0,0 +1,560 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package jsonpb
+
+import (
+ "encoding/json"
+ "errors"
+ "fmt"
+ "io"
+ "math"
+ "reflect"
+ "sort"
+ "strconv"
+ "strings"
+ "time"
+
+ "github.com/golang/protobuf/proto"
+ "google.golang.org/protobuf/encoding/protojson"
+ protoV2 "google.golang.org/protobuf/proto"
+ "google.golang.org/protobuf/reflect/protoreflect"
+ "google.golang.org/protobuf/reflect/protoregistry"
+)
+
+const wrapJSONMarshalV2 = false
+
+// Marshaler is a configurable object for marshaling protocol buffer messages
+// to the specified JSON representation.
+type Marshaler struct {
+ // OrigName specifies whether to use the original protobuf name for fields.
+ OrigName bool
+
+ // EnumsAsInts specifies whether to render enum values as integers,
+ // as opposed to string values.
+ EnumsAsInts bool
+
+ // EmitDefaults specifies whether to render fields with zero values.
+ EmitDefaults bool
+
+ // Indent controls whether the output is compact or not.
+ // If empty, the output is compact JSON. Otherwise, every JSON object
+ // entry and JSON array value will be on its own line.
+ // Each line will be preceded by repeated copies of Indent, where the
+ // number of copies is the current indentation depth.
+ Indent string
+
+ // AnyResolver is used to resolve the google.protobuf.Any well-known type.
+ // If unset, the global registry is used by default.
+ AnyResolver AnyResolver
+}
+
+// JSONPBMarshaler is implemented by protobuf messages that customize the
+// way they are marshaled to JSON. Messages that implement this should also
+// implement JSONPBUnmarshaler so that the custom format can be parsed.
+//
+// The JSON marshaling must follow the proto to JSON specification:
+//
+// https://developers.google.com/protocol-buffers/docs/proto3#json
+//
+// Deprecated: Custom types should implement protobuf reflection instead.
+type JSONPBMarshaler interface {
+ MarshalJSONPB(*Marshaler) ([]byte, error)
+}
+
+// Marshal serializes a protobuf message as JSON into w.
+func (jm *Marshaler) Marshal(w io.Writer, m proto.Message) error {
+ b, err := jm.marshal(m)
+ if len(b) > 0 {
+ if _, err := w.Write(b); err != nil {
+ return err
+ }
+ }
+ return err
+}
+
+// MarshalToString serializes a protobuf message as JSON in string form.
+func (jm *Marshaler) MarshalToString(m proto.Message) (string, error) {
+ b, err := jm.marshal(m)
+ if err != nil {
+ return "", err
+ }
+ return string(b), nil
+}
+
+func (jm *Marshaler) marshal(m proto.Message) ([]byte, error) {
+ v := reflect.ValueOf(m)
+ if m == nil || (v.Kind() == reflect.Ptr && v.IsNil()) {
+ return nil, errors.New("Marshal called with nil")
+ }
+
+ // Check for custom marshalers first since they may not properly
+ // implement protobuf reflection that the logic below relies on.
+ if jsm, ok := m.(JSONPBMarshaler); ok {
+ return jsm.MarshalJSONPB(jm)
+ }
+
+ if wrapJSONMarshalV2 {
+ opts := protojson.MarshalOptions{
+ UseProtoNames: jm.OrigName,
+ UseEnumNumbers: jm.EnumsAsInts,
+ EmitUnpopulated: jm.EmitDefaults,
+ Indent: jm.Indent,
+ }
+ if jm.AnyResolver != nil {
+ opts.Resolver = anyResolver{jm.AnyResolver}
+ }
+ return opts.Marshal(proto.MessageReflect(m).Interface())
+ } else {
+ // Check for unpopulated required fields first.
+ m2 := proto.MessageReflect(m)
+ if err := protoV2.CheckInitialized(m2.Interface()); err != nil {
+ return nil, err
+ }
+
+ w := jsonWriter{Marshaler: jm}
+ err := w.marshalMessage(m2, "", "")
+ return w.buf, err
+ }
+}
+
+type jsonWriter struct {
+ *Marshaler
+ buf []byte
+}
+
+func (w *jsonWriter) write(s string) {
+ w.buf = append(w.buf, s...)
+}
+
+func (w *jsonWriter) marshalMessage(m protoreflect.Message, indent, typeURL string) error {
+ if jsm, ok := proto.MessageV1(m.Interface()).(JSONPBMarshaler); ok {
+ b, err := jsm.MarshalJSONPB(w.Marshaler)
+ if err != nil {
+ return err
+ }
+ if typeURL != "" {
+ // we are marshaling this object to an Any type
+ var js map[string]*json.RawMessage
+ if err = json.Unmarshal(b, &js); err != nil {
+ return fmt.Errorf("type %T produced invalid JSON: %v", m.Interface(), err)
+ }
+ turl, err := json.Marshal(typeURL)
+ if err != nil {
+ return fmt.Errorf("failed to marshal type URL %q to JSON: %v", typeURL, err)
+ }
+ js["@type"] = (*json.RawMessage)(&turl)
+ if b, err = json.Marshal(js); err != nil {
+ return err
+ }
+ }
+ w.write(string(b))
+ return nil
+ }
+
+ md := m.Descriptor()
+ fds := md.Fields()
+
+ // Handle well-known types.
+ const secondInNanos = int64(time.Second / time.Nanosecond)
+ switch wellKnownType(md.FullName()) {
+ case "Any":
+ return w.marshalAny(m, indent)
+ case "BoolValue", "BytesValue", "StringValue",
+ "Int32Value", "UInt32Value", "FloatValue",
+ "Int64Value", "UInt64Value", "DoubleValue":
+ fd := fds.ByNumber(1)
+ return w.marshalValue(fd, m.Get(fd), indent)
+ case "Duration":
+ const maxSecondsInDuration = 315576000000
+ // "Generated output always contains 0, 3, 6, or 9 fractional digits,
+ // depending on required precision."
+ s := m.Get(fds.ByNumber(1)).Int()
+ ns := m.Get(fds.ByNumber(2)).Int()
+ if s < -maxSecondsInDuration || s > maxSecondsInDuration {
+ return fmt.Errorf("seconds out of range %v", s)
+ }
+ if ns <= -secondInNanos || ns >= secondInNanos {
+ return fmt.Errorf("ns out of range (%v, %v)", -secondInNanos, secondInNanos)
+ }
+ if (s > 0 && ns < 0) || (s < 0 && ns > 0) {
+ return errors.New("signs of seconds and nanos do not match")
+ }
+ var sign string
+ if s < 0 || ns < 0 {
+ sign, s, ns = "-", -1*s, -1*ns
+ }
+ x := fmt.Sprintf("%s%d.%09d", sign, s, ns)
+ x = strings.TrimSuffix(x, "000")
+ x = strings.TrimSuffix(x, "000")
+ x = strings.TrimSuffix(x, ".000")
+ w.write(fmt.Sprintf(`"%vs"`, x))
+ return nil
+ case "Timestamp":
+ // "RFC 3339, where generated output will always be Z-normalized
+ // and uses 0, 3, 6 or 9 fractional digits."
+ s := m.Get(fds.ByNumber(1)).Int()
+ ns := m.Get(fds.ByNumber(2)).Int()
+ if ns < 0 || ns >= secondInNanos {
+ return fmt.Errorf("ns out of range [0, %v)", secondInNanos)
+ }
+ t := time.Unix(s, ns).UTC()
+ // time.RFC3339Nano isn't exactly right (we need to get 3/6/9 fractional digits).
+ x := t.Format("2006-01-02T15:04:05.000000000")
+ x = strings.TrimSuffix(x, "000")
+ x = strings.TrimSuffix(x, "000")
+ x = strings.TrimSuffix(x, ".000")
+ w.write(fmt.Sprintf(`"%vZ"`, x))
+ return nil
+ case "Value":
+ // JSON value; which is a null, number, string, bool, object, or array.
+ od := md.Oneofs().Get(0)
+ fd := m.WhichOneof(od)
+ if fd == nil {
+ return errors.New("nil Value")
+ }
+ return w.marshalValue(fd, m.Get(fd), indent)
+ case "Struct", "ListValue":
+ // JSON object or array.
+ fd := fds.ByNumber(1)
+ return w.marshalValue(fd, m.Get(fd), indent)
+ }
+
+ w.write("{")
+ if w.Indent != "" {
+ w.write("\n")
+ }
+
+ firstField := true
+ if typeURL != "" {
+ if err := w.marshalTypeURL(indent, typeURL); err != nil {
+ return err
+ }
+ firstField = false
+ }
+
+ for i := 0; i < fds.Len(); {
+ fd := fds.Get(i)
+ if od := fd.ContainingOneof(); od != nil {
+ fd = m.WhichOneof(od)
+ i += od.Fields().Len()
+ if fd == nil {
+ continue
+ }
+ } else {
+ i++
+ }
+
+ v := m.Get(fd)
+
+ if !m.Has(fd) {
+ if !w.EmitDefaults || fd.ContainingOneof() != nil {
+ continue
+ }
+ if fd.Cardinality() != protoreflect.Repeated && (fd.Message() != nil || fd.Syntax() == protoreflect.Proto2) {
+ v = protoreflect.Value{} // use "null" for singular messages or proto2 scalars
+ }
+ }
+
+ if !firstField {
+ w.writeComma()
+ }
+ if err := w.marshalField(fd, v, indent); err != nil {
+ return err
+ }
+ firstField = false
+ }
+
+ // Handle proto2 extensions.
+ if md.ExtensionRanges().Len() > 0 {
+ // Collect a sorted list of all extension descriptor and values.
+ type ext struct {
+ desc protoreflect.FieldDescriptor
+ val protoreflect.Value
+ }
+ var exts []ext
+ m.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {
+ if fd.IsExtension() {
+ exts = append(exts, ext{fd, v})
+ }
+ return true
+ })
+ sort.Slice(exts, func(i, j int) bool {
+ return exts[i].desc.Number() < exts[j].desc.Number()
+ })
+
+ for _, ext := range exts {
+ if !firstField {
+ w.writeComma()
+ }
+ if err := w.marshalField(ext.desc, ext.val, indent); err != nil {
+ return err
+ }
+ firstField = false
+ }
+ }
+
+ if w.Indent != "" {
+ w.write("\n")
+ w.write(indent)
+ }
+ w.write("}")
+ return nil
+}
+
+func (w *jsonWriter) writeComma() {
+ if w.Indent != "" {
+ w.write(",\n")
+ } else {
+ w.write(",")
+ }
+}
+
+func (w *jsonWriter) marshalAny(m protoreflect.Message, indent string) error {
+ // "If the Any contains a value that has a special JSON mapping,
+ // it will be converted as follows: {"@type": xxx, "value": yyy}.
+ // Otherwise, the value will be converted into a JSON object,
+ // and the "@type" field will be inserted to indicate the actual data type."
+ md := m.Descriptor()
+ typeURL := m.Get(md.Fields().ByNumber(1)).String()
+ rawVal := m.Get(md.Fields().ByNumber(2)).Bytes()
+
+ var m2 protoreflect.Message
+ if w.AnyResolver != nil {
+ mi, err := w.AnyResolver.Resolve(typeURL)
+ if err != nil {
+ return err
+ }
+ m2 = proto.MessageReflect(mi)
+ } else {
+ mt, err := protoregistry.GlobalTypes.FindMessageByURL(typeURL)
+ if err != nil {
+ return err
+ }
+ m2 = mt.New()
+ }
+
+ if err := protoV2.Unmarshal(rawVal, m2.Interface()); err != nil {
+ return err
+ }
+
+ if wellKnownType(m2.Descriptor().FullName()) == "" {
+ return w.marshalMessage(m2, indent, typeURL)
+ }
+
+ w.write("{")
+ if w.Indent != "" {
+ w.write("\n")
+ }
+ if err := w.marshalTypeURL(indent, typeURL); err != nil {
+ return err
+ }
+ w.writeComma()
+ if w.Indent != "" {
+ w.write(indent)
+ w.write(w.Indent)
+ w.write(`"value": `)
+ } else {
+ w.write(`"value":`)
+ }
+ if err := w.marshalMessage(m2, indent+w.Indent, ""); err != nil {
+ return err
+ }
+ if w.Indent != "" {
+ w.write("\n")
+ w.write(indent)
+ }
+ w.write("}")
+ return nil
+}
+
+func (w *jsonWriter) marshalTypeURL(indent, typeURL string) error {
+ if w.Indent != "" {
+ w.write(indent)
+ w.write(w.Indent)
+ }
+ w.write(`"@type":`)
+ if w.Indent != "" {
+ w.write(" ")
+ }
+ b, err := json.Marshal(typeURL)
+ if err != nil {
+ return err
+ }
+ w.write(string(b))
+ return nil
+}
+
+// marshalField writes field description and value to the Writer.
+func (w *jsonWriter) marshalField(fd protoreflect.FieldDescriptor, v protoreflect.Value, indent string) error {
+ if w.Indent != "" {
+ w.write(indent)
+ w.write(w.Indent)
+ }
+ w.write(`"`)
+ switch {
+ case fd.IsExtension():
+ // For message set, use the fname of the message as the extension name.
+ name := string(fd.FullName())
+ if isMessageSet(fd.ContainingMessage()) {
+ name = strings.TrimSuffix(name, ".message_set_extension")
+ }
+
+ w.write("[" + name + "]")
+ case w.OrigName:
+ name := string(fd.Name())
+ if fd.Kind() == protoreflect.GroupKind {
+ name = string(fd.Message().Name())
+ }
+ w.write(name)
+ default:
+ w.write(string(fd.JSONName()))
+ }
+ w.write(`":`)
+ if w.Indent != "" {
+ w.write(" ")
+ }
+ return w.marshalValue(fd, v, indent)
+}
+
+func (w *jsonWriter) marshalValue(fd protoreflect.FieldDescriptor, v protoreflect.Value, indent string) error {
+ switch {
+ case fd.IsList():
+ w.write("[")
+ comma := ""
+ lv := v.List()
+ for i := 0; i < lv.Len(); i++ {
+ w.write(comma)
+ if w.Indent != "" {
+ w.write("\n")
+ w.write(indent)
+ w.write(w.Indent)
+ w.write(w.Indent)
+ }
+ if err := w.marshalSingularValue(fd, lv.Get(i), indent+w.Indent); err != nil {
+ return err
+ }
+ comma = ","
+ }
+ if w.Indent != "" {
+ w.write("\n")
+ w.write(indent)
+ w.write(w.Indent)
+ }
+ w.write("]")
+ return nil
+ case fd.IsMap():
+ kfd := fd.MapKey()
+ vfd := fd.MapValue()
+ mv := v.Map()
+
+ // Collect a sorted list of all map keys and values.
+ type entry struct{ key, val protoreflect.Value }
+ var entries []entry
+ mv.Range(func(k protoreflect.MapKey, v protoreflect.Value) bool {
+ entries = append(entries, entry{k.Value(), v})
+ return true
+ })
+ sort.Slice(entries, func(i, j int) bool {
+ switch kfd.Kind() {
+ case protoreflect.BoolKind:
+ return !entries[i].key.Bool() && entries[j].key.Bool()
+ case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind, protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
+ return entries[i].key.Int() < entries[j].key.Int()
+ case protoreflect.Uint32Kind, protoreflect.Fixed32Kind, protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
+ return entries[i].key.Uint() < entries[j].key.Uint()
+ case protoreflect.StringKind:
+ return entries[i].key.String() < entries[j].key.String()
+ default:
+ panic("invalid kind")
+ }
+ })
+
+ w.write(`{`)
+ comma := ""
+ for _, entry := range entries {
+ w.write(comma)
+ if w.Indent != "" {
+ w.write("\n")
+ w.write(indent)
+ w.write(w.Indent)
+ w.write(w.Indent)
+ }
+
+ s := fmt.Sprint(entry.key.Interface())
+ b, err := json.Marshal(s)
+ if err != nil {
+ return err
+ }
+ w.write(string(b))
+
+ w.write(`:`)
+ if w.Indent != "" {
+ w.write(` `)
+ }
+
+ if err := w.marshalSingularValue(vfd, entry.val, indent+w.Indent); err != nil {
+ return err
+ }
+ comma = ","
+ }
+ if w.Indent != "" {
+ w.write("\n")
+ w.write(indent)
+ w.write(w.Indent)
+ }
+ w.write(`}`)
+ return nil
+ default:
+ return w.marshalSingularValue(fd, v, indent)
+ }
+}
+
+func (w *jsonWriter) marshalSingularValue(fd protoreflect.FieldDescriptor, v protoreflect.Value, indent string) error {
+ switch {
+ case !v.IsValid():
+ w.write("null")
+ return nil
+ case fd.Message() != nil:
+ return w.marshalMessage(v.Message(), indent+w.Indent, "")
+ case fd.Enum() != nil:
+ if fd.Enum().FullName() == "google.protobuf.NullValue" {
+ w.write("null")
+ return nil
+ }
+
+ vd := fd.Enum().Values().ByNumber(v.Enum())
+ if vd == nil || w.EnumsAsInts {
+ w.write(strconv.Itoa(int(v.Enum())))
+ } else {
+ w.write(`"` + string(vd.Name()) + `"`)
+ }
+ return nil
+ default:
+ switch v.Interface().(type) {
+ case float32, float64:
+ switch {
+ case math.IsInf(v.Float(), +1):
+ w.write(`"Infinity"`)
+ return nil
+ case math.IsInf(v.Float(), -1):
+ w.write(`"-Infinity"`)
+ return nil
+ case math.IsNaN(v.Float()):
+ w.write(`"NaN"`)
+ return nil
+ }
+ case int64, uint64:
+ w.write(fmt.Sprintf(`"%d"`, v.Interface()))
+ return nil
+ }
+
+ b, err := json.Marshal(v.Interface())
+ if err != nil {
+ return err
+ }
+ w.write(string(b))
+ return nil
+ }
+}
diff --git a/vendor/github.com/golang/protobuf/jsonpb/json.go b/vendor/github.com/golang/protobuf/jsonpb/json.go
new file mode 100644
index 00000000000..480e2448de6
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/jsonpb/json.go
@@ -0,0 +1,69 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package jsonpb provides functionality to marshal and unmarshal between a
+// protocol buffer message and JSON. It follows the specification at
+// https://developers.google.com/protocol-buffers/docs/proto3#json.
+//
+// Do not rely on the default behavior of the standard encoding/json package
+// when called on generated message types as it does not operate correctly.
+//
+// Deprecated: Use the "google.golang.org/protobuf/encoding/protojson"
+// package instead.
+package jsonpb
+
+import (
+ "github.com/golang/protobuf/proto"
+ "google.golang.org/protobuf/reflect/protoreflect"
+ "google.golang.org/protobuf/reflect/protoregistry"
+ "google.golang.org/protobuf/runtime/protoimpl"
+)
+
+// AnyResolver takes a type URL, present in an Any message,
+// and resolves it into an instance of the associated message.
+type AnyResolver interface {
+ Resolve(typeURL string) (proto.Message, error)
+}
+
+type anyResolver struct{ AnyResolver }
+
+func (r anyResolver) FindMessageByName(message protoreflect.FullName) (protoreflect.MessageType, error) {
+ return r.FindMessageByURL(string(message))
+}
+
+func (r anyResolver) FindMessageByURL(url string) (protoreflect.MessageType, error) {
+ m, err := r.Resolve(url)
+ if err != nil {
+ return nil, err
+ }
+ return protoimpl.X.MessageTypeOf(m), nil
+}
+
+func (r anyResolver) FindExtensionByName(field protoreflect.FullName) (protoreflect.ExtensionType, error) {
+ return protoregistry.GlobalTypes.FindExtensionByName(field)
+}
+
+func (r anyResolver) FindExtensionByNumber(message protoreflect.FullName, field protoreflect.FieldNumber) (protoreflect.ExtensionType, error) {
+ return protoregistry.GlobalTypes.FindExtensionByNumber(message, field)
+}
+
+func wellKnownType(s protoreflect.FullName) string {
+ if s.Parent() == "google.protobuf" {
+ switch s.Name() {
+ case "Empty", "Any",
+ "BoolValue", "BytesValue", "StringValue",
+ "Int32Value", "UInt32Value", "FloatValue",
+ "Int64Value", "UInt64Value", "DoubleValue",
+ "Duration", "Timestamp",
+ "NullValue", "Struct", "Value", "ListValue":
+ return string(s.Name())
+ }
+ }
+ return ""
+}
+
+func isMessageSet(md protoreflect.MessageDescriptor) bool {
+ ms, ok := md.(interface{ IsMessageSet() bool })
+ return ok && ms.IsMessageSet()
+}
diff --git a/vendor/github.com/grafana/dskit/grpcutil/status.go b/vendor/github.com/grafana/dskit/grpcutil/status.go
index a9e9aab249a..1b21ef4d6ea 100644
--- a/vendor/github.com/grafana/dskit/grpcutil/status.go
+++ b/vendor/github.com/grafana/dskit/grpcutil/status.go
@@ -35,6 +35,22 @@ func ErrorToStatus(err error) (*status.Status, bool) {
return nil, false
}
+func ErrorToGRPCStatus(err error) (*grpcstatus.Status, bool) {
+ if err == nil {
+ return nil, false
+ }
+ type grpcStatus interface{ GRPCStatus() *grpcstatus.Status }
+ var gs grpcStatus
+ if errors.As(err, &gs) {
+ st := gs.GRPCStatus()
+ if st == nil {
+ return nil, false
+ }
+ return st, true
+ }
+ return nil, false
+}
+
// ErrorToStatusCode extracts gRPC status code from error and returns it.
//
// - If err is nil, codes.OK is returned.
diff --git a/vendor/github.com/grafana/dskit/httpgrpc/httpgrpc.go b/vendor/github.com/grafana/dskit/httpgrpc/httpgrpc.go
index 616023899b7..a7a250ca7a3 100644
--- a/vendor/github.com/grafana/dskit/httpgrpc/httpgrpc.go
+++ b/vendor/github.com/grafana/dskit/httpgrpc/httpgrpc.go
@@ -8,14 +8,15 @@ import (
"bytes"
"context"
"fmt"
+
"io"
"net/http"
"github.com/go-kit/log/level"
- spb "github.com/gogo/googleapis/google/rpc"
- "github.com/gogo/protobuf/types"
- "github.com/gogo/status"
+ spb "google.golang.org/genproto/googleapis/rpc/status"
"google.golang.org/grpc/metadata"
+ "google.golang.org/grpc/status"
+ "google.golang.org/protobuf/types/known/anypb"
"github.com/grafana/dskit/grpcutil"
"github.com/grafana/dskit/log"
@@ -131,7 +132,7 @@ func ErrorFromHTTPResponse(resp *HTTPResponse) error {
// ErrorFromHTTPResponseWithMessage converts an HTTP response into a grpc error, and uses supplied message for Error message.
func ErrorFromHTTPResponseWithMessage(resp *HTTPResponse, msg string) error {
- a, err := types.MarshalAny(resp)
+ a, err := anypb.New(resp)
if err != nil {
return err
}
@@ -139,13 +140,13 @@ func ErrorFromHTTPResponseWithMessage(resp *HTTPResponse, msg string) error {
return status.ErrorProto(&spb.Status{
Code: resp.Code,
Message: msg,
- Details: []*types.Any{a},
+ Details: []*anypb.Any{a},
})
}
// HTTPResponseFromError converts a grpc error into an HTTP response
func HTTPResponseFromError(err error) (*HTTPResponse, bool) {
- s, ok := grpcutil.ErrorToStatus(err)
+ s, ok := grpcutil.ErrorToGRPCStatus(err)
if !ok {
return nil, false
}
@@ -156,7 +157,7 @@ func HTTPResponseFromError(err error) (*HTTPResponse, bool) {
}
var resp HTTPResponse
- if err := types.UnmarshalAny(status.Details[0], &resp); err != nil {
+ if err := status.Details[0].UnmarshalTo(&resp); err != nil {
level.Error(log.Global()).Log("msg", "got error containing non-response", "err", err)
return nil, false
}
diff --git a/vendor/github.com/grafana/dskit/httpgrpc/httpgrpc.pb.fm.go b/vendor/github.com/grafana/dskit/httpgrpc/httpgrpc.pb.fm.go
new file mode 100644
index 00000000000..bdc25f2b765
--- /dev/null
+++ b/vendor/github.com/grafana/dskit/httpgrpc/httpgrpc.pb.fm.go
@@ -0,0 +1,417 @@
+// GENERATED CODE - DO NOT EDIT
+// This file was generated by protoc-gen-fastmarshal
+
+package httpgrpc
+
+import (
+ "fmt"
+ "sync/atomic"
+ "github.com/CrowdStrike/csproto"
+)
+
+//------------------------------------------------------------------------------
+// Custom Protobuf size/marshal/unmarshal code for HTTPRequest
+
+// Size calculates and returns the size, in bytes, required to hold the contents of m using the Protobuf
+// binary encoding.
+func (m *HTTPRequest) Size() int {
+ // nil message is always 0 bytes
+ if m == nil {
+ return 0
+ }
+ // return cached size, if present
+ if csz := int(atomic.LoadInt32(&m.sizeCache)); csz > 0 {
+ return csz
+ }
+ // calculate and cache
+ var sz, l int
+ _ = l // avoid unused variable
+
+ // Method (string,optional)
+ if l = len(m.Method); l > 0 {
+ sz += csproto.SizeOfTagKey(1) + csproto.SizeOfVarint(uint64(l)) + l
+ }
+ // Url (string,optional)
+ if l = len(m.Url); l > 0 {
+ sz += csproto.SizeOfTagKey(2) + csproto.SizeOfVarint(uint64(l)) + l
+ }
+ // Headers (message,repeated)
+ for _, val := range m.Headers {
+ if l = csproto.Size(val); l > 0 {
+ sz += csproto.SizeOfTagKey(3) + csproto.SizeOfVarint(uint64(l)) + l
+ }
+ }
+ // Body (bytes,optional)
+ if l = len(m.Body); l > 0 {
+ sz += csproto.SizeOfTagKey(4) + csproto.SizeOfVarint(uint64(l)) + l
+ }
+ // cache the size so it can be re-used in Marshal()/MarshalTo()
+ atomic.StoreInt32(&m.sizeCache, int32(sz))
+ return sz
+}
+
+// Marshal converts the contents of m to the Protobuf binary encoding and returns the result or an error.
+func (m *HTTPRequest) Marshal() ([]byte, error) {
+ siz := m.Size()
+ if siz == 0 {
+ return []byte{}, nil
+ }
+ buf := make([]byte, siz)
+ err := m.MarshalTo(buf)
+ return buf, err
+}
+
+// MarshalTo converts the contents of m to the Protobuf binary encoding and writes the result to dest.
+func (m *HTTPRequest) MarshalTo(dest []byte) error {
+ // nil message == no-op
+ if m == nil {
+ return nil
+ }
+ var (
+ enc = csproto.NewEncoder(dest)
+ buf []byte
+ err error
+ extVal interface{}
+ )
+ // ensure no unused variables
+ _ = enc
+ _ = buf
+ _ = err
+ _ = extVal
+
+ // Method (1,string,optional)
+ if len(m.Method) > 0 {
+ enc.EncodeString(1, m.Method)
+ }
+ // Url (2,string,optional)
+ if len(m.Url) > 0 {
+ enc.EncodeString(2, m.Url)
+ }
+ // Headers (3,message,repeated)
+ for _, mm := range m.Headers {
+ if err = enc.EncodeNested(3, mm); err != nil {
+ return fmt.Errorf("unable to encode message data for field 'headers' (tag=3): %w", err)
+ }
+ }
+ // Body (4,bytes,optional)
+ if len(m.Body) > 0 {
+ enc.EncodeBytes(4, m.Body)
+ }
+ return nil
+}
+
+// Unmarshal decodes a binary encoded Protobuf message from p and populates m with the result.
+func (m *HTTPRequest) Unmarshal(p []byte) error {
+ m.Reset()
+ if len(p) == 0 {
+ return nil
+ }
+ dec := csproto.NewDecoder(p)
+ for dec.More() {
+ tag, wt, err := dec.DecodeTag()
+ if err != nil {
+ return err
+ }
+ switch tag {
+ case 1: // Method (string,optional)
+ if wt != csproto.WireTypeLengthDelimited {
+ return fmt.Errorf("incorrect wire type %v for field 'method' (tag=1), expected 2 (length-delimited)", wt)
+ }
+ if s, err := dec.DecodeString(); err != nil {
+ return fmt.Errorf("unable to decode string value for field 'method' (tag=1): %w", err)
+ } else {
+ m.Method = s
+ }
+
+ case 2: // Url (string,optional)
+ if wt != csproto.WireTypeLengthDelimited {
+ return fmt.Errorf("incorrect wire type %v for field 'url' (tag=2), expected 2 (length-delimited)", wt)
+ }
+ if s, err := dec.DecodeString(); err != nil {
+ return fmt.Errorf("unable to decode string value for field 'url' (tag=2): %w", err)
+ } else {
+ m.Url = s
+ }
+
+ case 3: // Headers (message,repeated)
+ if wt != csproto.WireTypeLengthDelimited {
+ return fmt.Errorf("incorrect wire type %v for field 'headers' (tag=3), expected 2 (length-delimited)", wt)
+ }
+ var mm Header
+ if err = dec.DecodeNested(&mm); err != nil {
+ return fmt.Errorf("unable to decode message value for field 'headers' (tag=3): %w", err)
+ }
+ m.Headers = append(m.Headers, &mm)
+ case 4: // Body (bytes,optional)
+
+ if wt != csproto.WireTypeLengthDelimited {
+ return fmt.Errorf("incorrect wire type %v for field 'body' (tag=4), expected 2 (length-delimited)", wt)
+ }
+ if b, err := dec.DecodeBytes(); err != nil {
+ return fmt.Errorf("unable to decode bytes value for field 'body' (tag=4): %w", err)
+ } else {
+ m.Body = b
+ }
+
+ default:
+ if skipped, err := dec.Skip(tag, wt); err != nil {
+ return fmt.Errorf("invalid operation skipping tag %v: %w", tag, err)
+ } else {
+ m.unknownFields = append(m.unknownFields, skipped...)
+ }
+ }
+ }
+ return nil
+}
+
+//------------------------------------------------------------------------------
+// Custom Protobuf size/marshal/unmarshal code for HTTPResponse
+
+// Size calculates and returns the size, in bytes, required to hold the contents of m using the Protobuf
+// binary encoding.
+func (m *HTTPResponse) Size() int {
+ // nil message is always 0 bytes
+ if m == nil {
+ return 0
+ }
+ // return cached size, if present
+ if csz := int(atomic.LoadInt32(&m.sizeCache)); csz > 0 {
+ return csz
+ }
+ // calculate and cache
+ var sz, l int
+ _ = l // avoid unused variable
+
+ // Code (int32,optional)
+ if m.Code != 0 {
+ sz += csproto.SizeOfTagKey(1) + csproto.SizeOfVarint(uint64(m.Code))
+ }
+ // Headers (message,repeated)
+ for _, val := range m.Headers {
+ if l = csproto.Size(val); l > 0 {
+ sz += csproto.SizeOfTagKey(2) + csproto.SizeOfVarint(uint64(l)) + l
+ }
+ }
+ // Body (bytes,optional)
+ if l = len(m.Body); l > 0 {
+ sz += csproto.SizeOfTagKey(3) + csproto.SizeOfVarint(uint64(l)) + l
+ }
+ // cache the size so it can be re-used in Marshal()/MarshalTo()
+ atomic.StoreInt32(&m.sizeCache, int32(sz))
+ return sz
+}
+
+// Marshal converts the contents of m to the Protobuf binary encoding and returns the result or an error.
+func (m *HTTPResponse) Marshal() ([]byte, error) {
+ siz := m.Size()
+ if siz == 0 {
+ return []byte{}, nil
+ }
+ buf := make([]byte, siz)
+ err := m.MarshalTo(buf)
+ return buf, err
+}
+
+// MarshalTo converts the contents of m to the Protobuf binary encoding and writes the result to dest.
+func (m *HTTPResponse) MarshalTo(dest []byte) error {
+ // nil message == no-op
+ if m == nil {
+ return nil
+ }
+ var (
+ enc = csproto.NewEncoder(dest)
+ buf []byte
+ err error
+ extVal interface{}
+ )
+ // ensure no unused variables
+ _ = enc
+ _ = buf
+ _ = err
+ _ = extVal
+
+ // Code (1,int32,optional)
+ if m.Code != 0 {
+ enc.EncodeInt32(1, m.Code)
+ }
+ // Headers (2,message,repeated)
+ for _, mm := range m.Headers {
+ if err = enc.EncodeNested(2, mm); err != nil {
+ return fmt.Errorf("unable to encode message data for field 'headers' (tag=2): %w", err)
+ }
+ }
+ // Body (3,bytes,optional)
+ if len(m.Body) > 0 {
+ enc.EncodeBytes(3, m.Body)
+ }
+ return nil
+}
+
+// Unmarshal decodes a binary encoded Protobuf message from p and populates m with the result.
+func (m *HTTPResponse) Unmarshal(p []byte) error {
+ m.Reset()
+ if len(p) == 0 {
+ return nil
+ }
+ dec := csproto.NewDecoder(p)
+ for dec.More() {
+ tag, wt, err := dec.DecodeTag()
+ if err != nil {
+ return err
+ }
+ switch tag {
+ case 1: // Code (int32,optional)
+ if wt != csproto.WireTypeVarint {
+ return fmt.Errorf("incorrect wire type %v for tag field 'Code' (tag=1), expected 0 (varint)", wt)
+ }
+ if v, err := dec.DecodeInt32(); err != nil {
+ return fmt.Errorf("unable to decode int32 value for field 'Code' (tag=1): %w", err)
+ } else {
+ m.Code = v
+ }
+ case 2: // Headers (message,repeated)
+ if wt != csproto.WireTypeLengthDelimited {
+ return fmt.Errorf("incorrect wire type %v for field 'headers' (tag=2), expected 2 (length-delimited)", wt)
+ }
+ var mm Header
+ if err = dec.DecodeNested(&mm); err != nil {
+ return fmt.Errorf("unable to decode message value for field 'headers' (tag=2): %w", err)
+ }
+ m.Headers = append(m.Headers, &mm)
+ case 3: // Body (bytes,optional)
+
+ if wt != csproto.WireTypeLengthDelimited {
+ return fmt.Errorf("incorrect wire type %v for field 'body' (tag=3), expected 2 (length-delimited)", wt)
+ }
+ if b, err := dec.DecodeBytes(); err != nil {
+ return fmt.Errorf("unable to decode bytes value for field 'body' (tag=3): %w", err)
+ } else {
+ m.Body = b
+ }
+
+ default:
+ if skipped, err := dec.Skip(tag, wt); err != nil {
+ return fmt.Errorf("invalid operation skipping tag %v: %w", tag, err)
+ } else {
+ m.unknownFields = append(m.unknownFields, skipped...)
+ }
+ }
+ }
+ return nil
+}
+
+//------------------------------------------------------------------------------
+// Custom Protobuf size/marshal/unmarshal code for Header
+
+// Size calculates and returns the size, in bytes, required to hold the contents of m using the Protobuf
+// binary encoding.
+func (m *Header) Size() int {
+ // nil message is always 0 bytes
+ if m == nil {
+ return 0
+ }
+ // return cached size, if present
+ if csz := int(atomic.LoadInt32(&m.sizeCache)); csz > 0 {
+ return csz
+ }
+ // calculate and cache
+ var sz, l int
+ _ = l // avoid unused variable
+
+ // Key (string,optional)
+ if l = len(m.Key); l > 0 {
+ sz += csproto.SizeOfTagKey(1) + csproto.SizeOfVarint(uint64(l)) + l
+ }
+ // Values (string,repeated)
+ for _, sv := range m.Values {
+ l = len(sv)
+ sz += csproto.SizeOfTagKey(2) + csproto.SizeOfVarint(uint64(l)) + l
+ }
+ // cache the size so it can be re-used in Marshal()/MarshalTo()
+ atomic.StoreInt32(&m.sizeCache, int32(sz))
+ return sz
+}
+
+// Marshal converts the contents of m to the Protobuf binary encoding and returns the result or an error.
+func (m *Header) Marshal() ([]byte, error) {
+ siz := m.Size()
+ if siz == 0 {
+ return []byte{}, nil
+ }
+ buf := make([]byte, siz)
+ err := m.MarshalTo(buf)
+ return buf, err
+}
+
+// MarshalTo converts the contents of m to the Protobuf binary encoding and writes the result to dest.
+func (m *Header) MarshalTo(dest []byte) error {
+ // nil message == no-op
+ if m == nil {
+ return nil
+ }
+ var (
+ enc = csproto.NewEncoder(dest)
+ buf []byte
+ err error
+ extVal interface{}
+ )
+ // ensure no unused variables
+ _ = enc
+ _ = buf
+ _ = err
+ _ = extVal
+
+ // Key (1,string,optional)
+ if len(m.Key) > 0 {
+ enc.EncodeString(1, m.Key)
+ }
+ // Values (2,string,repeated)
+ for _, val := range m.Values {
+ enc.EncodeString(2, val)
+ }
+ return nil
+}
+
+// Unmarshal decodes a binary encoded Protobuf message from p and populates m with the result.
+func (m *Header) Unmarshal(p []byte) error {
+ m.Reset()
+ if len(p) == 0 {
+ return nil
+ }
+ dec := csproto.NewDecoder(p)
+ for dec.More() {
+ tag, wt, err := dec.DecodeTag()
+ if err != nil {
+ return err
+ }
+ switch tag {
+ case 1: // Key (string,optional)
+ if wt != csproto.WireTypeLengthDelimited {
+ return fmt.Errorf("incorrect wire type %v for field 'key' (tag=1), expected 2 (length-delimited)", wt)
+ }
+ if s, err := dec.DecodeString(); err != nil {
+ return fmt.Errorf("unable to decode string value for field 'key' (tag=1): %w", err)
+ } else {
+ m.Key = s
+ }
+
+ case 2: // Values (string,repeated)
+ if wt != csproto.WireTypeLengthDelimited {
+ return fmt.Errorf("incorrect wire type %v for field 'values' (tag=2), expected 2 (length-delimited)", wt)
+ }
+ if s, err := dec.DecodeString(); err != nil {
+ return fmt.Errorf("unable to decode string value for field 'values' (tag=2): %w", err)
+ } else {
+ m.Values = append(m.Values, s)
+ }
+
+ default:
+ if skipped, err := dec.Skip(tag, wt); err != nil {
+ return fmt.Errorf("invalid operation skipping tag %v: %w", tag, err)
+ } else {
+ m.unknownFields = append(m.unknownFields, skipped...)
+ }
+ }
+ }
+ return nil
+}
diff --git a/vendor/github.com/grafana/dskit/httpgrpc/httpgrpc.pb.go b/vendor/github.com/grafana/dskit/httpgrpc/httpgrpc.pb.go
index bab0efd5362..f8fee38c174 100644
--- a/vendor/github.com/grafana/dskit/httpgrpc/httpgrpc.pb.go
+++ b/vendor/github.com/grafana/dskit/httpgrpc/httpgrpc.pb.go
@@ -1,1311 +1,288 @@
-// Code generated by protoc-gen-gogo. DO NOT EDIT.
-// source: httpgrpc.proto
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.36.0
+// protoc v5.29.0
+// source: httpgrpc/httpgrpc.proto
package httpgrpc
import (
- bytes "bytes"
- context "context"
- fmt "fmt"
- _ "github.com/gogo/protobuf/gogoproto"
- proto "github.com/gogo/protobuf/proto"
- grpc "google.golang.org/grpc"
- codes "google.golang.org/grpc/codes"
- status "google.golang.org/grpc/status"
- io "io"
- math "math"
- math_bits "math/bits"
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
- strings "strings"
+ sync "sync"
)
-// Reference imports to suppress errors if they are not otherwise used.
-var _ = proto.Marshal
-var _ = fmt.Errorf
-var _ = math.Inf
-
-// This is a compile-time assertion to ensure that this generated file
-// is compatible with the proto package it is being compiled against.
-// A compilation error at this line likely means your copy of the
-// proto package needs to be updated.
-const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
+const (
+ // Verify that this generated code is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+ // Verify that runtime/protoimpl is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
type HTTPRequest struct {
- Method string `protobuf:"bytes,1,opt,name=method,proto3" json:"method,omitempty"`
- Url string `protobuf:"bytes,2,opt,name=url,proto3" json:"url,omitempty"`
- Headers []*Header `protobuf:"bytes,3,rep,name=headers,proto3" json:"headers,omitempty"`
- Body []byte `protobuf:"bytes,4,opt,name=body,proto3" json:"body,omitempty"`
-}
-
-func (m *HTTPRequest) Reset() { *m = HTTPRequest{} }
-func (*HTTPRequest) ProtoMessage() {}
-func (*HTTPRequest) Descriptor() ([]byte, []int) {
- return fileDescriptor_c50820dbc814fcdd, []int{0}
-}
-func (m *HTTPRequest) XXX_Unmarshal(b []byte) error {
- return m.Unmarshal(b)
-}
-func (m *HTTPRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
- if deterministic {
- return xxx_messageInfo_HTTPRequest.Marshal(b, m, deterministic)
- } else {
- b = b[:cap(b)]
- n, err := m.MarshalToSizedBuffer(b)
- if err != nil {
- return nil, err
- }
- return b[:n], nil
- }
-}
-func (m *HTTPRequest) XXX_Merge(src proto.Message) {
- xxx_messageInfo_HTTPRequest.Merge(m, src)
-}
-func (m *HTTPRequest) XXX_Size() int {
- return m.Size()
-}
-func (m *HTTPRequest) XXX_DiscardUnknown() {
- xxx_messageInfo_HTTPRequest.DiscardUnknown(m)
+ state protoimpl.MessageState `protogen:"open.v1"`
+ Method string `protobuf:"bytes,1,opt,name=method,proto3" json:"method,omitempty"`
+ Url string `protobuf:"bytes,2,opt,name=url,proto3" json:"url,omitempty"`
+ Headers []*Header `protobuf:"bytes,3,rep,name=headers,proto3" json:"headers,omitempty"`
+ Body []byte `protobuf:"bytes,4,opt,name=body,proto3" json:"body,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
}
-var xxx_messageInfo_HTTPRequest proto.InternalMessageInfo
-
-func (m *HTTPRequest) GetMethod() string {
- if m != nil {
- return m.Method
- }
- return ""
-}
-
-func (m *HTTPRequest) GetUrl() string {
- if m != nil {
- return m.Url
- }
- return ""
+func (x *HTTPRequest) Reset() {
+ *x = HTTPRequest{}
+ mi := &file_httpgrpc_httpgrpc_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
}
-func (m *HTTPRequest) GetHeaders() []*Header {
- if m != nil {
- return m.Headers
- }
- return nil
-}
-
-func (m *HTTPRequest) GetBody() []byte {
- if m != nil {
- return m.Body
- }
- return nil
+func (x *HTTPRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
}
-type HTTPResponse struct {
- Code int32 `protobuf:"varint,1,opt,name=Code,proto3" json:"Code,omitempty"`
- Headers []*Header `protobuf:"bytes,2,rep,name=headers,proto3" json:"headers,omitempty"`
- Body []byte `protobuf:"bytes,3,opt,name=body,proto3" json:"body,omitempty"`
-}
+func (*HTTPRequest) ProtoMessage() {}
-func (m *HTTPResponse) Reset() { *m = HTTPResponse{} }
-func (*HTTPResponse) ProtoMessage() {}
-func (*HTTPResponse) Descriptor() ([]byte, []int) {
- return fileDescriptor_c50820dbc814fcdd, []int{1}
-}
-func (m *HTTPResponse) XXX_Unmarshal(b []byte) error {
- return m.Unmarshal(b)
-}
-func (m *HTTPResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
- if deterministic {
- return xxx_messageInfo_HTTPResponse.Marshal(b, m, deterministic)
- } else {
- b = b[:cap(b)]
- n, err := m.MarshalToSizedBuffer(b)
- if err != nil {
- return nil, err
+func (x *HTTPRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_httpgrpc_httpgrpc_proto_msgTypes[0]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
}
- return b[:n], nil
- }
-}
-func (m *HTTPResponse) XXX_Merge(src proto.Message) {
- xxx_messageInfo_HTTPResponse.Merge(m, src)
-}
-func (m *HTTPResponse) XXX_Size() int {
- return m.Size()
-}
-func (m *HTTPResponse) XXX_DiscardUnknown() {
- xxx_messageInfo_HTTPResponse.DiscardUnknown(m)
-}
-
-var xxx_messageInfo_HTTPResponse proto.InternalMessageInfo
-
-func (m *HTTPResponse) GetCode() int32 {
- if m != nil {
- return m.Code
+ return ms
}
- return 0
+ return mi.MessageOf(x)
}
-func (m *HTTPResponse) GetHeaders() []*Header {
- if m != nil {
- return m.Headers
- }
- return nil
-}
-
-func (m *HTTPResponse) GetBody() []byte {
- if m != nil {
- return m.Body
- }
- return nil
-}
-
-type Header struct {
- Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
- Values []string `protobuf:"bytes,2,rep,name=values,proto3" json:"values,omitempty"`
+// Deprecated: Use HTTPRequest.ProtoReflect.Descriptor instead.
+func (*HTTPRequest) Descriptor() ([]byte, []int) {
+ return file_httpgrpc_httpgrpc_proto_rawDescGZIP(), []int{0}
}
-func (m *Header) Reset() { *m = Header{} }
-func (*Header) ProtoMessage() {}
-func (*Header) Descriptor() ([]byte, []int) {
- return fileDescriptor_c50820dbc814fcdd, []int{2}
-}
-func (m *Header) XXX_Unmarshal(b []byte) error {
- return m.Unmarshal(b)
-}
-func (m *Header) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
- if deterministic {
- return xxx_messageInfo_Header.Marshal(b, m, deterministic)
- } else {
- b = b[:cap(b)]
- n, err := m.MarshalToSizedBuffer(b)
- if err != nil {
- return nil, err
- }
- return b[:n], nil
+func (x *HTTPRequest) GetMethod() string {
+ if x != nil {
+ return x.Method
}
+ return ""
}
-func (m *Header) XXX_Merge(src proto.Message) {
- xxx_messageInfo_Header.Merge(m, src)
-}
-func (m *Header) XXX_Size() int {
- return m.Size()
-}
-func (m *Header) XXX_DiscardUnknown() {
- xxx_messageInfo_Header.DiscardUnknown(m)
-}
-
-var xxx_messageInfo_Header proto.InternalMessageInfo
-func (m *Header) GetKey() string {
- if m != nil {
- return m.Key
+func (x *HTTPRequest) GetUrl() string {
+ if x != nil {
+ return x.Url
}
return ""
}
-func (m *Header) GetValues() []string {
- if m != nil {
- return m.Values
+func (x *HTTPRequest) GetHeaders() []*Header {
+ if x != nil {
+ return x.Headers
}
return nil
}
-func init() {
- proto.RegisterType((*HTTPRequest)(nil), "httpgrpc.HTTPRequest")
- proto.RegisterType((*HTTPResponse)(nil), "httpgrpc.HTTPResponse")
- proto.RegisterType((*Header)(nil), "httpgrpc.Header")
-}
-
-func init() { proto.RegisterFile("httpgrpc.proto", fileDescriptor_c50820dbc814fcdd) }
-
-var fileDescriptor_c50820dbc814fcdd = []byte{
- // 301 bytes of a gzipped FileDescriptorProto
- 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x91, 0xbd, 0x4e, 0xc3, 0x30,
- 0x14, 0x85, 0xed, 0xa6, 0x04, 0xea, 0x56, 0xa8, 0xb2, 0xa0, 0x8a, 0x3a, 0x5c, 0x55, 0x99, 0x22,
- 0x86, 0x22, 0x05, 0x16, 0x46, 0x60, 0xc9, 0x88, 0xac, 0xbe, 0x40, 0x42, 0xac, 0x44, 0x22, 0xd4,
- 0x21, 0x3f, 0xa0, 0x6e, 0x3c, 0x02, 0x8f, 0xc1, 0xa3, 0x30, 0x66, 0xec, 0x48, 0x9c, 0x85, 0xb1,
- 0x8f, 0x80, 0xec, 0xa4, 0x10, 0x31, 0xb1, 0x9d, 0x7b, 0xee, 0x51, 0xbe, 0x7b, 0x62, 0x72, 0x1c,
- 0x17, 0x45, 0x1a, 0x65, 0xe9, 0xfd, 0x32, 0xcd, 0x44, 0x21, 0xe8, 0xd1, 0x7e, 0x9e, 0x9f, 0x44,
- 0x22, 0x12, 0xda, 0x3c, 0x57, 0xaa, 0xdd, 0xdb, 0x2f, 0x64, 0xec, 0xad, 0x56, 0x77, 0x8c, 0x3f,
- 0x95, 0x3c, 0x2f, 0xe8, 0x8c, 0x98, 0x8f, 0xbc, 0x88, 0x45, 0x68, 0xe1, 0x05, 0x76, 0x46, 0xac,
- 0x9b, 0xe8, 0x94, 0x18, 0x65, 0x96, 0x58, 0x03, 0x6d, 0x2a, 0x49, 0xcf, 0xc8, 0x61, 0xcc, 0xfd,
- 0x90, 0x67, 0xb9, 0x65, 0x2c, 0x0c, 0x67, 0xec, 0x4e, 0x97, 0x3f, 0x68, 0x4f, 0x2f, 0xd8, 0x3e,
- 0x40, 0x29, 0x19, 0x06, 0x22, 0xdc, 0x58, 0xc3, 0x05, 0x76, 0x26, 0x4c, 0x6b, 0x3b, 0x20, 0x93,
- 0x16, 0x9c, 0xa7, 0x62, 0x9d, 0x73, 0x95, 0xb9, 0x15, 0x21, 0xd7, 0xdc, 0x03, 0xa6, 0x75, 0x9f,
- 0x31, 0xf8, 0x2f, 0xc3, 0xe8, 0x31, 0x5c, 0x62, 0xb6, 0x31, 0x75, 0xff, 0x03, 0xdf, 0x74, 0xa5,
- 0x94, 0x54, 0x4d, 0x9f, 0xfd, 0xa4, 0xe4, 0xed, 0xa7, 0x47, 0xac, 0x9b, 0xdc, 0x6b, 0x32, 0x54,
- 0x77, 0xd1, 0x2b, 0x62, 0x7a, 0xfe, 0x3a, 0x4c, 0x38, 0x3d, 0xed, 0x41, 0x7f, 0x7f, 0xd5, 0x7c,
- 0xf6, 0xd7, 0x6e, 0x8b, 0xd8, 0xe8, 0xe6, 0xb2, 0xaa, 0x01, 0x6d, 0x6b, 0x40, 0xbb, 0x1a, 0xf0,
- 0xab, 0x04, 0xfc, 0x2e, 0x01, 0x7f, 0x48, 0xc0, 0x95, 0x04, 0xfc, 0x29, 0x01, 0x7f, 0x49, 0x40,
- 0x3b, 0x09, 0xf8, 0xad, 0x01, 0x54, 0x35, 0x80, 0xb6, 0x0d, 0xa0, 0xc0, 0xd4, 0x0f, 0x72, 0xf1,
- 0x1d, 0x00, 0x00, 0xff, 0xff, 0x44, 0x0e, 0x7c, 0xff, 0xc2, 0x01, 0x00, 0x00,
-}
-
-func (this *HTTPRequest) Equal(that interface{}) bool {
- if that == nil {
- return this == nil
- }
-
- that1, ok := that.(*HTTPRequest)
- if !ok {
- that2, ok := that.(HTTPRequest)
- if ok {
- that1 = &that2
- } else {
- return false
- }
- }
- if that1 == nil {
- return this == nil
- } else if this == nil {
- return false
- }
- if this.Method != that1.Method {
- return false
- }
- if this.Url != that1.Url {
- return false
- }
- if len(this.Headers) != len(that1.Headers) {
- return false
- }
- for i := range this.Headers {
- if !this.Headers[i].Equal(that1.Headers[i]) {
- return false
- }
- }
- if !bytes.Equal(this.Body, that1.Body) {
- return false
- }
- return true
-}
-func (this *HTTPResponse) Equal(that interface{}) bool {
- if that == nil {
- return this == nil
- }
-
- that1, ok := that.(*HTTPResponse)
- if !ok {
- that2, ok := that.(HTTPResponse)
- if ok {
- that1 = &that2
- } else {
- return false
- }
- }
- if that1 == nil {
- return this == nil
- } else if this == nil {
- return false
- }
- if this.Code != that1.Code {
- return false
- }
- if len(this.Headers) != len(that1.Headers) {
- return false
- }
- for i := range this.Headers {
- if !this.Headers[i].Equal(that1.Headers[i]) {
- return false
- }
- }
- if !bytes.Equal(this.Body, that1.Body) {
- return false
- }
- return true
-}
-func (this *Header) Equal(that interface{}) bool {
- if that == nil {
- return this == nil
- }
-
- that1, ok := that.(*Header)
- if !ok {
- that2, ok := that.(Header)
- if ok {
- that1 = &that2
- } else {
- return false
- }
- }
- if that1 == nil {
- return this == nil
- } else if this == nil {
- return false
- }
- if this.Key != that1.Key {
- return false
- }
- if len(this.Values) != len(that1.Values) {
- return false
+func (x *HTTPRequest) GetBody() []byte {
+ if x != nil {
+ return x.Body
}
- for i := range this.Values {
- if this.Values[i] != that1.Values[i] {
- return false
- }
- }
- return true
-}
-func (this *HTTPRequest) GoString() string {
- if this == nil {
- return "nil"
- }
- s := make([]string, 0, 8)
- s = append(s, "&httpgrpc.HTTPRequest{")
- s = append(s, "Method: "+fmt.Sprintf("%#v", this.Method)+",\n")
- s = append(s, "Url: "+fmt.Sprintf("%#v", this.Url)+",\n")
- if this.Headers != nil {
- s = append(s, "Headers: "+fmt.Sprintf("%#v", this.Headers)+",\n")
- }
- s = append(s, "Body: "+fmt.Sprintf("%#v", this.Body)+",\n")
- s = append(s, "}")
- return strings.Join(s, "")
-}
-func (this *HTTPResponse) GoString() string {
- if this == nil {
- return "nil"
- }
- s := make([]string, 0, 7)
- s = append(s, "&httpgrpc.HTTPResponse{")
- s = append(s, "Code: "+fmt.Sprintf("%#v", this.Code)+",\n")
- if this.Headers != nil {
- s = append(s, "Headers: "+fmt.Sprintf("%#v", this.Headers)+",\n")
- }
- s = append(s, "Body: "+fmt.Sprintf("%#v", this.Body)+",\n")
- s = append(s, "}")
- return strings.Join(s, "")
-}
-func (this *Header) GoString() string {
- if this == nil {
- return "nil"
- }
- s := make([]string, 0, 6)
- s = append(s, "&httpgrpc.Header{")
- s = append(s, "Key: "+fmt.Sprintf("%#v", this.Key)+",\n")
- s = append(s, "Values: "+fmt.Sprintf("%#v", this.Values)+",\n")
- s = append(s, "}")
- return strings.Join(s, "")
-}
-func valueToGoStringHttpgrpc(v interface{}, typ string) string {
- rv := reflect.ValueOf(v)
- if rv.IsNil() {
- return "nil"
- }
- pv := reflect.Indirect(rv).Interface()
- return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv)
-}
-
-// Reference imports to suppress errors if they are not otherwise used.
-var _ context.Context
-var _ grpc.ClientConn
-
-// This is a compile-time assertion to ensure that this generated file
-// is compatible with the grpc package it is being compiled against.
-const _ = grpc.SupportPackageIsVersion4
-
-// HTTPClient is the client API for HTTP service.
-//
-// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
-type HTTPClient interface {
- Handle(ctx context.Context, in *HTTPRequest, opts ...grpc.CallOption) (*HTTPResponse, error)
-}
-
-type hTTPClient struct {
- cc *grpc.ClientConn
-}
-
-func NewHTTPClient(cc *grpc.ClientConn) HTTPClient {
- return &hTTPClient{cc}
-}
-
-func (c *hTTPClient) Handle(ctx context.Context, in *HTTPRequest, opts ...grpc.CallOption) (*HTTPResponse, error) {
- out := new(HTTPResponse)
- err := c.cc.Invoke(ctx, "/httpgrpc.HTTP/Handle", in, out, opts...)
- if err != nil {
- return nil, err
- }
- return out, nil
-}
-
-// HTTPServer is the server API for HTTP service.
-type HTTPServer interface {
- Handle(context.Context, *HTTPRequest) (*HTTPResponse, error)
+ return nil
}
-// UnimplementedHTTPServer can be embedded to have forward compatible implementations.
-type UnimplementedHTTPServer struct {
+type HTTPResponse struct {
+ state protoimpl.MessageState `protogen:"open.v1"`
+ Code int32 `protobuf:"varint,1,opt,name=Code,proto3" json:"Code,omitempty"`
+ Headers []*Header `protobuf:"bytes,2,rep,name=headers,proto3" json:"headers,omitempty"`
+ Body []byte `protobuf:"bytes,3,opt,name=body,proto3" json:"body,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
}
-func (*UnimplementedHTTPServer) Handle(ctx context.Context, req *HTTPRequest) (*HTTPResponse, error) {
- return nil, status.Errorf(codes.Unimplemented, "method Handle not implemented")
+func (x *HTTPResponse) Reset() {
+ *x = HTTPResponse{}
+ mi := &file_httpgrpc_httpgrpc_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
}
-func RegisterHTTPServer(s *grpc.Server, srv HTTPServer) {
- s.RegisterService(&_HTTP_serviceDesc, srv)
+func (x *HTTPResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
}
-func _HTTP_Handle_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
- in := new(HTTPRequest)
- if err := dec(in); err != nil {
- return nil, err
- }
- if interceptor == nil {
- return srv.(HTTPServer).Handle(ctx, in)
- }
- info := &grpc.UnaryServerInfo{
- Server: srv,
- FullMethod: "/httpgrpc.HTTP/Handle",
- }
- handler := func(ctx context.Context, req interface{}) (interface{}, error) {
- return srv.(HTTPServer).Handle(ctx, req.(*HTTPRequest))
- }
- return interceptor(ctx, in, info, handler)
-}
-
-var _HTTP_serviceDesc = grpc.ServiceDesc{
- ServiceName: "httpgrpc.HTTP",
- HandlerType: (*HTTPServer)(nil),
- Methods: []grpc.MethodDesc{
- {
- MethodName: "Handle",
- Handler: _HTTP_Handle_Handler,
- },
- },
- Streams: []grpc.StreamDesc{},
- Metadata: "httpgrpc.proto",
-}
+func (*HTTPResponse) ProtoMessage() {}
-func (m *HTTPRequest) Marshal() (dAtA []byte, err error) {
- size := m.Size()
- dAtA = make([]byte, size)
- n, err := m.MarshalToSizedBuffer(dAtA[:size])
- if err != nil {
- return nil, err
+func (x *HTTPResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_httpgrpc_httpgrpc_proto_msgTypes[1]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
}
- return dAtA[:n], nil
+ return mi.MessageOf(x)
}
-func (m *HTTPRequest) MarshalTo(dAtA []byte) (int, error) {
- size := m.Size()
- return m.MarshalToSizedBuffer(dAtA[:size])
+// Deprecated: Use HTTPResponse.ProtoReflect.Descriptor instead.
+func (*HTTPResponse) Descriptor() ([]byte, []int) {
+ return file_httpgrpc_httpgrpc_proto_rawDescGZIP(), []int{1}
}
-func (m *HTTPRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
- i := len(dAtA)
- _ = i
- var l int
- _ = l
- if len(m.Body) > 0 {
- i -= len(m.Body)
- copy(dAtA[i:], m.Body)
- i = encodeVarintHttpgrpc(dAtA, i, uint64(len(m.Body)))
- i--
- dAtA[i] = 0x22
- }
- if len(m.Headers) > 0 {
- for iNdEx := len(m.Headers) - 1; iNdEx >= 0; iNdEx-- {
- {
- size, err := m.Headers[iNdEx].MarshalToSizedBuffer(dAtA[:i])
- if err != nil {
- return 0, err
- }
- i -= size
- i = encodeVarintHttpgrpc(dAtA, i, uint64(size))
- }
- i--
- dAtA[i] = 0x1a
- }
- }
- if len(m.Url) > 0 {
- i -= len(m.Url)
- copy(dAtA[i:], m.Url)
- i = encodeVarintHttpgrpc(dAtA, i, uint64(len(m.Url)))
- i--
- dAtA[i] = 0x12
- }
- if len(m.Method) > 0 {
- i -= len(m.Method)
- copy(dAtA[i:], m.Method)
- i = encodeVarintHttpgrpc(dAtA, i, uint64(len(m.Method)))
- i--
- dAtA[i] = 0xa
+func (x *HTTPResponse) GetCode() int32 {
+ if x != nil {
+ return x.Code
}
- return len(dAtA) - i, nil
+ return 0
}
-func (m *HTTPResponse) Marshal() (dAtA []byte, err error) {
- size := m.Size()
- dAtA = make([]byte, size)
- n, err := m.MarshalToSizedBuffer(dAtA[:size])
- if err != nil {
- return nil, err
+func (x *HTTPResponse) GetHeaders() []*Header {
+ if x != nil {
+ return x.Headers
}
- return dAtA[:n], nil
-}
-
-func (m *HTTPResponse) MarshalTo(dAtA []byte) (int, error) {
- size := m.Size()
- return m.MarshalToSizedBuffer(dAtA[:size])
+ return nil
}
-func (m *HTTPResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
- i := len(dAtA)
- _ = i
- var l int
- _ = l
- if len(m.Body) > 0 {
- i -= len(m.Body)
- copy(dAtA[i:], m.Body)
- i = encodeVarintHttpgrpc(dAtA, i, uint64(len(m.Body)))
- i--
- dAtA[i] = 0x1a
- }
- if len(m.Headers) > 0 {
- for iNdEx := len(m.Headers) - 1; iNdEx >= 0; iNdEx-- {
- {
- size, err := m.Headers[iNdEx].MarshalToSizedBuffer(dAtA[:i])
- if err != nil {
- return 0, err
- }
- i -= size
- i = encodeVarintHttpgrpc(dAtA, i, uint64(size))
- }
- i--
- dAtA[i] = 0x12
- }
+func (x *HTTPResponse) GetBody() []byte {
+ if x != nil {
+ return x.Body
}
- if m.Code != 0 {
- i = encodeVarintHttpgrpc(dAtA, i, uint64(m.Code))
- i--
- dAtA[i] = 0x8
- }
- return len(dAtA) - i, nil
+ return nil
}
-func (m *Header) Marshal() (dAtA []byte, err error) {
- size := m.Size()
- dAtA = make([]byte, size)
- n, err := m.MarshalToSizedBuffer(dAtA[:size])
- if err != nil {
- return nil, err
- }
- return dAtA[:n], nil
+type Header struct {
+ state protoimpl.MessageState `protogen:"open.v1"`
+ Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
+ Values []string `protobuf:"bytes,2,rep,name=values,proto3" json:"values,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
}
-func (m *Header) MarshalTo(dAtA []byte) (int, error) {
- size := m.Size()
- return m.MarshalToSizedBuffer(dAtA[:size])
+func (x *Header) Reset() {
+ *x = Header{}
+ mi := &file_httpgrpc_httpgrpc_proto_msgTypes[2]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
}
-func (m *Header) MarshalToSizedBuffer(dAtA []byte) (int, error) {
- i := len(dAtA)
- _ = i
- var l int
- _ = l
- if len(m.Values) > 0 {
- for iNdEx := len(m.Values) - 1; iNdEx >= 0; iNdEx-- {
- i -= len(m.Values[iNdEx])
- copy(dAtA[i:], m.Values[iNdEx])
- i = encodeVarintHttpgrpc(dAtA, i, uint64(len(m.Values[iNdEx])))
- i--
- dAtA[i] = 0x12
- }
- }
- if len(m.Key) > 0 {
- i -= len(m.Key)
- copy(dAtA[i:], m.Key)
- i = encodeVarintHttpgrpc(dAtA, i, uint64(len(m.Key)))
- i--
- dAtA[i] = 0xa
- }
- return len(dAtA) - i, nil
+func (x *Header) String() string {
+ return protoimpl.X.MessageStringOf(x)
}
-func encodeVarintHttpgrpc(dAtA []byte, offset int, v uint64) int {
- offset -= sovHttpgrpc(v)
- base := offset
- for v >= 1<<7 {
- dAtA[offset] = uint8(v&0x7f | 0x80)
- v >>= 7
- offset++
- }
- dAtA[offset] = uint8(v)
- return base
-}
-func (m *HTTPRequest) Size() (n int) {
- if m == nil {
- return 0
- }
- var l int
- _ = l
- l = len(m.Method)
- if l > 0 {
- n += 1 + l + sovHttpgrpc(uint64(l))
- }
- l = len(m.Url)
- if l > 0 {
- n += 1 + l + sovHttpgrpc(uint64(l))
- }
- if len(m.Headers) > 0 {
- for _, e := range m.Headers {
- l = e.Size()
- n += 1 + l + sovHttpgrpc(uint64(l))
- }
- }
- l = len(m.Body)
- if l > 0 {
- n += 1 + l + sovHttpgrpc(uint64(l))
- }
- return n
-}
+func (*Header) ProtoMessage() {}
-func (m *HTTPResponse) Size() (n int) {
- if m == nil {
- return 0
- }
- var l int
- _ = l
- if m.Code != 0 {
- n += 1 + sovHttpgrpc(uint64(m.Code))
- }
- if len(m.Headers) > 0 {
- for _, e := range m.Headers {
- l = e.Size()
- n += 1 + l + sovHttpgrpc(uint64(l))
+func (x *Header) ProtoReflect() protoreflect.Message {
+ mi := &file_httpgrpc_httpgrpc_proto_msgTypes[2]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
}
+ return ms
}
- l = len(m.Body)
- if l > 0 {
- n += 1 + l + sovHttpgrpc(uint64(l))
- }
- return n
+ return mi.MessageOf(x)
}
-func (m *Header) Size() (n int) {
- if m == nil {
- return 0
- }
- var l int
- _ = l
- l = len(m.Key)
- if l > 0 {
- n += 1 + l + sovHttpgrpc(uint64(l))
- }
- if len(m.Values) > 0 {
- for _, s := range m.Values {
- l = len(s)
- n += 1 + l + sovHttpgrpc(uint64(l))
- }
- }
- return n
+// Deprecated: Use Header.ProtoReflect.Descriptor instead.
+func (*Header) Descriptor() ([]byte, []int) {
+ return file_httpgrpc_httpgrpc_proto_rawDescGZIP(), []int{2}
}
-func sovHttpgrpc(x uint64) (n int) {
- return (math_bits.Len64(x|1) + 6) / 7
-}
-func sozHttpgrpc(x uint64) (n int) {
- return sovHttpgrpc(uint64((x << 1) ^ uint64((int64(x) >> 63))))
-}
-func (this *HTTPRequest) String() string {
- if this == nil {
- return "nil"
- }
- repeatedStringForHeaders := "[]*Header{"
- for _, f := range this.Headers {
- repeatedStringForHeaders += strings.Replace(f.String(), "Header", "Header", 1) + ","
- }
- repeatedStringForHeaders += "}"
- s := strings.Join([]string{`&HTTPRequest{`,
- `Method:` + fmt.Sprintf("%v", this.Method) + `,`,
- `Url:` + fmt.Sprintf("%v", this.Url) + `,`,
- `Headers:` + repeatedStringForHeaders + `,`,
- `Body:` + fmt.Sprintf("%v", this.Body) + `,`,
- `}`,
- }, "")
- return s
-}
-func (this *HTTPResponse) String() string {
- if this == nil {
- return "nil"
- }
- repeatedStringForHeaders := "[]*Header{"
- for _, f := range this.Headers {
- repeatedStringForHeaders += strings.Replace(f.String(), "Header", "Header", 1) + ","
- }
- repeatedStringForHeaders += "}"
- s := strings.Join([]string{`&HTTPResponse{`,
- `Code:` + fmt.Sprintf("%v", this.Code) + `,`,
- `Headers:` + repeatedStringForHeaders + `,`,
- `Body:` + fmt.Sprintf("%v", this.Body) + `,`,
- `}`,
- }, "")
- return s
-}
-func (this *Header) String() string {
- if this == nil {
- return "nil"
+func (x *Header) GetKey() string {
+ if x != nil {
+ return x.Key
}
- s := strings.Join([]string{`&Header{`,
- `Key:` + fmt.Sprintf("%v", this.Key) + `,`,
- `Values:` + fmt.Sprintf("%v", this.Values) + `,`,
- `}`,
- }, "")
- return s
-}
-func valueToStringHttpgrpc(v interface{}) string {
- rv := reflect.ValueOf(v)
- if rv.IsNil() {
- return "nil"
- }
- pv := reflect.Indirect(rv).Interface()
- return fmt.Sprintf("*%v", pv)
-}
-func (m *HTTPRequest) Unmarshal(dAtA []byte) error {
- l := len(dAtA)
- iNdEx := 0
- for iNdEx < l {
- preIndex := iNdEx
- var wire uint64
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowHttpgrpc
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- wire |= uint64(b&0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- fieldNum := int32(wire >> 3)
- wireType := int(wire & 0x7)
- if wireType == 4 {
- return fmt.Errorf("proto: HTTPRequest: wiretype end group for non-group")
- }
- if fieldNum <= 0 {
- return fmt.Errorf("proto: HTTPRequest: illegal tag %d (wire type %d)", fieldNum, wire)
- }
- switch fieldNum {
- case 1:
- if wireType != 2 {
- return fmt.Errorf("proto: wrong wireType = %d for field Method", wireType)
- }
- var stringLen uint64
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowHttpgrpc
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- stringLen |= uint64(b&0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- intStringLen := int(stringLen)
- if intStringLen < 0 {
- return ErrInvalidLengthHttpgrpc
- }
- postIndex := iNdEx + intStringLen
- if postIndex < 0 {
- return ErrInvalidLengthHttpgrpc
- }
- if postIndex > l {
- return io.ErrUnexpectedEOF
- }
- m.Method = string(dAtA[iNdEx:postIndex])
- iNdEx = postIndex
- case 2:
- if wireType != 2 {
- return fmt.Errorf("proto: wrong wireType = %d for field Url", wireType)
- }
- var stringLen uint64
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowHttpgrpc
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- stringLen |= uint64(b&0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- intStringLen := int(stringLen)
- if intStringLen < 0 {
- return ErrInvalidLengthHttpgrpc
- }
- postIndex := iNdEx + intStringLen
- if postIndex < 0 {
- return ErrInvalidLengthHttpgrpc
- }
- if postIndex > l {
- return io.ErrUnexpectedEOF
- }
- m.Url = string(dAtA[iNdEx:postIndex])
- iNdEx = postIndex
- case 3:
- if wireType != 2 {
- return fmt.Errorf("proto: wrong wireType = %d for field Headers", wireType)
- }
- var msglen int
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowHttpgrpc
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- msglen |= int(b&0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- if msglen < 0 {
- return ErrInvalidLengthHttpgrpc
- }
- postIndex := iNdEx + msglen
- if postIndex < 0 {
- return ErrInvalidLengthHttpgrpc
- }
- if postIndex > l {
- return io.ErrUnexpectedEOF
- }
- m.Headers = append(m.Headers, &Header{})
- if err := m.Headers[len(m.Headers)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
- return err
- }
- iNdEx = postIndex
- case 4:
- if wireType != 2 {
- return fmt.Errorf("proto: wrong wireType = %d for field Body", wireType)
- }
- var byteLen int
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowHttpgrpc
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- byteLen |= int(b&0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- if byteLen < 0 {
- return ErrInvalidLengthHttpgrpc
- }
- postIndex := iNdEx + byteLen
- if postIndex < 0 {
- return ErrInvalidLengthHttpgrpc
- }
- if postIndex > l {
- return io.ErrUnexpectedEOF
- }
- m.Body = append(m.Body[:0], dAtA[iNdEx:postIndex]...)
- if m.Body == nil {
- m.Body = []byte{}
- }
- iNdEx = postIndex
- default:
- iNdEx = preIndex
- skippy, err := skipHttpgrpc(dAtA[iNdEx:])
- if err != nil {
- return err
- }
- if skippy < 0 {
- return ErrInvalidLengthHttpgrpc
- }
- if (iNdEx + skippy) < 0 {
- return ErrInvalidLengthHttpgrpc
- }
- if (iNdEx + skippy) > l {
- return io.ErrUnexpectedEOF
- }
- iNdEx += skippy
- }
- }
-
- if iNdEx > l {
- return io.ErrUnexpectedEOF
- }
- return nil
+ return ""
}
-func (m *HTTPResponse) Unmarshal(dAtA []byte) error {
- l := len(dAtA)
- iNdEx := 0
- for iNdEx < l {
- preIndex := iNdEx
- var wire uint64
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowHttpgrpc
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- wire |= uint64(b&0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- fieldNum := int32(wire >> 3)
- wireType := int(wire & 0x7)
- if wireType == 4 {
- return fmt.Errorf("proto: HTTPResponse: wiretype end group for non-group")
- }
- if fieldNum <= 0 {
- return fmt.Errorf("proto: HTTPResponse: illegal tag %d (wire type %d)", fieldNum, wire)
- }
- switch fieldNum {
- case 1:
- if wireType != 0 {
- return fmt.Errorf("proto: wrong wireType = %d for field Code", wireType)
- }
- m.Code = 0
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowHttpgrpc
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- m.Code |= int32(b&0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- case 2:
- if wireType != 2 {
- return fmt.Errorf("proto: wrong wireType = %d for field Headers", wireType)
- }
- var msglen int
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowHttpgrpc
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- msglen |= int(b&0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- if msglen < 0 {
- return ErrInvalidLengthHttpgrpc
- }
- postIndex := iNdEx + msglen
- if postIndex < 0 {
- return ErrInvalidLengthHttpgrpc
- }
- if postIndex > l {
- return io.ErrUnexpectedEOF
- }
- m.Headers = append(m.Headers, &Header{})
- if err := m.Headers[len(m.Headers)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
- return err
- }
- iNdEx = postIndex
- case 3:
- if wireType != 2 {
- return fmt.Errorf("proto: wrong wireType = %d for field Body", wireType)
- }
- var byteLen int
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowHttpgrpc
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- byteLen |= int(b&0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- if byteLen < 0 {
- return ErrInvalidLengthHttpgrpc
- }
- postIndex := iNdEx + byteLen
- if postIndex < 0 {
- return ErrInvalidLengthHttpgrpc
- }
- if postIndex > l {
- return io.ErrUnexpectedEOF
- }
- m.Body = append(m.Body[:0], dAtA[iNdEx:postIndex]...)
- if m.Body == nil {
- m.Body = []byte{}
- }
- iNdEx = postIndex
- default:
- iNdEx = preIndex
- skippy, err := skipHttpgrpc(dAtA[iNdEx:])
- if err != nil {
- return err
- }
- if skippy < 0 {
- return ErrInvalidLengthHttpgrpc
- }
- if (iNdEx + skippy) < 0 {
- return ErrInvalidLengthHttpgrpc
- }
- if (iNdEx + skippy) > l {
- return io.ErrUnexpectedEOF
- }
- iNdEx += skippy
- }
- }
- if iNdEx > l {
- return io.ErrUnexpectedEOF
+func (x *Header) GetValues() []string {
+ if x != nil {
+ return x.Values
}
return nil
}
-func (m *Header) Unmarshal(dAtA []byte) error {
- l := len(dAtA)
- iNdEx := 0
- for iNdEx < l {
- preIndex := iNdEx
- var wire uint64
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowHttpgrpc
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- wire |= uint64(b&0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- fieldNum := int32(wire >> 3)
- wireType := int(wire & 0x7)
- if wireType == 4 {
- return fmt.Errorf("proto: Header: wiretype end group for non-group")
- }
- if fieldNum <= 0 {
- return fmt.Errorf("proto: Header: illegal tag %d (wire type %d)", fieldNum, wire)
- }
- switch fieldNum {
- case 1:
- if wireType != 2 {
- return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType)
- }
- var stringLen uint64
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowHttpgrpc
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- stringLen |= uint64(b&0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- intStringLen := int(stringLen)
- if intStringLen < 0 {
- return ErrInvalidLengthHttpgrpc
- }
- postIndex := iNdEx + intStringLen
- if postIndex < 0 {
- return ErrInvalidLengthHttpgrpc
- }
- if postIndex > l {
- return io.ErrUnexpectedEOF
- }
- m.Key = string(dAtA[iNdEx:postIndex])
- iNdEx = postIndex
- case 2:
- if wireType != 2 {
- return fmt.Errorf("proto: wrong wireType = %d for field Values", wireType)
- }
- var stringLen uint64
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowHttpgrpc
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- stringLen |= uint64(b&0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- intStringLen := int(stringLen)
- if intStringLen < 0 {
- return ErrInvalidLengthHttpgrpc
- }
- postIndex := iNdEx + intStringLen
- if postIndex < 0 {
- return ErrInvalidLengthHttpgrpc
- }
- if postIndex > l {
- return io.ErrUnexpectedEOF
- }
- m.Values = append(m.Values, string(dAtA[iNdEx:postIndex]))
- iNdEx = postIndex
- default:
- iNdEx = preIndex
- skippy, err := skipHttpgrpc(dAtA[iNdEx:])
- if err != nil {
- return err
- }
- if skippy < 0 {
- return ErrInvalidLengthHttpgrpc
- }
- if (iNdEx + skippy) < 0 {
- return ErrInvalidLengthHttpgrpc
- }
- if (iNdEx + skippy) > l {
- return io.ErrUnexpectedEOF
- }
- iNdEx += skippy
- }
- }
- if iNdEx > l {
- return io.ErrUnexpectedEOF
- }
- return nil
-}
-func skipHttpgrpc(dAtA []byte) (n int, err error) {
- l := len(dAtA)
- iNdEx := 0
- for iNdEx < l {
- var wire uint64
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return 0, ErrIntOverflowHttpgrpc
- }
- if iNdEx >= l {
- return 0, io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- wire |= (uint64(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- wireType := int(wire & 0x7)
- switch wireType {
- case 0:
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return 0, ErrIntOverflowHttpgrpc
- }
- if iNdEx >= l {
- return 0, io.ErrUnexpectedEOF
- }
- iNdEx++
- if dAtA[iNdEx-1] < 0x80 {
- break
- }
- }
- return iNdEx, nil
- case 1:
- iNdEx += 8
- return iNdEx, nil
- case 2:
- var length int
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return 0, ErrIntOverflowHttpgrpc
- }
- if iNdEx >= l {
- return 0, io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- length |= (int(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- if length < 0 {
- return 0, ErrInvalidLengthHttpgrpc
- }
- iNdEx += length
- if iNdEx < 0 {
- return 0, ErrInvalidLengthHttpgrpc
- }
- return iNdEx, nil
- case 3:
- for {
- var innerWire uint64
- var start int = iNdEx
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return 0, ErrIntOverflowHttpgrpc
- }
- if iNdEx >= l {
- return 0, io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- innerWire |= (uint64(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- innerWireType := int(innerWire & 0x7)
- if innerWireType == 4 {
- break
- }
- next, err := skipHttpgrpc(dAtA[start:])
- if err != nil {
- return 0, err
- }
- iNdEx = start + next
- if iNdEx < 0 {
- return 0, ErrInvalidLengthHttpgrpc
- }
- }
- return iNdEx, nil
- case 4:
- return iNdEx, nil
- case 5:
- iNdEx += 4
- return iNdEx, nil
- default:
- return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
- }
- }
- panic("unreachable")
+var File_httpgrpc_httpgrpc_proto protoreflect.FileDescriptor
+
+var file_httpgrpc_httpgrpc_proto_rawDesc = []byte{
+ 0x0a, 0x17, 0x68, 0x74, 0x74, 0x70, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x68, 0x74, 0x74, 0x70, 0x67,
+ 0x72, 0x70, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x08, 0x68, 0x74, 0x74, 0x70, 0x67,
+ 0x72, 0x70, 0x63, 0x22, 0x77, 0x0a, 0x0b, 0x48, 0x54, 0x54, 0x50, 0x52, 0x65, 0x71, 0x75, 0x65,
+ 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x01, 0x20, 0x01,
+ 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72,
+ 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x2a, 0x0a, 0x07,
+ 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e,
+ 0x68, 0x74, 0x74, 0x70, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52,
+ 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79,
+ 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x22, 0x62, 0x0a, 0x0c,
+ 0x48, 0x54, 0x54, 0x50, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04,
+ 0x43, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x43, 0x6f, 0x64, 0x65,
+ 0x12, 0x2a, 0x0a, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28,
+ 0x0b, 0x32, 0x10, 0x2e, 0x68, 0x74, 0x74, 0x70, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x48, 0x65, 0x61,
+ 0x64, 0x65, 0x72, 0x52, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x12, 0x0a, 0x04,
+ 0x62, 0x6f, 0x64, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79,
+ 0x22, 0x32, 0x0a, 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65,
+ 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x16, 0x0a, 0x06,
+ 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x76, 0x61,
+ 0x6c, 0x75, 0x65, 0x73, 0x32, 0x41, 0x0a, 0x04, 0x48, 0x54, 0x54, 0x50, 0x12, 0x39, 0x0a, 0x06,
+ 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x15, 0x2e, 0x68, 0x74, 0x74, 0x70, 0x67, 0x72, 0x70,
+ 0x63, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e,
+ 0x68, 0x74, 0x74, 0x70, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x52, 0x65, 0x73,
+ 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x23, 0x5a, 0x21, 0x67, 0x69, 0x74, 0x68, 0x75,
+ 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x72, 0x61, 0x66, 0x61, 0x6e, 0x61, 0x2f, 0x64, 0x73,
+ 0x6b, 0x69, 0x74, 0x2f, 0x68, 0x74, 0x74, 0x70, 0x67, 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x33,
}
var (
- ErrInvalidLengthHttpgrpc = fmt.Errorf("proto: negative length found during unmarshaling")
- ErrIntOverflowHttpgrpc = fmt.Errorf("proto: integer overflow")
+ file_httpgrpc_httpgrpc_proto_rawDescOnce sync.Once
+ file_httpgrpc_httpgrpc_proto_rawDescData = file_httpgrpc_httpgrpc_proto_rawDesc
)
+
+func file_httpgrpc_httpgrpc_proto_rawDescGZIP() []byte {
+ file_httpgrpc_httpgrpc_proto_rawDescOnce.Do(func() {
+ file_httpgrpc_httpgrpc_proto_rawDescData = protoimpl.X.CompressGZIP(file_httpgrpc_httpgrpc_proto_rawDescData)
+ })
+ return file_httpgrpc_httpgrpc_proto_rawDescData
+}
+
+var file_httpgrpc_httpgrpc_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
+var file_httpgrpc_httpgrpc_proto_goTypes = []any{
+ (*HTTPRequest)(nil), // 0: httpgrpc.HTTPRequest
+ (*HTTPResponse)(nil), // 1: httpgrpc.HTTPResponse
+ (*Header)(nil), // 2: httpgrpc.Header
+}
+var file_httpgrpc_httpgrpc_proto_depIdxs = []int32{
+ 2, // 0: httpgrpc.HTTPRequest.headers:type_name -> httpgrpc.Header
+ 2, // 1: httpgrpc.HTTPResponse.headers:type_name -> httpgrpc.Header
+ 0, // 2: httpgrpc.HTTP.Handle:input_type -> httpgrpc.HTTPRequest
+ 1, // 3: httpgrpc.HTTP.Handle:output_type -> httpgrpc.HTTPResponse
+ 3, // [3:4] is the sub-list for method output_type
+ 2, // [2:3] is the sub-list for method input_type
+ 2, // [2:2] is the sub-list for extension type_name
+ 2, // [2:2] is the sub-list for extension extendee
+ 0, // [0:2] is the sub-list for field type_name
+}
+
+func init() { file_httpgrpc_httpgrpc_proto_init() }
+func file_httpgrpc_httpgrpc_proto_init() {
+ if File_httpgrpc_httpgrpc_proto != nil {
+ return
+ }
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_httpgrpc_httpgrpc_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 3,
+ NumExtensions: 0,
+ NumServices: 1,
+ },
+ GoTypes: file_httpgrpc_httpgrpc_proto_goTypes,
+ DependencyIndexes: file_httpgrpc_httpgrpc_proto_depIdxs,
+ MessageInfos: file_httpgrpc_httpgrpc_proto_msgTypes,
+ }.Build()
+ File_httpgrpc_httpgrpc_proto = out.File
+ file_httpgrpc_httpgrpc_proto_rawDesc = nil
+ file_httpgrpc_httpgrpc_proto_goTypes = nil
+ file_httpgrpc_httpgrpc_proto_depIdxs = nil
+}
diff --git a/vendor/github.com/grafana/dskit/httpgrpc/httpgrpc.proto b/vendor/github.com/grafana/dskit/httpgrpc/httpgrpc.proto
index 8f546330a52..9a6db6ffafe 100644
--- a/vendor/github.com/grafana/dskit/httpgrpc/httpgrpc.proto
+++ b/vendor/github.com/grafana/dskit/httpgrpc/httpgrpc.proto
@@ -1,16 +1,7 @@
syntax = "proto3";
package httpgrpc;
-
-import "gogoproto/gogo.proto";
-
-option (gogoproto.equal_all) = true;
-option (gogoproto.gostring_all) = true;
-option (gogoproto.stringer_all) = true;
-option (gogoproto.goproto_stringer_all) = false;
-option (gogoproto.goproto_unkeyed_all) = false;
-option (gogoproto.goproto_unrecognized_all) = false;
-option (gogoproto.goproto_sizecache_all) = false;
+option go_package = "github.com/grafana/dskit/httpgrpc";
service HTTP {
rpc Handle(HTTPRequest) returns (HTTPResponse) {};
diff --git a/vendor/github.com/grafana/dskit/httpgrpc/httpgrpc_grpc.pb.go b/vendor/github.com/grafana/dskit/httpgrpc/httpgrpc_grpc.pb.go
new file mode 100644
index 00000000000..cddfd9bc11c
--- /dev/null
+++ b/vendor/github.com/grafana/dskit/httpgrpc/httpgrpc_grpc.pb.go
@@ -0,0 +1,119 @@
+// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
+// versions:
+// - protoc-gen-go-grpc v1.5.1
+// - protoc v5.29.0
+// source: httpgrpc/httpgrpc.proto
+
+package httpgrpc
+
+import (
+ context "context"
+ grpc "google.golang.org/grpc"
+ codes "google.golang.org/grpc/codes"
+ status "google.golang.org/grpc/status"
+)
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+// Requires gRPC-Go v1.64.0 or later.
+const _ = grpc.SupportPackageIsVersion9
+
+const (
+ HTTP_Handle_FullMethodName = "/httpgrpc.HTTP/Handle"
+)
+
+// HTTPClient is the client API for HTTP service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
+type HTTPClient interface {
+ Handle(ctx context.Context, in *HTTPRequest, opts ...grpc.CallOption) (*HTTPResponse, error)
+}
+
+type hTTPClient struct {
+ cc grpc.ClientConnInterface
+}
+
+func NewHTTPClient(cc grpc.ClientConnInterface) HTTPClient {
+ return &hTTPClient{cc}
+}
+
+func (c *hTTPClient) Handle(ctx context.Context, in *HTTPRequest, opts ...grpc.CallOption) (*HTTPResponse, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+ out := new(HTTPResponse)
+ err := c.cc.Invoke(ctx, HTTP_Handle_FullMethodName, in, out, cOpts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+// HTTPServer is the server API for HTTP service.
+// All implementations should embed UnimplementedHTTPServer
+// for forward compatibility.
+type HTTPServer interface {
+ Handle(context.Context, *HTTPRequest) (*HTTPResponse, error)
+}
+
+// UnimplementedHTTPServer should be embedded to have
+// forward compatible implementations.
+//
+// NOTE: this should be embedded by value instead of pointer to avoid a nil
+// pointer dereference when methods are called.
+type UnimplementedHTTPServer struct{}
+
+func (UnimplementedHTTPServer) Handle(context.Context, *HTTPRequest) (*HTTPResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method Handle not implemented")
+}
+func (UnimplementedHTTPServer) testEmbeddedByValue() {}
+
+// UnsafeHTTPServer may be embedded to opt out of forward compatibility for this service.
+// Use of this interface is not recommended, as added methods to HTTPServer will
+// result in compilation errors.
+type UnsafeHTTPServer interface {
+ mustEmbedUnimplementedHTTPServer()
+}
+
+func RegisterHTTPServer(s grpc.ServiceRegistrar, srv HTTPServer) {
+ // If the following call pancis, it indicates UnimplementedHTTPServer was
+ // embedded by pointer and is nil. This will cause panics if an
+ // unimplemented method is ever invoked, so we test this at initialization
+ // time to prevent it from happening at runtime later due to I/O.
+ if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
+ t.testEmbeddedByValue()
+ }
+ s.RegisterService(&HTTP_ServiceDesc, srv)
+}
+
+func _HTTP_Handle_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(HTTPRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(HTTPServer).Handle(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: HTTP_Handle_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(HTTPServer).Handle(ctx, req.(*HTTPRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+// HTTP_ServiceDesc is the grpc.ServiceDesc for HTTP service.
+// It's only intended for direct use with grpc.RegisterService,
+// and not to be introspected or modified (even as a copy)
+var HTTP_ServiceDesc = grpc.ServiceDesc{
+ ServiceName: "httpgrpc.HTTP",
+ HandlerType: (*HTTPServer)(nil),
+ Methods: []grpc.MethodDesc{
+ {
+ MethodName: "Handle",
+ Handler: _HTTP_Handle_Handler,
+ },
+ },
+ Streams: []grpc.StreamDesc{},
+ Metadata: "httpgrpc/httpgrpc.proto",
+}
diff --git a/vendor/github.com/grafana/dskit/httpgrpc/init.go b/vendor/github.com/grafana/dskit/httpgrpc/init.go
new file mode 100644
index 00000000000..c272b506e70
--- /dev/null
+++ b/vendor/github.com/grafana/dskit/httpgrpc/init.go
@@ -0,0 +1,11 @@
+package httpgrpc
+
+import (
+ "github.com/CrowdStrike/csproto"
+ "google.golang.org/grpc/encoding"
+ _ "google.golang.org/grpc/encoding/proto" // to register the Codec for "proto"
+)
+
+func init() {
+ encoding.RegisterCodec(csproto.GrpcCodec{})
+}
diff --git a/vendor/github.com/huandu/xstrings/.travis.yml b/vendor/github.com/huandu/xstrings/.travis.yml
deleted file mode 100644
index d6460be411e..00000000000
--- a/vendor/github.com/huandu/xstrings/.travis.yml
+++ /dev/null
@@ -1,7 +0,0 @@
-language: go
-install:
- - go get golang.org/x/tools/cmd/cover
- - go get github.com/mattn/goveralls
-script:
- - go test -v -covermode=count -coverprofile=coverage.out
- - 'if [ "$TRAVIS_PULL_REQUEST" = "false" ] && [ ! -z "$COVERALLS_TOKEN" ]; then $HOME/gopath/bin/goveralls -coverprofile=coverage.out -service=travis-ci -repotoken $COVERALLS_TOKEN; fi'
diff --git a/vendor/github.com/huandu/xstrings/README.md b/vendor/github.com/huandu/xstrings/README.md
index 292bf2f39e1..e809c79abc5 100644
--- a/vendor/github.com/huandu/xstrings/README.md
+++ b/vendor/github.com/huandu/xstrings/README.md
@@ -1,7 +1,7 @@
-# xstrings #
+# xstrings
-[![Build Status](https://travis-ci.org/huandu/xstrings.svg?branch=master)](https://travis-ci.org/huandu/xstrings)
-[![GoDoc](https://godoc.org/github.com/huandu/xstrings?status.svg)](https://godoc.org/github.com/huandu/xstrings)
+[![Build Status](https://github.com/huandu/xstrings/workflows/Go/badge.svg)](https://github.com/huandu/xstrings/actions)
+[![Go Doc](https://godoc.org/github.com/huandu/xstrings?status.svg)](https://pkg.go.dev/github.com/huandu/xstrings)
[![Go Report](https://goreportcard.com/badge/github.com/huandu/xstrings)](https://goreportcard.com/report/github.com/huandu/xstrings)
[![Coverage Status](https://coveralls.io/repos/github/huandu/xstrings/badge.svg?branch=master)](https://coveralls.io/github/huandu/xstrings?branch=master)
@@ -9,109 +9,110 @@ Go package [xstrings](https://godoc.org/github.com/huandu/xstrings) is a collect
All functions are well tested and carefully tuned for performance.
-## Propose a new function ##
+## Propose a new function
Please review [contributing guideline](CONTRIBUTING.md) and [create new issue](https://github.com/huandu/xstrings/issues) to state why it should be included.
-## Install ##
+## Install
Use `go get` to install this library.
go get github.com/huandu/xstrings
-## API document ##
+## API document
See [GoDoc](https://godoc.org/github.com/huandu/xstrings) for full document.
-## Function list ##
+## Function list
Go functions have a unique naming style. One, who has experience in other language but new in Go, may have difficulties to find out right string function to use.
Here is a list of functions in [strings](http://golang.org/pkg/strings) and [xstrings](https://godoc.org/github.com/huandu/xstrings) with enough extra information about how to map these functions to their friends in other languages. Hope this list could be helpful for fresh gophers.
-### Package `xstrings` functions ###
-
-*Keep this table sorted by Function in ascending order.*
-
-| Function | Friends | # |
-| -------- | ------- | --- |
-| [Center](https://godoc.org/github.com/huandu/xstrings#Center) | `str.center` in Python; `String#center` in Ruby | [#30](https://github.com/huandu/xstrings/issues/30) |
-| [Count](https://godoc.org/github.com/huandu/xstrings#Count) | `String#count` in Ruby | [#16](https://github.com/huandu/xstrings/issues/16) |
-| [Delete](https://godoc.org/github.com/huandu/xstrings#Delete) | `String#delete` in Ruby | [#17](https://github.com/huandu/xstrings/issues/17) |
-| [ExpandTabs](https://godoc.org/github.com/huandu/xstrings#ExpandTabs) | `str.expandtabs` in Python | [#27](https://github.com/huandu/xstrings/issues/27) |
-| [FirstRuneToLower](https://godoc.org/github.com/huandu/xstrings#FirstRuneToLower) | `lcfirst` in PHP or Perl | [#15](https://github.com/huandu/xstrings/issues/15) |
-| [FirstRuneToUpper](https://godoc.org/github.com/huandu/xstrings#FirstRuneToUpper) | `String#capitalize` in Ruby; `ucfirst` in PHP or Perl | [#15](https://github.com/huandu/xstrings/issues/15) |
-| [Insert](https://godoc.org/github.com/huandu/xstrings#Insert) | `String#insert` in Ruby | [#18](https://github.com/huandu/xstrings/issues/18) |
-| [LastPartition](https://godoc.org/github.com/huandu/xstrings#LastPartition) | `str.rpartition` in Python; `String#rpartition` in Ruby | [#19](https://github.com/huandu/xstrings/issues/19) |
-| [LeftJustify](https://godoc.org/github.com/huandu/xstrings#LeftJustify) | `str.ljust` in Python; `String#ljust` in Ruby | [#28](https://github.com/huandu/xstrings/issues/28) |
-| [Len](https://godoc.org/github.com/huandu/xstrings#Len) | `mb_strlen` in PHP | [#23](https://github.com/huandu/xstrings/issues/23) |
-| [Partition](https://godoc.org/github.com/huandu/xstrings#Partition) | `str.partition` in Python; `String#partition` in Ruby | [#10](https://github.com/huandu/xstrings/issues/10) |
-| [Reverse](https://godoc.org/github.com/huandu/xstrings#Reverse) | `String#reverse` in Ruby; `strrev` in PHP; `reverse` in Perl | [#7](https://github.com/huandu/xstrings/issues/7) |
-| [RightJustify](https://godoc.org/github.com/huandu/xstrings#RightJustify) | `str.rjust` in Python; `String#rjust` in Ruby | [#29](https://github.com/huandu/xstrings/issues/29) |
-| [RuneWidth](https://godoc.org/github.com/huandu/xstrings#RuneWidth) | - | [#27](https://github.com/huandu/xstrings/issues/27) |
-| [Scrub](https://godoc.org/github.com/huandu/xstrings#Scrub) | `String#scrub` in Ruby | [#20](https://github.com/huandu/xstrings/issues/20) |
-| [Shuffle](https://godoc.org/github.com/huandu/xstrings#Shuffle) | `str_shuffle` in PHP | [#13](https://github.com/huandu/xstrings/issues/13) |
-| [ShuffleSource](https://godoc.org/github.com/huandu/xstrings#ShuffleSource) | `str_shuffle` in PHP | [#13](https://github.com/huandu/xstrings/issues/13) |
-| [Slice](https://godoc.org/github.com/huandu/xstrings#Slice) | `mb_substr` in PHP | [#9](https://github.com/huandu/xstrings/issues/9) |
-| [Squeeze](https://godoc.org/github.com/huandu/xstrings#Squeeze) | `String#squeeze` in Ruby | [#11](https://github.com/huandu/xstrings/issues/11) |
-| [Successor](https://godoc.org/github.com/huandu/xstrings#Successor) | `String#succ` or `String#next` in Ruby | [#22](https://github.com/huandu/xstrings/issues/22) |
-| [SwapCase](https://godoc.org/github.com/huandu/xstrings#SwapCase) | `str.swapcase` in Python; `String#swapcase` in Ruby | [#12](https://github.com/huandu/xstrings/issues/12) |
-| [ToCamelCase](https://godoc.org/github.com/huandu/xstrings#ToCamelCase) | `String#camelize` in RoR | [#1](https://github.com/huandu/xstrings/issues/1) |
-| [ToKebab](https://godoc.org/github.com/huandu/xstrings#ToKebabCase) | - | [#41](https://github.com/huandu/xstrings/issues/41) |
-| [ToSnakeCase](https://godoc.org/github.com/huandu/xstrings#ToSnakeCase) | `String#underscore` in RoR | [#1](https://github.com/huandu/xstrings/issues/1) |
-| [Translate](https://godoc.org/github.com/huandu/xstrings#Translate) | `str.translate` in Python; `String#tr` in Ruby; `strtr` in PHP; `tr///` in Perl | [#21](https://github.com/huandu/xstrings/issues/21) |
-| [Width](https://godoc.org/github.com/huandu/xstrings#Width) | `mb_strwidth` in PHP | [#26](https://github.com/huandu/xstrings/issues/26) |
-| [WordCount](https://godoc.org/github.com/huandu/xstrings#WordCount) | `str_word_count` in PHP | [#14](https://github.com/huandu/xstrings/issues/14) |
-| [WordSplit](https://godoc.org/github.com/huandu/xstrings#WordSplit) | - | [#14](https://github.com/huandu/xstrings/issues/14) |
-
-### Package `strings` functions ###
-
-*Keep this table sorted by Function in ascending order.*
-
-| Function | Friends |
-| -------- | ------- |
-| [Contains](http://golang.org/pkg/strings/#Contains) | `String#include?` in Ruby |
-| [ContainsAny](http://golang.org/pkg/strings/#ContainsAny) | - |
-| [ContainsRune](http://golang.org/pkg/strings/#ContainsRune) | - |
-| [Count](http://golang.org/pkg/strings/#Count) | `str.count` in Python; `substr_count` in PHP |
-| [EqualFold](http://golang.org/pkg/strings/#EqualFold) | `stricmp` in PHP; `String#casecmp` in Ruby |
-| [Fields](http://golang.org/pkg/strings/#Fields) | `str.split` in Python; `split` in Perl; `String#split` in Ruby |
-| [FieldsFunc](http://golang.org/pkg/strings/#FieldsFunc) | - |
-| [HasPrefix](http://golang.org/pkg/strings/#HasPrefix) | `str.startswith` in Python; `String#start_with?` in Ruby |
-| [HasSuffix](http://golang.org/pkg/strings/#HasSuffix) | `str.endswith` in Python; `String#end_with?` in Ruby |
-| [Index](http://golang.org/pkg/strings/#Index) | `str.index` in Python; `String#index` in Ruby; `strpos` in PHP; `index` in Perl |
-| [IndexAny](http://golang.org/pkg/strings/#IndexAny) | - |
-| [IndexByte](http://golang.org/pkg/strings/#IndexByte) | - |
-| [IndexFunc](http://golang.org/pkg/strings/#IndexFunc) | - |
-| [IndexRune](http://golang.org/pkg/strings/#IndexRune) | - |
-| [Join](http://golang.org/pkg/strings/#Join) | `str.join` in Python; `Array#join` in Ruby; `implode` in PHP; `join` in Perl |
-| [LastIndex](http://golang.org/pkg/strings/#LastIndex) | `str.rindex` in Python; `String#rindex`; `strrpos` in PHP; `rindex` in Perl |
-| [LastIndexAny](http://golang.org/pkg/strings/#LastIndexAny) | - |
-| [LastIndexFunc](http://golang.org/pkg/strings/#LastIndexFunc) | - |
-| [Map](http://golang.org/pkg/strings/#Map) | `String#each_codepoint` in Ruby |
-| [Repeat](http://golang.org/pkg/strings/#Repeat) | operator `*` in Python and Ruby; `str_repeat` in PHP |
-| [Replace](http://golang.org/pkg/strings/#Replace) | `str.replace` in Python; `String#sub` in Ruby; `str_replace` in PHP |
-| [Split](http://golang.org/pkg/strings/#Split) | `str.split` in Python; `String#split` in Ruby; `explode` in PHP; `split` in Perl |
-| [SplitAfter](http://golang.org/pkg/strings/#SplitAfter) | - |
-| [SplitAfterN](http://golang.org/pkg/strings/#SplitAfterN) | - |
-| [SplitN](http://golang.org/pkg/strings/#SplitN) | `str.split` in Python; `String#split` in Ruby; `explode` in PHP; `split` in Perl |
-| [Title](http://golang.org/pkg/strings/#Title) | `str.title` in Python |
-| [ToLower](http://golang.org/pkg/strings/#ToLower) | `str.lower` in Python; `String#downcase` in Ruby; `strtolower` in PHP; `lc` in Perl |
-| [ToLowerSpecial](http://golang.org/pkg/strings/#ToLowerSpecial) | - |
-| [ToTitle](http://golang.org/pkg/strings/#ToTitle) | - |
-| [ToTitleSpecial](http://golang.org/pkg/strings/#ToTitleSpecial) | - |
-| [ToUpper](http://golang.org/pkg/strings/#ToUpper) | `str.upper` in Python; `String#upcase` in Ruby; `strtoupper` in PHP; `uc` in Perl |
-| [ToUpperSpecial](http://golang.org/pkg/strings/#ToUpperSpecial) | - |
-| [Trim](http://golang.org/pkg/strings/#Trim) | `str.strip` in Python; `String#strip` in Ruby; `trim` in PHP |
-| [TrimFunc](http://golang.org/pkg/strings/#TrimFunc) | - |
-| [TrimLeft](http://golang.org/pkg/strings/#TrimLeft) | `str.lstrip` in Python; `String#lstrip` in Ruby; `ltrim` in PHP |
-| [TrimLeftFunc](http://golang.org/pkg/strings/#TrimLeftFunc) | - |
-| [TrimPrefix](http://golang.org/pkg/strings/#TrimPrefix) | - |
-| [TrimRight](http://golang.org/pkg/strings/#TrimRight) | `str.rstrip` in Python; `String#rstrip` in Ruby; `rtrim` in PHP |
-| [TrimRightFunc](http://golang.org/pkg/strings/#TrimRightFunc) | - |
-| [TrimSpace](http://golang.org/pkg/strings/#TrimSpace) | `str.strip` in Python; `String#strip` in Ruby; `trim` in PHP |
-| [TrimSuffix](http://golang.org/pkg/strings/#TrimSuffix) | `String#chomp` in Ruby; `chomp` in Perl |
-
-## License ##
+### Package `xstrings` functions
+
+_Keep this table sorted by Function in ascending order._
+
+| Function | Friends | # |
+| --------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | --------------------------------------------------- |
+| [Center](https://godoc.org/github.com/huandu/xstrings#Center) | `str.center` in Python; `String#center` in Ruby | [#30](https://github.com/huandu/xstrings/issues/30) |
+| [Count](https://godoc.org/github.com/huandu/xstrings#Count) | `String#count` in Ruby | [#16](https://github.com/huandu/xstrings/issues/16) |
+| [Delete](https://godoc.org/github.com/huandu/xstrings#Delete) | `String#delete` in Ruby | [#17](https://github.com/huandu/xstrings/issues/17) |
+| [ExpandTabs](https://godoc.org/github.com/huandu/xstrings#ExpandTabs) | `str.expandtabs` in Python | [#27](https://github.com/huandu/xstrings/issues/27) |
+| [FirstRuneToLower](https://godoc.org/github.com/huandu/xstrings#FirstRuneToLower) | `lcfirst` in PHP or Perl | [#15](https://github.com/huandu/xstrings/issues/15) |
+| [FirstRuneToUpper](https://godoc.org/github.com/huandu/xstrings#FirstRuneToUpper) | `String#capitalize` in Ruby; `ucfirst` in PHP or Perl | [#15](https://github.com/huandu/xstrings/issues/15) |
+| [Insert](https://godoc.org/github.com/huandu/xstrings#Insert) | `String#insert` in Ruby | [#18](https://github.com/huandu/xstrings/issues/18) |
+| [LastPartition](https://godoc.org/github.com/huandu/xstrings#LastPartition) | `str.rpartition` in Python; `String#rpartition` in Ruby | [#19](https://github.com/huandu/xstrings/issues/19) |
+| [LeftJustify](https://godoc.org/github.com/huandu/xstrings#LeftJustify) | `str.ljust` in Python; `String#ljust` in Ruby | [#28](https://github.com/huandu/xstrings/issues/28) |
+| [Len](https://godoc.org/github.com/huandu/xstrings#Len) | `mb_strlen` in PHP | [#23](https://github.com/huandu/xstrings/issues/23) |
+| [Partition](https://godoc.org/github.com/huandu/xstrings#Partition) | `str.partition` in Python; `String#partition` in Ruby | [#10](https://github.com/huandu/xstrings/issues/10) |
+| [Reverse](https://godoc.org/github.com/huandu/xstrings#Reverse) | `String#reverse` in Ruby; `strrev` in PHP; `reverse` in Perl | [#7](https://github.com/huandu/xstrings/issues/7) |
+| [RightJustify](https://godoc.org/github.com/huandu/xstrings#RightJustify) | `str.rjust` in Python; `String#rjust` in Ruby | [#29](https://github.com/huandu/xstrings/issues/29) |
+| [RuneWidth](https://godoc.org/github.com/huandu/xstrings#RuneWidth) | - | [#27](https://github.com/huandu/xstrings/issues/27) |
+| [Scrub](https://godoc.org/github.com/huandu/xstrings#Scrub) | `String#scrub` in Ruby | [#20](https://github.com/huandu/xstrings/issues/20) |
+| [Shuffle](https://godoc.org/github.com/huandu/xstrings#Shuffle) | `str_shuffle` in PHP | [#13](https://github.com/huandu/xstrings/issues/13) |
+| [ShuffleSource](https://godoc.org/github.com/huandu/xstrings#ShuffleSource) | `str_shuffle` in PHP | [#13](https://github.com/huandu/xstrings/issues/13) |
+| [Slice](https://godoc.org/github.com/huandu/xstrings#Slice) | `mb_substr` in PHP | [#9](https://github.com/huandu/xstrings/issues/9) |
+| [Squeeze](https://godoc.org/github.com/huandu/xstrings#Squeeze) | `String#squeeze` in Ruby | [#11](https://github.com/huandu/xstrings/issues/11) |
+| [Successor](https://godoc.org/github.com/huandu/xstrings#Successor) | `String#succ` or `String#next` in Ruby | [#22](https://github.com/huandu/xstrings/issues/22) |
+| [SwapCase](https://godoc.org/github.com/huandu/xstrings#SwapCase) | `str.swapcase` in Python; `String#swapcase` in Ruby | [#12](https://github.com/huandu/xstrings/issues/12) |
+| [ToCamelCase](https://godoc.org/github.com/huandu/xstrings#ToCamelCase) | `String#camelize` in RoR | [#1](https://github.com/huandu/xstrings/issues/1) |
+| [ToKebab](https://godoc.org/github.com/huandu/xstrings#ToKebabCase) | - | [#41](https://github.com/huandu/xstrings/issues/41) |
+| [ToPascalCase](https://godoc.org/github.com/huandu/xstrings#ToPascalCase) | - | [#1](https://github.com/huandu/xstrings/issues/1) |
+| [ToSnakeCase](https://godoc.org/github.com/huandu/xstrings#ToSnakeCase) | `String#underscore` in RoR | [#1](https://github.com/huandu/xstrings/issues/1) |
+| [Translate](https://godoc.org/github.com/huandu/xstrings#Translate) | `str.translate` in Python; `String#tr` in Ruby; `strtr` in PHP; `tr///` in Perl | [#21](https://github.com/huandu/xstrings/issues/21) |
+| [Width](https://godoc.org/github.com/huandu/xstrings#Width) | `mb_strwidth` in PHP | [#26](https://github.com/huandu/xstrings/issues/26) |
+| [WordCount](https://godoc.org/github.com/huandu/xstrings#WordCount) | `str_word_count` in PHP | [#14](https://github.com/huandu/xstrings/issues/14) |
+| [WordSplit](https://godoc.org/github.com/huandu/xstrings#WordSplit) | - | [#14](https://github.com/huandu/xstrings/issues/14) |
+
+### Package `strings` functions
+
+_Keep this table sorted by Function in ascending order._
+
+| Function | Friends |
+| --------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
+| [Contains](http://golang.org/pkg/strings/#Contains) | `String#include?` in Ruby |
+| [ContainsAny](http://golang.org/pkg/strings/#ContainsAny) | - |
+| [ContainsRune](http://golang.org/pkg/strings/#ContainsRune) | - |
+| [Count](http://golang.org/pkg/strings/#Count) | `str.count` in Python; `substr_count` in PHP |
+| [EqualFold](http://golang.org/pkg/strings/#EqualFold) | `stricmp` in PHP; `String#casecmp` in Ruby |
+| [Fields](http://golang.org/pkg/strings/#Fields) | `str.split` in Python; `split` in Perl; `String#split` in Ruby |
+| [FieldsFunc](http://golang.org/pkg/strings/#FieldsFunc) | - |
+| [HasPrefix](http://golang.org/pkg/strings/#HasPrefix) | `str.startswith` in Python; `String#start_with?` in Ruby |
+| [HasSuffix](http://golang.org/pkg/strings/#HasSuffix) | `str.endswith` in Python; `String#end_with?` in Ruby |
+| [Index](http://golang.org/pkg/strings/#Index) | `str.index` in Python; `String#index` in Ruby; `strpos` in PHP; `index` in Perl |
+| [IndexAny](http://golang.org/pkg/strings/#IndexAny) | - |
+| [IndexByte](http://golang.org/pkg/strings/#IndexByte) | - |
+| [IndexFunc](http://golang.org/pkg/strings/#IndexFunc) | - |
+| [IndexRune](http://golang.org/pkg/strings/#IndexRune) | - |
+| [Join](http://golang.org/pkg/strings/#Join) | `str.join` in Python; `Array#join` in Ruby; `implode` in PHP; `join` in Perl |
+| [LastIndex](http://golang.org/pkg/strings/#LastIndex) | `str.rindex` in Python; `String#rindex`; `strrpos` in PHP; `rindex` in Perl |
+| [LastIndexAny](http://golang.org/pkg/strings/#LastIndexAny) | - |
+| [LastIndexFunc](http://golang.org/pkg/strings/#LastIndexFunc) | - |
+| [Map](http://golang.org/pkg/strings/#Map) | `String#each_codepoint` in Ruby |
+| [Repeat](http://golang.org/pkg/strings/#Repeat) | operator `*` in Python and Ruby; `str_repeat` in PHP |
+| [Replace](http://golang.org/pkg/strings/#Replace) | `str.replace` in Python; `String#sub` in Ruby; `str_replace` in PHP |
+| [Split](http://golang.org/pkg/strings/#Split) | `str.split` in Python; `String#split` in Ruby; `explode` in PHP; `split` in Perl |
+| [SplitAfter](http://golang.org/pkg/strings/#SplitAfter) | - |
+| [SplitAfterN](http://golang.org/pkg/strings/#SplitAfterN) | - |
+| [SplitN](http://golang.org/pkg/strings/#SplitN) | `str.split` in Python; `String#split` in Ruby; `explode` in PHP; `split` in Perl |
+| [Title](http://golang.org/pkg/strings/#Title) | `str.title` in Python |
+| [ToLower](http://golang.org/pkg/strings/#ToLower) | `str.lower` in Python; `String#downcase` in Ruby; `strtolower` in PHP; `lc` in Perl |
+| [ToLowerSpecial](http://golang.org/pkg/strings/#ToLowerSpecial) | - |
+| [ToTitle](http://golang.org/pkg/strings/#ToTitle) | - |
+| [ToTitleSpecial](http://golang.org/pkg/strings/#ToTitleSpecial) | - |
+| [ToUpper](http://golang.org/pkg/strings/#ToUpper) | `str.upper` in Python; `String#upcase` in Ruby; `strtoupper` in PHP; `uc` in Perl |
+| [ToUpperSpecial](http://golang.org/pkg/strings/#ToUpperSpecial) | - |
+| [Trim](http://golang.org/pkg/strings/#Trim) | `str.strip` in Python; `String#strip` in Ruby; `trim` in PHP |
+| [TrimFunc](http://golang.org/pkg/strings/#TrimFunc) | - |
+| [TrimLeft](http://golang.org/pkg/strings/#TrimLeft) | `str.lstrip` in Python; `String#lstrip` in Ruby; `ltrim` in PHP |
+| [TrimLeftFunc](http://golang.org/pkg/strings/#TrimLeftFunc) | - |
+| [TrimPrefix](http://golang.org/pkg/strings/#TrimPrefix) | - |
+| [TrimRight](http://golang.org/pkg/strings/#TrimRight) | `str.rstrip` in Python; `String#rstrip` in Ruby; `rtrim` in PHP |
+| [TrimRightFunc](http://golang.org/pkg/strings/#TrimRightFunc) | - |
+| [TrimSpace](http://golang.org/pkg/strings/#TrimSpace) | `str.strip` in Python; `String#strip` in Ruby; `trim` in PHP |
+| [TrimSuffix](http://golang.org/pkg/strings/#TrimSuffix) | `String#chomp` in Ruby; `chomp` in Perl |
+
+## License
This library is licensed under MIT license. See LICENSE for details.
diff --git a/vendor/github.com/huandu/xstrings/convert.go b/vendor/github.com/huandu/xstrings/convert.go
index 3d5a34950b0..5d8cfee470b 100644
--- a/vendor/github.com/huandu/xstrings/convert.go
+++ b/vendor/github.com/huandu/xstrings/convert.go
@@ -12,17 +12,38 @@ import (
// ToCamelCase is to convert words separated by space, underscore and hyphen to camel case.
//
// Some samples.
-// "some_words" => "SomeWords"
-// "http_server" => "HttpServer"
-// "no_https" => "NoHttps"
-// "_complex__case_" => "_Complex_Case_"
-// "some words" => "SomeWords"
+//
+// "some_words" => "someWords"
+// "http_server" => "httpServer"
+// "no_https" => "noHttps"
+// "_complex__case_" => "_complex_Case_"
+// "some words" => "someWords"
+// "GOLANG_IS_GREAT" => "golangIsGreat"
func ToCamelCase(str string) string {
+ return toCamelCase(str, false)
+}
+
+// ToPascalCase is to convert words separated by space, underscore and hyphen to pascal case.
+//
+// Some samples.
+//
+// "some_words" => "SomeWords"
+// "http_server" => "HttpServer"
+// "no_https" => "NoHttps"
+// "_complex__case_" => "_Complex_Case_"
+// "some words" => "SomeWords"
+// "GOLANG_IS_GREAT" => "GolangIsGreat"
+func ToPascalCase(str string) string {
+ return toCamelCase(str, true)
+}
+
+func toCamelCase(str string, isBig bool) string {
if len(str) == 0 {
return ""
}
buf := &stringBuilder{}
+ var isFirstRuneUpper bool
var r0, r1 rune
var size int
@@ -32,7 +53,14 @@ func ToCamelCase(str string) string {
str = str[size:]
if !isConnector(r0) {
- r0 = unicode.ToUpper(r0)
+ isFirstRuneUpper = unicode.IsUpper(r0)
+
+ if isBig {
+ r0 = unicode.ToUpper(r0)
+ } else {
+ r0 = unicode.ToLower(r0)
+ }
+
break
}
@@ -59,13 +87,25 @@ func ToCamelCase(str string) string {
}
if isConnector(r1) {
+ isFirstRuneUpper = unicode.IsUpper(r0)
r0 = unicode.ToUpper(r0)
} else {
- r0 = unicode.ToLower(r0)
+ if isFirstRuneUpper {
+ if unicode.IsUpper(r0) {
+ r0 = unicode.ToLower(r0)
+ } else {
+ isFirstRuneUpper = false
+ }
+ }
+
buf.WriteRune(r1)
}
}
+ if isFirstRuneUpper && !isBig {
+ r0 = unicode.ToLower(r0)
+ }
+
buf.WriteRune(r0)
return buf.String()
}
@@ -74,16 +114,17 @@ func ToCamelCase(str string) string {
// snake case format.
//
// Some samples.
-// "FirstName" => "first_name"
-// "HTTPServer" => "http_server"
-// "NoHTTPS" => "no_https"
-// "GO_PATH" => "go_path"
-// "GO PATH" => "go_path" // space is converted to underscore.
-// "GO-PATH" => "go_path" // hyphen is converted to underscore.
-// "http2xx" => "http_2xx" // insert an underscore before a number and after an alphabet.
-// "HTTP20xOK" => "http_20x_ok"
-// "Duration2m3s" => "duration_2m3s"
-// "Bld4Floor3rd" => "bld4_floor_3rd"
+//
+// "FirstName" => "first_name"
+// "HTTPServer" => "http_server"
+// "NoHTTPS" => "no_https"
+// "GO_PATH" => "go_path"
+// "GO PATH" => "go_path" // space is converted to underscore.
+// "GO-PATH" => "go_path" // hyphen is converted to underscore.
+// "http2xx" => "http_2xx" // insert an underscore before a number and after an alphabet.
+// "HTTP20xOK" => "http_20x_ok"
+// "Duration2m3s" => "duration_2m3s"
+// "Bld4Floor3rd" => "bld4_floor_3rd"
func ToSnakeCase(str string) string {
return camelCaseToLowerCase(str, '_')
}
@@ -92,16 +133,17 @@ func ToSnakeCase(str string) string {
// kebab case format.
//
// Some samples.
-// "FirstName" => "first-name"
-// "HTTPServer" => "http-server"
-// "NoHTTPS" => "no-https"
-// "GO_PATH" => "go-path"
-// "GO PATH" => "go-path" // space is converted to '-'.
-// "GO-PATH" => "go-path" // hyphen is converted to '-'.
-// "http2xx" => "http-2xx" // insert an underscore before a number and after an alphabet.
-// "HTTP20xOK" => "http-20x-ok"
-// "Duration2m3s" => "duration-2m3s"
-// "Bld4Floor3rd" => "bld4-floor-3rd"
+//
+// "FirstName" => "first-name"
+// "HTTPServer" => "http-server"
+// "NoHTTPS" => "no-https"
+// "GO_PATH" => "go-path"
+// "GO PATH" => "go-path" // space is converted to '-'.
+// "GO-PATH" => "go-path" // hyphen is converted to '-'.
+// "http2xx" => "http-2xx" // insert an underscore before a number and after an alphabet.
+// "HTTP20xOK" => "http-20x-ok"
+// "Duration2m3s" => "duration-2m3s"
+// "Bld4Floor3rd" => "bld4-floor-3rd"
func ToKebabCase(str string) string {
return camelCaseToLowerCase(str, '-')
}
@@ -130,7 +172,7 @@ func camelCaseToLowerCase(str string, connector rune) string {
wt, word, remaining = nextWord(remaining)
}
- if wt != invalidWord && wt != punctWord {
+ if wt != invalidWord && wt != punctWord && wt != connectorWord {
buf.WriteRune(connector)
}
@@ -510,17 +552,18 @@ func ShuffleSource(str string, src rand.Source) string {
// regardless whether the result is a valid rune or not.
//
// Only following characters are alphanumeric.
-// * a - z
-// * A - Z
-// * 0 - 9
+// - a - z
+// - A - Z
+// - 0 - 9
//
// Samples (borrowed from ruby's String#succ document):
-// "abcd" => "abce"
-// "THX1138" => "THX1139"
-// "<>" => "<>"
-// "1999zzz" => "2000aaa"
-// "ZZZ9999" => "AAAA0000"
-// "***" => "**+"
+//
+// "abcd" => "abce"
+// "THX1138" => "THX1139"
+// "<>" => "<>"
+// "1999zzz" => "2000aaa"
+// "ZZZ9999" => "AAAA0000"
+// "***" => "**+"
func Successor(str string) string {
if str == "" {
return str
diff --git a/vendor/github.com/huandu/xstrings/format.go b/vendor/github.com/huandu/xstrings/format.go
index 8cd76c525cc..b32219bbd58 100644
--- a/vendor/github.com/huandu/xstrings/format.go
+++ b/vendor/github.com/huandu/xstrings/format.go
@@ -17,9 +17,10 @@ import (
// If tabSize <= 0, ExpandTabs panics with error.
//
// Samples:
-// ExpandTabs("a\tbc\tdef\tghij\tk", 4) => "a bc def ghij k"
-// ExpandTabs("abcdefg\thij\nk\tl", 4) => "abcdefg hij\nk l"
-// ExpandTabs("z中\t文\tw", 4) => "z中 文 w"
+//
+// ExpandTabs("a\tbc\tdef\tghij\tk", 4) => "a bc def ghij k"
+// ExpandTabs("abcdefg\thij\nk\tl", 4) => "abcdefg hij\nk l"
+// ExpandTabs("z中\t文\tw", 4) => "z中 文 w"
func ExpandTabs(str string, tabSize int) string {
if tabSize <= 0 {
panic("tab size must be positive")
@@ -74,9 +75,10 @@ func ExpandTabs(str string, tabSize int) string {
// If pad is an empty string, str will be returned.
//
// Samples:
-// LeftJustify("hello", 4, " ") => "hello"
-// LeftJustify("hello", 10, " ") => "hello "
-// LeftJustify("hello", 10, "123") => "hello12312"
+//
+// LeftJustify("hello", 4, " ") => "hello"
+// LeftJustify("hello", 10, " ") => "hello "
+// LeftJustify("hello", 10, "123") => "hello12312"
func LeftJustify(str string, length int, pad string) string {
l := Len(str)
@@ -100,9 +102,10 @@ func LeftJustify(str string, length int, pad string) string {
// If pad is an empty string, str will be returned.
//
// Samples:
-// RightJustify("hello", 4, " ") => "hello"
-// RightJustify("hello", 10, " ") => " hello"
-// RightJustify("hello", 10, "123") => "12312hello"
+//
+// RightJustify("hello", 4, " ") => "hello"
+// RightJustify("hello", 10, " ") => " hello"
+// RightJustify("hello", 10, "123") => "12312hello"
func RightJustify(str string, length int, pad string) string {
l := Len(str)
@@ -126,9 +129,10 @@ func RightJustify(str string, length int, pad string) string {
// If pad is an empty string, str will be returned.
//
// Samples:
-// Center("hello", 4, " ") => "hello"
-// Center("hello", 10, " ") => " hello "
-// Center("hello", 10, "123") => "12hello123"
+//
+// Center("hello", 4, " ") => "hello"
+// Center("hello", 10, " ") => " hello "
+// Center("hello", 10, "123") => "12hello123"
func Center(str string, length int, pad string) string {
l := Len(str)
diff --git a/vendor/github.com/huandu/xstrings/manipulate.go b/vendor/github.com/huandu/xstrings/manipulate.go
index 64075f9bb8a..ab42fe0fec6 100644
--- a/vendor/github.com/huandu/xstrings/manipulate.go
+++ b/vendor/github.com/huandu/xstrings/manipulate.go
@@ -79,10 +79,12 @@ func Slice(str string, start, end int) string {
// The return value is a slice of strings with head, match and tail.
//
// If str contains sep, for example "hello" and "l", Partition returns
-// "he", "l", "lo"
+//
+// "he", "l", "lo"
//
// If str doesn't contain sep, for example "hello" and "x", Partition returns
-// "hello", "", ""
+//
+// "hello", "", ""
func Partition(str, sep string) (head, match, tail string) {
index := strings.Index(str, sep)
@@ -101,10 +103,12 @@ func Partition(str, sep string) (head, match, tail string) {
// The return value is a slice of strings with head, match and tail.
//
// If str contains sep, for example "hello" and "l", LastPartition returns
-// "hel", "l", "o"
+//
+// "hel", "l", "o"
//
// If str doesn't contain sep, for example "hello" and "x", LastPartition returns
-// "", "", "hello"
+//
+// "", "", "hello"
func LastPartition(str, sep string) (head, match, tail string) {
index := strings.LastIndex(str, sep)
diff --git a/vendor/github.com/huandu/xstrings/stringbuilder.go b/vendor/github.com/huandu/xstrings/stringbuilder.go
index bb0919d32f7..06812fea07d 100644
--- a/vendor/github.com/huandu/xstrings/stringbuilder.go
+++ b/vendor/github.com/huandu/xstrings/stringbuilder.go
@@ -1,4 +1,5 @@
-//+build go1.10
+//go:build go1.10
+// +build go1.10
package xstrings
diff --git a/vendor/github.com/huandu/xstrings/stringbuilder_go110.go b/vendor/github.com/huandu/xstrings/stringbuilder_go110.go
index dac389d139e..ccaa5aedd33 100644
--- a/vendor/github.com/huandu/xstrings/stringbuilder_go110.go
+++ b/vendor/github.com/huandu/xstrings/stringbuilder_go110.go
@@ -1,4 +1,5 @@
-//+build !go1.10
+//go:build !go1.10
+// +build !go1.10
package xstrings
diff --git a/vendor/github.com/huandu/xstrings/translate.go b/vendor/github.com/huandu/xstrings/translate.go
index 42e694fb176..1fac6a00be3 100644
--- a/vendor/github.com/huandu/xstrings/translate.go
+++ b/vendor/github.com/huandu/xstrings/translate.go
@@ -416,14 +416,16 @@ func (tr *Translator) HasPattern() bool {
//
// From and to are patterns representing a set of characters. Pattern is defined as following.
//
-// * Special characters
-// * '-' means a range of runes, e.g.
-// * "a-z" means all characters from 'a' to 'z' inclusive;
-// * "z-a" means all characters from 'z' to 'a' inclusive.
-// * '^' as first character means a set of all runes excepted listed, e.g.
-// * "^a-z" means all characters except 'a' to 'z' inclusive.
-// * '\' escapes special characters.
-// * Normal character represents itself, e.g. "abc" is a set including 'a', 'b' and 'c'.
+// Special characters:
+//
+// 1. '-' means a range of runes, e.g.
+// "a-z" means all characters from 'a' to 'z' inclusive;
+// "z-a" means all characters from 'z' to 'a' inclusive.
+// 2. '^' as first character means a set of all runes excepted listed, e.g.
+// "^a-z" means all characters except 'a' to 'z' inclusive.
+// 3. '\' escapes special characters.
+//
+// Normal character represents itself, e.g. "abc" is a set including 'a', 'b' and 'c'.
//
// Translate will try to find a 1:1 mapping from from to to.
// If to is smaller than from, last rune in to will be used to map "out of range" characters in from.
@@ -433,12 +435,13 @@ func (tr *Translator) HasPattern() bool {
// If the to pattern is an empty string, Translate works exactly the same as Delete.
//
// Samples:
-// Translate("hello", "aeiou", "12345") => "h2ll4"
-// Translate("hello", "a-z", "A-Z") => "HELLO"
-// Translate("hello", "z-a", "a-z") => "svool"
-// Translate("hello", "aeiou", "*") => "h*ll*"
-// Translate("hello", "^l", "*") => "**ll*"
-// Translate("hello ^ world", `\^lo`, "*") => "he*** * w*r*d"
+//
+// Translate("hello", "aeiou", "12345") => "h2ll4"
+// Translate("hello", "a-z", "A-Z") => "HELLO"
+// Translate("hello", "z-a", "a-z") => "svool"
+// Translate("hello", "aeiou", "*") => "h*ll*"
+// Translate("hello", "^l", "*") => "**ll*"
+// Translate("hello ^ world", `\^lo`, "*") => "he*** * w*r*d"
func Translate(str, from, to string) string {
tr := NewTranslator(from, to)
return tr.Translate(str)
@@ -448,9 +451,10 @@ func Translate(str, from, to string) string {
// Pattern is defined in Translate function.
//
// Samples:
-// Delete("hello", "aeiou") => "hll"
-// Delete("hello", "a-k") => "llo"
-// Delete("hello", "^a-k") => "he"
+//
+// Delete("hello", "aeiou") => "hll"
+// Delete("hello", "a-k") => "llo"
+// Delete("hello", "^a-k") => "he"
func Delete(str, pattern string) string {
tr := NewTranslator(pattern, "")
return tr.Translate(str)
@@ -460,9 +464,10 @@ func Delete(str, pattern string) string {
// Pattern is defined in Translate function.
//
// Samples:
-// Count("hello", "aeiou") => 3
-// Count("hello", "a-k") => 3
-// Count("hello", "^a-k") => 2
+//
+// Count("hello", "aeiou") => 3
+// Count("hello", "a-k") => 3
+// Count("hello", "^a-k") => 2
func Count(str, pattern string) int {
if pattern == "" || str == "" {
return 0
@@ -491,9 +496,10 @@ func Count(str, pattern string) int {
// If pattern is not empty, only runes matching the pattern will be squeezed.
//
// Samples:
-// Squeeze("hello", "") => "helo"
-// Squeeze("hello", "m-z") => "hello"
-// Squeeze("hello world", " ") => "hello world"
+//
+// Squeeze("hello", "") => "helo"
+// Squeeze("hello", "m-z") => "hello"
+// Squeeze("hello world", " ") => "hello world"
func Squeeze(str, pattern string) string {
var last, r rune
var size int
diff --git a/vendor/github.com/mitchellh/copystructure/.travis.yml b/vendor/github.com/mitchellh/copystructure/.travis.yml
deleted file mode 100644
index d7b9589ab11..00000000000
--- a/vendor/github.com/mitchellh/copystructure/.travis.yml
+++ /dev/null
@@ -1,12 +0,0 @@
-language: go
-
-go:
- - 1.7
- - tip
-
-script:
- - go test
-
-matrix:
- allow_failures:
- - go: tip
diff --git a/vendor/github.com/mitchellh/copystructure/README.md b/vendor/github.com/mitchellh/copystructure/README.md
index bcb8c8d2cb9..f0fbd2e5c98 100644
--- a/vendor/github.com/mitchellh/copystructure/README.md
+++ b/vendor/github.com/mitchellh/copystructure/README.md
@@ -1,21 +1,21 @@
-# copystructure
-
-copystructure is a Go library for deep copying values in Go.
-
-This allows you to copy Go values that may contain reference values
-such as maps, slices, or pointers, and copy their data as well instead
-of just their references.
-
-## Installation
-
-Standard `go get`:
-
-```
-$ go get github.com/mitchellh/copystructure
-```
-
-## Usage & Example
-
-For usage and examples see the [Godoc](http://godoc.org/github.com/mitchellh/copystructure).
-
-The `Copy` function has examples associated with it there.
+# copystructure
+
+copystructure is a Go library for deep copying values in Go.
+
+This allows you to copy Go values that may contain reference values
+such as maps, slices, or pointers, and copy their data as well instead
+of just their references.
+
+## Installation
+
+Standard `go get`:
+
+```
+$ go get github.com/mitchellh/copystructure
+```
+
+## Usage & Example
+
+For usage and examples see the [Godoc](http://godoc.org/github.com/mitchellh/copystructure).
+
+The `Copy` function has examples associated with it there.
diff --git a/vendor/github.com/mitchellh/copystructure/copystructure.go b/vendor/github.com/mitchellh/copystructure/copystructure.go
index 140435255e1..8089e6670a3 100644
--- a/vendor/github.com/mitchellh/copystructure/copystructure.go
+++ b/vendor/github.com/mitchellh/copystructure/copystructure.go
@@ -8,7 +8,30 @@ import (
"github.com/mitchellh/reflectwalk"
)
+const tagKey = "copy"
+
// Copy returns a deep copy of v.
+//
+// Copy is unable to copy unexported fields in a struct (lowercase field names).
+// Unexported fields can't be reflected by the Go runtime and therefore
+// copystructure can't perform any data copies.
+//
+// For structs, copy behavior can be controlled with struct tags. For example:
+//
+// struct {
+// Name string
+// Data *bytes.Buffer `copy:"shallow"`
+// }
+//
+// The available tag values are:
+//
+// * "ignore" - The field will be ignored, effectively resulting in it being
+// assigned the zero value in the copy.
+//
+// * "shallow" - The field will be be shallow copied. This means that references
+// values such as pointers, maps, slices, etc. will be directly assigned
+// versus deep copied.
+//
func Copy(v interface{}) (interface{}, error) {
return Config{}.Copy(v)
}
@@ -28,6 +51,19 @@ type CopierFunc func(interface{}) (interface{}, error)
// this map as well as to Copy in a mutex.
var Copiers map[reflect.Type]CopierFunc = make(map[reflect.Type]CopierFunc)
+// ShallowCopiers is a map of pointer types that behave specially
+// when they are copied. If a type is found in this map while deep
+// copying, the pointer value will be shallow copied and not walked
+// into.
+//
+// The key should be the type, obtained using: reflect.TypeOf(value
+// with type).
+//
+// It is unsafe to write to this map after Copies have started. If you
+// are writing to this map while also copying, wrap all modifications to
+// this map as well as to Copy in a mutex.
+var ShallowCopiers map[reflect.Type]struct{} = make(map[reflect.Type]struct{})
+
// Must is a helper that wraps a call to a function returning
// (interface{}, error) and panics if the error is non-nil. It is intended
// for use in variable initializations and should only be used when a copy
@@ -50,6 +86,11 @@ type Config struct {
// Copiers is a map of types associated with a CopierFunc. Use the global
// Copiers map if this is nil.
Copiers map[reflect.Type]CopierFunc
+
+ // ShallowCopiers is a map of pointer types that when they are
+ // shallow copied no matter where they are encountered. Use the
+ // global ShallowCopiers if this is nil.
+ ShallowCopiers map[reflect.Type]struct{}
}
func (c Config) Copy(v interface{}) (interface{}, error) {
@@ -65,6 +106,12 @@ func (c Config) Copy(v interface{}) (interface{}, error) {
if c.Copiers == nil {
c.Copiers = Copiers
}
+ w.copiers = c.Copiers
+
+ if c.ShallowCopiers == nil {
+ c.ShallowCopiers = ShallowCopiers
+ }
+ w.shallowCopiers = c.ShallowCopiers
err := reflectwalk.Walk(v, w)
if err != nil {
@@ -93,10 +140,12 @@ func ifaceKey(pointers, depth int) uint64 {
type walker struct {
Result interface{}
- depth int
- ignoreDepth int
- vals []reflect.Value
- cs []reflect.Value
+ copiers map[reflect.Type]CopierFunc
+ shallowCopiers map[reflect.Type]struct{}
+ depth int
+ ignoreDepth int
+ vals []reflect.Value
+ cs []reflect.Value
// This stores the number of pointers we've walked over, indexed by depth.
ps []int
@@ -263,6 +312,20 @@ func (w *walker) PointerExit(v bool) error {
return nil
}
+func (w *walker) Pointer(v reflect.Value) error {
+ if _, ok := w.shallowCopiers[v.Type()]; ok {
+ // Shallow copy this value. Use the same logic as primitive, then
+ // return skip.
+ if err := w.Primitive(v); err != nil {
+ return err
+ }
+
+ return reflectwalk.SkipEntry
+ }
+
+ return nil
+}
+
func (w *walker) Interface(v reflect.Value) error {
if !v.IsValid() {
return nil
@@ -356,7 +419,7 @@ func (w *walker) Struct(s reflect.Value) error {
w.lock(s)
var v reflect.Value
- if c, ok := Copiers[s.Type()]; ok {
+ if c, ok := w.copiers[s.Type()]; ok {
// We have a Copier for this struct, so we use that copier to
// get the copy, and we ignore anything deeper than this.
w.ignoreDepth = w.depth
@@ -396,9 +459,29 @@ func (w *walker) StructField(f reflect.StructField, v reflect.Value) error {
return reflectwalk.SkipEntry
}
+ switch f.Tag.Get(tagKey) {
+ case "shallow":
+ // If we're shallow copying then assign the value directly to the
+ // struct and skip the entry.
+ if v.IsValid() {
+ s := w.cs[len(w.cs)-1]
+ sf := reflect.Indirect(s).FieldByName(f.Name)
+ if sf.CanSet() {
+ sf.Set(v)
+ }
+ }
+
+ return reflectwalk.SkipEntry
+
+ case "ignore":
+ // Do nothing
+ return reflectwalk.SkipEntry
+ }
+
// Push the field onto the stack, we'll handle it when we exit
// the struct field in Exit...
w.valPush(reflect.ValueOf(f))
+
return nil
}
diff --git a/vendor/github.com/mitchellh/reflectwalk/reflectwalk.go b/vendor/github.com/mitchellh/reflectwalk/reflectwalk.go
index d7ab7b6d782..7fee7b050ba 100644
--- a/vendor/github.com/mitchellh/reflectwalk/reflectwalk.go
+++ b/vendor/github.com/mitchellh/reflectwalk/reflectwalk.go
@@ -69,6 +69,13 @@ type PointerWalker interface {
PointerExit(bool) error
}
+// PointerValueWalker implementations are notified with the value of
+// a particular pointer when a pointer is walked. Pointer is called
+// right before PointerEnter.
+type PointerValueWalker interface {
+ Pointer(reflect.Value) error
+}
+
// SkipEntry can be returned from walk functions to skip walking
// the value of this field. This is only valid in the following functions:
//
@@ -130,6 +137,17 @@ func walk(v reflect.Value, w interface{}) (err error) {
}
if pointerV.Kind() == reflect.Ptr {
+ if pw, ok := w.(PointerValueWalker); ok {
+ if err = pw.Pointer(pointerV); err != nil {
+ if err == SkipEntry {
+ // Skip the rest of this entry but clear the error
+ return nil
+ }
+
+ return
+ }
+ }
+
pointer = true
v = reflect.Indirect(pointerV)
}
@@ -230,7 +248,8 @@ func walkMap(v reflect.Value, w interface{}) error {
ew.Enter(MapValue)
}
- if err := walk(kv, w); err != nil {
+ // get the map value again as it may have changed in the MapElem call
+ if err := walk(v.MapIndex(k), w); err != nil {
return err
}
diff --git a/vendor/github.com/shopspring/decimal/.gitignore b/vendor/github.com/shopspring/decimal/.gitignore
index 8a43ce9d7b6..ff36b987f07 100644
--- a/vendor/github.com/shopspring/decimal/.gitignore
+++ b/vendor/github.com/shopspring/decimal/.gitignore
@@ -4,3 +4,6 @@
# IntelliJ
.idea/
*.iml
+
+# VS code
+*.code-workspace
diff --git a/vendor/github.com/shopspring/decimal/.travis.yml b/vendor/github.com/shopspring/decimal/.travis.yml
deleted file mode 100644
index 55d42b289d0..00000000000
--- a/vendor/github.com/shopspring/decimal/.travis.yml
+++ /dev/null
@@ -1,13 +0,0 @@
-language: go
-
-go:
- - 1.7.x
- - 1.12.x
- - 1.13.x
- - tip
-
-install:
- - go build .
-
-script:
- - go test -v
diff --git a/vendor/github.com/shopspring/decimal/CHANGELOG.md b/vendor/github.com/shopspring/decimal/CHANGELOG.md
index 01ba02feb2c..432d0fd4ea6 100644
--- a/vendor/github.com/shopspring/decimal/CHANGELOG.md
+++ b/vendor/github.com/shopspring/decimal/CHANGELOG.md
@@ -1,4 +1,61 @@
-## Decimal v1.2.0
+## Decimal v1.4.0
+#### BREAKING
+- Drop support for Go version older than 1.10 [#361](https://github.com/shopspring/decimal/pull/361)
+
+#### FEATURES
+- Add implementation of natural logarithm [#339](https://github.com/shopspring/decimal/pull/339) [#357](https://github.com/shopspring/decimal/pull/357)
+- Add improved implementation of power operation [#358](https://github.com/shopspring/decimal/pull/358)
+- Add Compare method which forwards calls to Cmp [#346](https://github.com/shopspring/decimal/pull/346)
+- Add NewFromBigRat constructor [#288](https://github.com/shopspring/decimal/pull/288)
+- Add NewFromUint64 constructor [#352](https://github.com/shopspring/decimal/pull/352)
+
+#### ENHANCEMENTS
+- Migrate to Github Actions [#245](https://github.com/shopspring/decimal/pull/245) [#340](https://github.com/shopspring/decimal/pull/340)
+- Fix examples for RoundDown, RoundFloor, RoundUp, and RoundCeil [#285](https://github.com/shopspring/decimal/pull/285) [#328](https://github.com/shopspring/decimal/pull/328) [#341](https://github.com/shopspring/decimal/pull/341)
+- Use Godoc standard to mark deprecated Equals and StringScaled methods [#342](https://github.com/shopspring/decimal/pull/342)
+- Removed unnecessary min function for RescalePair method [#265](https://github.com/shopspring/decimal/pull/265)
+- Avoid reallocation of initial slice in MarshalBinary (GobEncode) [#355](https://github.com/shopspring/decimal/pull/355)
+- Optimize NumDigits method [#301](https://github.com/shopspring/decimal/pull/301) [#356](https://github.com/shopspring/decimal/pull/356)
+- Optimize BigInt method [#359](https://github.com/shopspring/decimal/pull/359)
+- Support scanning uint64 [#131](https://github.com/shopspring/decimal/pull/131) [#364](https://github.com/shopspring/decimal/pull/364)
+- Add docs section with alternative libraries [#363](https://github.com/shopspring/decimal/pull/363)
+
+#### BUGFIXES
+- Fix incorrect calculation of decimal modulo [#258](https://github.com/shopspring/decimal/pull/258) [#317](https://github.com/shopspring/decimal/pull/317)
+- Allocate new(big.Int) in Copy method to deeply clone it [#278](https://github.com/shopspring/decimal/pull/278)
+- Fix overflow edge case in QuoRem method [#322](https://github.com/shopspring/decimal/pull/322)
+
+## Decimal v1.3.1
+
+#### ENHANCEMENTS
+- Reduce memory allocation in case of initialization from big.Int [#252](https://github.com/shopspring/decimal/pull/252)
+
+#### BUGFIXES
+- Fix binary marshalling of decimal zero value [#253](https://github.com/shopspring/decimal/pull/253)
+
+## Decimal v1.3.0
+
+#### FEATURES
+- Add NewFromFormattedString initializer [#184](https://github.com/shopspring/decimal/pull/184)
+- Add NewNullDecimal initializer [#234](https://github.com/shopspring/decimal/pull/234)
+- Add implementation of natural exponent function (Taylor, Hull-Abraham) [#229](https://github.com/shopspring/decimal/pull/229)
+- Add RoundUp, RoundDown, RoundCeil, RoundFloor methods [#196](https://github.com/shopspring/decimal/pull/196) [#202](https://github.com/shopspring/decimal/pull/202) [#220](https://github.com/shopspring/decimal/pull/220)
+- Add XML support for NullDecimal [#192](https://github.com/shopspring/decimal/pull/192)
+- Add IsInteger method [#179](https://github.com/shopspring/decimal/pull/179)
+- Add Copy helper method [#123](https://github.com/shopspring/decimal/pull/123)
+- Add InexactFloat64 helper method [#205](https://github.com/shopspring/decimal/pull/205)
+- Add CoefficientInt64 helper method [#244](https://github.com/shopspring/decimal/pull/244)
+
+#### ENHANCEMENTS
+- Performance optimization of NewFromString init method [#198](https://github.com/shopspring/decimal/pull/198)
+- Performance optimization of Abs and Round methods [#240](https://github.com/shopspring/decimal/pull/240)
+- Additional tests (CI) for ppc64le architecture [#188](https://github.com/shopspring/decimal/pull/188)
+
+#### BUGFIXES
+- Fix rounding in FormatFloat fallback path (roundShortest method, fix taken from Go main repository) [#161](https://github.com/shopspring/decimal/pull/161)
+- Add slice range checks to UnmarshalBinary method [#232](https://github.com/shopspring/decimal/pull/232)
+
+## Decimal v1.2.0
#### BREAKING
- Drop support for Go version older than 1.7 [#172](https://github.com/shopspring/decimal/pull/172)
diff --git a/vendor/github.com/shopspring/decimal/README.md b/vendor/github.com/shopspring/decimal/README.md
index b70f9015935..318c9df5813 100644
--- a/vendor/github.com/shopspring/decimal/README.md
+++ b/vendor/github.com/shopspring/decimal/README.md
@@ -1,6 +1,8 @@
# decimal
-[![Build Status](https://travis-ci.org/shopspring/decimal.png?branch=master)](https://travis-ci.org/shopspring/decimal) [![GoDoc](https://godoc.org/github.com/shopspring/decimal?status.svg)](https://godoc.org/github.com/shopspring/decimal) [![Go Report Card](https://goreportcard.com/badge/github.com/shopspring/decimal)](https://goreportcard.com/report/github.com/shopspring/decimal)
+[![ci](https://github.com/shopspring/decimal/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/shopspring/decimal/actions/workflows/ci.yml)
+[![GoDoc](https://godoc.org/github.com/shopspring/decimal?status.svg)](https://godoc.org/github.com/shopspring/decimal)
+[![Go Report Card](https://goreportcard.com/badge/github.com/shopspring/decimal)](https://goreportcard.com/report/github.com/shopspring/decimal)
Arbitrary-precision fixed-point decimal numbers in go.
@@ -20,7 +22,12 @@ Run `go get github.com/shopspring/decimal`
## Requirements
-Decimal library requires Go version `>=1.7`
+Decimal library requires Go version `>=1.10`
+
+## Documentation
+
+http://godoc.org/github.com/shopspring/decimal
+
## Usage
@@ -57,14 +64,16 @@ func main() {
}
```
-## Documentation
-
-http://godoc.org/github.com/shopspring/decimal
+## Alternative libraries
-## Production Usage
+When working with decimal numbers, you might face problems this library is not perfectly suited for.
+Fortunately, thanks to the wonderful community we have a dozen other libraries that you can choose from.
+Explore other alternatives to find the one that best fits your needs :)
-* [Spring](https://shopspring.com/), since August 14, 2014.
-* If you are using this in production, please let us know!
+* [cockroachdb/apd](https://github.com/cockroachdb/apd) - arbitrary precision, mutable and rich API similar to `big.Int`, more performant than this library
+* [alpacahq/alpacadecimal](https://github.com/alpacahq/alpacadecimal) - high performance, low precision (12 digits), fully compatible API with this library
+* [govalues/decimal](https://github.com/govalues/decimal) - high performance, zero-allocation, low precision (19 digits)
+* [greatcloak/decimal](https://github.com/greatcloak/decimal) - fork focusing on billing and e-commerce web application related use cases, includes out-of-the-box BSON marshaling support
## FAQ
diff --git a/vendor/github.com/shopspring/decimal/const.go b/vendor/github.com/shopspring/decimal/const.go
new file mode 100644
index 00000000000..e5d6fa87e8d
--- /dev/null
+++ b/vendor/github.com/shopspring/decimal/const.go
@@ -0,0 +1,63 @@
+package decimal
+
+import (
+ "strings"
+)
+
+const (
+ strLn10 = "2.302585092994045684017991454684364207601101488628772976033327900967572609677352480235997205089598298341967784042286248633409525465082806756666287369098781689482907208325554680843799894826233198528393505308965377732628846163366222287698219886746543667474404243274365155048934314939391479619404400222105101714174800368808401264708068556774321622835522011480466371565912137345074785694768346361679210180644507064800027750268491674655058685693567342067058113642922455440575892572420824131469568901675894025677631135691929203337658714166023010570308963457207544037084746994016826928280848118428931484852494864487192780967627127577539702766860595249671667418348570442250719796500471495105049221477656763693866297697952211071826454973477266242570942932258279850258550978526538320760672631716430950599508780752371033310119785754733154142180842754386359177811705430982748238504564801909561029929182431823752535770975053956518769751037497088869218020518933950723853920514463419726528728696511086257149219884997874887377134568620916705849807828059751193854445009978131146915934666241071846692310107598438319191292230792503747298650929009880391941702654416816335727555703151596113564846546190897042819763365836983716328982174407366009162177850541779276367731145041782137660111010731042397832521894898817597921798666394319523936855916447118246753245630912528778330963604262982153040874560927760726641354787576616262926568298704957954913954918049209069438580790032763017941503117866862092408537949861264933479354871737451675809537088281067452440105892444976479686075120275724181874989395971643105518848195288330746699317814634930000321200327765654130472621883970596794457943468343218395304414844803701305753674262153675579814770458031413637793236291560128185336498466942261465206459942072917119370602444929358037007718981097362533224548366988505528285966192805098447175198503666680874970496982273220244823343097169111136813588418696549323714996941979687803008850408979618598756579894836445212043698216415292987811742973332588607915912510967187510929248475023930572665446276200923068791518135803477701295593646298412366497023355174586195564772461857717369368404676577047874319780573853271810933883496338813069945569399346101090745616033312247949360455361849123333063704751724871276379140924398331810164737823379692265637682071706935846394531616949411701841938119405416449466111274712819705817783293841742231409930022911502362192186723337268385688273533371925103412930705632544426611429765388301822384091026198582888433587455960453004548370789052578473166283701953392231047527564998119228742789713715713228319641003422124210082180679525276689858180956119208391760721080919923461516952599099473782780648128058792731993893453415320185969711021407542282796298237068941764740642225757212455392526179373652434440560595336591539160312524480149313234572453879524389036839236450507881731359711238145323701508413491122324390927681724749607955799151363982881058285740538000653371655553014196332241918087621018204919492651483892"
+)
+
+var (
+ ln10 = newConstApproximation(strLn10)
+)
+
+type constApproximation struct {
+ exact Decimal
+ approximations []Decimal
+}
+
+func newConstApproximation(value string) constApproximation {
+ parts := strings.Split(value, ".")
+ coeff, fractional := parts[0], parts[1]
+
+ coeffLen := len(coeff)
+ maxPrecision := len(fractional)
+
+ var approximations []Decimal
+ for p := 1; p < maxPrecision; p *= 2 {
+ r := RequireFromString(value[:coeffLen+p])
+ approximations = append(approximations, r)
+ }
+
+ return constApproximation{
+ RequireFromString(value),
+ approximations,
+ }
+}
+
+// Returns the smallest approximation available that's at least as precise
+// as the passed precision (places after decimal point), i.e. Floor[ log2(precision) ] + 1
+func (c constApproximation) withPrecision(precision int32) Decimal {
+ i := 0
+
+ if precision >= 1 {
+ i++
+ }
+
+ for precision >= 16 {
+ precision /= 16
+ i += 4
+ }
+
+ for precision >= 2 {
+ precision /= 2
+ i++
+ }
+
+ if i >= len(c.approximations) {
+ return c.exact
+ }
+
+ return c.approximations[i]
+}
diff --git a/vendor/github.com/shopspring/decimal/decimal.go b/vendor/github.com/shopspring/decimal/decimal.go
index 801c1a0457a..a37a2301ef0 100644
--- a/vendor/github.com/shopspring/decimal/decimal.go
+++ b/vendor/github.com/shopspring/decimal/decimal.go
@@ -4,14 +4,14 @@
//
// The best way to create a new Decimal is to use decimal.NewFromString, ex:
//
-// n, err := decimal.NewFromString("-123.4567")
-// n.String() // output: "-123.4567"
+// n, err := decimal.NewFromString("-123.4567")
+// n.String() // output: "-123.4567"
//
// To use Decimal as part of a struct:
//
-// type Struct struct {
-// Number Decimal
-// }
+// type StructName struct {
+// Number Decimal
+// }
//
// Note: This can "only" represent numbers with a maximum of 2^31 digits after the decimal point.
package decimal
@@ -22,6 +22,7 @@ import (
"fmt"
"math"
"math/big"
+ "regexp"
"strconv"
"strings"
)
@@ -31,18 +32,31 @@ import (
//
// Example:
//
-// d1 := decimal.NewFromFloat(2).Div(decimal.NewFromFloat(3))
-// d1.String() // output: "0.6666666666666667"
-// d2 := decimal.NewFromFloat(2).Div(decimal.NewFromFloat(30000))
-// d2.String() // output: "0.0000666666666667"
-// d3 := decimal.NewFromFloat(20000).Div(decimal.NewFromFloat(3))
-// d3.String() // output: "6666.6666666666666667"
-// decimal.DivisionPrecision = 3
-// d4 := decimal.NewFromFloat(2).Div(decimal.NewFromFloat(3))
-// d4.String() // output: "0.667"
-//
+// d1 := decimal.NewFromFloat(2).Div(decimal.NewFromFloat(3))
+// d1.String() // output: "0.6666666666666667"
+// d2 := decimal.NewFromFloat(2).Div(decimal.NewFromFloat(30000))
+// d2.String() // output: "0.0000666666666667"
+// d3 := decimal.NewFromFloat(20000).Div(decimal.NewFromFloat(3))
+// d3.String() // output: "6666.6666666666666667"
+// decimal.DivisionPrecision = 3
+// d4 := decimal.NewFromFloat(2).Div(decimal.NewFromFloat(3))
+// d4.String() // output: "0.667"
var DivisionPrecision = 16
+// PowPrecisionNegativeExponent specifies the maximum precision of the result (digits after decimal point)
+// when calculating decimal power. Only used for cases where the exponent is a negative number.
+// This constant applies to Pow, PowInt32 and PowBigInt methods, PowWithPrecision method is not constrained by it.
+//
+// Example:
+//
+// d1, err := decimal.NewFromFloat(15.2).PowInt32(-2)
+// d1.String() // output: "0.0043282548476454"
+//
+// decimal.PowPrecisionNegativeExponent = 24
+// d2, err := decimal.NewFromFloat(15.2).PowInt32(-2)
+// d2.String() // output: "0.004328254847645429362881"
+var PowPrecisionNegativeExponent = 16
+
// MarshalJSONWithoutQuotes should be set to true if you want the decimal to
// be JSON marshaled as a number, instead of as a string.
// WARNING: this is dangerous for decimals with many digits, since many JSON
@@ -51,6 +65,10 @@ var DivisionPrecision = 16
// silently lose precision.
var MarshalJSONWithoutQuotes = false
+// ExpMaxIterations specifies the maximum number of iterations needed to calculate
+// precise natural exponent value using ExpHullAbrham method.
+var ExpMaxIterations = 1000
+
// Zero constant, to make computations faster.
// Zero should never be compared with == or != directly, please use decimal.Equal or decimal.Cmp instead.
var Zero = New(0, 1)
@@ -63,6 +81,8 @@ var fiveInt = big.NewInt(5)
var tenInt = big.NewInt(10)
var twentyInt = big.NewInt(20)
+var factorials = []Decimal{New(1, 0)}
+
// Decimal represents a fixed-point decimal. It is immutable.
// number = value * 10 ^ exp
type Decimal struct {
@@ -84,12 +104,12 @@ func New(value int64, exp int32) Decimal {
}
}
-// NewFromInt converts a int64 to Decimal.
+// NewFromInt converts an int64 to Decimal.
//
// Example:
//
-// NewFromInt(123).String() // output: "123"
-// NewFromInt(-10).String() // output: "-10"
+// NewFromInt(123).String() // output: "123"
+// NewFromInt(-10).String() // output: "-10"
func NewFromInt(value int64) Decimal {
return Decimal{
value: big.NewInt(value),
@@ -97,12 +117,12 @@ func NewFromInt(value int64) Decimal {
}
}
-// NewFromInt32 converts a int32 to Decimal.
+// NewFromInt32 converts an int32 to Decimal.
//
// Example:
//
-// NewFromInt(123).String() // output: "123"
-// NewFromInt(-10).String() // output: "-10"
+// NewFromInt(123).String() // output: "123"
+// NewFromInt(-10).String() // output: "-10"
func NewFromInt32(value int32) Decimal {
return Decimal{
value: big.NewInt(int64(value)),
@@ -110,23 +130,53 @@ func NewFromInt32(value int32) Decimal {
}
}
+// NewFromUint64 converts an uint64 to Decimal.
+//
+// Example:
+//
+// NewFromUint64(123).String() // output: "123"
+func NewFromUint64(value uint64) Decimal {
+ return Decimal{
+ value: new(big.Int).SetUint64(value),
+ exp: 0,
+ }
+}
+
// NewFromBigInt returns a new Decimal from a big.Int, value * 10 ^ exp
func NewFromBigInt(value *big.Int, exp int32) Decimal {
return Decimal{
- value: big.NewInt(0).Set(value),
+ value: new(big.Int).Set(value),
exp: exp,
}
}
+// NewFromBigRat returns a new Decimal from a big.Rat. The numerator and
+// denominator are divided and rounded to the given precision.
+//
+// Example:
+//
+// d1 := NewFromBigRat(big.NewRat(0, 1), 0) // output: "0"
+// d2 := NewFromBigRat(big.NewRat(4, 5), 1) // output: "0.8"
+// d3 := NewFromBigRat(big.NewRat(1000, 3), 3) // output: "333.333"
+// d4 := NewFromBigRat(big.NewRat(2, 7), 4) // output: "0.2857"
+func NewFromBigRat(value *big.Rat, precision int32) Decimal {
+ return Decimal{
+ value: new(big.Int).Set(value.Num()),
+ exp: 0,
+ }.DivRound(Decimal{
+ value: new(big.Int).Set(value.Denom()),
+ exp: 0,
+ }, precision)
+}
+
// NewFromString returns a new Decimal from a string representation.
// Trailing zeroes are not trimmed.
//
// Example:
//
-// d, err := NewFromString("-123.45")
-// d2, err := NewFromString(".0001")
-// d3, err := NewFromString("1.47000")
-//
+// d, err := NewFromString("-123.45")
+// d2, err := NewFromString(".0001")
+// d3, err := NewFromString("1.47000")
func NewFromString(value string) (Decimal, error) {
originalInput := value
var intString string
@@ -146,23 +196,45 @@ func NewFromString(value string) (Decimal, error) {
exp = expInt
}
- parts := strings.Split(value, ".")
- if len(parts) == 1 {
+ pIndex := -1
+ vLen := len(value)
+ for i := 0; i < vLen; i++ {
+ if value[i] == '.' {
+ if pIndex > -1 {
+ return Decimal{}, fmt.Errorf("can't convert %s to decimal: too many .s", value)
+ }
+ pIndex = i
+ }
+ }
+
+ if pIndex == -1 {
// There is no decimal point, we can just parse the original string as
// an int
intString = value
- } else if len(parts) == 2 {
- intString = parts[0] + parts[1]
- expInt := -len(parts[1])
- exp += int64(expInt)
} else {
- return Decimal{}, fmt.Errorf("can't convert %s to decimal: too many .s", value)
+ if pIndex+1 < vLen {
+ intString = value[:pIndex] + value[pIndex+1:]
+ } else {
+ intString = value[:pIndex]
+ }
+ expInt := -len(value[pIndex+1:])
+ exp += int64(expInt)
}
- dValue := new(big.Int)
- _, ok := dValue.SetString(intString, 10)
- if !ok {
- return Decimal{}, fmt.Errorf("can't convert %s to decimal", value)
+ var dValue *big.Int
+ // strconv.ParseInt is faster than new(big.Int).SetString so this is just a shortcut for strings we know won't overflow
+ if len(intString) <= 18 {
+ parsed64, err := strconv.ParseInt(intString, 10, 64)
+ if err != nil {
+ return Decimal{}, fmt.Errorf("can't convert %s to decimal", value)
+ }
+ dValue = big.NewInt(parsed64)
+ } else {
+ dValue = new(big.Int)
+ _, ok := dValue.SetString(intString, 10)
+ if !ok {
+ return Decimal{}, fmt.Errorf("can't convert %s to decimal", value)
+ }
}
if exp < math.MinInt32 || exp > math.MaxInt32 {
@@ -176,14 +248,36 @@ func NewFromString(value string) (Decimal, error) {
}, nil
}
-// RequireFromString returns a new Decimal from a string representation
-// or panics if NewFromString would have returned an error.
+// NewFromFormattedString returns a new Decimal from a formatted string representation.
+// The second argument - replRegexp, is a regular expression that is used to find characters that should be
+// removed from given decimal string representation. All matched characters will be replaced with an empty string.
//
// Example:
//
-// d := RequireFromString("-123.45")
-// d2 := RequireFromString(".0001")
+// r := regexp.MustCompile("[$,]")
+// d1, err := NewFromFormattedString("$5,125.99", r)
+//
+// r2 := regexp.MustCompile("[_]")
+// d2, err := NewFromFormattedString("1_000_000", r2)
+//
+// r3 := regexp.MustCompile("[USD\\s]")
+// d3, err := NewFromFormattedString("5000 USD", r3)
+func NewFromFormattedString(value string, replRegexp *regexp.Regexp) (Decimal, error) {
+ parsedValue := replRegexp.ReplaceAllString(value, "")
+ d, err := NewFromString(parsedValue)
+ if err != nil {
+ return Decimal{}, err
+ }
+ return d, nil
+}
+
+// RequireFromString returns a new Decimal from a string representation
+// or panics if NewFromString had returned an error.
+//
+// Example:
//
+// d := RequireFromString("-123.45")
+// d2 := RequireFromString(".0001")
func RequireFromString(value string) Decimal {
dec, err := NewFromString(value)
if err != nil {
@@ -279,8 +373,7 @@ func newFromFloat(val float64, bits uint64, flt *floatInfo) Decimal {
//
// Example:
//
-// NewFromFloatWithExponent(123.456, -2).String() // output: "123.46"
-//
+// NewFromFloatWithExponent(123.456, -2).String() // output: "123.46"
func NewFromFloatWithExponent(value float64, exp int32) Decimal {
if math.IsNaN(value) || math.IsInf(value, 0) {
panic(fmt.Sprintf("Cannot create a Decimal from %v", value))
@@ -361,6 +454,15 @@ func NewFromFloatWithExponent(value float64, exp int32) Decimal {
}
}
+// Copy returns a copy of decimal with the same value and exponent, but a different pointer to value.
+func (d Decimal) Copy() Decimal {
+ d.ensureInitialized()
+ return Decimal{
+ value: new(big.Int).Set(d.value),
+ exp: d.exp,
+ }
+}
+
// rescale returns a rescaled version of the decimal. Returned
// decimal may be less precise if the given exponent is bigger
// than the initial exponent of the Decimal.
@@ -368,7 +470,7 @@ func NewFromFloatWithExponent(value float64, exp int32) Decimal {
//
// Example:
//
-// d := New(12345, -4)
+// d := New(12345, -4)
// d2 := d.rescale(-1)
// d3 := d2.rescale(-4)
// println(d1)
@@ -380,7 +482,6 @@ func NewFromFloatWithExponent(value float64, exp int32) Decimal {
// 1.2345
// 1.2
// 1.2000
-//
func (d Decimal) rescale(exp int32) Decimal {
d.ensureInitialized()
@@ -410,6 +511,9 @@ func (d Decimal) rescale(exp int32) Decimal {
// Abs returns the absolute value of the decimal.
func (d Decimal) Abs() Decimal {
+ if !d.IsNegative() {
+ return d
+ }
d.ensureInitialized()
d2Value := new(big.Int).Abs(d.value)
return Decimal{
@@ -487,11 +591,13 @@ func (d Decimal) Div(d2 Decimal) Decimal {
return d.DivRound(d2, int32(DivisionPrecision))
}
-// QuoRem does divsion with remainder
+// QuoRem does division with remainder
// d.QuoRem(d2,precision) returns quotient q and remainder r such that
-// d = d2 * q + r, q an integer multiple of 10^(-precision)
-// 0 <= r < abs(d2) * 10 ^(-precision) if d>=0
-// 0 >= r > -abs(d2) * 10 ^(-precision) if d<0
+//
+// d = d2 * q + r, q an integer multiple of 10^(-precision)
+// 0 <= r < abs(d2) * 10 ^(-precision) if d>=0
+// 0 >= r > -abs(d2) * 10 ^(-precision) if d<0
+//
// Note that precision<0 is allowed as input.
func (d Decimal) QuoRem(d2 Decimal, precision int32) (Decimal, Decimal) {
d.ensureInitialized()
@@ -500,7 +606,7 @@ func (d Decimal) QuoRem(d2 Decimal, precision int32) (Decimal, Decimal) {
panic("decimal division by 0")
}
scale := -precision
- e := int64(d.exp - d2.exp - scale)
+ e := int64(d.exp) - int64(d2.exp) - int64(scale)
if e > math.MaxInt32 || e < math.MinInt32 {
panic("overflow in decimal QuoRem")
}
@@ -534,8 +640,10 @@ func (d Decimal) QuoRem(d2 Decimal, precision int32) (Decimal, Decimal) {
// DivRound divides and rounds to a given precision
// i.e. to an integer multiple of 10^(-precision)
-// for a positive quotient digit 5 is rounded up, away from 0
-// if the quotient is negative then digit 5 is rounded down, away from 0
+//
+// for a positive quotient digit 5 is rounded up, away from 0
+// if the quotient is negative then digit 5 is rounded down, away from 0
+//
// Note that precision<0 is allowed as input.
func (d Decimal) DivRound(d2 Decimal, precision int32) Decimal {
// QuoRem already checks initialization
@@ -563,32 +671,632 @@ func (d Decimal) DivRound(d2 Decimal, precision int32) Decimal {
// Mod returns d % d2.
func (d Decimal) Mod(d2 Decimal) Decimal {
- quo := d.Div(d2).Truncate(0)
- return d.Sub(d2.Mul(quo))
+ _, r := d.QuoRem(d2, 0)
+ return r
}
-// Pow returns d to the power d2
+// Pow returns d to the power of d2.
+// When exponent is negative the returned decimal will have maximum precision of PowPrecisionNegativeExponent places after decimal point.
+//
+// Pow returns 0 (zero-value of Decimal) instead of error for power operation edge cases, to handle those edge cases use PowWithPrecision
+// Edge cases not handled by Pow:
+// - 0 ** 0 => undefined value
+// - 0 ** y, where y < 0 => infinity
+// - x ** y, where x < 0 and y is non-integer decimal => imaginary value
+//
+// Example:
+//
+// d1 := decimal.NewFromFloat(4.0)
+// d2 := decimal.NewFromFloat(4.0)
+// res1 := d1.Pow(d2)
+// res1.String() // output: "256"
+//
+// d3 := decimal.NewFromFloat(5.0)
+// d4 := decimal.NewFromFloat(5.73)
+// res2 := d3.Pow(d4)
+// res2.String() // output: "10118.08037125"
func (d Decimal) Pow(d2 Decimal) Decimal {
- var temp Decimal
- if d2.IntPart() == 0 {
- return NewFromFloat(1)
+ baseSign := d.Sign()
+ expSign := d2.Sign()
+
+ if baseSign == 0 {
+ if expSign == 0 {
+ return Decimal{}
+ }
+ if expSign == 1 {
+ return Decimal{zeroInt, 0}
+ }
+ if expSign == -1 {
+ return Decimal{}
+ }
}
- temp = d.Pow(d2.Div(NewFromFloat(2)))
- if d2.IntPart()%2 == 0 {
- return temp.Mul(temp)
+
+ if expSign == 0 {
+ return Decimal{oneInt, 0}
+ }
+
+ // TODO: optimize extraction of fractional part
+ one := Decimal{oneInt, 0}
+ expIntPart, expFracPart := d2.QuoRem(one, 0)
+
+ if baseSign == -1 && !expFracPart.IsZero() {
+ return Decimal{}
+ }
+
+ intPartPow, _ := d.PowBigInt(expIntPart.value)
+
+ // if exponent is an integer we don't need to calculate d1**frac(d2)
+ if expFracPart.value.Sign() == 0 {
+ return intPartPow
+ }
+
+ // TODO: optimize NumDigits for more performant precision adjustment
+ digitsBase := d.NumDigits()
+ digitsExponent := d2.NumDigits()
+
+ precision := digitsBase
+
+ if digitsExponent > precision {
+ precision += digitsExponent
+ }
+
+ precision += 6
+
+ // Calculate x ** frac(y), where
+ // x ** frac(y) = exp(ln(x ** frac(y)) = exp(ln(x) * frac(y))
+ fracPartPow, err := d.Abs().Ln(-d.exp + int32(precision))
+ if err != nil {
+ return Decimal{}
}
- if d2.IntPart() > 0 {
- return temp.Mul(temp).Mul(d)
+
+ fracPartPow = fracPartPow.Mul(expFracPart)
+
+ fracPartPow, err = fracPartPow.ExpTaylor(-d.exp + int32(precision))
+ if err != nil {
+ return Decimal{}
}
- return temp.Mul(temp).Div(d)
+
+ // Join integer and fractional part,
+ // base ** (expBase + expFrac) = base ** expBase * base ** expFrac
+ res := intPartPow.Mul(fracPartPow)
+
+ return res
}
-// Cmp compares the numbers represented by d and d2 and returns:
+// PowWithPrecision returns d to the power of d2.
+// Precision parameter specifies minimum precision of the result (digits after decimal point).
+// Returned decimal is not rounded to 'precision' places after decimal point.
+//
+// PowWithPrecision returns error when:
+// - 0 ** 0 => undefined value
+// - 0 ** y, where y < 0 => infinity
+// - x ** y, where x < 0 and y is non-integer decimal => imaginary value
+//
+// Example:
+//
+// d1 := decimal.NewFromFloat(4.0)
+// d2 := decimal.NewFromFloat(4.0)
+// res1, err := d1.PowWithPrecision(d2, 2)
+// res1.String() // output: "256"
+//
+// d3 := decimal.NewFromFloat(5.0)
+// d4 := decimal.NewFromFloat(5.73)
+// res2, err := d3.PowWithPrecision(d4, 5)
+// res2.String() // output: "10118.080371595015625"
+//
+// d5 := decimal.NewFromFloat(-3.0)
+// d6 := decimal.NewFromFloat(-6.0)
+// res3, err := d5.PowWithPrecision(d6, 10)
+// res3.String() // output: "0.0013717421"
+func (d Decimal) PowWithPrecision(d2 Decimal, precision int32) (Decimal, error) {
+ baseSign := d.Sign()
+ expSign := d2.Sign()
+
+ if baseSign == 0 {
+ if expSign == 0 {
+ return Decimal{}, fmt.Errorf("cannot represent undefined value of 0**0")
+ }
+ if expSign == 1 {
+ return Decimal{zeroInt, 0}, nil
+ }
+ if expSign == -1 {
+ return Decimal{}, fmt.Errorf("cannot represent infinity value of 0 ** y, where y < 0")
+ }
+ }
+
+ if expSign == 0 {
+ return Decimal{oneInt, 0}, nil
+ }
+
+ // TODO: optimize extraction of fractional part
+ one := Decimal{oneInt, 0}
+ expIntPart, expFracPart := d2.QuoRem(one, 0)
+
+ if baseSign == -1 && !expFracPart.IsZero() {
+ return Decimal{}, fmt.Errorf("cannot represent imaginary value of x ** y, where x < 0 and y is non-integer decimal")
+ }
+
+ intPartPow, _ := d.powBigIntWithPrecision(expIntPart.value, precision)
+
+ // if exponent is an integer we don't need to calculate d1**frac(d2)
+ if expFracPart.value.Sign() == 0 {
+ return intPartPow, nil
+ }
+
+ // TODO: optimize NumDigits for more performant precision adjustment
+ digitsBase := d.NumDigits()
+ digitsExponent := d2.NumDigits()
+
+ if int32(digitsBase) > precision {
+ precision = int32(digitsBase)
+ }
+ if int32(digitsExponent) > precision {
+ precision += int32(digitsExponent)
+ }
+ // increase precision by 10 to compensate for errors in further calculations
+ precision += 10
+
+ // Calculate x ** frac(y), where
+ // x ** frac(y) = exp(ln(x ** frac(y)) = exp(ln(x) * frac(y))
+ fracPartPow, err := d.Abs().Ln(precision)
+ if err != nil {
+ return Decimal{}, err
+ }
+
+ fracPartPow = fracPartPow.Mul(expFracPart)
+
+ fracPartPow, err = fracPartPow.ExpTaylor(precision)
+ if err != nil {
+ return Decimal{}, err
+ }
+
+ // Join integer and fractional part,
+ // base ** (expBase + expFrac) = base ** expBase * base ** expFrac
+ res := intPartPow.Mul(fracPartPow)
+
+ return res, nil
+}
+
+// PowInt32 returns d to the power of exp, where exp is int32.
+// Only returns error when d and exp is 0, thus result is undefined.
+//
+// When exponent is negative the returned decimal will have maximum precision of PowPrecisionNegativeExponent places after decimal point.
+//
+// Example:
+//
+// d1, err := decimal.NewFromFloat(4.0).PowInt32(4)
+// d1.String() // output: "256"
+//
+// d2, err := decimal.NewFromFloat(3.13).PowInt32(5)
+// d2.String() // output: "300.4150512793"
+func (d Decimal) PowInt32(exp int32) (Decimal, error) {
+ if d.IsZero() && exp == 0 {
+ return Decimal{}, fmt.Errorf("cannot represent undefined value of 0**0")
+ }
+
+ isExpNeg := exp < 0
+ exp = abs(exp)
+
+ n, result := d, New(1, 0)
+
+ for exp > 0 {
+ if exp%2 == 1 {
+ result = result.Mul(n)
+ }
+ exp /= 2
+
+ if exp > 0 {
+ n = n.Mul(n)
+ }
+ }
+
+ if isExpNeg {
+ return New(1, 0).DivRound(result, int32(PowPrecisionNegativeExponent)), nil
+ }
+
+ return result, nil
+}
+
+// PowBigInt returns d to the power of exp, where exp is big.Int.
+// Only returns error when d and exp is 0, thus result is undefined.
+//
+// When exponent is negative the returned decimal will have maximum precision of PowPrecisionNegativeExponent places after decimal point.
+//
+// Example:
+//
+// d1, err := decimal.NewFromFloat(3.0).PowBigInt(big.NewInt(3))
+// d1.String() // output: "27"
+//
+// d2, err := decimal.NewFromFloat(629.25).PowBigInt(big.NewInt(5))
+// d2.String() // output: "98654323103449.5673828125"
+func (d Decimal) PowBigInt(exp *big.Int) (Decimal, error) {
+ return d.powBigIntWithPrecision(exp, int32(PowPrecisionNegativeExponent))
+}
+
+func (d Decimal) powBigIntWithPrecision(exp *big.Int, precision int32) (Decimal, error) {
+ if d.IsZero() && exp.Sign() == 0 {
+ return Decimal{}, fmt.Errorf("cannot represent undefined value of 0**0")
+ }
+
+ tmpExp := new(big.Int).Set(exp)
+ isExpNeg := exp.Sign() < 0
+
+ if isExpNeg {
+ tmpExp.Abs(tmpExp)
+ }
+
+ n, result := d, New(1, 0)
+
+ for tmpExp.Sign() > 0 {
+ if tmpExp.Bit(0) == 1 {
+ result = result.Mul(n)
+ }
+ tmpExp.Rsh(tmpExp, 1)
+
+ if tmpExp.Sign() > 0 {
+ n = n.Mul(n)
+ }
+ }
+
+ if isExpNeg {
+ return New(1, 0).DivRound(result, precision), nil
+ }
+
+ return result, nil
+}
+
+// ExpHullAbrham calculates the natural exponent of decimal (e to the power of d) using Hull-Abraham algorithm.
+// OverallPrecision argument specifies the overall precision of the result (integer part + decimal part).
+//
+// ExpHullAbrham is faster than ExpTaylor for small precision values, but it is much slower for large precision values.
+//
+// Example:
+//
+// NewFromFloat(26.1).ExpHullAbrham(2).String() // output: "220000000000"
+// NewFromFloat(26.1).ExpHullAbrham(20).String() // output: "216314672147.05767284"
+func (d Decimal) ExpHullAbrham(overallPrecision uint32) (Decimal, error) {
+ // Algorithm based on Variable precision exponential function.
+ // ACM Transactions on Mathematical Software by T. E. Hull & A. Abrham.
+ if d.IsZero() {
+ return Decimal{oneInt, 0}, nil
+ }
+
+ currentPrecision := overallPrecision
+
+ // Algorithm does not work if currentPrecision * 23 < |x|.
+ // Precision is automatically increased in such cases, so the value can be calculated precisely.
+ // If newly calculated precision is higher than ExpMaxIterations the currentPrecision will not be changed.
+ f := d.Abs().InexactFloat64()
+ if ncp := f / 23; ncp > float64(currentPrecision) && ncp < float64(ExpMaxIterations) {
+ currentPrecision = uint32(math.Ceil(ncp))
+ }
+
+ // fail if abs(d) beyond an over/underflow threshold
+ overflowThreshold := New(23*int64(currentPrecision), 0)
+ if d.Abs().Cmp(overflowThreshold) > 0 {
+ return Decimal{}, fmt.Errorf("over/underflow threshold, exp(x) cannot be calculated precisely")
+ }
+
+ // Return 1 if abs(d) small enough; this also avoids later over/underflow
+ overflowThreshold2 := New(9, -int32(currentPrecision)-1)
+ if d.Abs().Cmp(overflowThreshold2) <= 0 {
+ return Decimal{oneInt, d.exp}, nil
+ }
+
+ // t is the smallest integer >= 0 such that the corresponding abs(d/k) < 1
+ t := d.exp + int32(d.NumDigits()) // Add d.NumDigits because the paper assumes that d.value [0.1, 1)
+
+ if t < 0 {
+ t = 0
+ }
+
+ k := New(1, t) // reduction factor
+ r := Decimal{new(big.Int).Set(d.value), d.exp - t} // reduced argument
+ p := int32(currentPrecision) + t + 2 // precision for calculating the sum
+
+ // Determine n, the number of therms for calculating sum
+ // use first Newton step (1.435p - 1.182) / log10(p/abs(r))
+ // for solving appropriate equation, along with directed
+ // roundings and simple rational bound for log10(p/abs(r))
+ rf := r.Abs().InexactFloat64()
+ pf := float64(p)
+ nf := math.Ceil((1.453*pf - 1.182) / math.Log10(pf/rf))
+ if nf > float64(ExpMaxIterations) || math.IsNaN(nf) {
+ return Decimal{}, fmt.Errorf("exact value cannot be calculated in <=ExpMaxIterations iterations")
+ }
+ n := int64(nf)
+
+ tmp := New(0, 0)
+ sum := New(1, 0)
+ one := New(1, 0)
+ for i := n - 1; i > 0; i-- {
+ tmp.value.SetInt64(i)
+ sum = sum.Mul(r.DivRound(tmp, p))
+ sum = sum.Add(one)
+ }
+
+ ki := k.IntPart()
+ res := New(1, 0)
+ for i := ki; i > 0; i-- {
+ res = res.Mul(sum)
+ }
+
+ resNumDigits := int32(res.NumDigits())
+
+ var roundDigits int32
+ if resNumDigits > abs(res.exp) {
+ roundDigits = int32(currentPrecision) - resNumDigits - res.exp
+ } else {
+ roundDigits = int32(currentPrecision)
+ }
+
+ res = res.Round(roundDigits)
+
+ return res, nil
+}
+
+// ExpTaylor calculates the natural exponent of decimal (e to the power of d) using Taylor series expansion.
+// Precision argument specifies how precise the result must be (number of digits after decimal point).
+// Negative precision is allowed.
+//
+// ExpTaylor is much faster for large precision values than ExpHullAbrham.
+//
+// Example:
//
-// -1 if d < d2
-// 0 if d == d2
-// +1 if d > d2
+// d, err := NewFromFloat(26.1).ExpTaylor(2).String()
+// d.String() // output: "216314672147.06"
+//
+// NewFromFloat(26.1).ExpTaylor(20).String()
+// d.String() // output: "216314672147.05767284062928674083"
+//
+// NewFromFloat(26.1).ExpTaylor(-10).String()
+// d.String() // output: "220000000000"
+func (d Decimal) ExpTaylor(precision int32) (Decimal, error) {
+ // Note(mwoss): Implementation can be optimized by exclusively using big.Int API only
+ if d.IsZero() {
+ return Decimal{oneInt, 0}.Round(precision), nil
+ }
+
+ var epsilon Decimal
+ var divPrecision int32
+ if precision < 0 {
+ epsilon = New(1, -1)
+ divPrecision = 8
+ } else {
+ epsilon = New(1, -precision-1)
+ divPrecision = precision + 1
+ }
+
+ decAbs := d.Abs()
+ pow := d.Abs()
+ factorial := New(1, 0)
+
+ result := New(1, 0)
+
+ for i := int64(1); ; {
+ step := pow.DivRound(factorial, divPrecision)
+ result = result.Add(step)
+
+ // Stop Taylor series when current step is smaller than epsilon
+ if step.Cmp(epsilon) < 0 {
+ break
+ }
+
+ pow = pow.Mul(decAbs)
+
+ i++
+
+ // Calculate next factorial number or retrieve cached value
+ if len(factorials) >= int(i) && !factorials[i-1].IsZero() {
+ factorial = factorials[i-1]
+ } else {
+ // To avoid any race conditions, firstly the zero value is appended to a slice to create
+ // a spot for newly calculated factorial. After that, the zero value is replaced by calculated
+ // factorial using the index notation.
+ factorial = factorials[i-2].Mul(New(i, 0))
+ factorials = append(factorials, Zero)
+ factorials[i-1] = factorial
+ }
+ }
+
+ if d.Sign() < 0 {
+ result = New(1, 0).DivRound(result, precision+1)
+ }
+
+ result = result.Round(precision)
+ return result, nil
+}
+
+// Ln calculates natural logarithm of d.
+// Precision argument specifies how precise the result must be (number of digits after decimal point).
+// Negative precision is allowed.
+//
+// Example:
+//
+// d1, err := NewFromFloat(13.3).Ln(2)
+// d1.String() // output: "2.59"
+//
+// d2, err := NewFromFloat(579.161).Ln(10)
+// d2.String() // output: "6.3615805046"
+func (d Decimal) Ln(precision int32) (Decimal, error) {
+ // Algorithm based on The Use of Iteration Methods for Approximating the Natural Logarithm,
+ // James F. Epperson, The American Mathematical Monthly, Vol. 96, No. 9, November 1989, pp. 831-835.
+ if d.IsNegative() {
+ return Decimal{}, fmt.Errorf("cannot calculate natural logarithm for negative decimals")
+ }
+
+ if d.IsZero() {
+ return Decimal{}, fmt.Errorf("cannot represent natural logarithm of 0, result: -infinity")
+ }
+
+ calcPrecision := precision + 2
+ z := d.Copy()
+
+ var comp1, comp3, comp2, comp4, reduceAdjust Decimal
+ comp1 = z.Sub(Decimal{oneInt, 0})
+ comp3 = Decimal{oneInt, -1}
+
+ // for decimal in range [0.9, 1.1] where ln(d) is close to 0
+ usePowerSeries := false
+
+ if comp1.Abs().Cmp(comp3) <= 0 {
+ usePowerSeries = true
+ } else {
+ // reduce input decimal to range [0.1, 1)
+ expDelta := int32(z.NumDigits()) + z.exp
+ z.exp -= expDelta
+
+ // Input decimal was reduced by factor of 10^expDelta, thus we will need to add
+ // ln(10^expDelta) = expDelta * ln(10)
+ // to the result to compensate that
+ ln10 := ln10.withPrecision(calcPrecision)
+ reduceAdjust = NewFromInt32(expDelta)
+ reduceAdjust = reduceAdjust.Mul(ln10)
+
+ comp1 = z.Sub(Decimal{oneInt, 0})
+
+ if comp1.Abs().Cmp(comp3) <= 0 {
+ usePowerSeries = true
+ } else {
+ // initial estimate using floats
+ zFloat := z.InexactFloat64()
+ comp1 = NewFromFloat(math.Log(zFloat))
+ }
+ }
+
+ epsilon := Decimal{oneInt, -calcPrecision}
+
+ if usePowerSeries {
+ // Power Series - https://en.wikipedia.org/wiki/Logarithm#Power_series
+ // Calculating n-th term of formula: ln(z+1) = 2 sum [ 1 / (2n+1) * (z / (z+2))^(2n+1) ]
+ // until the difference between current and next term is smaller than epsilon.
+ // Coverage quite fast for decimals close to 1.0
+
+ // z + 2
+ comp2 = comp1.Add(Decimal{twoInt, 0})
+ // z / (z + 2)
+ comp3 = comp1.DivRound(comp2, calcPrecision)
+ // 2 * (z / (z + 2))
+ comp1 = comp3.Add(comp3)
+ comp2 = comp1.Copy()
+
+ for n := 1; ; n++ {
+ // 2 * (z / (z+2))^(2n+1)
+ comp2 = comp2.Mul(comp3).Mul(comp3)
+
+ // 1 / (2n+1) * 2 * (z / (z+2))^(2n+1)
+ comp4 = NewFromInt(int64(2*n + 1))
+ comp4 = comp2.DivRound(comp4, calcPrecision)
+
+ // comp1 = 2 sum [ 1 / (2n+1) * (z / (z+2))^(2n+1) ]
+ comp1 = comp1.Add(comp4)
+
+ if comp4.Abs().Cmp(epsilon) <= 0 {
+ break
+ }
+ }
+ } else {
+ // Halley's Iteration.
+ // Calculating n-th term of formula: a_(n+1) = a_n - 2 * (exp(a_n) - z) / (exp(a_n) + z),
+ // until the difference between current and next term is smaller than epsilon
+ var prevStep Decimal
+ maxIters := calcPrecision*2 + 10
+
+ for i := int32(0); i < maxIters; i++ {
+ // exp(a_n)
+ comp3, _ = comp1.ExpTaylor(calcPrecision)
+ // exp(a_n) - z
+ comp2 = comp3.Sub(z)
+ // 2 * (exp(a_n) - z)
+ comp2 = comp2.Add(comp2)
+ // exp(a_n) + z
+ comp4 = comp3.Add(z)
+ // 2 * (exp(a_n) - z) / (exp(a_n) + z)
+ comp3 = comp2.DivRound(comp4, calcPrecision)
+ // comp1 = a_(n+1) = a_n - 2 * (exp(a_n) - z) / (exp(a_n) + z)
+ comp1 = comp1.Sub(comp3)
+
+ if prevStep.Add(comp3).IsZero() {
+ // If iteration steps oscillate we should return early and prevent an infinity loop
+ // NOTE(mwoss): This should be quite a rare case, returning error is not necessary
+ break
+ }
+
+ if comp3.Abs().Cmp(epsilon) <= 0 {
+ break
+ }
+
+ prevStep = comp3
+ }
+ }
+
+ comp1 = comp1.Add(reduceAdjust)
+
+ return comp1.Round(precision), nil
+}
+
+// NumDigits returns the number of digits of the decimal coefficient (d.Value)
+func (d Decimal) NumDigits() int {
+ if d.value == nil {
+ return 1
+ }
+
+ if d.value.IsInt64() {
+ i64 := d.value.Int64()
+ // restrict fast path to integers with exact conversion to float64
+ if i64 <= (1<<53) && i64 >= -(1<<53) {
+ if i64 == 0 {
+ return 1
+ }
+ return int(math.Log10(math.Abs(float64(i64)))) + 1
+ }
+ }
+
+ estimatedNumDigits := int(float64(d.value.BitLen()) / math.Log2(10))
+
+ // estimatedNumDigits (lg10) may be off by 1, need to verify
+ digitsBigInt := big.NewInt(int64(estimatedNumDigits))
+ errorCorrectionUnit := digitsBigInt.Exp(tenInt, digitsBigInt, nil)
+
+ if d.value.CmpAbs(errorCorrectionUnit) >= 0 {
+ return estimatedNumDigits + 1
+ }
+
+ return estimatedNumDigits
+}
+
+// IsInteger returns true when decimal can be represented as an integer value, otherwise, it returns false.
+func (d Decimal) IsInteger() bool {
+ // The most typical case, all decimal with exponent higher or equal 0 can be represented as integer
+ if d.exp >= 0 {
+ return true
+ }
+ // When the exponent is negative we have to check every number after the decimal place
+ // If all of them are zeroes, we are sure that given decimal can be represented as an integer
+ var r big.Int
+ q := new(big.Int).Set(d.value)
+ for z := abs(d.exp); z > 0; z-- {
+ q.QuoRem(q, tenInt, &r)
+ if r.Cmp(zeroInt) != 0 {
+ return false
+ }
+ }
+ return true
+}
+
+// Abs calculates absolute value of any int32. Used for calculating absolute value of decimal's exponent.
+func abs(n int32) int32 {
+ if n < 0 {
+ return -n
+ }
+ return n
+}
+
+// Cmp compares the numbers represented by d and d2 and returns:
//
+// -1 if d < d2
+// 0 if d == d2
+// +1 if d > d2
func (d Decimal) Cmp(d2 Decimal) int {
d.ensureInitialized()
d2.ensureInitialized()
@@ -602,12 +1310,21 @@ func (d Decimal) Cmp(d2 Decimal) int {
return rd.value.Cmp(rd2.value)
}
+// Compare compares the numbers represented by d and d2 and returns:
+//
+// -1 if d < d2
+// 0 if d == d2
+// +1 if d > d2
+func (d Decimal) Compare(d2 Decimal) int {
+ return d.Cmp(d2)
+}
+
// Equal returns whether the numbers represented by d and d2 are equal.
func (d Decimal) Equal(d2 Decimal) bool {
return d.Cmp(d2) == 0
}
-// Equals is deprecated, please use Equal method instead
+// Deprecated: Equals is deprecated, please use Equal method instead.
func (d Decimal) Equals(d2 Decimal) bool {
return d.Equal(d2)
}
@@ -639,7 +1356,6 @@ func (d Decimal) LessThanOrEqual(d2 Decimal) bool {
// -1 if d < 0
// 0 if d == 0
// +1 if d > 0
-//
func (d Decimal) Sign() int {
if d.value == nil {
return 0
@@ -679,12 +1395,18 @@ func (d Decimal) Exponent() int32 {
return d.exp
}
-// Coefficient returns the coefficient of the decimal. It is scaled by 10^Exponent()
+// Coefficient returns the coefficient of the decimal. It is scaled by 10^Exponent()
func (d Decimal) Coefficient() *big.Int {
d.ensureInitialized()
- // we copy the coefficient so that mutating the result does not mutate the
- // Decimal.
- return big.NewInt(0).Set(d.value)
+ // we copy the coefficient so that mutating the result does not mutate the Decimal.
+ return new(big.Int).Set(d.value)
+}
+
+// CoefficientInt64 returns the coefficient of the decimal as int64. It is scaled by 10^Exponent()
+// If coefficient cannot be represented in an int64, the result will be undefined.
+func (d Decimal) CoefficientInt64() int64 {
+ d.ensureInitialized()
+ return d.value.Int64()
}
// IntPart returns the integer component of the decimal.
@@ -696,9 +1418,7 @@ func (d Decimal) IntPart() int64 {
// BigInt returns integer component of the decimal as a BigInt.
func (d Decimal) BigInt() *big.Int {
scaledD := d.rescale(0)
- i := &big.Int{}
- i.SetString(scaledD.String(), 10)
- return i
+ return scaledD.value
}
// BigFloat returns decimal as BigFloat.
@@ -730,18 +1450,24 @@ func (d Decimal) Float64() (f float64, exact bool) {
return d.Rat().Float64()
}
+// InexactFloat64 returns the nearest float64 value for d.
+// It doesn't indicate if the returned value represents d exactly.
+func (d Decimal) InexactFloat64() float64 {
+ f, _ := d.Float64()
+ return f
+}
+
// String returns the string representation of the decimal
// with the fixed point.
//
// Example:
//
-// d := New(-12345, -3)
-// println(d.String())
+// d := New(-12345, -3)
+// println(d.String())
//
// Output:
//
-// -12.345
-//
+// -12.345
func (d Decimal) String() string {
return d.string(true)
}
@@ -751,14 +1477,13 @@ func (d Decimal) String() string {
//
// Example:
//
-// NewFromFloat(0).StringFixed(2) // output: "0.00"
-// NewFromFloat(0).StringFixed(0) // output: "0"
-// NewFromFloat(5.45).StringFixed(0) // output: "5"
-// NewFromFloat(5.45).StringFixed(1) // output: "5.5"
-// NewFromFloat(5.45).StringFixed(2) // output: "5.45"
-// NewFromFloat(5.45).StringFixed(3) // output: "5.450"
-// NewFromFloat(545).StringFixed(-1) // output: "550"
-//
+// NewFromFloat(0).StringFixed(2) // output: "0.00"
+// NewFromFloat(0).StringFixed(0) // output: "0"
+// NewFromFloat(5.45).StringFixed(0) // output: "5"
+// NewFromFloat(5.45).StringFixed(1) // output: "5.5"
+// NewFromFloat(5.45).StringFixed(2) // output: "5.45"
+// NewFromFloat(5.45).StringFixed(3) // output: "5.450"
+// NewFromFloat(545).StringFixed(-1) // output: "550"
func (d Decimal) StringFixed(places int32) string {
rounded := d.Round(places)
return rounded.string(false)
@@ -769,14 +1494,13 @@ func (d Decimal) StringFixed(places int32) string {
//
// Example:
//
-// NewFromFloat(0).StringFixedBank(2) // output: "0.00"
-// NewFromFloat(0).StringFixedBank(0) // output: "0"
-// NewFromFloat(5.45).StringFixedBank(0) // output: "5"
-// NewFromFloat(5.45).StringFixedBank(1) // output: "5.4"
-// NewFromFloat(5.45).StringFixedBank(2) // output: "5.45"
-// NewFromFloat(5.45).StringFixedBank(3) // output: "5.450"
-// NewFromFloat(545).StringFixedBank(-1) // output: "540"
-//
+// NewFromFloat(0).StringFixedBank(2) // output: "0.00"
+// NewFromFloat(0).StringFixedBank(0) // output: "0"
+// NewFromFloat(5.45).StringFixedBank(0) // output: "5"
+// NewFromFloat(5.45).StringFixedBank(1) // output: "5.4"
+// NewFromFloat(5.45).StringFixedBank(2) // output: "5.45"
+// NewFromFloat(5.45).StringFixedBank(3) // output: "5.450"
+// NewFromFloat(545).StringFixedBank(-1) // output: "540"
func (d Decimal) StringFixedBank(places int32) string {
rounded := d.RoundBank(places)
return rounded.string(false)
@@ -794,10 +1518,12 @@ func (d Decimal) StringFixedCash(interval uint8) string {
//
// Example:
//
-// NewFromFloat(5.45).Round(1).String() // output: "5.5"
-// NewFromFloat(545).Round(-1).String() // output: "550"
-//
+// NewFromFloat(5.45).Round(1).String() // output: "5.5"
+// NewFromFloat(545).Round(-1).String() // output: "550"
func (d Decimal) Round(places int32) Decimal {
+ if d.exp == -places {
+ return d
+ }
// truncate to places + 1
ret := d.rescale(-places - 1)
@@ -818,6 +1544,103 @@ func (d Decimal) Round(places int32) Decimal {
return ret
}
+// RoundCeil rounds the decimal towards +infinity.
+//
+// Example:
+//
+// NewFromFloat(545).RoundCeil(-2).String() // output: "600"
+// NewFromFloat(500).RoundCeil(-2).String() // output: "500"
+// NewFromFloat(1.1001).RoundCeil(2).String() // output: "1.11"
+// NewFromFloat(-1.454).RoundCeil(1).String() // output: "-1.4"
+func (d Decimal) RoundCeil(places int32) Decimal {
+ if d.exp >= -places {
+ return d
+ }
+
+ rescaled := d.rescale(-places)
+ if d.Equal(rescaled) {
+ return d
+ }
+
+ if d.value.Sign() > 0 {
+ rescaled.value.Add(rescaled.value, oneInt)
+ }
+
+ return rescaled
+}
+
+// RoundFloor rounds the decimal towards -infinity.
+//
+// Example:
+//
+// NewFromFloat(545).RoundFloor(-2).String() // output: "500"
+// NewFromFloat(-500).RoundFloor(-2).String() // output: "-500"
+// NewFromFloat(1.1001).RoundFloor(2).String() // output: "1.1"
+// NewFromFloat(-1.454).RoundFloor(1).String() // output: "-1.5"
+func (d Decimal) RoundFloor(places int32) Decimal {
+ if d.exp >= -places {
+ return d
+ }
+
+ rescaled := d.rescale(-places)
+ if d.Equal(rescaled) {
+ return d
+ }
+
+ if d.value.Sign() < 0 {
+ rescaled.value.Sub(rescaled.value, oneInt)
+ }
+
+ return rescaled
+}
+
+// RoundUp rounds the decimal away from zero.
+//
+// Example:
+//
+// NewFromFloat(545).RoundUp(-2).String() // output: "600"
+// NewFromFloat(500).RoundUp(-2).String() // output: "500"
+// NewFromFloat(1.1001).RoundUp(2).String() // output: "1.11"
+// NewFromFloat(-1.454).RoundUp(1).String() // output: "-1.5"
+func (d Decimal) RoundUp(places int32) Decimal {
+ if d.exp >= -places {
+ return d
+ }
+
+ rescaled := d.rescale(-places)
+ if d.Equal(rescaled) {
+ return d
+ }
+
+ if d.value.Sign() > 0 {
+ rescaled.value.Add(rescaled.value, oneInt)
+ } else if d.value.Sign() < 0 {
+ rescaled.value.Sub(rescaled.value, oneInt)
+ }
+
+ return rescaled
+}
+
+// RoundDown rounds the decimal towards zero.
+//
+// Example:
+//
+// NewFromFloat(545).RoundDown(-2).String() // output: "500"
+// NewFromFloat(-500).RoundDown(-2).String() // output: "-500"
+// NewFromFloat(1.1001).RoundDown(2).String() // output: "1.1"
+// NewFromFloat(-1.454).RoundDown(1).String() // output: "-1.4"
+func (d Decimal) RoundDown(places int32) Decimal {
+ if d.exp >= -places {
+ return d
+ }
+
+ rescaled := d.rescale(-places)
+ if d.Equal(rescaled) {
+ return d
+ }
+ return rescaled
+}
+
// RoundBank rounds the decimal to places decimal places.
// If the final digit to round is equidistant from the nearest two integers the
// rounded value is taken as the even number
@@ -826,13 +1649,12 @@ func (d Decimal) Round(places int32) Decimal {
//
// Examples:
//
-// NewFromFloat(5.45).Round(1).String() // output: "5.4"
-// NewFromFloat(545).Round(-1).String() // output: "540"
-// NewFromFloat(5.46).Round(1).String() // output: "5.5"
-// NewFromFloat(546).Round(-1).String() // output: "550"
-// NewFromFloat(5.55).Round(1).String() // output: "5.6"
-// NewFromFloat(555).Round(-1).String() // output: "560"
-//
+// NewFromFloat(5.45).RoundBank(1).String() // output: "5.4"
+// NewFromFloat(545).RoundBank(-1).String() // output: "540"
+// NewFromFloat(5.46).RoundBank(1).String() // output: "5.5"
+// NewFromFloat(546).RoundBank(-1).String() // output: "550"
+// NewFromFloat(5.55).RoundBank(1).String() // output: "5.6"
+// NewFromFloat(555).RoundBank(-1).String() // output: "560"
func (d Decimal) RoundBank(places int32) Decimal {
round := d.Round(places)
@@ -854,11 +1676,13 @@ func (d Decimal) RoundBank(places int32) Decimal {
// interval. The amount payable for a cash transaction is rounded to the nearest
// multiple of the minimum currency unit available. The following intervals are
// available: 5, 10, 25, 50 and 100; any other number throws a panic.
-// 5: 5 cent rounding 3.43 => 3.45
-// 10: 10 cent rounding 3.45 => 3.50 (5 gets rounded up)
-// 25: 25 cent rounding 3.41 => 3.50
-// 50: 50 cent rounding 3.75 => 4.00
-// 100: 100 cent rounding 3.50 => 4.00
+//
+// 5: 5 cent rounding 3.43 => 3.45
+// 10: 10 cent rounding 3.45 => 3.50 (5 gets rounded up)
+// 25: 25 cent rounding 3.41 => 3.50
+// 50: 50 cent rounding 3.75 => 4.00
+// 100: 100 cent rounding 3.50 => 4.00
+//
// For more details: https://en.wikipedia.org/wiki/Cash_rounding
func (d Decimal) RoundCash(interval uint8) Decimal {
var iVal *big.Int
@@ -927,8 +1751,7 @@ func (d Decimal) Ceil() Decimal {
//
// Example:
//
-// decimal.NewFromString("123.456").Truncate(2).String() // "123.45"
-//
+// decimal.NewFromString("123.456").Truncate(2).String() // "123.45"
func (d Decimal) Truncate(precision int32) Decimal {
d.ensureInitialized()
if precision >= 0 && -precision > d.exp {
@@ -970,29 +1793,38 @@ func (d Decimal) MarshalJSON() ([]byte, error) {
// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface. As a string representation
// is already used when encoding to text, this method stores that string as []byte
func (d *Decimal) UnmarshalBinary(data []byte) error {
+ // Verify we have at least 4 bytes for the exponent. The GOB encoded value
+ // may be empty.
+ if len(data) < 4 {
+ return fmt.Errorf("error decoding binary %v: expected at least 4 bytes, got %d", data, len(data))
+ }
+
// Extract the exponent
d.exp = int32(binary.BigEndian.Uint32(data[:4]))
// Extract the value
d.value = new(big.Int)
- return d.value.GobDecode(data[4:])
+ if err := d.value.GobDecode(data[4:]); err != nil {
+ return fmt.Errorf("error decoding binary %v: %s", data, err)
+ }
+
+ return nil
}
// MarshalBinary implements the encoding.BinaryMarshaler interface.
func (d Decimal) MarshalBinary() (data []byte, err error) {
- // Write the exponent first since it's a fixed size
- v1 := make([]byte, 4)
- binary.BigEndian.PutUint32(v1, uint32(d.exp))
-
- // Add the value
- var v2 []byte
- if v2, err = d.value.GobEncode(); err != nil {
- return
+ // exp is written first, but encode value first to know output size
+ var valueData []byte
+ if valueData, err = d.value.GobEncode(); err != nil {
+ return nil, err
}
+ // Write the exponent in front, since it's a fixed size
+ expData := make([]byte, 4, len(valueData)+4)
+ binary.BigEndian.PutUint32(expData, uint32(d.exp))
+
// Return the byte array
- data = append(v1, v2...)
- return
+ return append(expData, valueData...), nil
}
// Scan implements the sql.Scanner interface for database deserialization.
@@ -1015,6 +1847,11 @@ func (d *Decimal) Scan(value interface{}) error {
*d = New(v, 0)
return nil
+ case uint64:
+ // while clickhouse may send 0 in db as uint64
+ *d = NewFromUint64(v)
+ return nil
+
default:
// default is trying to interpret value stored as string
str, err := unquoteIfQuoted(v)
@@ -1062,7 +1899,8 @@ func (d *Decimal) GobDecode(data []byte) error {
}
// StringScaled first scales the decimal then calls .String() on it.
-// NOTE: buggy, unintuitive, and DEPRECATED! Use StringFixed instead.
+//
+// Deprecated: buggy and unintuitive. Use StringFixed instead.
func (d Decimal) StringScaled(exp int32) string {
return d.rescale(exp).String()
}
@@ -1122,7 +1960,7 @@ func (d *Decimal) ensureInitialized() {
//
// To call this function with an array, you must do:
//
-// Min(arr[0], arr[1:]...)
+// Min(arr[0], arr[1:]...)
//
// This makes it harder to accidentally call Min with 0 arguments.
func Min(first Decimal, rest ...Decimal) Decimal {
@@ -1139,7 +1977,7 @@ func Min(first Decimal, rest ...Decimal) Decimal {
//
// To call this function with an array, you must do:
//
-// Max(arr[0], arr[1:]...)
+// Max(arr[0], arr[1:]...)
//
// This makes it harder to accidentally call Max with 0 arguments.
func Max(first Decimal, rest ...Decimal) Decimal {
@@ -1174,22 +2012,13 @@ func RescalePair(d1 Decimal, d2 Decimal) (Decimal, Decimal) {
d1.ensureInitialized()
d2.ensureInitialized()
- if d1.exp == d2.exp {
- return d1, d2
- }
-
- baseScale := min(d1.exp, d2.exp)
- if baseScale != d1.exp {
- return d1.rescale(baseScale), d2
+ if d1.exp < d2.exp {
+ return d1, d2.rescale(d1.exp)
+ } else if d1.exp > d2.exp {
+ return d1.rescale(d2.exp), d2
}
- return d1, d2.rescale(baseScale)
-}
-func min(x, y int32) int32 {
- if x >= y {
- return y
- }
- return x
+ return d1, d2
}
func unquoteIfQuoted(value interface{}) (string, error) {
@@ -1201,8 +2030,7 @@ func unquoteIfQuoted(value interface{}) (string, error) {
case []byte:
bytes = v
default:
- return "", fmt.Errorf("could not convert value '%+v' to byte array of type '%T'",
- value, value)
+ return "", fmt.Errorf("could not convert value '%+v' to byte array of type '%T'", value, value)
}
// If the amount is quoted, strip the quotes
@@ -1219,6 +2047,13 @@ type NullDecimal struct {
Valid bool
}
+func NewNullDecimal(d Decimal) NullDecimal {
+ return NullDecimal{
+ Decimal: d,
+ Valid: true,
+ }
+}
+
// Scan implements the sql.Scanner interface for database deserialization.
func (d *NullDecimal) Scan(value interface{}) error {
if value == nil {
@@ -1255,6 +2090,33 @@ func (d NullDecimal) MarshalJSON() ([]byte, error) {
return d.Decimal.MarshalJSON()
}
+// UnmarshalText implements the encoding.TextUnmarshaler interface for XML
+// deserialization
+func (d *NullDecimal) UnmarshalText(text []byte) error {
+ str := string(text)
+
+ // check for empty XML or XML without body e.g.,
+ if str == "" {
+ d.Valid = false
+ return nil
+ }
+ if err := d.Decimal.UnmarshalText(text); err != nil {
+ d.Valid = false
+ return err
+ }
+ d.Valid = true
+ return nil
+}
+
+// MarshalText implements the encoding.TextMarshaler interface for XML
+// serialization.
+func (d NullDecimal) MarshalText() (text []byte, err error) {
+ if !d.Valid {
+ return []byte{}, nil
+ }
+ return d.Decimal.MarshalText()
+}
+
// Trig functions
// Atan returns the arctangent, in radians, of x.
diff --git a/vendor/github.com/shopspring/decimal/rounding.go b/vendor/github.com/shopspring/decimal/rounding.go
index 8008f55cb98..d4b0cd00795 100644
--- a/vendor/github.com/shopspring/decimal/rounding.go
+++ b/vendor/github.com/shopspring/decimal/rounding.go
@@ -80,39 +80,80 @@ func roundShortest(d *decimal, mant uint64, exp int, flt *floatInfo) {
// would round to the original mantissa and not the neighbors.
inclusive := mant%2 == 0
+ // As we walk the digits we want to know whether rounding up would fall
+ // within the upper bound. This is tracked by upperdelta:
+ //
+ // If upperdelta == 0, the digits of d and upper are the same so far.
+ //
+ // If upperdelta == 1, we saw a difference of 1 between d and upper on a
+ // previous digit and subsequently only 9s for d and 0s for upper.
+ // (Thus rounding up may fall outside the bound, if it is exclusive.)
+ //
+ // If upperdelta == 2, then the difference is greater than 1
+ // and we know that rounding up falls within the bound.
+ var upperdelta uint8
+
// Now we can figure out the minimum number of digits required.
// Walk along until d has distinguished itself from upper and lower.
- for i := 0; i < d.nd; i++ {
+ for ui := 0; ; ui++ {
+ // lower, d, and upper may have the decimal points at different
+ // places. In this case upper is the longest, so we iterate from
+ // ui==0 and start li and mi at (possibly) -1.
+ mi := ui - upper.dp + d.dp
+ if mi >= d.nd {
+ break
+ }
+ li := ui - upper.dp + lower.dp
l := byte('0') // lower digit
- if i < lower.nd {
- l = lower.d[i]
+ if li >= 0 && li < lower.nd {
+ l = lower.d[li]
+ }
+ m := byte('0') // middle digit
+ if mi >= 0 {
+ m = d.d[mi]
}
- m := d.d[i] // middle digit
u := byte('0') // upper digit
- if i < upper.nd {
- u = upper.d[i]
+ if ui < upper.nd {
+ u = upper.d[ui]
}
// Okay to round down (truncate) if lower has a different digit
// or if lower is inclusive and is exactly the result of rounding
// down (i.e., and we have reached the final digit of lower).
- okdown := l != m || inclusive && i+1 == lower.nd
+ okdown := l != m || inclusive && li+1 == lower.nd
+ switch {
+ case upperdelta == 0 && m+1 < u:
+ // Example:
+ // m = 12345xxx
+ // u = 12347xxx
+ upperdelta = 2
+ case upperdelta == 0 && m != u:
+ // Example:
+ // m = 12345xxx
+ // u = 12346xxx
+ upperdelta = 1
+ case upperdelta == 1 && (m != '9' || u != '0'):
+ // Example:
+ // m = 1234598x
+ // u = 1234600x
+ upperdelta = 2
+ }
// Okay to round up if upper has a different digit and either upper
// is inclusive or upper is bigger than the result of rounding up.
- okup := m != u && (inclusive || m+1 < u || i+1 < upper.nd)
+ okup := upperdelta > 0 && (inclusive || upperdelta > 1 || ui+1 < upper.nd)
// If it's okay to do either, then round to the nearest one.
// If it's okay to do only one, do it.
switch {
case okdown && okup:
- d.Round(i + 1)
+ d.Round(mi + 1)
return
case okdown:
- d.RoundDown(i + 1)
+ d.RoundDown(mi + 1)
return
case okup:
- d.RoundUp(i + 1)
+ d.RoundUp(mi + 1)
return
}
}
diff --git a/vendor/github.com/spf13/cast/README.md b/vendor/github.com/spf13/cast/README.md
index 120a573426b..0e9e1459358 100644
--- a/vendor/github.com/spf13/cast/README.md
+++ b/vendor/github.com/spf13/cast/README.md
@@ -1,8 +1,9 @@
-cast
-====
-[![GoDoc](https://godoc.org/github.com/spf13/cast?status.svg)](https://godoc.org/github.com/spf13/cast)
-[![Build Status](https://github.com/spf13/cast/actions/workflows/go.yml/badge.svg)](https://github.com/spf13/cast/actions/workflows/go.yml)
-[![Go Report Card](https://goreportcard.com/badge/github.com/spf13/cast)](https://goreportcard.com/report/github.com/spf13/cast)
+# cast
+
+[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/spf13/cast/ci.yaml?branch=master&style=flat-square)](https://github.com/spf13/cast/actions/workflows/ci.yaml)
+[![PkgGoDev](https://pkg.go.dev/badge/mod/github.com/spf13/cast)](https://pkg.go.dev/mod/github.com/spf13/cast)
+![Go Version](https://img.shields.io/badge/go%20version-%3E=1.16-61CFDD.svg?style=flat-square)
+[![Go Report Card](https://goreportcard.com/badge/github.com/spf13/cast?style=flat-square)](https://goreportcard.com/report/github.com/spf13/cast)
Easy and safe casting from one type to another in Go
@@ -17,7 +18,7 @@ interface into a bool, etc. Cast does this intelligently when an obvious
conversion is possible. It doesn’t make any attempts to guess what you meant,
for example you can only convert a string to an int when it is a string
representation of an int such as “8”. Cast was developed for use in
-[Hugo](http://hugo.spf13.com), a website engine which uses YAML, TOML or JSON
+[Hugo](https://gohugo.io), a website engine which uses YAML, TOML or JSON
for meta data.
## Why use Cast?
@@ -72,4 +73,3 @@ the code for a complete set.
var eight interface{} = 8
cast.ToInt(eight) // 8
cast.ToInt(nil) // 0
-
diff --git a/vendor/github.com/spf13/cast/caste.go b/vendor/github.com/spf13/cast/caste.go
index 514d759bfb5..cd9c04885ac 100644
--- a/vendor/github.com/spf13/cast/caste.go
+++ b/vendor/github.com/spf13/cast/caste.go
@@ -18,6 +18,14 @@ import (
var errNegativeNotAllowed = errors.New("unable to cast negative value")
+type float64EProvider interface {
+ Float64() (float64, error)
+}
+
+type float64Provider interface {
+ Float64() float64
+}
+
// ToTimeE casts an interface to a time.Time type.
func ToTimeE(i interface{}) (tim time.Time, err error) {
return ToTimeInDefaultLocationE(i, time.UTC)
@@ -77,11 +85,14 @@ func ToDurationE(i interface{}) (d time.Duration, err error) {
d, err = time.ParseDuration(s + "ns")
}
return
- case json.Number:
+ case float64EProvider:
var v float64
v, err = s.Float64()
d = time.Duration(v)
return
+ case float64Provider:
+ d = time.Duration(s.Float64())
+ return
default:
err = fmt.Errorf("unable to cast %#v of type %T to Duration", i, i)
return
@@ -98,10 +109,31 @@ func ToBoolE(i interface{}) (bool, error) {
case nil:
return false, nil
case int:
- if i.(int) != 0 {
- return true, nil
- }
- return false, nil
+ return b != 0, nil
+ case int64:
+ return b != 0, nil
+ case int32:
+ return b != 0, nil
+ case int16:
+ return b != 0, nil
+ case int8:
+ return b != 0, nil
+ case uint:
+ return b != 0, nil
+ case uint64:
+ return b != 0, nil
+ case uint32:
+ return b != 0, nil
+ case uint16:
+ return b != 0, nil
+ case uint8:
+ return b != 0, nil
+ case float64:
+ return b != 0, nil
+ case float32:
+ return b != 0, nil
+ case time.Duration:
+ return b != 0, nil
case string:
return strconv.ParseBool(i.(string))
case json.Number:
@@ -153,12 +185,14 @@ func ToFloat64E(i interface{}) (float64, error) {
return v, nil
}
return 0, fmt.Errorf("unable to cast %#v of type %T to float64", i, i)
- case json.Number:
+ case float64EProvider:
v, err := s.Float64()
if err == nil {
return v, nil
}
return 0, fmt.Errorf("unable to cast %#v of type %T to float64", i, i)
+ case float64Provider:
+ return s.Float64(), nil
case bool:
if s {
return 1, nil
@@ -209,12 +243,14 @@ func ToFloat32E(i interface{}) (float32, error) {
return float32(v), nil
}
return 0, fmt.Errorf("unable to cast %#v of type %T to float32", i, i)
- case json.Number:
+ case float64EProvider:
v, err := s.Float64()
if err == nil {
return float32(v), nil
}
return 0, fmt.Errorf("unable to cast %#v of type %T to float32", i, i)
+ case float64Provider:
+ return float32(s.Float64()), nil
case bool:
if s {
return 1, nil
@@ -896,8 +932,8 @@ func indirectToStringerOrError(a interface{}) interface{} {
return nil
}
- var errorType = reflect.TypeOf((*error)(nil)).Elem()
- var fmtStringerType = reflect.TypeOf((*fmt.Stringer)(nil)).Elem()
+ errorType := reflect.TypeOf((*error)(nil)).Elem()
+ fmtStringerType := reflect.TypeOf((*fmt.Stringer)(nil)).Elem()
v := reflect.ValueOf(a)
for !v.Type().Implements(fmtStringerType) && !v.Type().Implements(errorType) && v.Kind() == reflect.Ptr && !v.IsNil() {
@@ -966,7 +1002,7 @@ func ToStringE(i interface{}) (string, error) {
// ToStringMapStringE casts an interface to a map[string]string type.
func ToStringMapStringE(i interface{}) (map[string]string, error) {
- var m = map[string]string{}
+ m := map[string]string{}
switch v := i.(type) {
case map[string]string:
@@ -996,7 +1032,7 @@ func ToStringMapStringE(i interface{}) (map[string]string, error) {
// ToStringMapStringSliceE casts an interface to a map[string][]string type.
func ToStringMapStringSliceE(i interface{}) (map[string][]string, error) {
- var m = map[string][]string{}
+ m := map[string][]string{}
switch v := i.(type) {
case map[string][]string:
@@ -1060,7 +1096,7 @@ func ToStringMapStringSliceE(i interface{}) (map[string][]string, error) {
// ToStringMapBoolE casts an interface to a map[string]bool type.
func ToStringMapBoolE(i interface{}) (map[string]bool, error) {
- var m = map[string]bool{}
+ m := map[string]bool{}
switch v := i.(type) {
case map[interface{}]interface{}:
@@ -1085,7 +1121,7 @@ func ToStringMapBoolE(i interface{}) (map[string]bool, error) {
// ToStringMapE casts an interface to a map[string]interface{} type.
func ToStringMapE(i interface{}) (map[string]interface{}, error) {
- var m = map[string]interface{}{}
+ m := map[string]interface{}{}
switch v := i.(type) {
case map[interface{}]interface{}:
@@ -1105,7 +1141,7 @@ func ToStringMapE(i interface{}) (map[string]interface{}, error) {
// ToStringMapIntE casts an interface to a map[string]int{} type.
func ToStringMapIntE(i interface{}) (map[string]int, error) {
- var m = map[string]int{}
+ m := map[string]int{}
if i == nil {
return m, fmt.Errorf("unable to cast %#v of type %T to map[string]int", i, i)
}
@@ -1146,7 +1182,7 @@ func ToStringMapIntE(i interface{}) (map[string]int, error) {
// ToStringMapInt64E casts an interface to a map[string]int64{} type.
func ToStringMapInt64E(i interface{}) (map[string]int64, error) {
- var m = map[string]int64{}
+ m := map[string]int64{}
if i == nil {
return m, fmt.Errorf("unable to cast %#v of type %T to map[string]int64", i, i)
}
@@ -1383,37 +1419,35 @@ func (f timeFormat) hasTimezone() bool {
return f.typ >= timeFormatNumericTimezone && f.typ <= timeFormatNumericAndNamedTimezone
}
-var (
- timeFormats = []timeFormat{
- {time.RFC3339, timeFormatNumericTimezone},
- {"2006-01-02T15:04:05", timeFormatNoTimezone}, // iso8601 without timezone
- {time.RFC1123Z, timeFormatNumericTimezone},
- {time.RFC1123, timeFormatNamedTimezone},
- {time.RFC822Z, timeFormatNumericTimezone},
- {time.RFC822, timeFormatNamedTimezone},
- {time.RFC850, timeFormatNamedTimezone},
- {"2006-01-02 15:04:05.999999999 -0700 MST", timeFormatNumericAndNamedTimezone}, // Time.String()
- {"2006-01-02T15:04:05-0700", timeFormatNumericTimezone}, // RFC3339 without timezone hh:mm colon
- {"2006-01-02 15:04:05Z0700", timeFormatNumericTimezone}, // RFC3339 without T or timezone hh:mm colon
- {"2006-01-02 15:04:05", timeFormatNoTimezone},
- {time.ANSIC, timeFormatNoTimezone},
- {time.UnixDate, timeFormatNamedTimezone},
- {time.RubyDate, timeFormatNumericTimezone},
- {"2006-01-02 15:04:05Z07:00", timeFormatNumericTimezone},
- {"2006-01-02", timeFormatNoTimezone},
- {"02 Jan 2006", timeFormatNoTimezone},
- {"2006-01-02 15:04:05 -07:00", timeFormatNumericTimezone},
- {"2006-01-02 15:04:05 -0700", timeFormatNumericTimezone},
- {time.Kitchen, timeFormatTimeOnly},
- {time.Stamp, timeFormatTimeOnly},
- {time.StampMilli, timeFormatTimeOnly},
- {time.StampMicro, timeFormatTimeOnly},
- {time.StampNano, timeFormatTimeOnly},
- }
-)
+var timeFormats = []timeFormat{
+ // Keep common formats at the top.
+ {"2006-01-02", timeFormatNoTimezone},
+ {time.RFC3339, timeFormatNumericTimezone},
+ {"2006-01-02T15:04:05", timeFormatNoTimezone}, // iso8601 without timezone
+ {time.RFC1123Z, timeFormatNumericTimezone},
+ {time.RFC1123, timeFormatNamedTimezone},
+ {time.RFC822Z, timeFormatNumericTimezone},
+ {time.RFC822, timeFormatNamedTimezone},
+ {time.RFC850, timeFormatNamedTimezone},
+ {"2006-01-02 15:04:05.999999999 -0700 MST", timeFormatNumericAndNamedTimezone}, // Time.String()
+ {"2006-01-02T15:04:05-0700", timeFormatNumericTimezone}, // RFC3339 without timezone hh:mm colon
+ {"2006-01-02 15:04:05Z0700", timeFormatNumericTimezone}, // RFC3339 without T or timezone hh:mm colon
+ {"2006-01-02 15:04:05", timeFormatNoTimezone},
+ {time.ANSIC, timeFormatNoTimezone},
+ {time.UnixDate, timeFormatNamedTimezone},
+ {time.RubyDate, timeFormatNumericTimezone},
+ {"2006-01-02 15:04:05Z07:00", timeFormatNumericTimezone},
+ {"02 Jan 2006", timeFormatNoTimezone},
+ {"2006-01-02 15:04:05 -07:00", timeFormatNumericTimezone},
+ {"2006-01-02 15:04:05 -0700", timeFormatNumericTimezone},
+ {time.Kitchen, timeFormatTimeOnly},
+ {time.Stamp, timeFormatTimeOnly},
+ {time.StampMilli, timeFormatTimeOnly},
+ {time.StampMicro, timeFormatTimeOnly},
+ {time.StampNano, timeFormatTimeOnly},
+}
func parseDateWith(s string, location *time.Location, formats []timeFormat) (d time.Time, e error) {
-
for _, format := range formats {
if d, e = time.Parse(format.format, s); e == nil {
diff --git a/vendor/google.golang.org/protobuf/cmd/protoc-gen-go/internal_gengo/init.go b/vendor/google.golang.org/protobuf/cmd/protoc-gen-go/internal_gengo/init.go
new file mode 100644
index 00000000000..62de8bb1b64
--- /dev/null
+++ b/vendor/google.golang.org/protobuf/cmd/protoc-gen-go/internal_gengo/init.go
@@ -0,0 +1,171 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package internal_gengo
+
+import (
+ "unicode"
+ "unicode/utf8"
+
+ "google.golang.org/protobuf/compiler/protogen"
+ "google.golang.org/protobuf/encoding/protowire"
+
+ "google.golang.org/protobuf/types/descriptorpb"
+)
+
+type fileInfo struct {
+ *protogen.File
+
+ allEnums []*enumInfo
+ allMessages []*messageInfo
+ allExtensions []*extensionInfo
+
+ allEnumsByPtr map[*enumInfo]int // value is index into allEnums
+ allMessagesByPtr map[*messageInfo]int // value is index into allMessages
+ allMessageFieldsByPtr map[*messageInfo]*structFields
+
+ // needRawDesc specifies whether the generator should emit logic to provide
+ // the legacy raw descriptor in GZIP'd form.
+ // This is updated by enum and message generation logic as necessary,
+ // and checked at the end of file generation.
+ needRawDesc bool
+}
+
+type structFields struct {
+ count int
+ unexported map[int]string
+}
+
+func (sf *structFields) append(name string) {
+ if r, _ := utf8.DecodeRuneInString(name); !unicode.IsUpper(r) {
+ if sf.unexported == nil {
+ sf.unexported = make(map[int]string)
+ }
+ sf.unexported[sf.count] = name
+ }
+ sf.count++
+}
+
+func newFileInfo(file *protogen.File) *fileInfo {
+ f := &fileInfo{File: file}
+
+ // Collect all enums, messages, and extensions in "flattened ordering".
+ // See filetype.TypeBuilder.
+ var walkMessages func([]*protogen.Message, func(*protogen.Message))
+ walkMessages = func(messages []*protogen.Message, f func(*protogen.Message)) {
+ for _, m := range messages {
+ f(m)
+ walkMessages(m.Messages, f)
+ }
+ }
+ initEnumInfos := func(enums []*protogen.Enum) {
+ for _, enum := range enums {
+ f.allEnums = append(f.allEnums, newEnumInfo(f, enum))
+ }
+ }
+ initMessageInfos := func(messages []*protogen.Message) {
+ for _, message := range messages {
+ f.allMessages = append(f.allMessages, newMessageInfo(f, message))
+ }
+ }
+ initExtensionInfos := func(extensions []*protogen.Extension) {
+ for _, extension := range extensions {
+ f.allExtensions = append(f.allExtensions, newExtensionInfo(f, extension))
+ }
+ }
+ initEnumInfos(f.Enums)
+ initMessageInfos(f.Messages)
+ initExtensionInfos(f.Extensions)
+ walkMessages(f.Messages, func(m *protogen.Message) {
+ initEnumInfos(m.Enums)
+ initMessageInfos(m.Messages)
+ initExtensionInfos(m.Extensions)
+ })
+
+ // Derive a reverse mapping of enum and message pointers to their index
+ // in allEnums and allMessages.
+ if len(f.allEnums) > 0 {
+ f.allEnumsByPtr = make(map[*enumInfo]int)
+ for i, e := range f.allEnums {
+ f.allEnumsByPtr[e] = i
+ }
+ }
+ if len(f.allMessages) > 0 {
+ f.allMessagesByPtr = make(map[*messageInfo]int)
+ f.allMessageFieldsByPtr = make(map[*messageInfo]*structFields)
+ for i, m := range f.allMessages {
+ f.allMessagesByPtr[m] = i
+ f.allMessageFieldsByPtr[m] = new(structFields)
+ }
+ }
+
+ return f
+}
+
+type enumInfo struct {
+ *protogen.Enum
+
+ genJSONMethod bool
+ genRawDescMethod bool
+}
+
+func newEnumInfo(f *fileInfo, enum *protogen.Enum) *enumInfo {
+ e := &enumInfo{Enum: enum}
+ e.genJSONMethod = true
+ e.genRawDescMethod = true
+ opaqueNewEnumInfoHook(f, e)
+ return e
+}
+
+type messageInfo struct {
+ *protogen.Message
+
+ genRawDescMethod bool
+ genExtRangeMethod bool
+
+ isTracked bool
+ noInterface bool
+ hasWeak bool
+}
+
+func newMessageInfo(f *fileInfo, message *protogen.Message) *messageInfo {
+ m := &messageInfo{Message: message}
+ m.genRawDescMethod = true
+ m.genExtRangeMethod = true
+ m.isTracked = isTrackedMessage(m)
+ for _, field := range m.Fields {
+ m.hasWeak = m.hasWeak || field.Desc.IsWeak()
+ }
+ opaqueNewMessageInfoHook(f, m)
+ return m
+}
+
+// isTrackedMessage reports whether field tracking is enabled on the message.
+func isTrackedMessage(m *messageInfo) (tracked bool) {
+ const trackFieldUse_fieldNumber = 37383685
+
+ // Decode the option from unknown fields to avoid a dependency on the
+ // annotation proto from protoc-gen-go.
+ b := m.Desc.Options().(*descriptorpb.MessageOptions).ProtoReflect().GetUnknown()
+ for len(b) > 0 {
+ num, typ, n := protowire.ConsumeTag(b)
+ b = b[n:]
+ if num == trackFieldUse_fieldNumber && typ == protowire.VarintType {
+ v, _ := protowire.ConsumeVarint(b)
+ tracked = protowire.DecodeBool(v)
+ }
+ m := protowire.ConsumeFieldValue(num, typ, b)
+ b = b[m:]
+ }
+ return tracked
+}
+
+type extensionInfo struct {
+ *protogen.Extension
+}
+
+func newExtensionInfo(f *fileInfo, extension *protogen.Extension) *extensionInfo {
+ x := &extensionInfo{Extension: extension}
+ return x
+}
diff --git a/vendor/google.golang.org/protobuf/cmd/protoc-gen-go/internal_gengo/init_opaque.go b/vendor/google.golang.org/protobuf/cmd/protoc-gen-go/internal_gengo/init_opaque.go
new file mode 100644
index 00000000000..221176a228c
--- /dev/null
+++ b/vendor/google.golang.org/protobuf/cmd/protoc-gen-go/internal_gengo/init_opaque.go
@@ -0,0 +1,33 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package internal_gengo
+
+import "google.golang.org/protobuf/types/gofeaturespb"
+
+func (m *messageInfo) isOpen() bool {
+ return m.Message.APILevel == gofeaturespb.GoFeatures_API_OPEN
+}
+
+func (m *messageInfo) isHybrid() bool {
+ return m.Message.APILevel == gofeaturespb.GoFeatures_API_HYBRID
+}
+
+func (m *messageInfo) isOpaque() bool {
+ return m.Message.APILevel == gofeaturespb.GoFeatures_API_OPAQUE
+}
+
+func opaqueNewEnumInfoHook(f *fileInfo, e *enumInfo) {
+ if f.File.APILevel != gofeaturespb.GoFeatures_API_OPEN {
+ e.genJSONMethod = false
+ e.genRawDescMethod = false
+ }
+}
+
+func opaqueNewMessageInfoHook(f *fileInfo, m *messageInfo) {
+ if !m.isOpen() {
+ m.genRawDescMethod = false
+ m.genExtRangeMethod = false
+ }
+}
diff --git a/vendor/google.golang.org/protobuf/cmd/protoc-gen-go/internal_gengo/main.go b/vendor/google.golang.org/protobuf/cmd/protoc-gen-go/internal_gengo/main.go
new file mode 100644
index 00000000000..9302b77022e
--- /dev/null
+++ b/vendor/google.golang.org/protobuf/cmd/protoc-gen-go/internal_gengo/main.go
@@ -0,0 +1,985 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package internal_gengo is internal to the protobuf module.
+package internal_gengo
+
+import (
+ "fmt"
+ "go/ast"
+ "go/parser"
+ "go/token"
+ "math"
+ "strconv"
+ "strings"
+ "unicode"
+ "unicode/utf8"
+
+ "google.golang.org/protobuf/compiler/protogen"
+ "google.golang.org/protobuf/internal/editionssupport"
+ "google.golang.org/protobuf/internal/encoding/tag"
+ "google.golang.org/protobuf/internal/filedesc"
+ "google.golang.org/protobuf/internal/genid"
+ "google.golang.org/protobuf/internal/version"
+ "google.golang.org/protobuf/reflect/protoreflect"
+ "google.golang.org/protobuf/runtime/protoimpl"
+
+ "google.golang.org/protobuf/types/descriptorpb"
+ "google.golang.org/protobuf/types/gofeaturespb"
+ "google.golang.org/protobuf/types/pluginpb"
+)
+
+// SupportedFeatures reports the set of supported protobuf language features.
+var SupportedFeatures = uint64(pluginpb.CodeGeneratorResponse_FEATURE_PROTO3_OPTIONAL | pluginpb.CodeGeneratorResponse_FEATURE_SUPPORTS_EDITIONS)
+
+var SupportedEditionsMinimum = editionssupport.Minimum
+var SupportedEditionsMaximum = editionssupport.Maximum
+
+// GenerateVersionMarkers specifies whether to generate version markers.
+var GenerateVersionMarkers = true
+
+// Standard library dependencies.
+const (
+ base64Package = protogen.GoImportPath("encoding/base64")
+ jsonPackage = protogen.GoImportPath("encoding/json")
+ mathPackage = protogen.GoImportPath("math")
+ reflectPackage = protogen.GoImportPath("reflect")
+ sortPackage = protogen.GoImportPath("sort")
+ stringsPackage = protogen.GoImportPath("strings")
+ syncPackage = protogen.GoImportPath("sync")
+ timePackage = protogen.GoImportPath("time")
+ utf8Package = protogen.GoImportPath("unicode/utf8")
+)
+
+// Protobuf library dependencies.
+//
+// These are declared as an interface type so that they can be more easily
+// patched to support unique build environments that impose restrictions
+// on the dependencies of generated source code.
+var (
+ protoPackage goImportPath = protogen.GoImportPath("google.golang.org/protobuf/proto")
+ protoifacePackage goImportPath = protogen.GoImportPath("google.golang.org/protobuf/runtime/protoiface")
+ protoimplPackage goImportPath = protogen.GoImportPath("google.golang.org/protobuf/runtime/protoimpl")
+ protojsonPackage goImportPath = protogen.GoImportPath("google.golang.org/protobuf/encoding/protojson")
+ protoreflectPackage goImportPath = protogen.GoImportPath("google.golang.org/protobuf/reflect/protoreflect")
+ protoregistryPackage goImportPath = protogen.GoImportPath("google.golang.org/protobuf/reflect/protoregistry")
+)
+
+type goImportPath interface {
+ String() string
+ Ident(string) protogen.GoIdent
+}
+
+func setToOpaque(msg *protogen.Message) {
+ msg.APILevel = gofeaturespb.GoFeatures_API_OPAQUE
+ for _, nested := range msg.Messages {
+ nested.APILevel = gofeaturespb.GoFeatures_API_OPAQUE
+ setToOpaque(nested)
+ }
+}
+
+// GenerateFile generates the contents of a .pb.go file.
+//
+// With the Hybrid API, multiple files are generated (_protoopaque.pb.go variant),
+// but only the first file (regular, not a variant) is returned.
+func GenerateFile(gen *protogen.Plugin, file *protogen.File) *protogen.GeneratedFile {
+ return generateFiles(gen, file)[0]
+}
+
+func generateFiles(gen *protogen.Plugin, file *protogen.File) []*protogen.GeneratedFile {
+ f := newFileInfo(file)
+ generated := []*protogen.GeneratedFile{
+ generateOneFile(gen, file, f, ""),
+ }
+ if f.APILevel == gofeaturespb.GoFeatures_API_HYBRID {
+ // Update all APILevel fields to OPAQUE
+ f.APILevel = gofeaturespb.GoFeatures_API_OPAQUE
+ for _, msg := range f.Messages {
+ setToOpaque(msg)
+ }
+ generated = append(generated, generateOneFile(gen, file, f, "_protoopaque"))
+ }
+ return generated
+}
+
+func generateOneFile(gen *protogen.Plugin, file *protogen.File, f *fileInfo, variant string) *protogen.GeneratedFile {
+ filename := file.GeneratedFilenamePrefix + variant + ".pb.go"
+ g := gen.NewGeneratedFile(filename, file.GoImportPath)
+
+ var packageDoc protogen.Comments
+ if !gen.InternalStripForEditionsDiff() {
+ genStandaloneComments(g, f, int32(genid.FileDescriptorProto_Syntax_field_number))
+ genGeneratedHeader(gen, g, f)
+ genStandaloneComments(g, f, int32(genid.FileDescriptorProto_Package_field_number))
+
+ packageDoc = genPackageKnownComment(f)
+ }
+ if variant == "_protoopaque" {
+ g.P("//go:build protoopaque")
+ } else if f.APILevel == gofeaturespb.GoFeatures_API_HYBRID {
+ g.P("//go:build !protoopaque")
+ }
+ g.P(packageDoc, "package ", f.GoPackageName)
+ g.P()
+
+ // Emit a static check that enforces a minimum version of the proto package.
+ if GenerateVersionMarkers {
+ g.P("const (")
+ g.P("// Verify that this generated code is sufficiently up-to-date.")
+ g.P("_ = ", protoimplPackage.Ident("EnforceVersion"), "(", protoimpl.GenVersion, " - ", protoimplPackage.Ident("MinVersion"), ")")
+ g.P("// Verify that runtime/protoimpl is sufficiently up-to-date.")
+ g.P("_ = ", protoimplPackage.Ident("EnforceVersion"), "(", protoimplPackage.Ident("MaxVersion"), " - ", protoimpl.GenVersion, ")")
+ g.P(")")
+ g.P()
+ }
+
+ for i, imps := 0, f.Desc.Imports(); i < imps.Len(); i++ {
+ genImport(gen, g, f, imps.Get(i))
+ }
+ for _, enum := range f.allEnums {
+ genEnum(g, f, enum)
+ }
+ for _, message := range f.allMessages {
+ genMessage(g, f, message)
+ }
+ genExtensions(g, f)
+
+ // The descriptor contains a lot of information about the syntax which is
+ // quite different between the proto2/3 version of a file and the equivalent
+ // editions version. For example, when a proto3 file is translated from
+ // proto3 to editions every field in that file that is marked optional in
+ // proto3 will have a features.field_presence option set.
+ // Another problem is that the descriptor contains implementation details
+ // that are not relevant for the semantic. For example, proto3 optional
+ // fields are implemented as oneof fields with one case. The descriptor
+ // contains different information about oneofs. If the file is translated
+ // to editions it no longer is treated as a oneof with one case and thus
+ // none of the oneof specific information is generated.
+ // To be able to compare the descriptor before and after translation of the
+ // associated proto file, we would need to trim many parts. This would lead
+ // to a brittle implementation in case the translation ever changes.
+ if !g.InternalStripForEditionsDiff() {
+ genReflectFileDescriptor(gen, g, f)
+ }
+
+ return g
+}
+
+// genStandaloneComments prints all leading comments for a FileDescriptorProto
+// location identified by the field number n.
+func genStandaloneComments(g *protogen.GeneratedFile, f *fileInfo, n int32) {
+ loc := f.Desc.SourceLocations().ByPath(protoreflect.SourcePath{n})
+ for _, s := range loc.LeadingDetachedComments {
+ g.P(protogen.Comments(s))
+ g.P()
+ }
+ if s := loc.LeadingComments; s != "" {
+ g.P(protogen.Comments(s))
+ g.P()
+ }
+}
+
+func genGeneratedHeader(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo) {
+ g.P("// Code generated by protoc-gen-go. DO NOT EDIT.")
+
+ if GenerateVersionMarkers {
+ g.P("// versions:")
+ protocGenGoVersion := version.String()
+ protocVersion := "(unknown)"
+ if v := gen.Request.GetCompilerVersion(); v != nil {
+ protocVersion = fmt.Sprintf("v%v.%v.%v", v.GetMajor(), v.GetMinor(), v.GetPatch())
+ if s := v.GetSuffix(); s != "" {
+ protocVersion += "-" + s
+ }
+ }
+ g.P("// \tprotoc-gen-go ", protocGenGoVersion)
+ g.P("// \tprotoc ", protocVersion)
+ }
+
+ if f.Proto.GetOptions().GetDeprecated() {
+ g.P("// ", f.Desc.Path(), " is a deprecated file.")
+ } else {
+ g.P("// source: ", f.Desc.Path())
+ }
+ g.P()
+}
+
+func genImport(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, imp protoreflect.FileImport) {
+ impFile, ok := gen.FilesByPath[imp.Path()]
+ if !ok {
+ return
+ }
+ if impFile.GoImportPath == f.GoImportPath {
+ // Don't generate imports or aliases for types in the same Go package.
+ return
+ }
+ // Generate imports for all non-weak dependencies, even if they are not
+ // referenced, because other code and tools depend on having the
+ // full transitive closure of protocol buffer types in the binary.
+ if !imp.IsWeak {
+ g.Import(impFile.GoImportPath)
+ }
+ if !imp.IsPublic {
+ return
+ }
+
+ // Generate public imports by generating the imported file, parsing it,
+ // and extracting every symbol that should receive a forwarding declaration.
+ impGens := generateFiles(gen, impFile)
+ for _, impGen := range impGens {
+ impGen.Skip()
+ }
+ b, err := impGens[0].Content()
+ if err != nil {
+ gen.Error(err)
+ return
+ }
+ fset := token.NewFileSet()
+ astFile, err := parser.ParseFile(fset, "", b, parser.ParseComments)
+ if err != nil {
+ gen.Error(err)
+ return
+ }
+ genForward := func(tok token.Token, name string, expr ast.Expr) {
+ // Don't import unexported symbols.
+ r, _ := utf8.DecodeRuneInString(name)
+ if !unicode.IsUpper(r) {
+ return
+ }
+ // Don't import the FileDescriptor.
+ if name == impFile.GoDescriptorIdent.GoName {
+ return
+ }
+ // Don't import decls referencing a symbol defined in another package.
+ // i.e., don't import decls which are themselves public imports:
+ //
+ // type T = somepackage.T
+ if _, ok := expr.(*ast.SelectorExpr); ok {
+ return
+ }
+ g.P(tok, " ", name, " = ", impFile.GoImportPath.Ident(name))
+ }
+ g.P("// Symbols defined in public import of ", imp.Path(), ".")
+ g.P()
+ for _, decl := range astFile.Decls {
+ switch decl := decl.(type) {
+ case *ast.GenDecl:
+ for _, spec := range decl.Specs {
+ switch spec := spec.(type) {
+ case *ast.TypeSpec:
+ genForward(decl.Tok, spec.Name.Name, spec.Type)
+ case *ast.ValueSpec:
+ for i, name := range spec.Names {
+ var expr ast.Expr
+ if i < len(spec.Values) {
+ expr = spec.Values[i]
+ }
+ genForward(decl.Tok, name.Name, expr)
+ }
+ case *ast.ImportSpec:
+ default:
+ panic(fmt.Sprintf("can't generate forward for spec type %T", spec))
+ }
+ }
+ }
+ }
+ g.P()
+}
+
+func genEnum(g *protogen.GeneratedFile, f *fileInfo, e *enumInfo) {
+ // Enum type declaration.
+ g.AnnotateSymbol(e.GoIdent.GoName, protogen.Annotation{Location: e.Location})
+ leadingComments := appendDeprecationSuffix(e.Comments.Leading,
+ e.Desc.ParentFile(),
+ e.Desc.Options().(*descriptorpb.EnumOptions).GetDeprecated())
+ g.P(leadingComments,
+ "type ", e.GoIdent, " int32")
+
+ // Enum value constants.
+ g.P("const (")
+ anyOldName := false
+ for _, value := range e.Values {
+ g.AnnotateSymbol(value.GoIdent.GoName, protogen.Annotation{Location: value.Location})
+ leadingComments := appendDeprecationSuffix(value.Comments.Leading,
+ value.Desc.ParentFile(),
+ value.Desc.Options().(*descriptorpb.EnumValueOptions).GetDeprecated())
+ g.P(leadingComments,
+ value.GoIdent, " ", e.GoIdent, " = ", value.Desc.Number(),
+ trailingComment(value.Comments.Trailing))
+
+ if value.PrefixedAlias.GoName != "" &&
+ value.PrefixedAlias.GoName != value.GoIdent.GoName {
+ anyOldName = true
+ }
+ }
+ g.P(")")
+ g.P()
+ if anyOldName {
+ g.P("// Old (prefixed) names for ", e.GoIdent, " enum values.")
+ g.P("const (")
+ for _, value := range e.Values {
+ if value.PrefixedAlias.GoName != "" &&
+ value.PrefixedAlias.GoName != value.GoIdent.GoName {
+ g.P(value.PrefixedAlias, " ", e.GoIdent, " = ", value.GoIdent)
+ }
+ }
+ g.P(")")
+ g.P()
+ }
+
+ // Enum value maps.
+ g.P("// Enum value maps for ", e.GoIdent, ".")
+ g.P("var (")
+ g.P(e.GoIdent.GoName+"_name", " = map[int32]string{")
+ for _, value := range e.Values {
+ duplicate := ""
+ if value.Desc != e.Desc.Values().ByNumber(value.Desc.Number()) {
+ duplicate = "// Duplicate value: "
+ }
+ g.P(duplicate, value.Desc.Number(), ": ", strconv.Quote(string(value.Desc.Name())), ",")
+ }
+ g.P("}")
+ g.P(e.GoIdent.GoName+"_value", " = map[string]int32{")
+ for _, value := range e.Values {
+ g.P(strconv.Quote(string(value.Desc.Name())), ": ", value.Desc.Number(), ",")
+ }
+ g.P("}")
+ g.P(")")
+ g.P()
+
+ // Enum method.
+ //
+ // NOTE: A pointer value is needed to represent presence in proto2.
+ // Since a proto2 message can reference a proto3 enum, it is useful to
+ // always generate this method (even on proto3 enums) to support that case.
+ g.P("func (x ", e.GoIdent, ") Enum() *", e.GoIdent, " {")
+ g.P("p := new(", e.GoIdent, ")")
+ g.P("*p = x")
+ g.P("return p")
+ g.P("}")
+ g.P()
+
+ // String method.
+ g.P("func (x ", e.GoIdent, ") String() string {")
+ g.P("return ", protoimplPackage.Ident("X"), ".EnumStringOf(x.Descriptor(), ", protoreflectPackage.Ident("EnumNumber"), "(x))")
+ g.P("}")
+ g.P()
+
+ genEnumReflectMethods(g, f, e)
+
+ // UnmarshalJSON method.
+ needsUnmarshalJSONMethod := false
+ if fde, ok := e.Desc.(*filedesc.Enum); ok {
+ needsUnmarshalJSONMethod = fde.L1.EditionFeatures.GenerateLegacyUnmarshalJSON
+ }
+ if e.genJSONMethod && needsUnmarshalJSONMethod {
+ g.P("// Deprecated: Do not use.")
+ g.P("func (x *", e.GoIdent, ") UnmarshalJSON(b []byte) error {")
+ g.P("num, err := ", protoimplPackage.Ident("X"), ".UnmarshalJSONEnum(x.Descriptor(), b)")
+ g.P("if err != nil {")
+ g.P("return err")
+ g.P("}")
+ g.P("*x = ", e.GoIdent, "(num)")
+ g.P("return nil")
+ g.P("}")
+ g.P()
+ }
+
+ // EnumDescriptor method.
+ if e.genRawDescMethod {
+ var indexes []string
+ for i := 1; i < len(e.Location.Path); i += 2 {
+ indexes = append(indexes, strconv.Itoa(int(e.Location.Path[i])))
+ }
+ g.P("// Deprecated: Use ", e.GoIdent, ".Descriptor instead.")
+ g.P("func (", e.GoIdent, ") EnumDescriptor() ([]byte, []int) {")
+ g.P("return ", rawDescVarName(f), "GZIP(), []int{", strings.Join(indexes, ","), "}")
+ g.P("}")
+ g.P()
+ f.needRawDesc = true
+ }
+}
+
+func genMessage(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) {
+ if m.Desc.IsMapEntry() {
+ return
+ }
+ if opaqueGenMessageHook(g, f, m) {
+ return
+ }
+
+ // Message type declaration.
+ g.AnnotateSymbol(m.GoIdent.GoName, protogen.Annotation{Location: m.Location})
+ leadingComments := appendDeprecationSuffix(m.Comments.Leading,
+ m.Desc.ParentFile(),
+ m.Desc.Options().(*descriptorpb.MessageOptions).GetDeprecated())
+ g.P(leadingComments,
+ "type ", m.GoIdent, " struct {")
+ genMessageFields(g, f, m)
+ g.P("}")
+ g.P()
+
+ genMessageKnownFunctions(g, f, m)
+ genMessageDefaultDecls(g, f, m)
+ genMessageMethods(g, f, m)
+ genMessageOneofWrapperTypes(g, f, m)
+}
+
+func genMessageFields(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) {
+ sf := f.allMessageFieldsByPtr[m]
+ genMessageInternalFields(g, f, m, sf)
+ for _, field := range m.Fields {
+ genMessageField(g, f, m, field, sf)
+ }
+}
+
+func genMessageInternalFields(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo, sf *structFields) {
+ g.P(genid.State_goname, " ", protoimplPackage.Ident("MessageState"))
+ sf.append(genid.State_goname)
+ g.P(genid.SizeCache_goname, " ", protoimplPackage.Ident("SizeCache"))
+ sf.append(genid.SizeCache_goname)
+ if m.hasWeak {
+ g.P(genid.WeakFields_goname, " ", protoimplPackage.Ident("WeakFields"))
+ sf.append(genid.WeakFields_goname)
+ }
+ g.P(genid.UnknownFields_goname, " ", protoimplPackage.Ident("UnknownFields"))
+ sf.append(genid.UnknownFields_goname)
+ if m.Desc.ExtensionRanges().Len() > 0 {
+ g.P(genid.ExtensionFields_goname, " ", protoimplPackage.Ident("ExtensionFields"))
+ sf.append(genid.ExtensionFields_goname)
+ }
+ if sf.count > 0 {
+ g.P()
+ }
+}
+
+func genMessageField(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo, field *protogen.Field, sf *structFields) {
+ if oneof := field.Oneof; oneof != nil && !oneof.Desc.IsSynthetic() {
+ // It would be a bit simpler to iterate over the oneofs below,
+ // but generating the field here keeps the contents of the Go
+ // struct in the same order as the contents of the source
+ // .proto file.
+ if oneof.Fields[0] != field {
+ return // only generate for first appearance
+ }
+
+ tags := structTags{
+ {"protobuf_oneof", string(oneof.Desc.Name())},
+ }
+ if m.isTracked {
+ tags = append(tags, gotrackTags...)
+ }
+
+ g.AnnotateSymbol(m.GoIdent.GoName+"."+oneof.GoName, protogen.Annotation{Location: oneof.Location})
+ leadingComments := oneof.Comments.Leading
+ if leadingComments != "" {
+ leadingComments += "\n"
+ }
+ ss := []string{fmt.Sprintf(" Types that are assignable to %s:\n", oneof.GoName)}
+ for _, field := range oneof.Fields {
+ ss = append(ss, "\t*"+field.GoIdent.GoName+"\n")
+ }
+ leadingComments += protogen.Comments(strings.Join(ss, ""))
+ g.P(leadingComments,
+ oneof.GoName, " ", oneofInterfaceName(oneof), tags)
+ sf.append(oneof.GoName)
+ return
+ }
+ goType, pointer := fieldGoType(g, f, field)
+ if pointer {
+ goType = "*" + goType
+ }
+ tags := structTags{
+ {"protobuf", fieldProtobufTagValue(field)},
+ {"json", fieldJSONTagValue(field)},
+ }
+ if field.Desc.IsMap() {
+ key := field.Message.Fields[0]
+ val := field.Message.Fields[1]
+ tags = append(tags, structTags{
+ {"protobuf_key", fieldProtobufTagValue(key)},
+ {"protobuf_val", fieldProtobufTagValue(val)},
+ }...)
+ }
+ if m.isTracked {
+ tags = append(tags, gotrackTags...)
+ }
+
+ name := field.GoName
+ if field.Desc.IsWeak() {
+ name = genid.WeakFieldPrefix_goname + name
+ }
+ g.AnnotateSymbol(m.GoIdent.GoName+"."+name, protogen.Annotation{Location: field.Location})
+ leadingComments := appendDeprecationSuffix(field.Comments.Leading,
+ field.Desc.ParentFile(),
+ field.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated())
+ g.P(leadingComments,
+ name, " ", goType, tags,
+ trailingComment(field.Comments.Trailing))
+ sf.append(field.GoName)
+}
+
+// genMessageDefaultDecls generates consts and vars holding the default
+// values of fields.
+func genMessageDefaultDecls(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) {
+ var consts, vars []string
+ for _, field := range m.Fields {
+ if !field.Desc.HasDefault() {
+ continue
+ }
+ name := "Default_" + m.GoIdent.GoName + "_" + field.GoName
+ goType, _ := fieldGoType(g, f, field)
+ defVal := field.Desc.Default()
+ switch field.Desc.Kind() {
+ case protoreflect.StringKind:
+ consts = append(consts, fmt.Sprintf("%s = %s(%q)", name, goType, defVal.String()))
+ case protoreflect.BytesKind:
+ vars = append(vars, fmt.Sprintf("%s = %s(%q)", name, goType, defVal.Bytes()))
+ case protoreflect.EnumKind:
+ idx := field.Desc.DefaultEnumValue().Index()
+ val := field.Enum.Values[idx]
+ if val.GoIdent.GoImportPath == f.GoImportPath {
+ consts = append(consts, fmt.Sprintf("%s = %s", name, g.QualifiedGoIdent(val.GoIdent)))
+ } else {
+ // If the enum value is declared in a different Go package,
+ // reference it by number since the name may not be correct.
+ // See https://github.com/golang/protobuf/issues/513.
+ consts = append(consts, fmt.Sprintf("%s = %s(%d) // %s",
+ name, g.QualifiedGoIdent(field.Enum.GoIdent), val.Desc.Number(), g.QualifiedGoIdent(val.GoIdent)))
+ }
+ case protoreflect.FloatKind, protoreflect.DoubleKind:
+ if f := defVal.Float(); math.IsNaN(f) || math.IsInf(f, 0) {
+ var fn, arg string
+ switch f := defVal.Float(); {
+ case math.IsInf(f, -1):
+ fn, arg = g.QualifiedGoIdent(mathPackage.Ident("Inf")), "-1"
+ case math.IsInf(f, +1):
+ fn, arg = g.QualifiedGoIdent(mathPackage.Ident("Inf")), "+1"
+ case math.IsNaN(f):
+ fn, arg = g.QualifiedGoIdent(mathPackage.Ident("NaN")), ""
+ }
+ vars = append(vars, fmt.Sprintf("%s = %s(%s(%s))", name, goType, fn, arg))
+ } else {
+ consts = append(consts, fmt.Sprintf("%s = %s(%v)", name, goType, f))
+ }
+ default:
+ consts = append(consts, fmt.Sprintf("%s = %s(%v)", name, goType, defVal.Interface()))
+ }
+ }
+ if len(consts) > 0 {
+ g.P("// Default values for ", m.GoIdent, " fields.")
+ g.P("const (")
+ for _, s := range consts {
+ g.P(s)
+ }
+ g.P(")")
+ }
+ if len(vars) > 0 {
+ g.P("// Default values for ", m.GoIdent, " fields.")
+ g.P("var (")
+ for _, s := range vars {
+ g.P(s)
+ }
+ g.P(")")
+ }
+ g.P()
+}
+
+func genMessageMethods(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) {
+ genMessageBaseMethods(g, f, m)
+ genMessageGetterMethods(g, f, m)
+ genMessageSetterMethods(g, f, m)
+}
+
+func genMessageBaseMethods(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) {
+ // Reset method.
+ g.P("func (x *", m.GoIdent, ") Reset() {")
+ g.P("*x = ", m.GoIdent, "{}")
+ g.P("mi := &", messageTypesVarName(f), "[", f.allMessagesByPtr[m], "]")
+ g.P("ms := ", protoimplPackage.Ident("X"), ".MessageStateOf(", protoimplPackage.Ident("Pointer"), "(x))")
+ g.P("ms.StoreMessageInfo(mi)")
+ g.P("}")
+ g.P()
+
+ // String method.
+ g.P("func (x *", m.GoIdent, ") String() string {")
+ g.P("return ", protoimplPackage.Ident("X"), ".MessageStringOf(x)")
+ g.P("}")
+ g.P()
+
+ // ProtoMessage method.
+ g.P("func (*", m.GoIdent, ") ProtoMessage() {}")
+ g.P()
+
+ // ProtoReflect method.
+ genMessageReflectMethods(g, f, m)
+
+ // Descriptor method.
+ if m.genRawDescMethod {
+ var indexes []string
+ for i := 1; i < len(m.Location.Path); i += 2 {
+ indexes = append(indexes, strconv.Itoa(int(m.Location.Path[i])))
+ }
+ g.P("// Deprecated: Use ", m.GoIdent, ".ProtoReflect.Descriptor instead.")
+ g.P("func (*", m.GoIdent, ") Descriptor() ([]byte, []int) {")
+ g.P("return ", rawDescVarName(f), "GZIP(), []int{", strings.Join(indexes, ","), "}")
+ g.P("}")
+ g.P()
+ f.needRawDesc = true
+ }
+}
+
+func genMessageGetterMethods(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) {
+ for _, field := range m.Fields {
+ genNoInterfacePragma(g, m.isTracked)
+
+ // Getter for parent oneof.
+ if oneof := field.Oneof; oneof != nil && oneof.Fields[0] == field && !oneof.Desc.IsSynthetic() {
+ g.AnnotateSymbol(m.GoIdent.GoName+".Get"+oneof.GoName, protogen.Annotation{Location: oneof.Location})
+ g.P("func (m *", m.GoIdent.GoName, ") Get", oneof.GoName, "() ", oneofInterfaceName(oneof), " {")
+ g.P("if m != nil {")
+ g.P("return m.", oneof.GoName)
+ g.P("}")
+ g.P("return nil")
+ g.P("}")
+ g.P()
+ }
+
+ // Getter for message field.
+ goType, pointer := fieldGoType(g, f, field)
+ defaultValue := fieldDefaultValue(g, f, m, field)
+ g.AnnotateSymbol(m.GoIdent.GoName+".Get"+field.GoName, protogen.Annotation{Location: field.Location})
+ leadingComments := appendDeprecationSuffix("",
+ field.Desc.ParentFile(),
+ field.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated())
+ switch {
+ case field.Desc.IsWeak():
+ g.P(leadingComments, "func (x *", m.GoIdent, ") Get", field.GoName, "() ", protoPackage.Ident("Message"), "{")
+ g.P("var w ", protoimplPackage.Ident("WeakFields"))
+ g.P("if x != nil {")
+ g.P("w = x.", genid.WeakFields_goname)
+ if m.isTracked {
+ g.P("_ = x.", genid.WeakFieldPrefix_goname+field.GoName)
+ }
+ g.P("}")
+ g.P("return ", protoimplPackage.Ident("X"), ".GetWeak(w, ", field.Desc.Number(), ", ", strconv.Quote(string(field.Message.Desc.FullName())), ")")
+ g.P("}")
+ case field.Oneof != nil && !field.Oneof.Desc.IsSynthetic():
+ g.P(leadingComments, "func (x *", m.GoIdent, ") Get", field.GoName, "() ", goType, " {")
+ g.P("if x, ok := x.Get", field.Oneof.GoName, "().(*", field.GoIdent, "); ok {")
+ g.P("return x.", field.GoName)
+ g.P("}")
+ g.P("return ", defaultValue)
+ g.P("}")
+ default:
+ g.P(leadingComments, "func (x *", m.GoIdent, ") Get", field.GoName, "() ", goType, " {")
+ if !field.Desc.HasPresence() || defaultValue == "nil" {
+ g.P("if x != nil {")
+ } else {
+ g.P("if x != nil && x.", field.GoName, " != nil {")
+ }
+ star := ""
+ if pointer {
+ star = "*"
+ }
+ g.P("return ", star, " x.", field.GoName)
+ g.P("}")
+ g.P("return ", defaultValue)
+ g.P("}")
+ }
+ g.P()
+ }
+}
+
+func genMessageSetterMethods(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) {
+ for _, field := range m.Fields {
+ if !field.Desc.IsWeak() {
+ continue
+ }
+
+ genNoInterfacePragma(g, m.noInterface)
+
+ g.AnnotateSymbol(m.GoIdent.GoName+".Set"+field.GoName, protogen.Annotation{
+ Location: field.Location,
+ Semantic: descriptorpb.GeneratedCodeInfo_Annotation_SET.Enum(),
+ })
+ leadingComments := appendDeprecationSuffix("",
+ field.Desc.ParentFile(),
+ field.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated())
+ g.P(leadingComments, "func (x *", m.GoIdent, ") Set", field.GoName, "(v ", protoPackage.Ident("Message"), ") {")
+ g.P("var w *", protoimplPackage.Ident("WeakFields"))
+ g.P("if x != nil {")
+ g.P("w = &x.", genid.WeakFields_goname)
+ if m.isTracked {
+ g.P("_ = x.", genid.WeakFieldPrefix_goname+field.GoName)
+ }
+ g.P("}")
+ g.P(protoimplPackage.Ident("X"), ".SetWeak(w, ", field.Desc.Number(), ", ", strconv.Quote(string(field.Message.Desc.FullName())), ", v)")
+ g.P("}")
+ g.P()
+ }
+}
+
+// fieldGoType returns the Go type used for a field.
+//
+// If it returns pointer=true, the struct field is a pointer to the type.
+func fieldGoType(g *protogen.GeneratedFile, f *fileInfo, field *protogen.Field) (goType string, pointer bool) {
+ if field.Desc.IsWeak() {
+ return "struct{}", false
+ }
+
+ pointer = field.Desc.HasPresence()
+ switch field.Desc.Kind() {
+ case protoreflect.BoolKind:
+ goType = "bool"
+ case protoreflect.EnumKind:
+ goType = g.QualifiedGoIdent(field.Enum.GoIdent)
+ case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
+ goType = "int32"
+ case protoreflect.Uint32Kind, protoreflect.Fixed32Kind:
+ goType = "uint32"
+ case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
+ goType = "int64"
+ case protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
+ goType = "uint64"
+ case protoreflect.FloatKind:
+ goType = "float32"
+ case protoreflect.DoubleKind:
+ goType = "float64"
+ case protoreflect.StringKind:
+ goType = "string"
+ case protoreflect.BytesKind:
+ goType = "[]byte"
+ pointer = false // rely on nullability of slices for presence
+ case protoreflect.MessageKind, protoreflect.GroupKind:
+ goType = "*" + g.QualifiedGoIdent(field.Message.GoIdent)
+ pointer = false // pointer captured as part of the type
+ }
+ switch {
+ case field.Desc.IsList():
+ return "[]" + goType, false
+ case field.Desc.IsMap():
+ keyType, _ := fieldGoType(g, f, field.Message.Fields[0])
+ valType, _ := fieldGoType(g, f, field.Message.Fields[1])
+ return fmt.Sprintf("map[%v]%v", keyType, valType), false
+ }
+ return goType, pointer
+}
+
+func fieldProtobufTagValue(field *protogen.Field) string {
+ var enumName string
+ if field.Desc.Kind() == protoreflect.EnumKind {
+ enumName = protoimpl.X.LegacyEnumName(field.Enum.Desc)
+ }
+ return tag.Marshal(field.Desc, enumName)
+}
+
+func fieldDefaultValue(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo, field *protogen.Field) string {
+ if field.Desc.IsList() {
+ return "nil"
+ }
+ if field.Desc.HasDefault() {
+ defVarName := "Default_" + m.GoIdent.GoName + "_" + field.GoName
+ if field.Desc.Kind() == protoreflect.BytesKind {
+ return "append([]byte(nil), " + defVarName + "...)"
+ }
+ return defVarName
+ }
+ switch field.Desc.Kind() {
+ case protoreflect.BoolKind:
+ return "false"
+ case protoreflect.StringKind:
+ return `""`
+ case protoreflect.MessageKind, protoreflect.GroupKind, protoreflect.BytesKind:
+ return "nil"
+ case protoreflect.EnumKind:
+ val := field.Enum.Values[0]
+ if val.GoIdent.GoImportPath == f.GoImportPath {
+ return g.QualifiedGoIdent(val.GoIdent)
+ } else {
+ // If the enum value is declared in a different Go package,
+ // reference it by number since the name may not be correct.
+ // See https://github.com/golang/protobuf/issues/513.
+ return g.QualifiedGoIdent(field.Enum.GoIdent) + "(" + strconv.FormatInt(int64(val.Desc.Number()), 10) + ")"
+ }
+ default:
+ return "0"
+ }
+}
+
+func fieldJSONTagValue(field *protogen.Field) string {
+ return string(field.Desc.Name()) + ",omitempty"
+}
+
+func genExtensions(g *protogen.GeneratedFile, f *fileInfo) {
+ if len(f.allExtensions) == 0 {
+ return
+ }
+
+ g.P("var ", extensionTypesVarName(f), " = []", protoimplPackage.Ident("ExtensionInfo"), "{")
+ for _, x := range f.allExtensions {
+ g.P("{")
+ g.P("ExtendedType: (*", x.Extendee.GoIdent, ")(nil),")
+ goType, pointer := fieldGoType(g, f, x.Extension)
+ if pointer {
+ goType = "*" + goType
+ }
+ g.P("ExtensionType: (", goType, ")(nil),")
+ g.P("Field: ", x.Desc.Number(), ",")
+ g.P("Name: ", strconv.Quote(string(x.Desc.FullName())), ",")
+ g.P("Tag: ", strconv.Quote(fieldProtobufTagValue(x.Extension)), ",")
+ g.P("Filename: ", strconv.Quote(f.Desc.Path()), ",")
+ g.P("},")
+ }
+ g.P("}")
+ g.P()
+
+ // Group extensions by the target message.
+ var orderedTargets []protogen.GoIdent
+ allExtensionsByTarget := make(map[protogen.GoIdent][]*extensionInfo)
+ allExtensionsByPtr := make(map[*extensionInfo]int)
+ for i, x := range f.allExtensions {
+ target := x.Extendee.GoIdent
+ if len(allExtensionsByTarget[target]) == 0 {
+ orderedTargets = append(orderedTargets, target)
+ }
+ allExtensionsByTarget[target] = append(allExtensionsByTarget[target], x)
+ allExtensionsByPtr[x] = i
+ }
+ for _, target := range orderedTargets {
+ g.P("// Extension fields to ", target, ".")
+ g.P("var (")
+ for _, x := range allExtensionsByTarget[target] {
+ xd := x.Desc
+ typeName := xd.Kind().String()
+ switch xd.Kind() {
+ case protoreflect.EnumKind:
+ typeName = string(xd.Enum().FullName())
+ case protoreflect.MessageKind, protoreflect.GroupKind:
+ typeName = string(xd.Message().FullName())
+ }
+ fieldName := string(xd.Name())
+
+ leadingComments := x.Comments.Leading
+ if leadingComments != "" {
+ leadingComments += "\n"
+ }
+ leadingComments += protogen.Comments(fmt.Sprintf(" %v %v %v = %v;\n",
+ xd.Cardinality(), typeName, fieldName, xd.Number()))
+ leadingComments = appendDeprecationSuffix(leadingComments,
+ x.Desc.ParentFile(),
+ x.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated())
+ g.P(leadingComments,
+ "E_", x.GoIdent, " = &", extensionTypesVarName(f), "[", allExtensionsByPtr[x], "]",
+ trailingComment(x.Comments.Trailing))
+ }
+ g.P(")")
+ g.P()
+ }
+}
+
+// genMessageOneofWrapperTypes generates the oneof wrapper types and
+// associates the types with the parent message type.
+func genMessageOneofWrapperTypes(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) {
+ for _, oneof := range m.Oneofs {
+ if oneof.Desc.IsSynthetic() {
+ continue
+ }
+ ifName := oneofInterfaceName(oneof)
+ g.P("type ", ifName, " interface {")
+ g.P(ifName, "()")
+ g.P("}")
+ g.P()
+ for _, field := range oneof.Fields {
+ g.AnnotateSymbol(field.GoIdent.GoName, protogen.Annotation{Location: field.Location})
+ g.AnnotateSymbol(field.GoIdent.GoName+"."+field.GoName, protogen.Annotation{Location: field.Location})
+ g.P("type ", field.GoIdent, " struct {")
+ goType, _ := fieldGoType(g, f, field)
+ tags := structTags{
+ {"protobuf", fieldProtobufTagValue(field)},
+ }
+ if m.isTracked {
+ tags = append(tags, gotrackTags...)
+ }
+ leadingComments := appendDeprecationSuffix(field.Comments.Leading,
+ field.Desc.ParentFile(),
+ field.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated())
+ g.P(leadingComments,
+ field.GoName, " ", goType, tags,
+ trailingComment(field.Comments.Trailing))
+ g.P("}")
+ g.P()
+ }
+ for _, field := range oneof.Fields {
+ g.P("func (*", field.GoIdent, ") ", ifName, "() {}")
+ g.P()
+ }
+ }
+}
+
+// oneofInterfaceName returns the name of the interface type implemented by
+// the oneof field value types.
+func oneofInterfaceName(oneof *protogen.Oneof) string {
+ return "is" + oneof.GoIdent.GoName
+}
+
+// genNoInterfacePragma generates a standalone "nointerface" pragma to
+// decorate methods with field-tracking support.
+func genNoInterfacePragma(g *protogen.GeneratedFile, tracked bool) {
+ if tracked {
+ g.P("//go:nointerface")
+ g.P()
+ }
+}
+
+var gotrackTags = structTags{{"go", "track"}}
+
+// structTags is a data structure for build idiomatic Go struct tags.
+// Each [2]string is a key-value pair, where value is the unescaped string.
+//
+// Example: structTags{{"key", "value"}}.String() -> `key:"value"`
+type structTags [][2]string
+
+func (tags structTags) String() string {
+ if len(tags) == 0 {
+ return ""
+ }
+ var ss []string
+ for _, tag := range tags {
+ // NOTE: When quoting the value, we need to make sure the backtick
+ // character does not appear. Convert all cases to the escaped hex form.
+ key := tag[0]
+ val := strings.Replace(strconv.Quote(tag[1]), "`", `\x60`, -1)
+ ss = append(ss, fmt.Sprintf("%s:%s", key, val))
+ }
+ return "`" + strings.Join(ss, " ") + "`"
+}
+
+// appendDeprecationSuffix optionally appends a deprecation notice as a suffix.
+func appendDeprecationSuffix(prefix protogen.Comments, parentFile protoreflect.FileDescriptor, deprecated bool) protogen.Comments {
+ fileDeprecated := parentFile.Options().(*descriptorpb.FileOptions).GetDeprecated()
+ if !deprecated && !fileDeprecated {
+ return prefix
+ }
+ if prefix != "" {
+ prefix += "\n"
+ }
+ if fileDeprecated {
+ return prefix + " Deprecated: The entire proto file " + protogen.Comments(parentFile.Path()) + " is marked as deprecated.\n"
+ }
+ return prefix + " Deprecated: Marked as deprecated in " + protogen.Comments(parentFile.Path()) + ".\n"
+}
+
+// trailingComment is like protogen.Comments, but lacks a trailing newline.
+type trailingComment protogen.Comments
+
+func (c trailingComment) String() string {
+ s := strings.TrimSuffix(protogen.Comments(c).String(), "\n")
+ if strings.Contains(s, "\n") {
+ // We don't support multi-lined trailing comments as it is unclear
+ // how to best render them in the generated code.
+ return ""
+ }
+ return s
+}
diff --git a/vendor/google.golang.org/protobuf/cmd/protoc-gen-go/internal_gengo/opaque.go b/vendor/google.golang.org/protobuf/cmd/protoc-gen-go/internal_gengo/opaque.go
new file mode 100644
index 00000000000..dafa095f0e9
--- /dev/null
+++ b/vendor/google.golang.org/protobuf/cmd/protoc-gen-go/internal_gengo/opaque.go
@@ -0,0 +1,1306 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package internal_gengo
+
+import (
+ "fmt"
+ "strconv"
+ "strings"
+ "unicode"
+ "unicode/utf8"
+
+ "google.golang.org/protobuf/compiler/protogen"
+ "google.golang.org/protobuf/internal/genid"
+ "google.golang.org/protobuf/reflect/protoreflect"
+
+ "google.golang.org/protobuf/types/descriptorpb"
+)
+
+func opaqueGenMessageHook(g *protogen.GeneratedFile, f *fileInfo, message *messageInfo) bool {
+ opaqueGenMessage(g, f, message)
+ return true
+}
+
+func opaqueGenMessage(g *protogen.GeneratedFile, f *fileInfo, message *messageInfo) {
+ // Message type declaration.
+ g.AnnotateSymbol(message.GoIdent.GoName, protogen.Annotation{Location: message.Location})
+ leadingComments := appendDeprecationSuffix(message.Comments.Leading,
+ message.Desc.ParentFile(),
+ message.Desc.Options().(*descriptorpb.MessageOptions).GetDeprecated())
+ g.P(leadingComments,
+ "type ", message.GoIdent, " struct {")
+
+ sf := f.allMessageFieldsByPtr[message]
+ if sf == nil {
+ sf = new(structFields)
+ f.allMessageFieldsByPtr[message] = sf
+ }
+
+ var tags structTags
+ switch {
+ case message.isOpen():
+ tags = structTags{{"protogen", "open.v1"}}
+ case message.isHybrid():
+ tags = structTags{{"protogen", "hybrid.v1"}}
+ case message.isOpaque():
+ tags = structTags{{"protogen", "opaque.v1"}}
+ }
+
+ g.P(genid.State_goname, " ", protoimplPackage.Ident("MessageState"), tags)
+ sf.append(genid.State_goname)
+ fields := message.Fields
+ for _, field := range fields {
+ opaqueGenMessageField(g, f, message, field, sf)
+ }
+ opaqueGenMessageInternalFields(g, f, message, sf)
+ g.P("}")
+ g.P()
+
+ genMessageKnownFunctions(g, f, message)
+ genMessageDefaultDecls(g, f, message)
+ opaqueGenMessageMethods(g, f, message)
+ opaqueGenMessageBuilder(g, f, message)
+ opaqueGenOneofWrapperTypes(g, f, message)
+}
+
+// opaqueGenMessageField generates a struct field.
+func opaqueGenMessageField(g *protogen.GeneratedFile, f *fileInfo, message *messageInfo, field *protogen.Field, sf *structFields) {
+ if oneof := field.Oneof; oneof != nil && !oneof.Desc.IsSynthetic() {
+ // It would be a bit simpler to iterate over the oneofs below,
+ // but generating the field here keeps the contents of the Go
+ // struct in the same order as the contents of the source
+ // .proto file.
+ if field != oneof.Fields[0] {
+ return
+ }
+ opaqueGenOneofFields(g, f, message, oneof, sf)
+ return
+ }
+
+ goType, pointer := opaqueFieldGoType(g, f, message, field)
+ if pointer {
+ goType = "*" + goType
+ }
+ protobufTagValue := fieldProtobufTagValue(field)
+ jsonTagValue := fieldJSONTagValue(field)
+ if g.InternalStripForEditionsDiff() {
+ if field.Desc.ContainingOneof() != nil && field.Desc.ContainingOneof().IsSynthetic() {
+ protobufTagValue = strings.ReplaceAll(protobufTagValue, ",oneof", "")
+ }
+ protobufTagValue = strings.ReplaceAll(protobufTagValue, ",proto3", "")
+ }
+ tags := structTags{
+ {"protobuf", protobufTagValue},
+ {"json", jsonTagValue},
+ }
+ if field.Desc.IsMap() {
+ keyTagValue := fieldProtobufTagValue(field.Message.Fields[0])
+ valTagValue := fieldProtobufTagValue(field.Message.Fields[1])
+ keyTagValue = strings.ReplaceAll(keyTagValue, ",proto3", "")
+ valTagValue = strings.ReplaceAll(valTagValue, ",proto3", "")
+ tags = append(tags, structTags{
+ {"protobuf_key", keyTagValue},
+ {"protobuf_val", valTagValue},
+ }...)
+ }
+
+ name := field.GoName
+ if field.Desc.IsWeak() {
+ g.P("// Deprecated: Do not use. This will be deleted in the near future.")
+ name = genid.WeakFieldPrefix_goname + name
+ } else if message.isOpaque() {
+ name = "xxx_hidden_" + name
+ }
+
+ if message.isOpaque() && !field.Desc.IsWeak() {
+ g.P(name, " ", goType, tags)
+ sf.append(name)
+ if message.isTracked {
+ g.P("// Deprecated: Do not use. This will be deleted in the near future.")
+ g.P("XXX_ft_", field.GoName, " struct{} `go:\"track\"`")
+ sf.append("XXX_ft_" + field.GoName)
+ }
+ } else {
+ if message.isTracked {
+ tags = append(tags, structTags{
+ {"go", "track"},
+ }...)
+ }
+ g.AnnotateSymbol(field.Parent.GoIdent.GoName+"."+name, protogen.Annotation{Location: field.Location})
+ leadingComments := appendDeprecationSuffix(field.Comments.Leading,
+ field.Desc.ParentFile(),
+ field.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated())
+ g.P(leadingComments,
+ name, " ", goType, tags,
+ trailingComment(field.Comments.Trailing))
+ sf.append(name)
+ }
+}
+
+// opaqueGenOneofFields generates the message fields for a oneof.
+func opaqueGenOneofFields(g *protogen.GeneratedFile, f *fileInfo, message *messageInfo, oneof *protogen.Oneof, sf *structFields) {
+ tags := structTags{
+ {"protobuf_oneof", string(oneof.Desc.Name())},
+ }
+ if message.isTracked {
+ tags = append(tags, structTags{
+ {"go", "track"},
+ }...)
+ }
+
+ oneofName := opaqueOneofFieldName(oneof, message.isOpaque())
+ goType := opaqueOneofInterfaceName(oneof)
+
+ if message.isOpaque() {
+ g.P(oneofName, " ", goType, tags)
+ sf.append(oneofName)
+ if message.isTracked {
+ g.P("// Deprecated: Do not use. This will be deleted in the near future.")
+ g.P("XXX_ft_", oneof.GoName, " struct{} `go:\"track\"`")
+ sf.append("XXX_ft_" + oneof.GoName)
+ }
+ return
+ }
+
+ leadingComments := oneof.Comments.Leading
+ if leadingComments != "" {
+ leadingComments += "\n"
+ }
+ // NOTE(rsc): The extra \n here is working around #52605,
+ // making the comment be in Go 1.19 doc comment format
+ // even though it's not really a doc comment.
+ ss := []string{" Types that are valid to be assigned to ", oneofName, ":\n\n"}
+ for _, field := range oneof.Fields {
+ ss = append(ss, "\t*"+opaqueFieldOneofType(field, message.isOpaque()).GoName+"\n")
+ }
+ leadingComments += protogen.Comments(strings.Join(ss, ""))
+ g.P(leadingComments, oneofName, " ", goType, tags)
+ sf.append(oneofName)
+}
+
+// opaqueGenMessageInternalFields adds additional XXX_ fields to a message struct.
+func opaqueGenMessageInternalFields(g *protogen.GeneratedFile, f *fileInfo, message *messageInfo, sf *structFields) {
+ if opaqueNeedsPresenceArray(message) {
+ if opaqueNeedsLazyStruct(message) {
+ g.P("// Deprecated: Do not use. This will be deleted in the near future.")
+ g.P("XXX_lazyUnmarshalInfo ", protoimplPackage.Ident("LazyUnmarshalInfo"))
+ sf.append("XXX_lazyUnmarshalInfo")
+ }
+ g.P("XXX_raceDetectHookData ", protoimplPackage.Ident("RaceDetectHookData"))
+ sf.append("XXX_raceDetectHookData")
+
+ // Presence must be stored in a data type no larger than 32 bit:
+ //
+ // Presence used to be a uint64, accessed with atomic.LoadUint64, but it
+ // turns out that on 32-bit platforms like GOARCH=arm, the struct field
+ // was 32-bit aligned (not 64-bit aligned) and hence atomic accesses
+ // failed.
+ //
+ // The easiest solution was to switch to a uint32 on all platforms,
+ // which did not come with a performance penalty.
+ g.P("XXX_presence [", (opaqueNumPresenceFields(message)+31)/32, "]uint32")
+ sf.append("XXX_presence")
+ }
+ if message.hasWeak {
+ g.P(genid.WeakFields_goname, " ", protoimplPackage.Ident("WeakFields"))
+ sf.append(genid.WeakFields_goname)
+ }
+ if message.Desc.ExtensionRanges().Len() > 0 {
+ g.P(genid.ExtensionFields_goname, " ", protoimplPackage.Ident("ExtensionFields"))
+ sf.append(genid.ExtensionFields_goname)
+ }
+ g.P(genid.UnknownFields_goname, " ", protoimplPackage.Ident("UnknownFields"))
+ sf.append(genid.UnknownFields_goname)
+ g.P(genid.SizeCache_goname, " ", protoimplPackage.Ident("SizeCache"))
+ sf.append(genid.SizeCache_goname)
+}
+
+func opaqueGenMessageMethods(g *protogen.GeneratedFile, f *fileInfo, message *messageInfo) {
+ genMessageBaseMethods(g, f, message)
+
+ isRepeated := func(field *protogen.Field) bool {
+ return field.Desc.Cardinality() == protoreflect.Repeated
+ }
+
+ for _, field := range message.Fields {
+ if isFirstOneofField(field) && !message.isOpaque() {
+ opaqueGenGetOneof(g, f, message, field.Oneof)
+ }
+ opaqueGenGet(g, f, message, field)
+ }
+ for _, field := range message.Fields {
+ // For the plain open mode, we only have set methods for weak fields.
+ if message.isOpen() && !field.Desc.IsWeak() {
+ continue
+ }
+ opaqueGenSet(g, f, message, field)
+ }
+ for _, field := range message.Fields {
+ // Open API does not have Has method.
+ // Repeated (includes map) fields do not have Has method.
+ if message.isOpen() || isRepeated(field) {
+ continue
+ }
+
+ if !field.Desc.HasPresence() {
+ continue
+ }
+
+ if isFirstOneofField(field) {
+ opaqueGenHasOneof(g, f, message, field.Oneof)
+ }
+ opaqueGenHas(g, f, message, field)
+ }
+ for _, field := range message.Fields {
+ // Open API does not have Clear method.
+ // Repeated (includes map) fields do not have Clear method.
+ if message.isOpen() || isRepeated(field) {
+ continue
+ }
+ if !field.Desc.HasPresence() {
+ continue
+ }
+
+ if isFirstOneofField(field) {
+ opaqueGenClearOneof(g, f, message, field.Oneof)
+ }
+ opaqueGenClear(g, f, message, field)
+ }
+ // Plain open protos do not have which methods.
+ if !message.isOpen() {
+ opaqueGenWhichOneof(g, f, message)
+ }
+
+ if g.InternalStripForEditionsDiff() {
+ return
+ }
+}
+
+func isLazy(field *protogen.Field) bool {
+ // Prerequisite: field is of kind message
+ if field.Message == nil {
+ return false
+ }
+
+ // Was the field marked as [lazy = true] in the .proto file?
+ fopts := field.Desc.Options().(*descriptorpb.FieldOptions)
+ return fopts.GetLazy()
+}
+
+// opaqueGenGet generates a Get method for a field.
+func opaqueGenGet(g *protogen.GeneratedFile, f *fileInfo, message *messageInfo, field *protogen.Field) {
+ goType, pointer := opaqueFieldGoType(g, f, message, field)
+ getterName, bcName := field.MethodName("Get")
+
+ // If we need a backwards compatible getter name, we add it now.
+ if bcName != "" {
+ defer func() {
+ g.P("// Deprecated: Use ", getterName, " instead.")
+ g.P("func (x *", message.GoIdent, ") ", bcName, "() ", goType, " {")
+ g.P("return x.", getterName, "()")
+ g.P("}")
+ g.P()
+ }()
+ }
+
+ leadingComments := appendDeprecationSuffix("",
+ field.Desc.ParentFile(),
+ field.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated())
+ fieldtrackNoInterface(g, message.isTracked)
+ g.AnnotateSymbol(message.GoIdent.GoName+"."+getterName, protogen.Annotation{Location: field.Location})
+
+ // Weak field.
+ if field.Desc.IsWeak() {
+ g.P(leadingComments, "func (x *", message.GoIdent, ") ", getterName, "() ", protoPackage.Ident("Message"), "{")
+ g.P("var w ", protoimplPackage.Ident("WeakFields"))
+ g.P("if x != nil {")
+ g.P("w = x.", genid.WeakFields_goname)
+ if message.isTracked {
+ g.P("_ = x.", genid.WeakFieldPrefix_goname+field.GoName)
+ }
+ g.P("}")
+ g.P("return ", protoimplPackage.Ident("X"), ".GetWeak(w, ", field.Desc.Number(), ", ", strconv.Quote(string(field.Message.Desc.FullName())), ")")
+ g.P("}")
+ g.P()
+ return
+ }
+
+ defaultValue := fieldDefaultValue(g, f, message, field)
+
+ // Oneof field.
+ if oneof := field.Oneof; oneof != nil && !oneof.Desc.IsSynthetic() {
+ structPtr := "x"
+ g.P(leadingComments, "func (x *", message.GoIdent, ") ", getterName, "() ", goType, " {")
+ g.P("if x != nil {")
+ if message.isOpaque() && message.isTracked {
+ g.P("_ = ", structPtr, ".XXX_ft_", field.Oneof.GoName)
+ }
+ g.P("if x, ok := ", structPtr, ".", opaqueOneofFieldName(oneof, message.isOpaque()), ".(*", opaqueFieldOneofType(field, message.isOpaque()), "); ok {")
+ g.P("return x.", field.GoName)
+ g.P("}")
+ // End if m != nil {.
+ g.P("}")
+ g.P("return ", defaultValue)
+ g.P("}")
+ g.P()
+ return
+ }
+
+ // Non-oneof field for open type message.
+ if !message.isOpaque() {
+ g.P(leadingComments, "func (x *", message.GoIdent, ") ", getterName, "() ", goType, " {")
+ if !field.Desc.HasPresence() || defaultValue == "nil" {
+ g.P("if x != nil {")
+ } else {
+ g.P("if x != nil && x.", field.GoName, " != nil {")
+ }
+ star := ""
+ if pointer {
+ star = "*"
+ }
+ g.P("return ", star, " x.", field.GoName)
+ g.P("}")
+ g.P("return ", defaultValue)
+ g.P("}")
+ g.P()
+ return
+ }
+
+ // Non-oneof field for opaque type message.
+ g.P(leadingComments, "func (x *", message.GoIdent, ") ", getterName, "() ", goType, "{")
+ structPtr := "x"
+ g.P("if x != nil {")
+ if message.isTracked {
+ g.P("_ = ", structPtr, ".XXX_ft_", field.GoName)
+ }
+ if usePresence(message, field) {
+ pi := opaqueFieldPresenceIndex(field)
+ ai := pi / 32
+ // For
+ //
+ // 1. Message fields of lazy messages (unmarshalled lazily),
+ // 2. Fields with a default value,
+ // 3. Closed enums
+ //
+ // ...we check presence, but for other fields using presence, we can return
+ // whatever is there and it should be correct regardless of presence, which
+ // saves us an atomic operation.
+ isEnum := field.Desc.Kind() == protoreflect.EnumKind
+ usePresenceForRead := (isLazy(field)) ||
+ field.Desc.HasDefault() || isEnum
+
+ if usePresenceForRead {
+ g.P("if ", protoimplPackage.Ident("X"), ".Present(&(", structPtr, ".XXX_presence[", ai, "]),", pi, ") {")
+ }
+ // For lazy, check if pointer is nil and optionally unmarshal
+ if isLazy(field) {
+ // Since pointer to lazily unmarshaled sub-message can be written during a conceptual
+ // "read" operation, all read/write accesses to the pointer must be atomic. This
+ // function gets inlined on x86 as just a simple get and compare. Still need to make the
+ // slice accesses be atomic.
+ g.P("if ", protoimplPackage.Ident("X"), ".AtomicCheckPointerIsNil(&", structPtr, ".xxx_hidden_", field.GoName, ") {")
+ g.P(protoimplPackage.Ident("X"), ".UnmarshalField(", structPtr, ", ", field.Desc.Number(), ")")
+ g.P("}")
+ }
+ if field.Message == nil || field.Desc.IsMap() {
+ star := ""
+ if pointer {
+ star = "*"
+ }
+ if pointer {
+ g.P("if ", structPtr, ".xxx_hidden_", field.GoName, "!= nil {")
+ }
+
+ g.P("return ", star, structPtr, ".xxx_hidden_", field.GoName)
+ if pointer {
+ g.P("}")
+ g.P("return ", defaultValue)
+ }
+ } else {
+ // We need to do an atomic load of the msg pointer field, but cannot explicitly use
+ // unsafe pointers here. We load the value and store into rv, via protoimpl.Pointer,
+ // which is aliased to unsafe.Pointer in pointer_unsafe.go, but is aliased to
+ // interface{} in pointer_reflect.go
+ star := ""
+ if pointer {
+ star = "*"
+ }
+ if isLazy(field) {
+ g.P("var rv ", star, goType)
+ g.P(protoimplPackage.Ident("X"), ".AtomicLoadPointer(", protoimplPackage.Ident("Pointer"), "(&", structPtr, ".xxx_hidden_", field.GoName, "), ", protoimplPackage.Ident("Pointer"), "(&rv))")
+ g.P("return ", star, "rv")
+ } else {
+ if pointer {
+ g.P("if ", structPtr, ".xxx_hidden_", field.GoName, "!= nil {")
+ }
+ g.P("return ", star, structPtr, ".xxx_hidden_", field.GoName)
+ if pointer {
+ g.P("}")
+ }
+ }
+ }
+ if usePresenceForRead {
+ g.P("}")
+ }
+ } else if pointer {
+ g.P("if ", structPtr, ".xxx_hidden_", field.GoName, " != nil {")
+ g.P("return *", structPtr, ".xxx_hidden_", field.GoName)
+ g.P("}")
+ } else {
+ g.P("return ", structPtr, ".xxx_hidden_", field.GoName)
+ }
+ // End if m != nil {.
+ g.P("}")
+ g.P("return ", defaultValue)
+ g.P("}")
+ g.P()
+}
+
+// opaqueGenSet generates a Set method for a field.
+func opaqueGenSet(g *protogen.GeneratedFile, f *fileInfo, message *messageInfo, field *protogen.Field) {
+ goType, pointer := opaqueFieldGoType(g, f, message, field)
+ setterName, bcName := field.MethodName("Set")
+
+ // If we need a backwards compatible setter name, we add it now.
+ if bcName != "" {
+ defer func() {
+ g.P("// Deprecated: Use ", setterName, " instead.")
+ g.P("func (x *", message.GoIdent, ") ", bcName, "(v ", goType, ") {")
+ g.P("x.", setterName, "(v)")
+ g.P("}")
+ g.P()
+ }()
+ }
+
+ leadingComments := appendDeprecationSuffix("",
+ field.Desc.ParentFile(),
+ field.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated())
+ g.AnnotateSymbol(message.GoIdent.GoName+"."+setterName, protogen.Annotation{
+ Location: field.Location,
+ Semantic: descriptorpb.GeneratedCodeInfo_Annotation_SET.Enum(),
+ })
+ fieldtrackNoInterface(g, message.noInterface)
+
+ // Weak field.
+ if field.Desc.IsWeak() {
+ g.P(leadingComments, "func (x *", message.GoIdent, ") ", setterName, "(v ", protoPackage.Ident("Message"), ") {")
+ g.P("var w *", protoimplPackage.Ident("WeakFields"))
+ g.P("if x != nil {")
+ g.P("w = &x.", genid.WeakFields_goname)
+ if message.isTracked {
+ g.P("_ = x.", genid.WeakFieldPrefix_goname+field.GoName)
+ }
+ g.P("}")
+ g.P(protoimplPackage.Ident("X"), ".SetWeak(w, ", field.Desc.Number(), ", ", strconv.Quote(string(field.Message.Desc.FullName())), ", v)")
+ g.P("}")
+ g.P()
+ return
+ }
+
+ // Oneof field.
+ if oneof := field.Oneof; oneof != nil && !oneof.Desc.IsSynthetic() {
+ g.P(leadingComments, "func (x *", message.GoIdent, ") ", setterName, "(v ", goType, ") {")
+ structPtr := "x"
+ if message.isOpaque() && message.isTracked {
+ // Add access to zero field for tracking
+ g.P(structPtr, ".XXX_ft_", oneof.GoName, " = struct{}{}")
+ }
+ if field.Desc.Kind() == protoreflect.BytesKind {
+ g.P("if v == nil { v = []byte{} }")
+ } else if field.Message != nil {
+ g.P("if v == nil {")
+ g.P(structPtr, ".", opaqueOneofFieldName(oneof, message.isOpaque()), "= nil")
+ g.P("return")
+ g.P("}")
+ }
+ g.P(structPtr, ".", opaqueOneofFieldName(oneof, message.isOpaque()), "= &", opaqueFieldOneofType(field, message.isOpaque()), "{v}")
+ g.P("}")
+ g.P()
+ return
+ }
+
+ // Non-oneof field for open type message.
+ if !message.isOpaque() {
+ g.P(leadingComments, "func (x *", message.GoIdent, ") ", setterName, "(v ", goType, ") {")
+ if field.Desc.Cardinality() != protoreflect.Repeated && field.Desc.Kind() == protoreflect.BytesKind {
+ g.P("if v == nil { v = []byte{} }")
+ }
+ amp := ""
+ if pointer {
+ amp = "&"
+ }
+
+ v := "v"
+ g.P("x.", field.GoName, " = ", amp, v)
+ g.P("}")
+ g.P()
+ return
+ }
+
+ // Non-oneof field for opaque type message.
+ g.P(leadingComments, "func (x *", message.GoIdent, ") ", setterName, "(v ", goType, ") {")
+ structPtr := "x"
+ if message.isTracked {
+ // Add access to zero field for tracking
+ g.P(structPtr, ".XXX_ft_", field.GoName, " = struct{}{}")
+ }
+ if field.Desc.Cardinality() != protoreflect.Repeated && field.Desc.Kind() == protoreflect.BytesKind {
+ g.P("if v == nil { v = []byte{} }")
+ }
+ amp := ""
+ if pointer {
+ amp = "&"
+ }
+ if usePresence(message, field) {
+ pi := opaqueFieldPresenceIndex(field)
+ ai := pi / 32
+
+ if field.Message != nil && field.Desc.IsList() {
+ g.P("var sv *", goType)
+ g.P(protoimplPackage.Ident("X"), ".AtomicLoadPointer(", protoimplPackage.Ident("Pointer"), "(&", structPtr, ".xxx_hidden_", field.GoName, "), ", protoimplPackage.Ident("Pointer"), "(&sv))")
+ g.P("if sv == nil {")
+ g.P("sv = &", goType, "{}")
+ g.P(protoimplPackage.Ident("X"), ".AtomicInitializePointer(", protoimplPackage.Ident("Pointer"), "(&", structPtr, ".xxx_hidden_", field.GoName, "), ", protoimplPackage.Ident("Pointer"), "(&sv))")
+ g.P("}")
+ g.P("*sv = v")
+ g.P(protoimplPackage.Ident("X"), ".SetPresent(&(", structPtr, ".XXX_presence[", ai, "]),", pi, ",", opaqueNumPresenceFields(message), ")")
+ } else if field.Message != nil && !field.Desc.IsMap() {
+ // Only for lazy messages do we need to set pointers atomically
+ if isLazy(field) {
+ g.P(protoimplPackage.Ident("X"), ".AtomicSetPointer(&", structPtr, ".xxx_hidden_", field.GoName, ", ", amp, "v)")
+ } else {
+ g.P(structPtr, ".xxx_hidden_", field.GoName, " = ", amp, "v")
+ }
+ // When setting a message or slice of messages to a nil
+ // value, we must clear the presence bit, else we will
+ // later think that this field still needs to be lazily decoded.
+ g.P("if v == nil {")
+ g.P(protoimplPackage.Ident("X"), ".ClearPresent(&(", structPtr, ".XXX_presence[", ai, "]),", pi, ")")
+ g.P("} else {")
+ g.P(protoimplPackage.Ident("X"), ".SetPresent(&(", structPtr, ".XXX_presence[", ai, "]),", pi, ",", opaqueNumPresenceFields(message), ")")
+ g.P("}")
+ } else {
+ // Any map or non-message, possibly repeated, field that uses presence (proto2 only)
+ g.P(structPtr, ".xxx_hidden_", field.GoName, " = ", amp, "v")
+ // For consistent behaviour with lazy fields, non-map repeated fields should be cleared when
+ // the last object is removed. Maps are cleared when set to a nil map.
+ if field.Desc.Cardinality() == protoreflect.Repeated { // Includes maps.
+ g.P("if v == nil {")
+ g.P(protoimplPackage.Ident("X"), ".ClearPresent(&(", structPtr, ".XXX_presence[", ai, "]),", pi, ")")
+ g.P("} else {")
+ }
+ g.P(protoimplPackage.Ident("X"), ".SetPresent(&(", structPtr, ".XXX_presence[", ai, "]),", pi, ",", opaqueNumPresenceFields(message), ")")
+ if field.Desc.Cardinality() == protoreflect.Repeated {
+ g.P("}")
+ }
+ }
+ } else {
+ // proto3 non-lazy fields
+ g.P(structPtr, ".xxx_hidden_", field.GoName, " = ", amp, "v")
+ }
+ g.P("}")
+ g.P()
+}
+
+// usePresence returns true if the presence map should be used for a field. It
+// is always true for lazy message types. It is also true for all scalar fields.
+// repeated, map or message fields are not using the presence map.
+func usePresence(message *messageInfo, field *protogen.Field) bool {
+ if !message.isOpaque() || field.Desc.IsWeak() {
+ return false
+ }
+ return opaqueFieldNeedsPresenceArray(message, field)
+}
+
+func opaqueFieldNeedsPresenceArray(message *messageInfo, field *protogen.Field) bool {
+ // Non optional fields need presence if truly lazy field, i.e. are message fields.
+ if isLazy(field) {
+ return true
+ }
+ isNotOneof := field.Desc.ContainingOneof() == nil || field.Desc.ContainingOneof().IsSynthetic()
+ return field.Desc.HasPresence() && field.Message == nil && isNotOneof
+}
+
+// opaqueGenHas generates a Has method for a field.
+func opaqueGenHas(g *protogen.GeneratedFile, f *fileInfo, message *messageInfo, field *protogen.Field) {
+ hasserName, _ := field.MethodName("Has")
+
+ leadingComments := appendDeprecationSuffix("",
+ field.Desc.ParentFile(),
+ field.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated())
+ g.AnnotateSymbol(message.GoIdent.GoName+"."+hasserName, protogen.Annotation{Location: field.Location})
+ fieldtrackNoInterface(g, message.noInterface)
+
+ // Weak field.
+ if field.Desc.IsWeak() {
+ g.P(leadingComments, "func (x *", message.GoIdent, ") ", hasserName, "() bool {")
+ g.P("var w ", protoimplPackage.Ident("WeakFields"))
+ g.P("if x != nil {")
+ g.P("w = x.", genid.WeakFields_goname)
+ if message.isTracked {
+ g.P("_ = x.", genid.WeakFieldPrefix_goname+field.GoName)
+ }
+ g.P("}")
+ g.P("return ", protoimplPackage.Ident("X"), ".HasWeak(w, ", field.Desc.Number(), ")")
+ g.P("}")
+ g.P()
+ return
+ }
+
+ // Oneof field.
+ if oneof := field.Oneof; oneof != nil && !oneof.Desc.IsSynthetic() {
+ g.P(leadingComments, "func (x *", message.GoIdent, ") ", hasserName, "() bool {")
+ structPtr := "x"
+ g.P("if ", structPtr, " == nil {")
+ g.P("return false")
+ g.P("}")
+ if message.isOpaque() && message.isTracked {
+ // Add access to zero field for tracking
+ g.P("_ = ", structPtr, ".", "XXX_ft_", oneof.GoName)
+ }
+ g.P("_, ok := ", structPtr, ".", opaqueOneofFieldName(oneof, message.isOpaque()), ".(*", opaqueFieldOneofType(field, message.isOpaque()), ")")
+ g.P("return ok")
+ g.P("}")
+ g.P()
+ return
+ }
+
+ // Non-oneof field in open message.
+ if !message.isOpaque() {
+ g.P(leadingComments, "func (x *", message.GoIdent, ") ", hasserName, "() bool {")
+ g.P("if x == nil {")
+ g.P("return false")
+ g.P("}")
+ g.P("return ", "x.", field.GoName, " != nil")
+ g.P("}")
+ g.P()
+ return
+ }
+
+ // Non-oneof field in opaque message.
+ g.P(leadingComments, "func (x *", message.GoIdent, ") ", hasserName, "() bool {")
+ g.P("if x == nil {")
+ g.P("return false")
+ g.P("}")
+ structPtr := "x"
+ if message.isTracked {
+ // Add access to zero field for tracking
+ g.P("_ = ", structPtr, ".", "XXX_ft_"+field.GoName)
+ }
+ if usePresence(message, field) {
+ pi := opaqueFieldPresenceIndex(field)
+ ai := pi / 32
+ g.P("return ", protoimplPackage.Ident("X"), ".Present(&(", structPtr, ".XXX_presence[", ai, "]),", pi, ")")
+ } else {
+ // Has for proto3 message without presence
+ g.P("return ", structPtr, ".xxx_hidden_", field.GoName, " != nil")
+ }
+
+ g.P("}")
+ g.P()
+}
+
+// opaqueGenClear generates a Clear method for a field.
+func opaqueGenClear(g *protogen.GeneratedFile, f *fileInfo, message *messageInfo, field *protogen.Field) {
+ clearerName, _ := field.MethodName("Clear")
+ pi := opaqueFieldPresenceIndex(field)
+ ai := pi / 32
+
+ leadingComments := appendDeprecationSuffix("",
+ field.Desc.ParentFile(),
+ field.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated())
+ g.AnnotateSymbol(message.GoIdent.GoName+"."+clearerName, protogen.Annotation{
+ Location: field.Location,
+ Semantic: descriptorpb.GeneratedCodeInfo_Annotation_SET.Enum(),
+ })
+ fieldtrackNoInterface(g, message.noInterface)
+
+ // Weak field.
+ if field.Desc.IsWeak() {
+ g.P(leadingComments, "func (x *", message.GoIdent, ") ", clearerName, "() {")
+ g.P("var w *", protoimplPackage.Ident("WeakFields"))
+ g.P("if x != nil {")
+ g.P("w = &x.", genid.WeakFields_goname)
+ if message.isTracked {
+ g.P("_ = x.", genid.WeakFieldPrefix_goname+field.GoName)
+ }
+ g.P("}")
+ g.P(protoimplPackage.Ident("X"), ".ClearWeak(w, ", field.Desc.Number(), ")")
+ g.P("}")
+ g.P()
+ return
+ }
+
+ // Oneof field.
+ if oneof := field.Oneof; oneof != nil && !oneof.Desc.IsSynthetic() {
+ g.P(leadingComments, "func (x *", message.GoIdent, ") ", clearerName, "() {")
+ structPtr := "x"
+ if message.isOpaque() && message.isTracked {
+ // Add access to zero field for tracking
+ g.P(structPtr, ".", "XXX_ft_", oneof.GoName, " = struct{}{}")
+ }
+ g.P("if _, ok := ", structPtr, ".", opaqueOneofFieldName(oneof, message.isOpaque()), ".(*", opaqueFieldOneofType(field, message.isOpaque()), "); ok {")
+ g.P(structPtr, ".", opaqueOneofFieldName(oneof, message.isOpaque()), " = nil")
+ g.P("}")
+ g.P("}")
+ g.P()
+ return
+ }
+
+ // Non-oneof field in open message.
+ if !message.isOpaque() {
+ g.P(leadingComments, "func (x *", message.GoIdent, ") ", clearerName, "() {")
+ g.P("x.", field.GoName, " = nil")
+ g.P("}")
+ g.P()
+ return
+ }
+
+ // Non-oneof field in opaque message.
+ g.P(leadingComments, "func (x *", message.GoIdent, ") ", clearerName, "() {")
+ structPtr := "x"
+ if message.isTracked {
+ // Add access to zero field for tracking
+ g.P(structPtr, ".", "XXX_ft_", field.GoName, " = struct{}{}")
+ }
+
+ if usePresence(message, field) {
+ g.P(protoimplPackage.Ident("X"), ".ClearPresent(&(", structPtr, ".XXX_presence[", ai, "]),", pi, ")")
+ }
+
+ // Avoid needing to read the presence value in Get by ensuring that we set the
+ // right zero value (unless we have an explicit default, in which case we
+ // revert to presence checking in Get). Rationale: Get is called far more
+ // frequently than Clear, it should be as lean as possible.
+ zv := opaqueZeroValueForField(g, field)
+ // For lazy, (repeated) message fields are unmarshalled lazily. Hence they are
+ // assigned atomically in Getters (which are allowed to be called
+ // concurrently). Due to this, historically, the code generator would use
+ // atomic operations everywhere.
+ //
+ // TODO(b/291588964): Stop using atomic operations for non-presence fields in
+ // write calls (Set/Clear). Concurrent reads are allowed,
+ // but concurrent read/write or write/write are not, we
+ // shouldn't cater to it.
+ if isLazy(field) {
+ goType, _ := opaqueFieldGoType(g, f, message, field)
+ g.P(protoimplPackage.Ident("X"), ".AtomicSetPointer(&", structPtr, ".xxx_hidden_", field.GoName, ",(", goType, ")(", zv, "))")
+ } else if !field.Desc.HasDefault() {
+ g.P(structPtr, ".xxx_hidden_", field.GoName, " = ", zv)
+ }
+ g.P("}")
+ g.P()
+}
+
+// Determine what value to set a cleared field to.
+func opaqueZeroValueForField(g *protogen.GeneratedFile, field *protogen.Field) string {
+ if field.Desc.Cardinality() == protoreflect.Repeated {
+ return "nil"
+ }
+ switch field.Desc.Kind() {
+ case protoreflect.StringKind:
+ return "nil"
+ case protoreflect.MessageKind, protoreflect.GroupKind, protoreflect.BytesKind:
+ return "nil"
+ case protoreflect.BoolKind:
+ return "false"
+ case protoreflect.EnumKind:
+ return g.QualifiedGoIdent(field.Enum.Values[0].GoIdent)
+ default:
+ return "0"
+ }
+}
+
+// opaqueGenGetOneof generates a Get function for a oneof union.
+func opaqueGenGetOneof(g *protogen.GeneratedFile, f *fileInfo, message *messageInfo, oneof *protogen.Oneof) {
+ ifName := opaqueOneofInterfaceName(oneof)
+ g.AnnotateSymbol(message.GoIdent.GoName+".Get"+oneof.GoName, protogen.Annotation{Location: oneof.Location})
+ fieldtrackNoInterface(g, message.isTracked)
+ g.P("func (x *", message.GoIdent.GoName, ") Get", oneof.GoName, "() ", ifName, " {")
+ g.P("if x != nil {")
+ g.P("return x.", opaqueOneofFieldName(oneof, message.isOpaque()))
+ g.P("}")
+ g.P("return nil")
+ g.P("}")
+ g.P()
+}
+
+// opaqueGenHasOneof generates a Has function for a oneof union.
+func opaqueGenHasOneof(g *protogen.GeneratedFile, f *fileInfo, message *messageInfo, oneof *protogen.Oneof) {
+ fieldtrackNoInterface(g, message.noInterface)
+ hasserName := oneof.MethodName("Has")
+ g.P("func (x *", message.GoIdent, ") ", hasserName, "() bool {")
+ g.P("if x == nil {")
+ g.P("return false")
+ g.P("}")
+ structPtr := "x"
+ if message.isOpaque() && message.isTracked {
+ // Add access to zero field for tracking
+ g.P("_ = ", structPtr, ".XXX_ft_", oneof.GoName)
+ }
+ g.P("return ", structPtr, ".", opaqueOneofFieldName(oneof, message.isOpaque()), " != nil")
+ g.P("}")
+ g.P()
+}
+
+// opaqueGenClearOneof generates a Clear function for a oneof union.
+func opaqueGenClearOneof(g *protogen.GeneratedFile, f *fileInfo, message *messageInfo, oneof *protogen.Oneof) {
+ fieldtrackNoInterface(g, message.noInterface)
+ clearerName := oneof.MethodName("Clear")
+ g.P("func (x *", message.GoIdent, ") ", clearerName, "() {")
+ structPtr := "x"
+ if message.isOpaque() && message.isTracked {
+ // Add access to zero field for tracking
+ g.P(structPtr, ".", "XXX_ft_", oneof.GoName, " = struct{}{}")
+ }
+ g.P(structPtr, ".", opaqueOneofFieldName(oneof, message.isOpaque()), " = nil")
+ g.P("}")
+ g.P()
+}
+
+// opaqueGenWhichOneof generates the Which method for each oneof union, as well as the case values for each member
+// of that union.
+func opaqueGenWhichOneof(g *protogen.GeneratedFile, f *fileInfo, message *messageInfo) {
+ // Go through the message, and for each field that is the first of a oneof field, dig down
+ // and generate constants + the actual which method.
+ oneofIndex := 0
+ for _, field := range message.Fields {
+ if oneof := field.Oneof; oneof != nil {
+ if !isFirstOneofField(field) {
+ continue
+ }
+ caseType := opaqueOneofCaseTypeName(oneof)
+ g.P("const ", message.GoIdent.GoName, "_", oneof.GoName, "_not_set_case ", caseType, " = ", 0)
+ for _, f := range oneof.Fields {
+ g.P("const ", message.GoIdent.GoName, "_", f.GoName, "_case ", caseType, " = ", f.Desc.Number())
+ }
+ fieldtrackNoInterface(g, message.noInterface)
+ whicherName := oneof.MethodName("Which")
+ g.P("func (x *", message.GoIdent, ") ", whicherName, "() ", caseType, " {")
+ g.P("if x == nil {")
+ g.P("return ", message.GoIdent.GoName, "_", oneof.GoName, "_not_set_case ")
+ g.P("}")
+ g.P("switch x.", opaqueOneofFieldName(oneof, message.isOpaque()), ".(type) {")
+ for _, f := range oneof.Fields {
+ g.P("case *", opaqueFieldOneofType(f, message.isOpaque()), ":")
+ g.P("return ", message.GoIdent.GoName, "_", f.GoName, "_case")
+ }
+ g.P("default", ":")
+ g.P("return ", message.GoIdent.GoName, "_", oneof.GoName, "_not_set_case ")
+ g.P("}")
+ g.P("}")
+ g.P()
+ oneofIndex++
+ }
+ }
+}
+
+func opaqueNeedsPresenceArray(message *messageInfo) bool {
+ if !message.isOpaque() {
+ return false
+ }
+ for _, field := range message.Fields {
+ if opaqueFieldNeedsPresenceArray(message, field) {
+ return true
+ }
+ }
+ return false
+}
+
+func opaqueNeedsLazyStruct(message *messageInfo) bool {
+ for _, field := range message.Fields {
+ if isLazy(field) {
+ return true
+ }
+ }
+ return false
+}
+
+// opaqueGenMessageBuilder generates a Builder type for a message.
+func opaqueGenMessageBuilder(g *protogen.GeneratedFile, f *fileInfo, message *messageInfo) {
+ if message.isOpen() {
+ return
+ }
+ // Builder type.
+ bName := g.QualifiedGoIdent(message.GoIdent) + genid.BuilderSuffix_goname
+ g.AnnotateSymbol(message.GoIdent.GoName+genid.BuilderSuffix_goname, protogen.Annotation{Location: message.Location})
+
+ leadingComments := appendDeprecationSuffix("",
+ message.Desc.ParentFile(),
+ message.Desc.Options().(*descriptorpb.MessageOptions).GetDeprecated())
+ g.P(leadingComments, "type ", bName, " struct {")
+ g.P("_ [0]func() // Prevents comparability and use of unkeyed literals for the builder.")
+ g.P()
+ for _, field := range message.Fields {
+ oneof := field.Oneof
+ if oneof == nil && field.Desc.IsWeak() {
+ continue
+ }
+
+ goType, pointer := opaqueBuilderFieldGoType(g, f, message, field)
+ if pointer {
+ goType = "*" + goType
+ } else if oneof != nil && fieldDefaultValue(g, f, message, field) != "nil" {
+ goType = "*" + goType
+ }
+ // Track all non-oneof fields. Note: synthetic oneofs are an
+ // implementation detail of proto3 optional fields:
+ // go/proto-proposals/proto3-presence.md, which should be tracked.
+ tag := ""
+ if (oneof == nil || oneof.Desc.IsSynthetic()) && message.isTracked {
+ tag = "`go:\"track\"`"
+ }
+ if oneof != nil && oneof.Fields[0] == field && !oneof.Desc.IsSynthetic() {
+ if oneof.Comments.Leading != "" {
+ g.P(oneof.Comments.Leading)
+ g.P()
+ }
+ g.P("// Fields of oneof ", opaqueOneofFieldName(oneof, message.isOpaque()), ":")
+ }
+ g.AnnotateSymbol(field.Parent.GoIdent.GoName+genid.BuilderSuffix_goname+"."+field.BuilderFieldName(), protogen.Annotation{Location: field.Location})
+ leadingComments := appendDeprecationSuffix(field.Comments.Leading,
+ field.Desc.ParentFile(),
+ field.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated())
+ g.P(leadingComments,
+ field.BuilderFieldName(), " ", goType, " ", tag)
+ if oneof != nil && oneof.Fields[len(oneof.Fields)-1] == field && !oneof.Desc.IsSynthetic() {
+ g.P("// -- end of ", opaqueOneofFieldName(oneof, message.isOpaque()))
+ }
+ }
+ g.P("}")
+ g.P()
+
+ opaqueGenBuildMethod(g, f, message, bName)
+}
+
+// opaqueGenBuildMethod generates the actual Build method for the builder
+func opaqueGenBuildMethod(g *protogen.GeneratedFile, f *fileInfo, message *messageInfo, bName string) {
+ // Build method on the builder type.
+ fieldtrackNoInterface(g, message.noInterface)
+ g.P("func (b0 ", bName, ") Build() *", message.GoIdent, " {")
+ g.P("m0 := &", message.GoIdent, "{}")
+
+ if message.isTracked {
+ // Redeclare the builder and message types as local
+ // defined types, so that field tracking records the
+ // field uses against these types instead of the
+ // original struct types.
+ //
+ // TODO: Actually redeclare the struct types
+ // without `go:"track"` tags?
+ g.P("type (notrackB ", bName, "; notrackM ", message.GoIdent, ")")
+ g.P("b, x := (*notrackB)(&b0), (*notrackM)(m0)")
+ } else {
+ g.P("b, x := &b0, m0")
+ }
+ g.P("_, _ = b, x")
+
+ for _, field := range message.Fields {
+ oneof := field.Oneof
+ if oneof == nil && field.Desc.IsWeak() {
+ continue
+ }
+ if oneof != nil && !oneof.Desc.IsSynthetic() {
+ qual := ""
+ if fieldDefaultValue(g, f, message, field) != "nil" {
+ qual = "*"
+ }
+
+ g.P("if b.", field.BuilderFieldName(), " != nil {")
+ oneofName := opaqueOneofFieldName(oneof, message.isOpaque())
+ oneofType := opaqueFieldOneofType(field, message.isOpaque())
+ g.P("x.", oneofName, " = &", oneofType, "{", qual, "b.", field.BuilderFieldName(), "}")
+ g.P("}")
+ } else { // proto3 optional ends up here (synthetic oneof)
+ qual := ""
+ _, pointer := opaqueBuilderFieldGoType(g, f, message, field)
+ if pointer && message.isOpaque() && !field.Desc.IsList() && field.Desc.Kind() != protoreflect.StringKind {
+ qual = "*"
+ } else if message.isOpaque() && field.Desc.IsList() && field.Desc.Message() != nil {
+ qual = "&"
+ }
+ presence := usePresence(message, field)
+ if presence {
+ g.P("if b.", field.BuilderFieldName(), " != nil {")
+ }
+ if presence {
+ pi := opaqueFieldPresenceIndex(field)
+ g.P(protoimplPackage.Ident("X"), ".SetPresentNonAtomic(&(x.XXX_presence[", pi/32, "]),", pi, ",", opaqueNumPresenceFields(message), ")")
+ }
+ goName := field.GoName
+ if message.isOpaque() {
+ goName = "xxx_hidden_" + goName
+ }
+ g.P("x.", goName, " = ", qual, "b.", field.BuilderFieldName())
+ if presence {
+ g.P("}")
+ }
+ }
+ }
+
+ g.P("return m0")
+ g.P("}")
+ g.P()
+}
+
+// opaqueBuilderFieldGoType does the same as opaqueFieldGoType, but corrects for
+// types that are different in a builder
+func opaqueBuilderFieldGoType(g *protogen.GeneratedFile, f *fileInfo, message *messageInfo, field *protogen.Field) (goType string, pointer bool) {
+ goType, pointer = opaqueFieldGoType(g, f, message, field)
+ kind := field.Desc.Kind()
+
+ // Use []T instead of *[]T for opaque repeated lists.
+ if message.isOpaque() && field.Desc.IsList() {
+ pointer = false
+ }
+
+ // Use *T for optional fields.
+ optional := field.Desc.HasPresence()
+ if optional &&
+ kind != protoreflect.GroupKind &&
+ kind != protoreflect.MessageKind &&
+ kind != protoreflect.BytesKind &&
+ field.Desc.Cardinality() != protoreflect.Repeated {
+ pointer = true
+ }
+
+ return goType, pointer
+}
+
+func opaqueGenOneofWrapperTypes(g *protogen.GeneratedFile, f *fileInfo, message *messageInfo) {
+ // TODO: We should avoid generating these wrapper types in pure-opaque mode.
+ if !message.isOpen() {
+ for _, oneof := range message.Oneofs {
+ if oneof.Desc.IsSynthetic() {
+ continue
+ }
+ caseTypeName := opaqueOneofCaseTypeName(oneof)
+ g.P("type ", caseTypeName, " ", protoreflectPackage.Ident("FieldNumber"))
+ g.P("")
+
+ idx := f.allMessagesByPtr[message]
+ typesVar := messageTypesVarName(f)
+ g.P("func (x ", caseTypeName, ") String() string {")
+ g.P("md := ", typesVar, "[", idx, "].Descriptor()")
+ g.P("if x == 0 {")
+ g.P(`return "not set"`)
+ g.P("}")
+ g.P("return ", protoimplPackage.Ident("X"), ".MessageFieldStringOf(md, ", protoreflectPackage.Ident("FieldNumber"), "(x))")
+ g.P("}")
+ g.P()
+ }
+ }
+ for _, oneof := range message.Oneofs {
+ if oneof.Desc.IsSynthetic() {
+ continue
+ }
+ ifName := opaqueOneofInterfaceName(oneof)
+ g.P("type ", ifName, " interface {")
+ g.P(ifName, "()")
+ g.P("}")
+ g.P()
+ for _, field := range oneof.Fields {
+ name := opaqueFieldOneofType(field, message.isOpaque())
+ g.AnnotateSymbol(name.GoName, protogen.Annotation{Location: field.Location})
+ g.AnnotateSymbol(name.GoName+"."+field.GoName, protogen.Annotation{Location: field.Location})
+ g.P("type ", name, " struct {")
+ goType, _ := opaqueFieldGoType(g, f, message, field)
+ protobufTagValue := fieldProtobufTagValue(field)
+ if g.InternalStripForEditionsDiff() {
+ protobufTagValue = strings.ReplaceAll(protobufTagValue, ",proto3", "")
+ }
+ tags := structTags{
+ {"protobuf", protobufTagValue},
+ }
+ leadingComments := appendDeprecationSuffix(field.Comments.Leading,
+ field.Desc.ParentFile(),
+ field.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated())
+ g.P(leadingComments,
+ field.GoName, " ", goType, tags,
+ trailingComment(field.Comments.Trailing))
+ g.P("}")
+ g.P()
+ }
+ for _, field := range oneof.Fields {
+ g.P("func (*", opaqueFieldOneofType(field, message.isOpaque()), ") ", ifName, "() {}")
+ g.P()
+ }
+ }
+}
+
+// opaqueFieldGoType returns the Go type used for a field.
+//
+// If it returns pointer=true, the struct field is a pointer to the type.
+func opaqueFieldGoType(g *protogen.GeneratedFile, f *fileInfo, message *messageInfo, field *protogen.Field) (goType string, pointer bool) {
+ if field.Desc.IsWeak() {
+ return "struct{}", false
+ }
+
+ pointer = true
+ switch field.Desc.Kind() {
+ case protoreflect.BoolKind:
+ goType = "bool"
+ case protoreflect.EnumKind:
+ goType = g.QualifiedGoIdent(field.Enum.GoIdent)
+ case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
+ goType = "int32"
+ case protoreflect.Uint32Kind, protoreflect.Fixed32Kind:
+ goType = "uint32"
+ case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
+ goType = "int64"
+ case protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
+ goType = "uint64"
+ case protoreflect.FloatKind:
+ goType = "float32"
+ case protoreflect.DoubleKind:
+ goType = "float64"
+ case protoreflect.StringKind:
+ goType = "string"
+ case protoreflect.BytesKind:
+ goType = "[]byte"
+ pointer = false
+ case protoreflect.MessageKind, protoreflect.GroupKind:
+ goType = opaqueMessageFieldGoType(g, f, field, message.isOpaque())
+ pointer = false
+ }
+ switch {
+ case field.Desc.IsList():
+ goType = "[]" + goType
+ pointer = false
+ case field.Desc.IsMap():
+ keyType, _ := opaqueFieldGoType(g, f, message, field.Message.Fields[0])
+ valType, _ := opaqueFieldGoType(g, f, message, field.Message.Fields[1])
+ return fmt.Sprintf("map[%v]%v", keyType, valType), false
+ }
+
+ // Extension fields always have pointer type, even when defined in a proto3 file.
+ if !field.Desc.IsExtension() && !field.Desc.HasPresence() {
+ pointer = false
+ }
+
+ if message.isOpaque() {
+ switch {
+ case field.Desc.IsList() && field.Desc.Message() != nil:
+ pointer = true
+ case !field.Desc.IsList() && field.Desc.Kind() == protoreflect.StringKind:
+ switch {
+ case field.Desc.HasPresence():
+ pointer = true
+ default:
+ pointer = false
+ }
+ default:
+ pointer = false
+ }
+ }
+
+ return goType, pointer
+}
+
+func opaqueMessageFieldGoType(g *protogen.GeneratedFile, f *fileInfo, field *protogen.Field, isOpaque bool) string {
+ return "*" + g.QualifiedGoIdent(field.Message.GoIdent)
+}
+
+// opaqueFieldPresenceIndex returns the index to pass to presence functions.
+//
+// TODO: field.Desc.Index() would be simpler, and would give space to record the presence of oneof fields.
+func opaqueFieldPresenceIndex(field *protogen.Field) int {
+ structFieldIndex := 0
+ for _, f := range field.Parent.Fields {
+ if field == f {
+ break
+ }
+ if f.Oneof == nil || isLastOneofField(f) {
+ structFieldIndex++
+ }
+ }
+ return structFieldIndex
+}
+
+// opaqueNumPresenceFields returns the number of fields that may be passed to presence functions.
+//
+// Since all fields in a oneof currently share a single entry in the presence bitmap,
+// this is not just len(message.Fields).
+func opaqueNumPresenceFields(message *messageInfo) int {
+ if len(message.Fields) == 0 {
+ return 0
+ }
+ return opaqueFieldPresenceIndex(message.Fields[len(message.Fields)-1]) + 1
+}
+
+func fieldtrackNoInterface(g *protogen.GeneratedFile, isTracked bool) {
+ if isTracked {
+ g.P("//go:nointerface")
+ }
+}
+
+// opaqueOneofFieldName returns the name of the struct field that holds
+// the value of a oneof.
+func opaqueOneofFieldName(oneof *protogen.Oneof, isOpaque bool) string {
+ if isOpaque {
+ return "xxx_hidden_" + oneof.GoName
+ }
+ return oneof.GoName
+}
+
+func opaqueFieldOneofType(field *protogen.Field, isOpaque bool) protogen.GoIdent {
+ ident := protogen.GoIdent{
+ GoImportPath: field.Parent.GoIdent.GoImportPath,
+ GoName: field.Parent.GoIdent.GoName + "_" + field.GoName,
+ }
+ // Check for collisions with nested messages or enums.
+ //
+ // This conflict resolution is incomplete: Among other things, it
+ // does not consider collisions with other oneof field types.
+Loop:
+ for {
+ for _, message := range field.Parent.Messages {
+ if message.GoIdent == ident {
+ ident.GoName += "_"
+ continue Loop
+ }
+ }
+ for _, enum := range field.Parent.Enums {
+ if enum.GoIdent == ident {
+ ident.GoName += "_"
+ continue Loop
+ }
+ }
+ return unexportIdent(ident, isOpaque)
+ }
+}
+
+// unexportIdent turns id into its unexported version (by lower-casing), but
+// only if isOpaque is set. This function is used for oneof wrapper types,
+// which remain exported in the non-opaque API for now.
+func unexportIdent(id protogen.GoIdent, isOpaque bool) protogen.GoIdent {
+ if !isOpaque {
+ return id
+ }
+ r, sz := utf8.DecodeRuneInString(id.GoName)
+ if r == utf8.RuneError {
+ panic(fmt.Sprintf("Go identifier %q contains invalid UTF8?!", id.GoName))
+ }
+ r = unicode.ToLower(r)
+ id.GoName = string(r) + id.GoName[sz:]
+ return id
+}
+
+func opaqueOneofInterfaceName(oneof *protogen.Oneof) string {
+ return fmt.Sprintf("is%s_%s", oneof.Parent.GoIdent.GoName, oneof.GoName)
+}
+func opaqueOneofCaseTypeName(oneof *protogen.Oneof) string {
+ return fmt.Sprintf("case_%s_%s", oneof.Parent.GoIdent.GoName, oneof.GoName)
+}
+
+// isFirstOneofField reports whether this is the first field in a oneof.
+func isFirstOneofField(field *protogen.Field) bool {
+ return field.Oneof != nil && field == field.Oneof.Fields[0] && !field.Oneof.Desc.IsSynthetic()
+}
+
+// isLastOneofField returns true if this is the last field in a oneof.
+func isLastOneofField(field *protogen.Field) bool {
+ return field.Oneof != nil && field == field.Oneof.Fields[len(field.Oneof.Fields)-1]
+}
diff --git a/vendor/google.golang.org/protobuf/cmd/protoc-gen-go/internal_gengo/reflect.go b/vendor/google.golang.org/protobuf/cmd/protoc-gen-go/internal_gengo/reflect.go
new file mode 100644
index 00000000000..a3f91a85c44
--- /dev/null
+++ b/vendor/google.golang.org/protobuf/cmd/protoc-gen-go/internal_gengo/reflect.go
@@ -0,0 +1,351 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package internal_gengo
+
+import (
+ "fmt"
+ "math"
+ "strings"
+ "unicode/utf8"
+
+ "google.golang.org/protobuf/compiler/protogen"
+ "google.golang.org/protobuf/proto"
+ "google.golang.org/protobuf/reflect/protopath"
+ "google.golang.org/protobuf/reflect/protorange"
+ "google.golang.org/protobuf/reflect/protoreflect"
+
+ "google.golang.org/protobuf/types/descriptorpb"
+)
+
+func genReflectFileDescriptor(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo) {
+ g.P("var ", f.GoDescriptorIdent, " ", protoreflectPackage.Ident("FileDescriptor"))
+ g.P()
+
+ genFileDescriptor(gen, g, f)
+ if len(f.allEnums) > 0 {
+ g.P("var ", enumTypesVarName(f), " = make([]", protoimplPackage.Ident("EnumInfo"), ",", len(f.allEnums), ")")
+ }
+ if len(f.allMessages) > 0 {
+ g.P("var ", messageTypesVarName(f), " = make([]", protoimplPackage.Ident("MessageInfo"), ",", len(f.allMessages), ")")
+ }
+
+ // Generate a unique list of Go types for all declarations and dependencies,
+ // and the associated index into the type list for all dependencies.
+ var goTypes []string
+ var depIdxs []string
+ seen := map[protoreflect.FullName]int{}
+ genDep := func(name protoreflect.FullName, depSource string) {
+ if depSource != "" {
+ line := fmt.Sprintf("%d, // %d: %s -> %s", seen[name], len(depIdxs), depSource, name)
+ depIdxs = append(depIdxs, line)
+ }
+ }
+ genEnum := func(e *protogen.Enum, depSource string) {
+ if e != nil {
+ name := e.Desc.FullName()
+ if _, ok := seen[name]; !ok {
+ line := fmt.Sprintf("(%s)(0), // %d: %s", g.QualifiedGoIdent(e.GoIdent), len(goTypes), name)
+ goTypes = append(goTypes, line)
+ seen[name] = len(seen)
+ }
+ if depSource != "" {
+ genDep(name, depSource)
+ }
+ }
+ }
+ genMessage := func(m *protogen.Message, depSource string) {
+ if m != nil {
+ name := m.Desc.FullName()
+ if _, ok := seen[name]; !ok {
+ line := fmt.Sprintf("(*%s)(nil), // %d: %s", g.QualifiedGoIdent(m.GoIdent), len(goTypes), name)
+ if m.Desc.IsMapEntry() {
+ // Map entry messages have no associated Go type.
+ line = fmt.Sprintf("nil, // %d: %s", len(goTypes), name)
+ }
+ goTypes = append(goTypes, line)
+ seen[name] = len(seen)
+ }
+ if depSource != "" {
+ genDep(name, depSource)
+ }
+ }
+ }
+
+ // This ordering is significant.
+ // See filetype.TypeBuilder.DependencyIndexes.
+ type offsetEntry struct {
+ start int
+ name string
+ }
+ var depOffsets []offsetEntry
+ for _, enum := range f.allEnums {
+ genEnum(enum.Enum, "")
+ }
+ for _, message := range f.allMessages {
+ genMessage(message.Message, "")
+ }
+ depOffsets = append(depOffsets, offsetEntry{len(depIdxs), "field type_name"})
+ for _, message := range f.allMessages {
+ for _, field := range message.Fields {
+ if field.Desc.IsWeak() {
+ continue
+ }
+ source := string(field.Desc.FullName())
+ genEnum(field.Enum, source+":type_name")
+ genMessage(field.Message, source+":type_name")
+ }
+ }
+ depOffsets = append(depOffsets, offsetEntry{len(depIdxs), "extension extendee"})
+ for _, extension := range f.allExtensions {
+ source := string(extension.Desc.FullName())
+ genMessage(extension.Extendee, source+":extendee")
+ }
+ depOffsets = append(depOffsets, offsetEntry{len(depIdxs), "extension type_name"})
+ for _, extension := range f.allExtensions {
+ source := string(extension.Desc.FullName())
+ genEnum(extension.Enum, source+":type_name")
+ genMessage(extension.Message, source+":type_name")
+ }
+ depOffsets = append(depOffsets, offsetEntry{len(depIdxs), "method input_type"})
+ for _, service := range f.Services {
+ for _, method := range service.Methods {
+ source := string(method.Desc.FullName())
+ genMessage(method.Input, source+":input_type")
+ }
+ }
+ depOffsets = append(depOffsets, offsetEntry{len(depIdxs), "method output_type"})
+ for _, service := range f.Services {
+ for _, method := range service.Methods {
+ source := string(method.Desc.FullName())
+ genMessage(method.Output, source+":output_type")
+ }
+ }
+ depOffsets = append(depOffsets, offsetEntry{len(depIdxs), ""})
+ for i := len(depOffsets) - 2; i >= 0; i-- {
+ curr, next := depOffsets[i], depOffsets[i+1]
+ depIdxs = append(depIdxs, fmt.Sprintf("%d, // [%d:%d] is the sub-list for %s",
+ curr.start, curr.start, next.start, curr.name))
+ }
+ if len(depIdxs) > math.MaxInt32 {
+ panic("too many dependencies") // sanity check
+ }
+
+ g.P("var ", goTypesVarName(f), " = []any{")
+ for _, s := range goTypes {
+ g.P(s)
+ }
+ g.P("}")
+
+ g.P("var ", depIdxsVarName(f), " = []int32{")
+ for _, s := range depIdxs {
+ g.P(s)
+ }
+ g.P("}")
+
+ g.P("func init() { ", initFuncName(f.File), "() }")
+
+ g.P("func ", initFuncName(f.File), "() {")
+ g.P("if ", f.GoDescriptorIdent, " != nil {")
+ g.P("return")
+ g.P("}")
+
+ // Ensure that initialization functions for different files in the same Go
+ // package run in the correct order: Call the init funcs for every .proto file
+ // imported by this one that is in the same Go package.
+ for i, imps := 0, f.Desc.Imports(); i < imps.Len(); i++ {
+ impFile := gen.FilesByPath[imps.Get(i).Path()]
+ if impFile.GoImportPath != f.GoImportPath {
+ continue
+ }
+ g.P(initFuncName(impFile), "()")
+ }
+
+ if len(f.allMessages) > 0 {
+ // Populate MessageInfo.OneofWrappers.
+ for _, message := range f.allMessages {
+ if len(message.Oneofs) > 0 {
+ idx := f.allMessagesByPtr[message]
+ typesVar := messageTypesVarName(f)
+
+ // Associate the wrapper types by directly passing them to the MessageInfo.
+ g.P(typesVar, "[", idx, "].OneofWrappers = []any {")
+ for _, oneof := range message.Oneofs {
+ if !oneof.Desc.IsSynthetic() {
+ for _, field := range oneof.Fields {
+ g.P("(*", unexportIdent(field.GoIdent, message.isOpaque()), ")(nil),")
+ }
+ }
+ }
+ g.P("}")
+ }
+ }
+ }
+
+ g.P("type x struct{}")
+ g.P("out := ", protoimplPackage.Ident("TypeBuilder"), "{")
+ g.P("File: ", protoimplPackage.Ident("DescBuilder"), "{")
+ g.P("GoPackagePath: ", reflectPackage.Ident("TypeOf"), "(x{}).PkgPath(),")
+ g.P("RawDescriptor: ", rawDescVarName(f), ",")
+ g.P("NumEnums: ", len(f.allEnums), ",")
+ g.P("NumMessages: ", len(f.allMessages), ",")
+ g.P("NumExtensions: ", len(f.allExtensions), ",")
+ g.P("NumServices: ", len(f.Services), ",")
+ g.P("},")
+ g.P("GoTypes: ", goTypesVarName(f), ",")
+ g.P("DependencyIndexes: ", depIdxsVarName(f), ",")
+ if len(f.allEnums) > 0 {
+ g.P("EnumInfos: ", enumTypesVarName(f), ",")
+ }
+ if len(f.allMessages) > 0 {
+ g.P("MessageInfos: ", messageTypesVarName(f), ",")
+ }
+ if len(f.allExtensions) > 0 {
+ g.P("ExtensionInfos: ", extensionTypesVarName(f), ",")
+ }
+ g.P("}.Build()")
+ g.P(f.GoDescriptorIdent, " = out.File")
+
+ // Set inputs to nil to allow GC to reclaim resources.
+ g.P(rawDescVarName(f), " = nil")
+ g.P(goTypesVarName(f), " = nil")
+ g.P(depIdxsVarName(f), " = nil")
+ g.P("}")
+}
+
+// stripSourceRetentionFieldsFromMessage walks the given message tree recursively
+// and clears any fields with the field option: [retention = RETENTION_SOURCE]
+func stripSourceRetentionFieldsFromMessage(m protoreflect.Message) {
+ protorange.Range(m, func(ppv protopath.Values) error {
+ m2, ok := ppv.Index(-1).Value.Interface().(protoreflect.Message)
+ if !ok {
+ return nil
+ }
+ m2.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {
+ fdo, ok := fd.Options().(*descriptorpb.FieldOptions)
+ if ok && fdo.GetRetention() == descriptorpb.FieldOptions_RETENTION_SOURCE {
+ m2.Clear(fd)
+ }
+ return true
+ })
+ return nil
+ })
+}
+
+func genFileDescriptor(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo) {
+ descProto := proto.Clone(f.Proto).(*descriptorpb.FileDescriptorProto)
+ descProto.SourceCodeInfo = nil // drop source code information
+ stripSourceRetentionFieldsFromMessage(descProto.ProtoReflect())
+ b, err := proto.MarshalOptions{AllowPartial: true, Deterministic: true}.Marshal(descProto)
+ if err != nil {
+ gen.Error(err)
+ return
+ }
+
+ g.P("var ", rawDescVarName(f), " = []byte{")
+ for len(b) > 0 {
+ n := 16
+ if n > len(b) {
+ n = len(b)
+ }
+
+ s := ""
+ for _, c := range b[:n] {
+ s += fmt.Sprintf("0x%02x,", c)
+ }
+ g.P(s)
+
+ b = b[n:]
+ }
+ g.P("}")
+ g.P()
+
+ if f.needRawDesc {
+ onceVar := rawDescVarName(f) + "Once"
+ dataVar := rawDescVarName(f) + "Data"
+ g.P("var (")
+ g.P(onceVar, " ", syncPackage.Ident("Once"))
+ g.P(dataVar, " = ", rawDescVarName(f))
+ g.P(")")
+ g.P()
+
+ g.P("func ", rawDescVarName(f), "GZIP() []byte {")
+ g.P(onceVar, ".Do(func() {")
+ g.P(dataVar, " = ", protoimplPackage.Ident("X"), ".CompressGZIP(", dataVar, ")")
+ g.P("})")
+ g.P("return ", dataVar)
+ g.P("}")
+ g.P()
+ }
+}
+
+func genEnumReflectMethods(g *protogen.GeneratedFile, f *fileInfo, e *enumInfo) {
+ idx := f.allEnumsByPtr[e]
+ typesVar := enumTypesVarName(f)
+
+ // Descriptor method.
+ g.P("func (", e.GoIdent, ") Descriptor() ", protoreflectPackage.Ident("EnumDescriptor"), " {")
+ g.P("return ", typesVar, "[", idx, "].Descriptor()")
+ g.P("}")
+ g.P()
+
+ // Type method.
+ g.P("func (", e.GoIdent, ") Type() ", protoreflectPackage.Ident("EnumType"), " {")
+ g.P("return &", typesVar, "[", idx, "]")
+ g.P("}")
+ g.P()
+
+ // Number method.
+ g.P("func (x ", e.GoIdent, ") Number() ", protoreflectPackage.Ident("EnumNumber"), " {")
+ g.P("return ", protoreflectPackage.Ident("EnumNumber"), "(x)")
+ g.P("}")
+ g.P()
+}
+
+func genMessageReflectMethods(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) {
+ idx := f.allMessagesByPtr[m]
+ typesVar := messageTypesVarName(f)
+
+ // ProtoReflect method.
+ g.P("func (x *", m.GoIdent, ") ProtoReflect() ", protoreflectPackage.Ident("Message"), " {")
+ g.P("mi := &", typesVar, "[", idx, "]")
+ g.P("if x != nil {")
+ g.P("ms := ", protoimplPackage.Ident("X"), ".MessageStateOf(", protoimplPackage.Ident("Pointer"), "(x))")
+ g.P("if ms.LoadMessageInfo() == nil {")
+ g.P("ms.StoreMessageInfo(mi)")
+ g.P("}")
+ g.P("return ms")
+ g.P("}")
+ g.P("return mi.MessageOf(x)")
+ g.P("}")
+ g.P()
+}
+
+func fileVarName(f *protogen.File, suffix string) string {
+ prefix := f.GoDescriptorIdent.GoName
+ _, n := utf8.DecodeRuneInString(prefix)
+ prefix = strings.ToLower(prefix[:n]) + prefix[n:]
+ return prefix + "_" + suffix
+}
+func rawDescVarName(f *fileInfo) string {
+ return fileVarName(f.File, "rawDesc")
+}
+func goTypesVarName(f *fileInfo) string {
+ return fileVarName(f.File, "goTypes")
+}
+func depIdxsVarName(f *fileInfo) string {
+ return fileVarName(f.File, "depIdxs")
+}
+func enumTypesVarName(f *fileInfo) string {
+ return fileVarName(f.File, "enumTypes")
+}
+func messageTypesVarName(f *fileInfo) string {
+ return fileVarName(f.File, "msgTypes")
+}
+func extensionTypesVarName(f *fileInfo) string {
+ return fileVarName(f.File, "extTypes")
+}
+func initFuncName(f *protogen.File) string {
+ return fileVarName(f, "init")
+}
diff --git a/vendor/google.golang.org/protobuf/cmd/protoc-gen-go/internal_gengo/well_known_types.go b/vendor/google.golang.org/protobuf/cmd/protoc-gen-go/internal_gengo/well_known_types.go
new file mode 100644
index 00000000000..2ae6b039603
--- /dev/null
+++ b/vendor/google.golang.org/protobuf/cmd/protoc-gen-go/internal_gengo/well_known_types.go
@@ -0,0 +1,1094 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package internal_gengo
+
+import (
+ "strings"
+
+ "google.golang.org/protobuf/compiler/protogen"
+ "google.golang.org/protobuf/internal/genid"
+)
+
+// Specialized support for well-known types are hard-coded into the generator
+// as opposed to being injected in adjacent .go sources in the generated package
+// in order to support specialized build systems like Bazel that always generate
+// dynamically from the source .proto files.
+
+func genPackageKnownComment(f *fileInfo) protogen.Comments {
+ switch f.Desc.Path() {
+ case genid.File_google_protobuf_any_proto:
+ return ` Package anypb contains generated types for ` + genid.File_google_protobuf_any_proto + `.
+
+ The Any message is a dynamic representation of any other message value.
+ It is functionally a tuple of the full name of the remote message type and
+ the serialized bytes of the remote message value.
+
+
+ Constructing an Any
+
+ An Any message containing another message value is constructed using New:
+
+ any, err := anypb.New(m)
+ if err != nil {
+ ... // handle error
+ }
+ ... // make use of any
+
+
+ Unmarshaling an Any
+
+ With a populated Any message, the underlying message can be serialized into
+ a remote concrete message value in a few ways.
+
+ If the exact concrete type is known, then a new (or pre-existing) instance
+ of that message can be passed to the UnmarshalTo method:
+
+ m := new(foopb.MyMessage)
+ if err := any.UnmarshalTo(m); err != nil {
+ ... // handle error
+ }
+ ... // make use of m
+
+ If the exact concrete type is not known, then the UnmarshalNew method can be
+ used to unmarshal the contents into a new instance of the remote message type:
+
+ m, err := any.UnmarshalNew()
+ if err != nil {
+ ... // handle error
+ }
+ ... // make use of m
+
+ UnmarshalNew uses the global type registry to resolve the message type and
+ construct a new instance of that message to unmarshal into. In order for a
+ message type to appear in the global registry, the Go type representing that
+ protobuf message type must be linked into the Go binary. For messages
+ generated by protoc-gen-go, this is achieved through an import of the
+ generated Go package representing a .proto file.
+
+ A common pattern with UnmarshalNew is to use a type switch with the resulting
+ proto.Message value:
+
+ switch m := m.(type) {
+ case *foopb.MyMessage:
+ ... // make use of m as a *foopb.MyMessage
+ case *barpb.OtherMessage:
+ ... // make use of m as a *barpb.OtherMessage
+ case *bazpb.SomeMessage:
+ ... // make use of m as a *bazpb.SomeMessage
+ }
+
+ This pattern ensures that the generated packages containing the message types
+ listed in the case clauses are linked into the Go binary and therefore also
+ registered in the global registry.
+
+
+ Type checking an Any
+
+ In order to type check whether an Any message represents some other message,
+ then use the MessageIs method:
+
+ if any.MessageIs((*foopb.MyMessage)(nil)) {
+ ... // make use of any, knowing that it contains a foopb.MyMessage
+ }
+
+ The MessageIs method can also be used with an allocated instance of the target
+ message type if the intention is to unmarshal into it if the type matches:
+
+ m := new(foopb.MyMessage)
+ if any.MessageIs(m) {
+ if err := any.UnmarshalTo(m); err != nil {
+ ... // handle error
+ }
+ ... // make use of m
+ }
+
+`
+ case genid.File_google_protobuf_timestamp_proto:
+ return ` Package timestamppb contains generated types for ` + genid.File_google_protobuf_timestamp_proto + `.
+
+ The Timestamp message represents a timestamp,
+ an instant in time since the Unix epoch (January 1st, 1970).
+
+
+ Conversion to a Go Time
+
+ The AsTime method can be used to convert a Timestamp message to a
+ standard Go time.Time value in UTC:
+
+ t := ts.AsTime()
+ ... // make use of t as a time.Time
+
+ Converting to a time.Time is a common operation so that the extensive
+ set of time-based operations provided by the time package can be leveraged.
+ See https://golang.org/pkg/time for more information.
+
+ The AsTime method performs the conversion on a best-effort basis. Timestamps
+ with denormal values (e.g., nanoseconds beyond 0 and 99999999, inclusive)
+ are normalized during the conversion to a time.Time. To manually check for
+ invalid Timestamps per the documented limitations in timestamp.proto,
+ additionally call the CheckValid method:
+
+ if err := ts.CheckValid(); err != nil {
+ ... // handle error
+ }
+
+
+ Conversion from a Go Time
+
+ The timestamppb.New function can be used to construct a Timestamp message
+ from a standard Go time.Time value:
+
+ ts := timestamppb.New(t)
+ ... // make use of ts as a *timestamppb.Timestamp
+
+ In order to construct a Timestamp representing the current time, use Now:
+
+ ts := timestamppb.Now()
+ ... // make use of ts as a *timestamppb.Timestamp
+
+`
+ case genid.File_google_protobuf_duration_proto:
+ return ` Package durationpb contains generated types for ` + genid.File_google_protobuf_duration_proto + `.
+
+ The Duration message represents a signed span of time.
+
+
+ Conversion to a Go Duration
+
+ The AsDuration method can be used to convert a Duration message to a
+ standard Go time.Duration value:
+
+ d := dur.AsDuration()
+ ... // make use of d as a time.Duration
+
+ Converting to a time.Duration is a common operation so that the extensive
+ set of time-based operations provided by the time package can be leveraged.
+ See https://golang.org/pkg/time for more information.
+
+ The AsDuration method performs the conversion on a best-effort basis.
+ Durations with denormal values (e.g., nanoseconds beyond -99999999 and
+ +99999999, inclusive; or seconds and nanoseconds with opposite signs)
+ are normalized during the conversion to a time.Duration. To manually check for
+ invalid Duration per the documented limitations in duration.proto,
+ additionally call the CheckValid method:
+
+ if err := dur.CheckValid(); err != nil {
+ ... // handle error
+ }
+
+ Note that the documented limitations in duration.proto does not protect a
+ Duration from overflowing the representable range of a time.Duration in Go.
+ The AsDuration method uses saturation arithmetic such that an overflow clamps
+ the resulting value to the closest representable value (e.g., math.MaxInt64
+ for positive overflow and math.MinInt64 for negative overflow).
+
+
+ Conversion from a Go Duration
+
+ The durationpb.New function can be used to construct a Duration message
+ from a standard Go time.Duration value:
+
+ dur := durationpb.New(d)
+ ... // make use of d as a *durationpb.Duration
+
+`
+ case genid.File_google_protobuf_struct_proto:
+ return ` Package structpb contains generated types for ` + genid.File_google_protobuf_struct_proto + `.
+
+ The messages (i.e., Value, Struct, and ListValue) defined in struct.proto are
+ used to represent arbitrary JSON. The Value message represents a JSON value,
+ the Struct message represents a JSON object, and the ListValue message
+ represents a JSON array. See https://json.org for more information.
+
+ The Value, Struct, and ListValue types have generated MarshalJSON and
+ UnmarshalJSON methods such that they serialize JSON equivalent to what the
+ messages themselves represent. Use of these types with the
+ "google.golang.org/protobuf/encoding/protojson" package
+ ensures that they will be serialized as their JSON equivalent.
+
+ # Conversion to and from a Go interface
+
+ The standard Go "encoding/json" package has functionality to serialize
+ arbitrary types to a large degree. The Value.AsInterface, Struct.AsMap, and
+ ListValue.AsSlice methods can convert the protobuf message representation into
+ a form represented by any, map[string]any, and []any.
+ This form can be used with other packages that operate on such data structures
+ and also directly with the standard json package.
+
+ In order to convert the any, map[string]any, and []any
+ forms back as Value, Struct, and ListValue messages, use the NewStruct,
+ NewList, and NewValue constructor functions.
+
+ # Example usage
+
+ Consider the following example JSON object:
+
+ {
+ "firstName": "John",
+ "lastName": "Smith",
+ "isAlive": true,
+ "age": 27,
+ "address": {
+ "streetAddress": "21 2nd Street",
+ "city": "New York",
+ "state": "NY",
+ "postalCode": "10021-3100"
+ },
+ "phoneNumbers": [
+ {
+ "type": "home",
+ "number": "212 555-1234"
+ },
+ {
+ "type": "office",
+ "number": "646 555-4567"
+ }
+ ],
+ "children": [],
+ "spouse": null
+ }
+
+ To construct a Value message representing the above JSON object:
+
+ m, err := structpb.NewValue(map[string]any{
+ "firstName": "John",
+ "lastName": "Smith",
+ "isAlive": true,
+ "age": 27,
+ "address": map[string]any{
+ "streetAddress": "21 2nd Street",
+ "city": "New York",
+ "state": "NY",
+ "postalCode": "10021-3100",
+ },
+ "phoneNumbers": []any{
+ map[string]any{
+ "type": "home",
+ "number": "212 555-1234",
+ },
+ map[string]any{
+ "type": "office",
+ "number": "646 555-4567",
+ },
+ },
+ "children": []any{},
+ "spouse": nil,
+ })
+ if err != nil {
+ ... // handle error
+ }
+ ... // make use of m as a *structpb.Value
+`
+ case genid.File_google_protobuf_field_mask_proto:
+ return ` Package fieldmaskpb contains generated types for ` + genid.File_google_protobuf_field_mask_proto + `.
+
+ The FieldMask message represents a set of symbolic field paths.
+ The paths are specific to some target message type,
+ which is not stored within the FieldMask message itself.
+
+
+ Constructing a FieldMask
+
+ The New function is used construct a FieldMask:
+
+ var messageType *descriptorpb.DescriptorProto
+ fm, err := fieldmaskpb.New(messageType, "field.name", "field.number")
+ if err != nil {
+ ... // handle error
+ }
+ ... // make use of fm
+
+ The "field.name" and "field.number" paths are valid paths according to the
+ google.protobuf.DescriptorProto message. Use of a path that does not correlate
+ to valid fields reachable from DescriptorProto would result in an error.
+
+ Once a FieldMask message has been constructed,
+ the Append method can be used to insert additional paths to the path set:
+
+ var messageType *descriptorpb.DescriptorProto
+ if err := fm.Append(messageType, "options"); err != nil {
+ ... // handle error
+ }
+
+
+ Type checking a FieldMask
+
+ In order to verify that a FieldMask represents a set of fields that are
+ reachable from some target message type, use the IsValid method:
+
+ var messageType *descriptorpb.DescriptorProto
+ if fm.IsValid(messageType) {
+ ... // make use of fm
+ }
+
+ IsValid needs to be passed the target message type as an input since the
+ FieldMask message itself does not store the message type that the set of paths
+ are for.
+`
+ default:
+ return ""
+ }
+}
+
+func genMessageKnownFunctions(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) {
+ switch m.Desc.FullName() {
+ case genid.Any_message_fullname:
+ g.P("// New marshals src into a new Any instance.")
+ g.P("func New(src ", protoPackage.Ident("Message"), ") (*Any, error) {")
+ g.P(" dst := new(Any)")
+ g.P(" if err := dst.MarshalFrom(src); err != nil {")
+ g.P(" return nil, err")
+ g.P(" }")
+ g.P(" return dst, nil")
+ g.P("}")
+ g.P()
+
+ g.P("// MarshalFrom marshals src into dst as the underlying message")
+ g.P("// using the provided marshal options.")
+ g.P("//")
+ g.P("// If no options are specified, call dst.MarshalFrom instead.")
+ g.P("func MarshalFrom(dst *Any, src ", protoPackage.Ident("Message"), ", opts ", protoPackage.Ident("MarshalOptions"), ") error {")
+ g.P(" const urlPrefix = \"type.googleapis.com/\"")
+ g.P(" if src == nil {")
+ g.P(" return ", protoimplPackage.Ident("X"), ".NewError(\"invalid nil source message\")")
+ g.P(" }")
+ g.P(" b, err := opts.Marshal(src)")
+ g.P(" if err != nil {")
+ g.P(" return err")
+ g.P(" }")
+ g.P(" dst.TypeUrl = urlPrefix + string(src.ProtoReflect().Descriptor().FullName())")
+ g.P(" dst.Value = b")
+ g.P(" return nil")
+ g.P("}")
+ g.P()
+
+ g.P("// UnmarshalTo unmarshals the underlying message from src into dst")
+ g.P("// using the provided unmarshal options.")
+ g.P("// It reports an error if dst is not of the right message type.")
+ g.P("//")
+ g.P("// If no options are specified, call src.UnmarshalTo instead.")
+ g.P("func UnmarshalTo(src *Any, dst ", protoPackage.Ident("Message"), ", opts ", protoPackage.Ident("UnmarshalOptions"), ") error {")
+ g.P(" if src == nil {")
+ g.P(" return ", protoimplPackage.Ident("X"), ".NewError(\"invalid nil source message\")")
+ g.P(" }")
+ g.P(" if !src.MessageIs(dst) {")
+ g.P(" got := dst.ProtoReflect().Descriptor().FullName()")
+ g.P(" want := src.MessageName()")
+ g.P(" return ", protoimplPackage.Ident("X"), ".NewError(\"mismatched message type: got %q, want %q\", got, want)")
+ g.P(" }")
+ g.P(" return opts.Unmarshal(src.GetValue(), dst)")
+ g.P("}")
+ g.P()
+
+ g.P("// UnmarshalNew unmarshals the underlying message from src into dst,")
+ g.P("// which is newly created message using a type resolved from the type URL.")
+ g.P("// The message type is resolved according to opt.Resolver,")
+ g.P("// which should implement protoregistry.MessageTypeResolver.")
+ g.P("// It reports an error if the underlying message type could not be resolved.")
+ g.P("//")
+ g.P("// If no options are specified, call src.UnmarshalNew instead.")
+ g.P("func UnmarshalNew(src *Any, opts ", protoPackage.Ident("UnmarshalOptions"), ") (dst ", protoPackage.Ident("Message"), ", err error) {")
+ g.P(" if src.GetTypeUrl() == \"\" {")
+ g.P(" return nil, ", protoimplPackage.Ident("X"), ".NewError(\"invalid empty type URL\")")
+ g.P(" }")
+ g.P(" if opts.Resolver == nil {")
+ g.P(" opts.Resolver = ", protoregistryPackage.Ident("GlobalTypes"))
+ g.P(" }")
+ g.P(" r, ok := opts.Resolver.(", protoregistryPackage.Ident("MessageTypeResolver"), ")")
+ g.P(" if !ok {")
+ g.P(" return nil, ", protoregistryPackage.Ident("NotFound"))
+ g.P(" }")
+ g.P(" mt, err := r.FindMessageByURL(src.GetTypeUrl())")
+ g.P(" if err != nil {")
+ g.P(" if err == ", protoregistryPackage.Ident("NotFound"), " {")
+ g.P(" return nil, err")
+ g.P(" }")
+ g.P(" return nil, ", protoimplPackage.Ident("X"), ".NewError(\"could not resolve %q: %v\", src.GetTypeUrl(), err)")
+ g.P(" }")
+ g.P(" dst = mt.New().Interface()")
+ g.P(" return dst, opts.Unmarshal(src.GetValue(), dst)")
+ g.P("}")
+ g.P()
+
+ g.P("// MessageIs reports whether the underlying message is of the same type as m.")
+ g.P("func (x *Any) MessageIs(m ", protoPackage.Ident("Message"), ") bool {")
+ g.P(" if m == nil {")
+ g.P(" return false")
+ g.P(" }")
+ g.P(" url := x.GetTypeUrl()")
+ g.P(" name := string(m.ProtoReflect().Descriptor().FullName())")
+ g.P(" if !", stringsPackage.Ident("HasSuffix"), "(url, name) {")
+ g.P(" return false")
+ g.P(" }")
+ g.P(" return len(url) == len(name) || url[len(url)-len(name)-1] == '/'")
+ g.P("}")
+ g.P()
+
+ g.P("// MessageName reports the full name of the underlying message,")
+ g.P("// returning an empty string if invalid.")
+ g.P("func (x *Any) MessageName() ", protoreflectPackage.Ident("FullName"), " {")
+ g.P(" url := x.GetTypeUrl()")
+ g.P(" name := ", protoreflectPackage.Ident("FullName"), "(url)")
+ g.P(" if i := ", stringsPackage.Ident("LastIndexByte"), "(url, '/'); i >= 0 {")
+ g.P(" name = name[i+len(\"/\"):]")
+ g.P(" }")
+ g.P(" if !name.IsValid() {")
+ g.P(" return \"\"")
+ g.P(" }")
+ g.P(" return name")
+ g.P("}")
+ g.P()
+
+ g.P("// MarshalFrom marshals m into x as the underlying message.")
+ g.P("func (x *Any) MarshalFrom(m ", protoPackage.Ident("Message"), ") error {")
+ g.P(" return MarshalFrom(x, m, ", protoPackage.Ident("MarshalOptions"), "{})")
+ g.P("}")
+ g.P()
+
+ g.P("// UnmarshalTo unmarshals the contents of the underlying message of x into m.")
+ g.P("// It resets m before performing the unmarshal operation.")
+ g.P("// It reports an error if m is not of the right message type.")
+ g.P("func (x *Any) UnmarshalTo(m ", protoPackage.Ident("Message"), ") error {")
+ g.P(" return UnmarshalTo(x, m, ", protoPackage.Ident("UnmarshalOptions"), "{})")
+ g.P("}")
+ g.P()
+
+ g.P("// UnmarshalNew unmarshals the contents of the underlying message of x into")
+ g.P("// a newly allocated message of the specified type.")
+ g.P("// It reports an error if the underlying message type could not be resolved.")
+ g.P("func (x *Any) UnmarshalNew() (", protoPackage.Ident("Message"), ", error) {")
+ g.P(" return UnmarshalNew(x, ", protoPackage.Ident("UnmarshalOptions"), "{})")
+ g.P("}")
+ g.P()
+
+ case genid.Timestamp_message_fullname:
+ g.P("// Now constructs a new Timestamp from the current time.")
+ g.P("func Now() *Timestamp {")
+ g.P(" return New(", timePackage.Ident("Now"), "())")
+ g.P("}")
+ g.P()
+
+ g.P("// New constructs a new Timestamp from the provided time.Time.")
+ g.P("func New(t ", timePackage.Ident("Time"), ") *Timestamp {")
+ g.P(" return &Timestamp{Seconds: int64(t.Unix()), Nanos: int32(t.Nanosecond())}")
+ g.P("}")
+ g.P()
+
+ g.P("// AsTime converts x to a time.Time.")
+ g.P("func (x *Timestamp) AsTime() ", timePackage.Ident("Time"), " {")
+ g.P(" return ", timePackage.Ident("Unix"), "(int64(x.GetSeconds()), int64(x.GetNanos())).UTC()")
+ g.P("}")
+ g.P()
+
+ g.P("// IsValid reports whether the timestamp is valid.")
+ g.P("// It is equivalent to CheckValid == nil.")
+ g.P("func (x *Timestamp) IsValid() bool {")
+ g.P(" return x.check() == 0")
+ g.P("}")
+ g.P()
+
+ g.P("// CheckValid returns an error if the timestamp is invalid.")
+ g.P("// In particular, it checks whether the value represents a date that is")
+ g.P("// in the range of 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z inclusive.")
+ g.P("// An error is reported for a nil Timestamp.")
+ g.P("func (x *Timestamp) CheckValid() error {")
+ g.P(" switch x.check() {")
+ g.P(" case invalidNil:")
+ g.P(" return ", protoimplPackage.Ident("X"), ".NewError(\"invalid nil Timestamp\")")
+ g.P(" case invalidUnderflow:")
+ g.P(" return ", protoimplPackage.Ident("X"), ".NewError(\"timestamp (%v) before 0001-01-01\", x)")
+ g.P(" case invalidOverflow:")
+ g.P(" return ", protoimplPackage.Ident("X"), ".NewError(\"timestamp (%v) after 9999-12-31\", x)")
+ g.P(" case invalidNanos:")
+ g.P(" return ", protoimplPackage.Ident("X"), ".NewError(\"timestamp (%v) has out-of-range nanos\", x)")
+ g.P(" default:")
+ g.P(" return nil")
+ g.P(" }")
+ g.P("}")
+ g.P()
+
+ g.P("const (")
+ g.P(" _ = iota")
+ g.P(" invalidNil")
+ g.P(" invalidUnderflow")
+ g.P(" invalidOverflow")
+ g.P(" invalidNanos")
+ g.P(")")
+ g.P()
+
+ g.P("func (x *Timestamp) check() uint {")
+ g.P(" const minTimestamp = -62135596800 // Seconds between 1970-01-01T00:00:00Z and 0001-01-01T00:00:00Z, inclusive")
+ g.P(" const maxTimestamp = +253402300799 // Seconds between 1970-01-01T00:00:00Z and 9999-12-31T23:59:59Z, inclusive")
+ g.P(" secs := x.GetSeconds()")
+ g.P(" nanos := x.GetNanos()")
+ g.P(" switch {")
+ g.P(" case x == nil:")
+ g.P(" return invalidNil")
+ g.P(" case secs < minTimestamp:")
+ g.P(" return invalidUnderflow")
+ g.P(" case secs > maxTimestamp:")
+ g.P(" return invalidOverflow")
+ g.P(" case nanos < 0 || nanos >= 1e9:")
+ g.P(" return invalidNanos")
+ g.P(" default:")
+ g.P(" return 0")
+ g.P(" }")
+ g.P("}")
+ g.P()
+
+ case genid.Duration_message_fullname:
+ g.P("// New constructs a new Duration from the provided time.Duration.")
+ g.P("func New(d ", timePackage.Ident("Duration"), ") *Duration {")
+ g.P(" nanos := d.Nanoseconds()")
+ g.P(" secs := nanos / 1e9")
+ g.P(" nanos -= secs * 1e9")
+ g.P(" return &Duration{Seconds: int64(secs), Nanos: int32(nanos)}")
+ g.P("}")
+ g.P()
+
+ g.P("// AsDuration converts x to a time.Duration,")
+ g.P("// returning the closest duration value in the event of overflow.")
+ g.P("func (x *Duration) AsDuration() ", timePackage.Ident("Duration"), " {")
+ g.P(" secs := x.GetSeconds()")
+ g.P(" nanos := x.GetNanos()")
+ g.P(" d := ", timePackage.Ident("Duration"), "(secs) * ", timePackage.Ident("Second"))
+ g.P(" overflow := d/", timePackage.Ident("Second"), " != ", timePackage.Ident("Duration"), "(secs)")
+ g.P(" d += ", timePackage.Ident("Duration"), "(nanos) * ", timePackage.Ident("Nanosecond"))
+ g.P(" overflow = overflow || (secs < 0 && nanos < 0 && d > 0)")
+ g.P(" overflow = overflow || (secs > 0 && nanos > 0 && d < 0)")
+ g.P(" if overflow {")
+ g.P(" switch {")
+ g.P(" case secs < 0:")
+ g.P(" return ", timePackage.Ident("Duration"), "(", mathPackage.Ident("MinInt64"), ")")
+ g.P(" case secs > 0:")
+ g.P(" return ", timePackage.Ident("Duration"), "(", mathPackage.Ident("MaxInt64"), ")")
+ g.P(" }")
+ g.P(" }")
+ g.P(" return d")
+ g.P("}")
+ g.P()
+
+ g.P("// IsValid reports whether the duration is valid.")
+ g.P("// It is equivalent to CheckValid == nil.")
+ g.P("func (x *Duration) IsValid() bool {")
+ g.P(" return x.check() == 0")
+ g.P("}")
+ g.P()
+
+ g.P("// CheckValid returns an error if the duration is invalid.")
+ g.P("// In particular, it checks whether the value is within the range of")
+ g.P("// -10000 years to +10000 years inclusive.")
+ g.P("// An error is reported for a nil Duration.")
+ g.P("func (x *Duration) CheckValid() error {")
+ g.P(" switch x.check() {")
+ g.P(" case invalidNil:")
+ g.P(" return ", protoimplPackage.Ident("X"), ".NewError(\"invalid nil Duration\")")
+ g.P(" case invalidUnderflow:")
+ g.P(" return ", protoimplPackage.Ident("X"), ".NewError(\"duration (%v) exceeds -10000 years\", x)")
+ g.P(" case invalidOverflow:")
+ g.P(" return ", protoimplPackage.Ident("X"), ".NewError(\"duration (%v) exceeds +10000 years\", x)")
+ g.P(" case invalidNanosRange:")
+ g.P(" return ", protoimplPackage.Ident("X"), ".NewError(\"duration (%v) has out-of-range nanos\", x)")
+ g.P(" case invalidNanosSign:")
+ g.P(" return ", protoimplPackage.Ident("X"), ".NewError(\"duration (%v) has seconds and nanos with different signs\", x)")
+ g.P(" default:")
+ g.P(" return nil")
+ g.P(" }")
+ g.P("}")
+ g.P()
+
+ g.P("const (")
+ g.P(" _ = iota")
+ g.P(" invalidNil")
+ g.P(" invalidUnderflow")
+ g.P(" invalidOverflow")
+ g.P(" invalidNanosRange")
+ g.P(" invalidNanosSign")
+ g.P(")")
+ g.P()
+
+ g.P("func (x *Duration) check() uint {")
+ g.P(" const absDuration = 315576000000 // 10000yr * 365.25day/yr * 24hr/day * 60min/hr * 60sec/min")
+ g.P(" secs := x.GetSeconds()")
+ g.P(" nanos := x.GetNanos()")
+ g.P(" switch {")
+ g.P(" case x == nil:")
+ g.P(" return invalidNil")
+ g.P(" case secs < -absDuration:")
+ g.P(" return invalidUnderflow")
+ g.P(" case secs > +absDuration:")
+ g.P(" return invalidOverflow")
+ g.P(" case nanos <= -1e9 || nanos >= +1e9:")
+ g.P(" return invalidNanosRange")
+ g.P(" case (secs > 0 && nanos < 0) || (secs < 0 && nanos > 0):")
+ g.P(" return invalidNanosSign")
+ g.P(" default:")
+ g.P(" return 0")
+ g.P(" }")
+ g.P("}")
+ g.P()
+
+ case genid.Struct_message_fullname:
+ g.P("// NewStruct constructs a Struct from a general-purpose Go map.")
+ g.P("// The map keys must be valid UTF-8.")
+ g.P("// The map values are converted using NewValue.")
+ g.P("func NewStruct(v map[string]any) (*Struct, error) {")
+ g.P(" x := &Struct{Fields: make(map[string]*Value, len(v))}")
+ g.P(" for k, v := range v {")
+ g.P(" if !", utf8Package.Ident("ValidString"), "(k) {")
+ g.P(" return nil, ", protoimplPackage.Ident("X"), ".NewError(\"invalid UTF-8 in string: %q\", k)")
+ g.P(" }")
+ g.P(" var err error")
+ g.P(" x.Fields[k], err = NewValue(v)")
+ g.P(" if err != nil {")
+ g.P(" return nil, err")
+ g.P(" }")
+ g.P(" }")
+ g.P(" return x, nil")
+ g.P("}")
+ g.P()
+
+ g.P("// AsMap converts x to a general-purpose Go map.")
+ g.P("// The map values are converted by calling Value.AsInterface.")
+ g.P("func (x *Struct) AsMap() map[string]any {")
+ g.P(" f := x.GetFields()")
+ g.P(" vs := make(map[string]any, len(f))")
+ g.P(" for k, v := range f {")
+ g.P(" vs[k] = v.AsInterface()")
+ g.P(" }")
+ g.P(" return vs")
+ g.P("}")
+ g.P()
+
+ g.P("func (x *Struct) MarshalJSON() ([]byte, error) {")
+ g.P(" return ", protojsonPackage.Ident("Marshal"), "(x)")
+ g.P("}")
+ g.P()
+
+ g.P("func (x *Struct) UnmarshalJSON(b []byte) error {")
+ g.P(" return ", protojsonPackage.Ident("Unmarshal"), "(b, x)")
+ g.P("}")
+ g.P()
+
+ case genid.ListValue_message_fullname:
+ g.P("// NewList constructs a ListValue from a general-purpose Go slice.")
+ g.P("// The slice elements are converted using NewValue.")
+ g.P("func NewList(v []any) (*ListValue, error) {")
+ g.P(" x := &ListValue{Values: make([]*Value, len(v))}")
+ g.P(" for i, v := range v {")
+ g.P(" var err error")
+ g.P(" x.Values[i], err = NewValue(v)")
+ g.P(" if err != nil {")
+ g.P(" return nil, err")
+ g.P(" }")
+ g.P(" }")
+ g.P(" return x, nil")
+ g.P("}")
+ g.P()
+
+ g.P("// AsSlice converts x to a general-purpose Go slice.")
+ g.P("// The slice elements are converted by calling Value.AsInterface.")
+ g.P("func (x *ListValue) AsSlice() []any {")
+ g.P(" vals := x.GetValues()")
+ g.P(" vs := make([]any, len(vals))")
+ g.P(" for i, v := range vals {")
+ g.P(" vs[i] = v.AsInterface()")
+ g.P(" }")
+ g.P(" return vs")
+ g.P("}")
+ g.P()
+
+ g.P("func (x *ListValue) MarshalJSON() ([]byte, error) {")
+ g.P(" return ", protojsonPackage.Ident("Marshal"), "(x)")
+ g.P("}")
+ g.P()
+
+ g.P("func (x *ListValue) UnmarshalJSON(b []byte) error {")
+ g.P(" return ", protojsonPackage.Ident("Unmarshal"), "(b, x)")
+ g.P("}")
+ g.P()
+
+ case genid.Value_message_fullname:
+ g.P("// NewValue constructs a Value from a general-purpose Go interface.")
+ g.P("//")
+ g.P("// ╔═══════════════════════════════════════╤════════════════════════════════════════════╗")
+ g.P("// ║ Go type │ Conversion ║")
+ g.P("// ╠═══════════════════════════════════════╪════════════════════════════════════════════╣")
+ g.P("// ║ nil │ stored as NullValue ║")
+ g.P("// ║ bool │ stored as BoolValue ║")
+ g.P("// ║ int, int8, int16, int32, int64 │ stored as NumberValue ║")
+ g.P("// ║ uint, uint8, uint16, uint32, uint64 │ stored as NumberValue ║")
+ g.P("// ║ float32, float64 │ stored as NumberValue ║")
+ g.P("// ║ json.Number │ stored as NumberValue ║")
+ g.P("// ║ string │ stored as StringValue; must be valid UTF-8 ║")
+ g.P("// ║ []byte │ stored as StringValue; base64-encoded ║")
+ g.P("// ║ map[string]any │ stored as StructValue ║")
+ g.P("// ║ []any │ stored as ListValue ║")
+ g.P("// ╚═══════════════════════════════════════╧════════════════════════════════════════════╝")
+ g.P("//")
+ g.P("// When converting an int64 or uint64 to a NumberValue, numeric precision loss")
+ g.P("// is possible since they are stored as a float64.")
+ g.P("func NewValue(v any) (*Value, error) {")
+ g.P(" switch v := v.(type) {")
+ g.P(" case nil:")
+ g.P(" return NewNullValue(), nil")
+ g.P(" case bool:")
+ g.P(" return NewBoolValue(v), nil")
+ g.P(" case int:")
+ g.P(" return NewNumberValue(float64(v)), nil")
+ g.P(" case int8:")
+ g.P(" return NewNumberValue(float64(v)), nil")
+ g.P(" case int16:")
+ g.P(" return NewNumberValue(float64(v)), nil")
+ g.P(" case int32:")
+ g.P(" return NewNumberValue(float64(v)), nil")
+ g.P(" case int64:")
+ g.P(" return NewNumberValue(float64(v)), nil")
+ g.P(" case uint:")
+ g.P(" return NewNumberValue(float64(v)), nil")
+ g.P(" case uint8:")
+ g.P(" return NewNumberValue(float64(v)), nil")
+ g.P(" case uint16:")
+ g.P(" return NewNumberValue(float64(v)), nil")
+ g.P(" case uint32:")
+ g.P(" return NewNumberValue(float64(v)), nil")
+ g.P(" case uint64:")
+ g.P(" return NewNumberValue(float64(v)), nil")
+ g.P(" case float32:")
+ g.P(" return NewNumberValue(float64(v)), nil")
+ g.P(" case float64:")
+ g.P(" return NewNumberValue(float64(v)), nil")
+ g.P(" case ", jsonPackage.Ident("Number"), ":")
+ g.P(" n, err := v.Float64()")
+ g.P(" if err != nil {")
+ g.P(" return nil, ", protoimplPackage.Ident("X"), ".NewError(\"invalid number format %q, expected a float64: %v\", v, err)")
+ g.P(" }")
+ g.P(" return NewNumberValue(n), nil")
+ g.P(" case string:")
+ g.P(" if !", utf8Package.Ident("ValidString"), "(v) {")
+ g.P(" return nil, ", protoimplPackage.Ident("X"), ".NewError(\"invalid UTF-8 in string: %q\", v)")
+ g.P(" }")
+ g.P(" return NewStringValue(v), nil")
+ g.P(" case []byte:")
+ g.P(" s := ", base64Package.Ident("StdEncoding"), ".EncodeToString(v)")
+ g.P(" return NewStringValue(s), nil")
+ g.P(" case map[string]any:")
+ g.P(" v2, err := NewStruct(v)")
+ g.P(" if err != nil {")
+ g.P(" return nil, err")
+ g.P(" }")
+ g.P(" return NewStructValue(v2), nil")
+ g.P(" case []any:")
+ g.P(" v2, err := NewList(v)")
+ g.P(" if err != nil {")
+ g.P(" return nil, err")
+ g.P(" }")
+ g.P(" return NewListValue(v2), nil")
+ g.P(" default:")
+ g.P(" return nil, ", protoimplPackage.Ident("X"), ".NewError(\"invalid type: %T\", v)")
+ g.P(" }")
+ g.P("}")
+ g.P()
+
+ g.P("// NewNullValue constructs a new null Value.")
+ g.P("func NewNullValue() *Value {")
+ g.P(" return &Value{Kind: &Value_NullValue{NullValue: NullValue_NULL_VALUE}}")
+ g.P("}")
+ g.P()
+
+ g.P("// NewBoolValue constructs a new boolean Value.")
+ g.P("func NewBoolValue(v bool) *Value {")
+ g.P(" return &Value{Kind: &Value_BoolValue{BoolValue: v}}")
+ g.P("}")
+ g.P()
+
+ g.P("// NewNumberValue constructs a new number Value.")
+ g.P("func NewNumberValue(v float64) *Value {")
+ g.P(" return &Value{Kind: &Value_NumberValue{NumberValue: v}}")
+ g.P("}")
+ g.P()
+
+ g.P("// NewStringValue constructs a new string Value.")
+ g.P("func NewStringValue(v string) *Value {")
+ g.P(" return &Value{Kind: &Value_StringValue{StringValue: v}}")
+ g.P("}")
+ g.P()
+
+ g.P("// NewStructValue constructs a new struct Value.")
+ g.P("func NewStructValue(v *Struct) *Value {")
+ g.P(" return &Value{Kind: &Value_StructValue{StructValue: v}}")
+ g.P("}")
+ g.P()
+
+ g.P("// NewListValue constructs a new list Value.")
+ g.P("func NewListValue(v *ListValue) *Value {")
+ g.P(" return &Value{Kind: &Value_ListValue{ListValue: v}}")
+ g.P("}")
+ g.P()
+
+ g.P("// AsInterface converts x to a general-purpose Go interface.")
+ g.P("//")
+ g.P("// Calling Value.MarshalJSON and \"encoding/json\".Marshal on this output produce")
+ g.P("// semantically equivalent JSON (assuming no errors occur).")
+ g.P("//")
+ g.P("// Floating-point values (i.e., \"NaN\", \"Infinity\", and \"-Infinity\") are")
+ g.P("// converted as strings to remain compatible with MarshalJSON.")
+ g.P("func (x *Value) AsInterface() any {")
+ g.P(" switch v := x.GetKind().(type) {")
+ g.P(" case *Value_NumberValue:")
+ g.P(" if v != nil {")
+ g.P(" switch {")
+ g.P(" case ", mathPackage.Ident("IsNaN"), "(v.NumberValue):")
+ g.P(" return \"NaN\"")
+ g.P(" case ", mathPackage.Ident("IsInf"), "(v.NumberValue, +1):")
+ g.P(" return \"Infinity\"")
+ g.P(" case ", mathPackage.Ident("IsInf"), "(v.NumberValue, -1):")
+ g.P(" return \"-Infinity\"")
+ g.P(" default:")
+ g.P(" return v.NumberValue")
+ g.P(" }")
+ g.P(" }")
+ g.P(" case *Value_StringValue:")
+ g.P(" if v != nil {")
+ g.P(" return v.StringValue")
+ g.P(" }")
+ g.P(" case *Value_BoolValue:")
+ g.P(" if v != nil {")
+ g.P(" return v.BoolValue")
+ g.P(" }")
+ g.P(" case *Value_StructValue:")
+ g.P(" if v != nil {")
+ g.P(" return v.StructValue.AsMap()")
+ g.P(" }")
+ g.P(" case *Value_ListValue:")
+ g.P(" if v != nil {")
+ g.P(" return v.ListValue.AsSlice()")
+ g.P(" }")
+ g.P(" }")
+ g.P(" return nil")
+ g.P("}")
+ g.P()
+
+ g.P("func (x *Value) MarshalJSON() ([]byte, error) {")
+ g.P(" return ", protojsonPackage.Ident("Marshal"), "(x)")
+ g.P("}")
+ g.P()
+
+ g.P("func (x *Value) UnmarshalJSON(b []byte) error {")
+ g.P(" return ", protojsonPackage.Ident("Unmarshal"), "(b, x)")
+ g.P("}")
+ g.P()
+
+ case genid.FieldMask_message_fullname:
+ g.P("// New constructs a field mask from a list of paths and verifies that")
+ g.P("// each one is valid according to the specified message type.")
+ g.P("func New(m ", protoPackage.Ident("Message"), ", paths ...string) (*FieldMask, error) {")
+ g.P(" x := new(FieldMask)")
+ g.P(" return x, x.Append(m, paths...)")
+ g.P("}")
+ g.P()
+
+ g.P("// Union returns the union of all the paths in the input field masks.")
+ g.P("func Union(mx *FieldMask, my *FieldMask, ms ...*FieldMask) *FieldMask {")
+ g.P(" var out []string")
+ g.P(" out = append(out, mx.GetPaths()...)")
+ g.P(" out = append(out, my.GetPaths()...)")
+ g.P(" for _, m := range ms {")
+ g.P(" out = append(out, m.GetPaths()...)")
+ g.P(" }")
+ g.P(" return &FieldMask{Paths: normalizePaths(out)}")
+ g.P("}")
+ g.P()
+
+ g.P("// Intersect returns the intersection of all the paths in the input field masks.")
+ g.P("func Intersect(mx *FieldMask, my *FieldMask, ms ...*FieldMask) *FieldMask {")
+ g.P(" var ss1, ss2 []string // reused buffers for performance")
+ g.P(" intersect := func(out, in []string) []string {")
+ g.P(" ss1 = normalizePaths(append(ss1[:0], in...))")
+ g.P(" ss2 = normalizePaths(append(ss2[:0], out...))")
+ g.P(" out = out[:0]")
+ g.P(" for i1, i2 := 0, 0; i1 < len(ss1) && i2 < len(ss2); {")
+ g.P(" switch s1, s2 := ss1[i1], ss2[i2]; {")
+ g.P(" case hasPathPrefix(s1, s2):")
+ g.P(" out = append(out, s1)")
+ g.P(" i1++")
+ g.P(" case hasPathPrefix(s2, s1):")
+ g.P(" out = append(out, s2)")
+ g.P(" i2++")
+ g.P(" case lessPath(s1, s2):")
+ g.P(" i1++")
+ g.P(" case lessPath(s2, s1):")
+ g.P(" i2++")
+ g.P(" }")
+ g.P(" }")
+ g.P(" return out")
+ g.P(" }")
+ g.P()
+ g.P(" out := Union(mx, my, ms...).GetPaths()")
+ g.P(" out = intersect(out, mx.GetPaths())")
+ g.P(" out = intersect(out, my.GetPaths())")
+ g.P(" for _, m := range ms {")
+ g.P(" out = intersect(out, m.GetPaths())")
+ g.P(" }")
+ g.P(" return &FieldMask{Paths: normalizePaths(out)}")
+ g.P("}")
+ g.P()
+
+ g.P("// IsValid reports whether all the paths are syntactically valid and")
+ g.P("// refer to known fields in the specified message type.")
+ g.P("// It reports false for a nil FieldMask.")
+ g.P("func (x *FieldMask) IsValid(m ", protoPackage.Ident("Message"), ") bool {")
+ g.P(" paths := x.GetPaths()")
+ g.P(" return x != nil && numValidPaths(m, paths) == len(paths)")
+ g.P("}")
+ g.P()
+
+ g.P("// Append appends a list of paths to the mask and verifies that each one")
+ g.P("// is valid according to the specified message type.")
+ g.P("// An invalid path is not appended and breaks insertion of subsequent paths.")
+ g.P("func (x *FieldMask) Append(m ", protoPackage.Ident("Message"), ", paths ...string) error {")
+ g.P(" numValid := numValidPaths(m, paths)")
+ g.P(" x.Paths = append(x.Paths, paths[:numValid]...)")
+ g.P(" paths = paths[numValid:]")
+ g.P(" if len(paths) > 0 {")
+ g.P(" name := m.ProtoReflect().Descriptor().FullName()")
+ g.P(" return ", protoimplPackage.Ident("X"), ".NewError(\"invalid path %q for message %q\", paths[0], name)")
+ g.P(" }")
+ g.P(" return nil")
+ g.P("}")
+ g.P()
+
+ g.P("func numValidPaths(m ", protoPackage.Ident("Message"), ", paths []string) int {")
+ g.P(" md0 := m.ProtoReflect().Descriptor()")
+ g.P(" for i, path := range paths {")
+ g.P(" md := md0")
+ g.P(" if !rangeFields(path, func(field string) bool {")
+ g.P(" // Search the field within the message.")
+ g.P(" if md == nil {")
+ g.P(" return false // not within a message")
+ g.P(" }")
+ g.P(" fd := md.Fields().ByName(", protoreflectPackage.Ident("Name"), "(field))")
+ g.P(" // The real field name of a group is the message name.")
+ g.P(" if fd == nil {")
+ g.P(" gd := md.Fields().ByName(", protoreflectPackage.Ident("Name"), "(", stringsPackage.Ident("ToLower"), "(field)))")
+ g.P(" if gd != nil && gd.Kind() == ", protoreflectPackage.Ident("GroupKind"), " && string(gd.Message().Name()) == field {")
+ g.P(" fd = gd")
+ g.P(" }")
+ g.P(" } else if fd.Kind() == ", protoreflectPackage.Ident("GroupKind"), " && string(fd.Message().Name()) != field {")
+ g.P(" fd = nil")
+ g.P(" }")
+ g.P(" if fd == nil {")
+ g.P(" return false // message has does not have this field")
+ g.P(" }")
+ g.P()
+ g.P(" // Identify the next message to search within.")
+ g.P(" md = fd.Message() // may be nil")
+ g.P()
+ g.P(" // Repeated fields are only allowed at the last position.")
+ g.P(" if fd.IsList() || fd.IsMap() {")
+ g.P(" md = nil")
+ g.P(" }")
+ g.P()
+ g.P(" return true")
+ g.P(" }) {")
+ g.P(" return i")
+ g.P(" }")
+ g.P(" }")
+ g.P(" return len(paths)")
+ g.P("}")
+ g.P()
+
+ g.P("// Normalize converts the mask to its canonical form where all paths are sorted")
+ g.P("// and redundant paths are removed.")
+ g.P("func (x *FieldMask) Normalize() {")
+ g.P(" x.Paths = normalizePaths(x.Paths)")
+ g.P("}")
+ g.P()
+ g.P("func normalizePaths(paths []string) []string {")
+ g.P(" ", sortPackage.Ident("Slice"), "(paths, func(i, j int) bool {")
+ g.P(" return lessPath(paths[i], paths[j])")
+ g.P(" })")
+ g.P()
+ g.P(" // Elide any path that is a prefix match on the previous.")
+ g.P(" out := paths[:0]")
+ g.P(" for _, path := range paths {")
+ g.P(" if len(out) > 0 && hasPathPrefix(path, out[len(out)-1]) {")
+ g.P(" continue")
+ g.P(" }")
+ g.P(" out = append(out, path)")
+ g.P(" }")
+ g.P(" return out")
+ g.P("}")
+ g.P()
+
+ g.P("// hasPathPrefix is like strings.HasPrefix, but further checks for either")
+ g.P("// an exact matche or that the prefix is delimited by a dot.")
+ g.P("func hasPathPrefix(path, prefix string) bool {")
+ g.P(" return ", stringsPackage.Ident("HasPrefix"), "(path, prefix) && (len(path) == len(prefix) || path[len(prefix)] == '.')")
+ g.P("}")
+ g.P()
+
+ g.P("// lessPath is a lexicographical comparison where dot is specially treated")
+ g.P("// as the smallest symbol.")
+ g.P("func lessPath(x, y string) bool {")
+ g.P(" for i := 0; i < len(x) && i < len(y); i++ {")
+ g.P(" if x[i] != y[i] {")
+ g.P(" return (x[i] - '.') < (y[i] - '.')")
+ g.P(" }")
+ g.P(" }")
+ g.P(" return len(x) < len(y)")
+ g.P("}")
+ g.P()
+
+ g.P("// rangeFields is like strings.Split(path, \".\"), but avoids allocations by")
+ g.P("// iterating over each field in place and calling a iterator function.")
+ g.P("func rangeFields(path string, f func(field string) bool) bool {")
+ g.P(" for {")
+ g.P(" var field string")
+ g.P(" if i := ", stringsPackage.Ident("IndexByte"), "(path, '.'); i >= 0 {")
+ g.P(" field, path = path[:i], path[i:]")
+ g.P(" } else {")
+ g.P(" field, path = path, \"\"")
+ g.P(" }")
+ g.P()
+ g.P(" if !f(field) {")
+ g.P(" return false")
+ g.P(" }")
+ g.P()
+ g.P(" if len(path) == 0 {")
+ g.P(" return true")
+ g.P(" }")
+ g.P(" path = ", stringsPackage.Ident("TrimPrefix"), "(path, \".\")")
+ g.P(" }")
+ g.P("}")
+ g.P()
+
+ case genid.BoolValue_message_fullname,
+ genid.Int32Value_message_fullname,
+ genid.Int64Value_message_fullname,
+ genid.UInt32Value_message_fullname,
+ genid.UInt64Value_message_fullname,
+ genid.FloatValue_message_fullname,
+ genid.DoubleValue_message_fullname,
+ genid.StringValue_message_fullname,
+ genid.BytesValue_message_fullname:
+ funcName := strings.TrimSuffix(m.GoIdent.GoName, "Value")
+ typeName := strings.ToLower(funcName)
+ switch typeName {
+ case "float":
+ typeName = "float32"
+ case "double":
+ typeName = "float64"
+ case "bytes":
+ typeName = "[]byte"
+ }
+
+ g.P("// ", funcName, " stores v in a new ", m.GoIdent, " and returns a pointer to it.")
+ g.P("func ", funcName, "(v ", typeName, ") *", m.GoIdent, " {")
+ g.P(" return &", m.GoIdent, "{Value: v}")
+ g.P("}")
+ g.P()
+ }
+}
diff --git a/vendor/google.golang.org/protobuf/cmd/protoc-gen-go/main.go b/vendor/google.golang.org/protobuf/cmd/protoc-gen-go/main.go
new file mode 100644
index 00000000000..f3b5acb5e01
--- /dev/null
+++ b/vendor/google.golang.org/protobuf/cmd/protoc-gen-go/main.go
@@ -0,0 +1,60 @@
+// Copyright 2018 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.
+
+// The protoc-gen-go binary is a protoc plugin to generate Go code for
+// both proto2 and proto3 versions of the protocol buffer language.
+//
+// For more information about the usage of this plugin, see:
+// https://protobuf.dev/reference/go/go-generated.
+package main
+
+import (
+ "errors"
+ "flag"
+ "fmt"
+ "os"
+ "path/filepath"
+
+ gengo "google.golang.org/protobuf/cmd/protoc-gen-go/internal_gengo"
+ "google.golang.org/protobuf/compiler/protogen"
+ "google.golang.org/protobuf/internal/version"
+)
+
+const genGoDocURL = "https://protobuf.dev/reference/go/go-generated"
+const grpcDocURL = "https://grpc.io/docs/languages/go/quickstart/#regenerate-grpc-code"
+
+func main() {
+ if len(os.Args) == 2 && os.Args[1] == "--version" {
+ fmt.Fprintf(os.Stdout, "%v %v\n", filepath.Base(os.Args[0]), version.String())
+ os.Exit(0)
+ }
+ if len(os.Args) == 2 && os.Args[1] == "--help" {
+ fmt.Fprintf(os.Stdout, "See "+genGoDocURL+" for usage information.\n")
+ os.Exit(0)
+ }
+
+ var (
+ flags flag.FlagSet
+ plugins = flags.String("plugins", "", "deprecated option")
+ experimentalStripNonFunctionalCodegen = flags.Bool("experimental_strip_nonfunctional_codegen", false, "experimental_strip_nonfunctional_codegen true means that the plugin will not emit certain parts of the generated code in order to make it possible to compare a proto2/proto3 file with its equivalent (according to proto spec) editions file. Primarily, this is the encoded descriptor.")
+ )
+ protogen.Options{
+ ParamFunc: flags.Set,
+ InternalStripForEditionsDiff: experimentalStripNonFunctionalCodegen,
+ }.Run(func(gen *protogen.Plugin) error {
+ if *plugins != "" {
+ return errors.New("protoc-gen-go: plugins are not supported; use 'protoc --go-grpc_out=...' to generate gRPC\n\n" +
+ "See " + grpcDocURL + " for more information.")
+ }
+ for _, f := range gen.Files {
+ if f.Generate {
+ gengo.GenerateFile(gen, f)
+ }
+ }
+ gen.SupportedFeatures = gengo.SupportedFeatures
+ gen.SupportedEditionsMinimum = gengo.SupportedEditionsMinimum
+ gen.SupportedEditionsMaximum = gengo.SupportedEditionsMaximum
+ return nil
+ })
+}
diff --git a/vendor/google.golang.org/protobuf/compiler/protogen/protogen.go b/vendor/google.golang.org/protobuf/compiler/protogen/protogen.go
new file mode 100644
index 00000000000..f7f295aa558
--- /dev/null
+++ b/vendor/google.golang.org/protobuf/compiler/protogen/protogen.go
@@ -0,0 +1,1567 @@
+// Copyright 2018 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 protogen provides support for writing protoc plugins.
+//
+// Plugins for protoc, the Protocol Buffer compiler,
+// are programs which read a [pluginpb.CodeGeneratorRequest] message from standard input
+// and write a [pluginpb.CodeGeneratorResponse] message to standard output.
+// This package provides support for writing plugins which generate Go code.
+package protogen
+
+import (
+ "bufio"
+ "bytes"
+ "fmt"
+ "go/ast"
+ "go/parser"
+ "go/printer"
+ "go/token"
+ "go/types"
+ "io"
+ "os"
+ "path"
+ "path/filepath"
+ "sort"
+ "strconv"
+ "strings"
+
+ "google.golang.org/protobuf/encoding/prototext"
+ "google.golang.org/protobuf/internal/filedesc"
+ "google.golang.org/protobuf/internal/genid"
+ "google.golang.org/protobuf/internal/strs"
+ "google.golang.org/protobuf/proto"
+ "google.golang.org/protobuf/reflect/protodesc"
+ "google.golang.org/protobuf/reflect/protoreflect"
+ "google.golang.org/protobuf/reflect/protoregistry"
+ "google.golang.org/protobuf/types/dynamicpb"
+
+ "google.golang.org/protobuf/types/descriptorpb"
+ "google.golang.org/protobuf/types/gofeaturespb"
+ "google.golang.org/protobuf/types/pluginpb"
+)
+
+const goPackageDocURL = "https://protobuf.dev/reference/go/go-generated#package"
+
+// Run executes a function as a protoc plugin.
+//
+// It reads a [pluginpb.CodeGeneratorRequest] message from [os.Stdin], invokes the plugin
+// function, and writes a [pluginpb.CodeGeneratorResponse] message to [os.Stdout].
+//
+// If a failure occurs while reading or writing, Run prints an error to
+// [os.Stderr] and calls [os.Exit](1).
+func (opts Options) Run(f func(*Plugin) error) {
+ if err := run(opts, f); err != nil {
+ fmt.Fprintf(os.Stderr, "%s: %v\n", filepath.Base(os.Args[0]), err)
+ os.Exit(1)
+ }
+}
+
+func run(opts Options, f func(*Plugin) error) error {
+ if len(os.Args) > 1 {
+ return fmt.Errorf("unknown argument %q (this program should be run by protoc, not directly)", os.Args[1])
+ }
+ in, err := io.ReadAll(os.Stdin)
+ if err != nil {
+ return err
+ }
+ req := &pluginpb.CodeGeneratorRequest{}
+ if err := proto.Unmarshal(in, req); err != nil {
+ return err
+ }
+ gen, err := opts.New(req)
+ if err != nil {
+ return err
+ }
+ if err := f(gen); err != nil {
+ // Errors from the plugin function are reported by setting the
+ // error field in the CodeGeneratorResponse.
+ //
+ // In contrast, errors that indicate a problem in protoc
+ // itself (unparsable input, I/O errors, etc.) are reported
+ // to stderr.
+ gen.Error(err)
+ }
+ resp := gen.Response()
+ out, err := proto.Marshal(resp)
+ if err != nil {
+ return err
+ }
+ if _, err := os.Stdout.Write(out); err != nil {
+ return err
+ }
+ return nil
+}
+
+// A Plugin is a protoc plugin invocation.
+type Plugin struct {
+ // Request is the CodeGeneratorRequest provided by protoc.
+ Request *pluginpb.CodeGeneratorRequest
+
+ // Files is the set of files to generate and everything they import.
+ // Files appear in topological order, so each file appears before any
+ // file that imports it.
+ Files []*File
+ FilesByPath map[string]*File
+
+ // SupportedFeatures is the set of protobuf language features supported by
+ // this generator plugin. See the documentation for
+ // google.protobuf.CodeGeneratorResponse.supported_features for details.
+ SupportedFeatures uint64
+
+ SupportedEditionsMinimum descriptorpb.Edition
+ SupportedEditionsMaximum descriptorpb.Edition
+
+ fileReg *protoregistry.Files
+ enumsByName map[protoreflect.FullName]*Enum
+ messagesByName map[protoreflect.FullName]*Message
+ annotateCode bool
+ pathType pathType
+ module string
+ genFiles []*GeneratedFile
+ opts Options
+ err error
+}
+
+type Options struct {
+ // If ParamFunc is non-nil, it will be called with each unknown
+ // generator parameter.
+ //
+ // Plugins for protoc can accept parameters from the command line,
+ // passed in the --_out protoc, separated from the output
+ // directory with a colon; e.g.,
+ //
+ // --go_out==,=:
+ //
+ // Parameters passed in this fashion as a comma-separated list of
+ // key=value pairs will be passed to the ParamFunc.
+ //
+ // The (flag.FlagSet).Set method matches this function signature,
+ // so parameters can be converted into flags as in the following:
+ //
+ // var flags flag.FlagSet
+ // value := flags.Bool("param", false, "")
+ // opts := &protogen.Options{
+ // ParamFunc: flags.Set,
+ // }
+ // opts.Run(func(p *protogen.Plugin) error {
+ // if *value { ... }
+ // })
+ ParamFunc func(name, value string) error
+
+ // ImportRewriteFunc is called with the import path of each package
+ // imported by a generated file. It returns the import path to use
+ // for this package.
+ ImportRewriteFunc func(GoImportPath) GoImportPath
+
+ // StripForEditionsDiff true means that the plugin will not emit certain
+ // parts of the generated code in order to make it possible to compare a
+ // proto2/proto3 file with its equivalent (according to proto spec)
+ // editions file. Primarily, this is the encoded descriptor.
+ //
+ // This must be a registered flag that is initialized by ParamFunc. It will
+ // be used by Options.New after it has parsed the flags.
+ //
+ // This struct field is for internal use by Go Protobuf only. Do not use it,
+ // we might remove it at any time.
+ InternalStripForEditionsDiff *bool
+
+ // DefaultAPILevel overrides which API to generate by default (despite what
+ // the editions feature default specifies). One of OPEN, HYBRID or OPAQUE.
+ DefaultAPILevel gofeaturespb.GoFeatures_APILevel
+}
+
+// New returns a new Plugin.
+func (opts Options) New(req *pluginpb.CodeGeneratorRequest) (*Plugin, error) {
+ gen := &Plugin{
+ Request: req,
+ FilesByPath: make(map[string]*File),
+ fileReg: new(protoregistry.Files),
+ enumsByName: make(map[protoreflect.FullName]*Enum),
+ messagesByName: make(map[protoreflect.FullName]*Message),
+ opts: opts,
+ }
+
+ packageNames := make(map[string]GoPackageName) // filename -> package name
+ importPaths := make(map[string]GoImportPath) // filename -> import path
+ apiLevel := make(map[string]gofeaturespb.GoFeatures_APILevel) // filename -> api level
+ for _, param := range strings.Split(req.GetParameter(), ",") {
+ var value string
+ if i := strings.Index(param, "="); i >= 0 {
+ value = param[i+1:]
+ param = param[0:i]
+ }
+ switch param {
+ case "":
+ // Ignore.
+ case "module":
+ gen.module = value
+ case "paths":
+ switch value {
+ case "import":
+ gen.pathType = pathTypeImport
+ case "source_relative":
+ gen.pathType = pathTypeSourceRelative
+ default:
+ return nil, fmt.Errorf(`unknown path type %q: want "import" or "source_relative"`, value)
+ }
+ case "annotate_code":
+ switch value {
+ case "true", "":
+ gen.annotateCode = true
+ case "false":
+ default:
+ return nil, fmt.Errorf(`bad value for parameter %q: want "true" or "false"`, param)
+ }
+ case "default_api_level":
+ switch value {
+ case "API_OPEN":
+ opts.DefaultAPILevel = gofeaturespb.GoFeatures_API_OPEN
+ case "API_HYBRID":
+ opts.DefaultAPILevel = gofeaturespb.GoFeatures_API_HYBRID
+ case "API_OPAQUE":
+ opts.DefaultAPILevel = gofeaturespb.GoFeatures_API_OPAQUE
+ default:
+ return nil, fmt.Errorf(`unknown API level %q for parameter %q: want "API_OPEN", "API_HYBRID" or "API_OPAQUE"`, value, param)
+ }
+ gen.opts = opts
+ default:
+ if param[0] == 'M' {
+ impPath, pkgName := splitImportPathAndPackageName(value)
+ if pkgName != "" {
+ packageNames[param[1:]] = pkgName
+ }
+ if impPath != "" {
+ importPaths[param[1:]] = impPath
+ }
+ continue
+ }
+ if strings.HasPrefix(param, "apilevelM") {
+ var level gofeaturespb.GoFeatures_APILevel
+ switch value {
+ case "API_OPEN":
+ level = gofeaturespb.GoFeatures_API_OPEN
+ case "API_HYBRID":
+ level = gofeaturespb.GoFeatures_API_HYBRID
+ case "API_OPAQUE":
+ level = gofeaturespb.GoFeatures_API_OPAQUE
+ default:
+ return nil, fmt.Errorf(`unknown API level %q for parameter %q: want "API_OPEN", "API_HYBRID" or "API_OPAQUE"`, value, param)
+ }
+ apiLevel[strings.TrimPrefix(param, "apilevelM")] = level
+ continue
+ }
+ if opts.ParamFunc != nil {
+ if err := opts.ParamFunc(param, value); err != nil {
+ return nil, err
+ }
+ }
+ }
+ }
+
+ // When the module= option is provided, we strip the module name
+ // prefix from generated files. This only makes sense if generated
+ // filenames are based on the import path.
+ if gen.module != "" && gen.pathType == pathTypeSourceRelative {
+ return nil, fmt.Errorf("cannot use module= with paths=source_relative")
+ }
+
+ // Figure out the import path and package name for each file.
+ //
+ // The rules here are complicated and have grown organically over time.
+ // Interactions between different ways of specifying package information
+ // may be surprising.
+ //
+ // The recommended approach is to include a go_package option in every
+ // .proto source file specifying the full import path of the Go package
+ // associated with this file.
+ //
+ // option go_package = "google.golang.org/protobuf/types/known/anypb";
+ //
+ // Alternatively, build systems which want to exert full control over
+ // import paths may specify M= flags.
+ for _, fdesc := range gen.Request.ProtoFile {
+ filename := fdesc.GetName()
+ // The "M" command-line flags take precedence over
+ // the "go_package" option in the .proto source file.
+ impPath, pkgName := splitImportPathAndPackageName(fdesc.GetOptions().GetGoPackage())
+ if importPaths[filename] == "" && impPath != "" {
+ importPaths[filename] = impPath
+ }
+ if packageNames[filename] == "" && pkgName != "" {
+ packageNames[filename] = pkgName
+ }
+ switch {
+ case importPaths[filename] == "":
+ // The import path must be specified one way or another.
+ return nil, fmt.Errorf(
+ "unable to determine Go import path for %q\n\n"+
+ "Please specify either:\n"+
+ "\t• a \"go_package\" option in the .proto source file, or\n"+
+ "\t• a \"M\" argument on the command line.\n\n"+
+ "See %v for more information.\n",
+ fdesc.GetName(), goPackageDocURL)
+ case !strings.Contains(string(importPaths[filename]), ".") &&
+ !strings.Contains(string(importPaths[filename]), "/"):
+ // Check that import paths contain at least a dot or slash to avoid
+ // a common mistake where import path is confused with package name.
+ return nil, fmt.Errorf(
+ "invalid Go import path %q for %q\n\n"+
+ "The import path must contain at least one period ('.') or forward slash ('/') character.\n\n"+
+ "See %v for more information.\n",
+ string(importPaths[filename]), fdesc.GetName(), goPackageDocURL)
+ case packageNames[filename] == "":
+ // If the package name is not explicitly specified,
+ // then derive a reasonable package name from the import path.
+ //
+ // NOTE: The package name is derived first from the import path in
+ // the "go_package" option (if present) before trying the "M" flag.
+ // The inverted order for this is because the primary use of the "M"
+ // flag is by build systems that have full control over the
+ // import paths all packages, where it is generally expected that
+ // the Go package name still be identical for the Go toolchain and
+ // for custom build systems like Bazel.
+ if impPath == "" {
+ impPath = importPaths[filename]
+ }
+ packageNames[filename] = cleanPackageName(path.Base(string(impPath)))
+ }
+ }
+
+ // Consistency check: Every file with the same Go import path should have
+ // the same Go package name.
+ packageFiles := make(map[GoImportPath][]string)
+ for filename, importPath := range importPaths {
+ if _, ok := packageNames[filename]; !ok {
+ // Skip files mentioned in a M= parameter
+ // but which do not appear in the CodeGeneratorRequest.
+ continue
+ }
+ packageFiles[importPath] = append(packageFiles[importPath], filename)
+ }
+ for importPath, filenames := range packageFiles {
+ for i := 1; i < len(filenames); i++ {
+ if a, b := packageNames[filenames[0]], packageNames[filenames[i]]; a != b {
+ return nil, fmt.Errorf("Go package %v has inconsistent names %v (%v) and %v (%v)",
+ importPath, a, filenames[0], b, filenames[i])
+ }
+ }
+ }
+
+ // The extracted types from the full import set
+ typeRegistry := newExtensionRegistry()
+ for _, fdesc := range gen.Request.ProtoFile {
+ filename := fdesc.GetName()
+ if gen.FilesByPath[filename] != nil {
+ return nil, fmt.Errorf("duplicate file name: %q", filename)
+ }
+ f, err := newFile(gen, fdesc, packageNames[filename], importPaths[filename], apiLevel[filename])
+ if err != nil {
+ return nil, err
+ }
+ gen.Files = append(gen.Files, f)
+ gen.FilesByPath[filename] = f
+ if err = typeRegistry.registerAllExtensionsFromFile(f.Desc); err != nil {
+ return nil, err
+ }
+ }
+ for _, filename := range gen.Request.FileToGenerate {
+ f, ok := gen.FilesByPath[filename]
+ if !ok {
+ return nil, fmt.Errorf("no descriptor for generated file: %v", filename)
+ }
+ f.Generate = true
+ }
+
+ // Create fully-linked descriptors if new extensions were found
+ if typeRegistry.hasNovelExtensions() {
+ for _, f := range gen.Files {
+ b, err := proto.Marshal(f.Proto.ProtoReflect().Interface())
+ if err != nil {
+ return nil, err
+ }
+ err = proto.UnmarshalOptions{Resolver: typeRegistry}.Unmarshal(b, f.Proto)
+ if err != nil {
+ return nil, err
+ }
+ }
+ }
+ return gen, nil
+}
+
+// InternalStripForEditionsDiff returns whether or not to strip non-functional
+// codegen for editions diff testing.
+//
+// This function is for internal use by Go Protobuf only. Do not use it, we
+// might remove it at any time.
+func (gen *Plugin) InternalStripForEditionsDiff() bool {
+ return gen.opts.InternalStripForEditionsDiff != nil && *gen.opts.InternalStripForEditionsDiff
+}
+
+// Error records an error in code generation. The generator will report the
+// error back to protoc and will not produce output.
+func (gen *Plugin) Error(err error) {
+ if gen.err == nil {
+ gen.err = err
+ }
+}
+
+// Response returns the generator output.
+func (gen *Plugin) Response() *pluginpb.CodeGeneratorResponse {
+ resp := &pluginpb.CodeGeneratorResponse{}
+ // Always report the support for editions. Otherwise protoc might obfuscate
+ // the error by saying editions are not supported by the plugin.
+ // It is arguable if protoc should handle this but it is possible that the
+ // error only exists because the plugin does not support editions and thus
+ // it is not unreasonable for protoc to suspect it is the lack of editions
+ // support that led to this error.
+ if gen.SupportedFeatures > 0 {
+ resp.SupportedFeatures = proto.Uint64(gen.SupportedFeatures)
+ }
+ if gen.SupportedEditionsMinimum != descriptorpb.Edition_EDITION_UNKNOWN && gen.SupportedEditionsMaximum != descriptorpb.Edition_EDITION_UNKNOWN {
+ resp.MinimumEdition = proto.Int32(int32(gen.SupportedEditionsMinimum))
+ resp.MaximumEdition = proto.Int32(int32(gen.SupportedEditionsMaximum))
+ }
+
+ if gen.err != nil {
+ resp.Error = proto.String(gen.err.Error())
+ return resp
+ }
+ for _, g := range gen.genFiles {
+ if g.skip {
+ continue
+ }
+ content, err := g.Content()
+ if err != nil {
+ return &pluginpb.CodeGeneratorResponse{
+ Error: proto.String(err.Error()),
+ }
+ }
+ filename := g.filename
+ if gen.module != "" {
+ trim := gen.module + "/"
+ if !strings.HasPrefix(filename, trim) {
+ return &pluginpb.CodeGeneratorResponse{
+ Error: proto.String(fmt.Sprintf("%v: generated file does not match prefix %q", filename, gen.module)),
+ }
+ }
+ filename = strings.TrimPrefix(filename, trim)
+ }
+ resp.File = append(resp.File, &pluginpb.CodeGeneratorResponse_File{
+ Name: proto.String(filename),
+ Content: proto.String(string(content)),
+ })
+ if gen.annotateCode && strings.HasSuffix(g.filename, ".go") {
+ meta, err := g.metaFile(content)
+ if err != nil {
+ return &pluginpb.CodeGeneratorResponse{
+ Error: proto.String(err.Error()),
+ }
+ }
+ resp.File = append(resp.File, &pluginpb.CodeGeneratorResponse_File{
+ Name: proto.String(filename + ".meta"),
+ Content: proto.String(meta),
+ })
+ }
+ }
+ return resp
+}
+
+// A File describes a .proto source file.
+type File struct {
+ Desc protoreflect.FileDescriptor
+ Proto *descriptorpb.FileDescriptorProto
+
+ GoDescriptorIdent GoIdent // name of Go variable for the file descriptor
+ GoPackageName GoPackageName // name of this file's Go package
+ GoImportPath GoImportPath // import path of this file's Go package
+
+ Enums []*Enum // top-level enum declarations
+ Messages []*Message // top-level message declarations
+ Extensions []*Extension // top-level extension declarations
+ Services []*Service // top-level service declarations
+
+ Generate bool // true if we should generate code for this file
+
+ // GeneratedFilenamePrefix is used to construct filenames for generated
+ // files associated with this source file.
+ //
+ // For example, the source file "dir/foo.proto" might have a filename prefix
+ // of "dir/foo". Appending ".pb.go" produces an output file of "dir/foo.pb.go".
+ GeneratedFilenamePrefix string
+
+ location Location
+
+ // APILevel specifies which API to generate. One of OPEN, HYBRID or OPAQUE.
+ APILevel gofeaturespb.GoFeatures_APILevel
+}
+
+func newFile(gen *Plugin, p *descriptorpb.FileDescriptorProto, packageName GoPackageName, importPath GoImportPath, apiLevel gofeaturespb.GoFeatures_APILevel) (*File, error) {
+ desc, err := protodesc.NewFile(p, gen.fileReg)
+ if err != nil {
+ return nil, fmt.Errorf("invalid FileDescriptorProto %q: %v", p.GetName(), err)
+ }
+ if err := gen.fileReg.RegisterFile(desc); err != nil {
+ return nil, fmt.Errorf("cannot register descriptor %q: %v", p.GetName(), err)
+ }
+ defaultAPILevel := gen.defaultAPILevel()
+ if apiLevel != gofeaturespb.GoFeatures_API_LEVEL_UNSPECIFIED {
+ defaultAPILevel = apiLevel
+ }
+ f := &File{
+ Desc: desc,
+ Proto: p,
+ GoPackageName: packageName,
+ GoImportPath: importPath,
+ location: Location{SourceFile: desc.Path()},
+
+ APILevel: fileAPILevel(desc, defaultAPILevel),
+ }
+
+ // Determine the prefix for generated Go files.
+ prefix := p.GetName()
+ if ext := path.Ext(prefix); ext == ".proto" || ext == ".protodevel" {
+ prefix = prefix[:len(prefix)-len(ext)]
+ }
+ switch gen.pathType {
+ case pathTypeImport:
+ // If paths=import, the output filename is derived from the Go import path.
+ prefix = path.Join(string(f.GoImportPath), path.Base(prefix))
+ case pathTypeSourceRelative:
+ // If paths=source_relative, the output filename is derived from
+ // the input filename.
+ }
+ f.GoDescriptorIdent = GoIdent{
+ GoName: "File_" + strs.GoSanitized(p.GetName()),
+ GoImportPath: f.GoImportPath,
+ }
+ f.GeneratedFilenamePrefix = prefix
+
+ for i, eds := 0, desc.Enums(); i < eds.Len(); i++ {
+ f.Enums = append(f.Enums, newEnum(gen, f, nil, eds.Get(i)))
+ }
+ for i, mds := 0, desc.Messages(); i < mds.Len(); i++ {
+ f.Messages = append(f.Messages, newMessage(gen, f, nil, mds.Get(i)))
+ }
+ for i, xds := 0, desc.Extensions(); i < xds.Len(); i++ {
+ f.Extensions = append(f.Extensions, newField(gen, f, nil, xds.Get(i)))
+ }
+ for i, sds := 0, desc.Services(); i < sds.Len(); i++ {
+ f.Services = append(f.Services, newService(gen, f, sds.Get(i)))
+ }
+ for _, message := range f.Messages {
+ if err := message.resolveDependencies(gen); err != nil {
+ return nil, err
+ }
+ }
+ for _, extension := range f.Extensions {
+ if err := extension.resolveDependencies(gen); err != nil {
+ return nil, err
+ }
+ }
+ for _, service := range f.Services {
+ for _, method := range service.Methods {
+ if err := method.resolveDependencies(gen); err != nil {
+ return nil, err
+ }
+ }
+ }
+ return f, nil
+}
+
+// splitImportPathAndPackageName splits off the optional Go package name
+// from the Go import path when separated by a ';' delimiter.
+func splitImportPathAndPackageName(s string) (GoImportPath, GoPackageName) {
+ if i := strings.Index(s, ";"); i >= 0 {
+ return GoImportPath(s[:i]), GoPackageName(s[i+1:])
+ }
+ return GoImportPath(s), ""
+}
+
+// An Enum describes an enum.
+type Enum struct {
+ Desc protoreflect.EnumDescriptor
+
+ GoIdent GoIdent // name of the generated Go type
+
+ Values []*EnumValue // enum value declarations
+
+ Location Location // location of this enum
+ Comments CommentSet // comments associated with this enum
+}
+
+func newEnum(gen *Plugin, f *File, parent *Message, desc protoreflect.EnumDescriptor) *Enum {
+ var loc Location
+ if parent != nil {
+ loc = parent.Location.appendPath(genid.DescriptorProto_EnumType_field_number, desc.Index())
+ } else {
+ loc = f.location.appendPath(genid.FileDescriptorProto_EnumType_field_number, desc.Index())
+ }
+ enum := &Enum{
+ Desc: desc,
+ GoIdent: newGoIdent(f, desc),
+ Location: loc,
+ Comments: makeCommentSet(gen, f.Desc.SourceLocations().ByDescriptor(desc)),
+ }
+ gen.enumsByName[desc.FullName()] = enum
+ for i, vds := 0, enum.Desc.Values(); i < vds.Len(); i++ {
+ enum.Values = append(enum.Values, newEnumValue(gen, f, parent, enum, vds.Get(i)))
+ }
+ return enum
+}
+
+// An EnumValue describes an enum value.
+type EnumValue struct {
+ Desc protoreflect.EnumValueDescriptor
+
+ GoIdent GoIdent // name of the generated Go declaration
+
+ // PrefixedAlias is usually empty, except when the strip_enum_prefix feature
+ // for this enum was set to GENERATE_BOTH, in which case PrefixedAlias holds
+ // the old name which should be generated as an alias for the new name for
+ // compatibility.
+ PrefixedAlias GoIdent
+
+ Parent *Enum // enum in which this value is declared
+
+ Location Location // location of this enum value
+ Comments CommentSet // comments associated with this enum value
+}
+
+func newEnumValue(gen *Plugin, f *File, message *Message, enum *Enum, desc protoreflect.EnumValueDescriptor) *EnumValue {
+ // A top-level enum value's name is: EnumName_ValueName
+ // An enum value contained in a message is: MessageName_ValueName
+ //
+ // For historical reasons, enum value names are not camel-cased.
+ parentIdent := enum.GoIdent
+ if message != nil {
+ parentIdent = message.GoIdent
+ }
+ name := parentIdent.GoName + "_" + string(desc.Name())
+ var prefixedName string
+ loc := enum.Location.appendPath(genid.EnumDescriptorProto_Value_field_number, desc.Index())
+ if ed, ok := enum.Desc.(*filedesc.Enum); ok {
+ prefix := strings.Replace(strings.ToLower(string(enum.Desc.Name())), "_", "", -1)
+
+ // Start with the StripEnumPrefix of the enum descriptor,
+ // then override it with the StripEnumPrefix of the enum value descriptor,
+ // if any.
+ sep := ed.L1.EditionFeatures.StripEnumPrefix
+ evof := desc.Options().(*descriptorpb.EnumValueOptions).GetFeatures()
+ if proto.HasExtension(evof, gofeaturespb.E_Go) {
+ gf := proto.GetExtension(evof, gofeaturespb.E_Go).(*gofeaturespb.GoFeatures)
+ if gf.StripEnumPrefix != nil {
+ sep = int(*gf.StripEnumPrefix)
+ }
+ }
+
+ switch sep {
+ case genid.GoFeatures_STRIP_ENUM_PREFIX_KEEP_enum_value:
+ // keep long name
+
+ case genid.GoFeatures_STRIP_ENUM_PREFIX_STRIP_enum_value:
+ name = parentIdent.GoName + "_" + strs.TrimEnumPrefix(string(desc.Name()), prefix)
+
+ case genid.GoFeatures_STRIP_ENUM_PREFIX_GENERATE_BOTH_enum_value:
+ prefixedName = name
+ name = parentIdent.GoName + "_" + strs.TrimEnumPrefix(string(desc.Name()), prefix)
+ }
+ }
+ ev := &EnumValue{
+ Desc: desc,
+ GoIdent: f.GoImportPath.Ident(name),
+ Parent: enum,
+ Location: loc,
+ Comments: makeCommentSet(gen, f.Desc.SourceLocations().ByDescriptor(desc)),
+ }
+ if prefixedName != "" {
+ ev.PrefixedAlias = f.GoImportPath.Ident(prefixedName)
+ }
+ return ev
+}
+
+// A Message describes a message.
+type Message struct {
+ Desc protoreflect.MessageDescriptor
+
+ GoIdent GoIdent // name of the generated Go type
+
+ Fields []*Field // message field declarations
+ Oneofs []*Oneof // message oneof declarations
+
+ Enums []*Enum // nested enum declarations
+ Messages []*Message // nested message declarations
+ Extensions []*Extension // nested extension declarations
+
+ Location Location // location of this message
+ Comments CommentSet // comments associated with this message
+
+ // APILevel specifies which API to generate. One of OPEN, HYBRID or OPAQUE.
+ APILevel gofeaturespb.GoFeatures_APILevel
+}
+
+func newMessage(gen *Plugin, f *File, parent *Message, desc protoreflect.MessageDescriptor) *Message {
+ var loc Location
+ if parent != nil {
+ loc = parent.Location.appendPath(genid.DescriptorProto_NestedType_field_number, desc.Index())
+ } else {
+ loc = f.location.appendPath(genid.FileDescriptorProto_MessageType_field_number, desc.Index())
+ }
+
+ def := f.APILevel
+ if parent != nil {
+ // editions feature semantics: applies to nested messages.
+ def = parent.APILevel
+ }
+
+ message := &Message{
+ Desc: desc,
+ GoIdent: newGoIdent(f, desc),
+ Location: loc,
+ Comments: makeCommentSet(gen, f.Desc.SourceLocations().ByDescriptor(desc)),
+
+ APILevel: messageAPILevel(desc, def),
+ }
+ gen.messagesByName[desc.FullName()] = message
+ for i, eds := 0, desc.Enums(); i < eds.Len(); i++ {
+ message.Enums = append(message.Enums, newEnum(gen, f, message, eds.Get(i)))
+ }
+ for i, mds := 0, desc.Messages(); i < mds.Len(); i++ {
+ message.Messages = append(message.Messages, newMessage(gen, f, message, mds.Get(i)))
+ }
+ for i, fds := 0, desc.Fields(); i < fds.Len(); i++ {
+ message.Fields = append(message.Fields, newField(gen, f, message, fds.Get(i)))
+ }
+ for i, ods := 0, desc.Oneofs(); i < ods.Len(); i++ {
+ message.Oneofs = append(message.Oneofs, newOneof(gen, f, message, ods.Get(i)))
+ }
+ for i, xds := 0, desc.Extensions(); i < xds.Len(); i++ {
+ message.Extensions = append(message.Extensions, newField(gen, f, message, xds.Get(i)))
+ }
+
+ // Resolve local references between fields and oneofs.
+ for _, field := range message.Fields {
+ if od := field.Desc.ContainingOneof(); od != nil {
+ oneof := message.Oneofs[od.Index()]
+ field.Oneof = oneof
+ oneof.Fields = append(oneof.Fields, field)
+ }
+ }
+
+ // Field name conflict resolution.
+ //
+ // We assume well-known method names that may be attached to a generated
+ // message type, as well as a 'Get*' method for each field. For each
+ // field in turn, we add _s to its name until there are no conflicts.
+ //
+ // Any change to the following set of method names is a potential
+ // incompatible API change because it may change generated field names.
+ //
+ // TODO: If we ever support a 'go_name' option to set the Go name of a
+ // field, we should consider dropping this entirely. The conflict
+ // resolution algorithm is subtle and surprising (changing the order
+ // in which fields appear in the .proto source file can change the
+ // names of fields in generated code), and does not adapt well to
+ // adding new per-field methods such as setters.
+ usedNames := map[string]bool{
+ "Reset": true,
+ "String": true,
+ "ProtoMessage": true,
+ "Marshal": true,
+ "Unmarshal": true,
+ "ExtensionRangeArray": true,
+ "ExtensionMap": true,
+ "Descriptor": true,
+ }
+ makeNameUnique := func(name string, hasGetter bool) string {
+ for usedNames[name] || (hasGetter && usedNames["Get"+name]) {
+ name += "_"
+ }
+ usedNames[name] = true
+ usedNames["Get"+name] = hasGetter
+ return name
+ }
+ for _, field := range message.Fields {
+ field.GoName = makeNameUnique(field.GoName, true)
+ field.GoIdent.GoName = message.GoIdent.GoName + "_" + field.GoName
+ if field.Oneof != nil && field.Oneof.Fields[0] == field {
+ // Make the name for a oneof unique as well. For historical reasons,
+ // this assumes that a getter method is not generated for oneofs.
+ // This is incorrect, but fixing it breaks existing code.
+ field.Oneof.GoName = makeNameUnique(field.Oneof.GoName, false)
+ field.Oneof.GoIdent.GoName = message.GoIdent.GoName + "_" + field.Oneof.GoName
+ }
+ }
+
+ // Oneof field name conflict resolution.
+ //
+ // This conflict resolution is incomplete as it does not consider collisions
+ // with other oneof field types, but fixing it breaks existing code.
+ for _, field := range message.Fields {
+ if field.Oneof != nil {
+ Loop:
+ for {
+ for _, nestedMessage := range message.Messages {
+ if nestedMessage.GoIdent == field.GoIdent {
+ field.GoIdent.GoName += "_"
+ continue Loop
+ }
+ }
+ for _, nestedEnum := range message.Enums {
+ if nestedEnum.GoIdent == field.GoIdent {
+ field.GoIdent.GoName += "_"
+ continue Loop
+ }
+ }
+ break Loop
+ }
+ }
+ }
+
+ opaqueNewMessageHook(message)
+
+ return message
+}
+
+func (message *Message) resolveDependencies(gen *Plugin) error {
+ for _, field := range message.Fields {
+ if err := field.resolveDependencies(gen); err != nil {
+ return err
+ }
+ }
+ for _, message := range message.Messages {
+ if err := message.resolveDependencies(gen); err != nil {
+ return err
+ }
+ }
+ for _, extension := range message.Extensions {
+ if err := extension.resolveDependencies(gen); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// A Field describes a message field.
+type Field struct {
+ Desc protoreflect.FieldDescriptor
+
+ // GoName is the base name of this field's Go field and methods.
+ // For code generated by protoc-gen-go, this means a field named
+ // '{{GoName}}' and a getter method named 'Get{{GoName}}'.
+ GoName string // e.g., "FieldName"
+
+ // GoIdent is the base name of a top-level declaration for this field.
+ // For code generated by protoc-gen-go, this means a wrapper type named
+ // '{{GoIdent}}' for members fields of a oneof, and a variable named
+ // 'E_{{GoIdent}}' for extension fields.
+ GoIdent GoIdent // e.g., "MessageName_FieldName"
+
+ Parent *Message // message in which this field is declared; nil if top-level extension
+ Oneof *Oneof // containing oneof; nil if not part of a oneof
+ Extendee *Message // extended message for extension fields; nil otherwise
+
+ Enum *Enum // type for enum fields; nil otherwise
+ Message *Message // type for message or group fields; nil otherwise
+
+ Location Location // location of this field
+ Comments CommentSet // comments associated with this field
+
+ // camelCase is the same as GoName, but without the name
+ // mangling. This is used in builders, where only the single
+ // name "Build" needs to be mangled.
+ camelCase string
+
+ // hasConflictHybrid tells us if we are to insert an '_' into
+ // the method names, (e.g. SetFoo becomes Set_Foo). This will
+ // be set even if we generate opaque protos, as we will want
+ // to potentially generate these method names anyway
+ // (opaque-v0).
+ hasConflictHybrid bool
+}
+
+func newField(gen *Plugin, f *File, message *Message, desc protoreflect.FieldDescriptor) *Field {
+ var loc Location
+ switch {
+ case desc.IsExtension() && message == nil:
+ loc = f.location.appendPath(genid.FileDescriptorProto_Extension_field_number, desc.Index())
+ case desc.IsExtension() && message != nil:
+ loc = message.Location.appendPath(genid.DescriptorProto_Extension_field_number, desc.Index())
+ default:
+ loc = message.Location.appendPath(genid.DescriptorProto_Field_field_number, desc.Index())
+ }
+ camelCased := strs.GoCamelCase(string(desc.Name()))
+ var parentPrefix string
+ if message != nil {
+ parentPrefix = message.GoIdent.GoName + "_"
+ }
+ field := &Field{
+ Desc: desc,
+ GoName: camelCased,
+ GoIdent: GoIdent{
+ GoImportPath: f.GoImportPath,
+ GoName: parentPrefix + camelCased,
+ },
+ Parent: message,
+ Location: loc,
+ Comments: makeCommentSet(gen, f.Desc.SourceLocations().ByDescriptor(desc)),
+ }
+
+ opaqueNewFieldHook(desc, field)
+
+ return field
+}
+
+func (field *Field) resolveDependencies(gen *Plugin) error {
+ desc := field.Desc
+ switch desc.Kind() {
+ case protoreflect.EnumKind:
+ name := field.Desc.Enum().FullName()
+ enum, ok := gen.enumsByName[name]
+ if !ok {
+ return fmt.Errorf("field %v: no descriptor for enum %v", desc.FullName(), name)
+ }
+ field.Enum = enum
+ case protoreflect.MessageKind, protoreflect.GroupKind:
+ name := desc.Message().FullName()
+ message, ok := gen.messagesByName[name]
+ if !ok {
+ return fmt.Errorf("field %v: no descriptor for type %v", desc.FullName(), name)
+ }
+ field.Message = message
+ }
+ if desc.IsExtension() {
+ name := desc.ContainingMessage().FullName()
+ message, ok := gen.messagesByName[name]
+ if !ok {
+ return fmt.Errorf("field %v: no descriptor for type %v", desc.FullName(), name)
+ }
+ field.Extendee = message
+ }
+ return nil
+}
+
+// A Oneof describes a message oneof.
+type Oneof struct {
+ Desc protoreflect.OneofDescriptor
+
+ // GoName is the base name of this oneof's Go field and methods.
+ // For code generated by protoc-gen-go, this means a field named
+ // '{{GoName}}' and a getter method named 'Get{{GoName}}'.
+ GoName string // e.g., "OneofName"
+
+ // GoIdent is the base name of a top-level declaration for this oneof.
+ GoIdent GoIdent // e.g., "MessageName_OneofName"
+
+ Parent *Message // message in which this oneof is declared
+
+ Fields []*Field // fields that are part of this oneof
+
+ Location Location // location of this oneof
+ Comments CommentSet // comments associated with this oneof
+
+ // camelCase is the same as GoName, but without the name mangling.
+ // This is used in builders, which never have their names mangled
+ camelCase string
+
+ // hasConflictHybrid tells us if we are to insert an '_' into
+ // the method names, (e.g. SetFoo becomes Set_Foo). This will
+ // be set even if we generate opaque protos, as we will want
+ // to potentially generate these method names anyway
+ // (opaque-v0).
+ hasConflictHybrid bool
+}
+
+func newOneof(gen *Plugin, f *File, message *Message, desc protoreflect.OneofDescriptor) *Oneof {
+ loc := message.Location.appendPath(genid.DescriptorProto_OneofDecl_field_number, desc.Index())
+ camelCased := strs.GoCamelCase(string(desc.Name()))
+ parentPrefix := message.GoIdent.GoName + "_"
+ oneof := &Oneof{
+ Desc: desc,
+ Parent: message,
+ GoName: camelCased,
+ GoIdent: GoIdent{
+ GoImportPath: f.GoImportPath,
+ GoName: parentPrefix + camelCased,
+ },
+ Location: loc,
+ Comments: makeCommentSet(gen, f.Desc.SourceLocations().ByDescriptor(desc)),
+ }
+
+ opaqueNewOneofHook(desc, oneof)
+
+ return oneof
+}
+
+// Extension is an alias of [Field] for documentation.
+type Extension = Field
+
+// A Service describes a service.
+type Service struct {
+ Desc protoreflect.ServiceDescriptor
+
+ GoName string
+
+ Methods []*Method // service method declarations
+
+ Location Location // location of this service
+ Comments CommentSet // comments associated with this service
+}
+
+func newService(gen *Plugin, f *File, desc protoreflect.ServiceDescriptor) *Service {
+ loc := f.location.appendPath(genid.FileDescriptorProto_Service_field_number, desc.Index())
+ service := &Service{
+ Desc: desc,
+ GoName: strs.GoCamelCase(string(desc.Name())),
+ Location: loc,
+ Comments: makeCommentSet(gen, f.Desc.SourceLocations().ByDescriptor(desc)),
+ }
+ for i, mds := 0, desc.Methods(); i < mds.Len(); i++ {
+ service.Methods = append(service.Methods, newMethod(gen, f, service, mds.Get(i)))
+ }
+ return service
+}
+
+// A Method describes a method in a service.
+type Method struct {
+ Desc protoreflect.MethodDescriptor
+
+ GoName string
+
+ Parent *Service // service in which this method is declared
+
+ Input *Message
+ Output *Message
+
+ Location Location // location of this method
+ Comments CommentSet // comments associated with this method
+}
+
+func newMethod(gen *Plugin, f *File, service *Service, desc protoreflect.MethodDescriptor) *Method {
+ loc := service.Location.appendPath(genid.ServiceDescriptorProto_Method_field_number, desc.Index())
+ method := &Method{
+ Desc: desc,
+ GoName: strs.GoCamelCase(string(desc.Name())),
+ Parent: service,
+ Location: loc,
+ Comments: makeCommentSet(gen, f.Desc.SourceLocations().ByDescriptor(desc)),
+ }
+ return method
+}
+
+func (method *Method) resolveDependencies(gen *Plugin) error {
+ desc := method.Desc
+
+ inName := desc.Input().FullName()
+ in, ok := gen.messagesByName[inName]
+ if !ok {
+ return fmt.Errorf("method %v: no descriptor for type %v", desc.FullName(), inName)
+ }
+ method.Input = in
+
+ outName := desc.Output().FullName()
+ out, ok := gen.messagesByName[outName]
+ if !ok {
+ return fmt.Errorf("method %v: no descriptor for type %v", desc.FullName(), outName)
+ }
+ method.Output = out
+
+ return nil
+}
+
+// A GeneratedFile is a generated file.
+type GeneratedFile struct {
+ gen *Plugin
+ skip bool
+ filename string
+ goImportPath GoImportPath
+ buf bytes.Buffer
+ packageNames map[GoImportPath]GoPackageName
+ usedPackageNames map[GoPackageName]bool
+ manualImports map[GoImportPath]bool
+ annotations map[string][]Annotation
+ stripForEditionsDiff bool
+}
+
+// NewGeneratedFile creates a new generated file with the given filename
+// and import path.
+func (gen *Plugin) NewGeneratedFile(filename string, goImportPath GoImportPath) *GeneratedFile {
+ g := &GeneratedFile{
+ gen: gen,
+ filename: filename,
+ goImportPath: goImportPath,
+ packageNames: make(map[GoImportPath]GoPackageName),
+ usedPackageNames: make(map[GoPackageName]bool),
+ manualImports: make(map[GoImportPath]bool),
+ annotations: make(map[string][]Annotation),
+ stripForEditionsDiff: gen.InternalStripForEditionsDiff(),
+ }
+
+ // All predeclared identifiers in Go are already used.
+ for _, s := range types.Universe.Names() {
+ g.usedPackageNames[GoPackageName(s)] = true
+ }
+
+ gen.genFiles = append(gen.genFiles, g)
+ return g
+}
+
+// P prints a line to the generated output. It converts each parameter to a
+// string following the same rules as [fmt.Print]. It never inserts spaces
+// between parameters.
+func (g *GeneratedFile) P(v ...any) {
+ for _, x := range v {
+ switch x := x.(type) {
+ case GoIdent:
+ fmt.Fprint(&g.buf, g.QualifiedGoIdent(x))
+ default:
+ fmt.Fprint(&g.buf, x)
+ }
+ }
+ fmt.Fprintln(&g.buf)
+}
+
+// QualifiedGoIdent returns the string to use for a Go identifier.
+//
+// If the identifier is from a different Go package than the generated file,
+// the returned name will be qualified (package.name) and an import statement
+// for the identifier's package will be included in the file.
+func (g *GeneratedFile) QualifiedGoIdent(ident GoIdent) string {
+ if ident.GoImportPath == g.goImportPath {
+ return ident.GoName
+ }
+ if packageName, ok := g.packageNames[ident.GoImportPath]; ok {
+ return string(packageName) + "." + ident.GoName
+ }
+ packageName := cleanPackageName(path.Base(string(ident.GoImportPath)))
+ for i, orig := 1, packageName; g.usedPackageNames[packageName]; i++ {
+ packageName = orig + GoPackageName(strconv.Itoa(i))
+ }
+ g.packageNames[ident.GoImportPath] = packageName
+ g.usedPackageNames[packageName] = true
+ return string(packageName) + "." + ident.GoName
+}
+
+// Import ensures a package is imported by the generated file.
+//
+// Packages referenced by [GeneratedFile.QualifiedGoIdent] are automatically imported.
+// Explicitly importing a package with Import is generally only necessary
+// when the import will be blank (import _ "package").
+func (g *GeneratedFile) Import(importPath GoImportPath) {
+ g.manualImports[importPath] = true
+}
+
+// Write implements [io.Writer].
+func (g *GeneratedFile) Write(p []byte) (n int, err error) {
+ return g.buf.Write(p)
+}
+
+// Skip removes the generated file from the plugin output.
+func (g *GeneratedFile) Skip() {
+ g.skip = true
+}
+
+// Unskip reverts a previous call to [GeneratedFile.Skip],
+// re-including the generated file in the plugin output.
+func (g *GeneratedFile) Unskip() {
+ g.skip = false
+}
+
+// InternalStripForEditionsDiff returns true if the plugin should not emit certain
+// parts of the generated code in order to make it possible to compare a
+// proto2/proto3 file with its equivalent (according to proto spec) editions
+// file. Primarily, this is the encoded descriptor.
+//
+// This function is for internal use by Go Protobuf only. Do not use it, we
+// might remove it at any time.
+func (g *GeneratedFile) InternalStripForEditionsDiff() bool {
+ return g.stripForEditionsDiff
+}
+
+// Annotate associates a symbol in a generated Go file with a location in a
+// source .proto file.
+//
+// The symbol may refer to a type, constant, variable, function, method, or
+// struct field. The "T.sel" syntax is used to identify the method or field
+// 'sel' on type 'T'.
+//
+// Deprecated: Use the [GeneratedFile.AnnotateSymbol] method instead.
+func (g *GeneratedFile) Annotate(symbol string, loc Location) {
+ g.AnnotateSymbol(symbol, Annotation{Location: loc})
+}
+
+// An Annotation provides semantic detail for a generated proto element.
+//
+// See the google.protobuf.GeneratedCodeInfo.Annotation documentation in
+// descriptor.proto for details.
+type Annotation struct {
+ // Location is the source .proto file for the element.
+ Location Location
+
+ // Semantic is the symbol's effect on the element in the original .proto file.
+ Semantic *descriptorpb.GeneratedCodeInfo_Annotation_Semantic
+}
+
+// AnnotateSymbol associates a symbol in a generated Go file with a location
+// in a source .proto file and a semantic type.
+//
+// The symbol may refer to a type, constant, variable, function, method, or
+// struct field. The "T.sel" syntax is used to identify the method or field
+// 'sel' on type 'T'.
+func (g *GeneratedFile) AnnotateSymbol(symbol string, info Annotation) {
+ g.annotations[symbol] = append(g.annotations[symbol], info)
+}
+
+// Content returns the contents of the generated file.
+func (g *GeneratedFile) Content() ([]byte, error) {
+ if !strings.HasSuffix(g.filename, ".go") {
+ return g.buf.Bytes(), nil
+ }
+
+ // Reformat generated code.
+ original := g.buf.Bytes()
+ fset := token.NewFileSet()
+ file, err := parser.ParseFile(fset, "", original, parser.ParseComments)
+ if err != nil {
+ // Print out the bad code with line numbers.
+ // This should never happen in practice, but it can while changing generated code
+ // so consider this a debugging aid.
+ var src bytes.Buffer
+ s := bufio.NewScanner(bytes.NewReader(original))
+ for line := 1; s.Scan(); line++ {
+ fmt.Fprintf(&src, "%5d\t%s\n", line, s.Bytes())
+ }
+ return nil, fmt.Errorf("%v: unparsable Go source: %v\n%v", g.filename, err, src.String())
+ }
+
+ // Collect a sorted list of all imports.
+ var importPaths [][2]string
+ rewriteImport := func(importPath string) string {
+ if f := g.gen.opts.ImportRewriteFunc; f != nil {
+ return string(f(GoImportPath(importPath)))
+ }
+ return importPath
+ }
+ for importPath := range g.packageNames {
+ pkgName := string(g.packageNames[GoImportPath(importPath)])
+ pkgPath := rewriteImport(string(importPath))
+ importPaths = append(importPaths, [2]string{pkgName, pkgPath})
+ }
+ for importPath := range g.manualImports {
+ if _, ok := g.packageNames[importPath]; !ok {
+ pkgPath := rewriteImport(string(importPath))
+ importPaths = append(importPaths, [2]string{"_", pkgPath})
+ }
+ }
+ sort.Slice(importPaths, func(i, j int) bool {
+ return importPaths[i][1] < importPaths[j][1]
+ })
+
+ // Modify the AST to include a new import block.
+ if len(importPaths) > 0 {
+ // Insert block after package statement or
+ // possible comment attached to the end of the package statement.
+ pos := file.Package
+ tokFile := fset.File(file.Package)
+ pkgLine := tokFile.Line(file.Package)
+ for _, c := range file.Comments {
+ if tokFile.Line(c.Pos()) > pkgLine {
+ break
+ }
+ pos = c.End()
+ }
+
+ // Construct the import block.
+ impDecl := &ast.GenDecl{
+ Tok: token.IMPORT,
+ TokPos: pos,
+ Lparen: pos,
+ Rparen: pos,
+ }
+ for _, importPath := range importPaths {
+ impDecl.Specs = append(impDecl.Specs, &ast.ImportSpec{
+ Name: &ast.Ident{
+ Name: importPath[0],
+ NamePos: pos,
+ },
+ Path: &ast.BasicLit{
+ Kind: token.STRING,
+ Value: strconv.Quote(importPath[1]),
+ ValuePos: pos,
+ },
+ EndPos: pos,
+ })
+ }
+ file.Decls = append([]ast.Decl{impDecl}, file.Decls...)
+ }
+
+ var out bytes.Buffer
+ if err = (&printer.Config{Mode: printer.TabIndent | printer.UseSpaces, Tabwidth: 8}).Fprint(&out, fset, file); err != nil {
+ return nil, fmt.Errorf("%v: can not reformat Go source: %v", g.filename, err)
+ }
+ return out.Bytes(), nil
+}
+
+func (g *GeneratedFile) generatedCodeInfo(content []byte) (*descriptorpb.GeneratedCodeInfo, error) {
+ fset := token.NewFileSet()
+ astFile, err := parser.ParseFile(fset, "", content, 0)
+ if err != nil {
+ return nil, err
+ }
+ info := &descriptorpb.GeneratedCodeInfo{}
+
+ seenAnnotations := make(map[string]bool)
+ annotate := func(s string, ident *ast.Ident) {
+ seenAnnotations[s] = true
+ for _, a := range g.annotations[s] {
+ info.Annotation = append(info.Annotation, &descriptorpb.GeneratedCodeInfo_Annotation{
+ SourceFile: proto.String(a.Location.SourceFile),
+ Path: a.Location.Path,
+ Begin: proto.Int32(int32(fset.Position(ident.Pos()).Offset)),
+ End: proto.Int32(int32(fset.Position(ident.End()).Offset)),
+ Semantic: a.Semantic,
+ })
+ }
+ }
+ for _, decl := range astFile.Decls {
+ switch decl := decl.(type) {
+ case *ast.GenDecl:
+ for _, spec := range decl.Specs {
+ switch spec := spec.(type) {
+ case *ast.TypeSpec:
+ annotate(spec.Name.Name, spec.Name)
+ switch st := spec.Type.(type) {
+ case *ast.StructType:
+ for _, field := range st.Fields.List {
+ for _, name := range field.Names {
+ annotate(spec.Name.Name+"."+name.Name, name)
+ }
+ }
+ case *ast.InterfaceType:
+ for _, field := range st.Methods.List {
+ for _, name := range field.Names {
+ annotate(spec.Name.Name+"."+name.Name, name)
+ }
+ }
+ }
+ case *ast.ValueSpec:
+ for _, name := range spec.Names {
+ annotate(name.Name, name)
+ }
+ }
+ }
+ case *ast.FuncDecl:
+ if decl.Recv == nil {
+ annotate(decl.Name.Name, decl.Name)
+ } else {
+ recv := decl.Recv.List[0].Type
+ if s, ok := recv.(*ast.StarExpr); ok {
+ recv = s.X
+ }
+ if id, ok := recv.(*ast.Ident); ok {
+ annotate(id.Name+"."+decl.Name.Name, decl.Name)
+ }
+ }
+ }
+ }
+ for a := range g.annotations {
+ if !seenAnnotations[a] {
+ return nil, fmt.Errorf("%v: no symbol matching annotation %q", g.filename, a)
+ }
+ }
+
+ return info, nil
+}
+
+// metaFile returns the contents of the file's metadata file, which is a
+// text formatted string of the google.protobuf.GeneratedCodeInfo.
+func (g *GeneratedFile) metaFile(content []byte) (string, error) {
+ info, err := g.generatedCodeInfo(content)
+ if err != nil {
+ return "", err
+ }
+
+ b, err := prototext.Marshal(info)
+ if err != nil {
+ return "", err
+ }
+ return string(b), nil
+}
+
+// A GoIdent is a Go identifier, consisting of a name and import path.
+// The name is a single identifier and may not be a dot-qualified selector.
+type GoIdent struct {
+ GoName string
+ GoImportPath GoImportPath
+}
+
+func (id GoIdent) String() string { return fmt.Sprintf("%q.%v", id.GoImportPath, id.GoName) }
+
+// newGoIdent returns the Go identifier for a descriptor.
+func newGoIdent(f *File, d protoreflect.Descriptor) GoIdent {
+ name := strings.TrimPrefix(string(d.FullName()), string(f.Desc.Package())+".")
+ return GoIdent{
+ GoName: strs.GoCamelCase(name),
+ GoImportPath: f.GoImportPath,
+ }
+}
+
+// A GoImportPath is the import path of a Go package.
+// For example: "google.golang.org/protobuf/compiler/protogen"
+type GoImportPath string
+
+func (p GoImportPath) String() string { return strconv.Quote(string(p)) }
+
+// Ident returns a GoIdent with s as the GoName and p as the GoImportPath.
+func (p GoImportPath) Ident(s string) GoIdent {
+ return GoIdent{GoName: s, GoImportPath: p}
+}
+
+// A GoPackageName is the name of a Go package. e.g., "protobuf".
+type GoPackageName string
+
+// cleanPackageName converts a string to a valid Go package name.
+func cleanPackageName(name string) GoPackageName {
+ return GoPackageName(strs.GoSanitized(name))
+}
+
+type pathType int
+
+const (
+ pathTypeImport pathType = iota
+ pathTypeSourceRelative
+)
+
+// A Location is a location in a .proto source file.
+//
+// See the google.protobuf.SourceCodeInfo documentation in descriptor.proto
+// for details.
+type Location struct {
+ SourceFile string
+ Path protoreflect.SourcePath
+}
+
+// appendPath add elements to a Location's path, returning a new Location.
+func (loc Location) appendPath(num protoreflect.FieldNumber, idx int) Location {
+ loc.Path = append(protoreflect.SourcePath(nil), loc.Path...) // make copy
+ loc.Path = append(loc.Path, int32(num), int32(idx))
+ return loc
+}
+
+// CommentSet is a set of leading and trailing comments associated
+// with a .proto descriptor declaration.
+type CommentSet struct {
+ LeadingDetached []Comments
+ Leading Comments
+ Trailing Comments
+}
+
+func makeCommentSet(gen *Plugin, loc protoreflect.SourceLocation) CommentSet {
+ if gen.InternalStripForEditionsDiff() {
+ return CommentSet{}
+ }
+ var leadingDetached []Comments
+ for _, s := range loc.LeadingDetachedComments {
+ leadingDetached = append(leadingDetached, Comments(s))
+ }
+ return CommentSet{
+ LeadingDetached: leadingDetached,
+ Leading: Comments(loc.LeadingComments),
+ Trailing: Comments(loc.TrailingComments),
+ }
+}
+
+// Comments is a comments string as provided by protoc.
+type Comments string
+
+// String formats the comments by inserting // to the start of each line,
+// ensuring that there is a trailing newline.
+// An empty comment is formatted as an empty string.
+func (c Comments) String() string {
+ if c == "" {
+ return ""
+ }
+ var b []byte
+ for _, line := range strings.Split(strings.TrimSuffix(string(c), "\n"), "\n") {
+ b = append(b, "//"...)
+ b = append(b, line...)
+ b = append(b, "\n"...)
+ }
+ return string(b)
+}
+
+// extensionRegistry allows registration of new extensions defined in the .proto
+// file for which we are generating bindings.
+//
+// Lookups consult the local type registry first and fall back to the base type
+// registry which defaults to protoregistry.GlobalTypes.
+type extensionRegistry struct {
+ base *protoregistry.Types
+ local *protoregistry.Types
+}
+
+func newExtensionRegistry() *extensionRegistry {
+ return &extensionRegistry{
+ base: protoregistry.GlobalTypes,
+ local: &protoregistry.Types{},
+ }
+}
+
+// FindExtensionByName implements proto.UnmarshalOptions.FindExtensionByName
+func (e *extensionRegistry) FindExtensionByName(field protoreflect.FullName) (protoreflect.ExtensionType, error) {
+ if xt, err := e.local.FindExtensionByName(field); err == nil {
+ return xt, nil
+ }
+
+ return e.base.FindExtensionByName(field)
+}
+
+// FindExtensionByNumber implements proto.UnmarshalOptions.FindExtensionByNumber
+func (e *extensionRegistry) FindExtensionByNumber(message protoreflect.FullName, field protoreflect.FieldNumber) (protoreflect.ExtensionType, error) {
+ if xt, err := e.local.FindExtensionByNumber(message, field); err == nil {
+ return xt, nil
+ }
+
+ return e.base.FindExtensionByNumber(message, field)
+}
+
+func (e *extensionRegistry) hasNovelExtensions() bool {
+ return e.local.NumExtensions() > 0
+}
+
+func (e *extensionRegistry) registerAllExtensionsFromFile(f protoreflect.FileDescriptor) error {
+ if err := e.registerAllExtensions(f.Extensions()); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (e *extensionRegistry) registerAllExtensionsFromMessage(ms protoreflect.MessageDescriptors) error {
+ for i := 0; i < ms.Len(); i++ {
+ m := ms.Get(i)
+ if err := e.registerAllExtensions(m.Extensions()); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (e *extensionRegistry) registerAllExtensions(exts protoreflect.ExtensionDescriptors) error {
+ for i := 0; i < exts.Len(); i++ {
+ if err := e.registerExtension(exts.Get(i)); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// registerExtension adds the given extension to the type registry if an
+// extension with that full name does not exist yet.
+func (e *extensionRegistry) registerExtension(xd protoreflect.ExtensionDescriptor) error {
+ if _, err := e.FindExtensionByName(xd.FullName()); err != protoregistry.NotFound {
+ // Either the extension already exists or there was an error, either way we're done.
+ return err
+ }
+ return e.local.RegisterExtension(dynamicpb.NewExtensionType(xd))
+}
diff --git a/vendor/google.golang.org/protobuf/compiler/protogen/protogen_apilevel.go b/vendor/google.golang.org/protobuf/compiler/protogen/protogen_apilevel.go
new file mode 100644
index 00000000000..27276fa4272
--- /dev/null
+++ b/vendor/google.golang.org/protobuf/compiler/protogen/protogen_apilevel.go
@@ -0,0 +1,192 @@
+// Copyright 2024 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 protogen
+
+import (
+ "fmt"
+
+ "google.golang.org/protobuf/internal/filedesc"
+ "google.golang.org/protobuf/internal/genid"
+ "google.golang.org/protobuf/reflect/protoreflect"
+ "google.golang.org/protobuf/types/gofeaturespb"
+)
+
+func fileAPILevel(fd protoreflect.FileDescriptor, def gofeaturespb.GoFeatures_APILevel) gofeaturespb.GoFeatures_APILevel {
+ level := gofeaturespb.GoFeatures_API_OPEN
+ level = def
+ if fd, ok := fd.(*filedesc.File); ok {
+ al := fd.L1.EditionFeatures.APILevel
+ if al != genid.GoFeatures_API_LEVEL_UNSPECIFIED_enum_value {
+ level = gofeaturespb.GoFeatures_APILevel(al)
+ }
+ }
+
+ return level
+}
+
+func messageAPILevel(md protoreflect.MessageDescriptor, def gofeaturespb.GoFeatures_APILevel) gofeaturespb.GoFeatures_APILevel {
+ level := def
+ if md, ok := md.(*filedesc.Message); ok {
+ al := md.L1.EditionFeatures.APILevel
+ if al != genid.GoFeatures_API_LEVEL_UNSPECIFIED_enum_value {
+ level = gofeaturespb.GoFeatures_APILevel(al)
+ }
+ }
+
+ return level
+}
+
+func (p *Plugin) defaultAPILevel() gofeaturespb.GoFeatures_APILevel {
+ if p.opts.DefaultAPILevel != gofeaturespb.GoFeatures_API_LEVEL_UNSPECIFIED {
+ return p.opts.DefaultAPILevel
+ }
+
+ return gofeaturespb.GoFeatures_API_OPEN
+}
+
+// MethodName returns the (possibly mangled) name of the generated accessor
+// method, along with the backwards-compatible name (if needed).
+//
+// method must be one of Get, Set, Has, Clear. MethodName panics otherwise.
+func (field *Field) MethodName(method string) (name, compat string) {
+ switch method {
+ case "Get":
+ return field.getterName()
+
+ case "Set":
+ return field.setterName()
+
+ case "Has", "Clear":
+ return field.methodName(method), ""
+
+ default:
+ panic(fmt.Sprintf("Field.MethodName called for unknown method %q", method))
+ }
+}
+
+// methodName returns the (possibly mangled) name of the generated method with
+// the given prefix.
+//
+// For the Open API, the return value is "".
+func (field *Field) methodName(prefix string) string {
+ switch field.Parent.APILevel {
+ case gofeaturespb.GoFeatures_API_OPEN:
+ // In the Open API, only generate getters (no Has or Clear methods).
+ return ""
+
+ case gofeaturespb.GoFeatures_API_HYBRID:
+ var infix string
+ if field.hasConflictHybrid {
+ infix = "_"
+ }
+ return prefix + infix + field.camelCase
+
+ case gofeaturespb.GoFeatures_API_OPAQUE:
+ return prefix + field.camelCase
+
+ default:
+ panic("BUG: message is neither open, nor hybrid, nor opaque?!")
+ }
+}
+
+// getterName returns the (possibly mangled) name of the generated Get method,
+// along with the backwards-compatible name (if needed).
+func (field *Field) getterName() (getter, compat string) {
+ switch field.Parent.APILevel {
+ case gofeaturespb.GoFeatures_API_OPEN:
+ // In the Open API, only generate a getter with the old style mangled name.
+ return "Get" + field.GoName, ""
+
+ case gofeaturespb.GoFeatures_API_HYBRID:
+ // In the Hybrid API, return the mangled getter name and the old style
+ // name if needed, for backwards compatibility with the Open API.
+ var infix string
+ if field.hasConflictHybrid {
+ infix = "_"
+ }
+ orig := "Get" + infix + field.camelCase
+ mangled := "Get" + field.GoName
+ if mangled == orig {
+ mangled = ""
+ }
+ return orig, mangled
+
+ case gofeaturespb.GoFeatures_API_OPAQUE:
+ return field.methodName("Get"), ""
+
+ default:
+ panic("BUG: message is neither open, nor hybrid, nor opaque?!")
+ }
+}
+
+// setterName returns the (possibly mangled) name of the generated Set method,
+// along with the backwards-compatible name (if needed).
+func (field *Field) setterName() (setter, compat string) {
+ // TODO(b/359846588): remove weak field support?
+ if field.Desc.IsWeak() && field.Parent.APILevel != gofeaturespb.GoFeatures_API_OPAQUE {
+ switch field.Parent.APILevel {
+ case gofeaturespb.GoFeatures_API_OPEN:
+ return "Set" + field.GoName, ""
+
+ default:
+ var infix string
+ if field.hasConflictHybrid {
+ infix = "_"
+ }
+ orig := "Set" + infix + field.camelCase
+ mangled := "Set" + field.GoName
+ if mangled == orig {
+ mangled = ""
+ }
+ return orig, mangled
+ }
+ }
+ return field.methodName("Set"), ""
+}
+
+// BuilderFieldName returns the name of this field in the corresponding _builder
+// struct.
+func (field *Field) BuilderFieldName() string {
+ return field.camelCase
+}
+
+// MethodName returns the (possibly mangled) name of the generated accessor
+// method.
+//
+// method must be one of Has, Clear, Which. MethodName panics otherwise.
+func (oneof *Oneof) MethodName(method string) string {
+ switch method {
+ case "Has", "Clear", "Which":
+ return oneof.methodName(method)
+
+ default:
+ panic(fmt.Sprintf("Oneof.MethodName called for unknown method %q", method))
+ }
+}
+
+// methodName returns the (possibly mangled) name of the generated method with
+// the given prefix.
+//
+// For the Open API, the return value is "".
+func (oneof *Oneof) methodName(prefix string) string {
+ switch oneof.Parent.APILevel {
+ case gofeaturespb.GoFeatures_API_OPEN:
+ // In the Open API, only generate getters.
+ return ""
+
+ case gofeaturespb.GoFeatures_API_HYBRID:
+ var infix string
+ if oneof.hasConflictHybrid {
+ infix = "_"
+ }
+ return prefix + infix + oneof.camelCase
+
+ case gofeaturespb.GoFeatures_API_OPAQUE:
+ return prefix + oneof.camelCase
+
+ default:
+ panic("BUG: message is neither open, nor hybrid, nor opaque?!")
+ }
+}
diff --git a/vendor/google.golang.org/protobuf/compiler/protogen/protogen_opaque.go b/vendor/google.golang.org/protobuf/compiler/protogen/protogen_opaque.go
new file mode 100644
index 00000000000..8b11cdbd55f
--- /dev/null
+++ b/vendor/google.golang.org/protobuf/compiler/protogen/protogen_opaque.go
@@ -0,0 +1,79 @@
+// Copyright 2024 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 protogen
+
+import (
+ "google.golang.org/protobuf/internal/strs"
+ "google.golang.org/protobuf/reflect/protoreflect"
+)
+
+func opaqueNewFieldHook(desc protoreflect.FieldDescriptor, field *Field) {
+ field.camelCase = strs.GoCamelCase(string(desc.Name()))
+}
+
+func opaqueNewOneofHook(desc protoreflect.OneofDescriptor, oneof *Oneof) {
+ oneof.camelCase = strs.GoCamelCase(string(desc.Name()))
+}
+
+func opaqueNewMessageHook(message *Message) {
+ // New name mangling scheme: Add a '_' between method base
+ // name (Get, Set, Clear etc) and original field name if
+ // needed. As a special case, there is one globally reserved
+ // name, e.g. "Build" thet still results in actual renaming of
+ // the builder field like in the old scheme. We begin by
+ // taking care of this special case.
+ for _, field := range message.Fields {
+ if field.camelCase == "Build" {
+ field.camelCase += "_"
+ }
+ }
+
+ // Then find all names of the original field names, we do not want the old scheme to affect
+ // how we name things.
+
+ camelCases := map[string]bool{}
+ for _, field := range message.Fields {
+ if field.Oneof != nil {
+ // We add the name of the union here (potentially many times).
+ camelCases[field.Oneof.camelCase] = true
+ }
+ // The member fields of the oneof are considered fields in the struct although
+ // they are not technically there. This is to allow changing a proto2 optional
+ // to a oneof with source code compatibility.
+ camelCases[field.camelCase] = true
+
+ }
+ // For each field, check if any of it's methods would clash with an original field name
+ for _, field := range message.Fields {
+ // Every field (except the union fields, that are taken care of separately) has
+ // a Get and a Set method.
+ methods := []string{"Set", "Get"}
+ // For explicit presence fields, we also have Has and Clear.
+ if field.Desc.HasPresence() {
+ methods = append(methods, "Has", "Clear")
+ }
+ for _, method := range methods {
+ // If any method name clashes with a field name, all methods get a
+ // "_" inserted between the operation and the field name.
+ if camelCases[method+field.camelCase] {
+ field.hasConflictHybrid = true
+ }
+ }
+ }
+ // The union names for oneofs need only have a methods prefix if there is a clash with Has, Clear or Which in
+ // hybrid and opaque-v0.
+ for _, field := range message.Fields {
+ if field.Oneof == nil {
+ continue
+ }
+ for _, method := range []string{"Has", "Clear", "Which"} {
+ // Same logic as for regular fields - all methods get the "_" if one needs it.
+ if camelCases[method+field.Oneof.camelCase] {
+ field.Oneof.hasConflictHybrid = true
+ }
+ }
+ }
+
+}
diff --git a/vendor/google.golang.org/protobuf/internal/msgfmt/format.go b/vendor/google.golang.org/protobuf/internal/msgfmt/format.go
new file mode 100644
index 00000000000..17b3f27b8a2
--- /dev/null
+++ b/vendor/google.golang.org/protobuf/internal/msgfmt/format.go
@@ -0,0 +1,261 @@
+// Copyright 2019 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 msgfmt implements a text marshaler combining the desirable features
+// of both the JSON and proto text formats.
+// It is optimized for human readability and has no associated deserializer.
+package msgfmt
+
+import (
+ "bytes"
+ "fmt"
+ "reflect"
+ "sort"
+ "strconv"
+ "strings"
+ "time"
+
+ "google.golang.org/protobuf/encoding/protowire"
+ "google.golang.org/protobuf/internal/detrand"
+ "google.golang.org/protobuf/internal/genid"
+ "google.golang.org/protobuf/internal/order"
+ "google.golang.org/protobuf/proto"
+ "google.golang.org/protobuf/reflect/protoreflect"
+ "google.golang.org/protobuf/reflect/protoregistry"
+)
+
+// Format returns a formatted string for the message.
+func Format(m proto.Message) string {
+ return string(appendMessage(nil, m.ProtoReflect()))
+}
+
+// FormatValue returns a formatted string for an arbitrary value.
+func FormatValue(v protoreflect.Value, fd protoreflect.FieldDescriptor) string {
+ return string(appendValue(nil, v, fd))
+}
+
+func appendValue(b []byte, v protoreflect.Value, fd protoreflect.FieldDescriptor) []byte {
+ switch v := v.Interface().(type) {
+ case nil:
+ return append(b, ""...)
+ case bool, int32, int64, uint32, uint64, float32, float64:
+ return append(b, fmt.Sprint(v)...)
+ case string:
+ return append(b, strconv.Quote(string(v))...)
+ case []byte:
+ return append(b, strconv.Quote(string(v))...)
+ case protoreflect.EnumNumber:
+ return appendEnum(b, v, fd)
+ case protoreflect.Message:
+ return appendMessage(b, v)
+ case protoreflect.List:
+ return appendList(b, v, fd)
+ case protoreflect.Map:
+ return appendMap(b, v, fd)
+ default:
+ panic(fmt.Sprintf("invalid type: %T", v))
+ }
+}
+
+func appendEnum(b []byte, v protoreflect.EnumNumber, fd protoreflect.FieldDescriptor) []byte {
+ if fd != nil {
+ if ev := fd.Enum().Values().ByNumber(v); ev != nil {
+ return append(b, ev.Name()...)
+ }
+ }
+ return strconv.AppendInt(b, int64(v), 10)
+}
+
+func appendMessage(b []byte, m protoreflect.Message) []byte {
+ if b2 := appendKnownMessage(b, m); b2 != nil {
+ return b2
+ }
+
+ b = append(b, '{')
+ order.RangeFields(m, order.IndexNameFieldOrder, func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {
+ b = append(b, fd.TextName()...)
+ b = append(b, ':')
+ b = appendValue(b, v, fd)
+ b = append(b, delim()...)
+ return true
+ })
+ b = appendUnknown(b, m.GetUnknown())
+ b = bytes.TrimRight(b, delim())
+ b = append(b, '}')
+ return b
+}
+
+var protocmpMessageType = reflect.TypeOf(map[string]any(nil))
+
+func appendKnownMessage(b []byte, m protoreflect.Message) []byte {
+ md := m.Descriptor()
+ fds := md.Fields()
+ switch md.FullName() {
+ case genid.Any_message_fullname:
+ var msgVal protoreflect.Message
+ url := m.Get(fds.ByNumber(genid.Any_TypeUrl_field_number)).String()
+ if v := reflect.ValueOf(m); v.Type().ConvertibleTo(protocmpMessageType) {
+ // For protocmp.Message, directly obtain the sub-message value
+ // which is stored in structured form, rather than as raw bytes.
+ m2 := v.Convert(protocmpMessageType).Interface().(map[string]any)
+ v, ok := m2[string(genid.Any_Value_field_name)].(proto.Message)
+ if !ok {
+ return nil
+ }
+ msgVal = v.ProtoReflect()
+ } else {
+ val := m.Get(fds.ByNumber(genid.Any_Value_field_number)).Bytes()
+ mt, err := protoregistry.GlobalTypes.FindMessageByURL(url)
+ if err != nil {
+ return nil
+ }
+ msgVal = mt.New()
+ err = proto.UnmarshalOptions{AllowPartial: true}.Unmarshal(val, msgVal.Interface())
+ if err != nil {
+ return nil
+ }
+ }
+
+ b = append(b, '{')
+ b = append(b, "["+url+"]"...)
+ b = append(b, ':')
+ b = appendMessage(b, msgVal)
+ b = append(b, '}')
+ return b
+
+ case genid.Timestamp_message_fullname:
+ secs := m.Get(fds.ByNumber(genid.Timestamp_Seconds_field_number)).Int()
+ nanos := m.Get(fds.ByNumber(genid.Timestamp_Nanos_field_number)).Int()
+ if nanos < 0 || nanos >= 1e9 {
+ return nil
+ }
+ t := time.Unix(secs, nanos).UTC()
+ x := t.Format("2006-01-02T15:04:05.000000000") // RFC 3339
+ x = strings.TrimSuffix(x, "000")
+ x = strings.TrimSuffix(x, "000")
+ x = strings.TrimSuffix(x, ".000")
+ return append(b, x+"Z"...)
+
+ case genid.Duration_message_fullname:
+ sign := ""
+ secs := m.Get(fds.ByNumber(genid.Duration_Seconds_field_number)).Int()
+ nanos := m.Get(fds.ByNumber(genid.Duration_Nanos_field_number)).Int()
+ if nanos <= -1e9 || nanos >= 1e9 || (secs > 0 && nanos < 0) || (secs < 0 && nanos > 0) {
+ return nil
+ }
+ if secs < 0 || nanos < 0 {
+ sign, secs, nanos = "-", -1*secs, -1*nanos
+ }
+ x := fmt.Sprintf("%s%d.%09d", sign, secs, nanos)
+ x = strings.TrimSuffix(x, "000")
+ x = strings.TrimSuffix(x, "000")
+ x = strings.TrimSuffix(x, ".000")
+ return append(b, x+"s"...)
+
+ case genid.BoolValue_message_fullname,
+ genid.Int32Value_message_fullname,
+ genid.Int64Value_message_fullname,
+ genid.UInt32Value_message_fullname,
+ genid.UInt64Value_message_fullname,
+ genid.FloatValue_message_fullname,
+ genid.DoubleValue_message_fullname,
+ genid.StringValue_message_fullname,
+ genid.BytesValue_message_fullname:
+ fd := fds.ByNumber(genid.WrapperValue_Value_field_number)
+ return appendValue(b, m.Get(fd), fd)
+ }
+
+ return nil
+}
+
+func appendUnknown(b []byte, raw protoreflect.RawFields) []byte {
+ rs := make(map[protoreflect.FieldNumber][]protoreflect.RawFields)
+ for len(raw) > 0 {
+ num, _, n := protowire.ConsumeField(raw)
+ rs[num] = append(rs[num], raw[:n])
+ raw = raw[n:]
+ }
+
+ var ns []protoreflect.FieldNumber
+ for n := range rs {
+ ns = append(ns, n)
+ }
+ sort.Slice(ns, func(i, j int) bool { return ns[i] < ns[j] })
+
+ for _, n := range ns {
+ var leftBracket, rightBracket string
+ if len(rs[n]) > 1 {
+ leftBracket, rightBracket = "[", "]"
+ }
+
+ b = strconv.AppendInt(b, int64(n), 10)
+ b = append(b, ':')
+ b = append(b, leftBracket...)
+ for _, r := range rs[n] {
+ num, typ, n := protowire.ConsumeTag(r)
+ r = r[n:]
+ switch typ {
+ case protowire.VarintType:
+ v, _ := protowire.ConsumeVarint(r)
+ b = strconv.AppendInt(b, int64(v), 10)
+ case protowire.Fixed32Type:
+ v, _ := protowire.ConsumeFixed32(r)
+ b = append(b, fmt.Sprintf("0x%08x", v)...)
+ case protowire.Fixed64Type:
+ v, _ := protowire.ConsumeFixed64(r)
+ b = append(b, fmt.Sprintf("0x%016x", v)...)
+ case protowire.BytesType:
+ v, _ := protowire.ConsumeBytes(r)
+ b = strconv.AppendQuote(b, string(v))
+ case protowire.StartGroupType:
+ v, _ := protowire.ConsumeGroup(num, r)
+ b = append(b, '{')
+ b = appendUnknown(b, v)
+ b = bytes.TrimRight(b, delim())
+ b = append(b, '}')
+ default:
+ panic(fmt.Sprintf("invalid type: %v", typ))
+ }
+ b = append(b, delim()...)
+ }
+ b = bytes.TrimRight(b, delim())
+ b = append(b, rightBracket...)
+ b = append(b, delim()...)
+ }
+ return b
+}
+
+func appendList(b []byte, v protoreflect.List, fd protoreflect.FieldDescriptor) []byte {
+ b = append(b, '[')
+ for i := 0; i < v.Len(); i++ {
+ b = appendValue(b, v.Get(i), fd)
+ b = append(b, delim()...)
+ }
+ b = bytes.TrimRight(b, delim())
+ b = append(b, ']')
+ return b
+}
+
+func appendMap(b []byte, v protoreflect.Map, fd protoreflect.FieldDescriptor) []byte {
+ b = append(b, '{')
+ order.RangeEntries(v, order.GenericKeyOrder, func(k protoreflect.MapKey, v protoreflect.Value) bool {
+ b = appendValue(b, k.Value(), fd.MapKey())
+ b = append(b, ':')
+ b = appendValue(b, v, fd.MapValue())
+ b = append(b, delim()...)
+ return true
+ })
+ b = bytes.TrimRight(b, delim())
+ b = append(b, '}')
+ return b
+}
+
+func delim() string {
+ // Deliberately introduce instability into the message string to
+ // discourage users from depending on it.
+ if detrand.Bool() {
+ return " "
+ }
+ return ", "
+}
diff --git a/vendor/google.golang.org/protobuf/reflect/protopath/path.go b/vendor/google.golang.org/protobuf/reflect/protopath/path.go
new file mode 100644
index 00000000000..fffac00ebce
--- /dev/null
+++ b/vendor/google.golang.org/protobuf/reflect/protopath/path.go
@@ -0,0 +1,122 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package protopath provides functionality for
+// representing a sequence of protobuf reflection operations on a message.
+package protopath
+
+import (
+ "fmt"
+
+ "google.golang.org/protobuf/internal/msgfmt"
+ "google.golang.org/protobuf/reflect/protoreflect"
+)
+
+// NOTE: The Path and Values are separate types here since there are use cases
+// where you would like to "address" some value in a message with just the path
+// and don't have the value information available.
+//
+// This is different from how github.com/google/go-cmp/cmp.Path operates,
+// which combines both path and value information together.
+// Since the cmp package itself is the only one ever constructing a cmp.Path,
+// it will always have the value available.
+
+// Path is a sequence of protobuf reflection steps applied to some root
+// protobuf message value to arrive at the current value.
+// The first step must be a [Root] step.
+type Path []Step
+
+// TODO: Provide a Parse function that parses something similar to or
+// perhaps identical to the output of Path.String.
+
+// Index returns the ith step in the path and supports negative indexing.
+// A negative index starts counting from the tail of the Path such that -1
+// refers to the last step, -2 refers to the second-to-last step, and so on.
+// It returns a zero Step value if the index is out-of-bounds.
+func (p Path) Index(i int) Step {
+ if i < 0 {
+ i = len(p) + i
+ }
+ if i < 0 || i >= len(p) {
+ return Step{}
+ }
+ return p[i]
+}
+
+// String returns a structured representation of the path
+// by concatenating the string representation of every path step.
+func (p Path) String() string {
+ var b []byte
+ for _, s := range p {
+ b = s.appendString(b)
+ }
+ return string(b)
+}
+
+// Values is a Path paired with a sequence of values at each step.
+// The lengths of [Values.Path] and [Values.Values] must be identical.
+// The first step must be a [Root] step and
+// the first value must be a concrete message value.
+type Values struct {
+ Path Path
+ Values []protoreflect.Value
+}
+
+// Len reports the length of the path and values.
+// If the path and values have differing length, it returns the minimum length.
+func (p Values) Len() int {
+ n := len(p.Path)
+ if n > len(p.Values) {
+ n = len(p.Values)
+ }
+ return n
+}
+
+// Index returns the ith step and value and supports negative indexing.
+// A negative index starts counting from the tail of the Values such that -1
+// refers to the last pair, -2 refers to the second-to-last pair, and so on.
+func (p Values) Index(i int) (out struct {
+ Step Step
+ Value protoreflect.Value
+}) {
+ // NOTE: This returns a single struct instead of two return values so that
+ // callers can make use of the the value in an expression:
+ // vs.Index(i).Value.Interface()
+ n := p.Len()
+ if i < 0 {
+ i = n + i
+ }
+ if i < 0 || i >= n {
+ return out
+ }
+ out.Step = p.Path[i]
+ out.Value = p.Values[i]
+ return out
+}
+
+// String returns a humanly readable representation of the path and last value.
+// Do not depend on the output being stable.
+//
+// For example:
+//
+// (path.to.MyMessage).list_field[5].map_field["hello"] = {hello: "world"}
+func (p Values) String() string {
+ n := p.Len()
+ if n == 0 {
+ return ""
+ }
+
+ // Determine the field descriptor associated with the last step.
+ var fd protoreflect.FieldDescriptor
+ last := p.Index(-1)
+ switch last.Step.kind {
+ case FieldAccessStep:
+ fd = last.Step.FieldDescriptor()
+ case MapIndexStep, ListIndexStep:
+ fd = p.Index(-2).Step.FieldDescriptor()
+ }
+
+ // Format the full path with the last value.
+ return fmt.Sprintf("%v = %v", p.Path[:n], msgfmt.FormatValue(last.Value, fd))
+}
diff --git a/vendor/google.golang.org/protobuf/reflect/protopath/step.go b/vendor/google.golang.org/protobuf/reflect/protopath/step.go
new file mode 100644
index 00000000000..95ae85c5b1d
--- /dev/null
+++ b/vendor/google.golang.org/protobuf/reflect/protopath/step.go
@@ -0,0 +1,241 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package protopath
+
+import (
+ "fmt"
+ "strconv"
+ "strings"
+
+ "google.golang.org/protobuf/internal/encoding/text"
+ "google.golang.org/protobuf/reflect/protoreflect"
+)
+
+// StepKind identifies the kind of step operation.
+// Each kind of step corresponds with some protobuf reflection operation.
+type StepKind int
+
+const (
+ invalidStep StepKind = iota
+ // RootStep identifies a step as the Root step operation.
+ RootStep
+ // FieldAccessStep identifies a step as the FieldAccess step operation.
+ FieldAccessStep
+ // UnknownAccessStep identifies a step as the UnknownAccess step operation.
+ UnknownAccessStep
+ // ListIndexStep identifies a step as the ListIndex step operation.
+ ListIndexStep
+ // MapIndexStep identifies a step as the MapIndex step operation.
+ MapIndexStep
+ // AnyExpandStep identifies a step as the AnyExpand step operation.
+ AnyExpandStep
+)
+
+func (k StepKind) String() string {
+ switch k {
+ case invalidStep:
+ return ""
+ case RootStep:
+ return "Root"
+ case FieldAccessStep:
+ return "FieldAccess"
+ case UnknownAccessStep:
+ return "UnknownAccess"
+ case ListIndexStep:
+ return "ListIndex"
+ case MapIndexStep:
+ return "MapIndex"
+ case AnyExpandStep:
+ return "AnyExpand"
+ default:
+ return fmt.Sprintf("", k)
+ }
+}
+
+// Step is a union where only one step operation may be specified at a time.
+// The different kinds of steps are specified by the constants defined for
+// the StepKind type.
+type Step struct {
+ kind StepKind
+ desc protoreflect.Descriptor
+ key protoreflect.Value
+}
+
+// Root indicates the root message that a path is relative to.
+// It should always (and only ever) be the first step in a path.
+func Root(md protoreflect.MessageDescriptor) Step {
+ if md == nil {
+ panic("nil message descriptor")
+ }
+ return Step{kind: RootStep, desc: md}
+}
+
+// FieldAccess describes access of a field within a message.
+// Extension field accesses are also represented using a FieldAccess and
+// must be provided with a protoreflect.FieldDescriptor
+//
+// Within the context of Values,
+// the type of the previous step value is always a message, and
+// the type of the current step value is determined by the field descriptor.
+func FieldAccess(fd protoreflect.FieldDescriptor) Step {
+ if fd == nil {
+ panic("nil field descriptor")
+ } else if _, ok := fd.(protoreflect.ExtensionTypeDescriptor); !ok && fd.IsExtension() {
+ panic(fmt.Sprintf("extension field %q must implement protoreflect.ExtensionTypeDescriptor", fd.FullName()))
+ }
+ return Step{kind: FieldAccessStep, desc: fd}
+}
+
+// UnknownAccess describes access to the unknown fields within a message.
+//
+// Within the context of Values,
+// the type of the previous step value is always a message, and
+// the type of the current step value is always a bytes type.
+func UnknownAccess() Step {
+ return Step{kind: UnknownAccessStep}
+}
+
+// ListIndex describes index of an element within a list.
+//
+// Within the context of Values,
+// the type of the previous, previous step value is always a message,
+// the type of the previous step value is always a list, and
+// the type of the current step value is determined by the field descriptor.
+func ListIndex(i int) Step {
+ if i < 0 {
+ panic(fmt.Sprintf("invalid list index: %v", i))
+ }
+ return Step{kind: ListIndexStep, key: protoreflect.ValueOfInt64(int64(i))}
+}
+
+// MapIndex describes index of an entry within a map.
+// The key type is determined by field descriptor that the map belongs to.
+//
+// Within the context of Values,
+// the type of the previous previous step value is always a message,
+// the type of the previous step value is always a map, and
+// the type of the current step value is determined by the field descriptor.
+func MapIndex(k protoreflect.MapKey) Step {
+ if !k.IsValid() {
+ panic("invalid map index")
+ }
+ return Step{kind: MapIndexStep, key: k.Value()}
+}
+
+// AnyExpand describes expansion of a google.protobuf.Any message into
+// a structured representation of the underlying message.
+//
+// Within the context of Values,
+// the type of the previous step value is always a google.protobuf.Any message, and
+// the type of the current step value is always a message.
+func AnyExpand(md protoreflect.MessageDescriptor) Step {
+ if md == nil {
+ panic("nil message descriptor")
+ }
+ return Step{kind: AnyExpandStep, desc: md}
+}
+
+// MessageDescriptor returns the message descriptor for Root or AnyExpand steps,
+// otherwise it returns nil.
+func (s Step) MessageDescriptor() protoreflect.MessageDescriptor {
+ switch s.kind {
+ case RootStep, AnyExpandStep:
+ return s.desc.(protoreflect.MessageDescriptor)
+ default:
+ return nil
+ }
+}
+
+// FieldDescriptor returns the field descriptor for FieldAccess steps,
+// otherwise it returns nil.
+func (s Step) FieldDescriptor() protoreflect.FieldDescriptor {
+ switch s.kind {
+ case FieldAccessStep:
+ return s.desc.(protoreflect.FieldDescriptor)
+ default:
+ return nil
+ }
+}
+
+// ListIndex returns the list index for ListIndex steps,
+// otherwise it returns 0.
+func (s Step) ListIndex() int {
+ switch s.kind {
+ case ListIndexStep:
+ return int(s.key.Int())
+ default:
+ return 0
+ }
+}
+
+// MapIndex returns the map key for MapIndex steps,
+// otherwise it returns an invalid map key.
+func (s Step) MapIndex() protoreflect.MapKey {
+ switch s.kind {
+ case MapIndexStep:
+ return s.key.MapKey()
+ default:
+ return protoreflect.MapKey{}
+ }
+}
+
+// Kind reports which kind of step this is.
+func (s Step) Kind() StepKind {
+ return s.kind
+}
+
+func (s Step) String() string {
+ return string(s.appendString(nil))
+}
+
+func (s Step) appendString(b []byte) []byte {
+ switch s.kind {
+ case RootStep:
+ b = append(b, '(')
+ b = append(b, s.desc.FullName()...)
+ b = append(b, ')')
+ case FieldAccessStep:
+ b = append(b, '.')
+ if fd := s.desc.(protoreflect.FieldDescriptor); fd.IsExtension() {
+ b = append(b, '(')
+ b = append(b, strings.Trim(fd.TextName(), "[]")...)
+ b = append(b, ')')
+ } else {
+ b = append(b, fd.TextName()...)
+ }
+ case UnknownAccessStep:
+ b = append(b, '.')
+ b = append(b, '?')
+ case ListIndexStep:
+ b = append(b, '[')
+ b = strconv.AppendInt(b, s.key.Int(), 10)
+ b = append(b, ']')
+ case MapIndexStep:
+ b = append(b, '[')
+ switch k := s.key.Interface().(type) {
+ case bool:
+ b = strconv.AppendBool(b, bool(k)) // e.g., "true" or "false"
+ case int32:
+ b = strconv.AppendInt(b, int64(k), 10) // e.g., "-32"
+ case int64:
+ b = strconv.AppendInt(b, int64(k), 10) // e.g., "-64"
+ case uint32:
+ b = strconv.AppendUint(b, uint64(k), 10) // e.g., "32"
+ case uint64:
+ b = strconv.AppendUint(b, uint64(k), 10) // e.g., "64"
+ case string:
+ b = text.AppendString(b, k) // e.g., `"hello, world"`
+ }
+ b = append(b, ']')
+ case AnyExpandStep:
+ b = append(b, '.')
+ b = append(b, '(')
+ b = append(b, s.desc.FullName()...)
+ b = append(b, ')')
+ default:
+ b = append(b, ""...)
+ }
+ return b
+}
diff --git a/vendor/google.golang.org/protobuf/reflect/protorange/range.go b/vendor/google.golang.org/protobuf/reflect/protorange/range.go
new file mode 100644
index 00000000000..7a032758b51
--- /dev/null
+++ b/vendor/google.golang.org/protobuf/reflect/protorange/range.go
@@ -0,0 +1,316 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package protorange provides functionality to traverse a message value.
+package protorange
+
+import (
+ "bytes"
+ "errors"
+
+ "google.golang.org/protobuf/internal/genid"
+ "google.golang.org/protobuf/internal/order"
+ "google.golang.org/protobuf/proto"
+ "google.golang.org/protobuf/reflect/protopath"
+ "google.golang.org/protobuf/reflect/protoreflect"
+ "google.golang.org/protobuf/reflect/protoregistry"
+)
+
+var (
+ // Break breaks traversal of children in the current value.
+ // It has no effect when traversing values that are not composite types
+ // (e.g., messages, lists, and maps).
+ Break = errors.New("break traversal of children in current value")
+
+ // Terminate terminates the entire range operation.
+ // All necessary Pop operations continue to be called.
+ Terminate = errors.New("terminate range operation")
+)
+
+// Range performs a depth-first traversal over reachable values in a message.
+//
+// See [Options.Range] for details.
+func Range(m protoreflect.Message, f func(protopath.Values) error) error {
+ return Options{}.Range(m, f, nil)
+}
+
+// Options configures traversal of a message value tree.
+type Options struct {
+ // Stable specifies whether to visit message fields and map entries
+ // in a stable ordering. If false, then the ordering is undefined and
+ // may be non-deterministic.
+ //
+ // Message fields are visited in ascending order by field number.
+ // Map entries are visited in ascending order, where
+ // boolean keys are ordered such that false sorts before true,
+ // numeric keys are ordered based on the numeric value, and
+ // string keys are lexicographically ordered by Unicode codepoints.
+ Stable bool
+
+ // Resolver is used for looking up types when expanding google.protobuf.Any
+ // messages. If nil, this defaults to using protoregistry.GlobalTypes.
+ // To prevent expansion of Any messages, pass an empty protoregistry.Types:
+ //
+ // Options{Resolver: (*protoregistry.Types)(nil)}
+ //
+ Resolver interface {
+ protoregistry.ExtensionTypeResolver
+ protoregistry.MessageTypeResolver
+ }
+}
+
+// Range performs a depth-first traversal over reachable values in a message.
+// The first push and the last pop are to push/pop a [protopath.Root] step.
+// If push or pop return any non-nil error (other than [Break] or [Terminate]),
+// it terminates the traversal and is returned by Range.
+//
+// The rules for traversing a message is as follows:
+//
+// - For messages, iterate over every populated known and extension field.
+// Each field is preceded by a push of a [protopath.FieldAccess] step,
+// followed by recursive application of the rules on the field value,
+// and succeeded by a pop of that step.
+// If the message has unknown fields, then push an [protopath.UnknownAccess] step
+// followed immediately by pop of that step.
+//
+// - As an exception to the above rule, if the current message is a
+// google.protobuf.Any message, expand the underlying message (if resolvable).
+// The expanded message is preceded by a push of a [protopath.AnyExpand] step,
+// followed by recursive application of the rules on the underlying message,
+// and succeeded by a pop of that step. Mutations to the expanded message
+// are written back to the Any message when popping back out.
+//
+// - For lists, iterate over every element. Each element is preceded by a push
+// of a [protopath.ListIndex] step, followed by recursive application of the rules
+// on the list element, and succeeded by a pop of that step.
+//
+// - For maps, iterate over every entry. Each entry is preceded by a push
+// of a [protopath.MapIndex] step, followed by recursive application of the rules
+// on the map entry value, and succeeded by a pop of that step.
+//
+// Mutations should only be made to the last value, otherwise the effects on
+// traversal will be undefined. If the mutation is made to the last value
+// during to a push, then the effects of the mutation will affect traversal.
+// For example, if the last value is currently a message, and the push function
+// populates a few fields in that message, then the newly modified fields
+// will be traversed.
+//
+// The [protopath.Values] provided to push functions is only valid until the
+// corresponding pop call and the values provided to a pop call is only valid
+// for the duration of the pop call itself.
+func (o Options) Range(m protoreflect.Message, push, pop func(protopath.Values) error) error {
+ var err error
+ p := new(protopath.Values)
+ if o.Resolver == nil {
+ o.Resolver = protoregistry.GlobalTypes
+ }
+
+ pushStep(p, protopath.Root(m.Descriptor()), protoreflect.ValueOfMessage(m))
+ if push != nil {
+ err = amendError(err, push(*p))
+ }
+ if err == nil {
+ err = o.rangeMessage(p, m, push, pop)
+ }
+ if pop != nil {
+ err = amendError(err, pop(*p))
+ }
+ popStep(p)
+
+ if err == Break || err == Terminate {
+ err = nil
+ }
+ return err
+}
+
+func (o Options) rangeMessage(p *protopath.Values, m protoreflect.Message, push, pop func(protopath.Values) error) (err error) {
+ if ok, err := o.rangeAnyMessage(p, m, push, pop); ok {
+ return err
+ }
+
+ fieldOrder := order.AnyFieldOrder
+ if o.Stable {
+ fieldOrder = order.NumberFieldOrder
+ }
+ order.RangeFields(m, fieldOrder, func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {
+ pushStep(p, protopath.FieldAccess(fd), v)
+ if push != nil {
+ err = amendError(err, push(*p))
+ }
+ if err == nil {
+ switch {
+ case fd.IsMap():
+ err = o.rangeMap(p, fd, v.Map(), push, pop)
+ case fd.IsList():
+ err = o.rangeList(p, fd, v.List(), push, pop)
+ case fd.Message() != nil:
+ err = o.rangeMessage(p, v.Message(), push, pop)
+ }
+ }
+ if pop != nil {
+ err = amendError(err, pop(*p))
+ }
+ popStep(p)
+ return err == nil
+ })
+
+ if b := m.GetUnknown(); len(b) > 0 && err == nil {
+ pushStep(p, protopath.UnknownAccess(), protoreflect.ValueOfBytes(b))
+ if push != nil {
+ err = amendError(err, push(*p))
+ }
+ if pop != nil {
+ err = amendError(err, pop(*p))
+ }
+ popStep(p)
+ }
+
+ if err == Break {
+ err = nil
+ }
+ return err
+}
+
+func (o Options) rangeAnyMessage(p *protopath.Values, m protoreflect.Message, push, pop func(protopath.Values) error) (ok bool, err error) {
+ md := m.Descriptor()
+ if md.FullName() != "google.protobuf.Any" {
+ return false, nil
+ }
+
+ fds := md.Fields()
+ url := m.Get(fds.ByNumber(genid.Any_TypeUrl_field_number)).String()
+ val := m.Get(fds.ByNumber(genid.Any_Value_field_number)).Bytes()
+ mt, errFind := o.Resolver.FindMessageByURL(url)
+ if errFind != nil {
+ return false, nil
+ }
+
+ // Unmarshal the raw encoded message value into a structured message value.
+ m2 := mt.New()
+ errUnmarshal := proto.UnmarshalOptions{
+ Merge: true,
+ AllowPartial: true,
+ Resolver: o.Resolver,
+ }.Unmarshal(val, m2.Interface())
+ if errUnmarshal != nil {
+ // If the the underlying message cannot be unmarshaled,
+ // then just treat this as an normal message type.
+ return false, nil
+ }
+
+ // Marshal Any before ranging to detect possible mutations.
+ b1, errMarshal := proto.MarshalOptions{
+ AllowPartial: true,
+ Deterministic: true,
+ }.Marshal(m2.Interface())
+ if errMarshal != nil {
+ return true, errMarshal
+ }
+
+ pushStep(p, protopath.AnyExpand(m2.Descriptor()), protoreflect.ValueOfMessage(m2))
+ if push != nil {
+ err = amendError(err, push(*p))
+ }
+ if err == nil {
+ err = o.rangeMessage(p, m2, push, pop)
+ }
+ if pop != nil {
+ err = amendError(err, pop(*p))
+ }
+ popStep(p)
+
+ // Marshal Any after ranging to detect possible mutations.
+ b2, errMarshal := proto.MarshalOptions{
+ AllowPartial: true,
+ Deterministic: true,
+ }.Marshal(m2.Interface())
+ if errMarshal != nil {
+ return true, errMarshal
+ }
+
+ // Mutations detected, write the new sequence of bytes to the Any message.
+ if !bytes.Equal(b1, b2) {
+ m.Set(fds.ByNumber(genid.Any_Value_field_number), protoreflect.ValueOfBytes(b2))
+ }
+
+ if err == Break {
+ err = nil
+ }
+ return true, err
+}
+
+func (o Options) rangeList(p *protopath.Values, fd protoreflect.FieldDescriptor, ls protoreflect.List, push, pop func(protopath.Values) error) (err error) {
+ for i := 0; i < ls.Len() && err == nil; i++ {
+ v := ls.Get(i)
+ pushStep(p, protopath.ListIndex(i), v)
+ if push != nil {
+ err = amendError(err, push(*p))
+ }
+ if err == nil && fd.Message() != nil {
+ err = o.rangeMessage(p, v.Message(), push, pop)
+ }
+ if pop != nil {
+ err = amendError(err, pop(*p))
+ }
+ popStep(p)
+ }
+
+ if err == Break {
+ err = nil
+ }
+ return err
+}
+
+func (o Options) rangeMap(p *protopath.Values, fd protoreflect.FieldDescriptor, ms protoreflect.Map, push, pop func(protopath.Values) error) (err error) {
+ keyOrder := order.AnyKeyOrder
+ if o.Stable {
+ keyOrder = order.GenericKeyOrder
+ }
+ order.RangeEntries(ms, keyOrder, func(k protoreflect.MapKey, v protoreflect.Value) bool {
+ pushStep(p, protopath.MapIndex(k), v)
+ if push != nil {
+ err = amendError(err, push(*p))
+ }
+ if err == nil && fd.MapValue().Message() != nil {
+ err = o.rangeMessage(p, v.Message(), push, pop)
+ }
+ if pop != nil {
+ err = amendError(err, pop(*p))
+ }
+ popStep(p)
+ return err == nil
+ })
+
+ if err == Break {
+ err = nil
+ }
+ return err
+}
+
+func pushStep(p *protopath.Values, s protopath.Step, v protoreflect.Value) {
+ p.Path = append(p.Path, s)
+ p.Values = append(p.Values, v)
+}
+
+func popStep(p *protopath.Values) {
+ p.Path = p.Path[:len(p.Path)-1]
+ p.Values = p.Values[:len(p.Values)-1]
+}
+
+// amendError amends the previous error with the current error if it is
+// considered more serious. The precedence order for errors is:
+//
+// nil < Break < Terminate < previous non-nil < current non-nil
+func amendError(prev, curr error) error {
+ switch {
+ case curr == nil:
+ return prev
+ case curr == Break && prev != nil:
+ return prev
+ case curr == Terminate && prev != nil && prev != Break:
+ return prev
+ default:
+ return curr
+ }
+}
diff --git a/vendor/google.golang.org/protobuf/types/dynamicpb/dynamic.go b/vendor/google.golang.org/protobuf/types/dynamicpb/dynamic.go
new file mode 100644
index 00000000000..1ba1dfa5ad8
--- /dev/null
+++ b/vendor/google.golang.org/protobuf/types/dynamicpb/dynamic.go
@@ -0,0 +1,718 @@
+// Copyright 2019 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 dynamicpb creates protocol buffer messages using runtime type information.
+package dynamicpb
+
+import (
+ "math"
+
+ "google.golang.org/protobuf/internal/errors"
+ "google.golang.org/protobuf/reflect/protoreflect"
+ "google.golang.org/protobuf/runtime/protoiface"
+ "google.golang.org/protobuf/runtime/protoimpl"
+)
+
+// enum is a dynamic protoreflect.Enum.
+type enum struct {
+ num protoreflect.EnumNumber
+ typ protoreflect.EnumType
+}
+
+func (e enum) Descriptor() protoreflect.EnumDescriptor { return e.typ.Descriptor() }
+func (e enum) Type() protoreflect.EnumType { return e.typ }
+func (e enum) Number() protoreflect.EnumNumber { return e.num }
+
+// enumType is a dynamic protoreflect.EnumType.
+type enumType struct {
+ desc protoreflect.EnumDescriptor
+}
+
+// NewEnumType creates a new EnumType with the provided descriptor.
+//
+// EnumTypes created by this package are equal if their descriptors are equal.
+// That is, if ed1 == ed2, then NewEnumType(ed1) == NewEnumType(ed2).
+//
+// Enum values created by the EnumType are equal if their numbers are equal.
+func NewEnumType(desc protoreflect.EnumDescriptor) protoreflect.EnumType {
+ return enumType{desc}
+}
+
+func (et enumType) New(n protoreflect.EnumNumber) protoreflect.Enum { return enum{n, et} }
+func (et enumType) Descriptor() protoreflect.EnumDescriptor { return et.desc }
+
+// extensionType is a dynamic protoreflect.ExtensionType.
+type extensionType struct {
+ desc extensionTypeDescriptor
+}
+
+// A Message is a dynamically constructed protocol buffer message.
+//
+// Message implements the [google.golang.org/protobuf/proto.Message] interface,
+// and may be used with all standard proto package functions
+// such as Marshal, Unmarshal, and so forth.
+//
+// Message also implements the [protoreflect.Message] interface.
+// See the [protoreflect] package documentation for that interface for how to
+// get and set fields and otherwise interact with the contents of a Message.
+//
+// Reflection API functions which construct messages, such as NewField,
+// return new dynamic messages of the appropriate type. Functions which take
+// messages, such as Set for a message-value field, will accept any message
+// with a compatible type.
+//
+// Operations which modify a Message are not safe for concurrent use.
+type Message struct {
+ typ messageType
+ known map[protoreflect.FieldNumber]protoreflect.Value
+ ext map[protoreflect.FieldNumber]protoreflect.FieldDescriptor
+ unknown protoreflect.RawFields
+}
+
+var (
+ _ protoreflect.Message = (*Message)(nil)
+ _ protoreflect.ProtoMessage = (*Message)(nil)
+ _ protoiface.MessageV1 = (*Message)(nil)
+)
+
+// NewMessage creates a new message with the provided descriptor.
+func NewMessage(desc protoreflect.MessageDescriptor) *Message {
+ return &Message{
+ typ: messageType{desc},
+ known: make(map[protoreflect.FieldNumber]protoreflect.Value),
+ ext: make(map[protoreflect.FieldNumber]protoreflect.FieldDescriptor),
+ }
+}
+
+// ProtoMessage implements the legacy message interface.
+func (m *Message) ProtoMessage() {}
+
+// ProtoReflect implements the [protoreflect.ProtoMessage] interface.
+func (m *Message) ProtoReflect() protoreflect.Message {
+ return m
+}
+
+// String returns a string representation of a message.
+func (m *Message) String() string {
+ return protoimpl.X.MessageStringOf(m)
+}
+
+// Reset clears the message to be empty, but preserves the dynamic message type.
+func (m *Message) Reset() {
+ m.known = make(map[protoreflect.FieldNumber]protoreflect.Value)
+ m.ext = make(map[protoreflect.FieldNumber]protoreflect.FieldDescriptor)
+ m.unknown = nil
+}
+
+// Descriptor returns the message descriptor.
+func (m *Message) Descriptor() protoreflect.MessageDescriptor {
+ return m.typ.desc
+}
+
+// Type returns the message type.
+func (m *Message) Type() protoreflect.MessageType {
+ return m.typ
+}
+
+// New returns a newly allocated empty message with the same descriptor.
+// See [protoreflect.Message] for details.
+func (m *Message) New() protoreflect.Message {
+ return m.Type().New()
+}
+
+// Interface returns the message.
+// See [protoreflect.Message] for details.
+func (m *Message) Interface() protoreflect.ProtoMessage {
+ return m
+}
+
+// ProtoMethods is an internal detail of the [protoreflect.Message] interface.
+// Users should never call this directly.
+func (m *Message) ProtoMethods() *protoiface.Methods {
+ return nil
+}
+
+// Range visits every populated field in undefined order.
+// See [protoreflect.Message] for details.
+func (m *Message) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) {
+ for num, v := range m.known {
+ fd := m.ext[num]
+ if fd == nil {
+ fd = m.Descriptor().Fields().ByNumber(num)
+ }
+ if !isSet(fd, v) {
+ continue
+ }
+ if !f(fd, v) {
+ return
+ }
+ }
+}
+
+// Has reports whether a field is populated.
+// See [protoreflect.Message] for details.
+func (m *Message) Has(fd protoreflect.FieldDescriptor) bool {
+ m.checkField(fd)
+ if fd.IsExtension() && m.ext[fd.Number()] != fd {
+ return false
+ }
+ v, ok := m.known[fd.Number()]
+ if !ok {
+ return false
+ }
+ return isSet(fd, v)
+}
+
+// Clear clears a field.
+// See [protoreflect.Message] for details.
+func (m *Message) Clear(fd protoreflect.FieldDescriptor) {
+ m.checkField(fd)
+ num := fd.Number()
+ delete(m.known, num)
+ delete(m.ext, num)
+}
+
+// Get returns the value of a field.
+// See [protoreflect.Message] for details.
+func (m *Message) Get(fd protoreflect.FieldDescriptor) protoreflect.Value {
+ m.checkField(fd)
+ num := fd.Number()
+ if fd.IsExtension() {
+ if fd != m.ext[num] {
+ return fd.(protoreflect.ExtensionTypeDescriptor).Type().Zero()
+ }
+ return m.known[num]
+ }
+ if v, ok := m.known[num]; ok {
+ switch {
+ case fd.IsMap():
+ if v.Map().Len() > 0 {
+ return v
+ }
+ case fd.IsList():
+ if v.List().Len() > 0 {
+ return v
+ }
+ default:
+ return v
+ }
+ }
+ switch {
+ case fd.IsMap():
+ return protoreflect.ValueOfMap(&dynamicMap{desc: fd})
+ case fd.IsList():
+ return protoreflect.ValueOfList(emptyList{desc: fd})
+ case fd.Message() != nil:
+ return protoreflect.ValueOfMessage(&Message{typ: messageType{fd.Message()}})
+ case fd.Kind() == protoreflect.BytesKind:
+ return protoreflect.ValueOfBytes(append([]byte(nil), fd.Default().Bytes()...))
+ default:
+ return fd.Default()
+ }
+}
+
+// Mutable returns a mutable reference to a repeated, map, or message field.
+// See [protoreflect.Message] for details.
+func (m *Message) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value {
+ m.checkField(fd)
+ if !fd.IsMap() && !fd.IsList() && fd.Message() == nil {
+ panic(errors.New("%v: getting mutable reference to non-composite type", fd.FullName()))
+ }
+ if m.known == nil {
+ panic(errors.New("%v: modification of read-only message", fd.FullName()))
+ }
+ num := fd.Number()
+ if fd.IsExtension() {
+ if fd != m.ext[num] {
+ m.ext[num] = fd
+ m.known[num] = fd.(protoreflect.ExtensionTypeDescriptor).Type().New()
+ }
+ return m.known[num]
+ }
+ if v, ok := m.known[num]; ok {
+ return v
+ }
+ m.clearOtherOneofFields(fd)
+ m.known[num] = m.NewField(fd)
+ if fd.IsExtension() {
+ m.ext[num] = fd
+ }
+ return m.known[num]
+}
+
+// Set stores a value in a field.
+// See [protoreflect.Message] for details.
+func (m *Message) Set(fd protoreflect.FieldDescriptor, v protoreflect.Value) {
+ m.checkField(fd)
+ if m.known == nil {
+ panic(errors.New("%v: modification of read-only message", fd.FullName()))
+ }
+ if fd.IsExtension() {
+ isValid := true
+ switch {
+ case !fd.(protoreflect.ExtensionTypeDescriptor).Type().IsValidValue(v):
+ isValid = false
+ case fd.IsList():
+ isValid = v.List().IsValid()
+ case fd.IsMap():
+ isValid = v.Map().IsValid()
+ case fd.Message() != nil:
+ isValid = v.Message().IsValid()
+ }
+ if !isValid {
+ panic(errors.New("%v: assigning invalid type %T", fd.FullName(), v.Interface()))
+ }
+ m.ext[fd.Number()] = fd
+ } else {
+ typecheck(fd, v)
+ }
+ m.clearOtherOneofFields(fd)
+ m.known[fd.Number()] = v
+}
+
+func (m *Message) clearOtherOneofFields(fd protoreflect.FieldDescriptor) {
+ od := fd.ContainingOneof()
+ if od == nil {
+ return
+ }
+ num := fd.Number()
+ for i := 0; i < od.Fields().Len(); i++ {
+ if n := od.Fields().Get(i).Number(); n != num {
+ delete(m.known, n)
+ }
+ }
+}
+
+// NewField returns a new value for assignable to the field of a given descriptor.
+// See [protoreflect.Message] for details.
+func (m *Message) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value {
+ m.checkField(fd)
+ switch {
+ case fd.IsExtension():
+ return fd.(protoreflect.ExtensionTypeDescriptor).Type().New()
+ case fd.IsMap():
+ return protoreflect.ValueOfMap(&dynamicMap{
+ desc: fd,
+ mapv: make(map[any]protoreflect.Value),
+ })
+ case fd.IsList():
+ return protoreflect.ValueOfList(&dynamicList{desc: fd})
+ case fd.Message() != nil:
+ return protoreflect.ValueOfMessage(NewMessage(fd.Message()).ProtoReflect())
+ default:
+ return fd.Default()
+ }
+}
+
+// WhichOneof reports which field in a oneof is populated, returning nil if none are populated.
+// See [protoreflect.Message] for details.
+func (m *Message) WhichOneof(od protoreflect.OneofDescriptor) protoreflect.FieldDescriptor {
+ for i := 0; i < od.Fields().Len(); i++ {
+ fd := od.Fields().Get(i)
+ if m.Has(fd) {
+ return fd
+ }
+ }
+ return nil
+}
+
+// GetUnknown returns the raw unknown fields.
+// See [protoreflect.Message] for details.
+func (m *Message) GetUnknown() protoreflect.RawFields {
+ return m.unknown
+}
+
+// SetUnknown sets the raw unknown fields.
+// See [protoreflect.Message] for details.
+func (m *Message) SetUnknown(r protoreflect.RawFields) {
+ if m.known == nil {
+ panic(errors.New("%v: modification of read-only message", m.typ.desc.FullName()))
+ }
+ m.unknown = r
+}
+
+// IsValid reports whether the message is valid.
+// See [protoreflect.Message] for details.
+func (m *Message) IsValid() bool {
+ return m.known != nil
+}
+
+func (m *Message) checkField(fd protoreflect.FieldDescriptor) {
+ if fd.IsExtension() && fd.ContainingMessage().FullName() == m.Descriptor().FullName() {
+ if _, ok := fd.(protoreflect.ExtensionTypeDescriptor); !ok {
+ panic(errors.New("%v: extension field descriptor does not implement ExtensionTypeDescriptor", fd.FullName()))
+ }
+ return
+ }
+ if fd.Parent() == m.Descriptor() {
+ return
+ }
+ fields := m.Descriptor().Fields()
+ index := fd.Index()
+ if index >= fields.Len() || fields.Get(index) != fd {
+ panic(errors.New("%v: field descriptor does not belong to this message", fd.FullName()))
+ }
+}
+
+type messageType struct {
+ desc protoreflect.MessageDescriptor
+}
+
+// NewMessageType creates a new MessageType with the provided descriptor.
+//
+// MessageTypes created by this package are equal if their descriptors are equal.
+// That is, if md1 == md2, then NewMessageType(md1) == NewMessageType(md2).
+func NewMessageType(desc protoreflect.MessageDescriptor) protoreflect.MessageType {
+ return messageType{desc}
+}
+
+func (mt messageType) New() protoreflect.Message { return NewMessage(mt.desc) }
+func (mt messageType) Zero() protoreflect.Message { return &Message{typ: messageType{mt.desc}} }
+func (mt messageType) Descriptor() protoreflect.MessageDescriptor { return mt.desc }
+func (mt messageType) Enum(i int) protoreflect.EnumType {
+ if ed := mt.desc.Fields().Get(i).Enum(); ed != nil {
+ return NewEnumType(ed)
+ }
+ return nil
+}
+func (mt messageType) Message(i int) protoreflect.MessageType {
+ if md := mt.desc.Fields().Get(i).Message(); md != nil {
+ return NewMessageType(md)
+ }
+ return nil
+}
+
+type emptyList struct {
+ desc protoreflect.FieldDescriptor
+}
+
+func (x emptyList) Len() int { return 0 }
+func (x emptyList) Get(n int) protoreflect.Value { panic(errors.New("out of range")) }
+func (x emptyList) Set(n int, v protoreflect.Value) {
+ panic(errors.New("modification of immutable list"))
+}
+func (x emptyList) Append(v protoreflect.Value) { panic(errors.New("modification of immutable list")) }
+func (x emptyList) AppendMutable() protoreflect.Value {
+ panic(errors.New("modification of immutable list"))
+}
+func (x emptyList) Truncate(n int) { panic(errors.New("modification of immutable list")) }
+func (x emptyList) NewElement() protoreflect.Value { return newListEntry(x.desc) }
+func (x emptyList) IsValid() bool { return false }
+
+type dynamicList struct {
+ desc protoreflect.FieldDescriptor
+ list []protoreflect.Value
+}
+
+func (x *dynamicList) Len() int {
+ return len(x.list)
+}
+
+func (x *dynamicList) Get(n int) protoreflect.Value {
+ return x.list[n]
+}
+
+func (x *dynamicList) Set(n int, v protoreflect.Value) {
+ typecheckSingular(x.desc, v)
+ x.list[n] = v
+}
+
+func (x *dynamicList) Append(v protoreflect.Value) {
+ typecheckSingular(x.desc, v)
+ x.list = append(x.list, v)
+}
+
+func (x *dynamicList) AppendMutable() protoreflect.Value {
+ if x.desc.Message() == nil {
+ panic(errors.New("%v: invalid AppendMutable on list with non-message type", x.desc.FullName()))
+ }
+ v := x.NewElement()
+ x.Append(v)
+ return v
+}
+
+func (x *dynamicList) Truncate(n int) {
+ // Zero truncated elements to avoid keeping data live.
+ for i := n; i < len(x.list); i++ {
+ x.list[i] = protoreflect.Value{}
+ }
+ x.list = x.list[:n]
+}
+
+func (x *dynamicList) NewElement() protoreflect.Value {
+ return newListEntry(x.desc)
+}
+
+func (x *dynamicList) IsValid() bool {
+ return true
+}
+
+type dynamicMap struct {
+ desc protoreflect.FieldDescriptor
+ mapv map[any]protoreflect.Value
+}
+
+func (x *dynamicMap) Get(k protoreflect.MapKey) protoreflect.Value { return x.mapv[k.Interface()] }
+func (x *dynamicMap) Set(k protoreflect.MapKey, v protoreflect.Value) {
+ typecheckSingular(x.desc.MapKey(), k.Value())
+ typecheckSingular(x.desc.MapValue(), v)
+ x.mapv[k.Interface()] = v
+}
+func (x *dynamicMap) Has(k protoreflect.MapKey) bool { return x.Get(k).IsValid() }
+func (x *dynamicMap) Clear(k protoreflect.MapKey) { delete(x.mapv, k.Interface()) }
+func (x *dynamicMap) Mutable(k protoreflect.MapKey) protoreflect.Value {
+ if x.desc.MapValue().Message() == nil {
+ panic(errors.New("%v: invalid Mutable on map with non-message value type", x.desc.FullName()))
+ }
+ v := x.Get(k)
+ if !v.IsValid() {
+ v = x.NewValue()
+ x.Set(k, v)
+ }
+ return v
+}
+func (x *dynamicMap) Len() int { return len(x.mapv) }
+func (x *dynamicMap) NewValue() protoreflect.Value {
+ if md := x.desc.MapValue().Message(); md != nil {
+ return protoreflect.ValueOfMessage(NewMessage(md).ProtoReflect())
+ }
+ return x.desc.MapValue().Default()
+}
+func (x *dynamicMap) IsValid() bool {
+ return x.mapv != nil
+}
+
+func (x *dynamicMap) Range(f func(protoreflect.MapKey, protoreflect.Value) bool) {
+ for k, v := range x.mapv {
+ if !f(protoreflect.ValueOf(k).MapKey(), v) {
+ return
+ }
+ }
+}
+
+func isSet(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {
+ switch {
+ case fd.IsMap():
+ return v.Map().Len() > 0
+ case fd.IsList():
+ return v.List().Len() > 0
+ case fd.ContainingOneof() != nil:
+ return true
+ case !fd.HasPresence() && !fd.IsExtension():
+ switch fd.Kind() {
+ case protoreflect.BoolKind:
+ return v.Bool()
+ case protoreflect.EnumKind:
+ return v.Enum() != 0
+ case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed32Kind, protoreflect.Sfixed64Kind:
+ return v.Int() != 0
+ case protoreflect.Uint32Kind, protoreflect.Uint64Kind, protoreflect.Fixed32Kind, protoreflect.Fixed64Kind:
+ return v.Uint() != 0
+ case protoreflect.FloatKind, protoreflect.DoubleKind:
+ return v.Float() != 0 || math.Signbit(v.Float())
+ case protoreflect.StringKind:
+ return v.String() != ""
+ case protoreflect.BytesKind:
+ return len(v.Bytes()) > 0
+ }
+ }
+ return true
+}
+
+func typecheck(fd protoreflect.FieldDescriptor, v protoreflect.Value) {
+ if err := typeIsValid(fd, v); err != nil {
+ panic(err)
+ }
+}
+
+func typeIsValid(fd protoreflect.FieldDescriptor, v protoreflect.Value) error {
+ switch {
+ case !v.IsValid():
+ return errors.New("%v: assigning invalid value", fd.FullName())
+ case fd.IsMap():
+ if mapv, ok := v.Interface().(*dynamicMap); !ok || mapv.desc != fd || !mapv.IsValid() {
+ return errors.New("%v: assigning invalid type %T", fd.FullName(), v.Interface())
+ }
+ return nil
+ case fd.IsList():
+ switch list := v.Interface().(type) {
+ case *dynamicList:
+ if list.desc == fd && list.IsValid() {
+ return nil
+ }
+ case emptyList:
+ if list.desc == fd && list.IsValid() {
+ return nil
+ }
+ }
+ return errors.New("%v: assigning invalid type %T", fd.FullName(), v.Interface())
+ default:
+ return singularTypeIsValid(fd, v)
+ }
+}
+
+func typecheckSingular(fd protoreflect.FieldDescriptor, v protoreflect.Value) {
+ if err := singularTypeIsValid(fd, v); err != nil {
+ panic(err)
+ }
+}
+
+func singularTypeIsValid(fd protoreflect.FieldDescriptor, v protoreflect.Value) error {
+ vi := v.Interface()
+ var ok bool
+ switch fd.Kind() {
+ case protoreflect.BoolKind:
+ _, ok = vi.(bool)
+ case protoreflect.EnumKind:
+ // We could check against the valid set of enum values, but do not.
+ _, ok = vi.(protoreflect.EnumNumber)
+ case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
+ _, ok = vi.(int32)
+ case protoreflect.Uint32Kind, protoreflect.Fixed32Kind:
+ _, ok = vi.(uint32)
+ case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
+ _, ok = vi.(int64)
+ case protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
+ _, ok = vi.(uint64)
+ case protoreflect.FloatKind:
+ _, ok = vi.(float32)
+ case protoreflect.DoubleKind:
+ _, ok = vi.(float64)
+ case protoreflect.StringKind:
+ _, ok = vi.(string)
+ case protoreflect.BytesKind:
+ _, ok = vi.([]byte)
+ case protoreflect.MessageKind, protoreflect.GroupKind:
+ var m protoreflect.Message
+ m, ok = vi.(protoreflect.Message)
+ if ok && m.Descriptor().FullName() != fd.Message().FullName() {
+ return errors.New("%v: assigning invalid message type %v", fd.FullName(), m.Descriptor().FullName())
+ }
+ if dm, ok := vi.(*Message); ok && dm.known == nil {
+ return errors.New("%v: assigning invalid zero-value message", fd.FullName())
+ }
+ }
+ if !ok {
+ return errors.New("%v: assigning invalid type %T", fd.FullName(), v.Interface())
+ }
+ return nil
+}
+
+func newListEntry(fd protoreflect.FieldDescriptor) protoreflect.Value {
+ switch fd.Kind() {
+ case protoreflect.BoolKind:
+ return protoreflect.ValueOfBool(false)
+ case protoreflect.EnumKind:
+ return protoreflect.ValueOfEnum(fd.Enum().Values().Get(0).Number())
+ case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
+ return protoreflect.ValueOfInt32(0)
+ case protoreflect.Uint32Kind, protoreflect.Fixed32Kind:
+ return protoreflect.ValueOfUint32(0)
+ case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
+ return protoreflect.ValueOfInt64(0)
+ case protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
+ return protoreflect.ValueOfUint64(0)
+ case protoreflect.FloatKind:
+ return protoreflect.ValueOfFloat32(0)
+ case protoreflect.DoubleKind:
+ return protoreflect.ValueOfFloat64(0)
+ case protoreflect.StringKind:
+ return protoreflect.ValueOfString("")
+ case protoreflect.BytesKind:
+ return protoreflect.ValueOfBytes(nil)
+ case protoreflect.MessageKind, protoreflect.GroupKind:
+ return protoreflect.ValueOfMessage(NewMessage(fd.Message()).ProtoReflect())
+ }
+ panic(errors.New("%v: unknown kind %v", fd.FullName(), fd.Kind()))
+}
+
+// NewExtensionType creates a new ExtensionType with the provided descriptor.
+//
+// Dynamic ExtensionTypes with the same descriptor compare as equal. That is,
+// if xd1 == xd2, then NewExtensionType(xd1) == NewExtensionType(xd2).
+//
+// The InterfaceOf and ValueOf methods of the extension type are defined as:
+//
+// func (xt extensionType) ValueOf(iv any) protoreflect.Value {
+// return protoreflect.ValueOf(iv)
+// }
+//
+// func (xt extensionType) InterfaceOf(v protoreflect.Value) any {
+// return v.Interface()
+// }
+//
+// The Go type used by the proto.GetExtension and proto.SetExtension functions
+// is determined by these methods, and is therefore equivalent to the Go type
+// used to represent a protoreflect.Value. See the protoreflect.Value
+// documentation for more details.
+func NewExtensionType(desc protoreflect.ExtensionDescriptor) protoreflect.ExtensionType {
+ if xt, ok := desc.(protoreflect.ExtensionTypeDescriptor); ok {
+ desc = xt.Descriptor()
+ }
+ return extensionType{extensionTypeDescriptor{desc}}
+}
+
+func (xt extensionType) New() protoreflect.Value {
+ switch {
+ case xt.desc.IsMap():
+ return protoreflect.ValueOfMap(&dynamicMap{
+ desc: xt.desc,
+ mapv: make(map[any]protoreflect.Value),
+ })
+ case xt.desc.IsList():
+ return protoreflect.ValueOfList(&dynamicList{desc: xt.desc})
+ case xt.desc.Message() != nil:
+ return protoreflect.ValueOfMessage(NewMessage(xt.desc.Message()))
+ default:
+ return xt.desc.Default()
+ }
+}
+
+func (xt extensionType) Zero() protoreflect.Value {
+ switch {
+ case xt.desc.IsMap():
+ return protoreflect.ValueOfMap(&dynamicMap{desc: xt.desc})
+ case xt.desc.Cardinality() == protoreflect.Repeated:
+ return protoreflect.ValueOfList(emptyList{desc: xt.desc})
+ case xt.desc.Message() != nil:
+ return protoreflect.ValueOfMessage(&Message{typ: messageType{xt.desc.Message()}})
+ default:
+ return xt.desc.Default()
+ }
+}
+
+func (xt extensionType) TypeDescriptor() protoreflect.ExtensionTypeDescriptor {
+ return xt.desc
+}
+
+func (xt extensionType) ValueOf(iv any) protoreflect.Value {
+ v := protoreflect.ValueOf(iv)
+ typecheck(xt.desc, v)
+ return v
+}
+
+func (xt extensionType) InterfaceOf(v protoreflect.Value) any {
+ typecheck(xt.desc, v)
+ return v.Interface()
+}
+
+func (xt extensionType) IsValidInterface(iv any) bool {
+ return typeIsValid(xt.desc, protoreflect.ValueOf(iv)) == nil
+}
+
+func (xt extensionType) IsValidValue(v protoreflect.Value) bool {
+ return typeIsValid(xt.desc, v) == nil
+}
+
+type extensionTypeDescriptor struct {
+ protoreflect.ExtensionDescriptor
+}
+
+func (xt extensionTypeDescriptor) Type() protoreflect.ExtensionType {
+ return extensionType{xt}
+}
+
+func (xt extensionTypeDescriptor) Descriptor() protoreflect.ExtensionDescriptor {
+ return xt.ExtensionDescriptor
+}
diff --git a/vendor/google.golang.org/protobuf/types/dynamicpb/types.go b/vendor/google.golang.org/protobuf/types/dynamicpb/types.go
new file mode 100644
index 00000000000..c432817bb9c
--- /dev/null
+++ b/vendor/google.golang.org/protobuf/types/dynamicpb/types.go
@@ -0,0 +1,184 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package dynamicpb
+
+import (
+ "fmt"
+ "strings"
+ "sync"
+ "sync/atomic"
+
+ "google.golang.org/protobuf/internal/errors"
+ "google.golang.org/protobuf/reflect/protoreflect"
+ "google.golang.org/protobuf/reflect/protoregistry"
+)
+
+type extField struct {
+ name protoreflect.FullName
+ number protoreflect.FieldNumber
+}
+
+// A Types is a collection of dynamically constructed descriptors.
+// Its methods are safe for concurrent use.
+//
+// Types implements [protoregistry.MessageTypeResolver] and [protoregistry.ExtensionTypeResolver].
+// A Types may be used as a [google.golang.org/protobuf/proto.UnmarshalOptions.Resolver].
+type Types struct {
+ // atomicExtFiles is used with sync/atomic and hence must be the first word
+ // of the struct to guarantee 64-bit alignment.
+ //
+ // TODO(stapelberg): once we only support Go 1.19 and newer, switch this
+ // field to be of type atomic.Uint64 to guarantee alignment on
+ // stack-allocated values, too.
+ atomicExtFiles uint64
+ extMu sync.Mutex
+
+ files *protoregistry.Files
+
+ extensionsByMessage map[extField]protoreflect.ExtensionDescriptor
+}
+
+// NewTypes creates a new Types registry with the provided files.
+// The Files registry is retained, and changes to Files will be reflected in Types.
+// It is not safe to concurrently change the Files while calling Types methods.
+func NewTypes(f *protoregistry.Files) *Types {
+ return &Types{
+ files: f,
+ }
+}
+
+// FindEnumByName looks up an enum by its full name;
+// e.g., "google.protobuf.Field.Kind".
+//
+// This returns (nil, [protoregistry.NotFound]) if not found.
+func (t *Types) FindEnumByName(name protoreflect.FullName) (protoreflect.EnumType, error) {
+ d, err := t.files.FindDescriptorByName(name)
+ if err != nil {
+ return nil, err
+ }
+ ed, ok := d.(protoreflect.EnumDescriptor)
+ if !ok {
+ return nil, errors.New("found wrong type: got %v, want enum", descName(d))
+ }
+ return NewEnumType(ed), nil
+}
+
+// FindExtensionByName looks up an extension field by the field's full name.
+// Note that this is the full name of the field as determined by
+// where the extension is declared and is unrelated to the full name of the
+// message being extended.
+//
+// This returns (nil, [protoregistry.NotFound]) if not found.
+func (t *Types) FindExtensionByName(name protoreflect.FullName) (protoreflect.ExtensionType, error) {
+ d, err := t.files.FindDescriptorByName(name)
+ if err != nil {
+ return nil, err
+ }
+ xd, ok := d.(protoreflect.ExtensionDescriptor)
+ if !ok {
+ return nil, errors.New("found wrong type: got %v, want extension", descName(d))
+ }
+ return NewExtensionType(xd), nil
+}
+
+// FindExtensionByNumber looks up an extension field by the field number
+// within some parent message, identified by full name.
+//
+// This returns (nil, [protoregistry.NotFound]) if not found.
+func (t *Types) FindExtensionByNumber(message protoreflect.FullName, field protoreflect.FieldNumber) (protoreflect.ExtensionType, error) {
+ // Construct the extension number map lazily, since not every user will need it.
+ // Update the map if new files are added to the registry.
+ if atomic.LoadUint64(&t.atomicExtFiles) != uint64(t.files.NumFiles()) {
+ t.updateExtensions()
+ }
+ xd := t.extensionsByMessage[extField{message, field}]
+ if xd == nil {
+ return nil, protoregistry.NotFound
+ }
+ return NewExtensionType(xd), nil
+}
+
+// FindMessageByName looks up a message by its full name;
+// e.g. "google.protobuf.Any".
+//
+// This returns (nil, [protoregistry.NotFound]) if not found.
+func (t *Types) FindMessageByName(name protoreflect.FullName) (protoreflect.MessageType, error) {
+ d, err := t.files.FindDescriptorByName(name)
+ if err != nil {
+ return nil, err
+ }
+ md, ok := d.(protoreflect.MessageDescriptor)
+ if !ok {
+ return nil, errors.New("found wrong type: got %v, want message", descName(d))
+ }
+ return NewMessageType(md), nil
+}
+
+// FindMessageByURL looks up a message by a URL identifier.
+// See documentation on google.protobuf.Any.type_url for the URL format.
+//
+// This returns (nil, [protoregistry.NotFound]) if not found.
+func (t *Types) FindMessageByURL(url string) (protoreflect.MessageType, error) {
+ // This function is similar to FindMessageByName but
+ // truncates anything before and including '/' in the URL.
+ message := protoreflect.FullName(url)
+ if i := strings.LastIndexByte(url, '/'); i >= 0 {
+ message = message[i+len("/"):]
+ }
+ return t.FindMessageByName(message)
+}
+
+func (t *Types) updateExtensions() {
+ t.extMu.Lock()
+ defer t.extMu.Unlock()
+ if atomic.LoadUint64(&t.atomicExtFiles) == uint64(t.files.NumFiles()) {
+ return
+ }
+ defer atomic.StoreUint64(&t.atomicExtFiles, uint64(t.files.NumFiles()))
+ t.files.RangeFiles(func(fd protoreflect.FileDescriptor) bool {
+ t.registerExtensions(fd.Extensions())
+ t.registerExtensionsInMessages(fd.Messages())
+ return true
+ })
+}
+
+func (t *Types) registerExtensionsInMessages(mds protoreflect.MessageDescriptors) {
+ count := mds.Len()
+ for i := 0; i < count; i++ {
+ md := mds.Get(i)
+ t.registerExtensions(md.Extensions())
+ t.registerExtensionsInMessages(md.Messages())
+ }
+}
+
+func (t *Types) registerExtensions(xds protoreflect.ExtensionDescriptors) {
+ count := xds.Len()
+ for i := 0; i < count; i++ {
+ xd := xds.Get(i)
+ field := xd.Number()
+ message := xd.ContainingMessage().FullName()
+ if t.extensionsByMessage == nil {
+ t.extensionsByMessage = make(map[extField]protoreflect.ExtensionDescriptor)
+ }
+ t.extensionsByMessage[extField{message, field}] = xd
+ }
+}
+
+func descName(d protoreflect.Descriptor) string {
+ switch d.(type) {
+ case protoreflect.EnumDescriptor:
+ return "enum"
+ case protoreflect.EnumValueDescriptor:
+ return "enum value"
+ case protoreflect.MessageDescriptor:
+ return "message"
+ case protoreflect.ExtensionDescriptor:
+ return "extension"
+ case protoreflect.ServiceDescriptor:
+ return "service"
+ default:
+ return fmt.Sprintf("%T", d)
+ }
+}
diff --git a/vendor/google.golang.org/protobuf/types/pluginpb/plugin.pb.go b/vendor/google.golang.org/protobuf/types/pluginpb/plugin.pb.go
new file mode 100644
index 00000000000..a8f6898a3f7
--- /dev/null
+++ b/vendor/google.golang.org/protobuf/types/pluginpb/plugin.pb.go
@@ -0,0 +1,628 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+//
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file or at
+// https://developers.google.com/open-source/licenses/bsd
+
+// Author: kenton@google.com (Kenton Varda)
+//
+// protoc (aka the Protocol Compiler) can be extended via plugins. A plugin is
+// just a program that reads a CodeGeneratorRequest from stdin and writes a
+// CodeGeneratorResponse to stdout.
+//
+// Plugins written using C++ can use google/protobuf/compiler/plugin.h instead
+// of dealing with the raw protocol defined here.
+//
+// A plugin executable needs only to be placed somewhere in the path. The
+// plugin should be named "protoc-gen-$NAME", and will then be used when the
+// flag "--${NAME}_out" is passed to protoc.
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: google/protobuf/compiler/plugin.proto
+
+package pluginpb
+
+import (
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ descriptorpb "google.golang.org/protobuf/types/descriptorpb"
+ reflect "reflect"
+ sync "sync"
+)
+
+// Sync with code_generator.h.
+type CodeGeneratorResponse_Feature int32
+
+const (
+ CodeGeneratorResponse_FEATURE_NONE CodeGeneratorResponse_Feature = 0
+ CodeGeneratorResponse_FEATURE_PROTO3_OPTIONAL CodeGeneratorResponse_Feature = 1
+ CodeGeneratorResponse_FEATURE_SUPPORTS_EDITIONS CodeGeneratorResponse_Feature = 2
+)
+
+// Enum value maps for CodeGeneratorResponse_Feature.
+var (
+ CodeGeneratorResponse_Feature_name = map[int32]string{
+ 0: "FEATURE_NONE",
+ 1: "FEATURE_PROTO3_OPTIONAL",
+ 2: "FEATURE_SUPPORTS_EDITIONS",
+ }
+ CodeGeneratorResponse_Feature_value = map[string]int32{
+ "FEATURE_NONE": 0,
+ "FEATURE_PROTO3_OPTIONAL": 1,
+ "FEATURE_SUPPORTS_EDITIONS": 2,
+ }
+)
+
+func (x CodeGeneratorResponse_Feature) Enum() *CodeGeneratorResponse_Feature {
+ p := new(CodeGeneratorResponse_Feature)
+ *p = x
+ return p
+}
+
+func (x CodeGeneratorResponse_Feature) String() string {
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (CodeGeneratorResponse_Feature) Descriptor() protoreflect.EnumDescriptor {
+ return file_google_protobuf_compiler_plugin_proto_enumTypes[0].Descriptor()
+}
+
+func (CodeGeneratorResponse_Feature) Type() protoreflect.EnumType {
+ return &file_google_protobuf_compiler_plugin_proto_enumTypes[0]
+}
+
+func (x CodeGeneratorResponse_Feature) Number() protoreflect.EnumNumber {
+ return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Do not use.
+func (x *CodeGeneratorResponse_Feature) UnmarshalJSON(b []byte) error {
+ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
+ if err != nil {
+ return err
+ }
+ *x = CodeGeneratorResponse_Feature(num)
+ return nil
+}
+
+// Deprecated: Use CodeGeneratorResponse_Feature.Descriptor instead.
+func (CodeGeneratorResponse_Feature) EnumDescriptor() ([]byte, []int) {
+ return file_google_protobuf_compiler_plugin_proto_rawDescGZIP(), []int{2, 0}
+}
+
+// The version number of protocol compiler.
+type Version struct {
+ state protoimpl.MessageState `protogen:"open.v1"`
+ Major *int32 `protobuf:"varint,1,opt,name=major" json:"major,omitempty"`
+ Minor *int32 `protobuf:"varint,2,opt,name=minor" json:"minor,omitempty"`
+ Patch *int32 `protobuf:"varint,3,opt,name=patch" json:"patch,omitempty"`
+ // A suffix for alpha, beta or rc release, e.g., "alpha-1", "rc2". It should
+ // be empty for mainline stable releases.
+ Suffix *string `protobuf:"bytes,4,opt,name=suffix" json:"suffix,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
+}
+
+func (x *Version) Reset() {
+ *x = Version{}
+ mi := &file_google_protobuf_compiler_plugin_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *Version) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Version) ProtoMessage() {}
+
+func (x *Version) ProtoReflect() protoreflect.Message {
+ mi := &file_google_protobuf_compiler_plugin_proto_msgTypes[0]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use Version.ProtoReflect.Descriptor instead.
+func (*Version) Descriptor() ([]byte, []int) {
+ return file_google_protobuf_compiler_plugin_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *Version) GetMajor() int32 {
+ if x != nil && x.Major != nil {
+ return *x.Major
+ }
+ return 0
+}
+
+func (x *Version) GetMinor() int32 {
+ if x != nil && x.Minor != nil {
+ return *x.Minor
+ }
+ return 0
+}
+
+func (x *Version) GetPatch() int32 {
+ if x != nil && x.Patch != nil {
+ return *x.Patch
+ }
+ return 0
+}
+
+func (x *Version) GetSuffix() string {
+ if x != nil && x.Suffix != nil {
+ return *x.Suffix
+ }
+ return ""
+}
+
+// An encoded CodeGeneratorRequest is written to the plugin's stdin.
+type CodeGeneratorRequest struct {
+ state protoimpl.MessageState `protogen:"open.v1"`
+ // The .proto files that were explicitly listed on the command-line. The
+ // code generator should generate code only for these files. Each file's
+ // descriptor will be included in proto_file, below.
+ FileToGenerate []string `protobuf:"bytes,1,rep,name=file_to_generate,json=fileToGenerate" json:"file_to_generate,omitempty"`
+ // The generator parameter passed on the command-line.
+ Parameter *string `protobuf:"bytes,2,opt,name=parameter" json:"parameter,omitempty"`
+ // FileDescriptorProtos for all files in files_to_generate and everything
+ // they import. The files will appear in topological order, so each file
+ // appears before any file that imports it.
+ //
+ // Note: the files listed in files_to_generate will include runtime-retention
+ // options only, but all other files will include source-retention options.
+ // The source_file_descriptors field below is available in case you need
+ // source-retention options for files_to_generate.
+ //
+ // protoc guarantees that all proto_files will be written after
+ // the fields above, even though this is not technically guaranteed by the
+ // protobuf wire format. This theoretically could allow a plugin to stream
+ // in the FileDescriptorProtos and handle them one by one rather than read
+ // the entire set into memory at once. However, as of this writing, this
+ // is not similarly optimized on protoc's end -- it will store all fields in
+ // memory at once before sending them to the plugin.
+ //
+ // Type names of fields and extensions in the FileDescriptorProto are always
+ // fully qualified.
+ ProtoFile []*descriptorpb.FileDescriptorProto `protobuf:"bytes,15,rep,name=proto_file,json=protoFile" json:"proto_file,omitempty"`
+ // File descriptors with all options, including source-retention options.
+ // These descriptors are only provided for the files listed in
+ // files_to_generate.
+ SourceFileDescriptors []*descriptorpb.FileDescriptorProto `protobuf:"bytes,17,rep,name=source_file_descriptors,json=sourceFileDescriptors" json:"source_file_descriptors,omitempty"`
+ // The version number of protocol compiler.
+ CompilerVersion *Version `protobuf:"bytes,3,opt,name=compiler_version,json=compilerVersion" json:"compiler_version,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
+}
+
+func (x *CodeGeneratorRequest) Reset() {
+ *x = CodeGeneratorRequest{}
+ mi := &file_google_protobuf_compiler_plugin_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *CodeGeneratorRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CodeGeneratorRequest) ProtoMessage() {}
+
+func (x *CodeGeneratorRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_google_protobuf_compiler_plugin_proto_msgTypes[1]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CodeGeneratorRequest.ProtoReflect.Descriptor instead.
+func (*CodeGeneratorRequest) Descriptor() ([]byte, []int) {
+ return file_google_protobuf_compiler_plugin_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *CodeGeneratorRequest) GetFileToGenerate() []string {
+ if x != nil {
+ return x.FileToGenerate
+ }
+ return nil
+}
+
+func (x *CodeGeneratorRequest) GetParameter() string {
+ if x != nil && x.Parameter != nil {
+ return *x.Parameter
+ }
+ return ""
+}
+
+func (x *CodeGeneratorRequest) GetProtoFile() []*descriptorpb.FileDescriptorProto {
+ if x != nil {
+ return x.ProtoFile
+ }
+ return nil
+}
+
+func (x *CodeGeneratorRequest) GetSourceFileDescriptors() []*descriptorpb.FileDescriptorProto {
+ if x != nil {
+ return x.SourceFileDescriptors
+ }
+ return nil
+}
+
+func (x *CodeGeneratorRequest) GetCompilerVersion() *Version {
+ if x != nil {
+ return x.CompilerVersion
+ }
+ return nil
+}
+
+// The plugin writes an encoded CodeGeneratorResponse to stdout.
+type CodeGeneratorResponse struct {
+ state protoimpl.MessageState `protogen:"open.v1"`
+ // Error message. If non-empty, code generation failed. The plugin process
+ // should exit with status code zero even if it reports an error in this way.
+ //
+ // This should be used to indicate errors in .proto files which prevent the
+ // code generator from generating correct code. Errors which indicate a
+ // problem in protoc itself -- such as the input CodeGeneratorRequest being
+ // unparseable -- should be reported by writing a message to stderr and
+ // exiting with a non-zero status code.
+ Error *string `protobuf:"bytes,1,opt,name=error" json:"error,omitempty"`
+ // A bitmask of supported features that the code generator supports.
+ // This is a bitwise "or" of values from the Feature enum.
+ SupportedFeatures *uint64 `protobuf:"varint,2,opt,name=supported_features,json=supportedFeatures" json:"supported_features,omitempty"`
+ // The minimum edition this plugin supports. This will be treated as an
+ // Edition enum, but we want to allow unknown values. It should be specified
+ // according the edition enum value, *not* the edition number. Only takes
+ // effect for plugins that have FEATURE_SUPPORTS_EDITIONS set.
+ MinimumEdition *int32 `protobuf:"varint,3,opt,name=minimum_edition,json=minimumEdition" json:"minimum_edition,omitempty"`
+ // The maximum edition this plugin supports. This will be treated as an
+ // Edition enum, but we want to allow unknown values. It should be specified
+ // according the edition enum value, *not* the edition number. Only takes
+ // effect for plugins that have FEATURE_SUPPORTS_EDITIONS set.
+ MaximumEdition *int32 `protobuf:"varint,4,opt,name=maximum_edition,json=maximumEdition" json:"maximum_edition,omitempty"`
+ File []*CodeGeneratorResponse_File `protobuf:"bytes,15,rep,name=file" json:"file,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
+}
+
+func (x *CodeGeneratorResponse) Reset() {
+ *x = CodeGeneratorResponse{}
+ mi := &file_google_protobuf_compiler_plugin_proto_msgTypes[2]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *CodeGeneratorResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CodeGeneratorResponse) ProtoMessage() {}
+
+func (x *CodeGeneratorResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_google_protobuf_compiler_plugin_proto_msgTypes[2]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CodeGeneratorResponse.ProtoReflect.Descriptor instead.
+func (*CodeGeneratorResponse) Descriptor() ([]byte, []int) {
+ return file_google_protobuf_compiler_plugin_proto_rawDescGZIP(), []int{2}
+}
+
+func (x *CodeGeneratorResponse) GetError() string {
+ if x != nil && x.Error != nil {
+ return *x.Error
+ }
+ return ""
+}
+
+func (x *CodeGeneratorResponse) GetSupportedFeatures() uint64 {
+ if x != nil && x.SupportedFeatures != nil {
+ return *x.SupportedFeatures
+ }
+ return 0
+}
+
+func (x *CodeGeneratorResponse) GetMinimumEdition() int32 {
+ if x != nil && x.MinimumEdition != nil {
+ return *x.MinimumEdition
+ }
+ return 0
+}
+
+func (x *CodeGeneratorResponse) GetMaximumEdition() int32 {
+ if x != nil && x.MaximumEdition != nil {
+ return *x.MaximumEdition
+ }
+ return 0
+}
+
+func (x *CodeGeneratorResponse) GetFile() []*CodeGeneratorResponse_File {
+ if x != nil {
+ return x.File
+ }
+ return nil
+}
+
+// Represents a single generated file.
+type CodeGeneratorResponse_File struct {
+ state protoimpl.MessageState `protogen:"open.v1"`
+ // The file name, relative to the output directory. The name must not
+ // contain "." or ".." components and must be relative, not be absolute (so,
+ // the file cannot lie outside the output directory). "/" must be used as
+ // the path separator, not "\".
+ //
+ // If the name is omitted, the content will be appended to the previous
+ // file. This allows the generator to break large files into small chunks,
+ // and allows the generated text to be streamed back to protoc so that large
+ // files need not reside completely in memory at one time. Note that as of
+ // this writing protoc does not optimize for this -- it will read the entire
+ // CodeGeneratorResponse before writing files to disk.
+ Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
+ // If non-empty, indicates that the named file should already exist, and the
+ // content here is to be inserted into that file at a defined insertion
+ // point. This feature allows a code generator to extend the output
+ // produced by another code generator. The original generator may provide
+ // insertion points by placing special annotations in the file that look
+ // like:
+ //
+ // @@protoc_insertion_point(NAME)
+ //
+ // The annotation can have arbitrary text before and after it on the line,
+ // which allows it to be placed in a comment. NAME should be replaced with
+ // an identifier naming the point -- this is what other generators will use
+ // as the insertion_point. Code inserted at this point will be placed
+ // immediately above the line containing the insertion point (thus multiple
+ // insertions to the same point will come out in the order they were added).
+ // The double-@ is intended to make it unlikely that the generated code
+ // could contain things that look like insertion points by accident.
+ //
+ // For example, the C++ code generator places the following line in the
+ // .pb.h files that it generates:
+ //
+ // // @@protoc_insertion_point(namespace_scope)
+ //
+ // This line appears within the scope of the file's package namespace, but
+ // outside of any particular class. Another plugin can then specify the
+ // insertion_point "namespace_scope" to generate additional classes or
+ // other declarations that should be placed in this scope.
+ //
+ // Note that if the line containing the insertion point begins with
+ // whitespace, the same whitespace will be added to every line of the
+ // inserted text. This is useful for languages like Python, where
+ // indentation matters. In these languages, the insertion point comment
+ // should be indented the same amount as any inserted code will need to be
+ // in order to work correctly in that context.
+ //
+ // The code generator that generates the initial file and the one which
+ // inserts into it must both run as part of a single invocation of protoc.
+ // Code generators are executed in the order in which they appear on the
+ // command line.
+ //
+ // If |insertion_point| is present, |name| must also be present.
+ InsertionPoint *string `protobuf:"bytes,2,opt,name=insertion_point,json=insertionPoint" json:"insertion_point,omitempty"`
+ // The file contents.
+ Content *string `protobuf:"bytes,15,opt,name=content" json:"content,omitempty"`
+ // Information describing the file content being inserted. If an insertion
+ // point is used, this information will be appropriately offset and inserted
+ // into the code generation metadata for the generated files.
+ GeneratedCodeInfo *descriptorpb.GeneratedCodeInfo `protobuf:"bytes,16,opt,name=generated_code_info,json=generatedCodeInfo" json:"generated_code_info,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
+}
+
+func (x *CodeGeneratorResponse_File) Reset() {
+ *x = CodeGeneratorResponse_File{}
+ mi := &file_google_protobuf_compiler_plugin_proto_msgTypes[3]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *CodeGeneratorResponse_File) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CodeGeneratorResponse_File) ProtoMessage() {}
+
+func (x *CodeGeneratorResponse_File) ProtoReflect() protoreflect.Message {
+ mi := &file_google_protobuf_compiler_plugin_proto_msgTypes[3]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CodeGeneratorResponse_File.ProtoReflect.Descriptor instead.
+func (*CodeGeneratorResponse_File) Descriptor() ([]byte, []int) {
+ return file_google_protobuf_compiler_plugin_proto_rawDescGZIP(), []int{2, 0}
+}
+
+func (x *CodeGeneratorResponse_File) GetName() string {
+ if x != nil && x.Name != nil {
+ return *x.Name
+ }
+ return ""
+}
+
+func (x *CodeGeneratorResponse_File) GetInsertionPoint() string {
+ if x != nil && x.InsertionPoint != nil {
+ return *x.InsertionPoint
+ }
+ return ""
+}
+
+func (x *CodeGeneratorResponse_File) GetContent() string {
+ if x != nil && x.Content != nil {
+ return *x.Content
+ }
+ return ""
+}
+
+func (x *CodeGeneratorResponse_File) GetGeneratedCodeInfo() *descriptorpb.GeneratedCodeInfo {
+ if x != nil {
+ return x.GeneratedCodeInfo
+ }
+ return nil
+}
+
+var File_google_protobuf_compiler_plugin_proto protoreflect.FileDescriptor
+
+var file_google_protobuf_compiler_plugin_proto_rawDesc = []byte{
+ 0x0a, 0x25, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
+ 0x66, 0x2f, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69,
+ 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x18, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65,
+ 0x72, 0x1a, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
+ 0x75, 0x66, 0x2f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x22, 0x63, 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14,
+ 0x0a, 0x05, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6d,
+ 0x61, 0x6a, 0x6f, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x18, 0x02, 0x20,
+ 0x01, 0x28, 0x05, 0x52, 0x05, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x61,
+ 0x74, 0x63, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x70, 0x61, 0x74, 0x63, 0x68,
+ 0x12, 0x16, 0x0a, 0x06, 0x73, 0x75, 0x66, 0x66, 0x69, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x06, 0x73, 0x75, 0x66, 0x66, 0x69, 0x78, 0x22, 0xcf, 0x02, 0x0a, 0x14, 0x43, 0x6f, 0x64,
+ 0x65, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+ 0x74, 0x12, 0x28, 0x0a, 0x10, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x67, 0x65, 0x6e,
+ 0x65, 0x72, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x66, 0x69, 0x6c,
+ 0x65, 0x54, 0x6f, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x70,
+ 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09,
+ 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x12, 0x43, 0x0a, 0x0a, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x0f, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e,
+ 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
+ 0x46, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72,
+ 0x6f, 0x74, 0x6f, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x5c,
+ 0x0a, 0x17, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x64, 0x65,
+ 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x18, 0x11, 0x20, 0x03, 0x28, 0x0b, 0x32,
+ 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
+ 0x66, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72,
+ 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x15, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x46, 0x69, 0x6c,
+ 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x4c, 0x0a, 0x10,
+ 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
+ 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65,
+ 0x72, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0f, 0x63, 0x6f, 0x6d, 0x70, 0x69,
+ 0x6c, 0x65, 0x72, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x85, 0x04, 0x0a, 0x15, 0x43,
+ 0x6f, 0x64, 0x65, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70,
+ 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x2d, 0x0a, 0x12, 0x73, 0x75,
+ 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73,
+ 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x11, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65,
+ 0x64, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x6d, 0x69, 0x6e,
+ 0x69, 0x6d, 0x75, 0x6d, 0x5f, 0x65, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01,
+ 0x28, 0x05, 0x52, 0x0e, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x45, 0x64, 0x69, 0x74, 0x69,
+ 0x6f, 0x6e, 0x12, 0x27, 0x0a, 0x0f, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x5f, 0x65, 0x64,
+ 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x6d, 0x61, 0x78,
+ 0x69, 0x6d, 0x75, 0x6d, 0x45, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x48, 0x0a, 0x04, 0x66,
+ 0x69, 0x6c, 0x65, 0x18, 0x0f, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
+ 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x63, 0x6f, 0x6d, 0x70,
+ 0x69, 0x6c, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x64, 0x65, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74,
+ 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x52,
+ 0x04, 0x66, 0x69, 0x6c, 0x65, 0x1a, 0xb1, 0x01, 0x0a, 0x04, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x12,
+ 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61,
+ 0x6d, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x5f,
+ 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x69, 0x6e, 0x73,
+ 0x65, 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x63,
+ 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f,
+ 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x52, 0x0a, 0x13, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74,
+ 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x10, 0x20, 0x01,
+ 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x43, 0x6f,
+ 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x11, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65,
+ 0x64, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x57, 0x0a, 0x07, 0x46, 0x65, 0x61,
+ 0x74, 0x75, 0x72, 0x65, 0x12, 0x10, 0x0a, 0x0c, 0x46, 0x45, 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f,
+ 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x46, 0x45, 0x41, 0x54, 0x55, 0x52,
+ 0x45, 0x5f, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x33, 0x5f, 0x4f, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x41,
+ 0x4c, 0x10, 0x01, 0x12, 0x1d, 0x0a, 0x19, 0x46, 0x45, 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f, 0x53,
+ 0x55, 0x50, 0x50, 0x4f, 0x52, 0x54, 0x53, 0x5f, 0x45, 0x44, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x53,
+ 0x10, 0x02, 0x42, 0x72, 0x0a, 0x1c, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c,
+ 0x65, 0x72, 0x42, 0x0c, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+ 0x5a, 0x29, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2e,
+ 0x6f, 0x72, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x79, 0x70,
+ 0x65, 0x73, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x70, 0x62, 0xaa, 0x02, 0x18, 0x47, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x43, 0x6f,
+ 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72,
+}
+
+var (
+ file_google_protobuf_compiler_plugin_proto_rawDescOnce sync.Once
+ file_google_protobuf_compiler_plugin_proto_rawDescData = file_google_protobuf_compiler_plugin_proto_rawDesc
+)
+
+func file_google_protobuf_compiler_plugin_proto_rawDescGZIP() []byte {
+ file_google_protobuf_compiler_plugin_proto_rawDescOnce.Do(func() {
+ file_google_protobuf_compiler_plugin_proto_rawDescData = protoimpl.X.CompressGZIP(file_google_protobuf_compiler_plugin_proto_rawDescData)
+ })
+ return file_google_protobuf_compiler_plugin_proto_rawDescData
+}
+
+var file_google_protobuf_compiler_plugin_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
+var file_google_protobuf_compiler_plugin_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
+var file_google_protobuf_compiler_plugin_proto_goTypes = []any{
+ (CodeGeneratorResponse_Feature)(0), // 0: google.protobuf.compiler.CodeGeneratorResponse.Feature
+ (*Version)(nil), // 1: google.protobuf.compiler.Version
+ (*CodeGeneratorRequest)(nil), // 2: google.protobuf.compiler.CodeGeneratorRequest
+ (*CodeGeneratorResponse)(nil), // 3: google.protobuf.compiler.CodeGeneratorResponse
+ (*CodeGeneratorResponse_File)(nil), // 4: google.protobuf.compiler.CodeGeneratorResponse.File
+ (*descriptorpb.FileDescriptorProto)(nil), // 5: google.protobuf.FileDescriptorProto
+ (*descriptorpb.GeneratedCodeInfo)(nil), // 6: google.protobuf.GeneratedCodeInfo
+}
+var file_google_protobuf_compiler_plugin_proto_depIdxs = []int32{
+ 5, // 0: google.protobuf.compiler.CodeGeneratorRequest.proto_file:type_name -> google.protobuf.FileDescriptorProto
+ 5, // 1: google.protobuf.compiler.CodeGeneratorRequest.source_file_descriptors:type_name -> google.protobuf.FileDescriptorProto
+ 1, // 2: google.protobuf.compiler.CodeGeneratorRequest.compiler_version:type_name -> google.protobuf.compiler.Version
+ 4, // 3: google.protobuf.compiler.CodeGeneratorResponse.file:type_name -> google.protobuf.compiler.CodeGeneratorResponse.File
+ 6, // 4: google.protobuf.compiler.CodeGeneratorResponse.File.generated_code_info:type_name -> google.protobuf.GeneratedCodeInfo
+ 5, // [5:5] is the sub-list for method output_type
+ 5, // [5:5] is the sub-list for method input_type
+ 5, // [5:5] is the sub-list for extension type_name
+ 5, // [5:5] is the sub-list for extension extendee
+ 0, // [0:5] is the sub-list for field type_name
+}
+
+func init() { file_google_protobuf_compiler_plugin_proto_init() }
+func file_google_protobuf_compiler_plugin_proto_init() {
+ if File_google_protobuf_compiler_plugin_proto != nil {
+ return
+ }
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_google_protobuf_compiler_plugin_proto_rawDesc,
+ NumEnums: 1,
+ NumMessages: 4,
+ NumExtensions: 0,
+ NumServices: 0,
+ },
+ GoTypes: file_google_protobuf_compiler_plugin_proto_goTypes,
+ DependencyIndexes: file_google_protobuf_compiler_plugin_proto_depIdxs,
+ EnumInfos: file_google_protobuf_compiler_plugin_proto_enumTypes,
+ MessageInfos: file_google_protobuf_compiler_plugin_proto_msgTypes,
+ }.Build()
+ File_google_protobuf_compiler_plugin_proto = out.File
+ file_google_protobuf_compiler_plugin_proto_rawDesc = nil
+ file_google_protobuf_compiler_plugin_proto_goTypes = nil
+ file_google_protobuf_compiler_plugin_proto_depIdxs = nil
+}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 1580492beeb..b128faf4806 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -37,6 +37,9 @@ cloud.google.com/go/storage
cloud.google.com/go/storage/internal
cloud.google.com/go/storage/internal/apiv2
cloud.google.com/go/storage/internal/apiv2/storagepb
+# dario.cat/mergo v1.0.1
+## explicit; go 1.13
+dario.cat/mergo
# github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0
## explicit; go 1.18
github.com/Azure/azure-sdk-for-go/sdk/azcore
@@ -110,6 +113,9 @@ 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/CrowdStrike/csproto v0.33.0
+## explicit; go 1.21
+github.com/CrowdStrike/csproto
# github.com/DmitriyVTitov/size v1.5.0
## explicit; go 1.14
github.com/DmitriyVTitov/size
@@ -118,11 +124,11 @@ github.com/DmitriyVTitov/size
# github.com/Masterminds/goutils v1.1.1
## explicit
github.com/Masterminds/goutils
-# github.com/Masterminds/semver/v3 v3.1.1
-## explicit; go 1.12
+# github.com/Masterminds/semver/v3 v3.3.0
+## explicit; go 1.21
github.com/Masterminds/semver/v3
-# github.com/Masterminds/sprig/v3 v3.2.1
-## explicit; go 1.13
+# github.com/Masterminds/sprig/v3 v3.3.0
+## explicit; go 1.21
github.com/Masterminds/sprig/v3
# github.com/alecthomas/chroma/v2 v2.15.0
## explicit; go 1.19
@@ -498,10 +504,33 @@ github.com/gogo/googleapis/google/rpc
## explicit; go 1.15
github.com/gogo/protobuf/gogoproto
github.com/gogo/protobuf/jsonpb
+github.com/gogo/protobuf/plugin/compare
+github.com/gogo/protobuf/plugin/defaultcheck
+github.com/gogo/protobuf/plugin/description
+github.com/gogo/protobuf/plugin/embedcheck
+github.com/gogo/protobuf/plugin/enumstringer
+github.com/gogo/protobuf/plugin/equal
+github.com/gogo/protobuf/plugin/face
+github.com/gogo/protobuf/plugin/gostring
+github.com/gogo/protobuf/plugin/marshalto
+github.com/gogo/protobuf/plugin/oneofcheck
+github.com/gogo/protobuf/plugin/populate
+github.com/gogo/protobuf/plugin/size
+github.com/gogo/protobuf/plugin/stringer
+github.com/gogo/protobuf/plugin/testgen
+github.com/gogo/protobuf/plugin/union
+github.com/gogo/protobuf/plugin/unmarshal
github.com/gogo/protobuf/proto
+github.com/gogo/protobuf/protoc-gen-gogo
github.com/gogo/protobuf/protoc-gen-gogo/descriptor
+github.com/gogo/protobuf/protoc-gen-gogo/generator
+github.com/gogo/protobuf/protoc-gen-gogo/generator/internal/remap
+github.com/gogo/protobuf/protoc-gen-gogo/grpc
+github.com/gogo/protobuf/protoc-gen-gogo/plugin
github.com/gogo/protobuf/sortkeys
github.com/gogo/protobuf/types
+github.com/gogo/protobuf/vanity
+github.com/gogo/protobuf/vanity/command
# github.com/gogo/status v1.1.1
## explicit; go 1.12
github.com/gogo/status
@@ -519,6 +548,7 @@ github.com/golang/groupcache/lru
github.com/golang/groupcache/singleflight
# github.com/golang/protobuf v1.5.4
## explicit; go 1.17
+github.com/golang/protobuf/jsonpb
github.com/golang/protobuf/proto
github.com/golang/protobuf/ptypes
github.com/golang/protobuf/ptypes/any
@@ -642,7 +672,7 @@ github.com/grafana/alerting/receivers/webex
github.com/grafana/alerting/receivers/webhook
github.com/grafana/alerting/receivers/wecom
github.com/grafana/alerting/templates
-# github.com/grafana/dskit v0.0.0-20250106205746-3702098cbd0c
+# github.com/grafana/dskit v0.0.0-20250106220817-6eb1cce03889
## explicit; go 1.21
github.com/grafana/dskit/backoff
github.com/grafana/dskit/ballast
@@ -782,12 +812,9 @@ github.com/hashicorp/vault/api/auth/kubernetes
# github.com/hashicorp/vault/api/auth/userpass v0.8.0
## explicit; go 1.21
github.com/hashicorp/vault/api/auth/userpass
-# github.com/huandu/xstrings v1.3.2
+# github.com/huandu/xstrings v1.5.0
## explicit; go 1.12
github.com/huandu/xstrings
-# github.com/imdario/mergo v0.3.16
-## explicit; go 1.13
-github.com/imdario/mergo
# github.com/inconshreveable/mousetrap v1.1.0
## explicit; go 1.18
github.com/inconshreveable/mousetrap
@@ -876,8 +903,8 @@ github.com/minio/minio-go/v7/pkg/tags
# github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db
## explicit
github.com/mitchellh/colorstring
-# github.com/mitchellh/copystructure v1.0.0
-## explicit
+# github.com/mitchellh/copystructure v1.2.0
+## explicit; go 1.15
github.com/mitchellh/copystructure
# github.com/mitchellh/go-homedir v1.1.0
## explicit
@@ -888,7 +915,7 @@ github.com/mitchellh/go-wordwrap
# github.com/mitchellh/mapstructure v1.5.0
## explicit; go 1.14
github.com/mitchellh/mapstructure
-# github.com/mitchellh/reflectwalk v1.0.0
+# github.com/mitchellh/reflectwalk v1.0.2
## explicit
github.com/mitchellh/reflectwalk
# github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd
@@ -1133,8 +1160,8 @@ github.com/shirou/gopsutil/v4/internal/common
github.com/shirou/gopsutil/v4/mem
github.com/shirou/gopsutil/v4/net
github.com/shirou/gopsutil/v4/process
-# github.com/shopspring/decimal v1.2.0
-## explicit; go 1.13
+# github.com/shopspring/decimal v1.4.0
+## explicit; go 1.10
github.com/shopspring/decimal
# github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c
## explicit; go 1.19
@@ -1152,8 +1179,8 @@ github.com/sirupsen/logrus
github.com/spf13/afero
github.com/spf13/afero/internal/common
github.com/spf13/afero/mem
-# github.com/spf13/cast v1.5.0
-## explicit; go 1.18
+# github.com/spf13/cast v1.7.0
+## explicit; go 1.19
github.com/spf13/cast
# github.com/spf13/cobra v1.8.0
## explicit; go 1.15
@@ -1588,6 +1615,9 @@ google.golang.org/grpc/tap
google.golang.org/grpc/test/bufconn
# google.golang.org/protobuf v1.36.1
## explicit; go 1.21
+google.golang.org/protobuf/cmd/protoc-gen-go
+google.golang.org/protobuf/cmd/protoc-gen-go/internal_gengo
+google.golang.org/protobuf/compiler/protogen
google.golang.org/protobuf/encoding/protodelim
google.golang.org/protobuf/encoding/protojson
google.golang.org/protobuf/encoding/prototext
@@ -1608,6 +1638,7 @@ google.golang.org/protobuf/internal/filetype
google.golang.org/protobuf/internal/flags
google.golang.org/protobuf/internal/genid
google.golang.org/protobuf/internal/impl
+google.golang.org/protobuf/internal/msgfmt
google.golang.org/protobuf/internal/order
google.golang.org/protobuf/internal/pragma
google.golang.org/protobuf/internal/protolazy
@@ -1617,17 +1648,21 @@ google.golang.org/protobuf/internal/version
google.golang.org/protobuf/proto
google.golang.org/protobuf/protoadapt
google.golang.org/protobuf/reflect/protodesc
+google.golang.org/protobuf/reflect/protopath
+google.golang.org/protobuf/reflect/protorange
google.golang.org/protobuf/reflect/protoreflect
google.golang.org/protobuf/reflect/protoregistry
google.golang.org/protobuf/runtime/protoiface
google.golang.org/protobuf/runtime/protoimpl
google.golang.org/protobuf/types/descriptorpb
+google.golang.org/protobuf/types/dynamicpb
google.golang.org/protobuf/types/gofeaturespb
google.golang.org/protobuf/types/known/anypb
google.golang.org/protobuf/types/known/durationpb
google.golang.org/protobuf/types/known/emptypb
google.golang.org/protobuf/types/known/fieldmaskpb
google.golang.org/protobuf/types/known/timestamppb
+google.golang.org/protobuf/types/pluginpb
# gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc
## explicit
gopkg.in/alexcesaro/quotedprintable.v3