build: upgrade dependencies

This commit is contained in:
Cyrille Nofficial 2021-09-01 19:40:58 +02:00
parent d82292f755
commit 6cf77035fe
113 changed files with 10521 additions and 1863 deletions

10
go.mod
View File

@ -3,11 +3,10 @@ module github.com/cyrilix/robocar-base
go 1.17 go 1.17
require ( require (
github.com/eclipse/paho.mqtt.golang v1.3.1 github.com/eclipse/paho.mqtt.golang v1.3.5
github.com/golang/protobuf v1.4.3 github.com/golang/protobuf v1.5.2
github.com/sirupsen/logrus v1.7.0 github.com/sirupsen/logrus v1.8.1
github.com/testcontainers/testcontainers-go v0.9.0 github.com/testcontainers/testcontainers-go v0.9.0
golang.org/x/net v0.0.0-20200904194848-62affa334b73 // indirect
) )
require ( require (
@ -27,10 +26,11 @@ require (
github.com/opencontainers/image-spec v1.0.1 // indirect github.com/opencontainers/image-spec v1.0.1 // indirect
github.com/opencontainers/runc v0.1.1 // indirect github.com/opencontainers/runc v0.1.1 // indirect
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0 // indirect
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f // indirect golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f // indirect
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd // indirect golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd // indirect
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 // indirect google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 // indirect
google.golang.org/grpc v1.17.0 // indirect google.golang.org/grpc v1.17.0 // indirect
google.golang.org/protobuf v1.23.0 // indirect google.golang.org/protobuf v1.26.0 // indirect
gopkg.in/yaml.v2 v2.3.0 // indirect gopkg.in/yaml.v2 v2.3.0 // indirect
) )

40
go.sum
View File

@ -23,8 +23,8 @@ github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKoh
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-units v0.3.3 h1:Xk8S3Xj5sLGlG5g67hJmYMmUgXv5N4PhkjJHHqrwnTk= github.com/docker/go-units v0.3.3 h1:Xk8S3Xj5sLGlG5g67hJmYMmUgXv5N4PhkjJHHqrwnTk=
github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/eclipse/paho.mqtt.golang v1.3.1 h1:6F5FYb1hxVSZS+p0ji5xBQamc5ltOolTYRy5R15uVmI= github.com/eclipse/paho.mqtt.golang v1.3.5 h1:sWtmgNxYM9P2sP+xEItMozsR3w0cqZFlqnNN1bdl41Y=
github.com/eclipse/paho.mqtt.golang v1.3.1/go.mod h1:eTzb4gxwwyWpqBUHGQZ4ABAV7+Jgm1PklsYT/eo8Hcc= github.com/eclipse/paho.mqtt.golang v1.3.5/go.mod h1:eTzb4gxwwyWpqBUHGQZ4ABAV7+Jgm1PklsYT/eo8Hcc=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
@ -42,18 +42,12 @@ github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfU
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@ -93,8 +87,8 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@ -109,14 +103,11 @@ github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVM
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0 h1:Jcxah/M+oLZ/R4/z5RzfPzGbPXnVDPkEDtf2JnuxN+U=
golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200904194848-62affa334b73 h1:MXfv8rhZWmFeqX3GNZRsd6vOLoaCHjYEX3qkRo3YBUA=
golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -124,7 +115,6 @@ golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
@ -143,13 +133,9 @@ google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/grpc v1.17.0 h1:TRJYBgMclJvGYn2rIMjj+h9KtMt5r1Ij7ODVRIZkwhk= google.golang.org/grpc v1.17.0 h1:TRJYBgMclJvGYn2rIMjj+h9KtMt5r1Ij7ODVRIZkwhk=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

View File

@ -104,8 +104,12 @@ func main() {
* Seemingly random disconnections may be caused by another client connecting to the broker with the same client * Seemingly random disconnections may be caused by another client connecting to the broker with the same client
identifier; this is as per the [spec](https://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc384800405). identifier; this is as per the [spec](https://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc384800405).
* A `MessageHandler` (called when a new message is received) must not block. If you wish to perform a long-running task, * Unless ordered delivery of messages is essential (and you have configured your broker to support this e.g.
or publish a message, then please use a go routine (blocking in the handler is a common cause of unexpected `pingresp `max_inflight_messages=1` in mosquitto) then set `ClientOptions.SetOrderMatters(false)`. Doing so will avoid the
below issue (deadlocks due to blocking message handlers).
* A `MessageHandler` (called when a new message is received) must not block (unless
`ClientOptions.SetOrderMatters(false)` set). If you wish to perform a long-running task, or publish a message, then
please use a go routine (blocking in the handler is a common cause of unexpected `pingresp
not received, disconnecting` errors). not received, disconnecting` errors).
* When QOS1+ subscriptions have been created previously and you connect with `CleanSession` set to false it is possible that the broker will deliver retained * When QOS1+ subscriptions have been created previously and you connect with `CleanSession` set to false it is possible that the broker will deliver retained
messages before `Subscribe` can be called. To process these messages either configure a handler with `AddRoute` or messages before `Subscribe` can be called. To process these messages either configure a handler with `AddRoute` or

View File

@ -55,6 +55,8 @@ const (
// information can be found in their respective documentation. // information can be found in their respective documentation.
// Numerous connection options may be specified by configuring a // Numerous connection options may be specified by configuring a
// and then supplying a ClientOptions type. // and then supplying a ClientOptions type.
// Implementations of Client must be safe for concurrent use by multiple
// goroutines
type Client interface { type Client interface {
// IsConnected returns a bool signifying whether // IsConnected returns a bool signifying whether
// the client is connected or not. // the client is connected or not.
@ -75,11 +77,21 @@ type Client interface {
// Returns a token to track delivery of the message to the broker // Returns a token to track delivery of the message to the broker
Publish(topic string, qos byte, retained bool, payload interface{}) Token Publish(topic string, qos byte, retained bool, payload interface{}) Token
// Subscribe starts a new subscription. Provide a MessageHandler to be executed when // Subscribe starts a new subscription. Provide a MessageHandler to be executed when
// a message is published on the topic provided, or nil for the default handler // a message is published on the topic provided, or nil for the default handler.
//
// If options.OrderMatters is true (the default) then callback must not block or
// call functions within this package that may block (e.g. Publish) other than in
// a new go routine.
// callback must be safe for concurrent use by multiple goroutines.
Subscribe(topic string, qos byte, callback MessageHandler) Token Subscribe(topic string, qos byte, callback MessageHandler) Token
// SubscribeMultiple starts a new subscription for multiple topics. Provide a MessageHandler to // SubscribeMultiple starts a new subscription for multiple topics. Provide a MessageHandler to
// be executed when a message is published on one of the topics provided, or nil for the // be executed when a message is published on one of the topics provided, or nil for the
// default handler // default handler.
//
// If options.OrderMatters is true (the default) then callback must not block or
// call functions within this package that may block (e.g. Publish) other than in
// a new go routine.
// callback must be safe for concurrent use by multiple goroutines.
SubscribeMultiple(filters map[string]byte, callback MessageHandler) Token SubscribeMultiple(filters map[string]byte, callback MessageHandler) Token
// Unsubscribe will end the subscription from each of the topics provided. // Unsubscribe will end the subscription from each of the topics provided.
// Messages published to those topics from other clients will no longer be // Messages published to those topics from other clients will no longer be
@ -87,7 +99,13 @@ type Client interface {
Unsubscribe(topics ...string) Token Unsubscribe(topics ...string) Token
// AddRoute allows you to add a handler for messages on a specific topic // AddRoute allows you to add a handler for messages on a specific topic
// without making a subscription. For example having a different handler // without making a subscription. For example having a different handler
// for parts of a wildcard subscription // for parts of a wildcard subscription or for receiving retained messages
// upon connection (before Sub scribe can be processed).
//
// If options.OrderMatters is true (the default) then callback must not block or
// call functions within this package that may block (e.g. Publish) other than in
// a new go routine.
// callback must be safe for concurrent use by multiple goroutines.
AddRoute(topic string, callback MessageHandler) AddRoute(topic string, callback MessageHandler)
// OptionsReader returns a ClientOptionsReader which is a copy of the clientoptions // OptionsReader returns a ClientOptionsReader which is a copy of the clientoptions
// in use by the client. // in use by the client.
@ -95,6 +113,8 @@ type Client interface {
} }
// client implements the Client interface // client implements the Client interface
// clients are safe for concurrent use by multiple
// goroutines
type client struct { type client struct {
lastSent atomic.Value // time.Time - the last time a packet was successfully sent to network lastSent atomic.Value // time.Time - the last time a packet was successfully sent to network
lastReceived atomic.Value // time.Time - the last time a packet was successfully received from network lastReceived atomic.Value // time.Time - the last time a packet was successfully received from network
@ -153,6 +173,11 @@ func NewClient(o *ClientOptions) Client {
// AddRoute allows you to add a handler for messages on a specific topic // AddRoute allows you to add a handler for messages on a specific topic
// without making a subscription. For example having a different handler // without making a subscription. For example having a different handler
// for parts of a wildcard subscription // for parts of a wildcard subscription
//
// If options.OrderMatters is true (the default) then callback must not block or
// call functions within this package that may block (e.g. Publish) other than in
// a new go routine.
// callback must be safe for concurrent use by multiple goroutines.
func (c *client) AddRoute(topic string, callback MessageHandler) { func (c *client) AddRoute(topic string, callback MessageHandler) {
if callback != nil { if callback != nil {
c.msgRouter.addRoute(topic, callback) c.msgRouter.addRoute(topic, callback)
@ -354,8 +379,13 @@ func (c *client) attemptConnection() (net.Conn, byte, bool, error) {
cm := newConnectMsgFromOptions(&c.options, broker) cm := newConnectMsgFromOptions(&c.options, broker)
DEBUG.Println(CLI, "about to write new connect msg") DEBUG.Println(CLI, "about to write new connect msg")
CONN: CONN:
tlsCfg := c.options.TLSConfig
if c.options.OnConnectAttempt != nil {
DEBUG.Println(CLI, "using custom onConnectAttempt handler...")
tlsCfg = c.options.OnConnectAttempt(broker, c.options.TLSConfig)
}
// Start by opening the network connection (tcp, tls, ws) etc // Start by opening the network connection (tcp, tls, ws) etc
conn, err = openConnection(broker, c.options.TLSConfig, c.options.ConnectTimeout, c.options.HTTPHeaders, c.options.WebsocketOptions) conn, err = openConnection(broker, tlsCfg, c.options.ConnectTimeout, c.options.HTTPHeaders, c.options.WebsocketOptions)
if err != nil { if err != nil {
ERROR.Println(CLI, err.Error()) ERROR.Println(CLI, err.Error())
WARN.Println(CLI, "failed to connect to broker, trying next") WARN.Println(CLI, "failed to connect to broker, trying next")
@ -372,7 +402,7 @@ func (c *client) attemptConnection() (net.Conn, byte, bool, error) {
// We may be have to attempt the connection with MQTT 3.1 // We may be have to attempt the connection with MQTT 3.1
if conn != nil { if conn != nil {
conn.Close() _ = conn.Close()
} }
if !c.options.protocolVersionExplicit && protocolVersion == 4 { // try falling back to 3.1? if !c.options.protocolVersionExplicit && protocolVersion == 4 { // try falling back to 3.1?
DEBUG.Println(CLI, "Trying reconnect using MQTT 3.1 protocol") DEBUG.Println(CLI, "Trying reconnect using MQTT 3.1 protocol")
@ -409,12 +439,22 @@ func (c *client) Disconnect(quiesce uint) {
dm := packets.NewControlPacket(packets.Disconnect).(*packets.DisconnectPacket) dm := packets.NewControlPacket(packets.Disconnect).(*packets.DisconnectPacket)
dt := newToken(packets.Disconnect) dt := newToken(packets.Disconnect)
c.oboundP <- &PacketAndToken{p: dm, t: dt} disconnectSent := false
select {
case c.oboundP <- &PacketAndToken{p: dm, t: dt}:
disconnectSent = true
case <-c.commsStopped:
WARN.Println("Disconnect packet could not be sent because comms stopped")
case <-time.After(time.Duration(quiesce) * time.Millisecond):
WARN.Println("Disconnect packet not sent due to timeout")
}
// wait for work to finish, or quiesce time consumed // wait for work to finish, or quiesce time consumed
DEBUG.Println(CLI, "calling WaitTimeout") if disconnectSent {
dt.WaitTimeout(time.Duration(quiesce) * time.Millisecond) DEBUG.Println(CLI, "calling WaitTimeout")
DEBUG.Println(CLI, "WaitTimeout done") dt.WaitTimeout(time.Duration(quiesce) * time.Millisecond)
DEBUG.Println(CLI, "WaitTimeout done")
}
} else { } else {
WARN.Println(CLI, "Disconnect() called but not connected (disconnected/reconnecting)") WARN.Println(CLI, "Disconnect() called but not connected (disconnected/reconnecting)")
c.setConnected(disconnected) c.setConnected(disconnected)
@ -459,10 +499,13 @@ func (c *client) internalConnLost(err error) {
DEBUG.Println(CLI, "internalConnLost waiting on workers") DEBUG.Println(CLI, "internalConnLost waiting on workers")
<-stopDone <-stopDone
DEBUG.Println(CLI, "internalConnLost workers stopped") DEBUG.Println(CLI, "internalConnLost workers stopped")
if c.options.CleanSession && !c.options.AutoReconnect { // It is possible that Disconnect was called which led to this error so reconnection depends upon status
reconnect := c.options.AutoReconnect && c.connectionStatus() > connecting
if c.options.CleanSession && !reconnect {
c.messageIds.cleanUp() c.messageIds.cleanUp()
} }
if c.options.AutoReconnect { if reconnect {
c.setConnected(reconnecting) c.setConnected(reconnecting)
go c.reconnect() go c.reconnect()
} else { } else {
@ -476,8 +519,8 @@ func (c *client) internalConnLost(err error) {
} }
} }
// startCommsWorkers is called when the connection is up. It starts off all of the routines needed to process incoming and // startCommsWorkers is called when the connection is up.
// outgoing messages. // It starts off all of the routines needed to process incoming and outgoing messages.
// Returns true if the comms workers were started (i.e. they were not already running) // Returns true if the comms workers were started (i.e. they were not already running)
func (c *client) startCommsWorkers(conn net.Conn, inboundFromStore <-chan packets.ControlPacket) bool { func (c *client) startCommsWorkers(conn net.Conn, inboundFromStore <-chan packets.ControlPacket) bool {
DEBUG.Println(CLI, "startCommsWorkers called") DEBUG.Println(CLI, "startCommsWorkers called")
@ -564,7 +607,22 @@ func (c *client) startCommsWorkers(conn net.Conn, inboundFromStore <-chan packet
commsIncomingPub = nil commsIncomingPub = nil
continue continue
} }
incomingPubChan <- pub // Care is needed here because an error elsewhere could trigger a deadlock
sendPubLoop:
for {
select {
case incomingPubChan <- pub:
break sendPubLoop
case err, ok := <-commsErrors:
if !ok { // commsErrors has been closed so we can ignore it
commsErrors = nil
continue
}
ERROR.Println(CLI, "Connect comms goroutine - error triggered during send Pub", err)
c.internalConnLost(err) // no harm in calling this if the connection is already down (or shutdown is in progress)
continue
}
}
case err, ok := <-commsErrors: case err, ok := <-commsErrors:
if !ok { if !ok {
commsErrors = nil commsErrors = nil
@ -686,10 +744,10 @@ func (c *client) Publish(topic string, qos byte, retained bool, payload interfac
// Subscribe starts a new subscription. Provide a MessageHandler to be executed when // Subscribe starts a new subscription. Provide a MessageHandler to be executed when
// a message is published on the topic provided. // a message is published on the topic provided.
// //
// Please note: you should try to keep the execution time of the callback to be // If options.OrderMatters is true (the default) then callback must not block or
// as low as possible, especially when SetOrderMatters(true) (the default) is in // call functions within this package that may block (e.g. Publish) other than in
// place. Blocking calls in message handlers might otherwise delay delivery to // a new go routine.
// other message handlers. // callback must be safe for concurrent use by multiple goroutines.
func (c *client) Subscribe(topic string, qos byte, callback MessageHandler) Token { func (c *client) Subscribe(topic string, qos byte, callback MessageHandler) Token {
token := newToken(packets.Subscribe).(*SubscribeToken) token := newToken(packets.Subscribe).(*SubscribeToken)
DEBUG.Println(CLI, "enter Subscribe") DEBUG.Println(CLI, "enter Subscribe")
@ -766,6 +824,11 @@ func (c *client) Subscribe(topic string, qos byte, callback MessageHandler) Toke
// SubscribeMultiple starts a new subscription for multiple topics. Provide a MessageHandler to // SubscribeMultiple starts a new subscription for multiple topics. Provide a MessageHandler to
// be executed when a message is published on one of the topics provided. // be executed when a message is published on one of the topics provided.
//
// If options.OrderMatters is true (the default) then callback must not block or
// call functions within this package that may block (e.g. Publish) other than in
// a new go routine.
// callback must be safe for concurrent use by multiple goroutines.
func (c *client) SubscribeMultiple(filters map[string]byte, callback MessageHandler) Token { func (c *client) SubscribeMultiple(filters map[string]byte, callback MessageHandler) Token {
var err error var err error
token := newToken(packets.Subscribe).(*SubscribeToken) token := newToken(packets.Subscribe).(*SubscribeToken)
@ -869,7 +932,7 @@ func (c *client) resume(subscription bool, ibound chan packets.ControlPacket) {
} }
details := packet.Details() details := packet.Details()
if isKeyOutbound(key) { if isKeyOutbound(key) {
switch packet.(type) { switch p := packet.(type) {
case *packets.SubscribePacket: case *packets.SubscribePacket:
if subscription { if subscription {
DEBUG.Println(STR, fmt.Sprintf("loaded pending subscribe (%d)", details.MessageID)) DEBUG.Println(STR, fmt.Sprintf("loaded pending subscribe (%d)", details.MessageID))
@ -909,13 +972,22 @@ func (c *client) resume(subscription bool, ibound chan packets.ControlPacket) {
return return
} }
case *packets.PublishPacket: case *packets.PublishPacket:
// spec: If the DUP flag is set to 0, it indicates that this is the first occasion that the Client or
// Server has attempted to send this MQTT PUBLISH Packet. If the DUP flag is set to 1, it indicates that
// this might be re-delivery of an earlier attempt to send the Packet.
//
// If the message is in the store than an attempt at delivery has been made (note that the message may
// never have made it onto the wire but tracking that would be complicated!).
if p.Qos != 0 { // spec: The DUP flag MUST be set to 0 for all QoS 0 messages
p.Dup = true
}
token := newToken(packets.Publish).(*PublishToken) token := newToken(packets.Publish).(*PublishToken)
token.messageID = details.MessageID token.messageID = details.MessageID
c.claimID(token, details.MessageID) c.claimID(token, details.MessageID)
DEBUG.Println(STR, fmt.Sprintf("loaded pending publish (%d)", details.MessageID)) DEBUG.Println(STR, fmt.Sprintf("loaded pending publish (%d)", details.MessageID))
DEBUG.Println(STR, details) DEBUG.Println(STR, details)
select { select {
case c.obound <- &PacketAndToken{p: packet, t: token}: case c.obound <- &PacketAndToken{p: p, t: token}:
case <-c.stop: case <-c.stop:
DEBUG.Println(STR, "resume exiting due to stop") DEBUG.Println(STR, "resume exiting due to stop")
return return

View File

@ -30,7 +30,8 @@ import (
// This just establishes the network connection; once established the type of connection should be irrelevant // This just establishes the network connection; once established the type of connection should be irrelevant
// //
// openConnection opens a network connection using the protocol indicated in the URL. Does not carry out any MQTT specific handshakes // openConnection opens a network connection using the protocol indicated in the URL.
// Does not carry out any MQTT specific handshakes.
func openConnection(uri *url.URL, tlsc *tls.Config, timeout time.Duration, headers http.Header, websocketOptions *WebsocketOptions) (net.Conn, error) { func openConnection(uri *url.URL, tlsc *tls.Config, timeout time.Duration, headers http.Header, websocketOptions *WebsocketOptions) (net.Conn, error) {
switch uri.Scheme { switch uri.Scheme {
case "ws": case "ws":
@ -81,7 +82,7 @@ func openConnection(uri *url.URL, tlsc *tls.Config, timeout time.Duration, heade
err = tlsConn.Handshake() err = tlsConn.Handshake()
if err != nil { if err != nil {
conn.Close() _ = conn.Close()
return nil, err return nil, err
} }

View File

@ -21,7 +21,6 @@ import (
"crypto/tls" "crypto/tls"
"net/http" "net/http"
"net/url" "net/url"
"regexp"
"strings" "strings"
"time" "time"
) )
@ -50,7 +49,11 @@ type OnConnectHandler func(Client)
// the initial connection is lost // the initial connection is lost
type ReconnectHandler func(Client, *ClientOptions) type ReconnectHandler func(Client, *ClientOptions)
// ClientOptions contains configurable options for an Client. // ConnectionAttemptHandler is invoked prior to making the initial connection.
type ConnectionAttemptHandler func(broker *url.URL, tlsCfg *tls.Config) *tls.Config
// ClientOptions contains configurable options for an Client. Note that these should be set using the
// relevant methods (e.g. AddBroker) rather than directly. See those functions for information on usage.
type ClientOptions struct { type ClientOptions struct {
Servers []*url.URL Servers []*url.URL
ClientID string ClientID string
@ -79,6 +82,7 @@ type ClientOptions struct {
OnConnect OnConnectHandler OnConnect OnConnectHandler
OnConnectionLost ConnectionLostHandler OnConnectionLost ConnectionLostHandler
OnReconnecting ReconnectHandler OnReconnecting ReconnectHandler
OnConnectAttempt ConnectionAttemptHandler
WriteTimeout time.Duration WriteTimeout time.Duration
MessageChannelDepth uint MessageChannelDepth uint
ResumeSubs bool ResumeSubs bool
@ -90,7 +94,7 @@ type ClientOptions struct {
// default values. // default values.
// Port: 1883 // Port: 1883
// CleanSession: True // CleanSession: True
// Order: True // Order: True (note: it is recommended that this be set to FALSE unless order is important)
// KeepAlive: 30 (seconds) // KeepAlive: 30 (seconds)
// ConnectTimeout: 30 (seconds) // ConnectTimeout: 30 (seconds)
// MaxReconnectInterval 10 (minutes) // MaxReconnectInterval 10 (minutes)
@ -120,6 +124,7 @@ func NewClientOptions() *ClientOptions {
Store: nil, Store: nil,
OnConnect: nil, OnConnect: nil,
OnConnectionLost: DefaultConnectionLostHandler, OnConnectionLost: DefaultConnectionLostHandler,
OnConnectAttempt: nil,
WriteTimeout: 0, // 0 represents timeout disabled WriteTimeout: 0, // 0 represents timeout disabled
ResumeSubs: false, ResumeSubs: false,
HTTPHeaders: make(map[string][]string), HTTPHeaders: make(map[string][]string),
@ -137,14 +142,12 @@ func NewClientOptions() *ClientOptions {
// //
// An example broker URI would look like: tcp://foobar.com:1883 // An example broker URI would look like: tcp://foobar.com:1883
func (o *ClientOptions) AddBroker(server string) *ClientOptions { func (o *ClientOptions) AddBroker(server string) *ClientOptions {
re := regexp.MustCompile(`%(25)?`)
if len(server) > 0 && server[0] == ':' { if len(server) > 0 && server[0] == ':' {
server = "127.0.0.1" + server server = "127.0.0.1" + server
} }
if !strings.Contains(server, "://") { if !strings.Contains(server, "://") {
server = "tcp://" + server server = "tcp://" + server
} }
server = re.ReplaceAllLiteralString(server, "%25")
brokerURI, err := url.Parse(server) brokerURI, err := url.Parse(server)
if err != nil { if err != nil {
ERROR.Println(CLI, "Failed to parse %q broker address: %s", server, err) ERROR.Println(CLI, "Failed to parse %q broker address: %s", server, err)
@ -206,10 +209,13 @@ func (o *ClientOptions) SetCleanSession(clean bool) *ClientOptions {
} }
// SetOrderMatters will set the message routing to guarantee order within // SetOrderMatters will set the message routing to guarantee order within
// each QoS level. By default, this value is true. If set to false, // each QoS level. By default, this value is true. If set to false (recommended),
// this flag indicates that messages can be delivered asynchronously // this flag indicates that messages can be delivered asynchronously
// from the client to the application and possibly arrive out of order. // from the client to the application and possibly arrive out of order.
// Specifically, the message handler is called in its own go routine. // Specifically, the message handler is called in its own go routine.
// Note that setting this to true does not guarantee in-order delivery
// (this is subject to broker settings like "max_inflight_messages=1" in mosquitto)
// and if true then handlers must not block.
func (o *ClientOptions) SetOrderMatters(order bool) *ClientOptions { func (o *ClientOptions) SetOrderMatters(order bool) *ClientOptions {
o.Order = order o.Order = order
return o return o
@ -289,6 +295,11 @@ func (o *ClientOptions) SetBinaryWill(topic string, payload []byte, qos byte, re
// SetDefaultPublishHandler sets the MessageHandler that will be called when a message // SetDefaultPublishHandler sets the MessageHandler that will be called when a message
// is received that does not match any known subscriptions. // is received that does not match any known subscriptions.
//
// If OrderMatters is true (the defaultHandler) then callback must not block or
// call functions within this package that may block (e.g. Publish) other than in
// a new go routine.
// defaultHandler must be safe for concurrent use by multiple goroutines.
func (o *ClientOptions) SetDefaultPublishHandler(defaultHandler MessageHandler) *ClientOptions { func (o *ClientOptions) SetDefaultPublishHandler(defaultHandler MessageHandler) *ClientOptions {
o.DefaultPublishHandler = defaultHandler o.DefaultPublishHandler = defaultHandler
return o return o
@ -315,6 +326,15 @@ func (o *ClientOptions) SetReconnectingHandler(cb ReconnectHandler) *ClientOptio
return o return o
} }
// SetConnectionAttemptHandler sets the ConnectionAttemptHandler callback to be executed prior
// to each attempt to connect to an MQTT broker. Returns the *tls.Config that will be used when establishing
// the connection (a copy of the tls.Config from ClientOptions will be passed in along with the broker URL).
// This allows connection specific changes to be made to the *tls.Config.
func (o *ClientOptions) SetConnectionAttemptHandler(onConnectAttempt ConnectionAttemptHandler) *ClientOptions {
o.OnConnectAttempt = onConnectAttempt
return o
}
// SetWriteTimeout puts a limit on how long a mqtt publish should block until it unblocks with a // SetWriteTimeout puts a limit on how long a mqtt publish should block until it unblocks with a
// timeout error. A duration of 0 never times out. Default never times out // timeout error. A duration of 0 never times out. Default never times out
func (o *ClientOptions) SetWriteTimeout(t time.Duration) *ClientOptions { func (o *ClientOptions) SetWriteTimeout(t time.Duration) *ClientOptions {

View File

@ -29,7 +29,11 @@ type ConnectPacket struct {
} }
func (c *ConnectPacket) String() string { func (c *ConnectPacket) String() string {
return fmt.Sprintf("%s protocolversion: %d protocolname: %s cleansession: %t willflag: %t WillQos: %d WillRetain: %t Usernameflag: %t Passwordflag: %t keepalive: %d clientId: %s willtopic: %s willmessage: %s Username: %s Password: %s", c.FixedHeader, c.ProtocolVersion, c.ProtocolName, c.CleanSession, c.WillFlag, c.WillQos, c.WillRetain, c.UsernameFlag, c.PasswordFlag, c.Keepalive, c.ClientIdentifier, c.WillTopic, c.WillMessage, c.Username, c.Password) var password string
if len(c.Password) > 0 {
password = "<redacted>"
}
return fmt.Sprintf("%s protocolversion: %d protocolname: %s cleansession: %t willflag: %t WillQos: %d WillRetain: %t Usernameflag: %t Passwordflag: %t keepalive: %d clientId: %s willtopic: %s willmessage: %s Username: %s Password: %s", c.FixedHeader, c.ProtocolVersion, c.ProtocolName, c.CleanSession, c.WillFlag, c.WillQos, c.WillRetain, c.UsernameFlag, c.PasswordFlag, c.Keepalive, c.ClientIdentifier, c.WillTopic, c.WillMessage, c.Username, password)
} }
func (c *ConnectPacket) Write(w io.Writer) error { func (c *ConnectPacket) Write(w io.Writer) error {

View File

@ -81,17 +81,27 @@ var ConnackReturnCodes = map[uint8]string{
255: "Connection Refused: Protocol Violation", 255: "Connection Refused: Protocol Violation",
} }
var (
ErrorRefusedBadProtocolVersion = errors.New("unacceptable protocol version")
ErrorRefusedIDRejected = errors.New("identifier rejected")
ErrorRefusedServerUnavailable = errors.New("server Unavailable")
ErrorRefusedBadUsernameOrPassword = errors.New("bad user name or password")
ErrorRefusedNotAuthorised = errors.New("not Authorized")
ErrorNetworkError = errors.New("network Error")
ErrorProtocolViolation = errors.New("protocol Violation")
)
// ConnErrors is a map of the errors codes constants for Connect() // ConnErrors is a map of the errors codes constants for Connect()
// to a Go error // to a Go error
var ConnErrors = map[byte]error{ var ConnErrors = map[byte]error{
Accepted: nil, Accepted: nil,
ErrRefusedBadProtocolVersion: errors.New("unacceptable protocol version"), ErrRefusedBadProtocolVersion: ErrorRefusedBadProtocolVersion,
ErrRefusedIDRejected: errors.New("identifier rejected"), ErrRefusedIDRejected: ErrorRefusedIDRejected,
ErrRefusedServerUnavailable: errors.New("server Unavailable"), ErrRefusedServerUnavailable: ErrorRefusedServerUnavailable,
ErrRefusedBadUsernameOrPassword: errors.New("bad user name or password"), ErrRefusedBadUsernameOrPassword: ErrorRefusedBadUsernameOrPassword,
ErrRefusedNotAuthorised: errors.New("not Authorized"), ErrRefusedNotAuthorised: ErrorRefusedNotAuthorised,
ErrNetworkError: errors.New("network Error"), ErrNetworkError: ErrorNetworkError,
ErrProtocolViolation: errors.New("protocol Violation"), ErrProtocolViolation: ErrorProtocolViolation,
} }
// ReadPacket takes an instance of an io.Reader (such as net.Conn) and attempts // ReadPacket takes an instance of an io.Reader (such as net.Conn) and attempts

View File

@ -132,13 +132,46 @@ func (r *router) setDefaultHandler(handler MessageHandler) {
// associated callback (or the defaultHandler, if one exists and no other route matched). If // associated callback (or the defaultHandler, if one exists and no other route matched). If
// anything is sent down the stop channel the function will end. // anything is sent down the stop channel the function will end.
func (r *router) matchAndDispatch(messages <-chan *packets.PublishPacket, order bool, client *client) <-chan *PacketAndToken { func (r *router) matchAndDispatch(messages <-chan *packets.PublishPacket, order bool, client *client) <-chan *PacketAndToken {
ackChan := make(chan *PacketAndToken) var wg sync.WaitGroup
go func() { ackOutChan := make(chan *PacketAndToken) // Channel returned to caller; closed when messages channel closed
var ackInChan chan *PacketAndToken // ACKs generated by ackFunc get put onto this channel
stopAckCopy := make(chan struct{}) // Closure requests stop of go routine copying ackInChan to ackOutChan
ackCopyStopped := make(chan struct{}) // Closure indicates that it is safe to close ackOutChan
goRoutinesDone := make(chan struct{}) // closed on wg.Done()
if order {
ackInChan = ackOutChan // When order = true no go routines are used so safe to use one channel and close when done
} else {
// When order = false ACK messages are sent in go routines so ackInChan cannot be closed until all goroutines done
ackInChan = make(chan *PacketAndToken)
go func() { // go routine to copy from ackInChan to ackOutChan until stopped
for {
select {
case a := <-ackInChan:
ackOutChan <- a
case <-stopAckCopy:
close(ackCopyStopped) // Signal main go routine that it is safe to close ackOutChan
for {
select {
case <-ackInChan: // drain ackInChan to ensure all goRoutines can complete cleanly (ACK dropped)
DEBUG.Println(ROU, "matchAndDispatch received acknowledgment after processing stopped (ACK dropped).")
case <-goRoutinesDone:
close(ackInChan) // Nothing further should be sent (a panic is probably better than silent failure)
DEBUG.Println(ROU, "matchAndDispatch order=false copy goroutine exiting.")
return
}
}
}
}
}()
}
go func() { // Main go routine handling inbound messages
for message := range messages { for message := range messages {
// DEBUG.Println(ROU, "matchAndDispatch received message") // DEBUG.Println(ROU, "matchAndDispatch received message")
sent := false sent := false
r.RLock() r.RLock()
m := messageFromPublish(message, ackFunc(ackChan, client.persist, message)) m := messageFromPublish(message, ackFunc(ackInChan, client.persist, message))
var handlers []MessageHandler var handlers []MessageHandler
for e := r.routes.Front(); e != nil; e = e.Next() { for e := r.routes.Front(); e != nil; e = e.Next() {
if e.Value.(*route).match(message.TopicName) { if e.Value.(*route).match(message.TopicName) {
@ -146,9 +179,11 @@ func (r *router) matchAndDispatch(messages <-chan *packets.PublishPacket, order
handlers = append(handlers, e.Value.(*route).callback) handlers = append(handlers, e.Value.(*route).callback)
} else { } else {
hd := e.Value.(*route).callback hd := e.Value.(*route).callback
wg.Add(1)
go func() { go func() {
hd(client, m) hd(client, m)
m.Ack() m.Ack()
wg.Done()
}() }()
} }
sent = true sent = true
@ -159,9 +194,11 @@ func (r *router) matchAndDispatch(messages <-chan *packets.PublishPacket, order
if order { if order {
handlers = append(handlers, r.defaultHandler) handlers = append(handlers, r.defaultHandler)
} else { } else {
wg.Add(1)
go func() { go func() {
r.defaultHandler(client, m) r.defaultHandler(client, m)
m.Ack() m.Ack()
wg.Done()
}() }()
} }
} else { } else {
@ -175,8 +212,18 @@ func (r *router) matchAndDispatch(messages <-chan *packets.PublishPacket, order
} }
// DEBUG.Println(ROU, "matchAndDispatch handled message") // DEBUG.Println(ROU, "matchAndDispatch handled message")
} }
close(ackChan) if order {
close(ackOutChan)
} else { // Ensure that nothing further will be written to ackOutChan before closing it
close(stopAckCopy)
<-ackCopyStopped
close(ackOutChan)
go func() {
wg.Wait() // Note: If this remains running then the user has handlers that are not returning
close(goRoutinesDone)
}()
}
DEBUG.Println(ROU, "matchAndDispatch exiting") DEBUG.Println(ROU, "matchAndDispatch exiting")
}() }()
return ackChan return ackOutChan
} }

View File

@ -2,9 +2,11 @@ package mqtt
import ( import (
"crypto/tls" "crypto/tls"
"fmt"
"io" "io"
"net" "net"
"net/http" "net/http"
"net/url"
"sync" "sync"
"time" "time"
@ -15,8 +17,11 @@ import (
type WebsocketOptions struct { type WebsocketOptions struct {
ReadBufferSize int ReadBufferSize int
WriteBufferSize int WriteBufferSize int
Proxy ProxyFunction
} }
type ProxyFunction func(req *http.Request) (*url.URL, error)
// NewWebsocket returns a new websocket and returns a net.Conn compatible interface using the gorilla/websocket package // NewWebsocket returns a new websocket and returns a net.Conn compatible interface using the gorilla/websocket package
func NewWebsocket(host string, tlsc *tls.Config, timeout time.Duration, requestHeader http.Header, options *WebsocketOptions) (net.Conn, error) { func NewWebsocket(host string, tlsc *tls.Config, timeout time.Duration, requestHeader http.Header, options *WebsocketOptions) (net.Conn, error) {
if timeout == 0 { if timeout == 0 {
@ -27,9 +32,11 @@ func NewWebsocket(host string, tlsc *tls.Config, timeout time.Duration, requestH
// Apply default options // Apply default options
options = &WebsocketOptions{} options = &WebsocketOptions{}
} }
if options.Proxy == nil {
options.Proxy = http.ProxyFromEnvironment
}
dialer := &websocket.Dialer{ dialer := &websocket.Dialer{
Proxy: http.ProxyFromEnvironment, Proxy: options.Proxy,
HandshakeTimeout: timeout, HandshakeTimeout: timeout,
EnableCompression: false, EnableCompression: false,
TLSClientConfig: tlsc, TLSClientConfig: tlsc,
@ -38,9 +45,12 @@ func NewWebsocket(host string, tlsc *tls.Config, timeout time.Duration, requestH
WriteBufferSize: options.WriteBufferSize, WriteBufferSize: options.WriteBufferSize,
} }
ws, _, err := dialer.Dial(host, requestHeader) ws, resp, err := dialer.Dial(host, requestHeader)
if err != nil { if err != nil {
if resp != nil {
WARN.Println(CLI, fmt.Sprintf("Websocket handshake failure. StatusCode: %d. Body: %s", resp.StatusCode, resp.Body))
}
return nil, err return nil, err
} }

View File

@ -13,6 +13,7 @@ import (
"strings" "strings"
"sync" "sync"
"google.golang.org/protobuf/reflect/protodesc"
"google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/reflect/protoregistry" "google.golang.org/protobuf/reflect/protoregistry"
"google.golang.org/protobuf/runtime/protoimpl" "google.golang.org/protobuf/runtime/protoimpl"
@ -62,14 +63,7 @@ func FileDescriptor(s filePath) fileDescGZIP {
// Find the descriptor in the v2 registry. // Find the descriptor in the v2 registry.
var b []byte var b []byte
if fd, _ := protoregistry.GlobalFiles.FindFileByPath(s); fd != nil { if fd, _ := protoregistry.GlobalFiles.FindFileByPath(s); fd != nil {
if fd, ok := fd.(interface{ ProtoLegacyRawDesc() []byte }); ok { b, _ = Marshal(protodesc.ToFileDescriptorProto(fd))
b = fd.ProtoLegacyRawDesc()
} else {
// TODO: Use protodesc.ToFileDescriptorProto to construct
// a descriptorpb.FileDescriptorProto and marshal it.
// However, doing so causes the proto package to have a dependency
// on descriptorpb, leading to cyclic dependency issues.
}
} }
// Locally cache the raw descriptor form for the file. // Locally cache the raw descriptor form for the file.

View File

@ -19,6 +19,8 @@ const urlPrefix = "type.googleapis.com/"
// AnyMessageName returns the message name contained in an anypb.Any message. // AnyMessageName returns the message name contained in an anypb.Any message.
// Most type assertions should use the Is function instead. // Most type assertions should use the Is function instead.
//
// Deprecated: Call the any.MessageName method instead.
func AnyMessageName(any *anypb.Any) (string, error) { func AnyMessageName(any *anypb.Any) (string, error) {
name, err := anyMessageName(any) name, err := anyMessageName(any)
return string(name), err return string(name), err
@ -38,6 +40,8 @@ func anyMessageName(any *anypb.Any) (protoreflect.FullName, error) {
} }
// MarshalAny marshals the given message m into an anypb.Any message. // MarshalAny marshals the given message m into an anypb.Any message.
//
// Deprecated: Call the anypb.New function instead.
func MarshalAny(m proto.Message) (*anypb.Any, error) { func MarshalAny(m proto.Message) (*anypb.Any, error) {
switch dm := m.(type) { switch dm := m.(type) {
case DynamicAny: case DynamicAny:
@ -58,6 +62,9 @@ func MarshalAny(m proto.Message) (*anypb.Any, error) {
// Empty returns a new message of the type specified in an anypb.Any message. // Empty returns a new message of the type specified in an anypb.Any message.
// It returns protoregistry.NotFound if the corresponding message type could not // It returns protoregistry.NotFound if the corresponding message type could not
// be resolved in the global registry. // be resolved in the global registry.
//
// Deprecated: Use protoregistry.GlobalTypes.FindMessageByName instead
// to resolve the message name and create a new instance of it.
func Empty(any *anypb.Any) (proto.Message, error) { func Empty(any *anypb.Any) (proto.Message, error) {
name, err := anyMessageName(any) name, err := anyMessageName(any)
if err != nil { if err != nil {
@ -76,6 +83,8 @@ func Empty(any *anypb.Any) (proto.Message, error) {
// //
// The target message m may be a *DynamicAny message. If the underlying message // The target message m may be a *DynamicAny message. If the underlying message
// type could not be resolved, then this returns protoregistry.NotFound. // type could not be resolved, then this returns protoregistry.NotFound.
//
// Deprecated: Call the any.UnmarshalTo method instead.
func UnmarshalAny(any *anypb.Any, m proto.Message) error { func UnmarshalAny(any *anypb.Any, m proto.Message) error {
if dm, ok := m.(*DynamicAny); ok { if dm, ok := m.(*DynamicAny); ok {
if dm.Message == nil { if dm.Message == nil {
@ -100,6 +109,8 @@ func UnmarshalAny(any *anypb.Any, m proto.Message) error {
} }
// Is reports whether the Any message contains a message of the specified type. // Is reports whether the Any message contains a message of the specified type.
//
// Deprecated: Call the any.MessageIs method instead.
func Is(any *anypb.Any, m proto.Message) bool { func Is(any *anypb.Any, m proto.Message) bool {
if any == nil || m == nil { if any == nil || m == nil {
return false return false
@ -119,6 +130,9 @@ func Is(any *anypb.Any, m proto.Message) bool {
// var x ptypes.DynamicAny // var x ptypes.DynamicAny
// if err := ptypes.UnmarshalAny(a, &x); err != nil { ... } // if err := ptypes.UnmarshalAny(a, &x); err != nil { ... }
// fmt.Printf("unmarshaled message: %v", x.Message) // fmt.Printf("unmarshaled message: %v", x.Message)
//
// Deprecated: Use the any.UnmarshalNew method instead to unmarshal
// the any message contents into a new instance of the underlying message.
type DynamicAny struct{ proto.Message } type DynamicAny struct{ proto.Message }
func (m DynamicAny) String() string { func (m DynamicAny) String() string {

View File

@ -3,4 +3,8 @@
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// Package ptypes provides functionality for interacting with well-known types. // Package ptypes provides functionality for interacting with well-known types.
//
// Deprecated: Well-known types have specialized functionality directly
// injected into the generated packages for each message type.
// See the deprecation notice for each function for the suggested alternative.
package ptypes package ptypes

View File

@ -21,6 +21,8 @@ const (
// Duration converts a durationpb.Duration to a time.Duration. // Duration converts a durationpb.Duration to a time.Duration.
// Duration returns an error if dur is invalid or overflows a time.Duration. // Duration returns an error if dur is invalid or overflows a time.Duration.
//
// Deprecated: Call the dur.AsDuration and dur.CheckValid methods instead.
func Duration(dur *durationpb.Duration) (time.Duration, error) { func Duration(dur *durationpb.Duration) (time.Duration, error) {
if err := validateDuration(dur); err != nil { if err := validateDuration(dur); err != nil {
return 0, err return 0, err
@ -39,6 +41,8 @@ func Duration(dur *durationpb.Duration) (time.Duration, error) {
} }
// DurationProto converts a time.Duration to a durationpb.Duration. // DurationProto converts a time.Duration to a durationpb.Duration.
//
// Deprecated: Call the durationpb.New function instead.
func DurationProto(d time.Duration) *durationpb.Duration { func DurationProto(d time.Duration) *durationpb.Duration {
nanos := d.Nanoseconds() nanos := d.Nanoseconds()
secs := nanos / 1e9 secs := nanos / 1e9

View File

@ -33,6 +33,8 @@ const (
// //
// A nil Timestamp returns an error. The first return value in that case is // A nil Timestamp returns an error. The first return value in that case is
// undefined. // undefined.
//
// Deprecated: Call the ts.AsTime and ts.CheckValid methods instead.
func Timestamp(ts *timestamppb.Timestamp) (time.Time, error) { func Timestamp(ts *timestamppb.Timestamp) (time.Time, error) {
// Don't return the zero value on error, because corresponds to a valid // Don't return the zero value on error, because corresponds to a valid
// timestamp. Instead return whatever time.Unix gives us. // timestamp. Instead return whatever time.Unix gives us.
@ -46,6 +48,8 @@ func Timestamp(ts *timestamppb.Timestamp) (time.Time, error) {
} }
// TimestampNow returns a google.protobuf.Timestamp for the current time. // TimestampNow returns a google.protobuf.Timestamp for the current time.
//
// Deprecated: Call the timestamppb.Now function instead.
func TimestampNow() *timestamppb.Timestamp { func TimestampNow() *timestamppb.Timestamp {
ts, err := TimestampProto(time.Now()) ts, err := TimestampProto(time.Now())
if err != nil { if err != nil {
@ -56,6 +60,8 @@ func TimestampNow() *timestamppb.Timestamp {
// TimestampProto converts the time.Time to a google.protobuf.Timestamp proto. // TimestampProto converts the time.Time to a google.protobuf.Timestamp proto.
// It returns an error if the resulting Timestamp is invalid. // It returns an error if the resulting Timestamp is invalid.
//
// Deprecated: Call the timestamppb.New function instead.
func TimestampProto(t time.Time) (*timestamppb.Timestamp, error) { func TimestampProto(t time.Time) (*timestamppb.Timestamp, error) {
ts := &timestamppb.Timestamp{ ts := &timestamppb.Timestamp{
Seconds: t.Unix(), Seconds: t.Unix(),
@ -69,6 +75,9 @@ func TimestampProto(t time.Time) (*timestamppb.Timestamp, error) {
// TimestampString returns the RFC 3339 string for valid Timestamps. // TimestampString returns the RFC 3339 string for valid Timestamps.
// For invalid Timestamps, it returns an error message in parentheses. // For invalid Timestamps, it returns an error message in parentheses.
//
// Deprecated: Call the ts.AsTime method instead,
// followed by a call to the Format method on the time.Time value.
func TimestampString(ts *timestamppb.Timestamp) string { func TimestampString(ts *timestamppb.Timestamp) string {
t, err := Timestamp(ts) t, err := Timestamp(ts)
if err != nil { if err != nil {

View File

@ -4,14 +4,12 @@ git:
depth: 1 depth: 1
env: env:
- GO111MODULE=on - GO111MODULE=on
go: [1.13.x, 1.14.x] go: 1.15.x
os: [linux, osx] os: linux
install: install:
- ./travis/install.sh - ./travis/install.sh
script: script:
- ./travis/cross_build.sh - cd ci
- ./travis/lint.sh - go run mage.go -v -w ../ crossBuild
- export GOMAXPROCS=4 - go run mage.go -v -w ../ lint
- export GORACE=halt_on_error=1 - go run mage.go -v -w ../ test
- go test -race -v ./...
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then go test -race -v -tags appengine ./... ; fi

View File

@ -1,3 +1,39 @@
# 1.8.1
Code quality:
* move magefile in its own subdir/submodule to remove magefile dependency on logrus consumer
* improve timestamp format documentation
Fixes:
* fix race condition on logger hooks
# 1.8.0
Correct versioning number replacing v1.7.1.
# 1.7.1
Beware this release has introduced a new public API and its semver is therefore incorrect.
Code quality:
* use go 1.15 in travis
* use magefile as task runner
Fixes:
* small fixes about new go 1.13 error formatting system
* Fix for long time race condiction with mutating data hooks
Features:
* build support for zos
# 1.7.0
Fixes:
* the dependency toward a windows terminal library has been removed
Features:
* a new buffer pool management API has been added
* a set of `<LogLevel>Fn()` functions have been added
# 1.6.0 # 1.6.0
Fixes: Fixes:
* end of line cleanup * end of line cleanup

View File

@ -402,7 +402,7 @@ func (f *MyJSONFormatter) Format(entry *Entry) ([]byte, error) {
// source of the official loggers. // source of the official loggers.
serialized, err := json.Marshal(entry.Data) serialized, err := json.Marshal(entry.Data)
if err != nil { if err != nil {
return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err) return nil, fmt.Errorf("Failed to marshal fields to JSON, %w", err)
} }
return append(serialized, '\n'), nil return append(serialized, '\n'), nil
} }

View File

@ -78,6 +78,14 @@ func NewEntry(logger *Logger) *Entry {
} }
} }
func (entry *Entry) Dup() *Entry {
data := make(Fields, len(entry.Data))
for k, v := range entry.Data {
data[k] = v
}
return &Entry{Logger: entry.Logger, Data: data, Time: entry.Time, Context: entry.Context, err: entry.err}
}
// Returns the bytes representation of this entry from the formatter. // Returns the bytes representation of this entry from the formatter.
func (entry *Entry) Bytes() ([]byte, error) { func (entry *Entry) Bytes() ([]byte, error) {
return entry.Logger.Formatter.Format(entry) return entry.Logger.Formatter.Format(entry)
@ -123,11 +131,9 @@ func (entry *Entry) WithFields(fields Fields) *Entry {
for k, v := range fields { for k, v := range fields {
isErrField := false isErrField := false
if t := reflect.TypeOf(v); t != nil { if t := reflect.TypeOf(v); t != nil {
switch t.Kind() { switch {
case reflect.Func: case t.Kind() == reflect.Func, t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Func:
isErrField = true isErrField = true
case reflect.Ptr:
isErrField = t.Elem().Kind() == reflect.Func
} }
} }
if isErrField { if isErrField {
@ -212,68 +218,72 @@ func (entry Entry) HasCaller() (has bool) {
entry.Caller != nil entry.Caller != nil
} }
// This function is not declared with a pointer value because otherwise func (entry *Entry) log(level Level, msg string) {
// race conditions will occur when using multiple goroutines
func (entry Entry) log(level Level, msg string) {
var buffer *bytes.Buffer var buffer *bytes.Buffer
// Default to now, but allow users to override if they want. newEntry := entry.Dup()
//
// We don't have to worry about polluting future calls to Entry#log() if newEntry.Time.IsZero() {
// with this assignment because this function is declared with a newEntry.Time = time.Now()
// non-pointer receiver.
if entry.Time.IsZero() {
entry.Time = time.Now()
} }
entry.Level = level newEntry.Level = level
entry.Message = msg newEntry.Message = msg
entry.Logger.mu.Lock()
if entry.Logger.ReportCaller {
entry.Caller = getCaller()
}
entry.Logger.mu.Unlock()
entry.fireHooks() newEntry.Logger.mu.Lock()
reportCaller := newEntry.Logger.ReportCaller
newEntry.Logger.mu.Unlock()
if reportCaller {
newEntry.Caller = getCaller()
}
newEntry.fireHooks()
buffer = getBuffer() buffer = getBuffer()
defer func() { defer func() {
entry.Buffer = nil newEntry.Buffer = nil
putBuffer(buffer) putBuffer(buffer)
}() }()
buffer.Reset() buffer.Reset()
entry.Buffer = buffer newEntry.Buffer = buffer
entry.write() newEntry.write()
entry.Buffer = nil newEntry.Buffer = nil
// To avoid Entry#log() returning a value that only would make sense for // To avoid Entry#log() returning a value that only would make sense for
// panic() to use in Entry#Panic(), we avoid the allocation by checking // panic() to use in Entry#Panic(), we avoid the allocation by checking
// directly here. // directly here.
if level <= PanicLevel { if level <= PanicLevel {
panic(&entry) panic(newEntry)
} }
} }
func (entry *Entry) fireHooks() { func (entry *Entry) fireHooks() {
var tmpHooks LevelHooks
entry.Logger.mu.Lock() entry.Logger.mu.Lock()
defer entry.Logger.mu.Unlock() tmpHooks = make(LevelHooks, len(entry.Logger.Hooks))
err := entry.Logger.Hooks.Fire(entry.Level, entry) for k, v := range entry.Logger.Hooks {
tmpHooks[k] = v
}
entry.Logger.mu.Unlock()
err := tmpHooks.Fire(entry.Level, entry)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err) fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err)
} }
} }
func (entry *Entry) write() { func (entry *Entry) write() {
entry.Logger.mu.Lock()
defer entry.Logger.mu.Unlock()
serialized, err := entry.Logger.Formatter.Format(entry) serialized, err := entry.Logger.Formatter.Format(entry)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "Failed to obtain reader, %v\n", err) fmt.Fprintf(os.Stderr, "Failed to obtain reader, %v\n", err)
return return
} }
if _, err = entry.Logger.Out.Write(serialized); err != nil { entry.Logger.mu.Lock()
defer entry.Logger.mu.Unlock()
if _, err := entry.Logger.Out.Write(serialized); err != nil {
fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err) fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err)
} }
} }
@ -319,7 +329,6 @@ func (entry *Entry) Fatal(args ...interface{}) {
func (entry *Entry) Panic(args ...interface{}) { func (entry *Entry) Panic(args ...interface{}) {
entry.Log(PanicLevel, args...) entry.Log(PanicLevel, args...)
panic(fmt.Sprint(args...))
} }
// Entry Printf family functions // Entry Printf family functions

View File

@ -23,6 +23,9 @@ func (f FieldMap) resolve(key fieldKey) string {
// JSONFormatter formats logs into parsable json // JSONFormatter formats logs into parsable json
type JSONFormatter struct { type JSONFormatter struct {
// TimestampFormat sets the format used for marshaling timestamps. // TimestampFormat sets the format used for marshaling timestamps.
// The format to use is the same than for time.Format or time.Parse from the standard
// library.
// The standard Library already provides a set of predefined format.
TimestampFormat string TimestampFormat string
// DisableTimestamp allows disabling automatic timestamps in output // DisableTimestamp allows disabling automatic timestamps in output
@ -118,7 +121,7 @@ func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
encoder.SetIndent("", " ") encoder.SetIndent("", " ")
} }
if err := encoder.Encode(data); err != nil { if err := encoder.Encode(data); err != nil {
return nil, fmt.Errorf("failed to marshal fields to JSON, %v", err) return nil, fmt.Errorf("failed to marshal fields to JSON, %w", err)
} }
return b.Bytes(), nil return b.Bytes(), nil

View File

@ -12,7 +12,7 @@ import (
// LogFunction For big messages, it can be more efficient to pass a function // LogFunction For big messages, it can be more efficient to pass a function
// and only call it if the log level is actually enables rather than // and only call it if the log level is actually enables rather than
// generating the log message and then checking if the level is enabled // generating the log message and then checking if the level is enabled
type LogFunction func()[]interface{} type LogFunction func() []interface{}
type Logger struct { type Logger struct {
// The logs are `io.Copy`'d to this in a mutex. It's common to set this to a // The logs are `io.Copy`'d to this in a mutex. It's common to set this to a

View File

@ -1,4 +1,4 @@
// +build linux aix // +build linux aix zos
// +build !js // +build !js
package logrus package logrus

View File

@ -53,7 +53,10 @@ type TextFormatter struct {
// the time passed since beginning of execution. // the time passed since beginning of execution.
FullTimestamp bool FullTimestamp bool
// TimestampFormat to use for display when a full timestamp is printed // TimestampFormat to use for display when a full timestamp is printed.
// The format to use is the same than for time.Format or time.Parse from the standard
// library.
// The standard Library already provides a set of predefined format.
TimestampFormat string TimestampFormat string
// The fields are sorted by default for a consistent output. For applications // The fields are sorted by default for a consistent output. For applications
@ -235,6 +238,8 @@ func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []strin
levelColor = yellow levelColor = yellow
case ErrorLevel, FatalLevel, PanicLevel: case ErrorLevel, FatalLevel, PanicLevel:
levelColor = red levelColor = red
case InfoLevel:
levelColor = blue
default: default:
levelColor = blue levelColor = blue
} }

View File

@ -6,14 +6,13 @@ package prototext
import ( import (
"fmt" "fmt"
"strings"
"unicode/utf8" "unicode/utf8"
"google.golang.org/protobuf/internal/encoding/messageset" "google.golang.org/protobuf/internal/encoding/messageset"
"google.golang.org/protobuf/internal/encoding/text" "google.golang.org/protobuf/internal/encoding/text"
"google.golang.org/protobuf/internal/errors" "google.golang.org/protobuf/internal/errors"
"google.golang.org/protobuf/internal/fieldnum"
"google.golang.org/protobuf/internal/flags" "google.golang.org/protobuf/internal/flags"
"google.golang.org/protobuf/internal/genid"
"google.golang.org/protobuf/internal/pragma" "google.golang.org/protobuf/internal/pragma"
"google.golang.org/protobuf/internal/set" "google.golang.org/protobuf/internal/set"
"google.golang.org/protobuf/internal/strs" "google.golang.org/protobuf/internal/strs"
@ -23,6 +22,7 @@ import (
) )
// Unmarshal reads the given []byte into the given proto.Message. // Unmarshal reads the given []byte into the given proto.Message.
// The provided message must be mutable (e.g., a non-nil pointer to a message).
func Unmarshal(b []byte, m proto.Message) error { func Unmarshal(b []byte, m proto.Message) error {
return UnmarshalOptions{}.Unmarshal(b, m) return UnmarshalOptions{}.Unmarshal(b, m)
} }
@ -51,9 +51,17 @@ type UnmarshalOptions struct {
} }
} }
// Unmarshal reads the given []byte and populates the given proto.Message using options in // Unmarshal reads the given []byte and populates the given proto.Message
// UnmarshalOptions object. // using options in the UnmarshalOptions object.
// The provided message must be mutable (e.g., a non-nil pointer to a message).
func (o UnmarshalOptions) Unmarshal(b []byte, m proto.Message) error { func (o UnmarshalOptions) Unmarshal(b []byte, m proto.Message) error {
return o.unmarshal(b, m)
}
// unmarshal is a centralized function that all unmarshal operations go through.
// For profiling purposes, avoid changing the name of this function or
// introducing other code paths for unmarshal that do not go through this.
func (o UnmarshalOptions) unmarshal(b []byte, m proto.Message) error {
proto.Reset(m) proto.Reset(m)
if o.Resolver == nil { if o.Resolver == nil {
@ -101,7 +109,7 @@ func (d decoder) unmarshalMessage(m pref.Message, checkDelims bool) error {
return errors.New("no support for proto1 MessageSets") return errors.New("no support for proto1 MessageSets")
} }
if messageDesc.FullName() == "google.protobuf.Any" { if messageDesc.FullName() == genid.Any_message_fullname {
return d.unmarshalAny(m, checkDelims) return d.unmarshalAny(m, checkDelims)
} }
@ -151,21 +159,11 @@ func (d decoder) unmarshalMessage(m pref.Message, checkDelims bool) error {
switch tok.NameKind() { switch tok.NameKind() {
case text.IdentName: case text.IdentName:
name = pref.Name(tok.IdentName()) name = pref.Name(tok.IdentName())
fd = fieldDescs.ByName(name) fd = fieldDescs.ByTextName(string(name))
if fd == nil {
// The proto name of a group field is in all lowercase,
// while the textproto field name is the group message name.
gd := fieldDescs.ByName(pref.Name(strings.ToLower(string(name))))
if gd != nil && gd.Kind() == pref.GroupKind && gd.Message().Name() == name {
fd = gd
}
} else if fd.Kind() == pref.GroupKind && fd.Message().Name() != name {
fd = nil // reset since field name is actually the message name
}
case text.TypeName: case text.TypeName:
// Handle extensions only. This code path is not for Any. // Handle extensions only. This code path is not for Any.
xt, xtErr = d.findExtension(pref.FullName(tok.TypeName())) xt, xtErr = d.opts.Resolver.FindExtensionByName(pref.FullName(tok.TypeName()))
case text.FieldNumber: case text.FieldNumber:
isFieldNumberName = true isFieldNumberName = true
@ -262,15 +260,6 @@ func (d decoder) unmarshalMessage(m pref.Message, checkDelims bool) error {
return nil return nil
} }
// findExtension returns protoreflect.ExtensionType from the Resolver if found.
func (d decoder) findExtension(xtName pref.FullName) (pref.ExtensionType, error) {
xt, err := d.opts.Resolver.FindExtensionByName(xtName)
if err == nil {
return xt, nil
}
return messageset.FindMessageSetExtension(d.opts.Resolver, xtName)
}
// unmarshalSingular unmarshals a non-repeated field value specified by the // unmarshalSingular unmarshals a non-repeated field value specified by the
// given FieldDescriptor. // given FieldDescriptor.
func (d decoder) unmarshalSingular(fd pref.FieldDescriptor, m pref.Message) error { func (d decoder) unmarshalSingular(fd pref.FieldDescriptor, m pref.Message) error {
@ -531,14 +520,13 @@ Loop:
return d.unexpectedTokenError(tok) return d.unexpectedTokenError(tok)
} }
name := tok.IdentName() switch name := pref.Name(tok.IdentName()); name {
switch name { case genid.MapEntry_Key_field_name:
case "key":
if !tok.HasSeparator() { if !tok.HasSeparator() {
return d.syntaxError(tok.Pos(), "missing field separator :") return d.syntaxError(tok.Pos(), "missing field separator :")
} }
if key.IsValid() { if key.IsValid() {
return d.newError(tok.Pos(), `map entry "key" cannot be repeated`) return d.newError(tok.Pos(), "map entry %q cannot be repeated", name)
} }
val, err := d.unmarshalScalar(fd.MapKey()) val, err := d.unmarshalScalar(fd.MapKey())
if err != nil { if err != nil {
@ -546,14 +534,14 @@ Loop:
} }
key = val.MapKey() key = val.MapKey()
case "value": case genid.MapEntry_Value_field_name:
if kind := fd.MapValue().Kind(); (kind != pref.MessageKind) && (kind != pref.GroupKind) { if kind := fd.MapValue().Kind(); (kind != pref.MessageKind) && (kind != pref.GroupKind) {
if !tok.HasSeparator() { if !tok.HasSeparator() {
return d.syntaxError(tok.Pos(), "missing field separator :") return d.syntaxError(tok.Pos(), "missing field separator :")
} }
} }
if pval.IsValid() { if pval.IsValid() {
return d.newError(tok.Pos(), `map entry "value" cannot be repeated`) return d.newError(tok.Pos(), "map entry %q cannot be repeated", name)
} }
pval, err = unmarshalMapValue() pval, err = unmarshalMapValue()
if err != nil { if err != nil {
@ -590,13 +578,9 @@ Loop:
func (d decoder) unmarshalAny(m pref.Message, checkDelims bool) error { func (d decoder) unmarshalAny(m pref.Message, checkDelims bool) error {
var typeURL string var typeURL string
var bValue []byte var bValue []byte
var seenTypeUrl bool
// hasFields tracks which valid fields have been seen in the loop below in var seenValue bool
// order to flag an error if there are duplicates or conflicts. It may var isExpanded bool
// contain the strings "type_url", "value" and "expanded". The literal
// "expanded" is used to indicate that the expanded form has been
// encountered already.
hasFields := map[string]bool{}
if checkDelims { if checkDelims {
tok, err := d.Read() tok, err := d.Read()
@ -635,12 +619,12 @@ Loop:
return d.syntaxError(tok.Pos(), "missing field separator :") return d.syntaxError(tok.Pos(), "missing field separator :")
} }
switch tok.IdentName() { switch name := pref.Name(tok.IdentName()); name {
case "type_url": case genid.Any_TypeUrl_field_name:
if hasFields["type_url"] { if seenTypeUrl {
return d.newError(tok.Pos(), "duplicate Any type_url field") return d.newError(tok.Pos(), "duplicate %v field", genid.Any_TypeUrl_field_fullname)
} }
if hasFields["expanded"] { if isExpanded {
return d.newError(tok.Pos(), "conflict with [%s] field", typeURL) return d.newError(tok.Pos(), "conflict with [%s] field", typeURL)
} }
tok, err := d.Read() tok, err := d.Read()
@ -650,15 +634,15 @@ Loop:
var ok bool var ok bool
typeURL, ok = tok.String() typeURL, ok = tok.String()
if !ok { if !ok {
return d.newError(tok.Pos(), "invalid Any type_url: %v", tok.RawString()) return d.newError(tok.Pos(), "invalid %v field value: %v", genid.Any_TypeUrl_field_fullname, tok.RawString())
} }
hasFields["type_url"] = true seenTypeUrl = true
case "value": case genid.Any_Value_field_name:
if hasFields["value"] { if seenValue {
return d.newError(tok.Pos(), "duplicate Any value field") return d.newError(tok.Pos(), "duplicate %v field", genid.Any_Value_field_fullname)
} }
if hasFields["expanded"] { if isExpanded {
return d.newError(tok.Pos(), "conflict with [%s] field", typeURL) return d.newError(tok.Pos(), "conflict with [%s] field", typeURL)
} }
tok, err := d.Read() tok, err := d.Read()
@ -667,22 +651,22 @@ Loop:
} }
s, ok := tok.String() s, ok := tok.String()
if !ok { if !ok {
return d.newError(tok.Pos(), "invalid Any value: %v", tok.RawString()) return d.newError(tok.Pos(), "invalid %v field value: %v", genid.Any_Value_field_fullname, tok.RawString())
} }
bValue = []byte(s) bValue = []byte(s)
hasFields["value"] = true seenValue = true
default: default:
if !d.opts.DiscardUnknown { if !d.opts.DiscardUnknown {
return d.newError(tok.Pos(), "invalid field name %q in google.protobuf.Any message", tok.RawString()) return d.newError(tok.Pos(), "invalid field name %q in %v message", tok.RawString(), genid.Any_message_fullname)
} }
} }
case text.TypeName: case text.TypeName:
if hasFields["expanded"] { if isExpanded {
return d.newError(tok.Pos(), "cannot have more than one type") return d.newError(tok.Pos(), "cannot have more than one type")
} }
if hasFields["type_url"] { if seenTypeUrl {
return d.newError(tok.Pos(), "conflict with type_url field") return d.newError(tok.Pos(), "conflict with type_url field")
} }
typeURL = tok.TypeName() typeURL = tok.TypeName()
@ -691,21 +675,21 @@ Loop:
if err != nil { if err != nil {
return err return err
} }
hasFields["expanded"] = true isExpanded = true
default: default:
if !d.opts.DiscardUnknown { if !d.opts.DiscardUnknown {
return d.newError(tok.Pos(), "invalid field name %q in google.protobuf.Any message", tok.RawString()) return d.newError(tok.Pos(), "invalid field name %q in %v message", tok.RawString(), genid.Any_message_fullname)
} }
} }
} }
fds := m.Descriptor().Fields() fds := m.Descriptor().Fields()
if len(typeURL) > 0 { if len(typeURL) > 0 {
m.Set(fds.ByNumber(fieldnum.Any_TypeUrl), pref.ValueOfString(typeURL)) m.Set(fds.ByNumber(genid.Any_TypeUrl_field_number), pref.ValueOfString(typeURL))
} }
if len(bValue) > 0 { if len(bValue) > 0 {
m.Set(fds.ByNumber(fieldnum.Any_Value), pref.ValueOfBytes(bValue)) m.Set(fds.ByNumber(genid.Any_Value_field_number), pref.ValueOfBytes(bValue))
} }
return nil return nil
} }

View File

@ -6,7 +6,6 @@ package prototext
import ( import (
"fmt" "fmt"
"sort"
"strconv" "strconv"
"unicode/utf8" "unicode/utf8"
@ -14,12 +13,13 @@ import (
"google.golang.org/protobuf/internal/encoding/messageset" "google.golang.org/protobuf/internal/encoding/messageset"
"google.golang.org/protobuf/internal/encoding/text" "google.golang.org/protobuf/internal/encoding/text"
"google.golang.org/protobuf/internal/errors" "google.golang.org/protobuf/internal/errors"
"google.golang.org/protobuf/internal/fieldnum"
"google.golang.org/protobuf/internal/flags" "google.golang.org/protobuf/internal/flags"
"google.golang.org/protobuf/internal/mapsort" "google.golang.org/protobuf/internal/genid"
"google.golang.org/protobuf/internal/order"
"google.golang.org/protobuf/internal/pragma" "google.golang.org/protobuf/internal/pragma"
"google.golang.org/protobuf/internal/strs" "google.golang.org/protobuf/internal/strs"
"google.golang.org/protobuf/proto" "google.golang.org/protobuf/proto"
"google.golang.org/protobuf/reflect/protoreflect"
pref "google.golang.org/protobuf/reflect/protoreflect" pref "google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/reflect/protoregistry" "google.golang.org/protobuf/reflect/protoregistry"
) )
@ -102,6 +102,13 @@ func (o MarshalOptions) Format(m proto.Message) string {
// MarshalOptions object. Do not depend on the output being stable. It may // MarshalOptions object. Do not depend on the output being stable. It may
// change over time across different versions of the program. // change over time across different versions of the program.
func (o MarshalOptions) Marshal(m proto.Message) ([]byte, error) { func (o MarshalOptions) Marshal(m proto.Message) ([]byte, error) {
return o.marshal(m)
}
// marshal is a centralized function that all marshal operations go through.
// For profiling purposes, avoid changing the name of this function or
// introducing other code paths for marshal that do not go through this.
func (o MarshalOptions) marshal(m proto.Message) ([]byte, error) {
var delims = [2]byte{'{', '}'} var delims = [2]byte{'{', '}'}
if o.Multiline && o.Indent == "" { if o.Multiline && o.Indent == "" {
@ -155,42 +162,22 @@ func (e encoder) marshalMessage(m pref.Message, inclDelims bool) error {
} }
// Handle Any expansion. // Handle Any expansion.
if messageDesc.FullName() == "google.protobuf.Any" { if messageDesc.FullName() == genid.Any_message_fullname {
if e.marshalAny(m) { if e.marshalAny(m) {
return nil return nil
} }
// If unable to expand, continue on to marshal Any as a regular message. // If unable to expand, continue on to marshal Any as a regular message.
} }
// Marshal known fields. // Marshal fields.
fieldDescs := messageDesc.Fields() var err error
size := fieldDescs.Len() order.RangeFields(m, order.IndexNameFieldOrder, func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {
for i := 0; i < size; { if err = e.marshalField(fd.TextName(), v, fd); err != nil {
fd := fieldDescs.Get(i) return false
if od := fd.ContainingOneof(); od != nil {
fd = m.WhichOneof(od)
i += od.Fields().Len()
} else {
i++
} }
return true
if fd == nil || !m.Has(fd) { })
continue if err != nil {
}
name := fd.Name()
// Use type name for group field name.
if fd.Kind() == pref.GroupKind {
name = fd.Message().Name()
}
val := m.Get(fd)
if err := e.marshalField(string(name), val, fd); err != nil {
return err
}
}
// Marshal extensions.
if err := e.marshalExtensions(m); err != nil {
return err return err
} }
@ -283,18 +270,18 @@ func (e encoder) marshalList(name string, list pref.List, fd pref.FieldDescripto
// marshalMap marshals the given protoreflect.Map as multiple name-value fields. // marshalMap marshals the given protoreflect.Map as multiple name-value fields.
func (e encoder) marshalMap(name string, mmap pref.Map, fd pref.FieldDescriptor) error { func (e encoder) marshalMap(name string, mmap pref.Map, fd pref.FieldDescriptor) error {
var err error var err error
mapsort.Range(mmap, fd.MapKey().Kind(), func(key pref.MapKey, val pref.Value) bool { order.RangeEntries(mmap, order.GenericKeyOrder, func(key pref.MapKey, val pref.Value) bool {
e.WriteName(name) e.WriteName(name)
e.StartMessage() e.StartMessage()
defer e.EndMessage() defer e.EndMessage()
e.WriteName("key") e.WriteName(string(genid.MapEntry_Key_field_name))
err = e.marshalSingular(key.Value(), fd.MapKey()) err = e.marshalSingular(key.Value(), fd.MapKey())
if err != nil { if err != nil {
return false return false
} }
e.WriteName("value") e.WriteName(string(genid.MapEntry_Value_field_name))
err = e.marshalSingular(val, fd.MapValue()) err = e.marshalSingular(val, fd.MapValue())
if err != nil { if err != nil {
return false return false
@ -304,48 +291,6 @@ func (e encoder) marshalMap(name string, mmap pref.Map, fd pref.FieldDescriptor)
return err return err
} }
// marshalExtensions marshals extension fields.
func (e encoder) marshalExtensions(m pref.Message) error {
type entry struct {
key string
value pref.Value
desc pref.FieldDescriptor
}
// Get a sorted list based on field key first.
var entries []entry
m.Range(func(fd pref.FieldDescriptor, v pref.Value) bool {
if !fd.IsExtension() {
return true
}
// For MessageSet extensions, the name used is the parent message.
name := fd.FullName()
if messageset.IsMessageSetExtension(fd) {
name = name.Parent()
}
entries = append(entries, entry{
key: string(name),
value: v,
desc: fd,
})
return true
})
// Sort extensions lexicographically.
sort.Slice(entries, func(i, j int) bool {
return entries[i].key < entries[j].key
})
// Write out sorted list.
for _, entry := range entries {
// Extension field name is the proto field name enclosed in [].
name := "[" + entry.key + "]"
if err := e.marshalField(name, entry.value, entry.desc); err != nil {
return err
}
}
return nil
}
// marshalUnknown parses the given []byte and marshals fields out. // marshalUnknown parses the given []byte and marshals fields out.
// This function assumes proper encoding in the given []byte. // This function assumes proper encoding in the given []byte.
func (e encoder) marshalUnknown(b []byte) { func (e encoder) marshalUnknown(b []byte) {
@ -392,7 +337,7 @@ func (e encoder) marshalUnknown(b []byte) {
func (e encoder) marshalAny(any pref.Message) bool { func (e encoder) marshalAny(any pref.Message) bool {
// Construct the embedded message. // Construct the embedded message.
fds := any.Descriptor().Fields() fds := any.Descriptor().Fields()
fdType := fds.ByNumber(fieldnum.Any_TypeUrl) fdType := fds.ByNumber(genid.Any_TypeUrl_field_number)
typeURL := any.Get(fdType).String() typeURL := any.Get(fdType).String()
mt, err := e.opts.Resolver.FindMessageByURL(typeURL) mt, err := e.opts.Resolver.FindMessageByURL(typeURL)
if err != nil { if err != nil {
@ -401,7 +346,7 @@ func (e encoder) marshalAny(any pref.Message) bool {
m := mt.New().Interface() m := mt.New().Interface()
// Unmarshal bytes into embedded message. // Unmarshal bytes into embedded message.
fdValue := fds.ByNumber(fieldnum.Any_Value) fdValue := fds.ByNumber(genid.Any_Value_field_number)
value := any.Get(fdValue) value := any.Get(fdValue)
err = proto.UnmarshalOptions{ err = proto.UnmarshalOptions{
AllowPartial: true, AllowPartial: true,

View File

@ -42,6 +42,8 @@ func formatListOpt(vs list, isRoot, allowMulti bool) string {
name = "FileImports" name = "FileImports"
case pref.Descriptor: case pref.Descriptor:
name = reflect.ValueOf(vs).MethodByName("Get").Type().Out(0).Name() + "s" name = reflect.ValueOf(vs).MethodByName("Get").Type().Out(0).Name() + "s"
default:
name = reflect.ValueOf(vs).Elem().Type().Name()
} }
start, end = name+"{", "}" start, end = name+"{", "}"
} }

View File

@ -26,6 +26,14 @@ func Bool() bool {
return randSeed%2 == 1 return randSeed%2 == 1
} }
// Intn returns a deterministically random integer between 0 and n-1, inclusive.
func Intn(n int) int {
if n <= 0 {
panic("must be positive")
}
return int(randSeed % uint64(n))
}
// randSeed is a best-effort at an approximate hash of the Go binary. // randSeed is a best-effort at an approximate hash of the Go binary.
var randSeed = binaryHash() var randSeed = binaryHash()

View File

@ -11,10 +11,9 @@ import (
"google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/encoding/protowire"
"google.golang.org/protobuf/internal/errors" "google.golang.org/protobuf/internal/errors"
pref "google.golang.org/protobuf/reflect/protoreflect" pref "google.golang.org/protobuf/reflect/protoreflect"
preg "google.golang.org/protobuf/reflect/protoregistry"
) )
// The MessageSet wire format is equivalent to a message defiend as follows, // The MessageSet wire format is equivalent to a message defined as follows,
// where each Item defines an extension field with a field number of 'type_id' // where each Item defines an extension field with a field number of 'type_id'
// and content of 'message'. MessageSet extensions must be non-repeated message // and content of 'message'. MessageSet extensions must be non-repeated message
// fields. // fields.
@ -48,33 +47,17 @@ func IsMessageSet(md pref.MessageDescriptor) bool {
return ok && xmd.IsMessageSet() return ok && xmd.IsMessageSet()
} }
// IsMessageSetExtension reports this field extends a MessageSet. // IsMessageSetExtension reports this field properly extends a MessageSet.
func IsMessageSetExtension(fd pref.FieldDescriptor) bool { func IsMessageSetExtension(fd pref.FieldDescriptor) bool {
if fd.Name() != ExtensionName { switch {
case fd.Name() != ExtensionName:
return false
case !IsMessageSet(fd.ContainingMessage()):
return false
case fd.FullName().Parent() != fd.Message().FullName():
return false return false
} }
if fd.FullName().Parent() != fd.Message().FullName() { return true
return false
}
return IsMessageSet(fd.ContainingMessage())
}
// FindMessageSetExtension locates a MessageSet extension field by name.
// In text and JSON formats, the extension name used is the message itself.
// The extension field name is derived by appending ExtensionName.
func FindMessageSetExtension(r preg.ExtensionTypeResolver, s pref.FullName) (pref.ExtensionType, error) {
name := s.Append(ExtensionName)
xt, err := r.FindExtensionByName(name)
if err != nil {
if err == preg.NotFound {
return nil, err
}
return nil, errors.Wrap(err, "%q", name)
}
if !IsMessageSetExtension(xt.TypeDescriptor()) {
return nil, preg.NotFound
}
return xt, nil
} }
// SizeField returns the size of a MessageSet item field containing an extension // SizeField returns the size of a MessageSet item field containing an extension

View File

@ -104,7 +104,7 @@ func Unmarshal(tag string, goType reflect.Type, evs pref.EnumValueDescriptors) p
case strings.HasPrefix(s, "json="): case strings.HasPrefix(s, "json="):
jsonName := s[len("json="):] jsonName := s[len("json="):]
if jsonName != strs.JSONCamelCase(string(f.L0.FullName.Name())) { if jsonName != strs.JSONCamelCase(string(f.L0.FullName.Name())) {
f.L1.JSONName.Init(jsonName) f.L1.StringName.InitJSON(jsonName)
} }
case s == "packed": case s == "packed":
f.L1.HasPacked = true f.L1.HasPacked = true

View File

@ -32,7 +32,6 @@ type Encoder struct {
encoderState encoderState
indent string indent string
newline string // set to "\n" if len(indent) > 0
delims [2]byte delims [2]byte
outputASCII bool outputASCII bool
} }
@ -61,7 +60,6 @@ func NewEncoder(indent string, delims [2]byte, outputASCII bool) (*Encoder, erro
return nil, errors.New("indent may only be composed of space and tab characters") return nil, errors.New("indent may only be composed of space and tab characters")
} }
e.indent = indent e.indent = indent
e.newline = "\n"
} }
switch delims { switch delims {
case [2]byte{0, 0}: case [2]byte{0, 0}:
@ -126,7 +124,7 @@ func appendString(out []byte, in string, outputASCII bool) []byte {
// are used to represent both the proto string and bytes type. // are used to represent both the proto string and bytes type.
r = rune(in[0]) r = rune(in[0])
fallthrough fallthrough
case r < ' ' || r == '"' || r == '\\': case r < ' ' || r == '"' || r == '\\' || r == 0x7f:
out = append(out, '\\') out = append(out, '\\')
switch r { switch r {
case '"', '\\': case '"', '\\':
@ -143,7 +141,7 @@ func appendString(out []byte, in string, outputASCII bool) []byte {
out = strconv.AppendUint(out, uint64(r), 16) out = strconv.AppendUint(out, uint64(r), 16)
} }
in = in[n:] in = in[n:]
case outputASCII && r >= utf8.RuneSelf: case r >= utf8.RuneSelf && (outputASCII || r <= 0x009f):
out = append(out, '\\') out = append(out, '\\')
if r <= math.MaxUint16 { if r <= math.MaxUint16 {
out = append(out, 'u') out = append(out, 'u')
@ -168,7 +166,7 @@ func appendString(out []byte, in string, outputASCII bool) []byte {
// escaping. If no characters need escaping, this returns the input length. // escaping. If no characters need escaping, this returns the input length.
func indexNeedEscapeInString(s string) int { func indexNeedEscapeInString(s string) int {
for i := 0; i < len(s); i++ { for i := 0; i < len(s); i++ {
if c := s[i]; c < ' ' || c == '"' || c == '\'' || c == '\\' || c >= utf8.RuneSelf { if c := s[i]; c < ' ' || c == '"' || c == '\'' || c == '\\' || c >= 0x7f {
return i return i
} }
} }

View File

@ -1,13 +0,0 @@
// 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.
// Code generated by generate-protos. DO NOT EDIT.
package fieldnum
// Field numbers for google.protobuf.Any.
const (
Any_TypeUrl = 1 // optional string
Any_Value = 2 // optional bytes
)

View File

@ -1,35 +0,0 @@
// 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.
// Code generated by generate-protos. DO NOT EDIT.
package fieldnum
// Field numbers for google.protobuf.Api.
const (
Api_Name = 1 // optional string
Api_Methods = 2 // repeated google.protobuf.Method
Api_Options = 3 // repeated google.protobuf.Option
Api_Version = 4 // optional string
Api_SourceContext = 5 // optional google.protobuf.SourceContext
Api_Mixins = 6 // repeated google.protobuf.Mixin
Api_Syntax = 7 // optional google.protobuf.Syntax
)
// Field numbers for google.protobuf.Method.
const (
Method_Name = 1 // optional string
Method_RequestTypeUrl = 2 // optional string
Method_RequestStreaming = 3 // optional bool
Method_ResponseTypeUrl = 4 // optional string
Method_ResponseStreaming = 5 // optional bool
Method_Options = 6 // repeated google.protobuf.Option
Method_Syntax = 7 // optional google.protobuf.Syntax
)
// Field numbers for google.protobuf.Mixin.
const (
Mixin_Name = 1 // optional string
Mixin_Root = 2 // optional string
)

View File

@ -1,240 +0,0 @@
// 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.
// Code generated by generate-protos. DO NOT EDIT.
package fieldnum
// Field numbers for google.protobuf.FileDescriptorSet.
const (
FileDescriptorSet_File = 1 // repeated google.protobuf.FileDescriptorProto
)
// Field numbers for google.protobuf.FileDescriptorProto.
const (
FileDescriptorProto_Name = 1 // optional string
FileDescriptorProto_Package = 2 // optional string
FileDescriptorProto_Dependency = 3 // repeated string
FileDescriptorProto_PublicDependency = 10 // repeated int32
FileDescriptorProto_WeakDependency = 11 // repeated int32
FileDescriptorProto_MessageType = 4 // repeated google.protobuf.DescriptorProto
FileDescriptorProto_EnumType = 5 // repeated google.protobuf.EnumDescriptorProto
FileDescriptorProto_Service = 6 // repeated google.protobuf.ServiceDescriptorProto
FileDescriptorProto_Extension = 7 // repeated google.protobuf.FieldDescriptorProto
FileDescriptorProto_Options = 8 // optional google.protobuf.FileOptions
FileDescriptorProto_SourceCodeInfo = 9 // optional google.protobuf.SourceCodeInfo
FileDescriptorProto_Syntax = 12 // optional string
)
// Field numbers for google.protobuf.DescriptorProto.
const (
DescriptorProto_Name = 1 // optional string
DescriptorProto_Field = 2 // repeated google.protobuf.FieldDescriptorProto
DescriptorProto_Extension = 6 // repeated google.protobuf.FieldDescriptorProto
DescriptorProto_NestedType = 3 // repeated google.protobuf.DescriptorProto
DescriptorProto_EnumType = 4 // repeated google.protobuf.EnumDescriptorProto
DescriptorProto_ExtensionRange = 5 // repeated google.protobuf.DescriptorProto.ExtensionRange
DescriptorProto_OneofDecl = 8 // repeated google.protobuf.OneofDescriptorProto
DescriptorProto_Options = 7 // optional google.protobuf.MessageOptions
DescriptorProto_ReservedRange = 9 // repeated google.protobuf.DescriptorProto.ReservedRange
DescriptorProto_ReservedName = 10 // repeated string
)
// Field numbers for google.protobuf.DescriptorProto.ExtensionRange.
const (
DescriptorProto_ExtensionRange_Start = 1 // optional int32
DescriptorProto_ExtensionRange_End = 2 // optional int32
DescriptorProto_ExtensionRange_Options = 3 // optional google.protobuf.ExtensionRangeOptions
)
// Field numbers for google.protobuf.DescriptorProto.ReservedRange.
const (
DescriptorProto_ReservedRange_Start = 1 // optional int32
DescriptorProto_ReservedRange_End = 2 // optional int32
)
// Field numbers for google.protobuf.ExtensionRangeOptions.
const (
ExtensionRangeOptions_UninterpretedOption = 999 // repeated google.protobuf.UninterpretedOption
)
// Field numbers for google.protobuf.FieldDescriptorProto.
const (
FieldDescriptorProto_Name = 1 // optional string
FieldDescriptorProto_Number = 3 // optional int32
FieldDescriptorProto_Label = 4 // optional google.protobuf.FieldDescriptorProto.Label
FieldDescriptorProto_Type = 5 // optional google.protobuf.FieldDescriptorProto.Type
FieldDescriptorProto_TypeName = 6 // optional string
FieldDescriptorProto_Extendee = 2 // optional string
FieldDescriptorProto_DefaultValue = 7 // optional string
FieldDescriptorProto_OneofIndex = 9 // optional int32
FieldDescriptorProto_JsonName = 10 // optional string
FieldDescriptorProto_Options = 8 // optional google.protobuf.FieldOptions
FieldDescriptorProto_Proto3Optional = 17 // optional bool
)
// Field numbers for google.protobuf.OneofDescriptorProto.
const (
OneofDescriptorProto_Name = 1 // optional string
OneofDescriptorProto_Options = 2 // optional google.protobuf.OneofOptions
)
// Field numbers for google.protobuf.EnumDescriptorProto.
const (
EnumDescriptorProto_Name = 1 // optional string
EnumDescriptorProto_Value = 2 // repeated google.protobuf.EnumValueDescriptorProto
EnumDescriptorProto_Options = 3 // optional google.protobuf.EnumOptions
EnumDescriptorProto_ReservedRange = 4 // repeated google.protobuf.EnumDescriptorProto.EnumReservedRange
EnumDescriptorProto_ReservedName = 5 // repeated string
)
// Field numbers for google.protobuf.EnumDescriptorProto.EnumReservedRange.
const (
EnumDescriptorProto_EnumReservedRange_Start = 1 // optional int32
EnumDescriptorProto_EnumReservedRange_End = 2 // optional int32
)
// Field numbers for google.protobuf.EnumValueDescriptorProto.
const (
EnumValueDescriptorProto_Name = 1 // optional string
EnumValueDescriptorProto_Number = 2 // optional int32
EnumValueDescriptorProto_Options = 3 // optional google.protobuf.EnumValueOptions
)
// Field numbers for google.protobuf.ServiceDescriptorProto.
const (
ServiceDescriptorProto_Name = 1 // optional string
ServiceDescriptorProto_Method = 2 // repeated google.protobuf.MethodDescriptorProto
ServiceDescriptorProto_Options = 3 // optional google.protobuf.ServiceOptions
)
// Field numbers for google.protobuf.MethodDescriptorProto.
const (
MethodDescriptorProto_Name = 1 // optional string
MethodDescriptorProto_InputType = 2 // optional string
MethodDescriptorProto_OutputType = 3 // optional string
MethodDescriptorProto_Options = 4 // optional google.protobuf.MethodOptions
MethodDescriptorProto_ClientStreaming = 5 // optional bool
MethodDescriptorProto_ServerStreaming = 6 // optional bool
)
// Field numbers for google.protobuf.FileOptions.
const (
FileOptions_JavaPackage = 1 // optional string
FileOptions_JavaOuterClassname = 8 // optional string
FileOptions_JavaMultipleFiles = 10 // optional bool
FileOptions_JavaGenerateEqualsAndHash = 20 // optional bool
FileOptions_JavaStringCheckUtf8 = 27 // optional bool
FileOptions_OptimizeFor = 9 // optional google.protobuf.FileOptions.OptimizeMode
FileOptions_GoPackage = 11 // optional string
FileOptions_CcGenericServices = 16 // optional bool
FileOptions_JavaGenericServices = 17 // optional bool
FileOptions_PyGenericServices = 18 // optional bool
FileOptions_PhpGenericServices = 42 // optional bool
FileOptions_Deprecated = 23 // optional bool
FileOptions_CcEnableArenas = 31 // optional bool
FileOptions_ObjcClassPrefix = 36 // optional string
FileOptions_CsharpNamespace = 37 // optional string
FileOptions_SwiftPrefix = 39 // optional string
FileOptions_PhpClassPrefix = 40 // optional string
FileOptions_PhpNamespace = 41 // optional string
FileOptions_PhpMetadataNamespace = 44 // optional string
FileOptions_RubyPackage = 45 // optional string
FileOptions_UninterpretedOption = 999 // repeated google.protobuf.UninterpretedOption
)
// Field numbers for google.protobuf.MessageOptions.
const (
MessageOptions_MessageSetWireFormat = 1 // optional bool
MessageOptions_NoStandardDescriptorAccessor = 2 // optional bool
MessageOptions_Deprecated = 3 // optional bool
MessageOptions_MapEntry = 7 // optional bool
MessageOptions_UninterpretedOption = 999 // repeated google.protobuf.UninterpretedOption
)
// Field numbers for google.protobuf.FieldOptions.
const (
FieldOptions_Ctype = 1 // optional google.protobuf.FieldOptions.CType
FieldOptions_Packed = 2 // optional bool
FieldOptions_Jstype = 6 // optional google.protobuf.FieldOptions.JSType
FieldOptions_Lazy = 5 // optional bool
FieldOptions_Deprecated = 3 // optional bool
FieldOptions_Weak = 10 // optional bool
FieldOptions_UninterpretedOption = 999 // repeated google.protobuf.UninterpretedOption
)
// Field numbers for google.protobuf.OneofOptions.
const (
OneofOptions_UninterpretedOption = 999 // repeated google.protobuf.UninterpretedOption
)
// Field numbers for google.protobuf.EnumOptions.
const (
EnumOptions_AllowAlias = 2 // optional bool
EnumOptions_Deprecated = 3 // optional bool
EnumOptions_UninterpretedOption = 999 // repeated google.protobuf.UninterpretedOption
)
// Field numbers for google.protobuf.EnumValueOptions.
const (
EnumValueOptions_Deprecated = 1 // optional bool
EnumValueOptions_UninterpretedOption = 999 // repeated google.protobuf.UninterpretedOption
)
// Field numbers for google.protobuf.ServiceOptions.
const (
ServiceOptions_Deprecated = 33 // optional bool
ServiceOptions_UninterpretedOption = 999 // repeated google.protobuf.UninterpretedOption
)
// Field numbers for google.protobuf.MethodOptions.
const (
MethodOptions_Deprecated = 33 // optional bool
MethodOptions_IdempotencyLevel = 34 // optional google.protobuf.MethodOptions.IdempotencyLevel
MethodOptions_UninterpretedOption = 999 // repeated google.protobuf.UninterpretedOption
)
// Field numbers for google.protobuf.UninterpretedOption.
const (
UninterpretedOption_Name = 2 // repeated google.protobuf.UninterpretedOption.NamePart
UninterpretedOption_IdentifierValue = 3 // optional string
UninterpretedOption_PositiveIntValue = 4 // optional uint64
UninterpretedOption_NegativeIntValue = 5 // optional int64
UninterpretedOption_DoubleValue = 6 // optional double
UninterpretedOption_StringValue = 7 // optional bytes
UninterpretedOption_AggregateValue = 8 // optional string
)
// Field numbers for google.protobuf.UninterpretedOption.NamePart.
const (
UninterpretedOption_NamePart_NamePart = 1 // required string
UninterpretedOption_NamePart_IsExtension = 2 // required bool
)
// Field numbers for google.protobuf.SourceCodeInfo.
const (
SourceCodeInfo_Location = 1 // repeated google.protobuf.SourceCodeInfo.Location
)
// Field numbers for google.protobuf.SourceCodeInfo.Location.
const (
SourceCodeInfo_Location_Path = 1 // repeated int32
SourceCodeInfo_Location_Span = 2 // repeated int32
SourceCodeInfo_Location_LeadingComments = 3 // optional string
SourceCodeInfo_Location_TrailingComments = 4 // optional string
SourceCodeInfo_Location_LeadingDetachedComments = 6 // repeated string
)
// Field numbers for google.protobuf.GeneratedCodeInfo.
const (
GeneratedCodeInfo_Annotation = 1 // repeated google.protobuf.GeneratedCodeInfo.Annotation
)
// Field numbers for google.protobuf.GeneratedCodeInfo.Annotation.
const (
GeneratedCodeInfo_Annotation_Path = 1 // repeated int32
GeneratedCodeInfo_Annotation_SourceFile = 2 // optional string
GeneratedCodeInfo_Annotation_Begin = 3 // optional int32
GeneratedCodeInfo_Annotation_End = 4 // optional int32
)

View File

@ -1,7 +0,0 @@
// 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 fieldnum contains constants for field numbers of fields in messages
// declared in descriptor.proto and any of the well-known types.
package fieldnum

View File

@ -1,13 +0,0 @@
// 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.
// Code generated by generate-protos. DO NOT EDIT.
package fieldnum
// Field numbers for google.protobuf.Duration.
const (
Duration_Seconds = 1 // optional int64
Duration_Nanos = 2 // optional int32
)

View File

@ -1,10 +0,0 @@
// 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.
// Code generated by generate-protos. DO NOT EDIT.
package fieldnum
// Field numbers for google.protobuf.Empty.
const ()

View File

@ -1,12 +0,0 @@
// 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.
// Code generated by generate-protos. DO NOT EDIT.
package fieldnum
// Field numbers for google.protobuf.FieldMask.
const (
FieldMask_Paths = 1 // repeated string
)

View File

@ -1,12 +0,0 @@
// 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.
// Code generated by generate-protos. DO NOT EDIT.
package fieldnum
// Field numbers for google.protobuf.SourceContext.
const (
SourceContext_FileName = 1 // optional string
)

View File

@ -1,33 +0,0 @@
// 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.
// Code generated by generate-protos. DO NOT EDIT.
package fieldnum
// Field numbers for google.protobuf.Struct.
const (
Struct_Fields = 1 // repeated google.protobuf.Struct.FieldsEntry
)
// Field numbers for google.protobuf.Struct.FieldsEntry.
const (
Struct_FieldsEntry_Key = 1 // optional string
Struct_FieldsEntry_Value = 2 // optional google.protobuf.Value
)
// Field numbers for google.protobuf.Value.
const (
Value_NullValue = 1 // optional google.protobuf.NullValue
Value_NumberValue = 2 // optional double
Value_StringValue = 3 // optional string
Value_BoolValue = 4 // optional bool
Value_StructValue = 5 // optional google.protobuf.Struct
Value_ListValue = 6 // optional google.protobuf.ListValue
)
// Field numbers for google.protobuf.ListValue.
const (
ListValue_Values = 1 // repeated google.protobuf.Value
)

View File

@ -1,13 +0,0 @@
// 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.
// Code generated by generate-protos. DO NOT EDIT.
package fieldnum
// Field numbers for google.protobuf.Timestamp.
const (
Timestamp_Seconds = 1 // optional int64
Timestamp_Nanos = 2 // optional int32
)

View File

@ -1,53 +0,0 @@
// 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.
// Code generated by generate-protos. DO NOT EDIT.
package fieldnum
// Field numbers for google.protobuf.Type.
const (
Type_Name = 1 // optional string
Type_Fields = 2 // repeated google.protobuf.Field
Type_Oneofs = 3 // repeated string
Type_Options = 4 // repeated google.protobuf.Option
Type_SourceContext = 5 // optional google.protobuf.SourceContext
Type_Syntax = 6 // optional google.protobuf.Syntax
)
// Field numbers for google.protobuf.Field.
const (
Field_Kind = 1 // optional google.protobuf.Field.Kind
Field_Cardinality = 2 // optional google.protobuf.Field.Cardinality
Field_Number = 3 // optional int32
Field_Name = 4 // optional string
Field_TypeUrl = 6 // optional string
Field_OneofIndex = 7 // optional int32
Field_Packed = 8 // optional bool
Field_Options = 9 // repeated google.protobuf.Option
Field_JsonName = 10 // optional string
Field_DefaultValue = 11 // optional string
)
// Field numbers for google.protobuf.Enum.
const (
Enum_Name = 1 // optional string
Enum_Enumvalue = 2 // repeated google.protobuf.EnumValue
Enum_Options = 3 // repeated google.protobuf.Option
Enum_SourceContext = 4 // optional google.protobuf.SourceContext
Enum_Syntax = 5 // optional google.protobuf.Syntax
)
// Field numbers for google.protobuf.EnumValue.
const (
EnumValue_Name = 1 // optional string
EnumValue_Number = 2 // optional int32
EnumValue_Options = 3 // repeated google.protobuf.Option
)
// Field numbers for google.protobuf.Option.
const (
Option_Name = 1 // optional string
Option_Value = 2 // optional google.protobuf.Any
)

View File

@ -1,52 +0,0 @@
// 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.
// Code generated by generate-protos. DO NOT EDIT.
package fieldnum
// Field numbers for google.protobuf.DoubleValue.
const (
DoubleValue_Value = 1 // optional double
)
// Field numbers for google.protobuf.FloatValue.
const (
FloatValue_Value = 1 // optional float
)
// Field numbers for google.protobuf.Int64Value.
const (
Int64Value_Value = 1 // optional int64
)
// Field numbers for google.protobuf.UInt64Value.
const (
UInt64Value_Value = 1 // optional uint64
)
// Field numbers for google.protobuf.Int32Value.
const (
Int32Value_Value = 1 // optional int32
)
// Field numbers for google.protobuf.UInt32Value.
const (
UInt32Value_Value = 1 // optional uint32
)
// Field numbers for google.protobuf.BoolValue.
const (
BoolValue_Value = 1 // optional bool
)
// Field numbers for google.protobuf.StringValue.
const (
StringValue_Value = 1 // optional string
)
// Field numbers for google.protobuf.BytesValue.
const (
BytesValue_Value = 1 // optional bytes
)

View File

@ -1,40 +0,0 @@
// 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 fieldsort defines an ordering of fields.
//
// The ordering defined by this package matches the historic behavior of the proto
// package, placing extensions first and oneofs last.
//
// There is no guarantee about stability of the wire encoding, and users should not
// depend on the order defined in this package as it is subject to change without
// notice.
package fieldsort
import (
"google.golang.org/protobuf/reflect/protoreflect"
)
// Less returns true if field a comes before field j in ordered wire marshal output.
func Less(a, b protoreflect.FieldDescriptor) bool {
ea := a.IsExtension()
eb := b.IsExtension()
oa := a.ContainingOneof()
ob := b.ContainingOneof()
switch {
case ea != eb:
return ea
case oa != nil && ob != nil:
if oa == ob {
return a.Number() < b.Number()
}
return oa.Index() < ob.Index()
case oa != nil && !oa.IsSynthetic():
return false
case ob != nil && !ob.IsSynthetic():
return true
default:
return a.Number() < b.Number()
}
}

View File

@ -3,11 +3,14 @@
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// Package filedesc provides functionality for constructing descriptors. // Package filedesc provides functionality for constructing descriptors.
//
// The types in this package implement interfaces in the protoreflect package
// related to protobuf descripriptors.
package filedesc package filedesc
import ( import (
"google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/encoding/protowire"
"google.golang.org/protobuf/internal/fieldnum" "google.golang.org/protobuf/internal/genid"
"google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/reflect/protoreflect"
pref "google.golang.org/protobuf/reflect/protoreflect" pref "google.golang.org/protobuf/reflect/protoreflect"
preg "google.golang.org/protobuf/reflect/protoregistry" preg "google.golang.org/protobuf/reflect/protoregistry"
@ -126,24 +129,24 @@ func (db *Builder) unmarshalCounts(b []byte, isFile bool) {
b = b[m:] b = b[m:]
if isFile { if isFile {
switch num { switch num {
case fieldnum.FileDescriptorProto_EnumType: case genid.FileDescriptorProto_EnumType_field_number:
db.NumEnums++ db.NumEnums++
case fieldnum.FileDescriptorProto_MessageType: case genid.FileDescriptorProto_MessageType_field_number:
db.unmarshalCounts(v, false) db.unmarshalCounts(v, false)
db.NumMessages++ db.NumMessages++
case fieldnum.FileDescriptorProto_Extension: case genid.FileDescriptorProto_Extension_field_number:
db.NumExtensions++ db.NumExtensions++
case fieldnum.FileDescriptorProto_Service: case genid.FileDescriptorProto_Service_field_number:
db.NumServices++ db.NumServices++
} }
} else { } else {
switch num { switch num {
case fieldnum.DescriptorProto_EnumType: case genid.DescriptorProto_EnumType_field_number:
db.NumEnums++ db.NumEnums++
case fieldnum.DescriptorProto_NestedType: case genid.DescriptorProto_NestedType_field_number:
db.unmarshalCounts(v, false) db.unmarshalCounts(v, false)
db.NumMessages++ db.NumMessages++
case fieldnum.DescriptorProto_Extension: case genid.DescriptorProto_Extension_field_number:
db.NumExtensions++ db.NumExtensions++
} }
} }

View File

@ -13,6 +13,8 @@ import (
"google.golang.org/protobuf/internal/descfmt" "google.golang.org/protobuf/internal/descfmt"
"google.golang.org/protobuf/internal/descopts" "google.golang.org/protobuf/internal/descopts"
"google.golang.org/protobuf/internal/encoding/defval" "google.golang.org/protobuf/internal/encoding/defval"
"google.golang.org/protobuf/internal/encoding/messageset"
"google.golang.org/protobuf/internal/genid"
"google.golang.org/protobuf/internal/pragma" "google.golang.org/protobuf/internal/pragma"
"google.golang.org/protobuf/internal/strs" "google.golang.org/protobuf/internal/strs"
pref "google.golang.org/protobuf/reflect/protoreflect" pref "google.golang.org/protobuf/reflect/protoreflect"
@ -98,15 +100,6 @@ func (fd *File) lazyInitOnce() {
fd.mu.Unlock() fd.mu.Unlock()
} }
// ProtoLegacyRawDesc is a pseudo-internal API for allowing the v1 code
// to be able to retrieve the raw descriptor.
//
// WARNING: This method is exempt from the compatibility promise and may be
// removed in the future without warning.
func (fd *File) ProtoLegacyRawDesc() []byte {
return fd.builder.RawDescriptor
}
// GoPackagePath is a pseudo-internal API for determining the Go package path // GoPackagePath is a pseudo-internal API for determining the Go package path
// that this file descriptor is declared in. // that this file descriptor is declared in.
// //
@ -206,7 +199,7 @@ type (
Number pref.FieldNumber Number pref.FieldNumber
Cardinality pref.Cardinality // must be consistent with Message.RequiredNumbers Cardinality pref.Cardinality // must be consistent with Message.RequiredNumbers
Kind pref.Kind Kind pref.Kind
JSONName jsonName StringName stringName
IsProto3Optional bool // promoted from google.protobuf.FieldDescriptorProto IsProto3Optional bool // promoted from google.protobuf.FieldDescriptorProto
IsWeak bool // promoted from google.protobuf.FieldOptions IsWeak bool // promoted from google.protobuf.FieldOptions
HasPacked bool // promoted from google.protobuf.FieldOptions HasPacked bool // promoted from google.protobuf.FieldOptions
@ -276,8 +269,9 @@ func (fd *Field) Options() pref.ProtoMessage {
func (fd *Field) Number() pref.FieldNumber { return fd.L1.Number } func (fd *Field) Number() pref.FieldNumber { return fd.L1.Number }
func (fd *Field) Cardinality() pref.Cardinality { return fd.L1.Cardinality } func (fd *Field) Cardinality() pref.Cardinality { return fd.L1.Cardinality }
func (fd *Field) Kind() pref.Kind { return fd.L1.Kind } func (fd *Field) Kind() pref.Kind { return fd.L1.Kind }
func (fd *Field) HasJSONName() bool { return fd.L1.JSONName.has } func (fd *Field) HasJSONName() bool { return fd.L1.StringName.hasJSON }
func (fd *Field) JSONName() string { return fd.L1.JSONName.get(fd) } func (fd *Field) JSONName() string { return fd.L1.StringName.getJSON(fd) }
func (fd *Field) TextName() string { return fd.L1.StringName.getText(fd) }
func (fd *Field) HasPresence() bool { func (fd *Field) HasPresence() bool {
return fd.L1.Cardinality != pref.Repeated && (fd.L0.ParentFile.L1.Syntax == pref.Proto2 || fd.L1.Message != nil || fd.L1.ContainingOneof != nil) return fd.L1.Cardinality != pref.Repeated && (fd.L0.ParentFile.L1.Syntax == pref.Proto2 || fd.L1.Message != nil || fd.L1.ContainingOneof != nil)
} }
@ -302,13 +296,13 @@ func (fd *Field) MapKey() pref.FieldDescriptor {
if !fd.IsMap() { if !fd.IsMap() {
return nil return nil
} }
return fd.Message().Fields().ByNumber(1) return fd.Message().Fields().ByNumber(genid.MapEntry_Key_field_number)
} }
func (fd *Field) MapValue() pref.FieldDescriptor { func (fd *Field) MapValue() pref.FieldDescriptor {
if !fd.IsMap() { if !fd.IsMap() {
return nil return nil
} }
return fd.Message().Fields().ByNumber(2) return fd.Message().Fields().ByNumber(genid.MapEntry_Value_field_number)
} }
func (fd *Field) HasDefault() bool { return fd.L1.Default.has } func (fd *Field) HasDefault() bool { return fd.L1.Default.has }
func (fd *Field) Default() pref.Value { return fd.L1.Default.get(fd) } func (fd *Field) Default() pref.Value { return fd.L1.Default.get(fd) }
@ -372,7 +366,7 @@ type (
} }
ExtensionL2 struct { ExtensionL2 struct {
Options func() pref.ProtoMessage Options func() pref.ProtoMessage
JSONName jsonName StringName stringName
IsProto3Optional bool // promoted from google.protobuf.FieldDescriptorProto IsProto3Optional bool // promoted from google.protobuf.FieldDescriptorProto
IsPacked bool // promoted from google.protobuf.FieldOptions IsPacked bool // promoted from google.protobuf.FieldOptions
Default defaultValue Default defaultValue
@ -390,8 +384,9 @@ func (xd *Extension) Options() pref.ProtoMessage {
func (xd *Extension) Number() pref.FieldNumber { return xd.L1.Number } func (xd *Extension) Number() pref.FieldNumber { return xd.L1.Number }
func (xd *Extension) Cardinality() pref.Cardinality { return xd.L1.Cardinality } func (xd *Extension) Cardinality() pref.Cardinality { return xd.L1.Cardinality }
func (xd *Extension) Kind() pref.Kind { return xd.L1.Kind } func (xd *Extension) Kind() pref.Kind { return xd.L1.Kind }
func (xd *Extension) HasJSONName() bool { return xd.lazyInit().JSONName.has } func (xd *Extension) HasJSONName() bool { return xd.lazyInit().StringName.hasJSON }
func (xd *Extension) JSONName() string { return xd.lazyInit().JSONName.get(xd) } func (xd *Extension) JSONName() string { return xd.lazyInit().StringName.getJSON(xd) }
func (xd *Extension) TextName() string { return xd.lazyInit().StringName.getText(xd) }
func (xd *Extension) HasPresence() bool { return xd.L1.Cardinality != pref.Repeated } func (xd *Extension) HasPresence() bool { return xd.L1.Cardinality != pref.Repeated }
func (xd *Extension) HasOptionalKeyword() bool { func (xd *Extension) HasOptionalKeyword() bool {
return (xd.L0.ParentFile.L1.Syntax == pref.Proto2 && xd.L1.Cardinality == pref.Optional) || xd.lazyInit().IsProto3Optional return (xd.L0.ParentFile.L1.Syntax == pref.Proto2 && xd.L1.Cardinality == pref.Optional) || xd.lazyInit().IsProto3Optional
@ -505,27 +500,50 @@ func (d *Base) Syntax() pref.Syntax { return d.L0.ParentFile.Syn
func (d *Base) IsPlaceholder() bool { return false } func (d *Base) IsPlaceholder() bool { return false }
func (d *Base) ProtoInternal(pragma.DoNotImplement) {} func (d *Base) ProtoInternal(pragma.DoNotImplement) {}
type jsonName struct { type stringName struct {
has bool hasJSON bool
once sync.Once once sync.Once
name string nameJSON string
nameText string
} }
// Init initializes the name. It is exported for use by other internal packages. // InitJSON initializes the name. It is exported for use by other internal packages.
func (js *jsonName) Init(s string) { func (s *stringName) InitJSON(name string) {
js.has = true s.hasJSON = true
js.name = s s.nameJSON = name
} }
func (js *jsonName) get(fd pref.FieldDescriptor) string { func (s *stringName) lazyInit(fd pref.FieldDescriptor) *stringName {
if !js.has { s.once.Do(func() {
js.once.Do(func() { if fd.IsExtension() {
js.name = strs.JSONCamelCase(string(fd.Name())) // For extensions, JSON and text are formatted the same way.
}) var name string
} if messageset.IsMessageSetExtension(fd) {
return js.name name = string("[" + fd.FullName().Parent() + "]")
} else {
name = string("[" + fd.FullName() + "]")
}
s.nameJSON = name
s.nameText = name
} else {
// Format the JSON name.
if !s.hasJSON {
s.nameJSON = strs.JSONCamelCase(string(fd.Name()))
}
// Format the text name.
s.nameText = string(fd.Name())
if fd.Kind() == pref.GroupKind {
s.nameText = string(fd.Message().Name())
}
}
})
return s
} }
func (s *stringName) getJSON(fd pref.FieldDescriptor) string { return s.lazyInit(fd).nameJSON }
func (s *stringName) getText(fd pref.FieldDescriptor) string { return s.lazyInit(fd).nameText }
func DefaultValue(v pref.Value, ev pref.EnumValueDescriptor) defaultValue { func DefaultValue(v pref.Value, ev pref.EnumValueDescriptor) defaultValue {
dv := defaultValue{has: v.IsValid(), val: v, enum: ev} dv := defaultValue{has: v.IsValid(), val: v, enum: ev}
if b, ok := v.Interface().([]byte); ok { if b, ok := v.Interface().([]byte); ok {

View File

@ -8,7 +8,7 @@ import (
"sync" "sync"
"google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/encoding/protowire"
"google.golang.org/protobuf/internal/fieldnum" "google.golang.org/protobuf/internal/genid"
"google.golang.org/protobuf/internal/strs" "google.golang.org/protobuf/internal/strs"
pref "google.golang.org/protobuf/reflect/protoreflect" pref "google.golang.org/protobuf/reflect/protoreflect"
) )
@ -107,7 +107,7 @@ func (fd *File) unmarshalSeed(b []byte) {
v, m := protowire.ConsumeBytes(b) v, m := protowire.ConsumeBytes(b)
b = b[m:] b = b[m:]
switch num { switch num {
case fieldnum.FileDescriptorProto_Syntax: case genid.FileDescriptorProto_Syntax_field_number:
switch string(v) { switch string(v) {
case "proto2": case "proto2":
fd.L1.Syntax = pref.Proto2 fd.L1.Syntax = pref.Proto2
@ -116,36 +116,36 @@ func (fd *File) unmarshalSeed(b []byte) {
default: default:
panic("invalid syntax") panic("invalid syntax")
} }
case fieldnum.FileDescriptorProto_Name: case genid.FileDescriptorProto_Name_field_number:
fd.L1.Path = sb.MakeString(v) fd.L1.Path = sb.MakeString(v)
case fieldnum.FileDescriptorProto_Package: case genid.FileDescriptorProto_Package_field_number:
fd.L1.Package = pref.FullName(sb.MakeString(v)) fd.L1.Package = pref.FullName(sb.MakeString(v))
case fieldnum.FileDescriptorProto_EnumType: case genid.FileDescriptorProto_EnumType_field_number:
if prevField != fieldnum.FileDescriptorProto_EnumType { if prevField != genid.FileDescriptorProto_EnumType_field_number {
if numEnums > 0 { if numEnums > 0 {
panic("non-contiguous repeated field") panic("non-contiguous repeated field")
} }
posEnums = len(b0) - len(b) - n - m posEnums = len(b0) - len(b) - n - m
} }
numEnums++ numEnums++
case fieldnum.FileDescriptorProto_MessageType: case genid.FileDescriptorProto_MessageType_field_number:
if prevField != fieldnum.FileDescriptorProto_MessageType { if prevField != genid.FileDescriptorProto_MessageType_field_number {
if numMessages > 0 { if numMessages > 0 {
panic("non-contiguous repeated field") panic("non-contiguous repeated field")
} }
posMessages = len(b0) - len(b) - n - m posMessages = len(b0) - len(b) - n - m
} }
numMessages++ numMessages++
case fieldnum.FileDescriptorProto_Extension: case genid.FileDescriptorProto_Extension_field_number:
if prevField != fieldnum.FileDescriptorProto_Extension { if prevField != genid.FileDescriptorProto_Extension_field_number {
if numExtensions > 0 { if numExtensions > 0 {
panic("non-contiguous repeated field") panic("non-contiguous repeated field")
} }
posExtensions = len(b0) - len(b) - n - m posExtensions = len(b0) - len(b) - n - m
} }
numExtensions++ numExtensions++
case fieldnum.FileDescriptorProto_Service: case genid.FileDescriptorProto_Service_field_number:
if prevField != fieldnum.FileDescriptorProto_Service { if prevField != genid.FileDescriptorProto_Service_field_number {
if numServices > 0 { if numServices > 0 {
panic("non-contiguous repeated field") panic("non-contiguous repeated field")
} }
@ -233,9 +233,9 @@ func (ed *Enum) unmarshalSeed(b []byte, sb *strs.Builder, pf *File, pd pref.Desc
v, m := protowire.ConsumeBytes(b) v, m := protowire.ConsumeBytes(b)
b = b[m:] b = b[m:]
switch num { switch num {
case fieldnum.EnumDescriptorProto_Name: case genid.EnumDescriptorProto_Name_field_number:
ed.L0.FullName = appendFullName(sb, pd.FullName(), v) ed.L0.FullName = appendFullName(sb, pd.FullName(), v)
case fieldnum.EnumDescriptorProto_Value: case genid.EnumDescriptorProto_Value_field_number:
numValues++ numValues++
} }
default: default:
@ -260,7 +260,7 @@ func (ed *Enum) unmarshalSeed(b []byte, sb *strs.Builder, pf *File, pd pref.Desc
v, m := protowire.ConsumeBytes(b) v, m := protowire.ConsumeBytes(b)
b = b[m:] b = b[m:]
switch num { switch num {
case fieldnum.EnumDescriptorProto_Value: case genid.EnumDescriptorProto_Value_field_number:
ed.L2.Values.List[i].unmarshalFull(v, sb, pf, ed, i) ed.L2.Values.List[i].unmarshalFull(v, sb, pf, ed, i)
i++ i++
} }
@ -288,33 +288,33 @@ func (md *Message) unmarshalSeed(b []byte, sb *strs.Builder, pf *File, pd pref.D
v, m := protowire.ConsumeBytes(b) v, m := protowire.ConsumeBytes(b)
b = b[m:] b = b[m:]
switch num { switch num {
case fieldnum.DescriptorProto_Name: case genid.DescriptorProto_Name_field_number:
md.L0.FullName = appendFullName(sb, pd.FullName(), v) md.L0.FullName = appendFullName(sb, pd.FullName(), v)
case fieldnum.DescriptorProto_EnumType: case genid.DescriptorProto_EnumType_field_number:
if prevField != fieldnum.DescriptorProto_EnumType { if prevField != genid.DescriptorProto_EnumType_field_number {
if numEnums > 0 { if numEnums > 0 {
panic("non-contiguous repeated field") panic("non-contiguous repeated field")
} }
posEnums = len(b0) - len(b) - n - m posEnums = len(b0) - len(b) - n - m
} }
numEnums++ numEnums++
case fieldnum.DescriptorProto_NestedType: case genid.DescriptorProto_NestedType_field_number:
if prevField != fieldnum.DescriptorProto_NestedType { if prevField != genid.DescriptorProto_NestedType_field_number {
if numMessages > 0 { if numMessages > 0 {
panic("non-contiguous repeated field") panic("non-contiguous repeated field")
} }
posMessages = len(b0) - len(b) - n - m posMessages = len(b0) - len(b) - n - m
} }
numMessages++ numMessages++
case fieldnum.DescriptorProto_Extension: case genid.DescriptorProto_Extension_field_number:
if prevField != fieldnum.DescriptorProto_Extension { if prevField != genid.DescriptorProto_Extension_field_number {
if numExtensions > 0 { if numExtensions > 0 {
panic("non-contiguous repeated field") panic("non-contiguous repeated field")
} }
posExtensions = len(b0) - len(b) - n - m posExtensions = len(b0) - len(b) - n - m
} }
numExtensions++ numExtensions++
case fieldnum.DescriptorProto_Options: case genid.DescriptorProto_Options_field_number:
md.unmarshalSeedOptions(v) md.unmarshalSeedOptions(v)
} }
prevField = num prevField = num
@ -375,9 +375,9 @@ func (md *Message) unmarshalSeedOptions(b []byte) {
v, m := protowire.ConsumeVarint(b) v, m := protowire.ConsumeVarint(b)
b = b[m:] b = b[m:]
switch num { switch num {
case fieldnum.MessageOptions_MapEntry: case genid.MessageOptions_MapEntry_field_number:
md.L1.IsMapEntry = protowire.DecodeBool(v) md.L1.IsMapEntry = protowire.DecodeBool(v)
case fieldnum.MessageOptions_MessageSetWireFormat: case genid.MessageOptions_MessageSetWireFormat_field_number:
md.L1.IsMessageSet = protowire.DecodeBool(v) md.L1.IsMessageSet = protowire.DecodeBool(v)
} }
default: default:
@ -400,20 +400,20 @@ func (xd *Extension) unmarshalSeed(b []byte, sb *strs.Builder, pf *File, pd pref
v, m := protowire.ConsumeVarint(b) v, m := protowire.ConsumeVarint(b)
b = b[m:] b = b[m:]
switch num { switch num {
case fieldnum.FieldDescriptorProto_Number: case genid.FieldDescriptorProto_Number_field_number:
xd.L1.Number = pref.FieldNumber(v) xd.L1.Number = pref.FieldNumber(v)
case fieldnum.FieldDescriptorProto_Label: case genid.FieldDescriptorProto_Label_field_number:
xd.L1.Cardinality = pref.Cardinality(v) xd.L1.Cardinality = pref.Cardinality(v)
case fieldnum.FieldDescriptorProto_Type: case genid.FieldDescriptorProto_Type_field_number:
xd.L1.Kind = pref.Kind(v) xd.L1.Kind = pref.Kind(v)
} }
case protowire.BytesType: case protowire.BytesType:
v, m := protowire.ConsumeBytes(b) v, m := protowire.ConsumeBytes(b)
b = b[m:] b = b[m:]
switch num { switch num {
case fieldnum.FieldDescriptorProto_Name: case genid.FieldDescriptorProto_Name_field_number:
xd.L0.FullName = appendFullName(sb, pd.FullName(), v) xd.L0.FullName = appendFullName(sb, pd.FullName(), v)
case fieldnum.FieldDescriptorProto_Extendee: case genid.FieldDescriptorProto_Extendee_field_number:
xd.L1.Extendee = PlaceholderMessage(makeFullName(sb, v)) xd.L1.Extendee = PlaceholderMessage(makeFullName(sb, v))
} }
default: default:
@ -436,7 +436,7 @@ func (sd *Service) unmarshalSeed(b []byte, sb *strs.Builder, pf *File, pd pref.D
v, m := protowire.ConsumeBytes(b) v, m := protowire.ConsumeBytes(b)
b = b[m:] b = b[m:]
switch num { switch num {
case fieldnum.ServiceDescriptorProto_Name: case genid.ServiceDescriptorProto_Name_field_number:
sd.L0.FullName = appendFullName(sb, pd.FullName(), v) sd.L0.FullName = appendFullName(sb, pd.FullName(), v)
} }
default: default:

View File

@ -10,7 +10,7 @@ import (
"google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/encoding/protowire"
"google.golang.org/protobuf/internal/descopts" "google.golang.org/protobuf/internal/descopts"
"google.golang.org/protobuf/internal/fieldnum" "google.golang.org/protobuf/internal/genid"
"google.golang.org/protobuf/internal/strs" "google.golang.org/protobuf/internal/strs"
"google.golang.org/protobuf/proto" "google.golang.org/protobuf/proto"
pref "google.golang.org/protobuf/reflect/protoreflect" pref "google.golang.org/protobuf/reflect/protoreflect"
@ -143,35 +143,35 @@ func (fd *File) unmarshalFull(b []byte) {
v, m := protowire.ConsumeVarint(b) v, m := protowire.ConsumeVarint(b)
b = b[m:] b = b[m:]
switch num { switch num {
case fieldnum.FileDescriptorProto_PublicDependency: case genid.FileDescriptorProto_PublicDependency_field_number:
fd.L2.Imports[v].IsPublic = true fd.L2.Imports[v].IsPublic = true
case fieldnum.FileDescriptorProto_WeakDependency: case genid.FileDescriptorProto_WeakDependency_field_number:
fd.L2.Imports[v].IsWeak = true fd.L2.Imports[v].IsWeak = true
} }
case protowire.BytesType: case protowire.BytesType:
v, m := protowire.ConsumeBytes(b) v, m := protowire.ConsumeBytes(b)
b = b[m:] b = b[m:]
switch num { switch num {
case fieldnum.FileDescriptorProto_Dependency: case genid.FileDescriptorProto_Dependency_field_number:
path := sb.MakeString(v) path := sb.MakeString(v)
imp, _ := fd.builder.FileRegistry.FindFileByPath(path) imp, _ := fd.builder.FileRegistry.FindFileByPath(path)
if imp == nil { if imp == nil {
imp = PlaceholderFile(path) imp = PlaceholderFile(path)
} }
fd.L2.Imports = append(fd.L2.Imports, pref.FileImport{FileDescriptor: imp}) fd.L2.Imports = append(fd.L2.Imports, pref.FileImport{FileDescriptor: imp})
case fieldnum.FileDescriptorProto_EnumType: case genid.FileDescriptorProto_EnumType_field_number:
fd.L1.Enums.List[enumIdx].unmarshalFull(v, sb) fd.L1.Enums.List[enumIdx].unmarshalFull(v, sb)
enumIdx++ enumIdx++
case fieldnum.FileDescriptorProto_MessageType: case genid.FileDescriptorProto_MessageType_field_number:
fd.L1.Messages.List[messageIdx].unmarshalFull(v, sb) fd.L1.Messages.List[messageIdx].unmarshalFull(v, sb)
messageIdx++ messageIdx++
case fieldnum.FileDescriptorProto_Extension: case genid.FileDescriptorProto_Extension_field_number:
fd.L1.Extensions.List[extensionIdx].unmarshalFull(v, sb) fd.L1.Extensions.List[extensionIdx].unmarshalFull(v, sb)
extensionIdx++ extensionIdx++
case fieldnum.FileDescriptorProto_Service: case genid.FileDescriptorProto_Service_field_number:
fd.L1.Services.List[serviceIdx].unmarshalFull(v, sb) fd.L1.Services.List[serviceIdx].unmarshalFull(v, sb)
serviceIdx++ serviceIdx++
case fieldnum.FileDescriptorProto_Options: case genid.FileDescriptorProto_Options_field_number:
rawOptions = appendOptions(rawOptions, v) rawOptions = appendOptions(rawOptions, v)
} }
default: default:
@ -196,13 +196,13 @@ func (ed *Enum) unmarshalFull(b []byte, sb *strs.Builder) {
v, m := protowire.ConsumeBytes(b) v, m := protowire.ConsumeBytes(b)
b = b[m:] b = b[m:]
switch num { switch num {
case fieldnum.EnumDescriptorProto_Value: case genid.EnumDescriptorProto_Value_field_number:
rawValues = append(rawValues, v) rawValues = append(rawValues, v)
case fieldnum.EnumDescriptorProto_ReservedName: case genid.EnumDescriptorProto_ReservedName_field_number:
ed.L2.ReservedNames.List = append(ed.L2.ReservedNames.List, pref.Name(sb.MakeString(v))) ed.L2.ReservedNames.List = append(ed.L2.ReservedNames.List, pref.Name(sb.MakeString(v)))
case fieldnum.EnumDescriptorProto_ReservedRange: case genid.EnumDescriptorProto_ReservedRange_field_number:
ed.L2.ReservedRanges.List = append(ed.L2.ReservedRanges.List, unmarshalEnumReservedRange(v)) ed.L2.ReservedRanges.List = append(ed.L2.ReservedRanges.List, unmarshalEnumReservedRange(v))
case fieldnum.EnumDescriptorProto_Options: case genid.EnumDescriptorProto_Options_field_number:
rawOptions = appendOptions(rawOptions, v) rawOptions = appendOptions(rawOptions, v)
} }
default: default:
@ -228,9 +228,9 @@ func unmarshalEnumReservedRange(b []byte) (r [2]pref.EnumNumber) {
v, m := protowire.ConsumeVarint(b) v, m := protowire.ConsumeVarint(b)
b = b[m:] b = b[m:]
switch num { switch num {
case fieldnum.EnumDescriptorProto_EnumReservedRange_Start: case genid.EnumDescriptorProto_EnumReservedRange_Start_field_number:
r[0] = pref.EnumNumber(v) r[0] = pref.EnumNumber(v)
case fieldnum.EnumDescriptorProto_EnumReservedRange_End: case genid.EnumDescriptorProto_EnumReservedRange_End_field_number:
r[1] = pref.EnumNumber(v) r[1] = pref.EnumNumber(v)
} }
default: default:
@ -255,17 +255,17 @@ func (vd *EnumValue) unmarshalFull(b []byte, sb *strs.Builder, pf *File, pd pref
v, m := protowire.ConsumeVarint(b) v, m := protowire.ConsumeVarint(b)
b = b[m:] b = b[m:]
switch num { switch num {
case fieldnum.EnumValueDescriptorProto_Number: case genid.EnumValueDescriptorProto_Number_field_number:
vd.L1.Number = pref.EnumNumber(v) vd.L1.Number = pref.EnumNumber(v)
} }
case protowire.BytesType: case protowire.BytesType:
v, m := protowire.ConsumeBytes(b) v, m := protowire.ConsumeBytes(b)
b = b[m:] b = b[m:]
switch num { switch num {
case fieldnum.EnumValueDescriptorProto_Name: case genid.EnumValueDescriptorProto_Name_field_number:
// NOTE: Enum values are in the same scope as the enum parent. // NOTE: Enum values are in the same scope as the enum parent.
vd.L0.FullName = appendFullName(sb, pd.Parent().FullName(), v) vd.L0.FullName = appendFullName(sb, pd.Parent().FullName(), v)
case fieldnum.EnumValueDescriptorProto_Options: case genid.EnumValueDescriptorProto_Options_field_number:
rawOptions = appendOptions(rawOptions, v) rawOptions = appendOptions(rawOptions, v)
} }
default: default:
@ -289,29 +289,29 @@ func (md *Message) unmarshalFull(b []byte, sb *strs.Builder) {
v, m := protowire.ConsumeBytes(b) v, m := protowire.ConsumeBytes(b)
b = b[m:] b = b[m:]
switch num { switch num {
case fieldnum.DescriptorProto_Field: case genid.DescriptorProto_Field_field_number:
rawFields = append(rawFields, v) rawFields = append(rawFields, v)
case fieldnum.DescriptorProto_OneofDecl: case genid.DescriptorProto_OneofDecl_field_number:
rawOneofs = append(rawOneofs, v) rawOneofs = append(rawOneofs, v)
case fieldnum.DescriptorProto_ReservedName: case genid.DescriptorProto_ReservedName_field_number:
md.L2.ReservedNames.List = append(md.L2.ReservedNames.List, pref.Name(sb.MakeString(v))) md.L2.ReservedNames.List = append(md.L2.ReservedNames.List, pref.Name(sb.MakeString(v)))
case fieldnum.DescriptorProto_ReservedRange: case genid.DescriptorProto_ReservedRange_field_number:
md.L2.ReservedRanges.List = append(md.L2.ReservedRanges.List, unmarshalMessageReservedRange(v)) md.L2.ReservedRanges.List = append(md.L2.ReservedRanges.List, unmarshalMessageReservedRange(v))
case fieldnum.DescriptorProto_ExtensionRange: case genid.DescriptorProto_ExtensionRange_field_number:
r, rawOptions := unmarshalMessageExtensionRange(v) r, rawOptions := unmarshalMessageExtensionRange(v)
opts := md.L0.ParentFile.builder.optionsUnmarshaler(&descopts.ExtensionRange, rawOptions) opts := md.L0.ParentFile.builder.optionsUnmarshaler(&descopts.ExtensionRange, rawOptions)
md.L2.ExtensionRanges.List = append(md.L2.ExtensionRanges.List, r) md.L2.ExtensionRanges.List = append(md.L2.ExtensionRanges.List, r)
md.L2.ExtensionRangeOptions = append(md.L2.ExtensionRangeOptions, opts) md.L2.ExtensionRangeOptions = append(md.L2.ExtensionRangeOptions, opts)
case fieldnum.DescriptorProto_EnumType: case genid.DescriptorProto_EnumType_field_number:
md.L1.Enums.List[enumIdx].unmarshalFull(v, sb) md.L1.Enums.List[enumIdx].unmarshalFull(v, sb)
enumIdx++ enumIdx++
case fieldnum.DescriptorProto_NestedType: case genid.DescriptorProto_NestedType_field_number:
md.L1.Messages.List[messageIdx].unmarshalFull(v, sb) md.L1.Messages.List[messageIdx].unmarshalFull(v, sb)
messageIdx++ messageIdx++
case fieldnum.DescriptorProto_Extension: case genid.DescriptorProto_Extension_field_number:
md.L1.Extensions.List[extensionIdx].unmarshalFull(v, sb) md.L1.Extensions.List[extensionIdx].unmarshalFull(v, sb)
extensionIdx++ extensionIdx++
case fieldnum.DescriptorProto_Options: case genid.DescriptorProto_Options_field_number:
md.unmarshalOptions(v) md.unmarshalOptions(v)
rawOptions = appendOptions(rawOptions, v) rawOptions = appendOptions(rawOptions, v)
} }
@ -347,9 +347,9 @@ func (md *Message) unmarshalOptions(b []byte) {
v, m := protowire.ConsumeVarint(b) v, m := protowire.ConsumeVarint(b)
b = b[m:] b = b[m:]
switch num { switch num {
case fieldnum.MessageOptions_MapEntry: case genid.MessageOptions_MapEntry_field_number:
md.L1.IsMapEntry = protowire.DecodeBool(v) md.L1.IsMapEntry = protowire.DecodeBool(v)
case fieldnum.MessageOptions_MessageSetWireFormat: case genid.MessageOptions_MessageSetWireFormat_field_number:
md.L1.IsMessageSet = protowire.DecodeBool(v) md.L1.IsMessageSet = protowire.DecodeBool(v)
} }
default: default:
@ -368,9 +368,9 @@ func unmarshalMessageReservedRange(b []byte) (r [2]pref.FieldNumber) {
v, m := protowire.ConsumeVarint(b) v, m := protowire.ConsumeVarint(b)
b = b[m:] b = b[m:]
switch num { switch num {
case fieldnum.DescriptorProto_ReservedRange_Start: case genid.DescriptorProto_ReservedRange_Start_field_number:
r[0] = pref.FieldNumber(v) r[0] = pref.FieldNumber(v)
case fieldnum.DescriptorProto_ReservedRange_End: case genid.DescriptorProto_ReservedRange_End_field_number:
r[1] = pref.FieldNumber(v) r[1] = pref.FieldNumber(v)
} }
default: default:
@ -390,16 +390,16 @@ func unmarshalMessageExtensionRange(b []byte) (r [2]pref.FieldNumber, rawOptions
v, m := protowire.ConsumeVarint(b) v, m := protowire.ConsumeVarint(b)
b = b[m:] b = b[m:]
switch num { switch num {
case fieldnum.DescriptorProto_ExtensionRange_Start: case genid.DescriptorProto_ExtensionRange_Start_field_number:
r[0] = pref.FieldNumber(v) r[0] = pref.FieldNumber(v)
case fieldnum.DescriptorProto_ExtensionRange_End: case genid.DescriptorProto_ExtensionRange_End_field_number:
r[1] = pref.FieldNumber(v) r[1] = pref.FieldNumber(v)
} }
case protowire.BytesType: case protowire.BytesType:
v, m := protowire.ConsumeBytes(b) v, m := protowire.ConsumeBytes(b)
b = b[m:] b = b[m:]
switch num { switch num {
case fieldnum.DescriptorProto_ExtensionRange_Options: case genid.DescriptorProto_ExtensionRange_Options_field_number:
rawOptions = appendOptions(rawOptions, v) rawOptions = appendOptions(rawOptions, v)
} }
default: default:
@ -425,13 +425,13 @@ func (fd *Field) unmarshalFull(b []byte, sb *strs.Builder, pf *File, pd pref.Des
v, m := protowire.ConsumeVarint(b) v, m := protowire.ConsumeVarint(b)
b = b[m:] b = b[m:]
switch num { switch num {
case fieldnum.FieldDescriptorProto_Number: case genid.FieldDescriptorProto_Number_field_number:
fd.L1.Number = pref.FieldNumber(v) fd.L1.Number = pref.FieldNumber(v)
case fieldnum.FieldDescriptorProto_Label: case genid.FieldDescriptorProto_Label_field_number:
fd.L1.Cardinality = pref.Cardinality(v) fd.L1.Cardinality = pref.Cardinality(v)
case fieldnum.FieldDescriptorProto_Type: case genid.FieldDescriptorProto_Type_field_number:
fd.L1.Kind = pref.Kind(v) fd.L1.Kind = pref.Kind(v)
case fieldnum.FieldDescriptorProto_OneofIndex: case genid.FieldDescriptorProto_OneofIndex_field_number:
// In Message.unmarshalFull, we allocate slices for both // In Message.unmarshalFull, we allocate slices for both
// the field and oneof descriptors before unmarshaling either // the field and oneof descriptors before unmarshaling either
// of them. This ensures pointers to slice elements are stable. // of them. This ensures pointers to slice elements are stable.
@ -441,22 +441,22 @@ func (fd *Field) unmarshalFull(b []byte, sb *strs.Builder, pf *File, pd pref.Des
panic("oneof type already set") panic("oneof type already set")
} }
fd.L1.ContainingOneof = od fd.L1.ContainingOneof = od
case fieldnum.FieldDescriptorProto_Proto3Optional: case genid.FieldDescriptorProto_Proto3Optional_field_number:
fd.L1.IsProto3Optional = protowire.DecodeBool(v) fd.L1.IsProto3Optional = protowire.DecodeBool(v)
} }
case protowire.BytesType: case protowire.BytesType:
v, m := protowire.ConsumeBytes(b) v, m := protowire.ConsumeBytes(b)
b = b[m:] b = b[m:]
switch num { switch num {
case fieldnum.FieldDescriptorProto_Name: case genid.FieldDescriptorProto_Name_field_number:
fd.L0.FullName = appendFullName(sb, pd.FullName(), v) fd.L0.FullName = appendFullName(sb, pd.FullName(), v)
case fieldnum.FieldDescriptorProto_JsonName: case genid.FieldDescriptorProto_JsonName_field_number:
fd.L1.JSONName.Init(sb.MakeString(v)) fd.L1.StringName.InitJSON(sb.MakeString(v))
case fieldnum.FieldDescriptorProto_DefaultValue: case genid.FieldDescriptorProto_DefaultValue_field_number:
fd.L1.Default.val = pref.ValueOfBytes(v) // temporarily store as bytes; later resolved in resolveMessages fd.L1.Default.val = pref.ValueOfBytes(v) // temporarily store as bytes; later resolved in resolveMessages
case fieldnum.FieldDescriptorProto_TypeName: case genid.FieldDescriptorProto_TypeName_field_number:
rawTypeName = v rawTypeName = v
case fieldnum.FieldDescriptorProto_Options: case genid.FieldDescriptorProto_Options_field_number:
fd.unmarshalOptions(v) fd.unmarshalOptions(v)
rawOptions = appendOptions(rawOptions, v) rawOptions = appendOptions(rawOptions, v)
} }
@ -488,10 +488,10 @@ func (fd *Field) unmarshalOptions(b []byte) {
v, m := protowire.ConsumeVarint(b) v, m := protowire.ConsumeVarint(b)
b = b[m:] b = b[m:]
switch num { switch num {
case fieldnum.FieldOptions_Packed: case genid.FieldOptions_Packed_field_number:
fd.L1.HasPacked = true fd.L1.HasPacked = true
fd.L1.IsPacked = protowire.DecodeBool(v) fd.L1.IsPacked = protowire.DecodeBool(v)
case fieldnum.FieldOptions_Weak: case genid.FieldOptions_Weak_field_number:
fd.L1.IsWeak = protowire.DecodeBool(v) fd.L1.IsWeak = protowire.DecodeBool(v)
case FieldOptions_EnforceUTF8: case FieldOptions_EnforceUTF8:
fd.L1.HasEnforceUTF8 = true fd.L1.HasEnforceUTF8 = true
@ -518,9 +518,9 @@ func (od *Oneof) unmarshalFull(b []byte, sb *strs.Builder, pf *File, pd pref.Des
v, m := protowire.ConsumeBytes(b) v, m := protowire.ConsumeBytes(b)
b = b[m:] b = b[m:]
switch num { switch num {
case fieldnum.OneofDescriptorProto_Name: case genid.OneofDescriptorProto_Name_field_number:
od.L0.FullName = appendFullName(sb, pd.FullName(), v) od.L0.FullName = appendFullName(sb, pd.FullName(), v)
case fieldnum.OneofDescriptorProto_Options: case genid.OneofDescriptorProto_Options_field_number:
rawOptions = appendOptions(rawOptions, v) rawOptions = appendOptions(rawOptions, v)
} }
default: default:
@ -543,20 +543,20 @@ func (xd *Extension) unmarshalFull(b []byte, sb *strs.Builder) {
v, m := protowire.ConsumeVarint(b) v, m := protowire.ConsumeVarint(b)
b = b[m:] b = b[m:]
switch num { switch num {
case fieldnum.FieldDescriptorProto_Proto3Optional: case genid.FieldDescriptorProto_Proto3Optional_field_number:
xd.L2.IsProto3Optional = protowire.DecodeBool(v) xd.L2.IsProto3Optional = protowire.DecodeBool(v)
} }
case protowire.BytesType: case protowire.BytesType:
v, m := protowire.ConsumeBytes(b) v, m := protowire.ConsumeBytes(b)
b = b[m:] b = b[m:]
switch num { switch num {
case fieldnum.FieldDescriptorProto_JsonName: case genid.FieldDescriptorProto_JsonName_field_number:
xd.L2.JSONName.Init(sb.MakeString(v)) xd.L2.StringName.InitJSON(sb.MakeString(v))
case fieldnum.FieldDescriptorProto_DefaultValue: case genid.FieldDescriptorProto_DefaultValue_field_number:
xd.L2.Default.val = pref.ValueOfBytes(v) // temporarily store as bytes; later resolved in resolveExtensions xd.L2.Default.val = pref.ValueOfBytes(v) // temporarily store as bytes; later resolved in resolveExtensions
case fieldnum.FieldDescriptorProto_TypeName: case genid.FieldDescriptorProto_TypeName_field_number:
rawTypeName = v rawTypeName = v
case fieldnum.FieldDescriptorProto_Options: case genid.FieldDescriptorProto_Options_field_number:
xd.unmarshalOptions(v) xd.unmarshalOptions(v)
rawOptions = appendOptions(rawOptions, v) rawOptions = appendOptions(rawOptions, v)
} }
@ -586,7 +586,7 @@ func (xd *Extension) unmarshalOptions(b []byte) {
v, m := protowire.ConsumeVarint(b) v, m := protowire.ConsumeVarint(b)
b = b[m:] b = b[m:]
switch num { switch num {
case fieldnum.FieldOptions_Packed: case genid.FieldOptions_Packed_field_number:
xd.L2.IsPacked = protowire.DecodeBool(v) xd.L2.IsPacked = protowire.DecodeBool(v)
} }
default: default:
@ -608,9 +608,9 @@ func (sd *Service) unmarshalFull(b []byte, sb *strs.Builder) {
v, m := protowire.ConsumeBytes(b) v, m := protowire.ConsumeBytes(b)
b = b[m:] b = b[m:]
switch num { switch num {
case fieldnum.ServiceDescriptorProto_Method: case genid.ServiceDescriptorProto_Method_field_number:
rawMethods = append(rawMethods, v) rawMethods = append(rawMethods, v)
case fieldnum.ServiceDescriptorProto_Options: case genid.ServiceDescriptorProto_Options_field_number:
rawOptions = appendOptions(rawOptions, v) rawOptions = appendOptions(rawOptions, v)
} }
default: default:
@ -641,22 +641,22 @@ func (md *Method) unmarshalFull(b []byte, sb *strs.Builder, pf *File, pd pref.De
v, m := protowire.ConsumeVarint(b) v, m := protowire.ConsumeVarint(b)
b = b[m:] b = b[m:]
switch num { switch num {
case fieldnum.MethodDescriptorProto_ClientStreaming: case genid.MethodDescriptorProto_ClientStreaming_field_number:
md.L1.IsStreamingClient = protowire.DecodeBool(v) md.L1.IsStreamingClient = protowire.DecodeBool(v)
case fieldnum.MethodDescriptorProto_ServerStreaming: case genid.MethodDescriptorProto_ServerStreaming_field_number:
md.L1.IsStreamingServer = protowire.DecodeBool(v) md.L1.IsStreamingServer = protowire.DecodeBool(v)
} }
case protowire.BytesType: case protowire.BytesType:
v, m := protowire.ConsumeBytes(b) v, m := protowire.ConsumeBytes(b)
b = b[m:] b = b[m:]
switch num { switch num {
case fieldnum.MethodDescriptorProto_Name: case genid.MethodDescriptorProto_Name_field_number:
md.L0.FullName = appendFullName(sb, pd.FullName(), v) md.L0.FullName = appendFullName(sb, pd.FullName(), v)
case fieldnum.MethodDescriptorProto_InputType: case genid.MethodDescriptorProto_InputType_field_number:
md.L1.Input = PlaceholderMessage(makeFullName(sb, v)) md.L1.Input = PlaceholderMessage(makeFullName(sb, v))
case fieldnum.MethodDescriptorProto_OutputType: case genid.MethodDescriptorProto_OutputType_field_number:
md.L1.Output = PlaceholderMessage(makeFullName(sb, v)) md.L1.Output = PlaceholderMessage(makeFullName(sb, v))
case fieldnum.MethodDescriptorProto_Options: case genid.MethodDescriptorProto_Options_field_number:
rawOptions = appendOptions(rawOptions, v) rawOptions = appendOptions(rawOptions, v)
} }
default: default:

View File

@ -10,6 +10,8 @@ import (
"sort" "sort"
"sync" "sync"
"google.golang.org/protobuf/internal/genid"
"google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/encoding/protowire"
"google.golang.org/protobuf/internal/descfmt" "google.golang.org/protobuf/internal/descfmt"
"google.golang.org/protobuf/internal/errors" "google.golang.org/protobuf/internal/errors"
@ -185,10 +187,7 @@ func (p *FieldRanges) CheckValid(isMessageSet bool) error {
// Unlike the FieldNumber.IsValid method, it allows ranges that cover the // Unlike the FieldNumber.IsValid method, it allows ranges that cover the
// reserved number range. // reserved number range.
func isValidFieldNumber(n protoreflect.FieldNumber, isMessageSet bool) bool { func isValidFieldNumber(n protoreflect.FieldNumber, isMessageSet bool) bool {
if isMessageSet { return protowire.MinValidNumber <= n && (n <= protowire.MaxValidNumber || isMessageSet)
return protowire.MinValidNumber <= n && n <= math.MaxInt32
}
return protowire.MinValidNumber <= n && n <= protowire.MaxValidNumber
} }
// CheckOverlap reports an error if p and q overlap. // CheckOverlap reports an error if p and q overlap.
@ -249,6 +248,7 @@ type OneofFields struct {
once sync.Once once sync.Once
byName map[pref.Name]pref.FieldDescriptor // protected by once byName map[pref.Name]pref.FieldDescriptor // protected by once
byJSON map[string]pref.FieldDescriptor // protected by once byJSON map[string]pref.FieldDescriptor // protected by once
byText map[string]pref.FieldDescriptor // protected by once
byNum map[pref.FieldNumber]pref.FieldDescriptor // protected by once byNum map[pref.FieldNumber]pref.FieldDescriptor // protected by once
} }
@ -256,6 +256,7 @@ func (p *OneofFields) Len() int { return
func (p *OneofFields) Get(i int) pref.FieldDescriptor { return p.List[i] } func (p *OneofFields) Get(i int) pref.FieldDescriptor { return p.List[i] }
func (p *OneofFields) ByName(s pref.Name) pref.FieldDescriptor { return p.lazyInit().byName[s] } func (p *OneofFields) ByName(s pref.Name) pref.FieldDescriptor { return p.lazyInit().byName[s] }
func (p *OneofFields) ByJSONName(s string) pref.FieldDescriptor { return p.lazyInit().byJSON[s] } func (p *OneofFields) ByJSONName(s string) pref.FieldDescriptor { return p.lazyInit().byJSON[s] }
func (p *OneofFields) ByTextName(s string) pref.FieldDescriptor { return p.lazyInit().byText[s] }
func (p *OneofFields) ByNumber(n pref.FieldNumber) pref.FieldDescriptor { return p.lazyInit().byNum[n] } func (p *OneofFields) ByNumber(n pref.FieldNumber) pref.FieldDescriptor { return p.lazyInit().byNum[n] }
func (p *OneofFields) Format(s fmt.State, r rune) { descfmt.FormatList(s, r, p) } func (p *OneofFields) Format(s fmt.State, r rune) { descfmt.FormatList(s, r, p) }
func (p *OneofFields) ProtoInternal(pragma.DoNotImplement) {} func (p *OneofFields) ProtoInternal(pragma.DoNotImplement) {}
@ -265,11 +266,13 @@ func (p *OneofFields) lazyInit() *OneofFields {
if len(p.List) > 0 { if len(p.List) > 0 {
p.byName = make(map[pref.Name]pref.FieldDescriptor, len(p.List)) p.byName = make(map[pref.Name]pref.FieldDescriptor, len(p.List))
p.byJSON = make(map[string]pref.FieldDescriptor, len(p.List)) p.byJSON = make(map[string]pref.FieldDescriptor, len(p.List))
p.byText = make(map[string]pref.FieldDescriptor, len(p.List))
p.byNum = make(map[pref.FieldNumber]pref.FieldDescriptor, len(p.List)) p.byNum = make(map[pref.FieldNumber]pref.FieldDescriptor, len(p.List))
for _, f := range p.List { for _, f := range p.List {
// Field names and numbers are guaranteed to be unique. // Field names and numbers are guaranteed to be unique.
p.byName[f.Name()] = f p.byName[f.Name()] = f
p.byJSON[f.JSONName()] = f p.byJSON[f.JSONName()] = f
p.byText[f.TextName()] = f
p.byNum[f.Number()] = f p.byNum[f.Number()] = f
} }
} }
@ -278,9 +281,170 @@ func (p *OneofFields) lazyInit() *OneofFields {
} }
type SourceLocations struct { type SourceLocations struct {
// List is a list of SourceLocations.
// The SourceLocation.Next field does not need to be populated
// as it will be lazily populated upon first need.
List []pref.SourceLocation List []pref.SourceLocation
// File is the parent file descriptor that these locations are relative to.
// If non-nil, ByDescriptor verifies that the provided descriptor
// is a child of this file descriptor.
File pref.FileDescriptor
once sync.Once
byPath map[pathKey]int
} }
func (p *SourceLocations) Len() int { return len(p.List) } func (p *SourceLocations) Len() int { return len(p.List) }
func (p *SourceLocations) Get(i int) pref.SourceLocation { return p.List[i] } func (p *SourceLocations) Get(i int) pref.SourceLocation { return p.lazyInit().List[i] }
func (p *SourceLocations) byKey(k pathKey) pref.SourceLocation {
if i, ok := p.lazyInit().byPath[k]; ok {
return p.List[i]
}
return pref.SourceLocation{}
}
func (p *SourceLocations) ByPath(path pref.SourcePath) pref.SourceLocation {
return p.byKey(newPathKey(path))
}
func (p *SourceLocations) ByDescriptor(desc pref.Descriptor) pref.SourceLocation {
if p.File != nil && desc != nil && p.File != desc.ParentFile() {
return pref.SourceLocation{} // mismatching parent files
}
var pathArr [16]int32
path := pathArr[:0]
for {
switch desc.(type) {
case pref.FileDescriptor:
// Reverse the path since it was constructed in reverse.
for i, j := 0, len(path)-1; i < j; i, j = i+1, j-1 {
path[i], path[j] = path[j], path[i]
}
return p.byKey(newPathKey(path))
case pref.MessageDescriptor:
path = append(path, int32(desc.Index()))
desc = desc.Parent()
switch desc.(type) {
case pref.FileDescriptor:
path = append(path, int32(genid.FileDescriptorProto_MessageType_field_number))
case pref.MessageDescriptor:
path = append(path, int32(genid.DescriptorProto_NestedType_field_number))
default:
return pref.SourceLocation{}
}
case pref.FieldDescriptor:
isExtension := desc.(pref.FieldDescriptor).IsExtension()
path = append(path, int32(desc.Index()))
desc = desc.Parent()
if isExtension {
switch desc.(type) {
case pref.FileDescriptor:
path = append(path, int32(genid.FileDescriptorProto_Extension_field_number))
case pref.MessageDescriptor:
path = append(path, int32(genid.DescriptorProto_Extension_field_number))
default:
return pref.SourceLocation{}
}
} else {
switch desc.(type) {
case pref.MessageDescriptor:
path = append(path, int32(genid.DescriptorProto_Field_field_number))
default:
return pref.SourceLocation{}
}
}
case pref.OneofDescriptor:
path = append(path, int32(desc.Index()))
desc = desc.Parent()
switch desc.(type) {
case pref.MessageDescriptor:
path = append(path, int32(genid.DescriptorProto_OneofDecl_field_number))
default:
return pref.SourceLocation{}
}
case pref.EnumDescriptor:
path = append(path, int32(desc.Index()))
desc = desc.Parent()
switch desc.(type) {
case pref.FileDescriptor:
path = append(path, int32(genid.FileDescriptorProto_EnumType_field_number))
case pref.MessageDescriptor:
path = append(path, int32(genid.DescriptorProto_EnumType_field_number))
default:
return pref.SourceLocation{}
}
case pref.EnumValueDescriptor:
path = append(path, int32(desc.Index()))
desc = desc.Parent()
switch desc.(type) {
case pref.EnumDescriptor:
path = append(path, int32(genid.EnumDescriptorProto_Value_field_number))
default:
return pref.SourceLocation{}
}
case pref.ServiceDescriptor:
path = append(path, int32(desc.Index()))
desc = desc.Parent()
switch desc.(type) {
case pref.FileDescriptor:
path = append(path, int32(genid.FileDescriptorProto_Service_field_number))
default:
return pref.SourceLocation{}
}
case pref.MethodDescriptor:
path = append(path, int32(desc.Index()))
desc = desc.Parent()
switch desc.(type) {
case pref.ServiceDescriptor:
path = append(path, int32(genid.ServiceDescriptorProto_Method_field_number))
default:
return pref.SourceLocation{}
}
default:
return pref.SourceLocation{}
}
}
}
func (p *SourceLocations) lazyInit() *SourceLocations {
p.once.Do(func() {
if len(p.List) > 0 {
// Collect all the indexes for a given path.
pathIdxs := make(map[pathKey][]int, len(p.List))
for i, l := range p.List {
k := newPathKey(l.Path)
pathIdxs[k] = append(pathIdxs[k], i)
}
// Update the next index for all locations.
p.byPath = make(map[pathKey]int, len(p.List))
for k, idxs := range pathIdxs {
for i := 0; i < len(idxs)-1; i++ {
p.List[idxs[i]].Next = idxs[i+1]
}
p.List[idxs[len(idxs)-1]].Next = 0
p.byPath[k] = idxs[0] // record the first location for this path
}
}
})
return p
}
func (p *SourceLocations) ProtoInternal(pragma.DoNotImplement) {} func (p *SourceLocations) ProtoInternal(pragma.DoNotImplement) {}
// pathKey is a comparable representation of protoreflect.SourcePath.
type pathKey struct {
arr [16]uint8 // first n-1 path segments; last element is the length
str string // used if the path does not fit in arr
}
func newPathKey(p pref.SourcePath) (k pathKey) {
if len(p) < len(k.arr) {
for i, ps := range p {
if ps < 0 || math.MaxUint8 <= ps {
return pathKey{str: p.String()}
}
k.arr[i] = uint8(ps)
}
k.arr[len(k.arr)-1] = uint8(len(p))
return k
}
return pathKey{str: p.String()}
}

View File

@ -142,6 +142,7 @@ type Fields struct {
once sync.Once once sync.Once
byName map[protoreflect.Name]*Field // protected by once byName map[protoreflect.Name]*Field // protected by once
byJSON map[string]*Field // protected by once byJSON map[string]*Field // protected by once
byText map[string]*Field // protected by once
byNum map[protoreflect.FieldNumber]*Field // protected by once byNum map[protoreflect.FieldNumber]*Field // protected by once
} }
@ -163,6 +164,12 @@ func (p *Fields) ByJSONName(s string) protoreflect.FieldDescriptor {
} }
return nil return nil
} }
func (p *Fields) ByTextName(s string) protoreflect.FieldDescriptor {
if d := p.lazyInit().byText[s]; d != nil {
return d
}
return nil
}
func (p *Fields) ByNumber(n protoreflect.FieldNumber) protoreflect.FieldDescriptor { func (p *Fields) ByNumber(n protoreflect.FieldNumber) protoreflect.FieldDescriptor {
if d := p.lazyInit().byNum[n]; d != nil { if d := p.lazyInit().byNum[n]; d != nil {
return d return d
@ -178,6 +185,7 @@ func (p *Fields) lazyInit() *Fields {
if len(p.List) > 0 { if len(p.List) > 0 {
p.byName = make(map[protoreflect.Name]*Field, len(p.List)) p.byName = make(map[protoreflect.Name]*Field, len(p.List))
p.byJSON = make(map[string]*Field, len(p.List)) p.byJSON = make(map[string]*Field, len(p.List))
p.byText = make(map[string]*Field, len(p.List))
p.byNum = make(map[protoreflect.FieldNumber]*Field, len(p.List)) p.byNum = make(map[protoreflect.FieldNumber]*Field, len(p.List))
for i := range p.List { for i := range p.List {
d := &p.List[i] d := &p.List[i]
@ -187,6 +195,9 @@ func (p *Fields) lazyInit() *Fields {
if _, ok := p.byJSON[d.JSONName()]; !ok { if _, ok := p.byJSON[d.JSONName()]; !ok {
p.byJSON[d.JSONName()] = d p.byJSON[d.JSONName()] = d
} }
if _, ok := p.byText[d.TextName()]; !ok {
p.byText[d.TextName()] = d
}
if _, ok := p.byNum[d.Number()]; !ok { if _, ok := p.byNum[d.Number()]; !ok {
p.byNum[d.Number()] = d p.byNum[d.Number()] = d
} }

View File

@ -0,0 +1,34 @@
// 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.
// Code generated by generate-protos. DO NOT EDIT.
package genid
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
)
const File_google_protobuf_any_proto = "google/protobuf/any.proto"
// Names for google.protobuf.Any.
const (
Any_message_name protoreflect.Name = "Any"
Any_message_fullname protoreflect.FullName = "google.protobuf.Any"
)
// Field names for google.protobuf.Any.
const (
Any_TypeUrl_field_name protoreflect.Name = "type_url"
Any_Value_field_name protoreflect.Name = "value"
Any_TypeUrl_field_fullname protoreflect.FullName = "google.protobuf.Any.type_url"
Any_Value_field_fullname protoreflect.FullName = "google.protobuf.Any.value"
)
// Field numbers for google.protobuf.Any.
const (
Any_TypeUrl_field_number protoreflect.FieldNumber = 1
Any_Value_field_number protoreflect.FieldNumber = 2
)

View File

@ -0,0 +1,106 @@
// 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.
// Code generated by generate-protos. DO NOT EDIT.
package genid
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
)
const File_google_protobuf_api_proto = "google/protobuf/api.proto"
// Names for google.protobuf.Api.
const (
Api_message_name protoreflect.Name = "Api"
Api_message_fullname protoreflect.FullName = "google.protobuf.Api"
)
// Field names for google.protobuf.Api.
const (
Api_Name_field_name protoreflect.Name = "name"
Api_Methods_field_name protoreflect.Name = "methods"
Api_Options_field_name protoreflect.Name = "options"
Api_Version_field_name protoreflect.Name = "version"
Api_SourceContext_field_name protoreflect.Name = "source_context"
Api_Mixins_field_name protoreflect.Name = "mixins"
Api_Syntax_field_name protoreflect.Name = "syntax"
Api_Name_field_fullname protoreflect.FullName = "google.protobuf.Api.name"
Api_Methods_field_fullname protoreflect.FullName = "google.protobuf.Api.methods"
Api_Options_field_fullname protoreflect.FullName = "google.protobuf.Api.options"
Api_Version_field_fullname protoreflect.FullName = "google.protobuf.Api.version"
Api_SourceContext_field_fullname protoreflect.FullName = "google.protobuf.Api.source_context"
Api_Mixins_field_fullname protoreflect.FullName = "google.protobuf.Api.mixins"
Api_Syntax_field_fullname protoreflect.FullName = "google.protobuf.Api.syntax"
)
// Field numbers for google.protobuf.Api.
const (
Api_Name_field_number protoreflect.FieldNumber = 1
Api_Methods_field_number protoreflect.FieldNumber = 2
Api_Options_field_number protoreflect.FieldNumber = 3
Api_Version_field_number protoreflect.FieldNumber = 4
Api_SourceContext_field_number protoreflect.FieldNumber = 5
Api_Mixins_field_number protoreflect.FieldNumber = 6
Api_Syntax_field_number protoreflect.FieldNumber = 7
)
// Names for google.protobuf.Method.
const (
Method_message_name protoreflect.Name = "Method"
Method_message_fullname protoreflect.FullName = "google.protobuf.Method"
)
// Field names for google.protobuf.Method.
const (
Method_Name_field_name protoreflect.Name = "name"
Method_RequestTypeUrl_field_name protoreflect.Name = "request_type_url"
Method_RequestStreaming_field_name protoreflect.Name = "request_streaming"
Method_ResponseTypeUrl_field_name protoreflect.Name = "response_type_url"
Method_ResponseStreaming_field_name protoreflect.Name = "response_streaming"
Method_Options_field_name protoreflect.Name = "options"
Method_Syntax_field_name protoreflect.Name = "syntax"
Method_Name_field_fullname protoreflect.FullName = "google.protobuf.Method.name"
Method_RequestTypeUrl_field_fullname protoreflect.FullName = "google.protobuf.Method.request_type_url"
Method_RequestStreaming_field_fullname protoreflect.FullName = "google.protobuf.Method.request_streaming"
Method_ResponseTypeUrl_field_fullname protoreflect.FullName = "google.protobuf.Method.response_type_url"
Method_ResponseStreaming_field_fullname protoreflect.FullName = "google.protobuf.Method.response_streaming"
Method_Options_field_fullname protoreflect.FullName = "google.protobuf.Method.options"
Method_Syntax_field_fullname protoreflect.FullName = "google.protobuf.Method.syntax"
)
// Field numbers for google.protobuf.Method.
const (
Method_Name_field_number protoreflect.FieldNumber = 1
Method_RequestTypeUrl_field_number protoreflect.FieldNumber = 2
Method_RequestStreaming_field_number protoreflect.FieldNumber = 3
Method_ResponseTypeUrl_field_number protoreflect.FieldNumber = 4
Method_ResponseStreaming_field_number protoreflect.FieldNumber = 5
Method_Options_field_number protoreflect.FieldNumber = 6
Method_Syntax_field_number protoreflect.FieldNumber = 7
)
// Names for google.protobuf.Mixin.
const (
Mixin_message_name protoreflect.Name = "Mixin"
Mixin_message_fullname protoreflect.FullName = "google.protobuf.Mixin"
)
// Field names for google.protobuf.Mixin.
const (
Mixin_Name_field_name protoreflect.Name = "name"
Mixin_Root_field_name protoreflect.Name = "root"
Mixin_Name_field_fullname protoreflect.FullName = "google.protobuf.Mixin.name"
Mixin_Root_field_fullname protoreflect.FullName = "google.protobuf.Mixin.root"
)
// Field numbers for google.protobuf.Mixin.
const (
Mixin_Name_field_number protoreflect.FieldNumber = 1
Mixin_Root_field_number protoreflect.FieldNumber = 2
)

View File

@ -0,0 +1,829 @@
// 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.
// Code generated by generate-protos. DO NOT EDIT.
package genid
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
)
const File_google_protobuf_descriptor_proto = "google/protobuf/descriptor.proto"
// Names for google.protobuf.FileDescriptorSet.
const (
FileDescriptorSet_message_name protoreflect.Name = "FileDescriptorSet"
FileDescriptorSet_message_fullname protoreflect.FullName = "google.protobuf.FileDescriptorSet"
)
// Field names for google.protobuf.FileDescriptorSet.
const (
FileDescriptorSet_File_field_name protoreflect.Name = "file"
FileDescriptorSet_File_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorSet.file"
)
// Field numbers for google.protobuf.FileDescriptorSet.
const (
FileDescriptorSet_File_field_number protoreflect.FieldNumber = 1
)
// Names for google.protobuf.FileDescriptorProto.
const (
FileDescriptorProto_message_name protoreflect.Name = "FileDescriptorProto"
FileDescriptorProto_message_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto"
)
// Field names for google.protobuf.FileDescriptorProto.
const (
FileDescriptorProto_Name_field_name protoreflect.Name = "name"
FileDescriptorProto_Package_field_name protoreflect.Name = "package"
FileDescriptorProto_Dependency_field_name protoreflect.Name = "dependency"
FileDescriptorProto_PublicDependency_field_name protoreflect.Name = "public_dependency"
FileDescriptorProto_WeakDependency_field_name protoreflect.Name = "weak_dependency"
FileDescriptorProto_MessageType_field_name protoreflect.Name = "message_type"
FileDescriptorProto_EnumType_field_name protoreflect.Name = "enum_type"
FileDescriptorProto_Service_field_name protoreflect.Name = "service"
FileDescriptorProto_Extension_field_name protoreflect.Name = "extension"
FileDescriptorProto_Options_field_name protoreflect.Name = "options"
FileDescriptorProto_SourceCodeInfo_field_name protoreflect.Name = "source_code_info"
FileDescriptorProto_Syntax_field_name protoreflect.Name = "syntax"
FileDescriptorProto_Name_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.name"
FileDescriptorProto_Package_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.package"
FileDescriptorProto_Dependency_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.dependency"
FileDescriptorProto_PublicDependency_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.public_dependency"
FileDescriptorProto_WeakDependency_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.weak_dependency"
FileDescriptorProto_MessageType_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.message_type"
FileDescriptorProto_EnumType_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.enum_type"
FileDescriptorProto_Service_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.service"
FileDescriptorProto_Extension_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.extension"
FileDescriptorProto_Options_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.options"
FileDescriptorProto_SourceCodeInfo_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.source_code_info"
FileDescriptorProto_Syntax_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.syntax"
)
// Field numbers for google.protobuf.FileDescriptorProto.
const (
FileDescriptorProto_Name_field_number protoreflect.FieldNumber = 1
FileDescriptorProto_Package_field_number protoreflect.FieldNumber = 2
FileDescriptorProto_Dependency_field_number protoreflect.FieldNumber = 3
FileDescriptorProto_PublicDependency_field_number protoreflect.FieldNumber = 10
FileDescriptorProto_WeakDependency_field_number protoreflect.FieldNumber = 11
FileDescriptorProto_MessageType_field_number protoreflect.FieldNumber = 4
FileDescriptorProto_EnumType_field_number protoreflect.FieldNumber = 5
FileDescriptorProto_Service_field_number protoreflect.FieldNumber = 6
FileDescriptorProto_Extension_field_number protoreflect.FieldNumber = 7
FileDescriptorProto_Options_field_number protoreflect.FieldNumber = 8
FileDescriptorProto_SourceCodeInfo_field_number protoreflect.FieldNumber = 9
FileDescriptorProto_Syntax_field_number protoreflect.FieldNumber = 12
)
// Names for google.protobuf.DescriptorProto.
const (
DescriptorProto_message_name protoreflect.Name = "DescriptorProto"
DescriptorProto_message_fullname protoreflect.FullName = "google.protobuf.DescriptorProto"
)
// Field names for google.protobuf.DescriptorProto.
const (
DescriptorProto_Name_field_name protoreflect.Name = "name"
DescriptorProto_Field_field_name protoreflect.Name = "field"
DescriptorProto_Extension_field_name protoreflect.Name = "extension"
DescriptorProto_NestedType_field_name protoreflect.Name = "nested_type"
DescriptorProto_EnumType_field_name protoreflect.Name = "enum_type"
DescriptorProto_ExtensionRange_field_name protoreflect.Name = "extension_range"
DescriptorProto_OneofDecl_field_name protoreflect.Name = "oneof_decl"
DescriptorProto_Options_field_name protoreflect.Name = "options"
DescriptorProto_ReservedRange_field_name protoreflect.Name = "reserved_range"
DescriptorProto_ReservedName_field_name protoreflect.Name = "reserved_name"
DescriptorProto_Name_field_fullname protoreflect.FullName = "google.protobuf.DescriptorProto.name"
DescriptorProto_Field_field_fullname protoreflect.FullName = "google.protobuf.DescriptorProto.field"
DescriptorProto_Extension_field_fullname protoreflect.FullName = "google.protobuf.DescriptorProto.extension"
DescriptorProto_NestedType_field_fullname protoreflect.FullName = "google.protobuf.DescriptorProto.nested_type"
DescriptorProto_EnumType_field_fullname protoreflect.FullName = "google.protobuf.DescriptorProto.enum_type"
DescriptorProto_ExtensionRange_field_fullname protoreflect.FullName = "google.protobuf.DescriptorProto.extension_range"
DescriptorProto_OneofDecl_field_fullname protoreflect.FullName = "google.protobuf.DescriptorProto.oneof_decl"
DescriptorProto_Options_field_fullname protoreflect.FullName = "google.protobuf.DescriptorProto.options"
DescriptorProto_ReservedRange_field_fullname protoreflect.FullName = "google.protobuf.DescriptorProto.reserved_range"
DescriptorProto_ReservedName_field_fullname protoreflect.FullName = "google.protobuf.DescriptorProto.reserved_name"
)
// Field numbers for google.protobuf.DescriptorProto.
const (
DescriptorProto_Name_field_number protoreflect.FieldNumber = 1
DescriptorProto_Field_field_number protoreflect.FieldNumber = 2
DescriptorProto_Extension_field_number protoreflect.FieldNumber = 6
DescriptorProto_NestedType_field_number protoreflect.FieldNumber = 3
DescriptorProto_EnumType_field_number protoreflect.FieldNumber = 4
DescriptorProto_ExtensionRange_field_number protoreflect.FieldNumber = 5
DescriptorProto_OneofDecl_field_number protoreflect.FieldNumber = 8
DescriptorProto_Options_field_number protoreflect.FieldNumber = 7
DescriptorProto_ReservedRange_field_number protoreflect.FieldNumber = 9
DescriptorProto_ReservedName_field_number protoreflect.FieldNumber = 10
)
// Names for google.protobuf.DescriptorProto.ExtensionRange.
const (
DescriptorProto_ExtensionRange_message_name protoreflect.Name = "ExtensionRange"
DescriptorProto_ExtensionRange_message_fullname protoreflect.FullName = "google.protobuf.DescriptorProto.ExtensionRange"
)
// Field names for google.protobuf.DescriptorProto.ExtensionRange.
const (
DescriptorProto_ExtensionRange_Start_field_name protoreflect.Name = "start"
DescriptorProto_ExtensionRange_End_field_name protoreflect.Name = "end"
DescriptorProto_ExtensionRange_Options_field_name protoreflect.Name = "options"
DescriptorProto_ExtensionRange_Start_field_fullname protoreflect.FullName = "google.protobuf.DescriptorProto.ExtensionRange.start"
DescriptorProto_ExtensionRange_End_field_fullname protoreflect.FullName = "google.protobuf.DescriptorProto.ExtensionRange.end"
DescriptorProto_ExtensionRange_Options_field_fullname protoreflect.FullName = "google.protobuf.DescriptorProto.ExtensionRange.options"
)
// Field numbers for google.protobuf.DescriptorProto.ExtensionRange.
const (
DescriptorProto_ExtensionRange_Start_field_number protoreflect.FieldNumber = 1
DescriptorProto_ExtensionRange_End_field_number protoreflect.FieldNumber = 2
DescriptorProto_ExtensionRange_Options_field_number protoreflect.FieldNumber = 3
)
// Names for google.protobuf.DescriptorProto.ReservedRange.
const (
DescriptorProto_ReservedRange_message_name protoreflect.Name = "ReservedRange"
DescriptorProto_ReservedRange_message_fullname protoreflect.FullName = "google.protobuf.DescriptorProto.ReservedRange"
)
// Field names for google.protobuf.DescriptorProto.ReservedRange.
const (
DescriptorProto_ReservedRange_Start_field_name protoreflect.Name = "start"
DescriptorProto_ReservedRange_End_field_name protoreflect.Name = "end"
DescriptorProto_ReservedRange_Start_field_fullname protoreflect.FullName = "google.protobuf.DescriptorProto.ReservedRange.start"
DescriptorProto_ReservedRange_End_field_fullname protoreflect.FullName = "google.protobuf.DescriptorProto.ReservedRange.end"
)
// Field numbers for google.protobuf.DescriptorProto.ReservedRange.
const (
DescriptorProto_ReservedRange_Start_field_number protoreflect.FieldNumber = 1
DescriptorProto_ReservedRange_End_field_number protoreflect.FieldNumber = 2
)
// Names for google.protobuf.ExtensionRangeOptions.
const (
ExtensionRangeOptions_message_name protoreflect.Name = "ExtensionRangeOptions"
ExtensionRangeOptions_message_fullname protoreflect.FullName = "google.protobuf.ExtensionRangeOptions"
)
// Field names for google.protobuf.ExtensionRangeOptions.
const (
ExtensionRangeOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option"
ExtensionRangeOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.ExtensionRangeOptions.uninterpreted_option"
)
// Field numbers for google.protobuf.ExtensionRangeOptions.
const (
ExtensionRangeOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999
)
// Names for google.protobuf.FieldDescriptorProto.
const (
FieldDescriptorProto_message_name protoreflect.Name = "FieldDescriptorProto"
FieldDescriptorProto_message_fullname protoreflect.FullName = "google.protobuf.FieldDescriptorProto"
)
// Field names for google.protobuf.FieldDescriptorProto.
const (
FieldDescriptorProto_Name_field_name protoreflect.Name = "name"
FieldDescriptorProto_Number_field_name protoreflect.Name = "number"
FieldDescriptorProto_Label_field_name protoreflect.Name = "label"
FieldDescriptorProto_Type_field_name protoreflect.Name = "type"
FieldDescriptorProto_TypeName_field_name protoreflect.Name = "type_name"
FieldDescriptorProto_Extendee_field_name protoreflect.Name = "extendee"
FieldDescriptorProto_DefaultValue_field_name protoreflect.Name = "default_value"
FieldDescriptorProto_OneofIndex_field_name protoreflect.Name = "oneof_index"
FieldDescriptorProto_JsonName_field_name protoreflect.Name = "json_name"
FieldDescriptorProto_Options_field_name protoreflect.Name = "options"
FieldDescriptorProto_Proto3Optional_field_name protoreflect.Name = "proto3_optional"
FieldDescriptorProto_Name_field_fullname protoreflect.FullName = "google.protobuf.FieldDescriptorProto.name"
FieldDescriptorProto_Number_field_fullname protoreflect.FullName = "google.protobuf.FieldDescriptorProto.number"
FieldDescriptorProto_Label_field_fullname protoreflect.FullName = "google.protobuf.FieldDescriptorProto.label"
FieldDescriptorProto_Type_field_fullname protoreflect.FullName = "google.protobuf.FieldDescriptorProto.type"
FieldDescriptorProto_TypeName_field_fullname protoreflect.FullName = "google.protobuf.FieldDescriptorProto.type_name"
FieldDescriptorProto_Extendee_field_fullname protoreflect.FullName = "google.protobuf.FieldDescriptorProto.extendee"
FieldDescriptorProto_DefaultValue_field_fullname protoreflect.FullName = "google.protobuf.FieldDescriptorProto.default_value"
FieldDescriptorProto_OneofIndex_field_fullname protoreflect.FullName = "google.protobuf.FieldDescriptorProto.oneof_index"
FieldDescriptorProto_JsonName_field_fullname protoreflect.FullName = "google.protobuf.FieldDescriptorProto.json_name"
FieldDescriptorProto_Options_field_fullname protoreflect.FullName = "google.protobuf.FieldDescriptorProto.options"
FieldDescriptorProto_Proto3Optional_field_fullname protoreflect.FullName = "google.protobuf.FieldDescriptorProto.proto3_optional"
)
// Field numbers for google.protobuf.FieldDescriptorProto.
const (
FieldDescriptorProto_Name_field_number protoreflect.FieldNumber = 1
FieldDescriptorProto_Number_field_number protoreflect.FieldNumber = 3
FieldDescriptorProto_Label_field_number protoreflect.FieldNumber = 4
FieldDescriptorProto_Type_field_number protoreflect.FieldNumber = 5
FieldDescriptorProto_TypeName_field_number protoreflect.FieldNumber = 6
FieldDescriptorProto_Extendee_field_number protoreflect.FieldNumber = 2
FieldDescriptorProto_DefaultValue_field_number protoreflect.FieldNumber = 7
FieldDescriptorProto_OneofIndex_field_number protoreflect.FieldNumber = 9
FieldDescriptorProto_JsonName_field_number protoreflect.FieldNumber = 10
FieldDescriptorProto_Options_field_number protoreflect.FieldNumber = 8
FieldDescriptorProto_Proto3Optional_field_number protoreflect.FieldNumber = 17
)
// Full and short names for google.protobuf.FieldDescriptorProto.Type.
const (
FieldDescriptorProto_Type_enum_fullname = "google.protobuf.FieldDescriptorProto.Type"
FieldDescriptorProto_Type_enum_name = "Type"
)
// Full and short names for google.protobuf.FieldDescriptorProto.Label.
const (
FieldDescriptorProto_Label_enum_fullname = "google.protobuf.FieldDescriptorProto.Label"
FieldDescriptorProto_Label_enum_name = "Label"
)
// Names for google.protobuf.OneofDescriptorProto.
const (
OneofDescriptorProto_message_name protoreflect.Name = "OneofDescriptorProto"
OneofDescriptorProto_message_fullname protoreflect.FullName = "google.protobuf.OneofDescriptorProto"
)
// Field names for google.protobuf.OneofDescriptorProto.
const (
OneofDescriptorProto_Name_field_name protoreflect.Name = "name"
OneofDescriptorProto_Options_field_name protoreflect.Name = "options"
OneofDescriptorProto_Name_field_fullname protoreflect.FullName = "google.protobuf.OneofDescriptorProto.name"
OneofDescriptorProto_Options_field_fullname protoreflect.FullName = "google.protobuf.OneofDescriptorProto.options"
)
// Field numbers for google.protobuf.OneofDescriptorProto.
const (
OneofDescriptorProto_Name_field_number protoreflect.FieldNumber = 1
OneofDescriptorProto_Options_field_number protoreflect.FieldNumber = 2
)
// Names for google.protobuf.EnumDescriptorProto.
const (
EnumDescriptorProto_message_name protoreflect.Name = "EnumDescriptorProto"
EnumDescriptorProto_message_fullname protoreflect.FullName = "google.protobuf.EnumDescriptorProto"
)
// Field names for google.protobuf.EnumDescriptorProto.
const (
EnumDescriptorProto_Name_field_name protoreflect.Name = "name"
EnumDescriptorProto_Value_field_name protoreflect.Name = "value"
EnumDescriptorProto_Options_field_name protoreflect.Name = "options"
EnumDescriptorProto_ReservedRange_field_name protoreflect.Name = "reserved_range"
EnumDescriptorProto_ReservedName_field_name protoreflect.Name = "reserved_name"
EnumDescriptorProto_Name_field_fullname protoreflect.FullName = "google.protobuf.EnumDescriptorProto.name"
EnumDescriptorProto_Value_field_fullname protoreflect.FullName = "google.protobuf.EnumDescriptorProto.value"
EnumDescriptorProto_Options_field_fullname protoreflect.FullName = "google.protobuf.EnumDescriptorProto.options"
EnumDescriptorProto_ReservedRange_field_fullname protoreflect.FullName = "google.protobuf.EnumDescriptorProto.reserved_range"
EnumDescriptorProto_ReservedName_field_fullname protoreflect.FullName = "google.protobuf.EnumDescriptorProto.reserved_name"
)
// Field numbers for google.protobuf.EnumDescriptorProto.
const (
EnumDescriptorProto_Name_field_number protoreflect.FieldNumber = 1
EnumDescriptorProto_Value_field_number protoreflect.FieldNumber = 2
EnumDescriptorProto_Options_field_number protoreflect.FieldNumber = 3
EnumDescriptorProto_ReservedRange_field_number protoreflect.FieldNumber = 4
EnumDescriptorProto_ReservedName_field_number protoreflect.FieldNumber = 5
)
// Names for google.protobuf.EnumDescriptorProto.EnumReservedRange.
const (
EnumDescriptorProto_EnumReservedRange_message_name protoreflect.Name = "EnumReservedRange"
EnumDescriptorProto_EnumReservedRange_message_fullname protoreflect.FullName = "google.protobuf.EnumDescriptorProto.EnumReservedRange"
)
// Field names for google.protobuf.EnumDescriptorProto.EnumReservedRange.
const (
EnumDescriptorProto_EnumReservedRange_Start_field_name protoreflect.Name = "start"
EnumDescriptorProto_EnumReservedRange_End_field_name protoreflect.Name = "end"
EnumDescriptorProto_EnumReservedRange_Start_field_fullname protoreflect.FullName = "google.protobuf.EnumDescriptorProto.EnumReservedRange.start"
EnumDescriptorProto_EnumReservedRange_End_field_fullname protoreflect.FullName = "google.protobuf.EnumDescriptorProto.EnumReservedRange.end"
)
// Field numbers for google.protobuf.EnumDescriptorProto.EnumReservedRange.
const (
EnumDescriptorProto_EnumReservedRange_Start_field_number protoreflect.FieldNumber = 1
EnumDescriptorProto_EnumReservedRange_End_field_number protoreflect.FieldNumber = 2
)
// Names for google.protobuf.EnumValueDescriptorProto.
const (
EnumValueDescriptorProto_message_name protoreflect.Name = "EnumValueDescriptorProto"
EnumValueDescriptorProto_message_fullname protoreflect.FullName = "google.protobuf.EnumValueDescriptorProto"
)
// Field names for google.protobuf.EnumValueDescriptorProto.
const (
EnumValueDescriptorProto_Name_field_name protoreflect.Name = "name"
EnumValueDescriptorProto_Number_field_name protoreflect.Name = "number"
EnumValueDescriptorProto_Options_field_name protoreflect.Name = "options"
EnumValueDescriptorProto_Name_field_fullname protoreflect.FullName = "google.protobuf.EnumValueDescriptorProto.name"
EnumValueDescriptorProto_Number_field_fullname protoreflect.FullName = "google.protobuf.EnumValueDescriptorProto.number"
EnumValueDescriptorProto_Options_field_fullname protoreflect.FullName = "google.protobuf.EnumValueDescriptorProto.options"
)
// Field numbers for google.protobuf.EnumValueDescriptorProto.
const (
EnumValueDescriptorProto_Name_field_number protoreflect.FieldNumber = 1
EnumValueDescriptorProto_Number_field_number protoreflect.FieldNumber = 2
EnumValueDescriptorProto_Options_field_number protoreflect.FieldNumber = 3
)
// Names for google.protobuf.ServiceDescriptorProto.
const (
ServiceDescriptorProto_message_name protoreflect.Name = "ServiceDescriptorProto"
ServiceDescriptorProto_message_fullname protoreflect.FullName = "google.protobuf.ServiceDescriptorProto"
)
// Field names for google.protobuf.ServiceDescriptorProto.
const (
ServiceDescriptorProto_Name_field_name protoreflect.Name = "name"
ServiceDescriptorProto_Method_field_name protoreflect.Name = "method"
ServiceDescriptorProto_Options_field_name protoreflect.Name = "options"
ServiceDescriptorProto_Name_field_fullname protoreflect.FullName = "google.protobuf.ServiceDescriptorProto.name"
ServiceDescriptorProto_Method_field_fullname protoreflect.FullName = "google.protobuf.ServiceDescriptorProto.method"
ServiceDescriptorProto_Options_field_fullname protoreflect.FullName = "google.protobuf.ServiceDescriptorProto.options"
)
// Field numbers for google.protobuf.ServiceDescriptorProto.
const (
ServiceDescriptorProto_Name_field_number protoreflect.FieldNumber = 1
ServiceDescriptorProto_Method_field_number protoreflect.FieldNumber = 2
ServiceDescriptorProto_Options_field_number protoreflect.FieldNumber = 3
)
// Names for google.protobuf.MethodDescriptorProto.
const (
MethodDescriptorProto_message_name protoreflect.Name = "MethodDescriptorProto"
MethodDescriptorProto_message_fullname protoreflect.FullName = "google.protobuf.MethodDescriptorProto"
)
// Field names for google.protobuf.MethodDescriptorProto.
const (
MethodDescriptorProto_Name_field_name protoreflect.Name = "name"
MethodDescriptorProto_InputType_field_name protoreflect.Name = "input_type"
MethodDescriptorProto_OutputType_field_name protoreflect.Name = "output_type"
MethodDescriptorProto_Options_field_name protoreflect.Name = "options"
MethodDescriptorProto_ClientStreaming_field_name protoreflect.Name = "client_streaming"
MethodDescriptorProto_ServerStreaming_field_name protoreflect.Name = "server_streaming"
MethodDescriptorProto_Name_field_fullname protoreflect.FullName = "google.protobuf.MethodDescriptorProto.name"
MethodDescriptorProto_InputType_field_fullname protoreflect.FullName = "google.protobuf.MethodDescriptorProto.input_type"
MethodDescriptorProto_OutputType_field_fullname protoreflect.FullName = "google.protobuf.MethodDescriptorProto.output_type"
MethodDescriptorProto_Options_field_fullname protoreflect.FullName = "google.protobuf.MethodDescriptorProto.options"
MethodDescriptorProto_ClientStreaming_field_fullname protoreflect.FullName = "google.protobuf.MethodDescriptorProto.client_streaming"
MethodDescriptorProto_ServerStreaming_field_fullname protoreflect.FullName = "google.protobuf.MethodDescriptorProto.server_streaming"
)
// Field numbers for google.protobuf.MethodDescriptorProto.
const (
MethodDescriptorProto_Name_field_number protoreflect.FieldNumber = 1
MethodDescriptorProto_InputType_field_number protoreflect.FieldNumber = 2
MethodDescriptorProto_OutputType_field_number protoreflect.FieldNumber = 3
MethodDescriptorProto_Options_field_number protoreflect.FieldNumber = 4
MethodDescriptorProto_ClientStreaming_field_number protoreflect.FieldNumber = 5
MethodDescriptorProto_ServerStreaming_field_number protoreflect.FieldNumber = 6
)
// Names for google.protobuf.FileOptions.
const (
FileOptions_message_name protoreflect.Name = "FileOptions"
FileOptions_message_fullname protoreflect.FullName = "google.protobuf.FileOptions"
)
// Field names for google.protobuf.FileOptions.
const (
FileOptions_JavaPackage_field_name protoreflect.Name = "java_package"
FileOptions_JavaOuterClassname_field_name protoreflect.Name = "java_outer_classname"
FileOptions_JavaMultipleFiles_field_name protoreflect.Name = "java_multiple_files"
FileOptions_JavaGenerateEqualsAndHash_field_name protoreflect.Name = "java_generate_equals_and_hash"
FileOptions_JavaStringCheckUtf8_field_name protoreflect.Name = "java_string_check_utf8"
FileOptions_OptimizeFor_field_name protoreflect.Name = "optimize_for"
FileOptions_GoPackage_field_name protoreflect.Name = "go_package"
FileOptions_CcGenericServices_field_name protoreflect.Name = "cc_generic_services"
FileOptions_JavaGenericServices_field_name protoreflect.Name = "java_generic_services"
FileOptions_PyGenericServices_field_name protoreflect.Name = "py_generic_services"
FileOptions_PhpGenericServices_field_name protoreflect.Name = "php_generic_services"
FileOptions_Deprecated_field_name protoreflect.Name = "deprecated"
FileOptions_CcEnableArenas_field_name protoreflect.Name = "cc_enable_arenas"
FileOptions_ObjcClassPrefix_field_name protoreflect.Name = "objc_class_prefix"
FileOptions_CsharpNamespace_field_name protoreflect.Name = "csharp_namespace"
FileOptions_SwiftPrefix_field_name protoreflect.Name = "swift_prefix"
FileOptions_PhpClassPrefix_field_name protoreflect.Name = "php_class_prefix"
FileOptions_PhpNamespace_field_name protoreflect.Name = "php_namespace"
FileOptions_PhpMetadataNamespace_field_name protoreflect.Name = "php_metadata_namespace"
FileOptions_RubyPackage_field_name protoreflect.Name = "ruby_package"
FileOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option"
FileOptions_JavaPackage_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.java_package"
FileOptions_JavaOuterClassname_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.java_outer_classname"
FileOptions_JavaMultipleFiles_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.java_multiple_files"
FileOptions_JavaGenerateEqualsAndHash_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.java_generate_equals_and_hash"
FileOptions_JavaStringCheckUtf8_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.java_string_check_utf8"
FileOptions_OptimizeFor_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.optimize_for"
FileOptions_GoPackage_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.go_package"
FileOptions_CcGenericServices_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.cc_generic_services"
FileOptions_JavaGenericServices_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.java_generic_services"
FileOptions_PyGenericServices_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.py_generic_services"
FileOptions_PhpGenericServices_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.php_generic_services"
FileOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.deprecated"
FileOptions_CcEnableArenas_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.cc_enable_arenas"
FileOptions_ObjcClassPrefix_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.objc_class_prefix"
FileOptions_CsharpNamespace_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.csharp_namespace"
FileOptions_SwiftPrefix_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.swift_prefix"
FileOptions_PhpClassPrefix_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.php_class_prefix"
FileOptions_PhpNamespace_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.php_namespace"
FileOptions_PhpMetadataNamespace_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.php_metadata_namespace"
FileOptions_RubyPackage_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.ruby_package"
FileOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.uninterpreted_option"
)
// Field numbers for google.protobuf.FileOptions.
const (
FileOptions_JavaPackage_field_number protoreflect.FieldNumber = 1
FileOptions_JavaOuterClassname_field_number protoreflect.FieldNumber = 8
FileOptions_JavaMultipleFiles_field_number protoreflect.FieldNumber = 10
FileOptions_JavaGenerateEqualsAndHash_field_number protoreflect.FieldNumber = 20
FileOptions_JavaStringCheckUtf8_field_number protoreflect.FieldNumber = 27
FileOptions_OptimizeFor_field_number protoreflect.FieldNumber = 9
FileOptions_GoPackage_field_number protoreflect.FieldNumber = 11
FileOptions_CcGenericServices_field_number protoreflect.FieldNumber = 16
FileOptions_JavaGenericServices_field_number protoreflect.FieldNumber = 17
FileOptions_PyGenericServices_field_number protoreflect.FieldNumber = 18
FileOptions_PhpGenericServices_field_number protoreflect.FieldNumber = 42
FileOptions_Deprecated_field_number protoreflect.FieldNumber = 23
FileOptions_CcEnableArenas_field_number protoreflect.FieldNumber = 31
FileOptions_ObjcClassPrefix_field_number protoreflect.FieldNumber = 36
FileOptions_CsharpNamespace_field_number protoreflect.FieldNumber = 37
FileOptions_SwiftPrefix_field_number protoreflect.FieldNumber = 39
FileOptions_PhpClassPrefix_field_number protoreflect.FieldNumber = 40
FileOptions_PhpNamespace_field_number protoreflect.FieldNumber = 41
FileOptions_PhpMetadataNamespace_field_number protoreflect.FieldNumber = 44
FileOptions_RubyPackage_field_number protoreflect.FieldNumber = 45
FileOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999
)
// Full and short names for google.protobuf.FileOptions.OptimizeMode.
const (
FileOptions_OptimizeMode_enum_fullname = "google.protobuf.FileOptions.OptimizeMode"
FileOptions_OptimizeMode_enum_name = "OptimizeMode"
)
// Names for google.protobuf.MessageOptions.
const (
MessageOptions_message_name protoreflect.Name = "MessageOptions"
MessageOptions_message_fullname protoreflect.FullName = "google.protobuf.MessageOptions"
)
// Field names for google.protobuf.MessageOptions.
const (
MessageOptions_MessageSetWireFormat_field_name protoreflect.Name = "message_set_wire_format"
MessageOptions_NoStandardDescriptorAccessor_field_name protoreflect.Name = "no_standard_descriptor_accessor"
MessageOptions_Deprecated_field_name protoreflect.Name = "deprecated"
MessageOptions_MapEntry_field_name protoreflect.Name = "map_entry"
MessageOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option"
MessageOptions_MessageSetWireFormat_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.message_set_wire_format"
MessageOptions_NoStandardDescriptorAccessor_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.no_standard_descriptor_accessor"
MessageOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.deprecated"
MessageOptions_MapEntry_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.map_entry"
MessageOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.uninterpreted_option"
)
// Field numbers for google.protobuf.MessageOptions.
const (
MessageOptions_MessageSetWireFormat_field_number protoreflect.FieldNumber = 1
MessageOptions_NoStandardDescriptorAccessor_field_number protoreflect.FieldNumber = 2
MessageOptions_Deprecated_field_number protoreflect.FieldNumber = 3
MessageOptions_MapEntry_field_number protoreflect.FieldNumber = 7
MessageOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999
)
// Names for google.protobuf.FieldOptions.
const (
FieldOptions_message_name protoreflect.Name = "FieldOptions"
FieldOptions_message_fullname protoreflect.FullName = "google.protobuf.FieldOptions"
)
// Field names for google.protobuf.FieldOptions.
const (
FieldOptions_Ctype_field_name protoreflect.Name = "ctype"
FieldOptions_Packed_field_name protoreflect.Name = "packed"
FieldOptions_Jstype_field_name protoreflect.Name = "jstype"
FieldOptions_Lazy_field_name protoreflect.Name = "lazy"
FieldOptions_Deprecated_field_name protoreflect.Name = "deprecated"
FieldOptions_Weak_field_name protoreflect.Name = "weak"
FieldOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option"
FieldOptions_Ctype_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.ctype"
FieldOptions_Packed_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.packed"
FieldOptions_Jstype_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.jstype"
FieldOptions_Lazy_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.lazy"
FieldOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.deprecated"
FieldOptions_Weak_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.weak"
FieldOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.uninterpreted_option"
)
// Field numbers for google.protobuf.FieldOptions.
const (
FieldOptions_Ctype_field_number protoreflect.FieldNumber = 1
FieldOptions_Packed_field_number protoreflect.FieldNumber = 2
FieldOptions_Jstype_field_number protoreflect.FieldNumber = 6
FieldOptions_Lazy_field_number protoreflect.FieldNumber = 5
FieldOptions_Deprecated_field_number protoreflect.FieldNumber = 3
FieldOptions_Weak_field_number protoreflect.FieldNumber = 10
FieldOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999
)
// Full and short names for google.protobuf.FieldOptions.CType.
const (
FieldOptions_CType_enum_fullname = "google.protobuf.FieldOptions.CType"
FieldOptions_CType_enum_name = "CType"
)
// Full and short names for google.protobuf.FieldOptions.JSType.
const (
FieldOptions_JSType_enum_fullname = "google.protobuf.FieldOptions.JSType"
FieldOptions_JSType_enum_name = "JSType"
)
// Names for google.protobuf.OneofOptions.
const (
OneofOptions_message_name protoreflect.Name = "OneofOptions"
OneofOptions_message_fullname protoreflect.FullName = "google.protobuf.OneofOptions"
)
// Field names for google.protobuf.OneofOptions.
const (
OneofOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option"
OneofOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.OneofOptions.uninterpreted_option"
)
// Field numbers for google.protobuf.OneofOptions.
const (
OneofOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999
)
// Names for google.protobuf.EnumOptions.
const (
EnumOptions_message_name protoreflect.Name = "EnumOptions"
EnumOptions_message_fullname protoreflect.FullName = "google.protobuf.EnumOptions"
)
// Field names for google.protobuf.EnumOptions.
const (
EnumOptions_AllowAlias_field_name protoreflect.Name = "allow_alias"
EnumOptions_Deprecated_field_name protoreflect.Name = "deprecated"
EnumOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option"
EnumOptions_AllowAlias_field_fullname protoreflect.FullName = "google.protobuf.EnumOptions.allow_alias"
EnumOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.EnumOptions.deprecated"
EnumOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.EnumOptions.uninterpreted_option"
)
// Field numbers for google.protobuf.EnumOptions.
const (
EnumOptions_AllowAlias_field_number protoreflect.FieldNumber = 2
EnumOptions_Deprecated_field_number protoreflect.FieldNumber = 3
EnumOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999
)
// Names for google.protobuf.EnumValueOptions.
const (
EnumValueOptions_message_name protoreflect.Name = "EnumValueOptions"
EnumValueOptions_message_fullname protoreflect.FullName = "google.protobuf.EnumValueOptions"
)
// Field names for google.protobuf.EnumValueOptions.
const (
EnumValueOptions_Deprecated_field_name protoreflect.Name = "deprecated"
EnumValueOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option"
EnumValueOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.EnumValueOptions.deprecated"
EnumValueOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.EnumValueOptions.uninterpreted_option"
)
// Field numbers for google.protobuf.EnumValueOptions.
const (
EnumValueOptions_Deprecated_field_number protoreflect.FieldNumber = 1
EnumValueOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999
)
// Names for google.protobuf.ServiceOptions.
const (
ServiceOptions_message_name protoreflect.Name = "ServiceOptions"
ServiceOptions_message_fullname protoreflect.FullName = "google.protobuf.ServiceOptions"
)
// Field names for google.protobuf.ServiceOptions.
const (
ServiceOptions_Deprecated_field_name protoreflect.Name = "deprecated"
ServiceOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option"
ServiceOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.ServiceOptions.deprecated"
ServiceOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.ServiceOptions.uninterpreted_option"
)
// Field numbers for google.protobuf.ServiceOptions.
const (
ServiceOptions_Deprecated_field_number protoreflect.FieldNumber = 33
ServiceOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999
)
// Names for google.protobuf.MethodOptions.
const (
MethodOptions_message_name protoreflect.Name = "MethodOptions"
MethodOptions_message_fullname protoreflect.FullName = "google.protobuf.MethodOptions"
)
// Field names for google.protobuf.MethodOptions.
const (
MethodOptions_Deprecated_field_name protoreflect.Name = "deprecated"
MethodOptions_IdempotencyLevel_field_name protoreflect.Name = "idempotency_level"
MethodOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option"
MethodOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.MethodOptions.deprecated"
MethodOptions_IdempotencyLevel_field_fullname protoreflect.FullName = "google.protobuf.MethodOptions.idempotency_level"
MethodOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.MethodOptions.uninterpreted_option"
)
// Field numbers for google.protobuf.MethodOptions.
const (
MethodOptions_Deprecated_field_number protoreflect.FieldNumber = 33
MethodOptions_IdempotencyLevel_field_number protoreflect.FieldNumber = 34
MethodOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999
)
// Full and short names for google.protobuf.MethodOptions.IdempotencyLevel.
const (
MethodOptions_IdempotencyLevel_enum_fullname = "google.protobuf.MethodOptions.IdempotencyLevel"
MethodOptions_IdempotencyLevel_enum_name = "IdempotencyLevel"
)
// Names for google.protobuf.UninterpretedOption.
const (
UninterpretedOption_message_name protoreflect.Name = "UninterpretedOption"
UninterpretedOption_message_fullname protoreflect.FullName = "google.protobuf.UninterpretedOption"
)
// Field names for google.protobuf.UninterpretedOption.
const (
UninterpretedOption_Name_field_name protoreflect.Name = "name"
UninterpretedOption_IdentifierValue_field_name protoreflect.Name = "identifier_value"
UninterpretedOption_PositiveIntValue_field_name protoreflect.Name = "positive_int_value"
UninterpretedOption_NegativeIntValue_field_name protoreflect.Name = "negative_int_value"
UninterpretedOption_DoubleValue_field_name protoreflect.Name = "double_value"
UninterpretedOption_StringValue_field_name protoreflect.Name = "string_value"
UninterpretedOption_AggregateValue_field_name protoreflect.Name = "aggregate_value"
UninterpretedOption_Name_field_fullname protoreflect.FullName = "google.protobuf.UninterpretedOption.name"
UninterpretedOption_IdentifierValue_field_fullname protoreflect.FullName = "google.protobuf.UninterpretedOption.identifier_value"
UninterpretedOption_PositiveIntValue_field_fullname protoreflect.FullName = "google.protobuf.UninterpretedOption.positive_int_value"
UninterpretedOption_NegativeIntValue_field_fullname protoreflect.FullName = "google.protobuf.UninterpretedOption.negative_int_value"
UninterpretedOption_DoubleValue_field_fullname protoreflect.FullName = "google.protobuf.UninterpretedOption.double_value"
UninterpretedOption_StringValue_field_fullname protoreflect.FullName = "google.protobuf.UninterpretedOption.string_value"
UninterpretedOption_AggregateValue_field_fullname protoreflect.FullName = "google.protobuf.UninterpretedOption.aggregate_value"
)
// Field numbers for google.protobuf.UninterpretedOption.
const (
UninterpretedOption_Name_field_number protoreflect.FieldNumber = 2
UninterpretedOption_IdentifierValue_field_number protoreflect.FieldNumber = 3
UninterpretedOption_PositiveIntValue_field_number protoreflect.FieldNumber = 4
UninterpretedOption_NegativeIntValue_field_number protoreflect.FieldNumber = 5
UninterpretedOption_DoubleValue_field_number protoreflect.FieldNumber = 6
UninterpretedOption_StringValue_field_number protoreflect.FieldNumber = 7
UninterpretedOption_AggregateValue_field_number protoreflect.FieldNumber = 8
)
// Names for google.protobuf.UninterpretedOption.NamePart.
const (
UninterpretedOption_NamePart_message_name protoreflect.Name = "NamePart"
UninterpretedOption_NamePart_message_fullname protoreflect.FullName = "google.protobuf.UninterpretedOption.NamePart"
)
// Field names for google.protobuf.UninterpretedOption.NamePart.
const (
UninterpretedOption_NamePart_NamePart_field_name protoreflect.Name = "name_part"
UninterpretedOption_NamePart_IsExtension_field_name protoreflect.Name = "is_extension"
UninterpretedOption_NamePart_NamePart_field_fullname protoreflect.FullName = "google.protobuf.UninterpretedOption.NamePart.name_part"
UninterpretedOption_NamePart_IsExtension_field_fullname protoreflect.FullName = "google.protobuf.UninterpretedOption.NamePart.is_extension"
)
// Field numbers for google.protobuf.UninterpretedOption.NamePart.
const (
UninterpretedOption_NamePart_NamePart_field_number protoreflect.FieldNumber = 1
UninterpretedOption_NamePart_IsExtension_field_number protoreflect.FieldNumber = 2
)
// Names for google.protobuf.SourceCodeInfo.
const (
SourceCodeInfo_message_name protoreflect.Name = "SourceCodeInfo"
SourceCodeInfo_message_fullname protoreflect.FullName = "google.protobuf.SourceCodeInfo"
)
// Field names for google.protobuf.SourceCodeInfo.
const (
SourceCodeInfo_Location_field_name protoreflect.Name = "location"
SourceCodeInfo_Location_field_fullname protoreflect.FullName = "google.protobuf.SourceCodeInfo.location"
)
// Field numbers for google.protobuf.SourceCodeInfo.
const (
SourceCodeInfo_Location_field_number protoreflect.FieldNumber = 1
)
// Names for google.protobuf.SourceCodeInfo.Location.
const (
SourceCodeInfo_Location_message_name protoreflect.Name = "Location"
SourceCodeInfo_Location_message_fullname protoreflect.FullName = "google.protobuf.SourceCodeInfo.Location"
)
// Field names for google.protobuf.SourceCodeInfo.Location.
const (
SourceCodeInfo_Location_Path_field_name protoreflect.Name = "path"
SourceCodeInfo_Location_Span_field_name protoreflect.Name = "span"
SourceCodeInfo_Location_LeadingComments_field_name protoreflect.Name = "leading_comments"
SourceCodeInfo_Location_TrailingComments_field_name protoreflect.Name = "trailing_comments"
SourceCodeInfo_Location_LeadingDetachedComments_field_name protoreflect.Name = "leading_detached_comments"
SourceCodeInfo_Location_Path_field_fullname protoreflect.FullName = "google.protobuf.SourceCodeInfo.Location.path"
SourceCodeInfo_Location_Span_field_fullname protoreflect.FullName = "google.protobuf.SourceCodeInfo.Location.span"
SourceCodeInfo_Location_LeadingComments_field_fullname protoreflect.FullName = "google.protobuf.SourceCodeInfo.Location.leading_comments"
SourceCodeInfo_Location_TrailingComments_field_fullname protoreflect.FullName = "google.protobuf.SourceCodeInfo.Location.trailing_comments"
SourceCodeInfo_Location_LeadingDetachedComments_field_fullname protoreflect.FullName = "google.protobuf.SourceCodeInfo.Location.leading_detached_comments"
)
// Field numbers for google.protobuf.SourceCodeInfo.Location.
const (
SourceCodeInfo_Location_Path_field_number protoreflect.FieldNumber = 1
SourceCodeInfo_Location_Span_field_number protoreflect.FieldNumber = 2
SourceCodeInfo_Location_LeadingComments_field_number protoreflect.FieldNumber = 3
SourceCodeInfo_Location_TrailingComments_field_number protoreflect.FieldNumber = 4
SourceCodeInfo_Location_LeadingDetachedComments_field_number protoreflect.FieldNumber = 6
)
// Names for google.protobuf.GeneratedCodeInfo.
const (
GeneratedCodeInfo_message_name protoreflect.Name = "GeneratedCodeInfo"
GeneratedCodeInfo_message_fullname protoreflect.FullName = "google.protobuf.GeneratedCodeInfo"
)
// Field names for google.protobuf.GeneratedCodeInfo.
const (
GeneratedCodeInfo_Annotation_field_name protoreflect.Name = "annotation"
GeneratedCodeInfo_Annotation_field_fullname protoreflect.FullName = "google.protobuf.GeneratedCodeInfo.annotation"
)
// Field numbers for google.protobuf.GeneratedCodeInfo.
const (
GeneratedCodeInfo_Annotation_field_number protoreflect.FieldNumber = 1
)
// Names for google.protobuf.GeneratedCodeInfo.Annotation.
const (
GeneratedCodeInfo_Annotation_message_name protoreflect.Name = "Annotation"
GeneratedCodeInfo_Annotation_message_fullname protoreflect.FullName = "google.protobuf.GeneratedCodeInfo.Annotation"
)
// Field names for google.protobuf.GeneratedCodeInfo.Annotation.
const (
GeneratedCodeInfo_Annotation_Path_field_name protoreflect.Name = "path"
GeneratedCodeInfo_Annotation_SourceFile_field_name protoreflect.Name = "source_file"
GeneratedCodeInfo_Annotation_Begin_field_name protoreflect.Name = "begin"
GeneratedCodeInfo_Annotation_End_field_name protoreflect.Name = "end"
GeneratedCodeInfo_Annotation_Path_field_fullname protoreflect.FullName = "google.protobuf.GeneratedCodeInfo.Annotation.path"
GeneratedCodeInfo_Annotation_SourceFile_field_fullname protoreflect.FullName = "google.protobuf.GeneratedCodeInfo.Annotation.source_file"
GeneratedCodeInfo_Annotation_Begin_field_fullname protoreflect.FullName = "google.protobuf.GeneratedCodeInfo.Annotation.begin"
GeneratedCodeInfo_Annotation_End_field_fullname protoreflect.FullName = "google.protobuf.GeneratedCodeInfo.Annotation.end"
)
// Field numbers for google.protobuf.GeneratedCodeInfo.Annotation.
const (
GeneratedCodeInfo_Annotation_Path_field_number protoreflect.FieldNumber = 1
GeneratedCodeInfo_Annotation_SourceFile_field_number protoreflect.FieldNumber = 2
GeneratedCodeInfo_Annotation_Begin_field_number protoreflect.FieldNumber = 3
GeneratedCodeInfo_Annotation_End_field_number protoreflect.FieldNumber = 4
)

View File

@ -0,0 +1,11 @@
// 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 genid contains constants for declarations in descriptor.proto
// and the well-known types.
package genid
import protoreflect "google.golang.org/protobuf/reflect/protoreflect"
const GoogleProtobuf_package protoreflect.FullName = "google.protobuf"

View File

@ -0,0 +1,34 @@
// 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.
// Code generated by generate-protos. DO NOT EDIT.
package genid
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
)
const File_google_protobuf_duration_proto = "google/protobuf/duration.proto"
// Names for google.protobuf.Duration.
const (
Duration_message_name protoreflect.Name = "Duration"
Duration_message_fullname protoreflect.FullName = "google.protobuf.Duration"
)
// Field names for google.protobuf.Duration.
const (
Duration_Seconds_field_name protoreflect.Name = "seconds"
Duration_Nanos_field_name protoreflect.Name = "nanos"
Duration_Seconds_field_fullname protoreflect.FullName = "google.protobuf.Duration.seconds"
Duration_Nanos_field_fullname protoreflect.FullName = "google.protobuf.Duration.nanos"
)
// Field numbers for google.protobuf.Duration.
const (
Duration_Seconds_field_number protoreflect.FieldNumber = 1
Duration_Nanos_field_number protoreflect.FieldNumber = 2
)

View File

@ -0,0 +1,19 @@
// 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.
// Code generated by generate-protos. DO NOT EDIT.
package genid
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
)
const File_google_protobuf_empty_proto = "google/protobuf/empty.proto"
// Names for google.protobuf.Empty.
const (
Empty_message_name protoreflect.Name = "Empty"
Empty_message_fullname protoreflect.FullName = "google.protobuf.Empty"
)

View File

@ -0,0 +1,31 @@
// 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.
// Code generated by generate-protos. DO NOT EDIT.
package genid
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
)
const File_google_protobuf_field_mask_proto = "google/protobuf/field_mask.proto"
// Names for google.protobuf.FieldMask.
const (
FieldMask_message_name protoreflect.Name = "FieldMask"
FieldMask_message_fullname protoreflect.FullName = "google.protobuf.FieldMask"
)
// Field names for google.protobuf.FieldMask.
const (
FieldMask_Paths_field_name protoreflect.Name = "paths"
FieldMask_Paths_field_fullname protoreflect.FullName = "google.protobuf.FieldMask.paths"
)
// Field numbers for google.protobuf.FieldMask.
const (
FieldMask_Paths_field_number protoreflect.FieldNumber = 1
)

View File

@ -0,0 +1,25 @@
// 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 genid
// Go names of implementation-specific struct fields in generated messages.
const (
State_goname = "state"
SizeCache_goname = "sizeCache"
SizeCacheA_goname = "XXX_sizecache"
WeakFields_goname = "weakFields"
WeakFieldsA_goname = "XXX_weak"
UnknownFields_goname = "unknownFields"
UnknownFieldsA_goname = "XXX_unrecognized"
ExtensionFields_goname = "extensionFields"
ExtensionFieldsA_goname = "XXX_InternalExtensions"
ExtensionFieldsB_goname = "XXX_extensions"
WeakFieldPrefix_goname = "XXX_weak_"
)

View File

@ -0,0 +1,16 @@
// 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 genid
import protoreflect "google.golang.org/protobuf/reflect/protoreflect"
// Generic field names and numbers for synthetic map entry messages.
const (
MapEntry_Key_field_name protoreflect.Name = "key"
MapEntry_Value_field_name protoreflect.Name = "value"
MapEntry_Key_field_number protoreflect.FieldNumber = 1
MapEntry_Value_field_number protoreflect.FieldNumber = 2
)

View File

@ -0,0 +1,31 @@
// 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.
// Code generated by generate-protos. DO NOT EDIT.
package genid
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
)
const File_google_protobuf_source_context_proto = "google/protobuf/source_context.proto"
// Names for google.protobuf.SourceContext.
const (
SourceContext_message_name protoreflect.Name = "SourceContext"
SourceContext_message_fullname protoreflect.FullName = "google.protobuf.SourceContext"
)
// Field names for google.protobuf.SourceContext.
const (
SourceContext_FileName_field_name protoreflect.Name = "file_name"
SourceContext_FileName_field_fullname protoreflect.FullName = "google.protobuf.SourceContext.file_name"
)
// Field numbers for google.protobuf.SourceContext.
const (
SourceContext_FileName_field_number protoreflect.FieldNumber = 1
)

View File

@ -0,0 +1,116 @@
// 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.
// Code generated by generate-protos. DO NOT EDIT.
package genid
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
)
const File_google_protobuf_struct_proto = "google/protobuf/struct.proto"
// Full and short names for google.protobuf.NullValue.
const (
NullValue_enum_fullname = "google.protobuf.NullValue"
NullValue_enum_name = "NullValue"
)
// Names for google.protobuf.Struct.
const (
Struct_message_name protoreflect.Name = "Struct"
Struct_message_fullname protoreflect.FullName = "google.protobuf.Struct"
)
// Field names for google.protobuf.Struct.
const (
Struct_Fields_field_name protoreflect.Name = "fields"
Struct_Fields_field_fullname protoreflect.FullName = "google.protobuf.Struct.fields"
)
// Field numbers for google.protobuf.Struct.
const (
Struct_Fields_field_number protoreflect.FieldNumber = 1
)
// Names for google.protobuf.Struct.FieldsEntry.
const (
Struct_FieldsEntry_message_name protoreflect.Name = "FieldsEntry"
Struct_FieldsEntry_message_fullname protoreflect.FullName = "google.protobuf.Struct.FieldsEntry"
)
// Field names for google.protobuf.Struct.FieldsEntry.
const (
Struct_FieldsEntry_Key_field_name protoreflect.Name = "key"
Struct_FieldsEntry_Value_field_name protoreflect.Name = "value"
Struct_FieldsEntry_Key_field_fullname protoreflect.FullName = "google.protobuf.Struct.FieldsEntry.key"
Struct_FieldsEntry_Value_field_fullname protoreflect.FullName = "google.protobuf.Struct.FieldsEntry.value"
)
// Field numbers for google.protobuf.Struct.FieldsEntry.
const (
Struct_FieldsEntry_Key_field_number protoreflect.FieldNumber = 1
Struct_FieldsEntry_Value_field_number protoreflect.FieldNumber = 2
)
// Names for google.protobuf.Value.
const (
Value_message_name protoreflect.Name = "Value"
Value_message_fullname protoreflect.FullName = "google.protobuf.Value"
)
// Field names for google.protobuf.Value.
const (
Value_NullValue_field_name protoreflect.Name = "null_value"
Value_NumberValue_field_name protoreflect.Name = "number_value"
Value_StringValue_field_name protoreflect.Name = "string_value"
Value_BoolValue_field_name protoreflect.Name = "bool_value"
Value_StructValue_field_name protoreflect.Name = "struct_value"
Value_ListValue_field_name protoreflect.Name = "list_value"
Value_NullValue_field_fullname protoreflect.FullName = "google.protobuf.Value.null_value"
Value_NumberValue_field_fullname protoreflect.FullName = "google.protobuf.Value.number_value"
Value_StringValue_field_fullname protoreflect.FullName = "google.protobuf.Value.string_value"
Value_BoolValue_field_fullname protoreflect.FullName = "google.protobuf.Value.bool_value"
Value_StructValue_field_fullname protoreflect.FullName = "google.protobuf.Value.struct_value"
Value_ListValue_field_fullname protoreflect.FullName = "google.protobuf.Value.list_value"
)
// Field numbers for google.protobuf.Value.
const (
Value_NullValue_field_number protoreflect.FieldNumber = 1
Value_NumberValue_field_number protoreflect.FieldNumber = 2
Value_StringValue_field_number protoreflect.FieldNumber = 3
Value_BoolValue_field_number protoreflect.FieldNumber = 4
Value_StructValue_field_number protoreflect.FieldNumber = 5
Value_ListValue_field_number protoreflect.FieldNumber = 6
)
// Oneof names for google.protobuf.Value.
const (
Value_Kind_oneof_name protoreflect.Name = "kind"
Value_Kind_oneof_fullname protoreflect.FullName = "google.protobuf.Value.kind"
)
// Names for google.protobuf.ListValue.
const (
ListValue_message_name protoreflect.Name = "ListValue"
ListValue_message_fullname protoreflect.FullName = "google.protobuf.ListValue"
)
// Field names for google.protobuf.ListValue.
const (
ListValue_Values_field_name protoreflect.Name = "values"
ListValue_Values_field_fullname protoreflect.FullName = "google.protobuf.ListValue.values"
)
// Field numbers for google.protobuf.ListValue.
const (
ListValue_Values_field_number protoreflect.FieldNumber = 1
)

View File

@ -0,0 +1,34 @@
// 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.
// Code generated by generate-protos. DO NOT EDIT.
package genid
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
)
const File_google_protobuf_timestamp_proto = "google/protobuf/timestamp.proto"
// Names for google.protobuf.Timestamp.
const (
Timestamp_message_name protoreflect.Name = "Timestamp"
Timestamp_message_fullname protoreflect.FullName = "google.protobuf.Timestamp"
)
// Field names for google.protobuf.Timestamp.
const (
Timestamp_Seconds_field_name protoreflect.Name = "seconds"
Timestamp_Nanos_field_name protoreflect.Name = "nanos"
Timestamp_Seconds_field_fullname protoreflect.FullName = "google.protobuf.Timestamp.seconds"
Timestamp_Nanos_field_fullname protoreflect.FullName = "google.protobuf.Timestamp.nanos"
)
// Field numbers for google.protobuf.Timestamp.
const (
Timestamp_Seconds_field_number protoreflect.FieldNumber = 1
Timestamp_Nanos_field_number protoreflect.FieldNumber = 2
)

View File

@ -0,0 +1,184 @@
// 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.
// Code generated by generate-protos. DO NOT EDIT.
package genid
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
)
const File_google_protobuf_type_proto = "google/protobuf/type.proto"
// Full and short names for google.protobuf.Syntax.
const (
Syntax_enum_fullname = "google.protobuf.Syntax"
Syntax_enum_name = "Syntax"
)
// Names for google.protobuf.Type.
const (
Type_message_name protoreflect.Name = "Type"
Type_message_fullname protoreflect.FullName = "google.protobuf.Type"
)
// Field names for google.protobuf.Type.
const (
Type_Name_field_name protoreflect.Name = "name"
Type_Fields_field_name protoreflect.Name = "fields"
Type_Oneofs_field_name protoreflect.Name = "oneofs"
Type_Options_field_name protoreflect.Name = "options"
Type_SourceContext_field_name protoreflect.Name = "source_context"
Type_Syntax_field_name protoreflect.Name = "syntax"
Type_Name_field_fullname protoreflect.FullName = "google.protobuf.Type.name"
Type_Fields_field_fullname protoreflect.FullName = "google.protobuf.Type.fields"
Type_Oneofs_field_fullname protoreflect.FullName = "google.protobuf.Type.oneofs"
Type_Options_field_fullname protoreflect.FullName = "google.protobuf.Type.options"
Type_SourceContext_field_fullname protoreflect.FullName = "google.protobuf.Type.source_context"
Type_Syntax_field_fullname protoreflect.FullName = "google.protobuf.Type.syntax"
)
// Field numbers for google.protobuf.Type.
const (
Type_Name_field_number protoreflect.FieldNumber = 1
Type_Fields_field_number protoreflect.FieldNumber = 2
Type_Oneofs_field_number protoreflect.FieldNumber = 3
Type_Options_field_number protoreflect.FieldNumber = 4
Type_SourceContext_field_number protoreflect.FieldNumber = 5
Type_Syntax_field_number protoreflect.FieldNumber = 6
)
// Names for google.protobuf.Field.
const (
Field_message_name protoreflect.Name = "Field"
Field_message_fullname protoreflect.FullName = "google.protobuf.Field"
)
// Field names for google.protobuf.Field.
const (
Field_Kind_field_name protoreflect.Name = "kind"
Field_Cardinality_field_name protoreflect.Name = "cardinality"
Field_Number_field_name protoreflect.Name = "number"
Field_Name_field_name protoreflect.Name = "name"
Field_TypeUrl_field_name protoreflect.Name = "type_url"
Field_OneofIndex_field_name protoreflect.Name = "oneof_index"
Field_Packed_field_name protoreflect.Name = "packed"
Field_Options_field_name protoreflect.Name = "options"
Field_JsonName_field_name protoreflect.Name = "json_name"
Field_DefaultValue_field_name protoreflect.Name = "default_value"
Field_Kind_field_fullname protoreflect.FullName = "google.protobuf.Field.kind"
Field_Cardinality_field_fullname protoreflect.FullName = "google.protobuf.Field.cardinality"
Field_Number_field_fullname protoreflect.FullName = "google.protobuf.Field.number"
Field_Name_field_fullname protoreflect.FullName = "google.protobuf.Field.name"
Field_TypeUrl_field_fullname protoreflect.FullName = "google.protobuf.Field.type_url"
Field_OneofIndex_field_fullname protoreflect.FullName = "google.protobuf.Field.oneof_index"
Field_Packed_field_fullname protoreflect.FullName = "google.protobuf.Field.packed"
Field_Options_field_fullname protoreflect.FullName = "google.protobuf.Field.options"
Field_JsonName_field_fullname protoreflect.FullName = "google.protobuf.Field.json_name"
Field_DefaultValue_field_fullname protoreflect.FullName = "google.protobuf.Field.default_value"
)
// Field numbers for google.protobuf.Field.
const (
Field_Kind_field_number protoreflect.FieldNumber = 1
Field_Cardinality_field_number protoreflect.FieldNumber = 2
Field_Number_field_number protoreflect.FieldNumber = 3
Field_Name_field_number protoreflect.FieldNumber = 4
Field_TypeUrl_field_number protoreflect.FieldNumber = 6
Field_OneofIndex_field_number protoreflect.FieldNumber = 7
Field_Packed_field_number protoreflect.FieldNumber = 8
Field_Options_field_number protoreflect.FieldNumber = 9
Field_JsonName_field_number protoreflect.FieldNumber = 10
Field_DefaultValue_field_number protoreflect.FieldNumber = 11
)
// Full and short names for google.protobuf.Field.Kind.
const (
Field_Kind_enum_fullname = "google.protobuf.Field.Kind"
Field_Kind_enum_name = "Kind"
)
// Full and short names for google.protobuf.Field.Cardinality.
const (
Field_Cardinality_enum_fullname = "google.protobuf.Field.Cardinality"
Field_Cardinality_enum_name = "Cardinality"
)
// Names for google.protobuf.Enum.
const (
Enum_message_name protoreflect.Name = "Enum"
Enum_message_fullname protoreflect.FullName = "google.protobuf.Enum"
)
// Field names for google.protobuf.Enum.
const (
Enum_Name_field_name protoreflect.Name = "name"
Enum_Enumvalue_field_name protoreflect.Name = "enumvalue"
Enum_Options_field_name protoreflect.Name = "options"
Enum_SourceContext_field_name protoreflect.Name = "source_context"
Enum_Syntax_field_name protoreflect.Name = "syntax"
Enum_Name_field_fullname protoreflect.FullName = "google.protobuf.Enum.name"
Enum_Enumvalue_field_fullname protoreflect.FullName = "google.protobuf.Enum.enumvalue"
Enum_Options_field_fullname protoreflect.FullName = "google.protobuf.Enum.options"
Enum_SourceContext_field_fullname protoreflect.FullName = "google.protobuf.Enum.source_context"
Enum_Syntax_field_fullname protoreflect.FullName = "google.protobuf.Enum.syntax"
)
// Field numbers for google.protobuf.Enum.
const (
Enum_Name_field_number protoreflect.FieldNumber = 1
Enum_Enumvalue_field_number protoreflect.FieldNumber = 2
Enum_Options_field_number protoreflect.FieldNumber = 3
Enum_SourceContext_field_number protoreflect.FieldNumber = 4
Enum_Syntax_field_number protoreflect.FieldNumber = 5
)
// Names for google.protobuf.EnumValue.
const (
EnumValue_message_name protoreflect.Name = "EnumValue"
EnumValue_message_fullname protoreflect.FullName = "google.protobuf.EnumValue"
)
// Field names for google.protobuf.EnumValue.
const (
EnumValue_Name_field_name protoreflect.Name = "name"
EnumValue_Number_field_name protoreflect.Name = "number"
EnumValue_Options_field_name protoreflect.Name = "options"
EnumValue_Name_field_fullname protoreflect.FullName = "google.protobuf.EnumValue.name"
EnumValue_Number_field_fullname protoreflect.FullName = "google.protobuf.EnumValue.number"
EnumValue_Options_field_fullname protoreflect.FullName = "google.protobuf.EnumValue.options"
)
// Field numbers for google.protobuf.EnumValue.
const (
EnumValue_Name_field_number protoreflect.FieldNumber = 1
EnumValue_Number_field_number protoreflect.FieldNumber = 2
EnumValue_Options_field_number protoreflect.FieldNumber = 3
)
// Names for google.protobuf.Option.
const (
Option_message_name protoreflect.Name = "Option"
Option_message_fullname protoreflect.FullName = "google.protobuf.Option"
)
// Field names for google.protobuf.Option.
const (
Option_Name_field_name protoreflect.Name = "name"
Option_Value_field_name protoreflect.Name = "value"
Option_Name_field_fullname protoreflect.FullName = "google.protobuf.Option.name"
Option_Value_field_fullname protoreflect.FullName = "google.protobuf.Option.value"
)
// Field numbers for google.protobuf.Option.
const (
Option_Name_field_number protoreflect.FieldNumber = 1
Option_Value_field_number protoreflect.FieldNumber = 2
)

View File

@ -0,0 +1,13 @@
// 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 genid
import protoreflect "google.golang.org/protobuf/reflect/protoreflect"
// Generic field name and number for messages in wrappers.proto.
const (
WrapperValue_Value_field_name protoreflect.Name = "value"
WrapperValue_Value_field_number protoreflect.FieldNumber = 1
)

View File

@ -0,0 +1,175 @@
// 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.
// Code generated by generate-protos. DO NOT EDIT.
package genid
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
)
const File_google_protobuf_wrappers_proto = "google/protobuf/wrappers.proto"
// Names for google.protobuf.DoubleValue.
const (
DoubleValue_message_name protoreflect.Name = "DoubleValue"
DoubleValue_message_fullname protoreflect.FullName = "google.protobuf.DoubleValue"
)
// Field names for google.protobuf.DoubleValue.
const (
DoubleValue_Value_field_name protoreflect.Name = "value"
DoubleValue_Value_field_fullname protoreflect.FullName = "google.protobuf.DoubleValue.value"
)
// Field numbers for google.protobuf.DoubleValue.
const (
DoubleValue_Value_field_number protoreflect.FieldNumber = 1
)
// Names for google.protobuf.FloatValue.
const (
FloatValue_message_name protoreflect.Name = "FloatValue"
FloatValue_message_fullname protoreflect.FullName = "google.protobuf.FloatValue"
)
// Field names for google.protobuf.FloatValue.
const (
FloatValue_Value_field_name protoreflect.Name = "value"
FloatValue_Value_field_fullname protoreflect.FullName = "google.protobuf.FloatValue.value"
)
// Field numbers for google.protobuf.FloatValue.
const (
FloatValue_Value_field_number protoreflect.FieldNumber = 1
)
// Names for google.protobuf.Int64Value.
const (
Int64Value_message_name protoreflect.Name = "Int64Value"
Int64Value_message_fullname protoreflect.FullName = "google.protobuf.Int64Value"
)
// Field names for google.protobuf.Int64Value.
const (
Int64Value_Value_field_name protoreflect.Name = "value"
Int64Value_Value_field_fullname protoreflect.FullName = "google.protobuf.Int64Value.value"
)
// Field numbers for google.protobuf.Int64Value.
const (
Int64Value_Value_field_number protoreflect.FieldNumber = 1
)
// Names for google.protobuf.UInt64Value.
const (
UInt64Value_message_name protoreflect.Name = "UInt64Value"
UInt64Value_message_fullname protoreflect.FullName = "google.protobuf.UInt64Value"
)
// Field names for google.protobuf.UInt64Value.
const (
UInt64Value_Value_field_name protoreflect.Name = "value"
UInt64Value_Value_field_fullname protoreflect.FullName = "google.protobuf.UInt64Value.value"
)
// Field numbers for google.protobuf.UInt64Value.
const (
UInt64Value_Value_field_number protoreflect.FieldNumber = 1
)
// Names for google.protobuf.Int32Value.
const (
Int32Value_message_name protoreflect.Name = "Int32Value"
Int32Value_message_fullname protoreflect.FullName = "google.protobuf.Int32Value"
)
// Field names for google.protobuf.Int32Value.
const (
Int32Value_Value_field_name protoreflect.Name = "value"
Int32Value_Value_field_fullname protoreflect.FullName = "google.protobuf.Int32Value.value"
)
// Field numbers for google.protobuf.Int32Value.
const (
Int32Value_Value_field_number protoreflect.FieldNumber = 1
)
// Names for google.protobuf.UInt32Value.
const (
UInt32Value_message_name protoreflect.Name = "UInt32Value"
UInt32Value_message_fullname protoreflect.FullName = "google.protobuf.UInt32Value"
)
// Field names for google.protobuf.UInt32Value.
const (
UInt32Value_Value_field_name protoreflect.Name = "value"
UInt32Value_Value_field_fullname protoreflect.FullName = "google.protobuf.UInt32Value.value"
)
// Field numbers for google.protobuf.UInt32Value.
const (
UInt32Value_Value_field_number protoreflect.FieldNumber = 1
)
// Names for google.protobuf.BoolValue.
const (
BoolValue_message_name protoreflect.Name = "BoolValue"
BoolValue_message_fullname protoreflect.FullName = "google.protobuf.BoolValue"
)
// Field names for google.protobuf.BoolValue.
const (
BoolValue_Value_field_name protoreflect.Name = "value"
BoolValue_Value_field_fullname protoreflect.FullName = "google.protobuf.BoolValue.value"
)
// Field numbers for google.protobuf.BoolValue.
const (
BoolValue_Value_field_number protoreflect.FieldNumber = 1
)
// Names for google.protobuf.StringValue.
const (
StringValue_message_name protoreflect.Name = "StringValue"
StringValue_message_fullname protoreflect.FullName = "google.protobuf.StringValue"
)
// Field names for google.protobuf.StringValue.
const (
StringValue_Value_field_name protoreflect.Name = "value"
StringValue_Value_field_fullname protoreflect.FullName = "google.protobuf.StringValue.value"
)
// Field numbers for google.protobuf.StringValue.
const (
StringValue_Value_field_number protoreflect.FieldNumber = 1
)
// Names for google.protobuf.BytesValue.
const (
BytesValue_message_name protoreflect.Name = "BytesValue"
BytesValue_message_fullname protoreflect.FullName = "google.protobuf.BytesValue"
)
// Field names for google.protobuf.BytesValue.
const (
BytesValue_Value_field_name protoreflect.Name = "value"
BytesValue_Value_field_fullname protoreflect.FullName = "google.protobuf.BytesValue.value"
)
// Field numbers for google.protobuf.BytesValue.
const (
BytesValue_Value_field_number protoreflect.FieldNumber = 1
)

View File

@ -1,25 +0,0 @@
// 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 genname contains constants for generated names.
package genname
const (
State = "state"
SizeCache = "sizeCache"
SizeCacheA = "XXX_sizecache"
WeakFields = "weakFields"
WeakFieldsA = "XXX_weak"
UnknownFields = "unknownFields"
UnknownFieldsA = "XXX_unrecognized"
ExtensionFields = "extensionFields"
ExtensionFieldsA = "XXX_InternalExtensions"
ExtensionFieldsB = "XXX_extensions"
WeakFieldPrefix = "XXX_weak_"
)

View File

@ -10,6 +10,7 @@ import (
"strconv" "strconv"
"google.golang.org/protobuf/encoding/prototext" "google.golang.org/protobuf/encoding/prototext"
"google.golang.org/protobuf/internal/errors"
"google.golang.org/protobuf/proto" "google.golang.org/protobuf/proto"
pref "google.golang.org/protobuf/reflect/protoreflect" pref "google.golang.org/protobuf/reflect/protoreflect"
piface "google.golang.org/protobuf/runtime/protoiface" piface "google.golang.org/protobuf/runtime/protoiface"
@ -19,6 +20,12 @@ import (
// functions that we do not want to appear in godoc. // functions that we do not want to appear in godoc.
type Export struct{} type Export struct{}
// NewError formats a string according to the format specifier and arguments and
// returns an error that has a "proto" prefix.
func (Export) NewError(f string, x ...interface{}) error {
return errors.New(f, x...)
}
// enum is any enum type generated by protoc-gen-go // enum is any enum type generated by protoc-gen-go
// and must be a named int32 type. // and must be a named int32 type.
type enum = interface{} type enum = interface{}
@ -160,7 +167,7 @@ func (Export) MessageTypeOf(m message) pref.MessageType {
if mv := (Export{}).protoMessageV2Of(m); mv != nil { if mv := (Export{}).protoMessageV2Of(m); mv != nil {
return mv.ProtoReflect().Type() return mv.ProtoReflect().Type()
} }
return legacyLoadMessageInfo(reflect.TypeOf(m), "") return legacyLoadMessageType(reflect.TypeOf(m), "")
} }
// MessageStringOf returns the message value as a string, // MessageStringOf returns the message value as a string,

View File

@ -10,6 +10,7 @@ import (
"sync" "sync"
"google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/encoding/protowire"
"google.golang.org/protobuf/internal/errors"
"google.golang.org/protobuf/proto" "google.golang.org/protobuf/proto"
pref "google.golang.org/protobuf/reflect/protoreflect" pref "google.golang.org/protobuf/reflect/protoreflect"
preg "google.golang.org/protobuf/reflect/protoregistry" preg "google.golang.org/protobuf/reflect/protoregistry"
@ -20,6 +21,7 @@ type errInvalidUTF8 struct{}
func (errInvalidUTF8) Error() string { return "string field contains invalid UTF-8" } func (errInvalidUTF8) Error() string { return "string field contains invalid UTF-8" }
func (errInvalidUTF8) InvalidUTF8() bool { return true } func (errInvalidUTF8) InvalidUTF8() bool { return true }
func (errInvalidUTF8) Unwrap() error { return errors.Error }
// initOneofFieldCoders initializes the fast-path functions for the fields in a oneof. // initOneofFieldCoders initializes the fast-path functions for the fields in a oneof.
// //
@ -242,7 +244,7 @@ func consumeMessageInfo(b []byte, p pointer, wtyp protowire.Type, f *coderFieldI
} }
v, n := protowire.ConsumeBytes(b) v, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return out, protowire.ParseError(n) return out, errDecode
} }
if p.Elem().IsNil() { if p.Elem().IsNil() {
p.SetPointer(pointerOfValue(reflect.New(f.mi.GoReflectType.Elem()))) p.SetPointer(pointerOfValue(reflect.New(f.mi.GoReflectType.Elem())))
@ -276,7 +278,7 @@ func consumeMessage(b []byte, m proto.Message, wtyp protowire.Type, opts unmarsh
} }
v, n := protowire.ConsumeBytes(b) v, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return out, protowire.ParseError(n) return out, errDecode
} }
o, err := opts.Options().UnmarshalState(piface.UnmarshalInput{ o, err := opts.Options().UnmarshalState(piface.UnmarshalInput{
Buf: v, Buf: v,
@ -420,7 +422,7 @@ func consumeGroup(b []byte, m proto.Message, num protowire.Number, wtyp protowir
} }
b, n := protowire.ConsumeGroup(num, b) b, n := protowire.ConsumeGroup(num, b)
if n < 0 { if n < 0 {
return out, protowire.ParseError(n) return out, errDecode
} }
o, err := opts.Options().UnmarshalState(piface.UnmarshalInput{ o, err := opts.Options().UnmarshalState(piface.UnmarshalInput{
Buf: b, Buf: b,
@ -494,7 +496,7 @@ func consumeMessageSliceInfo(b []byte, p pointer, wtyp protowire.Type, f *coderF
} }
v, n := protowire.ConsumeBytes(b) v, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return out, protowire.ParseError(n) return out, errDecode
} }
m := reflect.New(f.mi.GoReflectType.Elem()).Interface() m := reflect.New(f.mi.GoReflectType.Elem()).Interface()
mp := pointerOfIface(m) mp := pointerOfIface(m)
@ -550,7 +552,7 @@ func consumeMessageSlice(b []byte, p pointer, goType reflect.Type, wtyp protowir
} }
v, n := protowire.ConsumeBytes(b) v, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return out, protowire.ParseError(n) return out, errDecode
} }
mp := reflect.New(goType.Elem()) mp := reflect.New(goType.Elem())
o, err := opts.Options().UnmarshalState(piface.UnmarshalInput{ o, err := opts.Options().UnmarshalState(piface.UnmarshalInput{
@ -613,7 +615,7 @@ func consumeMessageSliceValue(b []byte, listv pref.Value, _ protowire.Number, wt
} }
v, n := protowire.ConsumeBytes(b) v, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return pref.Value{}, out, protowire.ParseError(n) return pref.Value{}, out, errDecode
} }
m := list.NewElement() m := list.NewElement()
o, err := opts.Options().UnmarshalState(piface.UnmarshalInput{ o, err := opts.Options().UnmarshalState(piface.UnmarshalInput{
@ -681,7 +683,7 @@ func consumeGroupSliceValue(b []byte, listv pref.Value, num protowire.Number, wt
} }
b, n := protowire.ConsumeGroup(num, b) b, n := protowire.ConsumeGroup(num, b)
if n < 0 { if n < 0 {
return pref.Value{}, out, protowire.ParseError(n) return pref.Value{}, out, errDecode
} }
m := list.NewElement() m := list.NewElement()
o, err := opts.Options().UnmarshalState(piface.UnmarshalInput{ o, err := opts.Options().UnmarshalState(piface.UnmarshalInput{
@ -767,7 +769,7 @@ func consumeGroupSlice(b []byte, p pointer, num protowire.Number, wtyp protowire
} }
b, n := protowire.ConsumeGroup(num, b) b, n := protowire.ConsumeGroup(num, b)
if n < 0 { if n < 0 {
return out, protowire.ParseError(n) return out, errDecode
} }
mp := reflect.New(goType.Elem()) mp := reflect.New(goType.Elem())
o, err := opts.Options().UnmarshalState(piface.UnmarshalInput{ o, err := opts.Options().UnmarshalState(piface.UnmarshalInput{

File diff suppressed because it is too large Load Diff

View File

@ -5,11 +5,11 @@
package impl package impl
import ( import (
"errors"
"reflect" "reflect"
"sort" "sort"
"google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/encoding/protowire"
"google.golang.org/protobuf/internal/genid"
pref "google.golang.org/protobuf/reflect/protoreflect" pref "google.golang.org/protobuf/reflect/protoreflect"
) )
@ -117,7 +117,7 @@ func consumeMap(b []byte, mapv reflect.Value, wtyp protowire.Type, mapi *mapInfo
} }
b, n := protowire.ConsumeBytes(b) b, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return out, protowire.ParseError(n) return out, errDecode
} }
var ( var (
key = mapi.keyZero key = mapi.keyZero
@ -126,15 +126,15 @@ func consumeMap(b []byte, mapv reflect.Value, wtyp protowire.Type, mapi *mapInfo
for len(b) > 0 { for len(b) > 0 {
num, wtyp, n := protowire.ConsumeTag(b) num, wtyp, n := protowire.ConsumeTag(b)
if n < 0 { if n < 0 {
return out, protowire.ParseError(n) return out, errDecode
} }
if num > protowire.MaxValidNumber { if num > protowire.MaxValidNumber {
return out, errors.New("invalid field number") return out, errDecode
} }
b = b[n:] b = b[n:]
err := errUnknown err := errUnknown
switch num { switch num {
case 1: case genid.MapEntry_Key_field_number:
var v pref.Value var v pref.Value
var o unmarshalOutput var o unmarshalOutput
v, o, err = mapi.keyFuncs.unmarshal(b, key, num, wtyp, opts) v, o, err = mapi.keyFuncs.unmarshal(b, key, num, wtyp, opts)
@ -143,7 +143,7 @@ func consumeMap(b []byte, mapv reflect.Value, wtyp protowire.Type, mapi *mapInfo
} }
key = v key = v
n = o.n n = o.n
case 2: case genid.MapEntry_Value_field_number:
var v pref.Value var v pref.Value
var o unmarshalOutput var o unmarshalOutput
v, o, err = mapi.valFuncs.unmarshal(b, val, num, wtyp, opts) v, o, err = mapi.valFuncs.unmarshal(b, val, num, wtyp, opts)
@ -156,7 +156,7 @@ func consumeMap(b []byte, mapv reflect.Value, wtyp protowire.Type, mapi *mapInfo
if err == errUnknown { if err == errUnknown {
n = protowire.ConsumeFieldValue(num, wtyp, b) n = protowire.ConsumeFieldValue(num, wtyp, b)
if n < 0 { if n < 0 {
return out, protowire.ParseError(n) return out, errDecode
} }
} else if err != nil { } else if err != nil {
return out, err return out, err
@ -174,7 +174,7 @@ func consumeMapOfMessage(b []byte, mapv reflect.Value, wtyp protowire.Type, mapi
} }
b, n := protowire.ConsumeBytes(b) b, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return out, protowire.ParseError(n) return out, errDecode
} }
var ( var (
key = mapi.keyZero key = mapi.keyZero
@ -183,10 +183,10 @@ func consumeMapOfMessage(b []byte, mapv reflect.Value, wtyp protowire.Type, mapi
for len(b) > 0 { for len(b) > 0 {
num, wtyp, n := protowire.ConsumeTag(b) num, wtyp, n := protowire.ConsumeTag(b)
if n < 0 { if n < 0 {
return out, protowire.ParseError(n) return out, errDecode
} }
if num > protowire.MaxValidNumber { if num > protowire.MaxValidNumber {
return out, errors.New("invalid field number") return out, errDecode
} }
b = b[n:] b = b[n:]
err := errUnknown err := errUnknown
@ -207,7 +207,7 @@ func consumeMapOfMessage(b []byte, mapv reflect.Value, wtyp protowire.Type, mapi
var v []byte var v []byte
v, n = protowire.ConsumeBytes(b) v, n = protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return out, protowire.ParseError(n) return out, errDecode
} }
var o unmarshalOutput var o unmarshalOutput
o, err = f.mi.unmarshalPointer(v, pointerOfValue(val), 0, opts) o, err = f.mi.unmarshalPointer(v, pointerOfValue(val), 0, opts)
@ -220,7 +220,7 @@ func consumeMapOfMessage(b []byte, mapv reflect.Value, wtyp protowire.Type, mapi
if err == errUnknown { if err == errUnknown {
n = protowire.ConsumeFieldValue(num, wtyp, b) n = protowire.ConsumeFieldValue(num, wtyp, b)
if n < 0 { if n < 0 {
return out, protowire.ParseError(n) return out, errDecode
} }
} else if err != nil { } else if err != nil {
return out, err return out, err

View File

@ -11,7 +11,7 @@ import (
"google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/encoding/protowire"
"google.golang.org/protobuf/internal/encoding/messageset" "google.golang.org/protobuf/internal/encoding/messageset"
"google.golang.org/protobuf/internal/fieldsort" "google.golang.org/protobuf/internal/order"
pref "google.golang.org/protobuf/reflect/protoreflect" pref "google.golang.org/protobuf/reflect/protoreflect"
piface "google.golang.org/protobuf/runtime/protoiface" piface "google.golang.org/protobuf/runtime/protoiface"
) )
@ -27,6 +27,7 @@ type coderMessageInfo struct {
coderFields map[protowire.Number]*coderFieldInfo coderFields map[protowire.Number]*coderFieldInfo
sizecacheOffset offset sizecacheOffset offset
unknownOffset offset unknownOffset offset
unknownPtrKind bool
extensionOffset offset extensionOffset offset
needsInitCheck bool needsInitCheck bool
isMessageSet bool isMessageSet bool
@ -47,9 +48,20 @@ type coderFieldInfo struct {
} }
func (mi *MessageInfo) makeCoderMethods(t reflect.Type, si structInfo) { func (mi *MessageInfo) makeCoderMethods(t reflect.Type, si structInfo) {
mi.sizecacheOffset = si.sizecacheOffset mi.sizecacheOffset = invalidOffset
mi.unknownOffset = si.unknownOffset mi.unknownOffset = invalidOffset
mi.extensionOffset = si.extensionOffset mi.extensionOffset = invalidOffset
if si.sizecacheOffset.IsValid() && si.sizecacheType == sizecacheType {
mi.sizecacheOffset = si.sizecacheOffset
}
if si.unknownOffset.IsValid() && (si.unknownType == unknownFieldsAType || si.unknownType == unknownFieldsBType) {
mi.unknownOffset = si.unknownOffset
mi.unknownPtrKind = si.unknownType.Kind() == reflect.Ptr
}
if si.extensionOffset.IsValid() && si.extensionType == extensionFieldsType {
mi.extensionOffset = si.extensionOffset
}
mi.coderFields = make(map[protowire.Number]*coderFieldInfo) mi.coderFields = make(map[protowire.Number]*coderFieldInfo)
fields := mi.Desc.Fields() fields := mi.Desc.Fields()
@ -73,6 +85,27 @@ func (mi *MessageInfo) makeCoderMethods(t reflect.Type, si structInfo) {
var funcs pointerCoderFuncs var funcs pointerCoderFuncs
var childMessage *MessageInfo var childMessage *MessageInfo
switch { switch {
case ft == nil:
// This never occurs for generated message types.
// It implies that a hand-crafted type has missing Go fields
// for specific protobuf message fields.
funcs = pointerCoderFuncs{
size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int {
return 0
},
marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
return nil, nil
},
unmarshal: func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) {
panic("missing Go struct field for " + string(fd.FullName()))
},
isInit: func(p pointer, f *coderFieldInfo) error {
panic("missing Go struct field for " + string(fd.FullName()))
},
merge: func(dst, src pointer, f *coderFieldInfo, opts mergeOptions) {
panic("missing Go struct field for " + string(fd.FullName()))
},
}
case isOneof: case isOneof:
fieldOffset = offsetOf(fs, mi.Exporter) fieldOffset = offsetOf(fs, mi.Exporter)
case fd.IsWeak(): case fd.IsWeak():
@ -136,7 +169,7 @@ func (mi *MessageInfo) makeCoderMethods(t reflect.Type, si structInfo) {
sort.Slice(mi.orderedCoderFields, func(i, j int) bool { sort.Slice(mi.orderedCoderFields, func(i, j int) bool {
fi := fields.ByNumber(mi.orderedCoderFields[i].num) fi := fields.ByNumber(mi.orderedCoderFields[i].num)
fj := fields.ByNumber(mi.orderedCoderFields[j].num) fj := fields.ByNumber(mi.orderedCoderFields[j].num)
return fieldsort.Less(fi, fj) return order.LegacyFieldOrder(fi, fj)
}) })
} }
@ -157,3 +190,28 @@ func (mi *MessageInfo) makeCoderMethods(t reflect.Type, si structInfo) {
mi.methods.Merge = mi.merge mi.methods.Merge = mi.merge
} }
} }
// getUnknownBytes returns a *[]byte for the unknown fields.
// It is the caller's responsibility to check whether the pointer is nil.
// This function is specially designed to be inlineable.
func (mi *MessageInfo) getUnknownBytes(p pointer) *[]byte {
if mi.unknownPtrKind {
return *p.Apply(mi.unknownOffset).BytesPtr()
} else {
return p.Apply(mi.unknownOffset).Bytes()
}
}
// mutableUnknownBytes returns a *[]byte for the unknown fields.
// The returned pointer is guaranteed to not be nil.
func (mi *MessageInfo) mutableUnknownBytes(p pointer) *[]byte {
if mi.unknownPtrKind {
bp := p.Apply(mi.unknownOffset).BytesPtr()
if *bp == nil {
*bp = new([]byte)
}
return *bp
} else {
return p.Apply(mi.unknownOffset).Bytes()
}
}

View File

@ -29,8 +29,9 @@ func sizeMessageSet(mi *MessageInfo, p pointer, opts marshalOptions) (size int)
size += xi.funcs.size(x.Value(), protowire.SizeTag(messageset.FieldMessage), opts) size += xi.funcs.size(x.Value(), protowire.SizeTag(messageset.FieldMessage), opts)
} }
unknown := *p.Apply(mi.unknownOffset).Bytes() if u := mi.getUnknownBytes(p); u != nil {
size += messageset.SizeUnknown(unknown) size += messageset.SizeUnknown(*u)
}
return size return size
} }
@ -69,10 +70,12 @@ func marshalMessageSet(mi *MessageInfo, b []byte, p pointer, opts marshalOptions
} }
} }
unknown := *p.Apply(mi.unknownOffset).Bytes() if u := mi.getUnknownBytes(p); u != nil {
b, err := messageset.AppendUnknown(b, unknown) var err error
if err != nil { b, err = messageset.AppendUnknown(b, *u)
return b, err if err != nil {
return b, err
}
} }
return b, nil return b, nil
@ -100,13 +103,13 @@ func unmarshalMessageSet(mi *MessageInfo, b []byte, p pointer, opts unmarshalOpt
*ep = make(map[int32]ExtensionField) *ep = make(map[int32]ExtensionField)
} }
ext := *ep ext := *ep
unknown := p.Apply(mi.unknownOffset).Bytes()
initialized := true initialized := true
err = messageset.Unmarshal(b, true, func(num protowire.Number, v []byte) error { err = messageset.Unmarshal(b, true, func(num protowire.Number, v []byte) error {
o, err := mi.unmarshalExtension(v, num, protowire.BytesType, ext, opts) o, err := mi.unmarshalExtension(v, num, protowire.BytesType, ext, opts)
if err == errUnknown { if err == errUnknown {
*unknown = protowire.AppendTag(*unknown, num, protowire.BytesType) u := mi.mutableUnknownBytes(p)
*unknown = append(*unknown, v...) *u = protowire.AppendTag(*u, num, protowire.BytesType)
*u = append(*u, v...)
return nil return nil
} }
if !o.initialized { if !o.initialized {

View File

@ -30,7 +30,7 @@ func consumeEnum(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, _
} }
v, n := protowire.ConsumeVarint(b) v, n := protowire.ConsumeVarint(b)
if n < 0 { if n < 0 {
return out, protowire.ParseError(n) return out, errDecode
} }
p.v.Elem().SetInt(int64(v)) p.v.Elem().SetInt(int64(v))
out.n = n out.n = n
@ -130,12 +130,12 @@ func consumeEnumSlice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInf
if wtyp == protowire.BytesType { if wtyp == protowire.BytesType {
b, n := protowire.ConsumeBytes(b) b, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return out, protowire.ParseError(n) return out, errDecode
} }
for len(b) > 0 { for len(b) > 0 {
v, n := protowire.ConsumeVarint(b) v, n := protowire.ConsumeVarint(b)
if n < 0 { if n < 0 {
return out, protowire.ParseError(n) return out, errDecode
} }
rv := reflect.New(s.Type().Elem()).Elem() rv := reflect.New(s.Type().Elem()).Elem()
rv.SetInt(int64(v)) rv.SetInt(int64(v))
@ -150,7 +150,7 @@ func consumeEnumSlice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInf
} }
v, n := protowire.ConsumeVarint(b) v, n := protowire.ConsumeVarint(b)
if n < 0 { if n < 0 {
return out, protowire.ParseError(n) return out, errDecode
} }
rv := reflect.New(s.Type().Elem()).Elem() rv := reflect.New(s.Type().Elem()).Elem()
rv.SetInt(int64(v)) rv.SetInt(int64(v))

View File

@ -423,6 +423,13 @@ func (c *messageConverter) PBValueOf(v reflect.Value) pref.Value {
if v.Type() != c.goType { if v.Type() != c.goType {
panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType)) panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType))
} }
if c.isNonPointer() {
if v.CanAddr() {
v = v.Addr() // T => *T
} else {
v = reflect.Zero(reflect.PtrTo(v.Type()))
}
}
if m, ok := v.Interface().(pref.ProtoMessage); ok { if m, ok := v.Interface().(pref.ProtoMessage); ok {
return pref.ValueOfMessage(m.ProtoReflect()) return pref.ValueOfMessage(m.ProtoReflect())
} }
@ -437,6 +444,16 @@ func (c *messageConverter) GoValueOf(v pref.Value) reflect.Value {
} else { } else {
rv = reflect.ValueOf(m.Interface()) rv = reflect.ValueOf(m.Interface())
} }
if c.isNonPointer() {
if rv.Type() != reflect.PtrTo(c.goType) {
panic(fmt.Sprintf("invalid type: got %v, want %v", rv.Type(), reflect.PtrTo(c.goType)))
}
if !rv.IsNil() {
rv = rv.Elem() // *T => T
} else {
rv = reflect.Zero(rv.Type().Elem())
}
}
if rv.Type() != c.goType { if rv.Type() != c.goType {
panic(fmt.Sprintf("invalid type: got %v, want %v", rv.Type(), c.goType)) panic(fmt.Sprintf("invalid type: got %v, want %v", rv.Type(), c.goType))
} }
@ -451,6 +468,9 @@ func (c *messageConverter) IsValidPB(v pref.Value) bool {
} else { } else {
rv = reflect.ValueOf(m.Interface()) rv = reflect.ValueOf(m.Interface())
} }
if c.isNonPointer() {
return rv.Type() == reflect.PtrTo(c.goType)
}
return rv.Type() == c.goType return rv.Type() == c.goType
} }
@ -459,9 +479,18 @@ func (c *messageConverter) IsValidGo(v reflect.Value) bool {
} }
func (c *messageConverter) New() pref.Value { func (c *messageConverter) New() pref.Value {
if c.isNonPointer() {
return c.PBValueOf(reflect.New(c.goType).Elem())
}
return c.PBValueOf(reflect.New(c.goType.Elem())) return c.PBValueOf(reflect.New(c.goType.Elem()))
} }
func (c *messageConverter) Zero() pref.Value { func (c *messageConverter) Zero() pref.Value {
return c.PBValueOf(reflect.Zero(c.goType)) return c.PBValueOf(reflect.Zero(c.goType))
} }
// isNonPointer reports whether the type is a non-pointer type.
// This never occurs for generated message types.
func (c *messageConverter) isNonPointer() bool {
return c.goType.Kind() != reflect.Ptr
}

View File

@ -17,6 +17,8 @@ import (
piface "google.golang.org/protobuf/runtime/protoiface" piface "google.golang.org/protobuf/runtime/protoiface"
) )
var errDecode = errors.New("cannot parse invalid wire-format data")
type unmarshalOptions struct { type unmarshalOptions struct {
flags protoiface.UnmarshalInputFlags flags protoiface.UnmarshalInputFlags
resolver interface { resolver interface {
@ -100,13 +102,13 @@ func (mi *MessageInfo) unmarshalPointer(b []byte, p pointer, groupTag protowire.
var n int var n int
tag, n = protowire.ConsumeVarint(b) tag, n = protowire.ConsumeVarint(b)
if n < 0 { if n < 0 {
return out, protowire.ParseError(n) return out, errDecode
} }
b = b[n:] b = b[n:]
} }
var num protowire.Number var num protowire.Number
if n := tag >> 3; n < uint64(protowire.MinValidNumber) || n > uint64(protowire.MaxValidNumber) { if n := tag >> 3; n < uint64(protowire.MinValidNumber) || n > uint64(protowire.MaxValidNumber) {
return out, errors.New("invalid field number") return out, errDecode
} else { } else {
num = protowire.Number(n) num = protowire.Number(n)
} }
@ -114,7 +116,7 @@ func (mi *MessageInfo) unmarshalPointer(b []byte, p pointer, groupTag protowire.
if wtyp == protowire.EndGroupType { if wtyp == protowire.EndGroupType {
if num != groupTag { if num != groupTag {
return out, errors.New("mismatching end group marker") return out, errDecode
} }
groupTag = 0 groupTag = 0
break break
@ -170,10 +172,10 @@ func (mi *MessageInfo) unmarshalPointer(b []byte, p pointer, groupTag protowire.
} }
n = protowire.ConsumeFieldValue(num, wtyp, b) n = protowire.ConsumeFieldValue(num, wtyp, b)
if n < 0 { if n < 0 {
return out, protowire.ParseError(n) return out, errDecode
} }
if !opts.DiscardUnknown() && mi.unknownOffset.IsValid() { if !opts.DiscardUnknown() && mi.unknownOffset.IsValid() {
u := p.Apply(mi.unknownOffset).Bytes() u := mi.mutableUnknownBytes(p)
*u = protowire.AppendTag(*u, num, wtyp) *u = protowire.AppendTag(*u, num, wtyp)
*u = append(*u, b[:n]...) *u = append(*u, b[:n]...)
} }
@ -181,7 +183,7 @@ func (mi *MessageInfo) unmarshalPointer(b []byte, p pointer, groupTag protowire.
b = b[n:] b = b[n:]
} }
if groupTag != 0 { if groupTag != 0 {
return out, errors.New("missing end group marker") return out, errDecode
} }
if mi.numRequiredFields > 0 && bits.OnesCount64(requiredMask) != int(mi.numRequiredFields) { if mi.numRequiredFields > 0 && bits.OnesCount64(requiredMask) != int(mi.numRequiredFields) {
initialized = false initialized = false
@ -221,7 +223,7 @@ func (mi *MessageInfo) unmarshalExtension(b []byte, num protowire.Number, wtyp p
return out, nil return out, nil
} }
case ValidationInvalid: case ValidationInvalid:
return out, errors.New("invalid wire format") return out, errDecode
case ValidationUnknown: case ValidationUnknown:
} }
} }

View File

@ -79,8 +79,9 @@ func (mi *MessageInfo) sizePointerSlow(p pointer, opts marshalOptions) (size int
size += f.funcs.size(fptr, f, opts) size += f.funcs.size(fptr, f, opts)
} }
if mi.unknownOffset.IsValid() { if mi.unknownOffset.IsValid() {
u := *p.Apply(mi.unknownOffset).Bytes() if u := mi.getUnknownBytes(p); u != nil {
size += len(u) size += len(*u)
}
} }
if mi.sizecacheOffset.IsValid() { if mi.sizecacheOffset.IsValid() {
if size > math.MaxInt32 { if size > math.MaxInt32 {
@ -141,8 +142,9 @@ func (mi *MessageInfo) marshalAppendPointer(b []byte, p pointer, opts marshalOpt
} }
} }
if mi.unknownOffset.IsValid() && !mi.isMessageSet { if mi.unknownOffset.IsValid() && !mi.isMessageSet {
u := *p.Apply(mi.unknownOffset).Bytes() if u := mi.getUnknownBytes(p); u != nil {
b = append(b, u...) b = append(b, (*u)...)
}
} }
return b, nil return b, nil
} }

View File

@ -30,7 +30,7 @@ func (Export) LegacyMessageTypeOf(m piface.MessageV1, name pref.FullName) pref.M
if mv := (Export{}).protoMessageV2Of(m); mv != nil { if mv := (Export{}).protoMessageV2Of(m); mv != nil {
return mv.ProtoReflect().Type() return mv.ProtoReflect().Type()
} }
return legacyLoadMessageInfo(reflect.TypeOf(m), name) return legacyLoadMessageType(reflect.TypeOf(m), name)
} }
// UnmarshalJSONEnum unmarshals an enum from a JSON-encoded input. // UnmarshalJSONEnum unmarshals an enum from a JSON-encoded input.

View File

@ -154,7 +154,8 @@ func (x placeholderExtension) Number() pref.FieldNumber { retu
func (x placeholderExtension) Cardinality() pref.Cardinality { return 0 } func (x placeholderExtension) Cardinality() pref.Cardinality { return 0 }
func (x placeholderExtension) Kind() pref.Kind { return 0 } func (x placeholderExtension) Kind() pref.Kind { return 0 }
func (x placeholderExtension) HasJSONName() bool { return false } func (x placeholderExtension) HasJSONName() bool { return false }
func (x placeholderExtension) JSONName() string { return "" } func (x placeholderExtension) JSONName() string { return "[" + string(x.name) + "]" }
func (x placeholderExtension) TextName() string { return "[" + string(x.name) + "]" }
func (x placeholderExtension) HasPresence() bool { return false } func (x placeholderExtension) HasPresence() bool { return false }
func (x placeholderExtension) HasOptionalKeyword() bool { return false } func (x placeholderExtension) HasOptionalKeyword() bool { return false }
func (x placeholderExtension) IsExtension() bool { return true } func (x placeholderExtension) IsExtension() bool { return true }

View File

@ -24,14 +24,24 @@ import (
// legacyWrapMessage wraps v as a protoreflect.Message, // legacyWrapMessage wraps v as a protoreflect.Message,
// where v must be a *struct kind and not implement the v2 API already. // where v must be a *struct kind and not implement the v2 API already.
func legacyWrapMessage(v reflect.Value) pref.Message { func legacyWrapMessage(v reflect.Value) pref.Message {
typ := v.Type() t := v.Type()
if typ.Kind() != reflect.Ptr || typ.Elem().Kind() != reflect.Struct { if t.Kind() != reflect.Ptr || t.Elem().Kind() != reflect.Struct {
return aberrantMessage{v: v} return aberrantMessage{v: v}
} }
mt := legacyLoadMessageInfo(typ, "") mt := legacyLoadMessageInfo(t, "")
return mt.MessageOf(v.Interface()) return mt.MessageOf(v.Interface())
} }
// legacyLoadMessageType dynamically loads a protoreflect.Type for t,
// where t must be not implement the v2 API already.
// The provided name is used if it cannot be determined from the message.
func legacyLoadMessageType(t reflect.Type, name pref.FullName) protoreflect.MessageType {
if t.Kind() != reflect.Ptr || t.Elem().Kind() != reflect.Struct {
return aberrantMessageType{t}
}
return legacyLoadMessageInfo(t, name)
}
var legacyMessageTypeCache sync.Map // map[reflect.Type]*MessageInfo var legacyMessageTypeCache sync.Map // map[reflect.Type]*MessageInfo
// legacyLoadMessageInfo dynamically loads a *MessageInfo for t, // legacyLoadMessageInfo dynamically loads a *MessageInfo for t,
@ -49,8 +59,9 @@ func legacyLoadMessageInfo(t reflect.Type, name pref.FullName) *MessageInfo {
GoReflectType: t, GoReflectType: t,
} }
var hasMarshal, hasUnmarshal bool
v := reflect.Zero(t).Interface() v := reflect.Zero(t).Interface()
if _, ok := v.(legacyMarshaler); ok { if _, hasMarshal = v.(legacyMarshaler); hasMarshal {
mi.methods.Marshal = legacyMarshal mi.methods.Marshal = legacyMarshal
// We have no way to tell whether the type's Marshal method // We have no way to tell whether the type's Marshal method
@ -59,10 +70,10 @@ func legacyLoadMessageInfo(t reflect.Type, name pref.FullName) *MessageInfo {
// calling Marshal methods when present. // calling Marshal methods when present.
mi.methods.Flags |= piface.SupportMarshalDeterministic mi.methods.Flags |= piface.SupportMarshalDeterministic
} }
if _, ok := v.(legacyUnmarshaler); ok { if _, hasUnmarshal = v.(legacyUnmarshaler); hasUnmarshal {
mi.methods.Unmarshal = legacyUnmarshal mi.methods.Unmarshal = legacyUnmarshal
} }
if _, ok := v.(legacyMerger); ok { if _, hasMerge := v.(legacyMerger); hasMerge || (hasMarshal && hasUnmarshal) {
mi.methods.Merge = legacyMerge mi.methods.Merge = legacyMerge
} }
@ -75,7 +86,7 @@ func legacyLoadMessageInfo(t reflect.Type, name pref.FullName) *MessageInfo {
var legacyMessageDescCache sync.Map // map[reflect.Type]protoreflect.MessageDescriptor var legacyMessageDescCache sync.Map // map[reflect.Type]protoreflect.MessageDescriptor
// LegacyLoadMessageDesc returns an MessageDescriptor derived from the Go type, // LegacyLoadMessageDesc returns an MessageDescriptor derived from the Go type,
// which must be a *struct kind and not implement the v2 API already. // which should be a *struct kind and must not implement the v2 API already.
// //
// This is exported for testing purposes. // This is exported for testing purposes.
func LegacyLoadMessageDesc(t reflect.Type) pref.MessageDescriptor { func LegacyLoadMessageDesc(t reflect.Type) pref.MessageDescriptor {
@ -114,17 +125,19 @@ func legacyLoadMessageDesc(t reflect.Type, name pref.FullName) pref.MessageDescr
// If the Go type has no fields, then this might be a proto3 empty message // If the Go type has no fields, then this might be a proto3 empty message
// from before the size cache was added. If there are any fields, check to // from before the size cache was added. If there are any fields, check to
// see that at least one of them looks like something we generated. // see that at least one of them looks like something we generated.
if nfield := t.Elem().NumField(); nfield > 0 { if t.Elem().Kind() == reflect.Struct {
hasProtoField := false if nfield := t.Elem().NumField(); nfield > 0 {
for i := 0; i < nfield; i++ { hasProtoField := false
f := t.Elem().Field(i) for i := 0; i < nfield; i++ {
if f.Tag.Get("protobuf") != "" || f.Tag.Get("protobuf_oneof") != "" || strings.HasPrefix(f.Name, "XXX_") { f := t.Elem().Field(i)
hasProtoField = true if f.Tag.Get("protobuf") != "" || f.Tag.Get("protobuf_oneof") != "" || strings.HasPrefix(f.Name, "XXX_") {
break hasProtoField = true
break
}
}
if !hasProtoField {
return aberrantLoadMessageDesc(t, name)
} }
}
if !hasProtoField {
return aberrantLoadMessageDesc(t, name)
} }
} }
@ -370,7 +383,7 @@ type legacyMerger interface {
Merge(protoiface.MessageV1) Merge(protoiface.MessageV1)
} }
var legacyProtoMethods = &piface.Methods{ var aberrantProtoMethods = &piface.Methods{
Marshal: legacyMarshal, Marshal: legacyMarshal,
Unmarshal: legacyUnmarshal, Unmarshal: legacyUnmarshal,
Merge: legacyMerge, Merge: legacyMerge,
@ -401,18 +414,40 @@ func legacyUnmarshal(in piface.UnmarshalInput) (piface.UnmarshalOutput, error) {
v := in.Message.(unwrapper).protoUnwrap() v := in.Message.(unwrapper).protoUnwrap()
unmarshaler, ok := v.(legacyUnmarshaler) unmarshaler, ok := v.(legacyUnmarshaler)
if !ok { if !ok {
return piface.UnmarshalOutput{}, errors.New("%T does not implement Marshal", v) return piface.UnmarshalOutput{}, errors.New("%T does not implement Unmarshal", v)
} }
return piface.UnmarshalOutput{}, unmarshaler.Unmarshal(in.Buf) return piface.UnmarshalOutput{}, unmarshaler.Unmarshal(in.Buf)
} }
func legacyMerge(in piface.MergeInput) piface.MergeOutput { func legacyMerge(in piface.MergeInput) piface.MergeOutput {
// Check whether this supports the legacy merger.
dstv := in.Destination.(unwrapper).protoUnwrap() dstv := in.Destination.(unwrapper).protoUnwrap()
merger, ok := dstv.(legacyMerger) merger, ok := dstv.(legacyMerger)
if ok {
merger.Merge(Export{}.ProtoMessageV1Of(in.Source))
return piface.MergeOutput{Flags: piface.MergeComplete}
}
// If legacy merger is unavailable, implement merge in terms of
// a marshal and unmarshal operation.
srcv := in.Source.(unwrapper).protoUnwrap()
marshaler, ok := srcv.(legacyMarshaler)
if !ok { if !ok {
return piface.MergeOutput{} return piface.MergeOutput{}
} }
merger.Merge(Export{}.ProtoMessageV1Of(in.Source)) dstv = in.Destination.(unwrapper).protoUnwrap()
unmarshaler, ok := dstv.(legacyUnmarshaler)
if !ok {
return piface.MergeOutput{}
}
b, err := marshaler.Marshal()
if err != nil {
return piface.MergeOutput{}
}
err = unmarshaler.Unmarshal(b)
if err != nil {
return piface.MergeOutput{}
}
return piface.MergeOutput{Flags: piface.MergeComplete} return piface.MergeOutput{Flags: piface.MergeComplete}
} }
@ -422,6 +457,9 @@ type aberrantMessageType struct {
} }
func (mt aberrantMessageType) New() pref.Message { func (mt aberrantMessageType) New() pref.Message {
if mt.t.Kind() == reflect.Ptr {
return aberrantMessage{reflect.New(mt.t.Elem())}
}
return aberrantMessage{reflect.Zero(mt.t)} return aberrantMessage{reflect.Zero(mt.t)}
} }
func (mt aberrantMessageType) Zero() pref.Message { func (mt aberrantMessageType) Zero() pref.Message {
@ -443,6 +481,17 @@ type aberrantMessage struct {
v reflect.Value v reflect.Value
} }
// Reset implements the v1 proto.Message.Reset method.
func (m aberrantMessage) Reset() {
if mr, ok := m.v.Interface().(interface{ Reset() }); ok {
mr.Reset()
return
}
if m.v.Kind() == reflect.Ptr && !m.v.IsNil() {
m.v.Elem().Set(reflect.Zero(m.v.Type().Elem()))
}
}
func (m aberrantMessage) ProtoReflect() pref.Message { func (m aberrantMessage) ProtoReflect() pref.Message {
return m return m
} }
@ -454,33 +503,40 @@ func (m aberrantMessage) Type() pref.MessageType {
return aberrantMessageType{m.v.Type()} return aberrantMessageType{m.v.Type()}
} }
func (m aberrantMessage) New() pref.Message { func (m aberrantMessage) New() pref.Message {
if m.v.Type().Kind() == reflect.Ptr {
return aberrantMessage{reflect.New(m.v.Type().Elem())}
}
return aberrantMessage{reflect.Zero(m.v.Type())} return aberrantMessage{reflect.Zero(m.v.Type())}
} }
func (m aberrantMessage) Interface() pref.ProtoMessage { func (m aberrantMessage) Interface() pref.ProtoMessage {
return m return m
} }
func (m aberrantMessage) Range(f func(pref.FieldDescriptor, pref.Value) bool) { func (m aberrantMessage) Range(f func(pref.FieldDescriptor, pref.Value) bool) {
return
} }
func (m aberrantMessage) Has(pref.FieldDescriptor) bool { func (m aberrantMessage) Has(pref.FieldDescriptor) bool {
panic("invalid field descriptor") return false
} }
func (m aberrantMessage) Clear(pref.FieldDescriptor) { func (m aberrantMessage) Clear(pref.FieldDescriptor) {
panic("invalid field descriptor") panic("invalid Message.Clear on " + string(m.Descriptor().FullName()))
} }
func (m aberrantMessage) Get(pref.FieldDescriptor) pref.Value { func (m aberrantMessage) Get(fd pref.FieldDescriptor) pref.Value {
panic("invalid field descriptor") if fd.Default().IsValid() {
return fd.Default()
}
panic("invalid Message.Get on " + string(m.Descriptor().FullName()))
} }
func (m aberrantMessage) Set(pref.FieldDescriptor, pref.Value) { func (m aberrantMessage) Set(pref.FieldDescriptor, pref.Value) {
panic("invalid field descriptor") panic("invalid Message.Set on " + string(m.Descriptor().FullName()))
} }
func (m aberrantMessage) Mutable(pref.FieldDescriptor) pref.Value { func (m aberrantMessage) Mutable(pref.FieldDescriptor) pref.Value {
panic("invalid field descriptor") panic("invalid Message.Mutable on " + string(m.Descriptor().FullName()))
} }
func (m aberrantMessage) NewField(pref.FieldDescriptor) pref.Value { func (m aberrantMessage) NewField(pref.FieldDescriptor) pref.Value {
panic("invalid field descriptor") panic("invalid Message.NewField on " + string(m.Descriptor().FullName()))
} }
func (m aberrantMessage) WhichOneof(pref.OneofDescriptor) pref.FieldDescriptor { func (m aberrantMessage) WhichOneof(pref.OneofDescriptor) pref.FieldDescriptor {
panic("invalid oneof descriptor") panic("invalid Message.WhichOneof descriptor on " + string(m.Descriptor().FullName()))
} }
func (m aberrantMessage) GetUnknown() pref.RawFields { func (m aberrantMessage) GetUnknown() pref.RawFields {
return nil return nil
@ -489,13 +545,13 @@ func (m aberrantMessage) SetUnknown(pref.RawFields) {
// SetUnknown discards its input on messages which don't support unknown field storage. // SetUnknown discards its input on messages which don't support unknown field storage.
} }
func (m aberrantMessage) IsValid() bool { func (m aberrantMessage) IsValid() bool {
// An invalid message is a read-only, empty message. Since we don't know anything if m.v.Kind() == reflect.Ptr {
// about the alleged contents of this message, we can't say with confidence that return !m.v.IsNil()
// it is invalid in this sense. Therefore, report it as valid. }
return true return false
} }
func (m aberrantMessage) ProtoMethods() *piface.Methods { func (m aberrantMessage) ProtoMethods() *piface.Methods {
return legacyProtoMethods return aberrantProtoMethods
} }
func (m aberrantMessage) protoUnwrap() interface{} { func (m aberrantMessage) protoUnwrap() interface{} {
return m.v.Interface() return m.v.Interface()

View File

@ -77,9 +77,9 @@ func (mi *MessageInfo) mergePointer(dst, src pointer, opts mergeOptions) {
} }
} }
if mi.unknownOffset.IsValid() { if mi.unknownOffset.IsValid() {
du := dst.Apply(mi.unknownOffset).Bytes() su := mi.getUnknownBytes(src)
su := src.Apply(mi.unknownOffset).Bytes() if su != nil && len(*su) > 0 {
if len(*su) > 0 { du := mi.mutableUnknownBytes(dst)
*du = append(*du, *su...) *du = append(*du, *su...)
} }
} }

View File

@ -12,9 +12,10 @@ import (
"sync" "sync"
"sync/atomic" "sync/atomic"
"google.golang.org/protobuf/internal/genname" "google.golang.org/protobuf/internal/genid"
"google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/reflect/protoreflect"
pref "google.golang.org/protobuf/reflect/protoreflect" pref "google.golang.org/protobuf/reflect/protoreflect"
preg "google.golang.org/protobuf/reflect/protoregistry"
) )
// MessageInfo provides protobuf related functionality for a given Go type // MessageInfo provides protobuf related functionality for a given Go type
@ -109,22 +110,29 @@ func (mi *MessageInfo) getPointer(m pref.Message) (p pointer, ok bool) {
type ( type (
SizeCache = int32 SizeCache = int32
WeakFields = map[int32]protoreflect.ProtoMessage WeakFields = map[int32]protoreflect.ProtoMessage
UnknownFields = []byte UnknownFields = unknownFieldsA // TODO: switch to unknownFieldsB
unknownFieldsA = []byte
unknownFieldsB = *[]byte
ExtensionFields = map[int32]ExtensionField ExtensionFields = map[int32]ExtensionField
) )
var ( var (
sizecacheType = reflect.TypeOf(SizeCache(0)) sizecacheType = reflect.TypeOf(SizeCache(0))
weakFieldsType = reflect.TypeOf(WeakFields(nil)) weakFieldsType = reflect.TypeOf(WeakFields(nil))
unknownFieldsType = reflect.TypeOf(UnknownFields(nil)) unknownFieldsAType = reflect.TypeOf(unknownFieldsA(nil))
unknownFieldsBType = reflect.TypeOf(unknownFieldsB(nil))
extensionFieldsType = reflect.TypeOf(ExtensionFields(nil)) extensionFieldsType = reflect.TypeOf(ExtensionFields(nil))
) )
type structInfo struct { type structInfo struct {
sizecacheOffset offset sizecacheOffset offset
sizecacheType reflect.Type
weakOffset offset weakOffset offset
weakType reflect.Type
unknownOffset offset unknownOffset offset
unknownType reflect.Type
extensionOffset offset extensionOffset offset
extensionType reflect.Type
fieldsByNumber map[pref.FieldNumber]reflect.StructField fieldsByNumber map[pref.FieldNumber]reflect.StructField
oneofsByName map[pref.Name]reflect.StructField oneofsByName map[pref.Name]reflect.StructField
@ -148,21 +156,25 @@ func (mi *MessageInfo) makeStructInfo(t reflect.Type) structInfo {
fieldLoop: fieldLoop:
for i := 0; i < t.NumField(); i++ { for i := 0; i < t.NumField(); i++ {
switch f := t.Field(i); f.Name { switch f := t.Field(i); f.Name {
case genname.SizeCache, genname.SizeCacheA: case genid.SizeCache_goname, genid.SizeCacheA_goname:
if f.Type == sizecacheType { if f.Type == sizecacheType {
si.sizecacheOffset = offsetOf(f, mi.Exporter) si.sizecacheOffset = offsetOf(f, mi.Exporter)
si.sizecacheType = f.Type
} }
case genname.WeakFields, genname.WeakFieldsA: case genid.WeakFields_goname, genid.WeakFieldsA_goname:
if f.Type == weakFieldsType { if f.Type == weakFieldsType {
si.weakOffset = offsetOf(f, mi.Exporter) si.weakOffset = offsetOf(f, mi.Exporter)
si.weakType = f.Type
} }
case genname.UnknownFields, genname.UnknownFieldsA: case genid.UnknownFields_goname, genid.UnknownFieldsA_goname:
if f.Type == unknownFieldsType { if f.Type == unknownFieldsAType || f.Type == unknownFieldsBType {
si.unknownOffset = offsetOf(f, mi.Exporter) si.unknownOffset = offsetOf(f, mi.Exporter)
si.unknownType = f.Type
} }
case genname.ExtensionFields, genname.ExtensionFieldsA, genname.ExtensionFieldsB: case genid.ExtensionFields_goname, genid.ExtensionFieldsA_goname, genid.ExtensionFieldsB_goname:
if f.Type == extensionFieldsType { if f.Type == extensionFieldsType {
si.extensionOffset = offsetOf(f, mi.Exporter) si.extensionOffset = offsetOf(f, mi.Exporter)
si.extensionType = f.Type
} }
default: default:
for _, s := range strings.Split(f.Tag.Get("protobuf"), ",") { for _, s := range strings.Split(f.Tag.Get("protobuf"), ",") {
@ -212,4 +224,53 @@ func (mi *MessageInfo) New() protoreflect.Message {
func (mi *MessageInfo) Zero() protoreflect.Message { func (mi *MessageInfo) Zero() protoreflect.Message {
return mi.MessageOf(reflect.Zero(mi.GoReflectType).Interface()) return mi.MessageOf(reflect.Zero(mi.GoReflectType).Interface())
} }
func (mi *MessageInfo) Descriptor() protoreflect.MessageDescriptor { return mi.Desc } func (mi *MessageInfo) Descriptor() protoreflect.MessageDescriptor {
return mi.Desc
}
func (mi *MessageInfo) Enum(i int) protoreflect.EnumType {
mi.init()
fd := mi.Desc.Fields().Get(i)
return Export{}.EnumTypeOf(mi.fieldTypes[fd.Number()])
}
func (mi *MessageInfo) Message(i int) protoreflect.MessageType {
mi.init()
fd := mi.Desc.Fields().Get(i)
switch {
case fd.IsWeak():
mt, _ := preg.GlobalTypes.FindMessageByName(fd.Message().FullName())
return mt
case fd.IsMap():
return mapEntryType{fd.Message(), mi.fieldTypes[fd.Number()]}
default:
return Export{}.MessageTypeOf(mi.fieldTypes[fd.Number()])
}
}
type mapEntryType struct {
desc protoreflect.MessageDescriptor
valType interface{} // zero value of enum or message type
}
func (mt mapEntryType) New() protoreflect.Message {
return nil
}
func (mt mapEntryType) Zero() protoreflect.Message {
return nil
}
func (mt mapEntryType) Descriptor() protoreflect.MessageDescriptor {
return mt.desc
}
func (mt mapEntryType) Enum(i int) protoreflect.EnumType {
fd := mt.desc.Fields().Get(i)
if fd.Enum() == nil {
return nil
}
return Export{}.EnumTypeOf(mt.valType)
}
func (mt mapEntryType) Message(i int) protoreflect.MessageType {
fd := mt.desc.Fields().Get(i)
if fd.Message() == nil {
return nil
}
return Export{}.MessageTypeOf(mt.valType)
}

View File

@ -8,6 +8,7 @@ import (
"fmt" "fmt"
"reflect" "reflect"
"google.golang.org/protobuf/internal/detrand"
"google.golang.org/protobuf/internal/pragma" "google.golang.org/protobuf/internal/pragma"
pref "google.golang.org/protobuf/reflect/protoreflect" pref "google.golang.org/protobuf/reflect/protoreflect"
) )
@ -16,6 +17,11 @@ type reflectMessageInfo struct {
fields map[pref.FieldNumber]*fieldInfo fields map[pref.FieldNumber]*fieldInfo
oneofs map[pref.Name]*oneofInfo oneofs map[pref.Name]*oneofInfo
// fieldTypes contains the zero value of an enum or message field.
// For lists, it contains the element type.
// For maps, it contains the entry value type.
fieldTypes map[pref.FieldNumber]interface{}
// denseFields is a subset of fields where: // denseFields is a subset of fields where:
// 0 < fieldDesc.Number() < len(denseFields) // 0 < fieldDesc.Number() < len(denseFields)
// It provides faster access to the fieldInfo, but may be incomplete. // It provides faster access to the fieldInfo, but may be incomplete.
@ -36,6 +42,7 @@ func (mi *MessageInfo) makeReflectFuncs(t reflect.Type, si structInfo) {
mi.makeKnownFieldsFunc(si) mi.makeKnownFieldsFunc(si)
mi.makeUnknownFieldsFunc(t, si) mi.makeUnknownFieldsFunc(t, si)
mi.makeExtensionFieldsFunc(t, si) mi.makeExtensionFieldsFunc(t, si)
mi.makeFieldTypes(si)
} }
// makeKnownFieldsFunc generates functions for operations that can be performed // makeKnownFieldsFunc generates functions for operations that can be performed
@ -51,17 +58,23 @@ func (mi *MessageInfo) makeKnownFieldsFunc(si structInfo) {
for i := 0; i < fds.Len(); i++ { for i := 0; i < fds.Len(); i++ {
fd := fds.Get(i) fd := fds.Get(i)
fs := si.fieldsByNumber[fd.Number()] fs := si.fieldsByNumber[fd.Number()]
isOneof := fd.ContainingOneof() != nil && !fd.ContainingOneof().IsSynthetic()
if isOneof {
fs = si.oneofsByName[fd.ContainingOneof().Name()]
}
var fi fieldInfo var fi fieldInfo
switch { switch {
case fd.ContainingOneof() != nil && !fd.ContainingOneof().IsSynthetic(): case fs.Type == nil:
fi = fieldInfoForOneof(fd, si.oneofsByName[fd.ContainingOneof().Name()], mi.Exporter, si.oneofWrappersByNumber[fd.Number()]) fi = fieldInfoForMissing(fd) // never occurs for officially generated message types
case isOneof:
fi = fieldInfoForOneof(fd, fs, mi.Exporter, si.oneofWrappersByNumber[fd.Number()])
case fd.IsMap(): case fd.IsMap():
fi = fieldInfoForMap(fd, fs, mi.Exporter) fi = fieldInfoForMap(fd, fs, mi.Exporter)
case fd.IsList(): case fd.IsList():
fi = fieldInfoForList(fd, fs, mi.Exporter) fi = fieldInfoForList(fd, fs, mi.Exporter)
case fd.IsWeak(): case fd.IsWeak():
fi = fieldInfoForWeakMessage(fd, si.weakOffset) fi = fieldInfoForWeakMessage(fd, si.weakOffset)
case fd.Kind() == pref.MessageKind || fd.Kind() == pref.GroupKind: case fd.Message() != nil:
fi = fieldInfoForMessage(fd, fs, mi.Exporter) fi = fieldInfoForMessage(fd, fs, mi.Exporter)
default: default:
fi = fieldInfoForScalar(fd, fs, mi.Exporter) fi = fieldInfoForScalar(fd, fs, mi.Exporter)
@ -92,27 +105,53 @@ func (mi *MessageInfo) makeKnownFieldsFunc(si structInfo) {
i++ i++
} }
} }
// Introduce instability to iteration order, but keep it deterministic.
if len(mi.rangeInfos) > 1 && detrand.Bool() {
i := detrand.Intn(len(mi.rangeInfos) - 1)
mi.rangeInfos[i], mi.rangeInfos[i+1] = mi.rangeInfos[i+1], mi.rangeInfos[i]
}
} }
func (mi *MessageInfo) makeUnknownFieldsFunc(t reflect.Type, si structInfo) { func (mi *MessageInfo) makeUnknownFieldsFunc(t reflect.Type, si structInfo) {
mi.getUnknown = func(pointer) pref.RawFields { return nil } switch {
mi.setUnknown = func(pointer, pref.RawFields) { return } case si.unknownOffset.IsValid() && si.unknownType == unknownFieldsAType:
if si.unknownOffset.IsValid() { // Handle as []byte.
mi.getUnknown = func(p pointer) pref.RawFields { mi.getUnknown = func(p pointer) pref.RawFields {
if p.IsNil() { if p.IsNil() {
return nil return nil
} }
rv := p.Apply(si.unknownOffset).AsValueOf(unknownFieldsType) return *p.Apply(mi.unknownOffset).Bytes()
return pref.RawFields(*rv.Interface().(*[]byte))
} }
mi.setUnknown = func(p pointer, b pref.RawFields) { mi.setUnknown = func(p pointer, b pref.RawFields) {
if p.IsNil() { if p.IsNil() {
panic("invalid SetUnknown on nil Message") panic("invalid SetUnknown on nil Message")
} }
rv := p.Apply(si.unknownOffset).AsValueOf(unknownFieldsType) *p.Apply(mi.unknownOffset).Bytes() = b
*rv.Interface().(*[]byte) = []byte(b)
} }
} else { case si.unknownOffset.IsValid() && si.unknownType == unknownFieldsBType:
// Handle as *[]byte.
mi.getUnknown = func(p pointer) pref.RawFields {
if p.IsNil() {
return nil
}
bp := p.Apply(mi.unknownOffset).BytesPtr()
if *bp == nil {
return nil
}
return **bp
}
mi.setUnknown = func(p pointer, b pref.RawFields) {
if p.IsNil() {
panic("invalid SetUnknown on nil Message")
}
bp := p.Apply(mi.unknownOffset).BytesPtr()
if *bp == nil {
*bp = new([]byte)
}
**bp = b
}
default:
mi.getUnknown = func(pointer) pref.RawFields { mi.getUnknown = func(pointer) pref.RawFields {
return nil return nil
} }
@ -139,6 +178,58 @@ func (mi *MessageInfo) makeExtensionFieldsFunc(t reflect.Type, si structInfo) {
} }
} }
} }
func (mi *MessageInfo) makeFieldTypes(si structInfo) {
md := mi.Desc
fds := md.Fields()
for i := 0; i < fds.Len(); i++ {
var ft reflect.Type
fd := fds.Get(i)
fs := si.fieldsByNumber[fd.Number()]
isOneof := fd.ContainingOneof() != nil && !fd.ContainingOneof().IsSynthetic()
if isOneof {
fs = si.oneofsByName[fd.ContainingOneof().Name()]
}
var isMessage bool
switch {
case fs.Type == nil:
continue // never occurs for officially generated message types
case isOneof:
if fd.Enum() != nil || fd.Message() != nil {
ft = si.oneofWrappersByNumber[fd.Number()].Field(0).Type
}
case fd.IsMap():
if fd.MapValue().Enum() != nil || fd.MapValue().Message() != nil {
ft = fs.Type.Elem()
}
isMessage = fd.MapValue().Message() != nil
case fd.IsList():
if fd.Enum() != nil || fd.Message() != nil {
ft = fs.Type.Elem()
}
isMessage = fd.Message() != nil
case fd.Enum() != nil:
ft = fs.Type
if fd.HasPresence() && ft.Kind() == reflect.Ptr {
ft = ft.Elem()
}
case fd.Message() != nil:
ft = fs.Type
if fd.IsWeak() {
ft = nil
}
isMessage = true
}
if isMessage && ft != nil && ft.Kind() != reflect.Ptr {
ft = reflect.PtrTo(ft) // never occurs for officially generated message types
}
if ft != nil {
if mi.fieldTypes == nil {
mi.fieldTypes = make(map[pref.FieldNumber]interface{})
}
mi.fieldTypes[fd.Number()] = reflect.Zero(ft).Interface()
}
}
}
type extensionMap map[int32]ExtensionField type extensionMap map[int32]ExtensionField
@ -306,7 +397,6 @@ var (
// pointer to a named Go struct. If the provided type has a ProtoReflect method, // pointer to a named Go struct. If the provided type has a ProtoReflect method,
// it must be implemented by calling this method. // it must be implemented by calling this method.
func (mi *MessageInfo) MessageOf(m interface{}) pref.Message { func (mi *MessageInfo) MessageOf(m interface{}) pref.Message {
// TODO: Switch the input to be an opaque Pointer.
if reflect.TypeOf(m) != mi.GoReflectType { if reflect.TypeOf(m) != mi.GoReflectType {
panic(fmt.Sprintf("type mismatch: got %T, want %v", m, mi.GoReflectType)) panic(fmt.Sprintf("type mismatch: got %T, want %v", m, mi.GoReflectType))
} }
@ -320,6 +410,17 @@ func (mi *MessageInfo) MessageOf(m interface{}) pref.Message {
func (m *messageReflectWrapper) pointer() pointer { return m.p } func (m *messageReflectWrapper) pointer() pointer { return m.p }
func (m *messageReflectWrapper) messageInfo() *MessageInfo { return m.mi } func (m *messageReflectWrapper) messageInfo() *MessageInfo { return m.mi }
// Reset implements the v1 proto.Message.Reset method.
func (m *messageIfaceWrapper) Reset() {
if mr, ok := m.protoUnwrap().(interface{ Reset() }); ok {
mr.Reset()
return
}
rv := reflect.ValueOf(m.protoUnwrap())
if rv.Kind() == reflect.Ptr && !rv.IsNil() {
rv.Elem().Set(reflect.Zero(rv.Type().Elem()))
}
}
func (m *messageIfaceWrapper) ProtoReflect() pref.Message { func (m *messageIfaceWrapper) ProtoReflect() pref.Message {
return (*messageReflectWrapper)(m) return (*messageReflectWrapper)(m)
} }

View File

@ -28,6 +28,39 @@ type fieldInfo struct {
newField func() pref.Value newField func() pref.Value
} }
func fieldInfoForMissing(fd pref.FieldDescriptor) fieldInfo {
// This never occurs for generated message types.
// It implies that a hand-crafted type has missing Go fields
// for specific protobuf message fields.
return fieldInfo{
fieldDesc: fd,
has: func(p pointer) bool {
return false
},
clear: func(p pointer) {
panic("missing Go struct field for " + string(fd.FullName()))
},
get: func(p pointer) pref.Value {
return fd.Default()
},
set: func(p pointer, v pref.Value) {
panic("missing Go struct field for " + string(fd.FullName()))
},
mutable: func(p pointer) pref.Value {
panic("missing Go struct field for " + string(fd.FullName()))
},
newMessage: func() pref.Message {
panic("missing Go struct field for " + string(fd.FullName()))
},
newField: func() pref.Value {
if v := fd.Default(); v.IsValid() {
return v
}
panic("missing Go struct field for " + string(fd.FullName()))
},
}
}
func fieldInfoForOneof(fd pref.FieldDescriptor, fs reflect.StructField, x exporter, ot reflect.Type) fieldInfo { func fieldInfoForOneof(fd pref.FieldDescriptor, fs reflect.StructField, x exporter, ot reflect.Type) fieldInfo {
ft := fs.Type ft := fs.Type
if ft.Kind() != reflect.Interface { if ft.Kind() != reflect.Interface {
@ -97,7 +130,7 @@ func fieldInfoForOneof(fd pref.FieldDescriptor, fs reflect.StructField, x export
rv.Set(reflect.New(ot)) rv.Set(reflect.New(ot))
} }
rv = rv.Elem().Elem().Field(0) rv = rv.Elem().Elem().Field(0)
if rv.IsNil() { if rv.Kind() == reflect.Ptr && rv.IsNil() {
rv.Set(conv.GoValueOf(pref.ValueOfMessage(conv.New().Message()))) rv.Set(conv.GoValueOf(pref.ValueOfMessage(conv.New().Message())))
} }
return conv.PBValueOf(rv) return conv.PBValueOf(rv)
@ -225,7 +258,10 @@ func fieldInfoForScalar(fd pref.FieldDescriptor, fs reflect.StructField, x expor
isBytes := ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8 isBytes := ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8
if nullable { if nullable {
if ft.Kind() != reflect.Ptr && ft.Kind() != reflect.Slice { if ft.Kind() != reflect.Ptr && ft.Kind() != reflect.Slice {
panic(fmt.Sprintf("field %v has invalid type: got %v, want pointer", fd.FullName(), ft)) // This never occurs for generated message types.
// Despite the protobuf type system specifying presence,
// the Go field type cannot represent it.
nullable = false
} }
if ft.Kind() == reflect.Ptr { if ft.Kind() == reflect.Ptr {
ft = ft.Elem() ft = ft.Elem()
@ -388,6 +424,9 @@ func fieldInfoForMessage(fd pref.FieldDescriptor, fs reflect.StructField, x expo
return false return false
} }
rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
if fs.Type.Kind() != reflect.Ptr {
return !isZero(rv)
}
return !rv.IsNil() return !rv.IsNil()
}, },
clear: func(p pointer) { clear: func(p pointer) {
@ -404,13 +443,13 @@ func fieldInfoForMessage(fd pref.FieldDescriptor, fs reflect.StructField, x expo
set: func(p pointer, v pref.Value) { set: func(p pointer, v pref.Value) {
rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
rv.Set(conv.GoValueOf(v)) rv.Set(conv.GoValueOf(v))
if rv.IsNil() { if fs.Type.Kind() == reflect.Ptr && rv.IsNil() {
panic(fmt.Sprintf("field %v has invalid nil pointer", fd.FullName())) panic(fmt.Sprintf("field %v has invalid nil pointer", fd.FullName()))
} }
}, },
mutable: func(p pointer) pref.Value { mutable: func(p pointer) pref.Value {
rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
if rv.IsNil() { if fs.Type.Kind() == reflect.Ptr && rv.IsNil() {
rv.Set(conv.GoValueOf(conv.New())) rv.Set(conv.GoValueOf(conv.New()))
} }
return conv.PBValueOf(rv) return conv.PBValueOf(rv)
@ -464,3 +503,41 @@ func makeOneofInfo(od pref.OneofDescriptor, si structInfo, x exporter) *oneofInf
} }
return oi return oi
} }
// isZero is identical to reflect.Value.IsZero.
// TODO: Remove this when Go1.13 is the minimally supported Go version.
func isZero(v reflect.Value) bool {
switch v.Kind() {
case reflect.Bool:
return !v.Bool()
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return v.Int() == 0
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return v.Uint() == 0
case reflect.Float32, reflect.Float64:
return math.Float64bits(v.Float()) == 0
case reflect.Complex64, reflect.Complex128:
c := v.Complex()
return math.Float64bits(real(c)) == 0 && math.Float64bits(imag(c)) == 0
case reflect.Array:
for i := 0; i < v.Len(); i++ {
if !isZero(v.Index(i)) {
return false
}
}
return true
case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice, reflect.UnsafePointer:
return v.IsNil()
case reflect.String:
return v.Len() == 0
case reflect.Struct:
for i := 0; i < v.NumField(); i++ {
if !isZero(v.Field(i)) {
return false
}
}
return true
default:
panic(&reflect.ValueError{"reflect.Value.IsZero", v.Kind()})
}
}

View File

@ -121,6 +121,7 @@ func (p pointer) String() *string { return p.v.Interface().(*string) }
func (p pointer) StringPtr() **string { return p.v.Interface().(**string) } func (p pointer) StringPtr() **string { return p.v.Interface().(**string) }
func (p pointer) StringSlice() *[]string { return p.v.Interface().(*[]string) } func (p pointer) StringSlice() *[]string { return p.v.Interface().(*[]string) }
func (p pointer) Bytes() *[]byte { return p.v.Interface().(*[]byte) } func (p pointer) Bytes() *[]byte { return p.v.Interface().(*[]byte) }
func (p pointer) BytesPtr() **[]byte { return p.v.Interface().(**[]byte) }
func (p pointer) BytesSlice() *[][]byte { return p.v.Interface().(*[][]byte) } func (p pointer) BytesSlice() *[][]byte { return p.v.Interface().(*[][]byte) }
func (p pointer) WeakFields() *weakFields { return (*weakFields)(p.v.Interface().(*WeakFields)) } func (p pointer) WeakFields() *weakFields { return (*weakFields)(p.v.Interface().(*WeakFields)) }
func (p pointer) Extensions() *map[int32]ExtensionField { func (p pointer) Extensions() *map[int32]ExtensionField {

View File

@ -109,6 +109,7 @@ func (p pointer) String() *string { return (*string)(p.p)
func (p pointer) StringPtr() **string { return (**string)(p.p) } func (p pointer) StringPtr() **string { return (**string)(p.p) }
func (p pointer) StringSlice() *[]string { return (*[]string)(p.p) } func (p pointer) StringSlice() *[]string { return (*[]string)(p.p) }
func (p pointer) Bytes() *[]byte { return (*[]byte)(p.p) } func (p pointer) Bytes() *[]byte { return (*[]byte)(p.p) }
func (p pointer) BytesPtr() **[]byte { return (**[]byte)(p.p) }
func (p pointer) BytesSlice() *[][]byte { return (*[][]byte)(p.p) } func (p pointer) BytesSlice() *[][]byte { return (*[][]byte)(p.p) }
func (p pointer) WeakFields() *weakFields { return (*weakFields)(p.p) } func (p pointer) WeakFields() *weakFields { return (*weakFields)(p.p) }
func (p pointer) Extensions() *map[int32]ExtensionField { return (*map[int32]ExtensionField)(p.p) } func (p pointer) Extensions() *map[int32]ExtensionField { return (*map[int32]ExtensionField)(p.p) }

View File

@ -14,6 +14,7 @@ import (
"google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/encoding/protowire"
"google.golang.org/protobuf/internal/encoding/messageset" "google.golang.org/protobuf/internal/encoding/messageset"
"google.golang.org/protobuf/internal/flags" "google.golang.org/protobuf/internal/flags"
"google.golang.org/protobuf/internal/genid"
"google.golang.org/protobuf/internal/strs" "google.golang.org/protobuf/internal/strs"
pref "google.golang.org/protobuf/reflect/protoreflect" pref "google.golang.org/protobuf/reflect/protoreflect"
preg "google.golang.org/protobuf/reflect/protoregistry" preg "google.golang.org/protobuf/reflect/protoregistry"
@ -282,9 +283,9 @@ State:
switch { switch {
case st.typ == validationTypeMap: case st.typ == validationTypeMap:
switch num { switch num {
case 1: case genid.MapEntry_Key_field_number:
vi.typ = st.keyType vi.typ = st.keyType
case 2: case genid.MapEntry_Value_field_number:
vi.typ = st.valType vi.typ = st.valType
vi.mi = st.mi vi.mi = st.mi
vi.requiredBit = 1 vi.requiredBit = 1

View File

@ -1,43 +0,0 @@
// 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 mapsort provides sorted access to maps.
package mapsort
import (
"sort"
"google.golang.org/protobuf/reflect/protoreflect"
)
// Range iterates over every map entry in sorted key order,
// calling f for each key and value encountered.
func Range(mapv protoreflect.Map, keyKind protoreflect.Kind, f func(protoreflect.MapKey, protoreflect.Value) bool) {
var keys []protoreflect.MapKey
mapv.Range(func(key protoreflect.MapKey, _ protoreflect.Value) bool {
keys = append(keys, key)
return true
})
sort.Slice(keys, func(i, j int) bool {
switch keyKind {
case protoreflect.BoolKind:
return !keys[i].Bool() && keys[j].Bool()
case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind,
protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
return keys[i].Int() < keys[j].Int()
case protoreflect.Uint32Kind, protoreflect.Fixed32Kind,
protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
return keys[i].Uint() < keys[j].Uint()
case protoreflect.StringKind:
return keys[i].String() < keys[j].String()
default:
panic("invalid kind: " + keyKind.String())
}
})
for _, key := range keys {
if !f(key, mapv.Get(key)) {
break
}
}
}

View File

@ -0,0 +1,89 @@
// 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 order
import (
pref "google.golang.org/protobuf/reflect/protoreflect"
)
// FieldOrder specifies the ordering to visit message fields.
// It is a function that reports whether x is ordered before y.
type FieldOrder func(x, y pref.FieldDescriptor) bool
var (
// AnyFieldOrder specifies no specific field ordering.
AnyFieldOrder FieldOrder = nil
// LegacyFieldOrder sorts fields in the same ordering as emitted by
// wire serialization in the github.com/golang/protobuf implementation.
LegacyFieldOrder FieldOrder = func(x, y pref.FieldDescriptor) bool {
ox, oy := x.ContainingOneof(), y.ContainingOneof()
inOneof := func(od pref.OneofDescriptor) bool {
return od != nil && !od.IsSynthetic()
}
// Extension fields sort before non-extension fields.
if x.IsExtension() != y.IsExtension() {
return x.IsExtension() && !y.IsExtension()
}
// Fields not within a oneof sort before those within a oneof.
if inOneof(ox) != inOneof(oy) {
return !inOneof(ox) && inOneof(oy)
}
// Fields in disjoint oneof sets are sorted by declaration index.
if ox != nil && oy != nil && ox != oy {
return ox.Index() < oy.Index()
}
// Fields sorted by field number.
return x.Number() < y.Number()
}
// NumberFieldOrder sorts fields by their field number.
NumberFieldOrder FieldOrder = func(x, y pref.FieldDescriptor) bool {
return x.Number() < y.Number()
}
// IndexNameFieldOrder sorts non-extension fields before extension fields.
// Non-extensions are sorted according to their declaration index.
// Extensions are sorted according to their full name.
IndexNameFieldOrder FieldOrder = func(x, y pref.FieldDescriptor) bool {
// Non-extension fields sort before extension fields.
if x.IsExtension() != y.IsExtension() {
return !x.IsExtension() && y.IsExtension()
}
// Extensions sorted by fullname.
if x.IsExtension() && y.IsExtension() {
return x.FullName() < y.FullName()
}
// Non-extensions sorted by declaration index.
return x.Index() < y.Index()
}
)
// KeyOrder specifies the ordering to visit map entries.
// It is a function that reports whether x is ordered before y.
type KeyOrder func(x, y pref.MapKey) bool
var (
// AnyKeyOrder specifies no specific key ordering.
AnyKeyOrder KeyOrder = nil
// GenericKeyOrder sorts false before true, numeric keys in ascending order,
// and strings in lexicographical ordering according to UTF-8 codepoints.
GenericKeyOrder KeyOrder = func(x, y pref.MapKey) bool {
switch x.Interface().(type) {
case bool:
return !x.Bool() && y.Bool()
case int32, int64:
return x.Int() < y.Int()
case uint32, uint64:
return x.Uint() < y.Uint()
case string:
return x.String() < y.String()
default:
panic("invalid map key type")
}
}
)

View File

@ -0,0 +1,115 @@
// 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 order provides ordered access to messages and maps.
package order
import (
"sort"
"sync"
pref "google.golang.org/protobuf/reflect/protoreflect"
)
type messageField struct {
fd pref.FieldDescriptor
v pref.Value
}
var messageFieldPool = sync.Pool{
New: func() interface{} { return new([]messageField) },
}
type (
// FieldRnger is an interface for visiting all fields in a message.
// The protoreflect.Message type implements this interface.
FieldRanger interface{ Range(VisitField) }
// VisitField is called everytime a message field is visited.
VisitField = func(pref.FieldDescriptor, pref.Value) bool
)
// RangeFields iterates over the fields of fs according to the specified order.
func RangeFields(fs FieldRanger, less FieldOrder, fn VisitField) {
if less == nil {
fs.Range(fn)
return
}
// Obtain a pre-allocated scratch buffer.
p := messageFieldPool.Get().(*[]messageField)
fields := (*p)[:0]
defer func() {
if cap(fields) < 1024 {
*p = fields
messageFieldPool.Put(p)
}
}()
// Collect all fields in the message and sort them.
fs.Range(func(fd pref.FieldDescriptor, v pref.Value) bool {
fields = append(fields, messageField{fd, v})
return true
})
sort.Slice(fields, func(i, j int) bool {
return less(fields[i].fd, fields[j].fd)
})
// Visit the fields in the specified ordering.
for _, f := range fields {
if !fn(f.fd, f.v) {
return
}
}
}
type mapEntry struct {
k pref.MapKey
v pref.Value
}
var mapEntryPool = sync.Pool{
New: func() interface{} { return new([]mapEntry) },
}
type (
// EntryRanger is an interface for visiting all fields in a message.
// The protoreflect.Map type implements this interface.
EntryRanger interface{ Range(VisitEntry) }
// VisitEntry is called everytime a map entry is visited.
VisitEntry = func(pref.MapKey, pref.Value) bool
)
// RangeEntries iterates over the entries of es according to the specified order.
func RangeEntries(es EntryRanger, less KeyOrder, fn VisitEntry) {
if less == nil {
es.Range(fn)
return
}
// Obtain a pre-allocated scratch buffer.
p := mapEntryPool.Get().(*[]mapEntry)
entries := (*p)[:0]
defer func() {
if cap(entries) < 1024 {
*p = entries
mapEntryPool.Put(p)
}
}()
// Collect all entries in the map and sort them.
es.Range(func(k pref.MapKey, v pref.Value) bool {
entries = append(entries, mapEntry{k, v})
return true
})
sort.Slice(entries, func(i, j int) bool {
return less(entries[i].k, entries[j].k)
})
// Visit the entries in the specified ordering.
for _, e := range entries {
if !fn(e.k, e.v) {
return
}
}
}

View File

@ -52,7 +52,7 @@ import (
// 10. Send out the CL for review and submit it. // 10. Send out the CL for review and submit it.
const ( const (
Major = 1 Major = 1
Minor = 23 Minor = 26
Patch = 0 Patch = 0
PreRelease = "" PreRelease = ""
) )

View File

@ -9,6 +9,7 @@ import (
"google.golang.org/protobuf/internal/encoding/messageset" "google.golang.org/protobuf/internal/encoding/messageset"
"google.golang.org/protobuf/internal/errors" "google.golang.org/protobuf/internal/errors"
"google.golang.org/protobuf/internal/flags" "google.golang.org/protobuf/internal/flags"
"google.golang.org/protobuf/internal/genid"
"google.golang.org/protobuf/internal/pragma" "google.golang.org/protobuf/internal/pragma"
"google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/reflect/protoregistry" "google.golang.org/protobuf/reflect/protoregistry"
@ -44,12 +45,14 @@ type UnmarshalOptions struct {
} }
// Unmarshal parses the wire-format message in b and places the result in m. // Unmarshal parses the wire-format message in b and places the result in m.
// The provided message must be mutable (e.g., a non-nil pointer to a message).
func Unmarshal(b []byte, m Message) error { func Unmarshal(b []byte, m Message) error {
_, err := UnmarshalOptions{}.unmarshal(b, m.ProtoReflect()) _, err := UnmarshalOptions{}.unmarshal(b, m.ProtoReflect())
return err return err
} }
// Unmarshal parses the wire-format message in b and places the result in m. // Unmarshal parses the wire-format message in b and places the result in m.
// The provided message must be mutable (e.g., a non-nil pointer to a message).
func (o UnmarshalOptions) Unmarshal(b []byte, m Message) error { func (o UnmarshalOptions) Unmarshal(b []byte, m Message) error {
_, err := o.unmarshal(b, m.ProtoReflect()) _, err := o.unmarshal(b, m.ProtoReflect())
return err return err
@ -63,12 +66,15 @@ func (o UnmarshalOptions) UnmarshalState(in protoiface.UnmarshalInput) (protoifa
return o.unmarshal(in.Buf, in.Message) return o.unmarshal(in.Buf, in.Message)
} }
// unmarshal is a centralized function that all unmarshal operations go through.
// For profiling purposes, avoid changing the name of this function or
// introducing other code paths for unmarshal that do not go through this.
func (o UnmarshalOptions) unmarshal(b []byte, m protoreflect.Message) (out protoiface.UnmarshalOutput, err error) { func (o UnmarshalOptions) unmarshal(b []byte, m protoreflect.Message) (out protoiface.UnmarshalOutput, err error) {
if o.Resolver == nil { if o.Resolver == nil {
o.Resolver = protoregistry.GlobalTypes o.Resolver = protoregistry.GlobalTypes
} }
if !o.Merge { if !o.Merge {
Reset(m.Interface()) // TODO Reset(m.Interface())
} }
allowPartial := o.AllowPartial allowPartial := o.AllowPartial
o.Merge = true o.Merge = true
@ -105,17 +111,17 @@ func (o UnmarshalOptions) unmarshalMessage(b []byte, m protoreflect.Message) err
func (o UnmarshalOptions) unmarshalMessageSlow(b []byte, m protoreflect.Message) error { func (o UnmarshalOptions) unmarshalMessageSlow(b []byte, m protoreflect.Message) error {
md := m.Descriptor() md := m.Descriptor()
if messageset.IsMessageSet(md) { if messageset.IsMessageSet(md) {
return unmarshalMessageSet(b, m, o) return o.unmarshalMessageSet(b, m)
} }
fields := md.Fields() fields := md.Fields()
for len(b) > 0 { for len(b) > 0 {
// Parse the tag (field number and wire type). // Parse the tag (field number and wire type).
num, wtyp, tagLen := protowire.ConsumeTag(b) num, wtyp, tagLen := protowire.ConsumeTag(b)
if tagLen < 0 { if tagLen < 0 {
return protowire.ParseError(tagLen) return errDecode
} }
if num > protowire.MaxValidNumber { if num > protowire.MaxValidNumber {
return errors.New("invalid field number") return errDecode
} }
// Find the field descriptor for this field number. // Find the field descriptor for this field number.
@ -155,7 +161,7 @@ func (o UnmarshalOptions) unmarshalMessageSlow(b []byte, m protoreflect.Message)
} }
valLen = protowire.ConsumeFieldValue(num, wtyp, b[tagLen:]) valLen = protowire.ConsumeFieldValue(num, wtyp, b[tagLen:])
if valLen < 0 { if valLen < 0 {
return protowire.ParseError(valLen) return errDecode
} }
if !o.DiscardUnknown { if !o.DiscardUnknown {
m.SetUnknown(append(m.GetUnknown(), b[:tagLen+valLen]...)) m.SetUnknown(append(m.GetUnknown(), b[:tagLen+valLen]...))
@ -190,7 +196,7 @@ func (o UnmarshalOptions) unmarshalMap(b []byte, wtyp protowire.Type, mapv proto
} }
b, n = protowire.ConsumeBytes(b) b, n = protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return 0, protowire.ParseError(n) return 0, errDecode
} }
var ( var (
keyField = fd.MapKey() keyField = fd.MapKey()
@ -209,21 +215,21 @@ func (o UnmarshalOptions) unmarshalMap(b []byte, wtyp protowire.Type, mapv proto
for len(b) > 0 { for len(b) > 0 {
num, wtyp, n := protowire.ConsumeTag(b) num, wtyp, n := protowire.ConsumeTag(b)
if n < 0 { if n < 0 {
return 0, protowire.ParseError(n) return 0, errDecode
} }
if num > protowire.MaxValidNumber { if num > protowire.MaxValidNumber {
return 0, errors.New("invalid field number") return 0, errDecode
} }
b = b[n:] b = b[n:]
err = errUnknown err = errUnknown
switch num { switch num {
case 1: case genid.MapEntry_Key_field_number:
key, n, err = o.unmarshalScalar(b, wtyp, keyField) key, n, err = o.unmarshalScalar(b, wtyp, keyField)
if err != nil { if err != nil {
break break
} }
haveKey = true haveKey = true
case 2: case genid.MapEntry_Value_field_number:
var v protoreflect.Value var v protoreflect.Value
v, n, err = o.unmarshalScalar(b, wtyp, valField) v, n, err = o.unmarshalScalar(b, wtyp, valField)
if err != nil { if err != nil {
@ -242,7 +248,7 @@ func (o UnmarshalOptions) unmarshalMap(b []byte, wtyp protowire.Type, mapv proto
if err == errUnknown { if err == errUnknown {
n = protowire.ConsumeFieldValue(num, wtyp, b) n = protowire.ConsumeFieldValue(num, wtyp, b)
if n < 0 { if n < 0 {
return 0, protowire.ParseError(n) return 0, errDecode
} }
} else if err != nil { } else if err != nil {
return 0, err return 0, err
@ -268,3 +274,5 @@ func (o UnmarshalOptions) unmarshalMap(b []byte, wtyp protowire.Type, mapv proto
// to the unknown field set of a message. It is never returned from an exported // to the unknown field set of a message. It is never returned from an exported
// function. // function.
var errUnknown = errors.New("BUG: internal error (unknown)") var errUnknown = errors.New("BUG: internal error (unknown)")
var errDecode = errors.New("cannot parse invalid wire-format data")

View File

@ -27,7 +27,7 @@ func (o UnmarshalOptions) unmarshalScalar(b []byte, wtyp protowire.Type, fd prot
} }
v, n := protowire.ConsumeVarint(b) v, n := protowire.ConsumeVarint(b)
if n < 0 { if n < 0 {
return val, 0, protowire.ParseError(n) return val, 0, errDecode
} }
return protoreflect.ValueOfBool(protowire.DecodeBool(v)), n, nil return protoreflect.ValueOfBool(protowire.DecodeBool(v)), n, nil
case protoreflect.EnumKind: case protoreflect.EnumKind:
@ -36,7 +36,7 @@ func (o UnmarshalOptions) unmarshalScalar(b []byte, wtyp protowire.Type, fd prot
} }
v, n := protowire.ConsumeVarint(b) v, n := protowire.ConsumeVarint(b)
if n < 0 { if n < 0 {
return val, 0, protowire.ParseError(n) return val, 0, errDecode
} }
return protoreflect.ValueOfEnum(protoreflect.EnumNumber(v)), n, nil return protoreflect.ValueOfEnum(protoreflect.EnumNumber(v)), n, nil
case protoreflect.Int32Kind: case protoreflect.Int32Kind:
@ -45,7 +45,7 @@ func (o UnmarshalOptions) unmarshalScalar(b []byte, wtyp protowire.Type, fd prot
} }
v, n := protowire.ConsumeVarint(b) v, n := protowire.ConsumeVarint(b)
if n < 0 { if n < 0 {
return val, 0, protowire.ParseError(n) return val, 0, errDecode
} }
return protoreflect.ValueOfInt32(int32(v)), n, nil return protoreflect.ValueOfInt32(int32(v)), n, nil
case protoreflect.Sint32Kind: case protoreflect.Sint32Kind:
@ -54,7 +54,7 @@ func (o UnmarshalOptions) unmarshalScalar(b []byte, wtyp protowire.Type, fd prot
} }
v, n := protowire.ConsumeVarint(b) v, n := protowire.ConsumeVarint(b)
if n < 0 { if n < 0 {
return val, 0, protowire.ParseError(n) return val, 0, errDecode
} }
return protoreflect.ValueOfInt32(int32(protowire.DecodeZigZag(v & math.MaxUint32))), n, nil return protoreflect.ValueOfInt32(int32(protowire.DecodeZigZag(v & math.MaxUint32))), n, nil
case protoreflect.Uint32Kind: case protoreflect.Uint32Kind:
@ -63,7 +63,7 @@ func (o UnmarshalOptions) unmarshalScalar(b []byte, wtyp protowire.Type, fd prot
} }
v, n := protowire.ConsumeVarint(b) v, n := protowire.ConsumeVarint(b)
if n < 0 { if n < 0 {
return val, 0, protowire.ParseError(n) return val, 0, errDecode
} }
return protoreflect.ValueOfUint32(uint32(v)), n, nil return protoreflect.ValueOfUint32(uint32(v)), n, nil
case protoreflect.Int64Kind: case protoreflect.Int64Kind:
@ -72,7 +72,7 @@ func (o UnmarshalOptions) unmarshalScalar(b []byte, wtyp protowire.Type, fd prot
} }
v, n := protowire.ConsumeVarint(b) v, n := protowire.ConsumeVarint(b)
if n < 0 { if n < 0 {
return val, 0, protowire.ParseError(n) return val, 0, errDecode
} }
return protoreflect.ValueOfInt64(int64(v)), n, nil return protoreflect.ValueOfInt64(int64(v)), n, nil
case protoreflect.Sint64Kind: case protoreflect.Sint64Kind:
@ -81,7 +81,7 @@ func (o UnmarshalOptions) unmarshalScalar(b []byte, wtyp protowire.Type, fd prot
} }
v, n := protowire.ConsumeVarint(b) v, n := protowire.ConsumeVarint(b)
if n < 0 { if n < 0 {
return val, 0, protowire.ParseError(n) return val, 0, errDecode
} }
return protoreflect.ValueOfInt64(protowire.DecodeZigZag(v)), n, nil return protoreflect.ValueOfInt64(protowire.DecodeZigZag(v)), n, nil
case protoreflect.Uint64Kind: case protoreflect.Uint64Kind:
@ -90,7 +90,7 @@ func (o UnmarshalOptions) unmarshalScalar(b []byte, wtyp protowire.Type, fd prot
} }
v, n := protowire.ConsumeVarint(b) v, n := protowire.ConsumeVarint(b)
if n < 0 { if n < 0 {
return val, 0, protowire.ParseError(n) return val, 0, errDecode
} }
return protoreflect.ValueOfUint64(v), n, nil return protoreflect.ValueOfUint64(v), n, nil
case protoreflect.Sfixed32Kind: case protoreflect.Sfixed32Kind:
@ -99,7 +99,7 @@ func (o UnmarshalOptions) unmarshalScalar(b []byte, wtyp protowire.Type, fd prot
} }
v, n := protowire.ConsumeFixed32(b) v, n := protowire.ConsumeFixed32(b)
if n < 0 { if n < 0 {
return val, 0, protowire.ParseError(n) return val, 0, errDecode
} }
return protoreflect.ValueOfInt32(int32(v)), n, nil return protoreflect.ValueOfInt32(int32(v)), n, nil
case protoreflect.Fixed32Kind: case protoreflect.Fixed32Kind:
@ -108,7 +108,7 @@ func (o UnmarshalOptions) unmarshalScalar(b []byte, wtyp protowire.Type, fd prot
} }
v, n := protowire.ConsumeFixed32(b) v, n := protowire.ConsumeFixed32(b)
if n < 0 { if n < 0 {
return val, 0, protowire.ParseError(n) return val, 0, errDecode
} }
return protoreflect.ValueOfUint32(uint32(v)), n, nil return protoreflect.ValueOfUint32(uint32(v)), n, nil
case protoreflect.FloatKind: case protoreflect.FloatKind:
@ -117,7 +117,7 @@ func (o UnmarshalOptions) unmarshalScalar(b []byte, wtyp protowire.Type, fd prot
} }
v, n := protowire.ConsumeFixed32(b) v, n := protowire.ConsumeFixed32(b)
if n < 0 { if n < 0 {
return val, 0, protowire.ParseError(n) return val, 0, errDecode
} }
return protoreflect.ValueOfFloat32(math.Float32frombits(uint32(v))), n, nil return protoreflect.ValueOfFloat32(math.Float32frombits(uint32(v))), n, nil
case protoreflect.Sfixed64Kind: case protoreflect.Sfixed64Kind:
@ -126,7 +126,7 @@ func (o UnmarshalOptions) unmarshalScalar(b []byte, wtyp protowire.Type, fd prot
} }
v, n := protowire.ConsumeFixed64(b) v, n := protowire.ConsumeFixed64(b)
if n < 0 { if n < 0 {
return val, 0, protowire.ParseError(n) return val, 0, errDecode
} }
return protoreflect.ValueOfInt64(int64(v)), n, nil return protoreflect.ValueOfInt64(int64(v)), n, nil
case protoreflect.Fixed64Kind: case protoreflect.Fixed64Kind:
@ -135,7 +135,7 @@ func (o UnmarshalOptions) unmarshalScalar(b []byte, wtyp protowire.Type, fd prot
} }
v, n := protowire.ConsumeFixed64(b) v, n := protowire.ConsumeFixed64(b)
if n < 0 { if n < 0 {
return val, 0, protowire.ParseError(n) return val, 0, errDecode
} }
return protoreflect.ValueOfUint64(v), n, nil return protoreflect.ValueOfUint64(v), n, nil
case protoreflect.DoubleKind: case protoreflect.DoubleKind:
@ -144,7 +144,7 @@ func (o UnmarshalOptions) unmarshalScalar(b []byte, wtyp protowire.Type, fd prot
} }
v, n := protowire.ConsumeFixed64(b) v, n := protowire.ConsumeFixed64(b)
if n < 0 { if n < 0 {
return val, 0, protowire.ParseError(n) return val, 0, errDecode
} }
return protoreflect.ValueOfFloat64(math.Float64frombits(v)), n, nil return protoreflect.ValueOfFloat64(math.Float64frombits(v)), n, nil
case protoreflect.StringKind: case protoreflect.StringKind:
@ -153,7 +153,7 @@ func (o UnmarshalOptions) unmarshalScalar(b []byte, wtyp protowire.Type, fd prot
} }
v, n := protowire.ConsumeBytes(b) v, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return val, 0, protowire.ParseError(n) return val, 0, errDecode
} }
if strs.EnforceUTF8(fd) && !utf8.Valid(v) { if strs.EnforceUTF8(fd) && !utf8.Valid(v) {
return protoreflect.Value{}, 0, errors.InvalidUTF8(string(fd.FullName())) return protoreflect.Value{}, 0, errors.InvalidUTF8(string(fd.FullName()))
@ -165,7 +165,7 @@ func (o UnmarshalOptions) unmarshalScalar(b []byte, wtyp protowire.Type, fd prot
} }
v, n := protowire.ConsumeBytes(b) v, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return val, 0, protowire.ParseError(n) return val, 0, errDecode
} }
return protoreflect.ValueOfBytes(append(emptyBuf[:], v...)), n, nil return protoreflect.ValueOfBytes(append(emptyBuf[:], v...)), n, nil
case protoreflect.MessageKind: case protoreflect.MessageKind:
@ -174,7 +174,7 @@ func (o UnmarshalOptions) unmarshalScalar(b []byte, wtyp protowire.Type, fd prot
} }
v, n := protowire.ConsumeBytes(b) v, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return val, 0, protowire.ParseError(n) return val, 0, errDecode
} }
return protoreflect.ValueOfBytes(v), n, nil return protoreflect.ValueOfBytes(v), n, nil
case protoreflect.GroupKind: case protoreflect.GroupKind:
@ -183,7 +183,7 @@ func (o UnmarshalOptions) unmarshalScalar(b []byte, wtyp protowire.Type, fd prot
} }
v, n := protowire.ConsumeGroup(fd.Number(), b) v, n := protowire.ConsumeGroup(fd.Number(), b)
if n < 0 { if n < 0 {
return val, 0, protowire.ParseError(n) return val, 0, errDecode
} }
return protoreflect.ValueOfBytes(v), n, nil return protoreflect.ValueOfBytes(v), n, nil
default: default:
@ -197,12 +197,12 @@ func (o UnmarshalOptions) unmarshalList(b []byte, wtyp protowire.Type, list prot
if wtyp == protowire.BytesType { if wtyp == protowire.BytesType {
buf, n := protowire.ConsumeBytes(b) buf, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return 0, protowire.ParseError(n) return 0, errDecode
} }
for len(buf) > 0 { for len(buf) > 0 {
v, n := protowire.ConsumeVarint(buf) v, n := protowire.ConsumeVarint(buf)
if n < 0 { if n < 0 {
return 0, protowire.ParseError(n) return 0, errDecode
} }
buf = buf[n:] buf = buf[n:]
list.Append(protoreflect.ValueOfBool(protowire.DecodeBool(v))) list.Append(protoreflect.ValueOfBool(protowire.DecodeBool(v)))
@ -214,7 +214,7 @@ func (o UnmarshalOptions) unmarshalList(b []byte, wtyp protowire.Type, list prot
} }
v, n := protowire.ConsumeVarint(b) v, n := protowire.ConsumeVarint(b)
if n < 0 { if n < 0 {
return 0, protowire.ParseError(n) return 0, errDecode
} }
list.Append(protoreflect.ValueOfBool(protowire.DecodeBool(v))) list.Append(protoreflect.ValueOfBool(protowire.DecodeBool(v)))
return n, nil return n, nil
@ -222,12 +222,12 @@ func (o UnmarshalOptions) unmarshalList(b []byte, wtyp protowire.Type, list prot
if wtyp == protowire.BytesType { if wtyp == protowire.BytesType {
buf, n := protowire.ConsumeBytes(b) buf, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return 0, protowire.ParseError(n) return 0, errDecode
} }
for len(buf) > 0 { for len(buf) > 0 {
v, n := protowire.ConsumeVarint(buf) v, n := protowire.ConsumeVarint(buf)
if n < 0 { if n < 0 {
return 0, protowire.ParseError(n) return 0, errDecode
} }
buf = buf[n:] buf = buf[n:]
list.Append(protoreflect.ValueOfEnum(protoreflect.EnumNumber(v))) list.Append(protoreflect.ValueOfEnum(protoreflect.EnumNumber(v)))
@ -239,7 +239,7 @@ func (o UnmarshalOptions) unmarshalList(b []byte, wtyp protowire.Type, list prot
} }
v, n := protowire.ConsumeVarint(b) v, n := protowire.ConsumeVarint(b)
if n < 0 { if n < 0 {
return 0, protowire.ParseError(n) return 0, errDecode
} }
list.Append(protoreflect.ValueOfEnum(protoreflect.EnumNumber(v))) list.Append(protoreflect.ValueOfEnum(protoreflect.EnumNumber(v)))
return n, nil return n, nil
@ -247,12 +247,12 @@ func (o UnmarshalOptions) unmarshalList(b []byte, wtyp protowire.Type, list prot
if wtyp == protowire.BytesType { if wtyp == protowire.BytesType {
buf, n := protowire.ConsumeBytes(b) buf, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return 0, protowire.ParseError(n) return 0, errDecode
} }
for len(buf) > 0 { for len(buf) > 0 {
v, n := protowire.ConsumeVarint(buf) v, n := protowire.ConsumeVarint(buf)
if n < 0 { if n < 0 {
return 0, protowire.ParseError(n) return 0, errDecode
} }
buf = buf[n:] buf = buf[n:]
list.Append(protoreflect.ValueOfInt32(int32(v))) list.Append(protoreflect.ValueOfInt32(int32(v)))
@ -264,7 +264,7 @@ func (o UnmarshalOptions) unmarshalList(b []byte, wtyp protowire.Type, list prot
} }
v, n := protowire.ConsumeVarint(b) v, n := protowire.ConsumeVarint(b)
if n < 0 { if n < 0 {
return 0, protowire.ParseError(n) return 0, errDecode
} }
list.Append(protoreflect.ValueOfInt32(int32(v))) list.Append(protoreflect.ValueOfInt32(int32(v)))
return n, nil return n, nil
@ -272,12 +272,12 @@ func (o UnmarshalOptions) unmarshalList(b []byte, wtyp protowire.Type, list prot
if wtyp == protowire.BytesType { if wtyp == protowire.BytesType {
buf, n := protowire.ConsumeBytes(b) buf, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return 0, protowire.ParseError(n) return 0, errDecode
} }
for len(buf) > 0 { for len(buf) > 0 {
v, n := protowire.ConsumeVarint(buf) v, n := protowire.ConsumeVarint(buf)
if n < 0 { if n < 0 {
return 0, protowire.ParseError(n) return 0, errDecode
} }
buf = buf[n:] buf = buf[n:]
list.Append(protoreflect.ValueOfInt32(int32(protowire.DecodeZigZag(v & math.MaxUint32)))) list.Append(protoreflect.ValueOfInt32(int32(protowire.DecodeZigZag(v & math.MaxUint32))))
@ -289,7 +289,7 @@ func (o UnmarshalOptions) unmarshalList(b []byte, wtyp protowire.Type, list prot
} }
v, n := protowire.ConsumeVarint(b) v, n := protowire.ConsumeVarint(b)
if n < 0 { if n < 0 {
return 0, protowire.ParseError(n) return 0, errDecode
} }
list.Append(protoreflect.ValueOfInt32(int32(protowire.DecodeZigZag(v & math.MaxUint32)))) list.Append(protoreflect.ValueOfInt32(int32(protowire.DecodeZigZag(v & math.MaxUint32))))
return n, nil return n, nil
@ -297,12 +297,12 @@ func (o UnmarshalOptions) unmarshalList(b []byte, wtyp protowire.Type, list prot
if wtyp == protowire.BytesType { if wtyp == protowire.BytesType {
buf, n := protowire.ConsumeBytes(b) buf, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return 0, protowire.ParseError(n) return 0, errDecode
} }
for len(buf) > 0 { for len(buf) > 0 {
v, n := protowire.ConsumeVarint(buf) v, n := protowire.ConsumeVarint(buf)
if n < 0 { if n < 0 {
return 0, protowire.ParseError(n) return 0, errDecode
} }
buf = buf[n:] buf = buf[n:]
list.Append(protoreflect.ValueOfUint32(uint32(v))) list.Append(protoreflect.ValueOfUint32(uint32(v)))
@ -314,7 +314,7 @@ func (o UnmarshalOptions) unmarshalList(b []byte, wtyp protowire.Type, list prot
} }
v, n := protowire.ConsumeVarint(b) v, n := protowire.ConsumeVarint(b)
if n < 0 { if n < 0 {
return 0, protowire.ParseError(n) return 0, errDecode
} }
list.Append(protoreflect.ValueOfUint32(uint32(v))) list.Append(protoreflect.ValueOfUint32(uint32(v)))
return n, nil return n, nil
@ -322,12 +322,12 @@ func (o UnmarshalOptions) unmarshalList(b []byte, wtyp protowire.Type, list prot
if wtyp == protowire.BytesType { if wtyp == protowire.BytesType {
buf, n := protowire.ConsumeBytes(b) buf, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return 0, protowire.ParseError(n) return 0, errDecode
} }
for len(buf) > 0 { for len(buf) > 0 {
v, n := protowire.ConsumeVarint(buf) v, n := protowire.ConsumeVarint(buf)
if n < 0 { if n < 0 {
return 0, protowire.ParseError(n) return 0, errDecode
} }
buf = buf[n:] buf = buf[n:]
list.Append(protoreflect.ValueOfInt64(int64(v))) list.Append(protoreflect.ValueOfInt64(int64(v)))
@ -339,7 +339,7 @@ func (o UnmarshalOptions) unmarshalList(b []byte, wtyp protowire.Type, list prot
} }
v, n := protowire.ConsumeVarint(b) v, n := protowire.ConsumeVarint(b)
if n < 0 { if n < 0 {
return 0, protowire.ParseError(n) return 0, errDecode
} }
list.Append(protoreflect.ValueOfInt64(int64(v))) list.Append(protoreflect.ValueOfInt64(int64(v)))
return n, nil return n, nil
@ -347,12 +347,12 @@ func (o UnmarshalOptions) unmarshalList(b []byte, wtyp protowire.Type, list prot
if wtyp == protowire.BytesType { if wtyp == protowire.BytesType {
buf, n := protowire.ConsumeBytes(b) buf, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return 0, protowire.ParseError(n) return 0, errDecode
} }
for len(buf) > 0 { for len(buf) > 0 {
v, n := protowire.ConsumeVarint(buf) v, n := protowire.ConsumeVarint(buf)
if n < 0 { if n < 0 {
return 0, protowire.ParseError(n) return 0, errDecode
} }
buf = buf[n:] buf = buf[n:]
list.Append(protoreflect.ValueOfInt64(protowire.DecodeZigZag(v))) list.Append(protoreflect.ValueOfInt64(protowire.DecodeZigZag(v)))
@ -364,7 +364,7 @@ func (o UnmarshalOptions) unmarshalList(b []byte, wtyp protowire.Type, list prot
} }
v, n := protowire.ConsumeVarint(b) v, n := protowire.ConsumeVarint(b)
if n < 0 { if n < 0 {
return 0, protowire.ParseError(n) return 0, errDecode
} }
list.Append(protoreflect.ValueOfInt64(protowire.DecodeZigZag(v))) list.Append(protoreflect.ValueOfInt64(protowire.DecodeZigZag(v)))
return n, nil return n, nil
@ -372,12 +372,12 @@ func (o UnmarshalOptions) unmarshalList(b []byte, wtyp protowire.Type, list prot
if wtyp == protowire.BytesType { if wtyp == protowire.BytesType {
buf, n := protowire.ConsumeBytes(b) buf, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return 0, protowire.ParseError(n) return 0, errDecode
} }
for len(buf) > 0 { for len(buf) > 0 {
v, n := protowire.ConsumeVarint(buf) v, n := protowire.ConsumeVarint(buf)
if n < 0 { if n < 0 {
return 0, protowire.ParseError(n) return 0, errDecode
} }
buf = buf[n:] buf = buf[n:]
list.Append(protoreflect.ValueOfUint64(v)) list.Append(protoreflect.ValueOfUint64(v))
@ -389,7 +389,7 @@ func (o UnmarshalOptions) unmarshalList(b []byte, wtyp protowire.Type, list prot
} }
v, n := protowire.ConsumeVarint(b) v, n := protowire.ConsumeVarint(b)
if n < 0 { if n < 0 {
return 0, protowire.ParseError(n) return 0, errDecode
} }
list.Append(protoreflect.ValueOfUint64(v)) list.Append(protoreflect.ValueOfUint64(v))
return n, nil return n, nil
@ -397,12 +397,12 @@ func (o UnmarshalOptions) unmarshalList(b []byte, wtyp protowire.Type, list prot
if wtyp == protowire.BytesType { if wtyp == protowire.BytesType {
buf, n := protowire.ConsumeBytes(b) buf, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return 0, protowire.ParseError(n) return 0, errDecode
} }
for len(buf) > 0 { for len(buf) > 0 {
v, n := protowire.ConsumeFixed32(buf) v, n := protowire.ConsumeFixed32(buf)
if n < 0 { if n < 0 {
return 0, protowire.ParseError(n) return 0, errDecode
} }
buf = buf[n:] buf = buf[n:]
list.Append(protoreflect.ValueOfInt32(int32(v))) list.Append(protoreflect.ValueOfInt32(int32(v)))
@ -414,7 +414,7 @@ func (o UnmarshalOptions) unmarshalList(b []byte, wtyp protowire.Type, list prot
} }
v, n := protowire.ConsumeFixed32(b) v, n := protowire.ConsumeFixed32(b)
if n < 0 { if n < 0 {
return 0, protowire.ParseError(n) return 0, errDecode
} }
list.Append(protoreflect.ValueOfInt32(int32(v))) list.Append(protoreflect.ValueOfInt32(int32(v)))
return n, nil return n, nil
@ -422,12 +422,12 @@ func (o UnmarshalOptions) unmarshalList(b []byte, wtyp protowire.Type, list prot
if wtyp == protowire.BytesType { if wtyp == protowire.BytesType {
buf, n := protowire.ConsumeBytes(b) buf, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return 0, protowire.ParseError(n) return 0, errDecode
} }
for len(buf) > 0 { for len(buf) > 0 {
v, n := protowire.ConsumeFixed32(buf) v, n := protowire.ConsumeFixed32(buf)
if n < 0 { if n < 0 {
return 0, protowire.ParseError(n) return 0, errDecode
} }
buf = buf[n:] buf = buf[n:]
list.Append(protoreflect.ValueOfUint32(uint32(v))) list.Append(protoreflect.ValueOfUint32(uint32(v)))
@ -439,7 +439,7 @@ func (o UnmarshalOptions) unmarshalList(b []byte, wtyp protowire.Type, list prot
} }
v, n := protowire.ConsumeFixed32(b) v, n := protowire.ConsumeFixed32(b)
if n < 0 { if n < 0 {
return 0, protowire.ParseError(n) return 0, errDecode
} }
list.Append(protoreflect.ValueOfUint32(uint32(v))) list.Append(protoreflect.ValueOfUint32(uint32(v)))
return n, nil return n, nil
@ -447,12 +447,12 @@ func (o UnmarshalOptions) unmarshalList(b []byte, wtyp protowire.Type, list prot
if wtyp == protowire.BytesType { if wtyp == protowire.BytesType {
buf, n := protowire.ConsumeBytes(b) buf, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return 0, protowire.ParseError(n) return 0, errDecode
} }
for len(buf) > 0 { for len(buf) > 0 {
v, n := protowire.ConsumeFixed32(buf) v, n := protowire.ConsumeFixed32(buf)
if n < 0 { if n < 0 {
return 0, protowire.ParseError(n) return 0, errDecode
} }
buf = buf[n:] buf = buf[n:]
list.Append(protoreflect.ValueOfFloat32(math.Float32frombits(uint32(v)))) list.Append(protoreflect.ValueOfFloat32(math.Float32frombits(uint32(v))))
@ -464,7 +464,7 @@ func (o UnmarshalOptions) unmarshalList(b []byte, wtyp protowire.Type, list prot
} }
v, n := protowire.ConsumeFixed32(b) v, n := protowire.ConsumeFixed32(b)
if n < 0 { if n < 0 {
return 0, protowire.ParseError(n) return 0, errDecode
} }
list.Append(protoreflect.ValueOfFloat32(math.Float32frombits(uint32(v)))) list.Append(protoreflect.ValueOfFloat32(math.Float32frombits(uint32(v))))
return n, nil return n, nil
@ -472,12 +472,12 @@ func (o UnmarshalOptions) unmarshalList(b []byte, wtyp protowire.Type, list prot
if wtyp == protowire.BytesType { if wtyp == protowire.BytesType {
buf, n := protowire.ConsumeBytes(b) buf, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return 0, protowire.ParseError(n) return 0, errDecode
} }
for len(buf) > 0 { for len(buf) > 0 {
v, n := protowire.ConsumeFixed64(buf) v, n := protowire.ConsumeFixed64(buf)
if n < 0 { if n < 0 {
return 0, protowire.ParseError(n) return 0, errDecode
} }
buf = buf[n:] buf = buf[n:]
list.Append(protoreflect.ValueOfInt64(int64(v))) list.Append(protoreflect.ValueOfInt64(int64(v)))
@ -489,7 +489,7 @@ func (o UnmarshalOptions) unmarshalList(b []byte, wtyp protowire.Type, list prot
} }
v, n := protowire.ConsumeFixed64(b) v, n := protowire.ConsumeFixed64(b)
if n < 0 { if n < 0 {
return 0, protowire.ParseError(n) return 0, errDecode
} }
list.Append(protoreflect.ValueOfInt64(int64(v))) list.Append(protoreflect.ValueOfInt64(int64(v)))
return n, nil return n, nil
@ -497,12 +497,12 @@ func (o UnmarshalOptions) unmarshalList(b []byte, wtyp protowire.Type, list prot
if wtyp == protowire.BytesType { if wtyp == protowire.BytesType {
buf, n := protowire.ConsumeBytes(b) buf, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return 0, protowire.ParseError(n) return 0, errDecode
} }
for len(buf) > 0 { for len(buf) > 0 {
v, n := protowire.ConsumeFixed64(buf) v, n := protowire.ConsumeFixed64(buf)
if n < 0 { if n < 0 {
return 0, protowire.ParseError(n) return 0, errDecode
} }
buf = buf[n:] buf = buf[n:]
list.Append(protoreflect.ValueOfUint64(v)) list.Append(protoreflect.ValueOfUint64(v))
@ -514,7 +514,7 @@ func (o UnmarshalOptions) unmarshalList(b []byte, wtyp protowire.Type, list prot
} }
v, n := protowire.ConsumeFixed64(b) v, n := protowire.ConsumeFixed64(b)
if n < 0 { if n < 0 {
return 0, protowire.ParseError(n) return 0, errDecode
} }
list.Append(protoreflect.ValueOfUint64(v)) list.Append(protoreflect.ValueOfUint64(v))
return n, nil return n, nil
@ -522,12 +522,12 @@ func (o UnmarshalOptions) unmarshalList(b []byte, wtyp protowire.Type, list prot
if wtyp == protowire.BytesType { if wtyp == protowire.BytesType {
buf, n := protowire.ConsumeBytes(b) buf, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return 0, protowire.ParseError(n) return 0, errDecode
} }
for len(buf) > 0 { for len(buf) > 0 {
v, n := protowire.ConsumeFixed64(buf) v, n := protowire.ConsumeFixed64(buf)
if n < 0 { if n < 0 {
return 0, protowire.ParseError(n) return 0, errDecode
} }
buf = buf[n:] buf = buf[n:]
list.Append(protoreflect.ValueOfFloat64(math.Float64frombits(v))) list.Append(protoreflect.ValueOfFloat64(math.Float64frombits(v)))
@ -539,7 +539,7 @@ func (o UnmarshalOptions) unmarshalList(b []byte, wtyp protowire.Type, list prot
} }
v, n := protowire.ConsumeFixed64(b) v, n := protowire.ConsumeFixed64(b)
if n < 0 { if n < 0 {
return 0, protowire.ParseError(n) return 0, errDecode
} }
list.Append(protoreflect.ValueOfFloat64(math.Float64frombits(v))) list.Append(protoreflect.ValueOfFloat64(math.Float64frombits(v)))
return n, nil return n, nil
@ -549,7 +549,7 @@ func (o UnmarshalOptions) unmarshalList(b []byte, wtyp protowire.Type, list prot
} }
v, n := protowire.ConsumeBytes(b) v, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return 0, protowire.ParseError(n) return 0, errDecode
} }
if strs.EnforceUTF8(fd) && !utf8.Valid(v) { if strs.EnforceUTF8(fd) && !utf8.Valid(v) {
return 0, errors.InvalidUTF8(string(fd.FullName())) return 0, errors.InvalidUTF8(string(fd.FullName()))
@ -562,7 +562,7 @@ func (o UnmarshalOptions) unmarshalList(b []byte, wtyp protowire.Type, list prot
} }
v, n := protowire.ConsumeBytes(b) v, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return 0, protowire.ParseError(n) return 0, errDecode
} }
list.Append(protoreflect.ValueOfBytes(append(emptyBuf[:], v...))) list.Append(protoreflect.ValueOfBytes(append(emptyBuf[:], v...)))
return n, nil return n, nil
@ -572,7 +572,7 @@ func (o UnmarshalOptions) unmarshalList(b []byte, wtyp protowire.Type, list prot
} }
v, n := protowire.ConsumeBytes(b) v, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return 0, protowire.ParseError(n) return 0, errDecode
} }
m := list.NewElement() m := list.NewElement()
if err := o.unmarshalMessage(v, m.Message()); err != nil { if err := o.unmarshalMessage(v, m.Message()); err != nil {
@ -586,7 +586,7 @@ func (o UnmarshalOptions) unmarshalList(b []byte, wtyp protowire.Type, list prot
} }
v, n := protowire.ConsumeGroup(fd.Number(), b) v, n := protowire.ConsumeGroup(fd.Number(), b)
if n < 0 { if n < 0 {
return 0, protowire.ParseError(n) return 0, errDecode
} }
m := list.NewElement() m := list.NewElement()
if err := o.unmarshalMessage(v, m.Message()); err != nil { if err := o.unmarshalMessage(v, m.Message()); err != nil {

View File

@ -5,12 +5,9 @@
package proto package proto
import ( import (
"sort"
"google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/encoding/protowire"
"google.golang.org/protobuf/internal/encoding/messageset" "google.golang.org/protobuf/internal/encoding/messageset"
"google.golang.org/protobuf/internal/fieldsort" "google.golang.org/protobuf/internal/order"
"google.golang.org/protobuf/internal/mapsort"
"google.golang.org/protobuf/internal/pragma" "google.golang.org/protobuf/internal/pragma"
"google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/runtime/protoiface" "google.golang.org/protobuf/runtime/protoiface"
@ -134,6 +131,9 @@ func (o MarshalOptions) MarshalState(in protoiface.MarshalInput) (protoiface.Mar
return o.marshal(in.Buf, in.Message) return o.marshal(in.Buf, in.Message)
} }
// marshal is a centralized function that all marshal operations go through.
// For profiling purposes, avoid changing the name of this function or
// introducing other code paths for marshal that do not go through this.
func (o MarshalOptions) marshal(b []byte, m protoreflect.Message) (out protoiface.MarshalOutput, err error) { func (o MarshalOptions) marshal(b []byte, m protoreflect.Message) (out protoiface.MarshalOutput, err error) {
allowPartial := o.AllowPartial allowPartial := o.AllowPartial
o.AllowPartial = true o.AllowPartial = true
@ -206,16 +206,17 @@ func growcap(oldcap, wantcap int) (newcap int) {
func (o MarshalOptions) marshalMessageSlow(b []byte, m protoreflect.Message) ([]byte, error) { func (o MarshalOptions) marshalMessageSlow(b []byte, m protoreflect.Message) ([]byte, error) {
if messageset.IsMessageSet(m.Descriptor()) { if messageset.IsMessageSet(m.Descriptor()) {
return marshalMessageSet(b, m, o) return o.marshalMessageSet(b, m)
}
fieldOrder := order.AnyFieldOrder
if o.Deterministic {
// TODO: This should use a more natural ordering like NumberFieldOrder,
// but doing so breaks golden tests that make invalid assumption about
// output stability of this implementation.
fieldOrder = order.LegacyFieldOrder
} }
// There are many choices for what order we visit fields in. The default one here
// is chosen for reasonable efficiency and simplicity given the protoreflect API.
// It is not deterministic, since Message.Range does not return fields in any
// defined order.
//
// When using deterministic serialization, we sort the known fields.
var err error var err error
o.rangeFields(m, func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool { order.RangeFields(m, fieldOrder, func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {
b, err = o.marshalField(b, fd, v) b, err = o.marshalField(b, fd, v)
return err == nil return err == nil
}) })
@ -226,27 +227,6 @@ func (o MarshalOptions) marshalMessageSlow(b []byte, m protoreflect.Message) ([]
return b, nil return b, nil
} }
// rangeFields visits fields in a defined order when deterministic serialization is enabled.
func (o MarshalOptions) rangeFields(m protoreflect.Message, f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) {
if !o.Deterministic {
m.Range(f)
return
}
var fds []protoreflect.FieldDescriptor
m.Range(func(fd protoreflect.FieldDescriptor, _ protoreflect.Value) bool {
fds = append(fds, fd)
return true
})
sort.Slice(fds, func(a, b int) bool {
return fieldsort.Less(fds[a], fds[b])
})
for _, fd := range fds {
if !f(fd, m.Get(fd)) {
break
}
}
}
func (o MarshalOptions) marshalField(b []byte, fd protoreflect.FieldDescriptor, value protoreflect.Value) ([]byte, error) { func (o MarshalOptions) marshalField(b []byte, fd protoreflect.FieldDescriptor, value protoreflect.Value) ([]byte, error) {
switch { switch {
case fd.IsList(): case fd.IsList():
@ -289,8 +269,12 @@ func (o MarshalOptions) marshalList(b []byte, fd protoreflect.FieldDescriptor, l
func (o MarshalOptions) marshalMap(b []byte, fd protoreflect.FieldDescriptor, mapv protoreflect.Map) ([]byte, error) { func (o MarshalOptions) marshalMap(b []byte, fd protoreflect.FieldDescriptor, mapv protoreflect.Map) ([]byte, error) {
keyf := fd.MapKey() keyf := fd.MapKey()
valf := fd.MapValue() valf := fd.MapValue()
keyOrder := order.AnyKeyOrder
if o.Deterministic {
keyOrder = order.GenericKeyOrder
}
var err error var err error
o.rangeMap(mapv, keyf.Kind(), func(key protoreflect.MapKey, value protoreflect.Value) bool { order.RangeEntries(mapv, keyOrder, func(key protoreflect.MapKey, value protoreflect.Value) bool {
b = protowire.AppendTag(b, fd.Number(), protowire.BytesType) b = protowire.AppendTag(b, fd.Number(), protowire.BytesType)
var pos int var pos int
b, pos = appendSpeculativeLength(b) b, pos = appendSpeculativeLength(b)
@ -309,14 +293,6 @@ func (o MarshalOptions) marshalMap(b []byte, fd protoreflect.FieldDescriptor, ma
return b, err return b, err
} }
func (o MarshalOptions) rangeMap(mapv protoreflect.Map, kind protoreflect.Kind, f func(protoreflect.MapKey, protoreflect.Value) bool) {
if !o.Deterministic {
mapv.Range(f)
return
}
mapsort.Range(mapv, kind, f)
}
// When encoding length-prefixed fields, we speculatively set aside some number of bytes // When encoding length-prefixed fields, we speculatively set aside some number of bytes
// for the length, encode the data, and then encode the length (shifting the data if necessary // for the length, encode the data, and then encode the length (shifting the data if necessary
// to make room). // to make room).

View File

@ -111,18 +111,31 @@ func equalList(fd pref.FieldDescriptor, x, y pref.List) bool {
// equalValue compares two singular values. // equalValue compares two singular values.
func equalValue(fd pref.FieldDescriptor, x, y pref.Value) bool { func equalValue(fd pref.FieldDescriptor, x, y pref.Value) bool {
switch { switch fd.Kind() {
case fd.Message() != nil: case pref.BoolKind:
return equalMessage(x.Message(), y.Message()) return x.Bool() == y.Bool()
case fd.Kind() == pref.BytesKind: case pref.EnumKind:
return bytes.Equal(x.Bytes(), y.Bytes()) return x.Enum() == y.Enum()
case fd.Kind() == pref.FloatKind, fd.Kind() == pref.DoubleKind: case pref.Int32Kind, pref.Sint32Kind,
pref.Int64Kind, pref.Sint64Kind,
pref.Sfixed32Kind, pref.Sfixed64Kind:
return x.Int() == y.Int()
case pref.Uint32Kind, pref.Uint64Kind,
pref.Fixed32Kind, pref.Fixed64Kind:
return x.Uint() == y.Uint()
case pref.FloatKind, pref.DoubleKind:
fx := x.Float() fx := x.Float()
fy := y.Float() fy := y.Float()
if math.IsNaN(fx) || math.IsNaN(fy) { if math.IsNaN(fx) || math.IsNaN(fy) {
return math.IsNaN(fx) && math.IsNaN(fy) return math.IsNaN(fx) && math.IsNaN(fy)
} }
return fx == fy return fx == fy
case pref.StringKind:
return x.String() == y.String()
case pref.BytesKind:
return bytes.Equal(x.Bytes(), y.Bytes())
case pref.MessageKind, pref.GroupKind:
return equalMessage(x.Message(), y.Message())
default: default:
return x.Interface() == y.Interface() return x.Interface() == y.Interface()
} }

View File

@ -9,28 +9,33 @@ import (
"google.golang.org/protobuf/internal/encoding/messageset" "google.golang.org/protobuf/internal/encoding/messageset"
"google.golang.org/protobuf/internal/errors" "google.golang.org/protobuf/internal/errors"
"google.golang.org/protobuf/internal/flags" "google.golang.org/protobuf/internal/flags"
"google.golang.org/protobuf/internal/order"
"google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/reflect/protoregistry" "google.golang.org/protobuf/reflect/protoregistry"
) )
func sizeMessageSet(m protoreflect.Message) (size int) { func (o MarshalOptions) sizeMessageSet(m protoreflect.Message) (size int) {
m.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool { m.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {
size += messageset.SizeField(fd.Number()) size += messageset.SizeField(fd.Number())
size += protowire.SizeTag(messageset.FieldMessage) size += protowire.SizeTag(messageset.FieldMessage)
size += protowire.SizeBytes(sizeMessage(v.Message())) size += protowire.SizeBytes(o.size(v.Message()))
return true return true
}) })
size += messageset.SizeUnknown(m.GetUnknown()) size += messageset.SizeUnknown(m.GetUnknown())
return size return size
} }
func marshalMessageSet(b []byte, m protoreflect.Message, o MarshalOptions) ([]byte, error) { func (o MarshalOptions) marshalMessageSet(b []byte, m protoreflect.Message) ([]byte, error) {
if !flags.ProtoLegacy { if !flags.ProtoLegacy {
return b, errors.New("no support for message_set_wire_format") return b, errors.New("no support for message_set_wire_format")
} }
fieldOrder := order.AnyFieldOrder
if o.Deterministic {
fieldOrder = order.NumberFieldOrder
}
var err error var err error
o.rangeFields(m, func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool { order.RangeFields(m, fieldOrder, func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {
b, err = marshalMessageSetField(b, fd, v, o) b, err = o.marshalMessageSetField(b, fd, v)
return err == nil return err == nil
}) })
if err != nil { if err != nil {
@ -39,7 +44,7 @@ func marshalMessageSet(b []byte, m protoreflect.Message, o MarshalOptions) ([]by
return messageset.AppendUnknown(b, m.GetUnknown()) return messageset.AppendUnknown(b, m.GetUnknown())
} }
func marshalMessageSetField(b []byte, fd protoreflect.FieldDescriptor, value protoreflect.Value, o MarshalOptions) ([]byte, error) { func (o MarshalOptions) marshalMessageSetField(b []byte, fd protoreflect.FieldDescriptor, value protoreflect.Value) ([]byte, error) {
b = messageset.AppendFieldStart(b, fd.Number()) b = messageset.AppendFieldStart(b, fd.Number())
b = protowire.AppendTag(b, messageset.FieldMessage, protowire.BytesType) b = protowire.AppendTag(b, messageset.FieldMessage, protowire.BytesType)
b = protowire.AppendVarint(b, uint64(o.Size(value.Message().Interface()))) b = protowire.AppendVarint(b, uint64(o.Size(value.Message().Interface())))
@ -51,12 +56,12 @@ func marshalMessageSetField(b []byte, fd protoreflect.FieldDescriptor, value pro
return b, nil return b, nil
} }
func unmarshalMessageSet(b []byte, m protoreflect.Message, o UnmarshalOptions) error { func (o UnmarshalOptions) unmarshalMessageSet(b []byte, m protoreflect.Message) error {
if !flags.ProtoLegacy { if !flags.ProtoLegacy {
return errors.New("no support for message_set_wire_format") return errors.New("no support for message_set_wire_format")
} }
return messageset.Unmarshal(b, false, func(num protowire.Number, v []byte) error { return messageset.Unmarshal(b, false, func(num protowire.Number, v []byte) error {
err := unmarshalMessageSetField(m, num, v, o) err := o.unmarshalMessageSetField(m, num, v)
if err == errUnknown { if err == errUnknown {
unknown := m.GetUnknown() unknown := m.GetUnknown()
unknown = protowire.AppendTag(unknown, num, protowire.BytesType) unknown = protowire.AppendTag(unknown, num, protowire.BytesType)
@ -68,7 +73,7 @@ func unmarshalMessageSet(b []byte, m protoreflect.Message, o UnmarshalOptions) e
}) })
} }
func unmarshalMessageSetField(m protoreflect.Message, num protowire.Number, v []byte, o UnmarshalOptions) error { func (o UnmarshalOptions) unmarshalMessageSetField(m protoreflect.Message, num protowire.Number, v []byte) error {
md := m.Descriptor() md := m.Descriptor()
if !md.ExtensionRanges().Has(num) { if !md.ExtensionRanges().Has(num) {
return errUnknown return errUnknown

View File

@ -32,3 +32,12 @@ var Error error
func init() { func init() {
Error = errors.Error Error = errors.Error
} }
// MessageName returns the full name of m.
// If m is nil, it returns an empty string.
func MessageName(m Message) protoreflect.FullName {
if m == nil {
return ""
}
return m.ProtoReflect().Descriptor().FullName()
}

View File

@ -23,10 +23,13 @@ func (o MarshalOptions) Size(m Message) int {
return 0 return 0
} }
return sizeMessage(m.ProtoReflect()) return o.size(m.ProtoReflect())
} }
func sizeMessage(m protoreflect.Message) (size int) { // size is a centralized function that all size operations go through.
// For profiling purposes, avoid changing the name of this function or
// introducing other code paths for size that do not go through this.
func (o MarshalOptions) size(m protoreflect.Message) (size int) {
methods := protoMethods(m) methods := protoMethods(m)
if methods != nil && methods.Size != nil { if methods != nil && methods.Size != nil {
out := methods.Size(protoiface.SizeInput{ out := methods.Size(protoiface.SizeInput{
@ -42,52 +45,52 @@ func sizeMessage(m protoreflect.Message) (size int) {
}) })
return len(out.Buf) return len(out.Buf)
} }
return sizeMessageSlow(m) return o.sizeMessageSlow(m)
} }
func sizeMessageSlow(m protoreflect.Message) (size int) { func (o MarshalOptions) sizeMessageSlow(m protoreflect.Message) (size int) {
if messageset.IsMessageSet(m.Descriptor()) { if messageset.IsMessageSet(m.Descriptor()) {
return sizeMessageSet(m) return o.sizeMessageSet(m)
} }
m.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool { m.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {
size += sizeField(fd, v) size += o.sizeField(fd, v)
return true return true
}) })
size += len(m.GetUnknown()) size += len(m.GetUnknown())
return size return size
} }
func sizeField(fd protoreflect.FieldDescriptor, value protoreflect.Value) (size int) { func (o MarshalOptions) sizeField(fd protoreflect.FieldDescriptor, value protoreflect.Value) (size int) {
num := fd.Number() num := fd.Number()
switch { switch {
case fd.IsList(): case fd.IsList():
return sizeList(num, fd, value.List()) return o.sizeList(num, fd, value.List())
case fd.IsMap(): case fd.IsMap():
return sizeMap(num, fd, value.Map()) return o.sizeMap(num, fd, value.Map())
default: default:
return protowire.SizeTag(num) + sizeSingular(num, fd.Kind(), value) return protowire.SizeTag(num) + o.sizeSingular(num, fd.Kind(), value)
} }
} }
func sizeList(num protowire.Number, fd protoreflect.FieldDescriptor, list protoreflect.List) (size int) { func (o MarshalOptions) sizeList(num protowire.Number, fd protoreflect.FieldDescriptor, list protoreflect.List) (size int) {
if fd.IsPacked() && list.Len() > 0 { if fd.IsPacked() && list.Len() > 0 {
content := 0 content := 0
for i, llen := 0, list.Len(); i < llen; i++ { for i, llen := 0, list.Len(); i < llen; i++ {
content += sizeSingular(num, fd.Kind(), list.Get(i)) content += o.sizeSingular(num, fd.Kind(), list.Get(i))
} }
return protowire.SizeTag(num) + protowire.SizeBytes(content) return protowire.SizeTag(num) + protowire.SizeBytes(content)
} }
for i, llen := 0, list.Len(); i < llen; i++ { for i, llen := 0, list.Len(); i < llen; i++ {
size += protowire.SizeTag(num) + sizeSingular(num, fd.Kind(), list.Get(i)) size += protowire.SizeTag(num) + o.sizeSingular(num, fd.Kind(), list.Get(i))
} }
return size return size
} }
func sizeMap(num protowire.Number, fd protoreflect.FieldDescriptor, mapv protoreflect.Map) (size int) { func (o MarshalOptions) sizeMap(num protowire.Number, fd protoreflect.FieldDescriptor, mapv protoreflect.Map) (size int) {
mapv.Range(func(key protoreflect.MapKey, value protoreflect.Value) bool { mapv.Range(func(key protoreflect.MapKey, value protoreflect.Value) bool {
size += protowire.SizeTag(num) size += protowire.SizeTag(num)
size += protowire.SizeBytes(sizeField(fd.MapKey(), key.Value()) + sizeField(fd.MapValue(), value)) size += protowire.SizeBytes(o.sizeField(fd.MapKey(), key.Value()) + o.sizeField(fd.MapValue(), value))
return true return true
}) })
return size return size

View File

@ -11,7 +11,7 @@ import (
"google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/reflect/protoreflect"
) )
func sizeSingular(num protowire.Number, kind protoreflect.Kind, v protoreflect.Value) int { func (o MarshalOptions) sizeSingular(num protowire.Number, kind protoreflect.Kind, v protoreflect.Value) int {
switch kind { switch kind {
case protoreflect.BoolKind: case protoreflect.BoolKind:
return protowire.SizeVarint(protowire.EncodeBool(v.Bool())) return protowire.SizeVarint(protowire.EncodeBool(v.Bool()))
@ -46,9 +46,9 @@ func sizeSingular(num protowire.Number, kind protoreflect.Kind, v protoreflect.V
case protoreflect.BytesKind: case protoreflect.BytesKind:
return protowire.SizeBytes(len(v.Bytes())) return protowire.SizeBytes(len(v.Bytes()))
case protoreflect.MessageKind: case protoreflect.MessageKind:
return protowire.SizeBytes(sizeMessage(v.Message())) return protowire.SizeBytes(o.size(v.Message()))
case protoreflect.GroupKind: case protoreflect.GroupKind:
return protowire.SizeGroup(num, sizeMessage(v.Message())) return protowire.SizeGroup(num, o.size(v.Message()))
default: default:
return 0 return 0
} }

View File

@ -0,0 +1,276 @@
// 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 protodesc provides functionality for converting
// FileDescriptorProto messages to/from protoreflect.FileDescriptor values.
//
// The google.protobuf.FileDescriptorProto is a protobuf message that describes
// the type information for a .proto file in a form that is easily serializable.
// The protoreflect.FileDescriptor is a more structured representation of
// the FileDescriptorProto message where references and remote dependencies
// can be directly followed.
package protodesc
import (
"google.golang.org/protobuf/internal/errors"
"google.golang.org/protobuf/internal/filedesc"
"google.golang.org/protobuf/internal/pragma"
"google.golang.org/protobuf/internal/strs"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/reflect/protoregistry"
"google.golang.org/protobuf/types/descriptorpb"
)
// Resolver is the resolver used by NewFile to resolve dependencies.
// The enums and messages provided must belong to some parent file,
// which is also registered.
//
// It is implemented by protoregistry.Files.
type Resolver interface {
FindFileByPath(string) (protoreflect.FileDescriptor, error)
FindDescriptorByName(protoreflect.FullName) (protoreflect.Descriptor, error)
}
// FileOptions configures the construction of file descriptors.
type FileOptions struct {
pragma.NoUnkeyedLiterals
// AllowUnresolvable configures New to permissively allow unresolvable
// file, enum, or message dependencies. Unresolved dependencies are replaced
// by placeholder equivalents.
//
// The following dependencies may be left unresolved:
// • Resolving an imported file.
// • Resolving the type for a message field or extension field.
// If the kind of the field is unknown, then a placeholder is used for both
// the Enum and Message accessors on the protoreflect.FieldDescriptor.
// • Resolving an enum value set as the default for an optional enum field.
// If unresolvable, the protoreflect.FieldDescriptor.Default is set to the
// first value in the associated enum (or zero if the also enum dependency
// is also unresolvable). The protoreflect.FieldDescriptor.DefaultEnumValue
// is populated with a placeholder.
// • Resolving the extended message type for an extension field.
// • Resolving the input or output message type for a service method.
//
// If the unresolved dependency uses a relative name,
// then the placeholder will contain an invalid FullName with a "*." prefix,
// indicating that the starting prefix of the full name is unknown.
AllowUnresolvable bool
}
// NewFile creates a new protoreflect.FileDescriptor from the provided
// file descriptor message. See FileOptions.New for more information.
func NewFile(fd *descriptorpb.FileDescriptorProto, r Resolver) (protoreflect.FileDescriptor, error) {
return FileOptions{}.New(fd, r)
}
// NewFiles creates a new protoregistry.Files from the provided
// FileDescriptorSet message. See FileOptions.NewFiles for more information.
func NewFiles(fd *descriptorpb.FileDescriptorSet) (*protoregistry.Files, error) {
return FileOptions{}.NewFiles(fd)
}
// New creates a new protoreflect.FileDescriptor from the provided
// file descriptor message. The file must represent a valid proto file according
// to protobuf semantics. The returned descriptor is a deep copy of the input.
//
// Any imported files, enum types, or message types referenced in the file are
// resolved using the provided registry. When looking up an import file path,
// the path must be unique. The newly created file descriptor is not registered
// back into the provided file registry.
func (o FileOptions) New(fd *descriptorpb.FileDescriptorProto, r Resolver) (protoreflect.FileDescriptor, error) {
if r == nil {
r = (*protoregistry.Files)(nil) // empty resolver
}
// Handle the file descriptor content.
f := &filedesc.File{L2: &filedesc.FileL2{}}
switch fd.GetSyntax() {
case "proto2", "":
f.L1.Syntax = protoreflect.Proto2
case "proto3":
f.L1.Syntax = protoreflect.Proto3
default:
return nil, errors.New("invalid syntax: %q", fd.GetSyntax())
}
f.L1.Path = fd.GetName()
if f.L1.Path == "" {
return nil, errors.New("file path must be populated")
}
f.L1.Package = protoreflect.FullName(fd.GetPackage())
if !f.L1.Package.IsValid() && f.L1.Package != "" {
return nil, errors.New("invalid package: %q", f.L1.Package)
}
if opts := fd.GetOptions(); opts != nil {
opts = proto.Clone(opts).(*descriptorpb.FileOptions)
f.L2.Options = func() protoreflect.ProtoMessage { return opts }
}
f.L2.Imports = make(filedesc.FileImports, len(fd.GetDependency()))
for _, i := range fd.GetPublicDependency() {
if !(0 <= i && int(i) < len(f.L2.Imports)) || f.L2.Imports[i].IsPublic {
return nil, errors.New("invalid or duplicate public import index: %d", i)
}
f.L2.Imports[i].IsPublic = true
}
for _, i := range fd.GetWeakDependency() {
if !(0 <= i && int(i) < len(f.L2.Imports)) || f.L2.Imports[i].IsWeak {
return nil, errors.New("invalid or duplicate weak import index: %d", i)
}
f.L2.Imports[i].IsWeak = true
}
imps := importSet{f.Path(): true}
for i, path := range fd.GetDependency() {
imp := &f.L2.Imports[i]
f, err := r.FindFileByPath(path)
if err == protoregistry.NotFound && (o.AllowUnresolvable || imp.IsWeak) {
f = filedesc.PlaceholderFile(path)
} else if err != nil {
return nil, errors.New("could not resolve import %q: %v", path, err)
}
imp.FileDescriptor = f
if imps[imp.Path()] {
return nil, errors.New("already imported %q", path)
}
imps[imp.Path()] = true
}
for i := range fd.GetDependency() {
imp := &f.L2.Imports[i]
imps.importPublic(imp.Imports())
}
// Handle source locations.
f.L2.Locations.File = f
for _, loc := range fd.GetSourceCodeInfo().GetLocation() {
var l protoreflect.SourceLocation
// TODO: Validate that the path points to an actual declaration?
l.Path = protoreflect.SourcePath(loc.GetPath())
s := loc.GetSpan()
switch len(s) {
case 3:
l.StartLine, l.StartColumn, l.EndLine, l.EndColumn = int(s[0]), int(s[1]), int(s[0]), int(s[2])
case 4:
l.StartLine, l.StartColumn, l.EndLine, l.EndColumn = int(s[0]), int(s[1]), int(s[2]), int(s[3])
default:
return nil, errors.New("invalid span: %v", s)
}
// TODO: Validate that the span information is sensible?
// See https://github.com/protocolbuffers/protobuf/issues/6378.
if false && (l.EndLine < l.StartLine || l.StartLine < 0 || l.StartColumn < 0 || l.EndColumn < 0 ||
(l.StartLine == l.EndLine && l.EndColumn <= l.StartColumn)) {
return nil, errors.New("invalid span: %v", s)
}
l.LeadingDetachedComments = loc.GetLeadingDetachedComments()
l.LeadingComments = loc.GetLeadingComments()
l.TrailingComments = loc.GetTrailingComments()
f.L2.Locations.List = append(f.L2.Locations.List, l)
}
// Step 1: Allocate and derive the names for all declarations.
// This copies all fields from the descriptor proto except:
// google.protobuf.FieldDescriptorProto.type_name
// google.protobuf.FieldDescriptorProto.default_value
// google.protobuf.FieldDescriptorProto.oneof_index
// google.protobuf.FieldDescriptorProto.extendee
// google.protobuf.MethodDescriptorProto.input
// google.protobuf.MethodDescriptorProto.output
var err error
sb := new(strs.Builder)
r1 := make(descsByName)
if f.L1.Enums.List, err = r1.initEnumDeclarations(fd.GetEnumType(), f, sb); err != nil {
return nil, err
}
if f.L1.Messages.List, err = r1.initMessagesDeclarations(fd.GetMessageType(), f, sb); err != nil {
return nil, err
}
if f.L1.Extensions.List, err = r1.initExtensionDeclarations(fd.GetExtension(), f, sb); err != nil {
return nil, err
}
if f.L1.Services.List, err = r1.initServiceDeclarations(fd.GetService(), f, sb); err != nil {
return nil, err
}
// Step 2: Resolve every dependency reference not handled by step 1.
r2 := &resolver{local: r1, remote: r, imports: imps, allowUnresolvable: o.AllowUnresolvable}
if err := r2.resolveMessageDependencies(f.L1.Messages.List, fd.GetMessageType()); err != nil {
return nil, err
}
if err := r2.resolveExtensionDependencies(f.L1.Extensions.List, fd.GetExtension()); err != nil {
return nil, err
}
if err := r2.resolveServiceDependencies(f.L1.Services.List, fd.GetService()); err != nil {
return nil, err
}
// Step 3: Validate every enum, message, and extension declaration.
if err := validateEnumDeclarations(f.L1.Enums.List, fd.GetEnumType()); err != nil {
return nil, err
}
if err := validateMessageDeclarations(f.L1.Messages.List, fd.GetMessageType()); err != nil {
return nil, err
}
if err := validateExtensionDeclarations(f.L1.Extensions.List, fd.GetExtension()); err != nil {
return nil, err
}
return f, nil
}
type importSet map[string]bool
func (is importSet) importPublic(imps protoreflect.FileImports) {
for i := 0; i < imps.Len(); i++ {
if imp := imps.Get(i); imp.IsPublic {
is[imp.Path()] = true
is.importPublic(imp.Imports())
}
}
}
// NewFiles creates a new protoregistry.Files from the provided
// FileDescriptorSet message. The descriptor set must include only
// valid files according to protobuf semantics. The returned descriptors
// are a deep copy of the input.
func (o FileOptions) NewFiles(fds *descriptorpb.FileDescriptorSet) (*protoregistry.Files, error) {
files := make(map[string]*descriptorpb.FileDescriptorProto)
for _, fd := range fds.File {
if _, ok := files[fd.GetName()]; ok {
return nil, errors.New("file appears multiple times: %q", fd.GetName())
}
files[fd.GetName()] = fd
}
r := &protoregistry.Files{}
for _, fd := range files {
if err := o.addFileDeps(r, fd, files); err != nil {
return nil, err
}
}
return r, nil
}
func (o FileOptions) addFileDeps(r *protoregistry.Files, fd *descriptorpb.FileDescriptorProto, files map[string]*descriptorpb.FileDescriptorProto) error {
// Set the entry to nil while descending into a file's dependencies to detect cycles.
files[fd.GetName()] = nil
for _, dep := range fd.Dependency {
depfd, ok := files[dep]
if depfd == nil {
if ok {
return errors.New("import cycle in file: %q", dep)
}
continue
}
if err := o.addFileDeps(r, depfd, files); err != nil {
return err
}
}
// Delete the entry once dependencies are processed.
delete(files, fd.GetName())
f, err := o.New(fd, r)
if err != nil {
return err
}
return r.RegisterFile(f)
}

View File

@ -0,0 +1,248 @@
// 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 protodesc
import (
"google.golang.org/protobuf/internal/errors"
"google.golang.org/protobuf/internal/filedesc"
"google.golang.org/protobuf/internal/strs"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/types/descriptorpb"
)
type descsByName map[protoreflect.FullName]protoreflect.Descriptor
func (r descsByName) initEnumDeclarations(eds []*descriptorpb.EnumDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (es []filedesc.Enum, err error) {
es = make([]filedesc.Enum, len(eds)) // allocate up-front to ensure stable pointers
for i, ed := range eds {
e := &es[i]
e.L2 = new(filedesc.EnumL2)
if e.L0, err = r.makeBase(e, parent, ed.GetName(), i, sb); err != nil {
return nil, err
}
if opts := ed.GetOptions(); opts != nil {
opts = proto.Clone(opts).(*descriptorpb.EnumOptions)
e.L2.Options = func() protoreflect.ProtoMessage { return opts }
}
for _, s := range ed.GetReservedName() {
e.L2.ReservedNames.List = append(e.L2.ReservedNames.List, protoreflect.Name(s))
}
for _, rr := range ed.GetReservedRange() {
e.L2.ReservedRanges.List = append(e.L2.ReservedRanges.List, [2]protoreflect.EnumNumber{
protoreflect.EnumNumber(rr.GetStart()),
protoreflect.EnumNumber(rr.GetEnd()),
})
}
if e.L2.Values.List, err = r.initEnumValuesFromDescriptorProto(ed.GetValue(), e, sb); err != nil {
return nil, err
}
}
return es, nil
}
func (r descsByName) initEnumValuesFromDescriptorProto(vds []*descriptorpb.EnumValueDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (vs []filedesc.EnumValue, err error) {
vs = make([]filedesc.EnumValue, len(vds)) // allocate up-front to ensure stable pointers
for i, vd := range vds {
v := &vs[i]
if v.L0, err = r.makeBase(v, parent, vd.GetName(), i, sb); err != nil {
return nil, err
}
if opts := vd.GetOptions(); opts != nil {
opts = proto.Clone(opts).(*descriptorpb.EnumValueOptions)
v.L1.Options = func() protoreflect.ProtoMessage { return opts }
}
v.L1.Number = protoreflect.EnumNumber(vd.GetNumber())
}
return vs, nil
}
func (r descsByName) initMessagesDeclarations(mds []*descriptorpb.DescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (ms []filedesc.Message, err error) {
ms = make([]filedesc.Message, len(mds)) // allocate up-front to ensure stable pointers
for i, md := range mds {
m := &ms[i]
m.L2 = new(filedesc.MessageL2)
if m.L0, err = r.makeBase(m, parent, md.GetName(), i, sb); err != nil {
return nil, err
}
if opts := md.GetOptions(); opts != nil {
opts = proto.Clone(opts).(*descriptorpb.MessageOptions)
m.L2.Options = func() protoreflect.ProtoMessage { return opts }
m.L1.IsMapEntry = opts.GetMapEntry()
m.L1.IsMessageSet = opts.GetMessageSetWireFormat()
}
for _, s := range md.GetReservedName() {
m.L2.ReservedNames.List = append(m.L2.ReservedNames.List, protoreflect.Name(s))
}
for _, rr := range md.GetReservedRange() {
m.L2.ReservedRanges.List = append(m.L2.ReservedRanges.List, [2]protoreflect.FieldNumber{
protoreflect.FieldNumber(rr.GetStart()),
protoreflect.FieldNumber(rr.GetEnd()),
})
}
for _, xr := range md.GetExtensionRange() {
m.L2.ExtensionRanges.List = append(m.L2.ExtensionRanges.List, [2]protoreflect.FieldNumber{
protoreflect.FieldNumber(xr.GetStart()),
protoreflect.FieldNumber(xr.GetEnd()),
})
var optsFunc func() protoreflect.ProtoMessage
if opts := xr.GetOptions(); opts != nil {
opts = proto.Clone(opts).(*descriptorpb.ExtensionRangeOptions)
optsFunc = func() protoreflect.ProtoMessage { return opts }
}
m.L2.ExtensionRangeOptions = append(m.L2.ExtensionRangeOptions, optsFunc)
}
if m.L2.Fields.List, err = r.initFieldsFromDescriptorProto(md.GetField(), m, sb); err != nil {
return nil, err
}
if m.L2.Oneofs.List, err = r.initOneofsFromDescriptorProto(md.GetOneofDecl(), m, sb); err != nil {
return nil, err
}
if m.L1.Enums.List, err = r.initEnumDeclarations(md.GetEnumType(), m, sb); err != nil {
return nil, err
}
if m.L1.Messages.List, err = r.initMessagesDeclarations(md.GetNestedType(), m, sb); err != nil {
return nil, err
}
if m.L1.Extensions.List, err = r.initExtensionDeclarations(md.GetExtension(), m, sb); err != nil {
return nil, err
}
}
return ms, nil
}
func (r descsByName) initFieldsFromDescriptorProto(fds []*descriptorpb.FieldDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (fs []filedesc.Field, err error) {
fs = make([]filedesc.Field, len(fds)) // allocate up-front to ensure stable pointers
for i, fd := range fds {
f := &fs[i]
if f.L0, err = r.makeBase(f, parent, fd.GetName(), i, sb); err != nil {
return nil, err
}
f.L1.IsProto3Optional = fd.GetProto3Optional()
if opts := fd.GetOptions(); opts != nil {
opts = proto.Clone(opts).(*descriptorpb.FieldOptions)
f.L1.Options = func() protoreflect.ProtoMessage { return opts }
f.L1.IsWeak = opts.GetWeak()
f.L1.HasPacked = opts.Packed != nil
f.L1.IsPacked = opts.GetPacked()
}
f.L1.Number = protoreflect.FieldNumber(fd.GetNumber())
f.L1.Cardinality = protoreflect.Cardinality(fd.GetLabel())
if fd.Type != nil {
f.L1.Kind = protoreflect.Kind(fd.GetType())
}
if fd.JsonName != nil {
f.L1.StringName.InitJSON(fd.GetJsonName())
}
}
return fs, nil
}
func (r descsByName) initOneofsFromDescriptorProto(ods []*descriptorpb.OneofDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (os []filedesc.Oneof, err error) {
os = make([]filedesc.Oneof, len(ods)) // allocate up-front to ensure stable pointers
for i, od := range ods {
o := &os[i]
if o.L0, err = r.makeBase(o, parent, od.GetName(), i, sb); err != nil {
return nil, err
}
if opts := od.GetOptions(); opts != nil {
opts = proto.Clone(opts).(*descriptorpb.OneofOptions)
o.L1.Options = func() protoreflect.ProtoMessage { return opts }
}
}
return os, nil
}
func (r descsByName) initExtensionDeclarations(xds []*descriptorpb.FieldDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (xs []filedesc.Extension, err error) {
xs = make([]filedesc.Extension, len(xds)) // allocate up-front to ensure stable pointers
for i, xd := range xds {
x := &xs[i]
x.L2 = new(filedesc.ExtensionL2)
if x.L0, err = r.makeBase(x, parent, xd.GetName(), i, sb); err != nil {
return nil, err
}
if opts := xd.GetOptions(); opts != nil {
opts = proto.Clone(opts).(*descriptorpb.FieldOptions)
x.L2.Options = func() protoreflect.ProtoMessage { return opts }
x.L2.IsPacked = opts.GetPacked()
}
x.L1.Number = protoreflect.FieldNumber(xd.GetNumber())
x.L1.Cardinality = protoreflect.Cardinality(xd.GetLabel())
if xd.Type != nil {
x.L1.Kind = protoreflect.Kind(xd.GetType())
}
if xd.JsonName != nil {
x.L2.StringName.InitJSON(xd.GetJsonName())
}
}
return xs, nil
}
func (r descsByName) initServiceDeclarations(sds []*descriptorpb.ServiceDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (ss []filedesc.Service, err error) {
ss = make([]filedesc.Service, len(sds)) // allocate up-front to ensure stable pointers
for i, sd := range sds {
s := &ss[i]
s.L2 = new(filedesc.ServiceL2)
if s.L0, err = r.makeBase(s, parent, sd.GetName(), i, sb); err != nil {
return nil, err
}
if opts := sd.GetOptions(); opts != nil {
opts = proto.Clone(opts).(*descriptorpb.ServiceOptions)
s.L2.Options = func() protoreflect.ProtoMessage { return opts }
}
if s.L2.Methods.List, err = r.initMethodsFromDescriptorProto(sd.GetMethod(), s, sb); err != nil {
return nil, err
}
}
return ss, nil
}
func (r descsByName) initMethodsFromDescriptorProto(mds []*descriptorpb.MethodDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (ms []filedesc.Method, err error) {
ms = make([]filedesc.Method, len(mds)) // allocate up-front to ensure stable pointers
for i, md := range mds {
m := &ms[i]
if m.L0, err = r.makeBase(m, parent, md.GetName(), i, sb); err != nil {
return nil, err
}
if opts := md.GetOptions(); opts != nil {
opts = proto.Clone(opts).(*descriptorpb.MethodOptions)
m.L1.Options = func() protoreflect.ProtoMessage { return opts }
}
m.L1.IsStreamingClient = md.GetClientStreaming()
m.L1.IsStreamingServer = md.GetServerStreaming()
}
return ms, nil
}
func (r descsByName) makeBase(child, parent protoreflect.Descriptor, name string, idx int, sb *strs.Builder) (filedesc.BaseL0, error) {
if !protoreflect.Name(name).IsValid() {
return filedesc.BaseL0{}, errors.New("descriptor %q has an invalid nested name: %q", parent.FullName(), name)
}
// Derive the full name of the child.
// Note that enum values are a sibling to the enum parent in the namespace.
var fullName protoreflect.FullName
if _, ok := parent.(protoreflect.EnumDescriptor); ok {
fullName = sb.AppendFullName(parent.FullName().Parent(), protoreflect.Name(name))
} else {
fullName = sb.AppendFullName(parent.FullName(), protoreflect.Name(name))
}
if _, ok := r[fullName]; ok {
return filedesc.BaseL0{}, errors.New("descriptor %q already declared", fullName)
}
r[fullName] = child
// TODO: Verify that the full name does not already exist in the resolver?
// This is not as critical since most usages of NewFile will register
// the created file back into the registry, which will perform this check.
return filedesc.BaseL0{
FullName: fullName,
ParentFile: parent.ParentFile().(*filedesc.File),
Parent: parent,
Index: idx,
}, nil
}

View File

@ -0,0 +1,286 @@
// 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 protodesc
import (
"google.golang.org/protobuf/internal/encoding/defval"
"google.golang.org/protobuf/internal/errors"
"google.golang.org/protobuf/internal/filedesc"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/reflect/protoregistry"
"google.golang.org/protobuf/types/descriptorpb"
)
// resolver is a wrapper around a local registry of declarations within the file
// and the remote resolver. The remote resolver is restricted to only return
// descriptors that have been imported.
type resolver struct {
local descsByName
remote Resolver
imports importSet
allowUnresolvable bool
}
func (r *resolver) resolveMessageDependencies(ms []filedesc.Message, mds []*descriptorpb.DescriptorProto) (err error) {
for i, md := range mds {
m := &ms[i]
for j, fd := range md.GetField() {
f := &m.L2.Fields.List[j]
if f.L1.Cardinality == protoreflect.Required {
m.L2.RequiredNumbers.List = append(m.L2.RequiredNumbers.List, f.L1.Number)
}
if fd.OneofIndex != nil {
k := int(fd.GetOneofIndex())
if !(0 <= k && k < len(md.GetOneofDecl())) {
return errors.New("message field %q has an invalid oneof index: %d", f.FullName(), k)
}
o := &m.L2.Oneofs.List[k]
f.L1.ContainingOneof = o
o.L1.Fields.List = append(o.L1.Fields.List, f)
}
if f.L1.Kind, f.L1.Enum, f.L1.Message, err = r.findTarget(f.Kind(), f.Parent().FullName(), partialName(fd.GetTypeName()), f.IsWeak()); err != nil {
return errors.New("message field %q cannot resolve type: %v", f.FullName(), err)
}
if fd.DefaultValue != nil {
v, ev, err := unmarshalDefault(fd.GetDefaultValue(), f, r.allowUnresolvable)
if err != nil {
return errors.New("message field %q has invalid default: %v", f.FullName(), err)
}
f.L1.Default = filedesc.DefaultValue(v, ev)
}
}
if err := r.resolveMessageDependencies(m.L1.Messages.List, md.GetNestedType()); err != nil {
return err
}
if err := r.resolveExtensionDependencies(m.L1.Extensions.List, md.GetExtension()); err != nil {
return err
}
}
return nil
}
func (r *resolver) resolveExtensionDependencies(xs []filedesc.Extension, xds []*descriptorpb.FieldDescriptorProto) (err error) {
for i, xd := range xds {
x := &xs[i]
if x.L1.Extendee, err = r.findMessageDescriptor(x.Parent().FullName(), partialName(xd.GetExtendee()), false); err != nil {
return errors.New("extension field %q cannot resolve extendee: %v", x.FullName(), err)
}
if x.L1.Kind, x.L2.Enum, x.L2.Message, err = r.findTarget(x.Kind(), x.Parent().FullName(), partialName(xd.GetTypeName()), false); err != nil {
return errors.New("extension field %q cannot resolve type: %v", x.FullName(), err)
}
if xd.DefaultValue != nil {
v, ev, err := unmarshalDefault(xd.GetDefaultValue(), x, r.allowUnresolvable)
if err != nil {
return errors.New("extension field %q has invalid default: %v", x.FullName(), err)
}
x.L2.Default = filedesc.DefaultValue(v, ev)
}
}
return nil
}
func (r *resolver) resolveServiceDependencies(ss []filedesc.Service, sds []*descriptorpb.ServiceDescriptorProto) (err error) {
for i, sd := range sds {
s := &ss[i]
for j, md := range sd.GetMethod() {
m := &s.L2.Methods.List[j]
m.L1.Input, err = r.findMessageDescriptor(m.Parent().FullName(), partialName(md.GetInputType()), false)
if err != nil {
return errors.New("service method %q cannot resolve input: %v", m.FullName(), err)
}
m.L1.Output, err = r.findMessageDescriptor(s.FullName(), partialName(md.GetOutputType()), false)
if err != nil {
return errors.New("service method %q cannot resolve output: %v", m.FullName(), err)
}
}
}
return nil
}
// findTarget finds an enum or message descriptor if k is an enum, message,
// group, or unknown. If unknown, and the name could be resolved, the kind
// returned kind is set based on the type of the resolved descriptor.
func (r *resolver) findTarget(k protoreflect.Kind, scope protoreflect.FullName, ref partialName, isWeak bool) (protoreflect.Kind, protoreflect.EnumDescriptor, protoreflect.MessageDescriptor, error) {
switch k {
case protoreflect.EnumKind:
ed, err := r.findEnumDescriptor(scope, ref, isWeak)
if err != nil {
return 0, nil, nil, err
}
return k, ed, nil, nil
case protoreflect.MessageKind, protoreflect.GroupKind:
md, err := r.findMessageDescriptor(scope, ref, isWeak)
if err != nil {
return 0, nil, nil, err
}
return k, nil, md, nil
case 0:
// Handle unspecified kinds (possible with parsers that operate
// on a per-file basis without knowledge of dependencies).
d, err := r.findDescriptor(scope, ref)
if err == protoregistry.NotFound && (r.allowUnresolvable || isWeak) {
return k, filedesc.PlaceholderEnum(ref.FullName()), filedesc.PlaceholderMessage(ref.FullName()), nil
} else if err == protoregistry.NotFound {
return 0, nil, nil, errors.New("%q not found", ref.FullName())
} else if err != nil {
return 0, nil, nil, err
}
switch d := d.(type) {
case protoreflect.EnumDescriptor:
return protoreflect.EnumKind, d, nil, nil
case protoreflect.MessageDescriptor:
return protoreflect.MessageKind, nil, d, nil
default:
return 0, nil, nil, errors.New("unknown kind")
}
default:
if ref != "" {
return 0, nil, nil, errors.New("target name cannot be specified for %v", k)
}
if !k.IsValid() {
return 0, nil, nil, errors.New("invalid kind: %d", k)
}
return k, nil, nil, nil
}
}
// findDescriptor finds the descriptor by name,
// which may be a relative name within some scope.
//
// Suppose the scope was "fizz.buzz" and the reference was "Foo.Bar",
// then the following full names are searched:
// * fizz.buzz.Foo.Bar
// * fizz.Foo.Bar
// * Foo.Bar
func (r *resolver) findDescriptor(scope protoreflect.FullName, ref partialName) (protoreflect.Descriptor, error) {
if !ref.IsValid() {
return nil, errors.New("invalid name reference: %q", ref)
}
if ref.IsFull() {
scope, ref = "", ref[1:]
}
var foundButNotImported protoreflect.Descriptor
for {
// Derive the full name to search.
s := protoreflect.FullName(ref)
if scope != "" {
s = scope + "." + s
}
// Check the current file for the descriptor.
if d, ok := r.local[s]; ok {
return d, nil
}
// Check the remote registry for the descriptor.
d, err := r.remote.FindDescriptorByName(s)
if err == nil {
// Only allow descriptors covered by one of the imports.
if r.imports[d.ParentFile().Path()] {
return d, nil
}
foundButNotImported = d
} else if err != protoregistry.NotFound {
return nil, errors.Wrap(err, "%q", s)
}
// Continue on at a higher level of scoping.
if scope == "" {
if d := foundButNotImported; d != nil {
return nil, errors.New("resolved %q, but %q is not imported", d.FullName(), d.ParentFile().Path())
}
return nil, protoregistry.NotFound
}
scope = scope.Parent()
}
}
func (r *resolver) findEnumDescriptor(scope protoreflect.FullName, ref partialName, isWeak bool) (protoreflect.EnumDescriptor, error) {
d, err := r.findDescriptor(scope, ref)
if err == protoregistry.NotFound && (r.allowUnresolvable || isWeak) {
return filedesc.PlaceholderEnum(ref.FullName()), nil
} else if err == protoregistry.NotFound {
return nil, errors.New("%q not found", ref.FullName())
} else if err != nil {
return nil, err
}
ed, ok := d.(protoreflect.EnumDescriptor)
if !ok {
return nil, errors.New("resolved %q, but it is not an enum", d.FullName())
}
return ed, nil
}
func (r *resolver) findMessageDescriptor(scope protoreflect.FullName, ref partialName, isWeak bool) (protoreflect.MessageDescriptor, error) {
d, err := r.findDescriptor(scope, ref)
if err == protoregistry.NotFound && (r.allowUnresolvable || isWeak) {
return filedesc.PlaceholderMessage(ref.FullName()), nil
} else if err == protoregistry.NotFound {
return nil, errors.New("%q not found", ref.FullName())
} else if err != nil {
return nil, err
}
md, ok := d.(protoreflect.MessageDescriptor)
if !ok {
return nil, errors.New("resolved %q, but it is not an message", d.FullName())
}
return md, nil
}
// partialName is the partial name. A leading dot means that the name is full,
// otherwise the name is relative to some current scope.
// See google.protobuf.FieldDescriptorProto.type_name.
type partialName string
func (s partialName) IsFull() bool {
return len(s) > 0 && s[0] == '.'
}
func (s partialName) IsValid() bool {
if s.IsFull() {
return protoreflect.FullName(s[1:]).IsValid()
}
return protoreflect.FullName(s).IsValid()
}
const unknownPrefix = "*."
// FullName converts the partial name to a full name on a best-effort basis.
// If relative, it creates an invalid full name, using a "*." prefix
// to indicate that the start of the full name is unknown.
func (s partialName) FullName() protoreflect.FullName {
if s.IsFull() {
return protoreflect.FullName(s[1:])
}
return protoreflect.FullName(unknownPrefix + s)
}
func unmarshalDefault(s string, fd protoreflect.FieldDescriptor, allowUnresolvable bool) (protoreflect.Value, protoreflect.EnumValueDescriptor, error) {
var evs protoreflect.EnumValueDescriptors
if fd.Enum() != nil {
evs = fd.Enum().Values()
}
v, ev, err := defval.Unmarshal(s, fd.Kind(), evs, defval.Descriptor)
if err != nil && allowUnresolvable && evs != nil && protoreflect.Name(s).IsValid() {
v = protoreflect.ValueOfEnum(0)
if evs.Len() > 0 {
v = protoreflect.ValueOfEnum(evs.Get(0).Number())
}
ev = filedesc.PlaceholderEnumValue(fd.Enum().FullName().Parent().Append(protoreflect.Name(s)))
} else if err != nil {
return v, ev, err
}
if fd.Syntax() == protoreflect.Proto3 {
return v, ev, errors.New("cannot be specified under proto3 semantics")
}
if fd.Kind() == protoreflect.MessageKind || fd.Kind() == protoreflect.GroupKind || fd.Cardinality() == protoreflect.Repeated {
return v, ev, errors.New("cannot be specified on composite types")
}
return v, ev, nil
}

Some files were not shown because too many files have changed in this diff Show More